Skip to content

#1251 Let a rulebook declare that a guidance hook is how it is reached - #1259

Merged
williamthorsen merged 8 commits into
mainfrom
1251
Aug 10, 2026
Merged

#1251 Let a rulebook declare that a guidance hook is how it is reached#1259
williamthorsen merged 8 commits into
mainfrom
1251

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Aug 10, 2026

Copy link
Copy Markdown
Owner

What

Rulebooks can now name hook in their delivery, declaring that a guidance-hook binding is the route they take into an agent's context. sync now warns when a binding and a rulebook disagree: a bound rulebook that never claims the route, and one that is also delivered ambiently, so its text reaches the session twice. Neither fails the run.

An empty delivery list is now rejected. It previously parsed and named no route at all, so the rulebook deployed nowhere with nothing to say so; a rulebook carrying one must name at least one of ambient, hook, and skill before it will sync.

Why

Two rulebooks in the shipped library are reached only through a guidance-hook binding, and nothing in their declaration said so. The arrangement worked by accident and read as an omission rather than a choice.

That silence also left three misconfigurations unreported. A project could bind a rulebook never written for the splice, bind one that then delivers the same text into a session twice, or adopt a rulebook offering the route and never bind it, and get no signal in any of the three cases.

Details

🎉 Features

  • delivery accepts hook, alone or beside ambient and skill. The mode records a route rather than requesting one: the binding that splices a rulebook into a host body lives in codeassembly.yaml, so a rulebook cannot route itself there. That asymmetry is what makes a disagreement between the two expressible at all.
  • 🚨 Breaking: delivery: [] is rejected on parse, carrying the same message an unknown mode does. A project holding an empty list syncs today and fails outright after upgrading.
  • sync and sync --dry-run report three disagreements between a binding and the delivery of the rulebook it names. Bound while never claiming the route, and bound while also delivering ambient, are warnings; claiming the route while nothing binds it is advice. None changes the run's exit status or the files written, because a rulebook's delivery is written by its author and a binding by whoever adopts it, so a mismatch is not always the adopter's to fix.
  • The code-layout and TypeScript preference rulebooks declare hook alongside skill, stating the route a project already reaches them by. Both stay available as consult- skills, which is how they reach a session that invokes no hook-declaring skill or subagent.

🧪 Tests

  • Coverage spans the parse (hook alone and combined, and the empty list), the advisory computation through a real sync (each kind, the case where two fire for one rulebook, and the agreeing case), both report paths, and the frontmatter of the two library rulebooks that carry the route.

📚 Documentation

  • The README's declaration-format and guidance-hook sections and the content-specification rulebook cover the third mode, with the three reported conditions tabulated beside the two failures a binding can already cause.

Closes #1251

A rulebook can now declare `delivery: hook`, stating that a guidance-hook binding is how it reaches an agent's context. The mode is declarative: the binding that splices a rulebook into a skill or subagent body lives in `codeassembly.yaml`, so a rulebook cannot route itself there, and declaring the mode records the route rather than requesting it. It combines freely with `ambient` and `skill`.

An empty `delivery` list is now rejected. It previously parsed and named no route at all, leaving the rulebook to deploy nowhere with nothing to say so.
`sync` now compares each guidance-hook binding against the delivery the rulebook it names declares, and collects three disagreements: a bound rulebook that never claims the hook route, a bound rulebook that also charges every session with the same text, and a rulebook that claims the route while no binding uses it.

Every finding is advisory. A rulebook's delivery is written by its author and a binding by whoever adopts it, so a disagreement between the two is not always the adopter's to resolve and never fails their run.
`sync` and `sync --dry-run` now report each disagreement between a guidance-hook binding and the delivery of the rulebook it names. A binding whose rulebook never claims the hook route, and one whose rulebook also charges every session with the same text, are warnings; a rulebook offering a hook route that nothing binds is advice for adopting it.

A dry run reports them too, because each describes the declaration rather than the writes, and a dry run is where a declaration gets checked before it is committed to.
… rulebooks

The code-layout and TypeScript preference rulebooks now declare `hook` alongside `skill`, stating the route a project already reaches them by when it binds them to a guidance hook. Both remain available as `consult-` skills, which is how they reach a session that invokes no hook-declaring skill or subagent.
@williamthorsen williamthorsen added breaking Breaking API change or removal of functionality feature Added or improved external functionality scope:agents labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Dependency audit

Production dependency audit passed.

The README's guidance-hook section and the content specification now cover `delivery: hook`: what declaring it states, why it instructs nothing where `ambient` and `skill` instruct the resolver, and the three disagreements sync reports once a rulebook names the route. The specification also records that an empty `delivery` list is rejected on parse.
… closure

A guidance-hook binding naming a rulebook absent from the deploy closure now fails the run naming the rulebook and the hook, the way the two sibling passes over the same bindings already do. The advisory pass previously skipped such a binding in silence.
…is specified

The README paragraph defining what a declared rulebook's delivery does now covers all three modes, so a reader who meets `delivery: [hook, skill]` in the shipped library can account for it from the place the field is specified.
…sing

The assertion that a clean declaration renders no advisory now matches a phrase from each of the three kinds, sourced from one shared record the per-kind assertions also read. It previously matched a phrase only one kind carries, so a regression emitting either of the others passed it.

The advisory cases also move inside the suite whose fixture lifecycle they were duplicating.
@williamthorsen
williamthorsen marked this pull request as ready for review August 10, 2026 00:38
@williamthorsen williamthorsen self-assigned this Aug 10, 2026
@williamthorsen
williamthorsen merged commit 022dade into main Aug 10, 2026
3 checks passed
@williamthorsen
williamthorsen deleted the 1251 branch August 10, 2026 00:40
williamthorsen added a commit that referenced this pull request Aug 13, 2026
…e-v0.3.0 codeassembly-v0.9.0 factory-v0.2.6 codeassembly-mcp-v0.2.5

codeassembly-v0.9.0
- #1288 feat: State mutability and name the lede reader at the artifact type lists (#1303)
- #1285 fix: Require plain bullets for checklists on both update-jira-ticket paths (#1302)
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1294 feat: Specify artifact mutability and its sanctioned exceptions (#1297)
- #1293 fix: Present and classify discretionary findings as actionable (#1295)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1280 feat: Add a refresh path that edits an existing AGENTS.md instead of redrafting it (#1287)
- #1055 feat: Replace the lede doctrine with corpus-derived guidance and retire the changelog-writer (#1286)
- deps: Upgrade all deps to latest version
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)
- #1263 refactor: Retire the deferred-lint mechanism and adopt toolbelt.errors in agents (#1279)
- #1262 refactor: Hoist unreadable for-of expressions and promote the lint rule to an error (#1276)
- #1267 fix: Extend the no-hard-wrapping instruction to every GitHub composer (#1275)
- #1177 fix: Rewrite links, tokens, and template variables in a Markdown file support entry (#1273)
- #1176 feat: Add a ticketing-preferences hook to the skills that split and create tickets (#1268)
- #1252 fix: Keep a skill's own sections out of injected guidance (#1266)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)
- #1247 feat: Add a personal tooling-preferences rulebook (#1257)
- #1251 feat: Let a rulebook declare that a guidance hook is how it is reached (#1259)
- #1246 feat: Guard home-domain writes and record their provenance (#1254)
- #1175 feat: Link new tickets to their blockers and parents (#1249)

factory-v0.2.6
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- deps: Upgrade all deps to latest version
- deps: Upgrade all deps to latest version
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)

kb-v0.6.0
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)
- #1261 feat: Attach causes to kb's loader errors and retire its lint deferral (#1272)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)

codeassembly-lifecycle-v0.4.0
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1261 feat: Attach causes to kb's loader errors and retire its lint deferral (#1272)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)

codeassembly-mcp-v0.2.5
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)

codeassembly-run-core-v0.3.0
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)
- #1261 feat: Attach causes to kb's loader errors and retire its lint deferral (#1272)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking API change or removal of functionality feature Added or improved external functionality scope:agents

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Guidance-hook delivery cannot be declared

1 participant