Skip to content

fix(codex): apply_patch shrink gate simulates real patch, gate inline-script writes - #104

Merged
fusengine merged 5 commits into
mainfrom
fix/codex-apply-patch-shrink
Sep 6, 2026
Merged

fix(codex): apply_patch shrink gate simulates real patch, gate inline-script writes#104
fusengine merged 5 commits into
mainfrom
fix/codex-apply-patch-shrink

Conversation

@fusengine

Copy link
Copy Markdown
Owner

Summary

  • apply_patch SOLID size gate now computes the post-patch line count by simulating the patch on the real file (computePatchResultLines), reusing the strict-shrink policy shared with Claude Edit; the Codex message now describes the apply_patch procedure instead of telling Codex to switch tools.
  • Inline-script writes (bun -e / node -e / tsx -e / deno eval / ruby -e / perl -e, plus stdin forms) that write a code file are now blocked on every target (Claude, Codex, Kimi, Cursor), using a new single-pass shell lexer that skips quoted strings, heredoc bodies, comments, and command substitution so commit/PR text mentioning these commands is never falsely blocked.
  • PATCH release 0.1.95, CHANGELOG updated, .codex/ added to gitignore (same treatment as .claude/, generated session state).

Test plan

  • bun test: 1779 pass, 1 skip, 0 fail
  • bunx tsc --noEmit: clean
  • bun run build: clean
  • 300-case bash-write corpus: 0 loosened vs main; 68 canonical Claude Code commit/gh forms verified at main parity

…-script writes

Two fixes shipped together:

- apply_patch SOLID size gate now computes the post-patch line count by
  simulating the patch on the real file content (computePatchResultLines
  in src/policy/edit-outcome.ts), reusing the strict-shrink policy shared
  with Claude Edit. 205 to 199 and 205 to 204 stay allowed, 205 to 206 and
  199 to 201 are refused, an invalid patch is refused. The Codex guidance
  message now describes the apply_patch procedure instead of telling
  Codex to switch tools. Claude path unchanged.

- Inline-script writes are now subject to the SOLID gate on every target
  (Claude, Codex, Kimi, Cursor): bun -e, node -e, tsx -e, deno eval,
  ruby -e, perl -e, and stdin forms (bun -, node -, ruby -, perl -) that
  write a code file are blocked the same way redirections are, with a
  prompt to use Write or Edit instead; safe paths stay allowed, other
  cases still ask. Anchor text now comes from a single-pass shell lexer
  (src/policy/guards/bash-write-lexer*.ts) that skips quoted strings,
  heredoc bodies, comments, arithmetic, and tracks command substitution,
  so commit or PR bodies that merely mention these commands are never
  blocked (68 canonical Claude Code commit and gh forms verified at main
  parity; 300-case corpus: 0 loosened vs main). Dead stripQuoted removed.

Tests: 1779 pass, 1 skip, 0 fail.
CI used bun-version latest, which moved from Bun 1.4.0 (main green on 2026-09-03) to 1.4.2. A rerun of main's own commit c8ba997 under 1.4.2 (run 33753558144, rerun) fails the same two assertions in test/track-journal-toctou.test.ts, confirming those failures are environmental drift in Bun itself, not caused by this branch. Pinning bun-version to 1.4.0 keeps CI deterministic until that is investigated.

Also widen test (d) in test/bash-write-heredoc-edges.test.ts from a 5ms to a 50ms per-iteration budget; 5.08ms was measured on the shared runner, too tight a margin for wall-clock timing there.

Follow-up needed: investigate track-journal-toctou behavior under Bun 1.4.2 on Linux before unpinning bun-version.
Three test files (test/lessons.test.ts, test/lessons-session.test.ts,
test/lesson-compact.test.ts) pointed process.env.HOME at a tmp dir and
never restored it. src/tracking/integrity.ts captured the HMAC key
directory from os.homedir() once at import time. On Linux os.homedir()
follows HOME at call time, so a child bun process spawned later by
test/track-journal-toctou.test.ts signed its journal events with a key
under the tmp HOME while the parent verified with the key captured at
import; the child events were rejected and the test saw a total loss.
On macOS Bun ignores a mutated HOME in os.homedir(), which is why it
never reproduced locally. bun test runs files in readdir order, which
changed with the runner image update of 2026-08-31, so main itself
went red in CI.

Fix: integrity.ts resolves the key and nonce paths lazily at call
time; the three tests restore HOME in afterAll.
No version bump: package.json and CHANGELOG are already at 0.1.95 from
08a6306 for this still-open PR, and this commit only extends that
unreleased entry's Fixed section with f710fe2 before the release ships.
@fusengine
fusengine merged commit abbc6b9 into main Sep 6, 2026
1 check passed
@fusengine
fusengine deleted the fix/codex-apply-patch-shrink branch September 6, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant