#1125 Honor invocation tokens in rulebook bodies - #1129
Merged
Conversation
The invocation-token grammar recognizes a `rulebook` kind alongside `skill` and `subagent`. A rulebook token resolves to the skill name its target deploys under, honoring a `skill-name` override, and reports a reason when the target deploys no skill to invoke.
A rulebook that names another artifact by invocation token in its body pulls that artifact into the deployed set, so the reference needs no duplicate `dependencies:` entry. A rulebook naming itself keeps the reference without becoming a dependency cycle.
A `{rulebook:<slug>}` token counts as an edge only from a rulebook body, the one place it renders.
A rulebook body may now invoke what it routes to. A `{rulebook:<slug>}` token renders as the deployed skill name of the rulebook it names, and `{skill:}` and `{subagent:}` tokens render in a rulebook body as they already do in skills and subagents. Each renders behind the sigil of the harness it is delivered to, in both ambient and skill delivery.
A token naming a rulebook that deploys no skill to invoke fails the run before anything is written, naming every offending token at once and pointing at `dependencies:` for the relationship it cannot express.
Linking to a sibling rulebook still fails the run, and the error now names the `{rulebook:<slug>}` token that addresses it instead, so the rejection teaches the convention rather than only reporting the rule.
…fication
The content specification describes `{rulebook:<slug>}` alongside the skill and subagent tokens: what it renders to, why only a rulebook body renders one, and why an `ambient`-only target is rejected in favor of `dependencies:`. The links section now sends an author writing a sibling-rulebook link to the token instead, and the rewriting caveat covers tokens as well as links, so an example keeps its `<slug>` placeholder rather than naming a real artifact.
…ries it
The error raised for an unusable `{rulebook:<slug>}` token names the file it was found in, so an author fixing a skill or subagent goes straight to the source rather than searching the deployed set for it.
A subagent whose body fails to render now aborts the sync before the ambient host and skill files are written, and fails `--dry-run` rather than passing it. Previously the failure surfaced only in the last write pass, leaving earlier passes already on disk.
This covers an unmapped `{tool:NAME}` placeholder as well as the `{rulebook:<slug>}` token a subagent body may not carry.
A subagent named by a token in a rulebook body is asserted to enter the deployed closure, alongside the skill and rulebook edges already covered. Drops a rulebook-transform assertion whose name claimed the pre-pass runs before rewriting. Both paths throw, so the assertion held either way; the sibling case asserting two offending tokens in one error is what distinguishes them.
The rulebook slug derived inside the sibling-rulebook branch is named `targetSlug`, so it no longer shadows the enclosing `target` parameter holding the link target as authored.
The content specification states that only `{rulebook:<slug>}` is checked against the deployed set. A `{skill:<slug>}` or `{subagent:<slug>}` token renders on every harness its body reaches, including one its target narrows itself away from with `harnesses:`, so an author naming such a skill scopes it in the surrounding text.
Dependency auditProduction dependency audit passed. |
williamthorsen
marked this pull request as ready for review
July 31, 2026 01:40
williamthorsen
added a commit
that referenced
this pull request
Aug 4, 2026
…e-v0.2.2 codeassembly-v0.4.0 factory-v0.2.2 codeassembly-mcp-v0.2.2 codeassembly-v0.4.0 - #1153 feat: Make codeassembly and kb CLI tools publishable (#1164) - #1091 fix: Anchor a project-deployed link where its target deploys (#1159) - #1156 refactor: Rename packages to publishable names (#1157) - #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155) - #1110 tooling: Migrate Vitest to nmr's centralized model (#1154) - refactor: Refine typescript-preferences - #1150 fix: State doc-description form and make comment mood opt-in (#1151) - deps: Upgrade first-party linting deps to latest version - #1137 feat: Establish personal rulebooks for code layout and TypeScript preferences (#1144) - #1126 feat: Check a package's own guidance content before it ships (#1138) - refactor: Fix lint - tooling: Remove redundant lint rules - #1133 fix: Reject an anchor link that names no heading (#1135) - #1122 feat: Capture lede decisions as an accumulating corpus (#1132) - #1125 feat: Honor invocation tokens in rulebook bodies (#1129) - #1107 feat: Render rulebook links and path tokens per harness (#1124) - #1115 feat: Sync guidance at build and install so an upgrade cannot leave it stale (#1123) - #1114 feat: Adopt a dependency's guidance by naming the package (#1121) - #1088 feat: Deliver project ambient rulebooks per harness (#1113) - #1087 refactor: Rename the authoring rulebook and mark its enforced rules (#1092) - #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102) - #1094 refactor: Remove the ambient ripgrep dependency from the test suite (#1097) - deps: Upgrade all deps to latest version - tooling: Upgrade all deps to latest version & modernize configs - refactor: Fix lint - #1077 feat: Show the proposed edit above post-review menu options (#1078) - #1068 feat: Deliver ambient rulebooks mechanically, retiring GLOBAL.md (#1075) - #1069 feat: Add a no-second-person rule to the lede-voice doctrine (#1070) - #1050 feat: Add a redundancy rule to the lede-voice doctrine (#1058) - #1035 internal: Add lifecycle workspace with the canonical envelope, vocabulary & lane fold (#1049) - #1006 internal: Extend lifecycle-event instrumentation to five high-traffic skills (#1034) - #1028 feat: Rule out absence-of-removed-code tests (#1032) - #114 feat: Let reviewers emit gated insights into review artifacts (#1031) - #1027 internal: Retire input.received and redundant skill.progress emits (#1030) - #1026 fix: Name the side effects an approval ask authorizes (#1029) - #1022 fix: Normalize action and question label identifiers across asks blocks (#1025) factory-v0.2.2 - #1156 refactor: Rename packages to publishable names (#1157) - deps: Upgrade all deps to latest version - #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155) - #1110 tooling: Migrate Vitest to nmr's centralized model (#1154) - tooling: Remove redundant lint rules - deps: Upgrade deps to latest version - deps: Upgrade all deps to latest version - deps: Upgrade all deps to latest version - tooling: Upgrade all deps to latest version & modernize configs - refactor: Fix lint - deps: Upgrade all deps to latest version kb-v0.3.0 - #1153 feat: Make codeassembly and kb CLI tools publishable (#1164) - #1156 refactor: Rename packages to publishable names (#1157) - #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155) - #1110 tooling: Migrate Vitest to nmr's centralized model (#1154) - tooling: Remove redundant lint rules - #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102) - tooling: Upgrade all deps to latest version & modernize configs - refactor: Fix lint codeassembly-lifecycle-v0.2.0 - #1153 feat: Make codeassembly and kb CLI tools publishable (#1164) - #1156 refactor: Rename packages to publishable names (#1157) - #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155) - #1110 tooling: Migrate Vitest to nmr's centralized model (#1154) - tooling: Remove redundant lint rules - #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102) - tooling: Upgrade all deps to latest version & modernize configs - #1038 feat: Add the read-only git adapter for worktree and base-branch ground truth (#1059) - #1051 feat: Bound fold memory and rescan cost with a retention window (#1057) - #1035 internal: Add lifecycle workspace with the canonical envelope, vocabulary & lane fold (#1049) codeassembly-mcp-v0.2.2 - deps: Upgrade all deps to latest version - #1156 refactor: Rename packages to publishable names (#1157) - #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155) - #1110 tooling: Migrate Vitest to nmr's centralized model (#1154) - #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102) - tooling: Upgrade all deps to latest version & modernize configs - refactor: Fix lint codeassembly-run-core-v0.2.2 - #1156 refactor: Rename packages to publishable names (#1157) - #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155) - #1110 tooling: Migrate Vitest to nmr's centralized model (#1154) - #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102) - tooling: Upgrade all deps to latest version & modernize configs - refactor: Fix lint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A rulebook can now route an agent to another skill, subagent, or rulebook as a direct invocation rather than a name mentioned in prose; each delivery renders that invocation in the form the receiving harness understands. A rulebook that routes to a missing target, or to one that deploys nothing an agent can invoke, now fails the run. Naming a routing target is now enough to have it deployed alongside the rulebook that names it.
Why
A hub-and-spoke guidance set exists to send an agent to the right reference, and a rulebook had no way to say where. Prose routing left the reader a name to type, with nothing guaranteeing the named artifact had been deployed and nothing failing when it did not exist -- a gap that widens as more packages ship a cheatsheet plus a set of reference rulebooks.
Details
🎉 Features
{rulebook:<slug>}token in a rulebook body renders the harness skill sigil plus the skill name its target deploys under, honoring askill-nameoverride on that target.{skill:}and{subagent:}tokens render in a rulebook body as they already do in skills and subagents, in both ambient and skill delivery.dependencies:for the relationship it cannot express.{rulebook:<slug>}token that addresses it instead.🐛 Bug fixes
--dry-runrather than passing it. This covers an unmapped{tool:NAME}placeholder alongside the newly rejected token.🏗️ Internal features
rulebookkind alongsideskillandsubagent, resolving a target to the skill name it deploys under or reporting why it cannot.dependencies:entry. A rulebook naming itself keeps the reference without becoming a dependency cycle, and a{rulebook:}token counts as an edge only from a rulebook body.♻️ Refactoring
🧪 Tests
Closes #1125