Skip to content

#1114 Adopt a dependency's guidance by naming the package - #1121

Merged
williamthorsen merged 11 commits into
mainfrom
1114
Jul 30, 2026
Merged

#1114 Adopt a dependency's guidance by naming the package#1121
williamthorsen merged 11 commits into
mainfrom
1114

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Jul 30, 2026

Copy link
Copy Markdown
Owner

What

A project can now adopt guidance accompanying a package by naming the package in codeassembly.yaml. This brings in every rulebook, skill, and subagent that the package carries. The sync command and drop key support this new guidance-delivery method.

A package makes its guidance available by naming the content directory in its package.json.

Why

Dependencies were the only producer of agent guidance with no route into a consuming repo. Each package that shipped guidance had to invent its own bridge and have it wired up by hand in every repo that consumed it, so guidance that existed went unread, and the copy a repo did wire up drifted from the version installed.

Details

🎉 Features

  • packages: is a new top-level block in codeassembly.yaml, carrying the same use/drop shape as an artifact type, so root: true and the two-tier scope chain apply to it with no new semantics. Among packages the highest tier wins, and within a tier the last declared wins.
  • A declared name resolves through Node's module resolver to the directory the package names under codeassembly.content in its own package.json. Resolution holds under pnpm hoisting, pnpm's symlinked layout, and workspace:* links, and a package shipping no importable JavaScript resolves. A name that is a filesystem path is rejected, pointing at sources instead.
  • The resolved directory joins the source search order below every sources entry and above the built-in library, and participates in the existing shadow warning. Its whole catalog seeds the dependency closure, so all four artifact types reach a consumer through the resolution paths that already existed.
  • sync reports installed direct dependencies that declare content and that the project has neither adopted nor declined, printing the packages: block that would adopt them.
  • A declared package that is not installed, declares no content directory, or points at a missing one fails the run, dry-run included, before anything is written, naming what was searched.

♻️ Refactoring

  • The codeassembly.yaml parse wrapper attaches the caught error as cause, so a malformed-YAML failure carries its origin.
  • Cross-namespace collision detection in sync uses Set.prototype.intersection.

🧪 Tests

  • Fixture packages under a temp project's node_modules exercise resolution and end-to-end deployment with no real install, covering scoped and unscoped names, a content directory nested under one the package already owns, a package with no JavaScript, and a symlinked node_modules entry.

📚 Documentation

  • The package README gains a consumer section covering the declaration, precedence, resolution, and discovery advice, and a producer section covering the required codeassembly.content key, the directory layout it points at, and the files entry whose omission a workspace:* self-link cannot catch.

Closes #1114

`codeassembly.yaml` accepts a `packages:` block naming installed packages that ship CodeAssembly content. It behaves like the existing per-type blocks: entries accumulate across the project and project-local tiers, a higher tier can drop a package a lower tier declared, and `root: true` discards the packages declared below it.
A package that ships CodeAssembly content declares where it lives with a `codeassembly` entry in its `package.json`, pointing at a directory structured like a content root. There is no default location, so a package can nest its content under a directory it already owns.

Resolution holds under pnpm's symlinked layout and under `workspace:*` links, so a repo that produces a package consumes its own guidance through the same declaration a third party writes. A package that ships no JavaScript at all resolves like any other. A declared package that is not installed, or that declares no content, fails with an error naming the package and every location searched.
A malformed `codeassembly.yaml` reports the underlying YAML error as the wrapped error's cause, so the original parse position survives into a stack trace.
Naming an installed package in `codeassembly.yaml`'s `packages:` block deploys every rulebook, skill, and subagent it ships, and its content joins the search order for any slug declared elsewhere. A hand-declared `sources` entry outranks a package, and a package outranks the built-in library, so a package that masks a library slug is reported by the existing shadow warning.

Dropping the package from a higher tier retracts what it contributed. A declared package that is not installed, or whose content directory is missing, fails the run before anything is written, `--dry-run` included.
`sync` reports the direct dependencies that ship CodeAssembly content the project has not declared, printing the `packages:` block that adopts them.

The report is advice only: nothing is deployed until the project declares the package, and a dependency that cannot be read is skipped rather than failing the run.
Readers adopting a dependency's guidance find the `packages:` declaration, its precedence relative to `sources` and the library, how a project-local tier declines a package, and what `sync` reports about dependencies that ship content undeclared.

Package authors find the required `codeassembly` key in `package.json`, the directory shape it points at, and why the content directory must appear in published `files` — the one mistake a `workspace:*` self-link hides from the author and surfaces only in a consumer's install.
…es entry

Resolution through a symlinked `node_modules` entry is asserted rather than assumed, covering how pnpm lays out both an external dependency and a `workspace:*` sibling.
Two packages that ship the same slug resolve by the rule every other declaration block follows: the highest tier wins, and within a tier the last declared wins. A project-local tier can now override a package the committed tier adopted.

`drop` also records the package as declined rather than merely absent, which lets a caller tell a package a project turned down from one it has never mentioned.
`drop` silences the discovery advice for a package the project turned down, so declining a dependency is durable rather than re-offered on the next `sync`.

A `packages:` entry that is a filesystem path fails with an error pointing at `sources`. Node answers a relative specifier with the anchor directory itself, so `./guidance` would otherwise resolve to a directory beneath the project and `../sibling` to one outside it.
The precedence rule reads in cross-tier terms: every `sources` entry from any tier outranks every package, and packages rank among themselves by tier then declaration order.

Readers learn that installation safety covers an undeclared dependency, while upgrading a declared one deploys any artifact its new version adds, with `sync --dry-run` naming the source of each. They also learn that a package's catalog is its rulebooks, skills, and subagents, so a collection it ships reaches a consumer only when that consumer names it, and that a `dependencies:` edge is how a package pulls in an artifact from outside its own catalog.
@williamthorsen williamthorsen added feature Added or improved external functionality scope:agents labels Jul 30, 2026
@github-actions

Copy link
Copy Markdown

Dependency audit

Production dependency audit passed.

@williamthorsen williamthorsen self-assigned this Jul 30, 2026
@williamthorsen
williamthorsen marked this pull request as ready for review July 30, 2026 07:34
@williamthorsen
williamthorsen merged commit cc5d238 into main Jul 30, 2026
3 checks passed
@williamthorsen
williamthorsen deleted the 1114 branch July 30, 2026 07:50
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Added or improved external functionality scope:agents

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Packages deliver the guidance artifacts for using them

1 participant