Skip to content

v1.20.1 — the filter that was never read, and the check that would have said so - #20

Merged
sshlg merged 1 commit into
mainfrom
fix-hk-01-hooks-if
Sep 13, 2026
Merged

sshlg merged 1 commit into
mainfrom
fix-hk-01-hooks-if

Conversation

@sshlg

@sshlg sshlg commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

What

Claude Code 2.1.270 prints agent-sync: hooks.json: unknown key "if" in hooks.PreToolUse[1] ignored at every session start. Read out of the 2.1.270 binary's hook schema: a matcher group is {matcher, hooks}; if exists on a command handler only. The key sat beside matcher since 0.1.0 — declared, never evaluated. guard.sh has always narrowed to a commit with its own parser, so behaviour does not change; the warning goes.

Why removed, not moved

A handler-level if would be real, and a real Bash(git commit *) skips git -C <dir> commit, env X=1 git commit and cd d && git commit — the forms the parser exists to cover (2026-08-07 measurement).

Change

  • hooks.json: key removed; description says why there is no if
  • guard.sh header, references/hooks.md, README hook table, live AS-09 row: same statement
  • test/validate.py check_hooks_manifest: refuses any key outside the schema at either level; self-test plant hooks.json key at the wrong level (the exact file that shipped 0.1.0→1.20.0) → detected
  • test/audit_regressions/fix-sy-07.01.py: coverage from matchers + description, asserts no if at either level
  • versions → 1.20.1 (six homes), CHANGELOG, ledger REQ-29/30

Verification

npm test EXIT=0: PASS: agent-sync v1.20.1 — all checks green; SELF-TEST PASS (61 fixtures); claim cell 24; SessionStart identity 6; installer 11.

Sibling: task-pipeline #92 moves the same key onto the handler in its exported template.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y8geRdSG7rAD3xcGTrZpoZ

…ve said so

