Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
200 commits
Select commit Hold shift + click to select a range
dae7c7e
feat(backup): add settings backup configuration
ibetitsmike Jul 30, 2026
05a9fcb
fix(backup): persist backup settings through config
ibetitsmike Jul 30, 2026
e5aec8e
feat(backup): add settings backup primitives
ibetitsmike Jul 30, 2026
0532a4e
feat(backup): add backup orchestration
ibetitsmike Jul 30, 2026
f4085c6
feat(settings): add settings backup controls
ibetitsmike Jul 30, 2026
d598aad
fix(backup): wire the service to the git cache and payload modules
ibetitsmike Jul 30, 2026
53a6757
fix(backup): keep unchanged backups a true no-op and report secrets t…
ibetitsmike Jul 30, 2026
4e5dceb
fix(backup): align MCP redaction with Mux's real reference forms and …
ibetitsmike Jul 30, 2026
d82ca66
fix(backup): treat a repository with no backup as a normal state
ibetitsmike Jul 30, 2026
8612c48
fix(backup): make the secret-scan override reachable and clarify a pr…
ibetitsmike Jul 30, 2026
23c574b
refactor(backup): apply simplify/deslop cleanup and audit comments
ibetitsmike Jul 30, 2026
f4f6acc
fix(backup): close three path and redaction gaps found in review
ibetitsmike Jul 30, 2026
451d9cd
fix(backup): harden paths against symlinks and .git, validate payload…
ibetitsmike Jul 30, 2026
014c8a7
fix(backup): never write a manifest this code cannot read back
ibetitsmike Jul 30, 2026
e1bf23b
fix(backup): keep manifest validation strict
ibetitsmike Jul 30, 2026
bea3bcb
fix(backup): deliver a configured token to git and align the override…
ibetitsmike Jul 30, 2026
05af030
fix(backup): close four review gaps in paths, commands, modes, and pr…
ibetitsmike Jul 30, 2026
f0f2748
fix(backup): redact bearer tokens in stdio commands and clarify previ…
ibetitsmike Jul 30, 2026
5e0154f
fix(backup): preview preferences by their merge result
ibetitsmike Jul 30, 2026
5bd18c0
fix(backup): close redaction and mode gaps found in self-review
ibetitsmike Jul 30, 2026
f98f7e0
fix(backup): stop restore from dropping machine-local preferences
ibetitsmike Jul 30, 2026
b4a19cf
fix(backup): force-stage payload files the target repository ignores
ibetitsmike Jul 30, 2026
9f330e9
fix(backup): clear ignored cache leftovers and preflight restore dest…
ibetitsmike Jul 30, 2026
67ee89d
fix(backup): keep the GitHub token off other hosts and close three pa…
ibetitsmike Jul 31, 2026
b0c1b78
fix(backup): close four export paths that could carry data outside th…
ibetitsmike Jul 31, 2026
18b42bc
fix(backup): merge provider options per provider and tighten two comp…
ibetitsmike Jul 31, 2026
e6db268
fix(backup): let a restore repair a corrupt local MCP config
ibetitsmike Jul 31, 2026
1e1b9cf
fix(backup): refuse ambiguous MCP keys and case-colliding payload paths
ibetitsmike Jul 31, 2026
48ecbb3
fix(backup): discard cache modifications and never resurrect a delete…
ibetitsmike Jul 31, 2026
e269f11
fix(backup): recheck the remote before reporting an unchanged push
ibetitsmike Jul 31, 2026
31df786
fix(backup): exclude the editor command, widen flag separators, class…
ibetitsmike Jul 31, 2026
13ccd6f
fix(backup): classify push-time write denials and exclude local disk …
ibetitsmike Jul 31, 2026
8cf23c0
fix(backup): require approval for restored MCP commands, gate the sec…
ibetitsmike Jul 31, 2026
04cbd68
fix(backup): fail closed on an unparseable backup MCP config and upda…
ibetitsmike Jul 31, 2026
47b315b
fix(backup): treat re-enabling a command as a change and never send a…
ibetitsmike Jul 31, 2026
d0ab977
fix(backup): approve a changed disabled command a workspace override …
ibetitsmike Jul 31, 2026
8158a92
fix(backup): redact paired user credentials and type corrupt payloads…
ibetitsmike Jul 31, 2026
26b62e9
fix(backup): apply the paired credential rule only to curl commands
ibetitsmike Jul 31, 2026
38674bb
fix(backup): type a missing manifest entry as invalid and keep passwo…
ibetitsmike Jul 31, 2026
1c1a673
fix(backup): redact a colon-bearing certificate password whole
ibetitsmike Jul 31, 2026
0a2c169
fix(backup): match curl.exe, redact slash-bearing cert passwords, hon…
ibetitsmike Jul 31, 2026
dd38164
refactor(backup): never export stdio MCP command text instead of pars…
ibetitsmike Jul 31, 2026
b30fce9
fix(backup): refuse to publish a path Windows cannot check out
ibetitsmike Jul 31, 2026
acbf7d5
fix(backup): rehydrate commands across entry shapes and drop unrestor…
ibetitsmike Jul 31, 2026
e822518
fix(backup): rehydrate a mixed entry's url and headers, qualify the s…
ibetitsmike Jul 31, 2026
3a7b948
fix(backup): keep mixed HTTP entries and try the token after gh is de…
ibetitsmike Jul 31, 2026
cf42150
fix(backup): treat an empty url as stdio and report the pushing crede…
ibetitsmike Jul 31, 2026
d377760
fix(backup): mirror normalizeEntry's url truthiness exactly
ibetitsmike Jul 31, 2026
10cf472
fix(backup): bind a restored MCP header credential to the local endpoint
ibetitsmike Jul 31, 2026
a5fa1e9
fix(backup): withhold a mismatched endpoint's whole headers subtree f…
ibetitsmike Jul 31, 2026
6850123
fix(backup): restore a header only from the local value at that path
ibetitsmike Jul 31, 2026
9daecda
fix(backup): use shared tooltips for the backup action shortcut hints
ibetitsmike Jul 31, 2026
189d6fe
fix(backup): read local values by own property when the backup names …
ibetitsmike Jul 31, 2026
d6a38b0
fix(backup): exclude hidden files and keep the ambient ssh retry non-…
ibetitsmike Jul 31, 2026
59e75c1
refactor(backup): reuse the validated jsonc tree and drop redundant t…
ibetitsmike Jul 31, 2026
1ad8ce6
fix(backup): report an unreachable remote instead of a local IO error
ibetitsmike Jul 31, 2026
c482264
test(backup): pin the client-facing unreachable-remote error code
ibetitsmike Jul 31, 2026
d9aabc2
fix(backup): approve url-to-stdio transitions, widen credential-name …
ibetitsmike Jul 31, 2026
2a2c24b
fix(backup): keep local snapshots writable, skip the unused clone che…
ibetitsmike Jul 31, 2026
9dcbb2e
docs(backup): tighten comments added in this branch
ibetitsmike Jul 31, 2026
afd1504
fix(backup): gate non-documentation recursive files behind a payload-…
ibetitsmike Jul 31, 2026
1f37b4f
fix(backup): merge restored preferences inside the serialized config …
ibetitsmike Jul 31, 2026
1681736
docs(backup): drop two comments that restate the code
ibetitsmike Jul 31, 2026
d2d2c4a
test(backup): pin nested materialization under the sparse checkout
ibetitsmike Jul 31, 2026
86dc1a1
fix(backup): derive persisted and IPC backup settings from one schema
ibetitsmike Jul 31, 2026
730ee22
fix(backup): normalize the managed path and keep a configured core.ss…
ibetitsmike Jul 31, 2026
7f1cdf8
fix(backup): extend a GIT_SSH wrapper instead of replacing it
ibetitsmike Jul 31, 2026
3a354f0
fix(backup): stop exporting URL query values, bound payload size, mat…
ibetitsmike Jul 31, 2026
f9dd5e3
fix(backup): publish only the MCP fields Mux reads, bound the manifes…
ibetitsmike Jul 31, 2026
b99d2b4
fix(backup): treat a non-object servers map as unsupported, bound the…
ibetitsmike Jul 31, 2026
b1e878b
fix(backup): stop publishing MCP endpoints and comments
ibetitsmike Jul 31, 2026
5746653
test(backup): answer the core.sshCommand probe in the credential ladd…
ibetitsmike Jul 31, 2026
86c418a
fix(backup): keep case-distinct local files in a safety snapshot
ibetitsmike Jul 31, 2026
6ea1f44
fix(backup): report local-only files by filesystem identity, not spel…
ibetitsmike Jul 31, 2026
49ec57f
fix(backup): keep every name a shared file identity has
ibetitsmike Jul 31, 2026
31a795c
fix(backup): refuse a restore whose entries are already one local file
ibetitsmike Jul 31, 2026
3229ff5
fix(backup): run the whole restore preflight before the safety snapshot
ibetitsmike Jul 31, 2026
304223e
fix(backup): validate backup preferences in the preflight, remove a f…
ibetitsmike Jul 31, 2026
0e9f123
fix(backup): read a file through the handle its size was checked on
ibetitsmike Jul 31, 2026
d69e6bd
fix(backup): verify an opened file is still the contained one, write …
ibetitsmike Jul 31, 2026
029ebe5
fix(backup): resolve the root once per operation, finish every write
ibetitsmike Jul 31, 2026
e4bc6f0
fix(backup): check the root by identity, not by its resolved name
ibetitsmike Jul 31, 2026
675d59c
fix(backup): keep the safety snapshot and local MCP reads inside the …
ibetitsmike Jul 31, 2026
3b4f7d5
fix(backup): refuse a symlinked git cache root or per-repository cache
ibetitsmike Jul 31, 2026
12827b0
perf(backup): fetch only the configured backup branch
ibetitsmike Jul 31, 2026
3f49cd4
fix(backup): read porcelain status verbatim, do not hide a failed ref…
ibetitsmike Jul 31, 2026
45a7177
fix(backup): fetch nothing when the backup branch does not exist yet
ibetitsmike Jul 31, 2026
9ade3ad
fix(backup): repair a half-initialized cache and keep it blob-filtered
ibetitsmike Jul 31, 2026
4886ec8
fix(backup): keep payload bytes verbatim and check where a push lands
ibetitsmike Jul 31, 2026
e48149e
chore(backup): pin the locale for git invocations
ibetitsmike Jul 31, 2026
25c2275
fix(backup): check every push url, and do not write attributes throug…
ibetitsmike Jul 31, 2026
eebadaa
fix(backup): check `.git` before writing repository config
ibetitsmike Jul 31, 2026
63d6aa6
fix(backup): check `.git` before initializing or repairing a cache
ibetitsmike Jul 31, 2026
963530b
fix(backup): do not report a server-side push denial as backup drift
ibetitsmike Jul 31, 2026
ab0f8bb
refactor(backup): remove the explicit-token credential rung
ibetitsmike Aug 4, 2026
c47c2cd
fix(backup): apply code-review findings
ibetitsmike Aug 4, 2026
7a25918
fix(backup): strip GitHub token variables from the gh rung
ibetitsmike Aug 4, 2026
92b0506
fix(backup): fetch lazy blobs through the credential ladder
ibetitsmike Aug 4, 2026
faff9fa
fix(backup): reject a repository URL that embeds a credential
ibetitsmike Aug 4, 2026
0790226
fix(backup): surface the required command approvals on a blocked restore
ibetitsmike Aug 4, 2026
103ba7c
fix(backup): report a config write that never reached disk
ibetitsmike Aug 4, 2026
6f6e068
refactor(backup): pass keybind hints through Button's explicit toolti…
ibetitsmike Aug 4, 2026
c1a4b6f
fix(scripts): pass PR JSON to jq through stdin, not argv
ibetitsmike Aug 4, 2026
0dd5112
fix(backup): compare the stored origin url, not the insteadOf-rewritt…
ibetitsmike Aug 4, 2026
989c032
fix(backup): reject gitfile and commondir indirection in the cache
ibetitsmike Aug 4, 2026
cc43007
fix(backup): hash approvals over JSON, not a NUL-delimited preimage
ibetitsmike Aug 4, 2026
44df5b5
backup: neutralize all content-transforming git attributes in the cache
ibetitsmike Aug 4, 2026
1590de2
backup: rebuild cache-local git config from a closed allowlist
ibetitsmike Aug 4, 2026
f1f66ef
backup: strip git repo-selection env vars, contain hard links at payl…
ibetitsmike Aug 4, 2026
51dfa68
backup: strip environment-supplied git config, force core.bare in the…
ibetitsmike Aug 4, 2026
180f2a7
backup: owner-only safety snapshot modes, clear approvals on settings…
ibetitsmike Aug 4, 2026
ee8cf48
backup: reject any symlink under the cache's .git directory
ibetitsmike Aug 4, 2026
795a2dc
backup: owner-only cache tree, carry the snapshot path on post-snapsh…
ibetitsmike Aug 4, 2026
7887967
🤖 fix: isolate hard-linked backup metadata
ibetitsmike Aug 4, 2026
321c052
🤖 fix: preserve relative backup repository paths
ibetitsmike Aug 4, 2026
03698c1
🤖 fix: self-heal backup cache configuration
ibetitsmike Aug 4, 2026
61e124c
🤖 fix: preserve filtered Git repository formats
ibetitsmike Aug 4, 2026
a3c6a89
🤖 refactor: remove redundant keybind comment
ibetitsmike Aug 5, 2026
d94dba4
🤖 fix: gate credential-named backup files
ibetitsmike Aug 5, 2026
f07708a
🤖 fix: recover malformed backup cache config
ibetitsmike Aug 5, 2026
737b91b
🤖 fix: preserve backup repository object format
ibetitsmike Aug 5, 2026
991a7b6
🤖 fix: make MCP settings backups portable
ibetitsmike Aug 5, 2026
691cf49
🤖 fix: gate disabled MCP transport changes
ibetitsmike Aug 5, 2026
021ac86
🤖 fix: gate credential-bearing MCP URLs
ibetitsmike Aug 5, 2026
7568dbb
🤖 fix: harden backup URL and restore validation
ibetitsmike Aug 5, 2026
678788f
🤖 fix: harden backup credentials and file reads
ibetitsmike Aug 5, 2026
2522cea
🤖 fix: validate backup branches and snapshot inputs
ibetitsmike Aug 6, 2026
a245ce5
🤖 fix: close backup URL and restore races
ibetitsmike Aug 6, 2026
592fb7b
🤖 fix: require approval for published MCP commands
ibetitsmike Aug 6, 2026
33b4ffc
🤖 fix: disambiguate backup redaction markers
ibetitsmike Aug 6, 2026
2d7dcbe
🤖 fix: guard portable field lookup
ibetitsmike Aug 6, 2026
38979fc
🤖 fix: gate additional backup credentials
ibetitsmike Aug 6, 2026
f14399c
🤖 fix: reject slashless backup credentials
ibetitsmike Aug 6, 2026
3677c42
🤖 fix: allow usernames in git+ssh and ssh+git remotes
ibetitsmike Aug 6, 2026
806a27a
🤖 fix: narrow git URL comments to verified behavior
ibetitsmike Aug 6, 2026
3f1097b
🤖 fix: route git+ssh and ssh+git remotes through the ssh rung
ibetitsmike Aug 6, 2026
c5aae5e
🤖 fix: clear stale git lock files from the backup cache
ibetitsmike Aug 6, 2026
f17d664
🤖 fix: keep auto gc from outliving awaited cache commands
ibetitsmike Aug 6, 2026
f4e30db
🤖 fix: keep a restored MCP config owner-only
ibetitsmike Aug 6, 2026
f09292d
🤖 fix: set exact owner-only mode and keep severed link permissions
ibetitsmike Aug 6, 2026
52ded67
🤖 fix: rebuild a backup cache left with an incomplete .git
ibetitsmike Aug 6, 2026
76f789f
🤖 fix: reuse a cache directory left without a .git
ibetitsmike Aug 6, 2026
2384847
🤖 fix: discard a backup cache atomically
ibetitsmike Aug 6, 2026
73ca167
🤖 fix: reap caches left by an interrupted discard
ibetitsmike Aug 6, 2026
2c3271c
🤖 fix: rebuild a corrupt backup cache instead of enumerating corruption
ibetitsmike Aug 6, 2026
95c4754
🤖 fix: keep tamper refusals out of the backup cache rebuild retry
ibetitsmike Aug 6, 2026
3535b49
🤖 fix: recheck cache ownership at the point of deletion
ibetitsmike Aug 6, 2026
8ce2e4e
🤖 fix: gate credential-named agent definitions before publishing
ibetitsmike Aug 6, 2026
c693328
🤖 fix: refuse backups that could never be restored
ibetitsmike Aug 6, 2026
fbd1a49
🤖 fix: put BatchMode=yes ahead of a configured ssh option
ibetitsmike Aug 6, 2026
ac4e483
🤖 fix: read a Windows drive path as a local repository
ibetitsmike Aug 6, 2026
7a38e87
🤖 fix: bound retained restore snapshots
ibetitsmike Aug 6, 2026
7d2b5f6
🤖 fix: only reap snapshots whose restore has returned
ibetitsmike Aug 6, 2026
8c032f7
🤖 fix: read local safety snapshots with local path rules
ibetitsmike Aug 6, 2026
2e97a15
🤖 fix: parse a double-quoted ssh path before touching the command
ibetitsmike Aug 6, 2026
58d7925
🤖 fix: do not reap snapshots while a restore is still running
ibetitsmike Aug 6, 2026
609b9d8
🤖 fix: keep separators when decoding a quoted ssh path
ibetitsmike Aug 6, 2026
02669c1
🤖 fix: reject percent-encoded credentials in an ssh repo url
ibetitsmike Aug 6, 2026
6c7c766
🤖 fix: serialize local payload work across repositories
ibetitsmike Aug 6, 2026
4c4f9a4
🤖 fix: scan for an encoded userinfo delimiter instead of decoding
ibetitsmike Aug 6, 2026
240f706
🤖 fix: order same-millisecond snapshots by creation
ibetitsmike Aug 6, 2026
f34ebcf
🤖 docs: correct two overstated comment claims
ibetitsmike Aug 6, 2026
f774f05
🤖 docs: correct two more comment claims about their own code
ibetitsmike Aug 6, 2026
04e15d1
🤖 fix: parse an unquoted ssh path with escaped whitespace
ibetitsmike Aug 6, 2026
e98e98a
🤖 fix: resolve encoded authority delimiters before splitting userinfo
ibetitsmike Aug 6, 2026
422d460
🤖 fix: decode MCP URL authorities before finding userinfo
ibetitsmike Aug 6, 2026
95a28ba
🤖 fix: skip shell assignments when finding the ssh program
ibetitsmike Aug 6, 2026
63120d0
🤖 fix: read the ssh program with one shell-word scanner
ibetitsmike Aug 6, 2026
0e3854e
🤖 fix: only add an ssh option where the client can be located
ibetitsmike Aug 6, 2026
e7cace3
🤖 fix: treat a passphrase URL parameter as a credential
ibetitsmike Aug 6, 2026
6e459b9
🤖 fix: sanitize settingsBackup on the real config load path
ibetitsmike Aug 6, 2026
835a179
🤖 fix: drop special permission bits when restoring a file
ibetitsmike Aug 6, 2026
75da7ed
🤖 fix: restore hard-linked entries instead of refusing them
ibetitsmike Aug 6, 2026
1ad571c
🤖 fix: bound the output git ls-remote may buffer
ibetitsmike Aug 6, 2026
4f0c2d4
🤖 fix: settle the output-cap bail-out without waiting on descendants
ibetitsmike Aug 6, 2026
231fa99
🤖 fix: refuse an unwritable restore destination during planning
ibetitsmike Aug 6, 2026
f17854c
🤖 fix: kill the whole tree on cap overflow and preflight two more res…
ibetitsmike Aug 7, 2026
49a5776
🤖 ci: give each quarantined unit test file its own bun process
ibetitsmike Aug 7, 2026
888cd77
🤖 fix: detach only the command whose output is capped
ibetitsmike Aug 7, 2026
e3f4054
🤖 fix: count capped output per chunk, and correct two comment claims
ibetitsmike Aug 7, 2026
015755e
fix: bound cumulative subprocess output
ibetitsmike Aug 7, 2026
8414c75
refactor: simplify settings backup internals
ibetitsmike Aug 7, 2026
5d40873
🤖 tests: simplify settings backup tests
ibetitsmike Aug 7, 2026
2883e56
🤖 refactor: clean up simplification comments
ibetitsmike Aug 7, 2026
59e879e
🤖 fix: kill capped-command trees on timeout, and preflight restore chmod
ibetitsmike Aug 7, 2026
6d2bcba
🤖 fix: preflight sticky-directory unlink ownership before restore writes
ibetitsmike Aug 7, 2026
1f74c56
🤖 fix: terminate a capped command's group even after its leader exited
ibetitsmike Aug 7, 2026
0d2f2cd
🤖 fix: terminate timed backup command trees
ibetitsmike Aug 7, 2026
1ae8b43
🤖 fix: bound backup payload file counts
ibetitsmike Aug 7, 2026
f463d91
🤖 fix: refresh backup settings after config changes
ibetitsmike Aug 7, 2026
d5c1fca
🤖 fix: report severed hard-link aliases as local-only
ibetitsmike Aug 7, 2026
68cb540
🤖 fix: load backup settings even when the config subscription fails
ibetitsmike Aug 7, 2026
77059d1
refactor: cleanup gate round 3 (comments, deslop, load-ordering simpl…
ibetitsmike Aug 7, 2026
a53e259
fix: bound remote managed-tree materialization and settings freshness
ibetitsmike Aug 7, 2026
2947ef6
fix: cap backup network git output and bound payload directory comple…
ibetitsmike Aug 7, 2026
841eb42
fix: shallow the backup cache clone and fetch
ibetitsmike Aug 7, 2026
edc1190
fix: post-save config re-read, gitlink refusal, cache object budget, …
ibetitsmike Aug 7, 2026
4c0d5f8
fix: dead-stream freshness, over-budget cache discard, MCP redaction …
ibetitsmike Aug 8, 2026
2979fd6
fix: keep unsubscribed settings stale and reap inactive backup caches
ibetitsmike Aug 8, 2026
4955283
fix: gate freshness on stream liveness and clean the whole cache work…
ibetitsmike Aug 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,13 @@ jobs:
# order-dependent on origin/main; only reliable in its own process.
src/browser/features/RightSidebar/Memory/MemoryTab.test.tsx
)
bun test --max-concurrency=1 "${isolated_unit_tests[@]}"
# One process per file rather than one shared isolated process. Sharing it still
# segfaults Bun on the runner (exit 132, "Bun has crashed", zero failing assertions)
# while leaving the file transition as the only suspect, and these files are already
# here because they do not survive sharing a process.
for isolated_unit_test in "${isolated_unit_tests[@]}"; do
bun test --max-concurrency=1 "$isolated_unit_test"
done

mapfile -d '' unit_files < <(
find src -type f \( -name '*.test.ts' -o -name '*.test.tsx' \) \
Expand Down
17 changes: 11 additions & 6 deletions scripts/check_codex_comments.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,16 @@ compute_codex_sets_from_arrays() {
local comments_json="$1"
local threads_json="$2"

REGULAR_COMMENTS=$(jq -cn --argjson comments "$comments_json" --arg bot "$BOT_LOGIN_GRAPHQL" '[
$comments[]
# JSON goes through stdin, never argv: a long review history exceeds Linux's
# per-argument limit (MAX_ARG_STRLEN, ~128KB) and made --argjson fail with
# "Argument list too long". printf is a shell builtin, so it has no such limit.
REGULAR_COMMENTS=$(printf '%s' "$comments_json" | jq -c --arg bot "$BOT_LOGIN_GRAPHQL" '[
.[]
| select(.author.login == $bot and .isMinimized == false and (.body | test("Didn.t find any major issues|usage limits have been reached|create a Codex account") | not))
]')

UNRESOLVED_THREADS=$(jq -cn --argjson threads "$threads_json" --arg bot "$BOT_LOGIN_GRAPHQL" '[
$threads[]
UNRESOLVED_THREADS=$(printf '%s' "$threads_json" | jq -c --arg bot "$BOT_LOGIN_GRAPHQL" '[
.[]
| select(.isResolved == false and .comments.nodes[0].author.login == $bot)
]')
}
Expand Down Expand Up @@ -189,7 +192,8 @@ fetch_all_comments_via_api() {
fi

page_comments=$(echo "$page_data" | jq -c '.data.repository.pullRequest.comments.nodes // []')
all_comments=$(jq -cn --argjson existing "$all_comments" --argjson page "$page_comments" '$existing + $page')
# Accumulated pages outgrow MAX_ARG_STRLEN, so concatenate via stdin rather than --argjson.
all_comments=$(printf '%s\n%s' "$all_comments" "$page_comments" | jq -cs '.[0] + .[1]')

has_next=$(echo "$page_data" | jq -r '.data.repository.pullRequest.comments.pageInfo.hasNextPage')
end_cursor=$(echo "$page_data" | jq -r '.data.repository.pullRequest.comments.pageInfo.endCursor // empty')
Expand Down Expand Up @@ -262,7 +266,8 @@ fetch_all_threads_via_api() {
fi

page_threads=$(echo "$page_data" | jq -c '.data.repository.pullRequest.reviewThreads.nodes // []')
all_threads=$(jq -cn --argjson existing "$all_threads" --argjson page "$page_threads" '$existing + $page')
# Same MAX_ARG_STRLEN concern as the comments accumulator above.
all_threads=$(printf '%s\n%s' "$all_threads" "$page_threads" | jq -cs '.[0] + .[1]')

has_next=$(echo "$page_data" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')
end_cursor=$(echo "$page_data" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor // empty')
Expand Down
3 changes: 2 additions & 1 deletion scripts/wait_pr_codex.sh
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ FETCH_ALL_THUMBS_UP_REACTIONS() {
fi

page_nodes=$(echo "$reactions_page" | jq -c '.data.repository.pullRequest.reactions.nodes // []')
all_reactions=$(jq -cn --argjson existing "$all_reactions" --argjson page "$page_nodes" '$existing + $page')
# Via stdin: accumulated pages can exceed Linux's per-argument limit (MAX_ARG_STRLEN).
all_reactions=$(printf '%s\n%s' "$all_reactions" "$page_nodes" | jq -cs '.[0] + .[1]')

has_next=$(echo "$reactions_page" | jq -r '.data.repository.pullRequest.reactions.pageInfo.hasNextPage')
end_cursor=$(echo "$reactions_page" | jq -r '.data.repository.pullRequest.reactions.pageInfo.endCursor // empty')
Expand Down
87 changes: 87 additions & 0 deletions src/browser/features/Settings/Sections/BackupSection.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { userEvent, within } from "@storybook/test";
import { lightweightMeta } from "@/browser/stories/meta.js";
import { createMockORPCClient } from "@/browser/stories/mocks/orpc";
import { BackupSection } from "./BackupSection.js";
import { SettingsSectionStory } from "./settingsStoryUtils.js";

const meta: Meta = {
...lightweightMeta,
title: "Settings/Sections/BackupSection",
component: BackupSection,
};

export default meta;
type Story = StoryObj<typeof meta>;

function renderBackupSection() {
return (
<SettingsSectionStory
setup={() =>
createMockORPCClient({
backupSettings: {
repoUrl: "git@github.com:example/dotfiles.git",
branch: "main",
path: "mux/",
},
backupValidation: {
reachable: true,
empty: false,
credential: "gh",
},
backupPreview: {
pushChanges: [
{ status: "M", path: "mux/preferences.json" },
{ status: "A", path: "mux/memory/global/preferences.md" },
],
restoreChanges: [
{ status: "M", path: "preferences.json" },
{ status: "A", path: "skills/release/SKILL.md" },
],
localOnlyFiles: ["agents/local-only.md"],
redactions: ["mcp.jsonc: github.headers.Authorization"],
commandApprovals: [
{
path: "servers.notes.command",
command: "npx -y @modelcontextprotocol/server-filesystem /home/dev/notes",
token: "8d2e4787fcc88a36cbd9067997213f1a791ec3999af6e9bf2259f6f3a1a0337e",
},
],
},
})
}
>
<div className="bg-background min-h-screen p-4 sm:p-6">
<BackupSection />
</div>
</SettingsSectionStory>
);
}

export const Configured: Story = {
render: renderBackupSection,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByText("Settings backup");
await userEvent.click(canvas.getByRole("button", { name: "Validate" }));
await canvas.findByText(/Credential used: GitHub CLI/i);
await userEvent.click(canvas.getByRole("button", { name: "Preview changes" }));
await canvas.findByText("Backup to repository");
await canvas.findByText("Restore to this device");
await canvas.findByText(/github\.headers\.Authorization/i);
await canvas.findByText("agents/local-only.md");
await canvas.findByRole("checkbox", { name: "Approve MCP command changes" });
},
};

export const Phone: Story = {
globals: {
viewport: { value: "mobile2", isRotated: false },
},
parameters: {
pixel: {
matrix: { themes: ["dark", "light"], viewports: ["phone"] },
},
},
render: renderBackupSection,
};
Loading
Loading