Skip to content

fix(local-agent): write agent hooks where each tool reads them - #1224

Merged
jeff-r2026 merged 5 commits into
Tencent:mainfrom
SaulMoro:fix/local-agent-hook-paths
Oct 20, 2026
Merged

jeff-r2026 merged 5 commits into
Tencent:mainfrom
SaulMoro:fix/local-agent-hook-paths

Conversation

@SaulMoro

Copy link
Copy Markdown
Collaborator

Closes #1220

Summary

 server-pushed hooks
- project settings paths under HOME
+ Muse ~/.config/muse/settings.json with schema_version: 1
+ Qoder CN ~/.qoder-cn/settings.json; remove old-path entries too
- Hermes SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Stop
+ Hermes on_session_start / pre_llm_call / pre_tool_call / post_tool_call / on_session_end
- acknowledge unsupported ZCode/OpenCode installs
+ fail the acknowledgement before writing
+ Codex: trust the installed hook; preserve survivor approval by exact original key and unchanged native hash

Codex removal maps each surviving file/event/group/handler key to its original key. Identical content in a removed group cannot approve an unapproved survivor.

Evidence

  • Real CLI after npm run build, using source add-http and hook-dispatch against an isolated HTTP fixture. Before on main: ZCode returned "status":"success" and config.json changed:; Muse wrote ~/.muse/hooks.json; native Codex listed stop:0:0 echo codex-agent-hook untrusted. After: ZCode returned "status":"failed" and config.json unchanged; Muse reported ~/.config/muse/settings.json schema_version: 1 and ~/.muse/hooks.json absent; Codex listed stop:0:0 echo codex-agent-hook trusted after reinstall and removal.
  • Three regressions failed before the fix and now pass. Given a removed approved two-handler group, an unapproved identical personal hook, and an approved surviving two-handler group, then HTTP uninstall, HTTP reinstall, and teardown each leave only the personal duplicate unapproved.
  • Native Codex 0.163.0 assertions pass through public teardown. After compaction, stop:0:0 echo personal remains modified; both stop:1:0 echo approved first and stop:1:1 echo approved second remain trusted. The ownership manifest is empty.
  • npx tsc --noEmit, npm run lint, and npm run build pass. npx vitest run passes 11,217 tests, with 21 skipped. Six focused files pass 329 tests; an additional focused run of the local-agent and Codex trust suites passes 190 tests.
  • Not run here: native Muse, Qoder CN, Hermes, and OpenCode execution; Windows; other tool/provider combinations, including GitLab and GitHub. These remain for CI or native follow-up.

Merge Danger

Door: two-way

The code can be reverted. Existing settings and ownership records stay in their current formats.

Blast Radius: hooks

Touches HTTP hook installation, replacement, and removal. Codex trust writes require exact retained identity and unchanged native content.

Pre-existing limits remain. Full uninstall later removes built-ins without preserving personal survivor trust. Legacy ZCode records cannot clean native hooks.events through the generic remover.

Optional next improvement: add a full-uninstall test with trusted built-in, recorded server hook, and personal hook; assert the personal survivor stays trusted after built-in removal.

…nt#1220)

The HTTP local agent joined each tool's project-scope settings path to
$HOME, so Muse and Qoder CN got agent hooks in files they never read, and
ZCode got a Claude-shaped hooks key its strict schema rejects, taking the
whole user config with it.

- Resolve the user-scope settings file, as pull does, and clear the old
  path on removal.
- Refuse ZCode until agent hooks are written in its hooks.events format.
- Trust a Codex agent hook after writing it, and fail the ack when Codex
  will not run it (no codex on PATH, codexTrustEnabled: false).
- Register Hermes agent hooks under Hermes's own event names.
- Fail the ack for an event OpenCode has no equivalent for.
…ion Muse settings (Tencent#1220)

Codex keys hook trust by position, so removing or reinstalling one agent
hook left every later hook in the file untrusted. Removal now re-trusts
the hooks whose hash Codex trusted before the rewrite, and nothing else.

A new Muse settings.json now carries schema_version: 1, which Muse
requires to load it.
…trusted (Tencent#1220)

Two identical hooks share a Codex hash but not an approval, so carrying
trust over by hash could approve a copy the member never approved. Match
each surviving entry to the one it was, in order, instead.
@github-actions

Copy link
Copy Markdown
  • [P1 blocking] Clear inherited approvals for untrusted survivors in src/codex-trust.ts:310. Given [agent hook, trusted personal hook, untrusted identical personal hook], removing the agent shifts the untrusted duplicate onto the trusted personal hook’s old key. Its identical hash makes Codex report it as trusted. The new preservation pass only adds approvals; it never clears this inherited approval, so both personal hooks become trusted. Reconcile surviving keys against their original trust status, including removing incorrectly inherited grants.

The PR description supplies sufficient post-build real-CLI testing evidence. The explicitly deferred provider/agent coverage is not blocking.

@github-actions

Copy link
Copy Markdown

No new findings in the specified PR diff.

  • Resolved: The earlier inherited-approval finding is fixed in src/codex-trust.ts:315: surviving hooks that inherit trust without matching their original approval have that grant removed. The diff also adds a regression test for the reported scenario.
  • Testing: The PR description supplies sufficient post-build real-CLI verification. Explicitly deferred provider/agent coverage is not blocking.

Review was read-only; I did not run, build, or install anything from the PR.

@jeff-r2026
jeff-r2026 merged commit 6bd1e8d into Tencent:main Oct 20, 2026
14 checks passed
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 26, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 27, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
jeff-r2026 pushed a commit that referenced this pull request Oct 27, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 27, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
SaulMoro added a commit that referenced this pull request Oct 27, 2026
…tor (#1221)

The env, workflows, recall, stats, AI backend, votes judge and HTTP agent
hook rows of #1221's matrix become a required `features` facet, one
`SupportCell` per row: the mark and the evidence letter, as the matrix
writes them. A cell a later fix changed (#1193, #1224, #1245, #1374) says
so in its note and keeps teamai's-code-only evidence until it is rerun.
Data only: nothing reads it but the support page.
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.

[bug] local agent: agent hooks go to files the tool does not read, and the ZCode one makes ZCode reject its user config

2 participants