Claude Code 2.1.270 prints `agent-sync: hooks.json: unknown key "if" in
hooks.PreToolUse[1] ignored` at every session start. The key was there since
0.1.0. Read out of the binary's hook schema: a matcher group is `{matcher,
hooks}` and nothing else; `if` exists on a command handler only. So the filter
was declared and never evaluated — guard.sh has run on every Bash call in a
coordinated project for its whole life, narrowing to a commit with its own
parser. Nothing in behaviour changes with the key gone; the warning does.

Removed rather than moved: a handler-level `if` would be real, and a real
`Bash(git commit *)` skips `git -C <dir> commit`, `env X=1 git commit` and
`cd d && git commit` — the forms the parser covers. hooks.json's description,
guard.sh's header, references/hooks.md, the README hook table and the live
AS-09 row say the same thing; dated records keep their wording.

`check_hooks_manifest` refuses any key Claude Code does not know at either
level, with a self-test plant that puts the old `if` back and watches the
check fire (`claude plugin validate --strict` passes the defective file).
`fix-sy-07.01.py` derived "git commit is covered" from the group's `if`; it
now asserts the matchers, the description and the absence of `if`.

Gate: npm test EXIT=0 — PASS: agent-sync v1.20.1 — all checks green;
SELF-TEST PASS (61 fixtures); claim cell 24; SessionStart identity 6;
installer 11.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y8geRdSG7rAD3xcGTrZpoZ
@sshlg
sshlg merged commit a0c9825 into main Sep 13, 2026
2 checks passed
@sshlg
sshlg deleted the fix-hk-01-hooks-if branch September 13, 2026 20:54
sshlg added a commit to ssheleg/sshlg-skills that referenced this pull request Sep 13, 2026
… runs here

All three homes move together: skills.json, the submodule pointer (a0c9825, the
squash-merge of ssheleg/agent-sync#20, tagged v1.20.1) and the README table;
the CTX-04.06 staging receipt regenerated rather than edited, as #127 did.
Registry read: `npm view @ssheleg/agent-sync version` → 1.20.1;
`python3 test/check_pins.py` → every pin matches its release.

task-pipeline's pin waits for #92 (validate at step ~207 of 465).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y8geRdSG7rAD3xcGTrZpoZ
sshlg added a commit to ssheleg/sshlg-skills that referenced this pull request Sep 14, 2026
… it (#137)

* Family audit 2026-09-13 — the hook key nobody read, and `injectors` cites the running version

Claude Code 2.1.270 prints `agent-sync: hooks.json: unknown key "if" in
hooks.PreToolUse[1] ignored` at every session start. Read out of the binary's
hook schema: a matcher group is `{matcher, hooks}`; `if` exists on a handler
only. The key filtered nothing since agent-sync 0.1.0, `claude plugin validate
--strict` passes it, and the same shape sat in task-pipeline's exported
template. Fixed in agent-sync v1.20.1 and task-pipeline v1.86.2 (in flight);
the pins move here once both are on the registry.

This commit:
- `lib/injectors.js` consulted the plugin cache in directory order and cited
  agent-sync's hooks.json at 1.18.6 while 1.20.0 was running. It now reads the
  version `installed_plugins.json` names first, then newest semver
  (`orderVersions`, `installedVersion`; +5 fixtures, `injectors_test.js` 14
  checks). Verified live against this machine's registry.
- `docs/evidence/audits/2026-09-13-family-hooks/` — the audit (ten gates, four
  read-only auditors over 28 skills, 1,104 doc addresses) and a 13-task plan
  where every task carries a packet an unfamiliar agent can execute, plus the
  model-routing table (Fable high plans, Opus high/xhigh executes).
- `docs/HANDOFF.md` points at that plan as the active one.
- DOCMAP ratchet re-derived: fixtures 1014 → 1019.

Gate: node test/run.js → PASS: 87 checks green; COUNTED 87 suites, 1019
fixtures, 9 pinned members.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y8geRdSG7rAD3xcGTrZpoZ

* Pin agent-sync to v1.20.1 — the hook key is gone from the plugin that runs here

All three homes move together: skills.json, the submodule pointer (a0c9825, the
squash-merge of ssheleg/agent-sync#20, tagged v1.20.1) and the README table;
the CTX-04.06 staging receipt regenerated rather than edited, as #127 did.
Registry read: `npm view @ssheleg/agent-sync version` → 1.20.1;
`python3 test/check_pins.py` → every pin matches its release.

task-pipeline's pin waits for #92 (validate at step ~207 of 465).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y8geRdSG7rAD3xcGTrZpoZ

* Guard: a pipe into `python3 -` beside a heredoc is one stdin with two passengers

Measured on the operator's own agent, 2026-09-14: `heroku config:get
DATABASE_URL -a app | python3 - <<'PY'`. The pipe and the heredoc both fed
stdin, the pipe won, the interpreter parsed the connection string as source
and SyntaxError printed the line it could not parse — password included. The
agent was protecting the value from argv and did not see the channel was
already taken by the program.

New rule `secret-into-stdin-program`: any pipe into an interpreter that reads
its code from stdin (`python3 -`, `python -`, `node -`, `ruby -`, `perl -`,
`sh|bash|zsh -s`) with a heredoc beside it is refused, with the two fixes: put
the program in a file (`… | python3 probe.py`), or hand the value over as a
variable with the output scrubbed (project-observatory's
`tools/use_secret.py pipe NAME -- python3 probe.py`). The producer's shape is
not checked — the mistake is the same whoever is upstream. Two cases in
test/secrets_test.js; 35 checks green.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* DOCMAP ratchet: fixtures 1019 -> 1021 — the two stdin-program cases

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* DOCMAP: the Ratchets sentence follows its marker (fixtures=1021)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Pin seven members at the releases the 2026-09-13 audit produced

All three homes move together for each: skills.json, the submodule pointer at
the annotated tag, and the README table. Registry-confirmed before the pin —
`python3 test/check_pins.py` reports `ok` for all seven and BEHIND for the two
still in flight (super-ux 0.56.2, task-pipeline 1.87.0), which is the honest
state rather than a pin to something nobody published.

  agent-sync     1.20.1 → 1.20.2   the operator reap reaches the git plane
  make-skill     0.28.0 → 0.29.0   HOOKS_SCHEMA, the check that closes the class
  sheleg-design  1.60.2 → 1.61.0   17 KB of doctrine becomes reachable
  seo-aeo-audit  0.26.0 → 0.26.1   B-27 closes; the estimator was the defect
  sheleg-dev     0.12.0 → 0.13.0   degradation in all seven bodies
  agent-stack    0.24.2 → 0.24.3   the budget is measured, not estimated
  telegram-dev   0.2.0  → 0.2.1    both invocation forms in the README

The CTX-04.06 staging receipt was regenerated rather than edited.
DOCMAP ratchet re-derived: fixtures 1019 → 1021.

Gate: node test/run.js → PASS, 87 suites, 1021 fixtures, 9 pinned members.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Pin super-ux at 0.56.2

Registry-confirmed: npm view super-ux version -> 0.56.2. All three homes move
together; the CTX-04.06 staging receipt regenerated rather than edited.
task-pipeline stays BEHIND until 1.87.0 publishes — an honest state, not a pin
to something nobody served.

Gate: node test/run.js -> PASS, 87 suites, 1021 fixtures, 9 pinned members.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Pin task-pipeline at 1.87.0 — the plan-audit gate the operator asked for

The ninth and last pin of this wave. All three homes move together;
`check_pins.py` now reports `every pin matches its release` across the set.
The CTX-04.06 staging receipt was regenerated rather than edited.

v1.87.0 is stage 4's own gate: every live node's packet must answer the cold
reader's eight questions, two nodes the GRAPH leaves unordered may not edit one
file, priority is computed from what each node unblocks, and a recorded
per-stage model map is checked. Plus the plan-then-execute profile, with its
basis written down.

Gate: node test/run.js -> PASS, 87 suites, 1021 fixtures, 9 pinned members.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Робот <r@e.com>
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