From 867c1cb0fc257c4da62ebaab4d0cbcd435c9d397 Mon Sep 17 00:00:00 2001 From: Superlogicai Date: Fri, 6 Nov 2026 06:12:25 -1000 Subject: [PATCH 1/2] fix(decisions): recognize new transcript side-channel lines Replaying 30 days of real transcripts through the schema-drift tripwire, five Claude sessions (CLI v2.1.299-310) false-tripped on api-request, api-request-blob, artifact-autoreact-ledger, queue-operation and system lines, and Codex peaked at 19 of 20 on event_msg. Extraction was never affected; only the warning banner. Add all six to the named allowlist, same treatment as attachment. Worst streak is now 12 (Claude) and 4 (Codex). The 2026-09-12 types stay flagged. Co-Authored-By: Claude Opus 5.5 --- docs/LANDMINES.md | 8 ++++++++ docs/TESTING.md | 12 ++++++++++++ scripts/decision-integrity-check.ts | 12 ++++++++++++ src/lib/decisions.ts | 12 ++++++++++++ 4 files changed, 44 insertions(+) diff --git a/docs/LANDMINES.md b/docs/LANDMINES.md index c5e6a3d..75ff7a4 100644 --- a/docs/LANDMINES.md +++ b/docs/LANDMINES.md @@ -473,6 +473,14 @@ fix is ever reverted or bypassed. Referenced from CLAUDE.md. one real scenario (CLI drops `assistant`/`user` entirely) this tripwire exists to catch. Stayed a named allowlist. Run `npm run check` (now includes `schema-drift:check`) before trusting any future change here. + **Recurred 2026-11-06:** simulating the tripwire over 30 days of real + transcripts, five Claude sessions (CLI v2.1.299-310) false-tripped, worst + streak 43, on `api-request`, `api-request-blob`, + `artifact-autoreact-ledger`, `queue-operation` and `system` lines. Codex + peaked at 19 of 20 on `event_msg`. All six added to the recognized list; + worst streak is now 12 (Claude) and 4 (Codex). Before adding a type, + replay recent `~/.claude/projects` and `~/.codex/sessions` files through + the allowlist and print envelope types only, never message content. - **Copy-paste out of a Claude Code pane silently breaks long commands (found 2026-09-27).** Two distinct bugs were conflated live before the diff --git a/docs/TESTING.md b/docs/TESTING.md index 328d862..153636b 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -7054,3 +7054,15 @@ their screenshots), reported the mid-drag text selection fixed above, asked for the view pills, and accepted the phase. Not individually confirmed from the manual list: release outside the window (3), Finder file drop alongside board drags (5), external rename during a drag (6). + +### Schema-drift side-channel allowlist (2026-11-06) + +Automated: `npm run check` pins the six new types as recognized and the +2026-09-12 types as still flagged. Offline replay over 30 days of real +transcripts (161 Claude, 80 Codex files, envelope types only): 0 sessions +reach the threshold, down from 5. + +Manual, installed app after `npm run reinstall`: run a long Claude session +with subagents and confirm no "transcript format doesn't match" banner +appears. Not yet run; the banner isn't persisted, so the old false trip was +only reproduced by replay. diff --git a/scripts/decision-integrity-check.ts b/scripts/decision-integrity-check.ts index dfc8ba4..e5e2ca8 100644 --- a/scripts/decision-integrity-check.ts +++ b/scripts/decision-integrity-check.ts @@ -122,6 +122,18 @@ for (const line of [ ]) { assert.equal(transcriptEnvelopeType(line), "unrecognized", `${line} must be flagged, not silently ignored`); } +// Side-channel lines that false-tripped the tripwire on CLI v2.1.299-310 and +// nearly did on Codex (2026-11-06). +for (const type of [ + "api-request", + "api-request-blob", + "artifact-autoreact-ledger", + "queue-operation", + "system", + "event_msg", +]) { + assert.equal(transcriptEnvelopeType(JSON.stringify({ type })), "recognized", `${type} is a known side channel`); +} assert.equal(transcriptEnvelopeType("not json"), "unparseable"); assert.equal(transcriptEnvelopeType('{"type":"assistant"'), "unparseable", "a partial line mid-flush is not drift"); diff --git a/src/lib/decisions.ts b/src/lib/decisions.ts index 1b8169a..1fdded5 100644 --- a/src/lib/decisions.ts +++ b/src/lib/decisions.ts @@ -47,6 +47,12 @@ const assistantBuf = new Map(); // session_id -> pendi // allowlist, updated by hand each time a new benign side-channel type // ships (see decision-integrity-check.ts's regression test, which pins the // 2026-09-12 types as still-must-flag — never add those here). +// +// Recurrence 2026-11-06: simulated over 30 days of real transcripts, five +// Claude sessions (CLI v2.1.299-310) false-tripped on api-request, +// api-request-blob, artifact-autoreact-ledger, queue-operation and system +// lines; Codex peaked at 19 of 20 on event_msg. With these added the worst +// streak is 12 (Claude) and 4 (Codex). const SCHEMA_DRIFT_THRESHOLD = 20; const unrecognizedStreak = new Map(); // session_id -> consecutive unrecognized-envelope lines const driftWarned = new Set(); // session_id already warned — fire once, not per line @@ -79,6 +85,12 @@ export function transcriptEnvelopeType(line: string): "recognized" | "unrecogniz obj.type === "pi_message" || obj.type === "deepseek_message" || obj.type === "attachment" || + obj.type === "api-request" || + obj.type === "api-request-blob" || + obj.type === "artifact-autoreact-ledger" || + obj.type === "queue-operation" || + obj.type === "system" || + obj.type === "event_msg" || isAntigravityEnvelope(obj) ? "recognized" : "unrecognized"; From 8296bb1edd0851dac501bde25d4c8245dfa962cc Mon Sep 17 00:00:00 2001 From: Superlogicai Date: Fri, 6 Nov 2026 06:12:25 -1000 Subject: [PATCH 2/2] fix(deps): patch rustls advisories Bump rustls 0.23.41 to 0.23.46, rustls-webpki 0.103.13 to 0.103.16 and webpki-roots 1.0.8 to 1.0.11, clearing six RUSTSEC advisories on crates compiled through ureq. Lockfile only. cargo audit still lists rkyv and rsa, which are lockfile entries not compiled into the app. Co-Authored-By: Claude Opus 5.5 --- src-tauri/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8d32aec..52149f8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3475,9 +3475,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.41" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "log", "once_cell", @@ -3499,9 +3499,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.13" +version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ "ring", "rustls-pki-types", @@ -5493,9 +5493,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" +checksum = "f5f280bbb2b287bc8e7de7e3852945a0ff50d1bbcb5ed42b6c7a568c546df171" dependencies = [ "rustls-pki-types", ]