Skip to content

Codex and Hermes never left an intent record, because their edits name the file inside the patch - #71

Merged
opencdlee-dotcom merged 1 commit into
mainfrom
agent/claude/intent-hook-patch-paths
Sep 24, 2026
Merged

opencdlee-dotcom merged 1 commit into
mainfrom
agent/claude/intent-hook-patch-paths

Conversation

@opencdlee-dotcom

Copy link
Copy Markdown
Owner

Why

The intent ledger lets a supervised agent vouch for its own writes: the harness calls aegis.py intent hook <tool> after each file write, and a surface change whose bytes match a record grades LOW instead of HIGH. On this Mac, ~/.aegis/intent.jsonl holds 3,689 claude-code records and zero from Codex or Hermes. Because of that, some agent-config edits those two agents made still alert.

There were two reasons, and only one of them was in aegis:

  • aegis: hook mode read only tool_input.file_path / path. Codex's apply_patch and Hermes's patch(mode=patch) send V4A patch text and no path field. The files they write are named inside the patch (*** Add File:, *** Update File:, *** Move to:), relative to the payload's cwd.
  • config (fixed outside this repo): the Codex hook entry matched Write|Edit|…, Claude Code's tool names. Codex never calls those, so the hook never fired. Hermes had no entry at all.

What

  • _v4a_patch_paths(text, cwd) collects the files a V4A patch leaves on disk. An Update followed by a Move to records the destination. Delete File is skipped because there is no content to attest. Only line-start markers count, so prose that quotes a marker is not treated as a write.
  • _intent_hook_paths(payload) checks the direct path first (Claude Code; Hermes write_file and patch(mode=replace)). If there isn't one, it reads every V4A patch in tool_input: a dict value, a list element (the older Codex ["apply_patch", patch] form), or a bare string (Codex freeform).
  • Hook mode still prints nothing and always exits 0.

Evidence

  • New tests: one Codex dict payload, one Codex bare-string payload, and one Hermes patch payload each attest every written file. The Move to and Delete cases are pinned, and a prose line that mentions a marker yields nothing. Both tests failed before the change and pass after it.
  • Full suite: 2073 passed, 6 skipped, 30 xfailed, 0 failed (local, macOS, py3; ledger audited after the run: no rows added to the live custody.jsonl).

Not in this PR

Outside the repo, the Codex hooks.json matcher now includes apply_patch, and Hermes config.yaml has a new post_tool_call entry. Each agent's own consent gate has to approve the changed hook (Codex trusted_hash, the Hermes shell-hook allowlist). That approval is the operator's, and it happens at the next launch.

🤖 Generated with Claude Code

…e the file inside the patch

Hook mode read only tool_input.file_path / path. Codex apply_patch and
Hermes patch(mode=patch) send V4A patch text with the paths inside it,
relative to the payload's cwd, so the live ledger held 3,689 claude-code
records and none from either agent. Parse Add/Update/Move-to targets out
of any V4A patch in tool_input; a direct path still wins.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@opencdlee-dotcom
opencdlee-dotcom merged commit ab9bd3b into main Sep 24, 2026
9 checks passed
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