Skip to content

Integration batch Q - #1465

Merged
Juliusolsson05 merged 57 commits into
mainfrom
integration/batch-2026-09-27-q
Sep 27, 2026
Merged

Juliusolsson05 merged 57 commits into
mainfrom
integration/batch-2026-09-27-q

Conversation

@Juliusolsson05

@Juliusolsson05 Juliusolsson05 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Integration batch Q (owner-approved merge mode, owner-requested history form). The branch was created from origin/main f0bcf09 (batch P); each member PR was retargeted here and merged through GitHub.

Every member had GATE PASS (--member) on f0bcf09. #1420 (security) and #1450 were manager-verified at the cap. #1417 was left out (it conflicts with a member in codex.ts). Merged after green exact-head CI and a recorded non-member gate PASS (see comments).

🤖 Generated with Claude Code

Juliusolsson05 and others added 30 commits September 26, 2026 20:36
Refs #234

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compatibility review in docs/plans/2026-09-26-accept-codex-0157.md: release
notes, a rollout-corpus survey by version, the 0.157 PTY recordings, and
daily production use. The one parser-side gap (token_usage_record) is
agent-transcript-parser#38.

Fixes #234

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #234

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bumps opencode-terminal-headless to 7a009541 (och#10), which returns the
db-path lookup as dbPathPending instead of awaiting it. The adapter keeps the
package's proof honest: it latches the TUI's first output from spawn and
passes it as tuiOutputSeen, and holds terminal input until that output so
nothing commit-capable reaches the PTY before the TUI paints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1397 review b, steering q97)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y (q100)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ivery doc (#1397 review a)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…persist (#1304)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…crets (#1304, q108)

A destination change cleared the old token before setting the new one; a
failed set then brought the old server back without it, and a delete whose
clear failed partway lost some blobs. Secret steps now snapshot the server's
ciphertext blobs and restore them on failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1420, q110 SECURITY)

- a destination change clears the old secrets BEFORE publishing the new
  document, so no crash point leaves the new destination with the old token;
- launch reads are serialized with mutations (no half-applied reads);
- rollback restores old secrets only when the old document is back on disk
  or the destination is unchanged; otherwise it fails closed (no secret);
