Repository navigation
Compare a turn's patch with the working tree, file by file (CF-5) - #302
Merged
Merged
Conversation
codex-cli 0.163.0 sends a fileChange's files with absolute paths and each file's diff separately. Modex joined the diffs into args.patch and dropped the paths, so a turn's patch could not be checked file by file. args.files now keeps each file's path, kind, move target and how many lines of args.patch are its diff, so the diffs are not stored twice. Coven-Harness: Claude Code / claude-opus-5-5
A patch tool was labelled as the turn's, but nothing said whether the files still matched it. A patch the CLI reported as applied now has Compare with working tree. Main takes the patch from the thread's own record and reads only the files it names, inside the thread's folder, and answers per file: as this turn left it, still has this turn's edit, changed since, deleted since, or not compared with the reason. Only verdicts reach the window. Opening a row reads nothing; comparing writes and runs nothing. Links out of the folder, directories, files over 8 MiB, removal-only edits, notebook edits and Codex patches saved before per-file records are not compared, and say why. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Oct 18, 2026
[P1][CF-5] Add provenance-aware citations, command evidence, and owned artifact actions to chat
#278
Closed
Code coverage overviewLanguages: TypeScript TypeScript / code-coverage-agent
View coverage of the 10 most impacted files.
ℹ️ Calculations represent line coverage. Results may change as calculations are updated. Updated |
3 of 15 tasks
This was referenced Oct 18, 2026
BunsDev
added a commit
that referenced
this pull request
Oct 19, 2026
* Show and copy the lines a Codex memory citation points to A reply's "From Codex memory" citation was display-only. Each one now has Show lines and Copy, which ask main (evidence:memory) for the cited lines. main/engine/memory-citations.ts reads only inside Codex's memories folder ($CODEX_HOME/memories, else ~/.codex/memories) and refuses an absolute path, any "..", a symlink that resolves outside, a directory, a file over 8 MiB, and a range past the end. It returns the 1-based, inclusive lines, cut to 64 KiB, and opens, runs and fetches nothing. The command is local-only: a paired desktop never reads this Mac's memory files. Streamer Mode masks the shown lines. Local codex-cli 0.163.0 sessions cite paths relative to the memories folder (MEMORY.md), and a one-line citation's note matched its line counted from 1, not 0. Tests first: memory-citations.test.ts (7) and two e2e cases in conversation-evidence.spec.ts (show/copy exact lines with nothing started; an escaping citation refused), red before the code. Part of #278. Coven-Harness: Claude Code / claude-opus-5-5 * Compare a turn's patch with the working tree, file by file (CF-5) (#302) * Keep each Codex file change's path, kind and share of the patch codex-cli 0.163.0 sends a fileChange's files with absolute paths and each file's diff separately. Modex joined the diffs into args.patch and dropped the paths, so a turn's patch could not be checked file by file. args.files now keeps each file's path, kind, move target and how many lines of args.patch are its diff, so the diffs are not stored twice. Coven-Harness: Claude Code / claude-opus-5-5 * Compare a turn's patch with the working tree, file by file A patch tool was labelled as the turn's, but nothing said whether the files still matched it. A patch the CLI reported as applied now has Compare with working tree. Main takes the patch from the thread's own record and reads only the files it names, inside the thread's folder, and answers per file: as this turn left it, still has this turn's edit, changed since, deleted since, or not compared with the reason. Only verdicts reach the window. Opening a row reads nothing; comparing writes and runs nothing. Links out of the folder, directories, files over 8 MiB, removal-only edits, notebook edits and Codex patches saved before per-file records are not compared, and say why. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5
BunsDev
added a commit
that referenced
this pull request
Oct 19, 2026
…5) (#311) * Show and copy the lines a Codex memory citation points to A reply's "From Codex memory" citation was display-only. Each one now has Show lines and Copy, which ask main (evidence:memory) for the cited lines. main/engine/memory-citations.ts reads only inside Codex's memories folder ($CODEX_HOME/memories, else ~/.codex/memories) and refuses an absolute path, any "..", a symlink that resolves outside, a directory, a file over 8 MiB, and a range past the end. It returns the 1-based, inclusive lines, cut to 64 KiB, and opens, runs and fetches nothing. The command is local-only: a paired desktop never reads this Mac's memory files. Streamer Mode masks the shown lines. Local codex-cli 0.163.0 sessions cite paths relative to the memories folder (MEMORY.md), and a one-line citation's note matched its line counted from 1, not 0. Tests first: memory-citations.test.ts (7) and two e2e cases in conversation-evidence.spec.ts (show/copy exact lines with nothing started; an escaping citation refused), red before the code. Part of #278. Coven-Harness: Claude Code / claude-opus-5-5 * Compare a turn's patch with the working tree, file by file (CF-5) (#302) * Keep each Codex file change's path, kind and share of the patch codex-cli 0.163.0 sends a fileChange's files with absolute paths and each file's diff separately. Modex joined the diffs into args.patch and dropped the paths, so a turn's patch could not be checked file by file. args.files now keeps each file's path, kind, move target and how many lines of args.patch are its diff, so the diffs are not stored twice. Coven-Harness: Claude Code / claude-opus-5-5 * Compare a turn's patch with the working tree, file by file A patch tool was labelled as the turn's, but nothing said whether the files still matched it. A patch the CLI reported as applied now has Compare with working tree. Main takes the patch from the thread's own record and reads only the files it names, inside the thread's folder, and answers per file: as this turn left it, still has this turn's edit, changed since, deleted since, or not compared with the reason. Only verdicts reach the window. Opening a row reads nothing; comparing writes and runs nothing. Links out of the folder, directories, files over 8 MiB, removal-only edits, notebook edits and Codex patches saved before per-file records are not compared, and say why. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Keep a long tool's raw output in main, from its first byte The transcript keeps a tool's last 256 KiB; the rest of a long Codex command's output was dropped. Codex streams every chunk (item/commandExecution/outputDelta), so its backend now hands each raw chunk to an optional main-only sink hook, TurnSink.output. The runner maps it to the tool's transcript item and ToolLogStore keeps it. Output that fits in the preview is never written. Past that, the store keeps up to 10 MiB from the first byte in one file per item under app/tool-logs/<thread>/, records the total when the tool finishes, reads back 256 KiB pages ending on character boundaries, and is removed with its thread. Thread ids are checked and item ids are hex-encoded, so no id becomes a path. Nothing raw is journaled or sent to the window. Claude Code 2.1.302 hands Claude at most bashOutputMaxChars (default 30,000, up to 128,000 characters) and keeps the rest in its own file, so a Claude result never outgrows the preview and its backend does not call the hook. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Add the full-log e2e test (red until the UI lands) Coven-Harness: Claude Code / claude-opus-5-5 * Show a long tool's full log a page at a time A tool whose output passed the 256 KB preview now has Show full log under its truncation notice. It asks main (evidence:tool-log) for the kept output from the first byte, 256 KB per page, with Earlier, Later, Copy page and Hide. The status says whether all of it was kept, the first part of how much, or that the tool never finished. Streamer Mode masks the page; nothing is read until asked, and reading runs nothing. The page shape, sizes and byte formatter move to shared/evidence.ts. The offline Store demo refuses the command like its other evidence reads. Part of #278 (CF-5), tracker #273. Coven-Harness: Claude Code / claude-opus-5-5 * Document the full log: what main keeps, how it reads back, and why Claude needs none Coven-Harness: Claude Code / claude-opus-5-5
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #278 (CF-5), tracker #273. Stacked on #299: it adds one command to #299's
EvidenceCommands, so it targetscf5-memory-citationsand will retarget tomainwhen #299 merges. The claim is here.This takes the CF-5 open item "Turn patches compared against the current working tree, beyond the label". The acceptance line is: captured turn patch and later working-tree changes cannot be confused; stale revisions are visibly identified.
What changes
A patch row (
apply_patch,Edit,MultiEdit,Write,NotebookEdit) still carries the label "The patch as this turn applied it…". A patch the CLI reported as applied now also has Compare with working tree, then Check again, with the time of each check. Each file it touched gets one verdict:Writeor a Codex add wrote, or is still gone after a Codex delete.Edit/MultiEditput in is still there, or every Codex hunk's new lines are still there, in order. The rest of the file is not known, and the label doesn't claim it.Where it reads. Main does the comparison (
main/engine/patch-state.ts, commandevidence:patch).O_NOFOLLOW.What stays still. Opening a row reads nothing. Comparing writes nothing, runs nothing and fetches nothing. A denied, failed, stopped, still-running or unknown-outcome patch isn't offered and is refused in main. That rule is in one shared function,
appliedPatch.Paired desktops can compare too. They learn less than
files:readalready gives them. The offline Store demo refuses the command like its other system commands.The Codex record
From local codex-cli 0.163.0 sessions and Modex's own thread records on this Mac (8 threads: 10 updates, 6 adds):
fileChangehas an absolutepath.@@ -a,b +c,d @@, no---/+++header).Modex joined those diffs into
args.patchand dropped the paths.args.filesnow keeps each file'spath,kind,movePath, andlines: how many lines ofpatchare that file's diff. Each diff stays stored once, andargs.patchis unchanged for every reader. This is one line at thefileChangestart incodex.ts, outside the regions #293 changes, with an inline type import so it stays clear of #293's import hunk.No session content was copied into the repository; fixtures are synthetic.
Tests, red first
test/patch-state.test.ts, 14 tests. It failed to compile before the module existed (TS2307).Write: as left, changed, deleted.Edit: still has its edit, even after unrelated lines change; changed once its text is gone; removal-only edits are not compared.MultiEdit: every new text must be present.\ No newline at end of file; a move judged at its new path; a file back at the old path; a move from outside the folder...and links out are not read.okpath covered.changedinstead ofhas-edit) before its fix.test/codex-backend.test.ts: afileChangekeeps each file's path, kind, move target and line share, and splittingpatchbylinesgives back each diff exactly. It failed withargs.filesundefinedbefore the change.e2e/turn-patch-state.spec.ts, 3 tests, through the real app, main and theclaude -padapter. A fake Claude CLI really editsgreeting.txt, writesnotes.txt, and writes a file outside the project.Checks
Three signed commits:
5ae9155: the Codex record and its test.f9b30b8: the comparison, the UI and the docs.3afdc1e: merges Show and copy the lines a Codex memory citation points to (CF-5) #299, which carriesmainat844ae04(Capture fidelity states in every theme, measure a long transcript, and fix what they found (CF-8) #301).macOS (Apple Silicon), Node 24.18.1, pnpm 10.34.5. The load average ran from 30 to 164 during these runs.
On
3afdc1e(the PR head):pnpm buildpnpm typecheckpnpm --filter @modex/core testpnpm --filter @modex/desktop testpnpm --filter @modex/site testpnpm --filter @modex/store-desktop testpnpm run test:worktreesturn-patch-state,conversation-evidence,conversation-fidelity,typed-turns,event-journal,transcript-measurepnpm --filter @modex/site test:e2eOn
f9b30b8, before the merge: a fullpnpm build,pnpm typecheck,pnpm testandpnpm test:e2e.pnpm teststopped at its first stage. Three tests inscripts/test/worktree-entry.test.mjssaw a child exit status ofnull, which is the script's own 20-secondspawnSynctimeout killing the child, at a load average up to 164. This PR does not touchscripts/, and that stage passed 109/109 on3afdc1e. Because the chain stops at the first failure, the package unit suites ran only on3afdc1e, above.event-journal.spec.ts:9timed out at 90 s. It passed in the targeted run on3afdc1e.--repeat-each=3, 9/9). In an earlier repeat, every test body passed but oneafterAllapp.close()hung under the same load. Six neighbouring transcript specs passed 20/20.CI decides.
Still open on #278
runner.ts,codex.ts,claude.ts), so it starts after Make Claude Stop truthful on claude -p: native interrupt, bounded exit, withdrawn prompts (CF-2) #286 and Answer each approval and question once, and show Codex questions as cards (CF-3) #293 land.resultsare opaque JSON, with no local sample.