Skip to content

hooks: 馃悰 Keep primitive fire limits stable across releases - #315

Merged
yasyf merged 1 commit into
mainfrom
hook-diet-nudgekey
Oct 5, 2026
Merged

yasyf merged 1 commit into
mainfrom
hook-diet-nudgekey

Conversation

@yasyf

@yasyf yasyf commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Context: The hook-diet lane in the release-v3 drive found a max_fires=1 nudge
firing repeatedly, tracked as captain-hook cc-notes task 8ec2bdf. One session held
39 keys for the cc-notes "cc-notes is installed" nudge, one per release from 12.73.0
to 12.87.6, and it fired 73 times. The monorepo's pr_landing_fields nudge had about
28 keys and appeared 4-5 times to agents.

Summary: Attribute primitive hooks to the pack or repo module that registered them
so their state keys and fire counters survive capt-hook releases.

Motivation: Every primitive registers a framework-defined handler through on(),
which recorded the handler's file under ~/.daemonkit/tools/capt-hook/<version>/.
RegisteredHook._state_identity could not make that file relative to the pack
directory and used the absolute path. Each release therefore minted a new key and
reset the hook's max_fires counter mid-session.

Details:

  • Match hook() by attributing framework-defined handlers to the first caller
    outside the framework. User and builtin-pack handlers keep their own file,
    preserving each handler's module when a decorator is shared across modules.
  • Add keyword-only source_file to on(). The loader's provision_pack_resources,
    announce_pr_status, and announce_faults hooks pass their source file explicitly;
    CliState.discover stamps their identities as package-relative loader.py.
  • Give review FIX routing the pack or repo file for primitive fires. Store the
    watched repo root in PackIndex and rename plugin_rel_path to root_rel_path.
    Relativize repo-local targets so scanning sessions can find them with
    git cat-file -e origin/<default>:<path>, including hook() and @on hooks.
  • Include repo directories containing only primitive hooks in capt-hook list
    and the hook-lint pass.
  • Add a subprocess test that loads captain_hook from two symlinked installs,
    asserting identical keys and identity ccx\0guard.py for nudge, gate,
    llm_nudge, set_tool_input, and rewrite_command. Cover shared decorators,
    loader.py identities, repo-relative FIX targets, and the caller file in
    decision records.
  • Leave old session keys unmigrated. Each primitive's counter restarts once after
    upgrading.

Context: The hook-diet lane in the release-v3 drive found a `max_fires=1` nudge
firing repeatedly, tracked as captain-hook cc-notes task `8ec2bdf`. One session held
39 keys for the cc-notes "cc-notes is installed" nudge, one per release from 12.73.0
to 12.87.6, and it fired 73 times. The monorepo's `pr_landing_fields` nudge had about
28 keys and appeared 4-5 times to agents.

Summary: Attribute primitive hooks to the pack or repo module that registered them
so their state keys and fire counters survive capt-hook releases.

Motivation: Every primitive registers a framework-defined handler through `on()`,
which recorded the handler's file under `~/.daemonkit/tools/capt-hook/<version>/`.
`RegisteredHook._state_identity` could not make that file relative to the pack
directory and used the absolute path. Each release therefore minted a new key and
reset the hook's `max_fires` counter mid-session.

Details:

- Match `hook()` by attributing framework-defined handlers to the first caller
  outside the framework. User and builtin-pack handlers keep their own file,
  preserving each handler's module when a decorator is shared across modules.
- Add keyword-only `source_file` to `on()`. The loader's `provision_pack_resources`,
  `announce_pr_status`, and `announce_faults` hooks pass their source file explicitly;
  `CliState.discover` stamps their identities as package-relative `loader.py`.
- Give review FIX routing the pack or repo file for primitive fires. Store the
  watched repo root in `PackIndex` and rename `plugin_rel_path` to `root_rel_path`.
  Relativize repo-local targets so scanning sessions can find them with
  `git cat-file -e origin/<default>:<path>`, including `hook()` and `@on` hooks.
- Include repo directories containing only primitive hooks in `capt-hook list`
  and the hook-lint pass.
- Add a subprocess test that loads `captain_hook` from two symlinked installs,
  asserting identical keys and identity `ccx\0guard.py` for `nudge`, `gate`,
  `llm_nudge`, `set_tool_input`, and `rewrite_command`. Cover shared decorators,
  `loader.py` identities, repo-relative FIX targets, and the caller file in
  decision records.
- Leave old session keys unmigrated. Each primitive's counter restarts once after
  upgrading.

cc-task: 8ec2bdf

Claude-Session-Id: 900424b6-7393-480c-a26a-f1bd21da6e57
@yasyf
yasyf force-pushed the hook-diet-nudgekey branch from ac8ede3 to f533c8b Compare October 5, 2026 07:21
@yasyf
yasyf merged commit 3072caf into main Oct 5, 2026
23 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