- snapshotServer treats only ENOENT as empty;
- change listeners run after commit, isolated, and cannot fail a committed save.
Fail-first tests pin each case (review a findings 1-4 and the reverse mix).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ing)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…narrowing)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… launch refuses a mismatch (#1420, q113 SECURITY)

Order-based fixes left a window in each direction (new address + old token,
then old address + new token after a failed prune and a restart or failed
restore). Each encrypted record now carries the destination identity it was
saved for, and reads (launch and the Settings state) return it only when it
matches the server's current destination: fail closed across crashes, failed
rollbacks and failed restores. Pre-binding records are upgraded once at load
to the destination their document names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d it, and bind it on user confirmation (#1420, q114 SECURITY)

An old record carries no proof of its destination, and the document beside
it may be the very inconsistent state binding refuses. Legacy records are
kept on disk, read as not set, and shown as 'saved by an earlier version':
the user confirms them for the current destination (Settings, IPC only;
not on the agent tool surface) or re-enters them. One-time cost for
upgrading users.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tination (#1420)

Masking the whole env/header value that contained ${input:…} let an agent
move the endpoint inside it without changing the identity, so the saved
token stayed bound and launched to the new host. Mask only the reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n survives recovery and maintenance (#1420, q115)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1420, q118)

Masking only the ${input:…} token hid WHICH input a value uses: an agent
could re-point an endpoint host at a new input it set itself and the saved
token went there. The `${input}` marker also collided with that literal
text. Stored values hold reference ids, never secret values, so compare
them raw; only env/header key order is normalised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up of #1429. listWorktreesForCwdDetailed is exported and every other
consumer acts on timedOut: the conversations family is marked gitTimedOut,
not cached, and the picker says siblings may be missing; worktree activity
answers { ok: false, timedOut: true } (worktrees.read activityTimedOut, the
dump says 'Git timed out'); the agent-activity repo root retries once and
then throws instead of filing a worktree's activity under its folder; history
chunks skip worktree attribution on a timeout (worktreesForAttribution).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… never as the worktree folder (#1430, q126)

Two git timeouts made the recorder fall back to the cwd as repoRoot; the
store persisted it and summarize grouped by it, so a worktree became a
repository of its own that later intervals could not fold back. It is now
recorded as '' (the existing Unknown), with the cwd still naming the
worktree row. Pinned through the real recorder and store.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r where it goes (#1420, B6 R3)

The destination identity covered the entry text and reference ids but not
the VALUES of inputs that decide where a request goes. An agent re-set an
imported API_BASE_URL (or the host inside an endpoint template) with
mcp_servers_set_secret and the next launch sent the key there.

Each record now also carries a digest of the entry's steering inputs'
values (everything not a pure credential), excluding its own value, so a
rotated token stays bound. A changed steering value withholds the others
(kept, never deleted) until the user confirms; an agent setting a steering
value turns the server off for review. Confirm never binds a record saved
for a different destination.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1420)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er be probed (#1409)

Replays the recorded listen(0) page server (62678) and vite (4173). On main,
both are probed on the first scan that sees them, and the probe carries
Node's default User-Agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nges need review, user edits rebind (#1420, q127)

No credential/steering classifier in the security decision: a key's name
does not prove how a program uses its value. The digest now covers every
other referenced input. Any agent or import value change turns the server
off for review and withholds the siblings until the user confirms. A user
edit in Settings is the confirmation: it rebinds the siblings that were
valid just before it (never ones an agent change already withheld).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… probe (#1409)

A listener is probed and listed only after it has listened for 5 s, so the
short-lived loopback servers of test suites run inside a lane never receive
the unsolicited GET /. The probe sends AgentCode-LanePortProbe/1, and the
long-running Codex proxy harness excuses exactly that User-Agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1409)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ages when unwatched; lsof failure is not empty (#1452 review A)

- the window's age starts when lsof returned the listener, not at scan start (a
  slow lsof or a scan straddling a plan change shortened it);
- an empty plan and stop() forget ages and probe answers;
- listListeners throws on a timeout, signal or missing lsof instead of
  returning [], so a settled chip is not pruned and hidden for another window;
- the regression tests pin each scenario, the exact boundary, and the lsof
  error shapes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r probe; harness excuses only GET / + UA (#1452 review b)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Juliusolsson05 and others added 24 commits September 27, 2026 10:44
…ecret (#1420, r3 round 2)

mcp_servers_set_secret on the withheld token itself, an agent save with
values, and mcp_servers_remove destroyed a secret that was kept precisely
for the user's decision. Each is now refused before anything changes; the
user confirms, re-enters or removes it in Settings. Also pins that a user's
move deletes the old blob (a no-op clearServer survived before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1458 for passive discovery (#1452)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on (#1420)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s are closed and the prompt mutations are killed on main (#1354 round 2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…held for the agent guard (#1420, q130)

The withheld guard skipped any input whose value could not be decrypted, so
an agent could replace a present-but-unreadable blob (a key mismatch, a
corrupt file). Presence is now raw: only ENOENT means no secret; any other
stat failure throws and the agent write is refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imed-out history to the reconciler

a: a page built after git recovered is not appended to one built while it
timed out (useConversationList restarts from page 1 when the family changes).
a+b: a history chunk read while git timed out is handed to the live
reconciler (WorkspaceRefs.worktreeReconcilerRef, handHistoryToReconciler)
so a recovered catalog replays it, instead of losing its worktree evidence.
b: the picker note only in Repository scope. a: assert the repository-
unknown warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g orphaned inputs (#1420, q131)

An agent update that drops every ${input:…} reference keeps the blobs
(agents never prune), and a guard that walked only defined inputs then let
mcp_servers_remove delete them, or a re-add with a value replace them. The
guard now walks defined inputs plus every stored blob (strict listing: only
ENOENT is empty); a blob with no input proves no binding, so it is withheld.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… drop the dead lister (#1430 review c)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ages never override a known context (#1450 verification a/b)

a: with a fresh catalog already cached, refresh() answers 'cached' and never
notifies, so a timed-out history chunk never repainted. replayCachedCatalog
replays against a real cached catalog; the hand-off calls it on 'cached'.
Pinned with the recorded codex-0151 window (was main cwd, now worktree-2).

b: the older-history loader handed pages over even when the pane knew a
newer context; the reconciler treats observed records as newest, so a
recovered catalog moved the pane back. Hand over only while the context is
unknown, the same recency rule as the answered-git backfill. Pinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…be answers or prunes (#1452 round-2 review A)

A scan waiting on lsof when the plan was emptied resumed after the clear
and wrote its listeners' ages back, so a restored plan probed at once.
Every age, probe and cache write is now fenced on the plan generation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lerRef (#1450 CI)

useIpcSubscriptions publishes the live reconciler into WorkspaceRefs
(round 1); this harness builds refs by hand and lacked the slot, so the
publish threw. Also incidental proof the production publish runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nce (#1450 B6 verify)

A scroll-up during a git timeout handed the older page over as if it were
the newest, so a recovered catalog moved the pane to the older worktree.
observe() takes a position; older pages go to the old end of the window
(overflow dropped, never folded over newer baseline evidence). Pinned with
the recorded codex-0151 window + three-worktree catalog. Also fixes the
stale resolveRepoRoot header (Unknown, not the cwd).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…consumers

# Conflicts:
#	src/main/conversations/service.system.test.ts
…-3 review A)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1420, B6 check)

On a case-insensitive disk TOK.bin is tok.bin, so an agent save naming TOK
overwrote a withheld, orphaned or undecryptable tok secret.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, #1329)

- agent-transcript-parser 68dbfff -> 7e8a67c (#37): the Claude native-resume
  live test owns its probe launches and never touches the real login.
- workflow-mcp ef995af -> 6bcaf113 (#63): the Codex live test gets an
  access-only login, never a copy of the real ~/.codex/auth.json.
- claude-code-headless f52fc82 -> 1cfa8c92 (#68): the composer canary leaves
  no transcript or cwd, and one shared trust entry.

All three package diffs are test-only (no package.json change), so the
lockfile needs no resync; npm's own resync only dropped unrelated optional
peer entries, which were left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
workflow-mcp#71 merged after #63: one shared pollUntil and run waits that end
on every terminal status replace the 0.5 s counted polls that failed package
CI. Test-only (six test files), so the lockfile still needs no resync
(npm ci --dry-run accepts it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1397 review round 1)

Brings in the blocker fix for review b/c: the late database-path recovery is
reported from onPositioned, so the app's one history heal cannot run before a
BUSY-deferred reader positions. Package manifests are unchanged; no lockfile
resync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…out-db-wait

fix(opencode): spawn the TUI without waiting on opencode db path
fix(user-mcp): keep disk, memory and secrets consistent when a secret step fails (#1304)
…sumers

fix(git): a timed-out worktree list is never read as 'no family'
…-servers

fix(browser-pocket): don't probe short-lived lane listeners; tag the probe (#1409)
…dentials

chore(packages): bump the live-test credential and residue fixes (#1295)
@Juliusolsson05 Juliusolsson05 added the type:chore Maintenance, deps, tests, docs label Sep 27, 2026
@Juliusolsson05

Copy link
Copy Markdown
Owner Author

Batch disposition (B6): members merged via GitHub after member GATE PASS on f0bcf09. #1420 security manager-verified (case-insensitive guard; all attacks refused). #1463 bumps cch→#68, wfm→#71 (incl. #63) and parser→#37. #1397 bumps och→#11. It merges when exact-head CI is green, the body is in past tense and a non-member gate PASS is recorded.

@Juliusolsson05

Copy link
Copy Markdown
Owner Author

Pre-merge gate record: merge-gate.sh agent-code 1465 --dry → GATE PASS #1465 (d71c35a, 0 behind main, checks green, reviews OK). The body is in past tense. Merging.

@Juliusolsson05
Juliusolsson05 marked this pull request as ready for review September 27, 2026 21:31
@Juliusolsson05
Juliusolsson05 merged commit 2bb6646 into main Sep 27, 2026
2 checks passed
@Juliusolsson05
Juliusolsson05 deleted the integration/batch-2026-09-27-q branch September 27, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment