Skip to content

#1280 Add a refresh path that edits an existing AGENTS.md instead of redrafting it - #1287

Merged
williamthorsen merged 6 commits into
mainfrom
1280
Aug 11, 2026
Merged

#1280 Add a refresh path that edits an existing AGENTS.md instead of redrafting it#1287
williamthorsen merged 6 commits into
mainfrom
1280

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Aug 11, 2026

Copy link
Copy Markdown
Owner

What

Refines the update-project-guidance skill so that modification of an existing AGENTS.md is performed differently from generation of a new one. If an existing file already contains substantive guidance, the skill instructs an agent to edit it in place, making only the revisions needed to align its content with the codebase.

Separately, the published guidance checklist now also checks that the repository-root AGENTS.md file is harness-neutral and contains no CodeAssembly-managed rulebook regions.

Why

Run against a mature AGENTS.md, the skill drafted a replacement from its skeleton, so the densest sections, the ones carrying the most value, were the likeliest to be summarized away. Nothing checked the file's claims against the codebase either, and drift is what actually goes wrong in a mature ambient file: a stale directory listing, a count off by two, a tool named one hop from what runs. Each of those passes every check the guidance checklist could answer, whose only drift signal was a freshness count that any edit resets.

Details

🎉 Features

  • Baseline resolution and path selection (Phase 1). The baseline is the first candidate carrying substantive claims: the repo-root AGENTS.md, else .agents/PROJECT.md, else .agents/AGENTS.md. A baseline takes the refresh path; no baseline takes the authoring path. Where both legacy files carry content, .agents/PROJECT.md is the baseline as the later convention and the other joins the gap-scan sources, so its content reaches the change list rather than being archived unread. The baseline resolves in memory, leaving the write gate as the only point the skill writes anything.
  • Two constraints on the repo-root file (Phase 3), governing both paths. No path into a harness-owned directory, home-anchored or repository-local, since one body of text serves every harness; and no <!-- rulebook: marker, because sync strips a complete region from that file and an unpaired marker escapes the sweep instead.
  • The refresh path (3c). A constraint pre-pass makes every violation a repair whatever the audit says about it. A two-tier audit follows: tier 1 sweeps every checkable token exhaustively, tier 2 the narrative prose in sections the gap-scan window touched. Verdicts are holds (requiring the command run or the path:line read as evidence), drifted (stating what is true now), and unchecked (stating why), and the ledger closes by naming what it did not audit.
  • A bounded gap scan. The window reaches back to whichever is earlier: the last commit touching AGENTS.md, or twenty commits. Twenty is a floor, never a ceiling, so a drive-by edit to the file cannot shrink it. git status --porcelain joins it for the mid-session case, every git log names its own --format against a configured format.pretty, and a repository without history states its bound as whole-repo additions. One unbounded check against the skeleton asks whether an ambient category is missing altogether.
  • Change-list vocabulary and placement. Anything the list does not name is carried through byte-identical. An addition lands in its matching skeleton section, a new section needs the user's agreement, a removal or relocation names its destination as a recommendation, and a relocation behind a pointer is the sanctioned response to an overrun of the line budget. A worked example carries a four-row ledger and the change list it produced.
  • A closing checklist step (3g). Both paths end by running the published guidance checklist with rdy run --packages from the repository root, skipped where rdy is absent or no configured package publishes the kit, and never reported as a pass it did not produce. The freshness check's outcome is pre-declared: it reads committed history, so it still reports stale on an uncommitted refresh and its advice to re-run the skill is not to be acted on.
  • Two checks in the guidance kit. AGENTS.md is harness-neutral and AGENTS.md hosts no rulebook region, both at recommend severity beside the existing content-quality checks, each skipping when the file is absent and reporting every offending line by number. Detection lives in guidance-constraints.ts as pure string transforms, matching the lib/ shape of guidance-import, guidance-size, and guidance-staleness.

🧪 Tests

  • 16 unit tests over the three detection helpers in guidance-constraints.unit.test.ts: both harness-path spellings, a harness other than Claude, 1-based line numbers across a multi-line body, the .agents/ and .config/ near-misses that must not fire, an opening marker, a closing marker, an unpaired opener, irregular marker spacing, and a comment that merely mentions rulebooks.
  • One test pins the detection pattern to the canonical HARNESSES table: a harness added there fails the suite until the pattern covers its home directory in both spellings. The pattern restates those two directory names so the compiled kit carries string literals rather than the table's filesystem imports, and the pin is what keeps that duplication from going stale unnoticed.

Closes #1280

Running `update-project-guidance` against a repository that already has an `AGENTS.md` now reconciles with the file rather than drafting a replacement, so a dense section survives the pass instead of being summarized away.

The refresh audits the claims the file makes against the codebase and reports a verdict for each, catching a directory listing that has gained an entry or a count that has drifted rather than reproducing it. Claims it could not check are named as unchecked rather than dropped.
`update-project-guidance` now rejects a path scoped to one harness's home, and any rulebook marker, in the repository-root `AGENTS.md`. Both the authoring and the refresh path enforce this, and a refresh repairs an existing violation rather than carrying it through.
`update-project-guidance` now finishes by running the published `guidance` checklist against the file it produced, so wiring, size, and freshness are reported in the same pass that wrote the content. Where the checklist is not installed, the step is reported as skipped rather than as a pass.

A freshness failure straight after a refresh is expected and clears on commit, and the skill says so instead of acting on the checklist's advice to re-run itself.
The published `guidance` checklist now reports a path scoped to one harness's home, and a rulebook marker, in a repository's root `AGENTS.md`, naming the line to fix. Every repository running the checklist gets the two constraints enforced, not only the one being refreshed at the time.

An unpaired marker is reported too. `codeassembly sync` removes only a complete open/close pair, so a lone marker would otherwise survive every run.
A refresh's search for missing content now reaches back twenty commits even when `AGENTS.md` was touched more recently, so a drive-by edit no longer shrinks the window to the handful of commits behind it. The rule had been stated as the later of the two boundaries, which selected the narrower window and permitted the collapse it was meant to prevent.

A stub at the repository root no longer shadows a mature legacy guidance file: the baseline is chosen by which candidate carries substantive claims, so a repository mid-migration refreshes its real content instead of redrafting it. Where both legacy filenames carry content, the later convention becomes the baseline and the other is scanned for gaps rather than archived unread.

The harness-path rule now reads as it is enforced, covering a repository-local harness directory as well as a home-anchored one, and its remediation names a remedy that fits: state the fact without the harness path, or record it in that harness's own guidance file.
A harness added to the configuration table now fails the suite until the guidance check's detection pattern covers its home directory, in both the home-anchored and the repository-local spelling. The pattern restates those directory names so the compiled checklist carries two string literals rather than the table's filesystem imports, and this is what keeps that duplication from going stale unnoticed.
@williamthorsen williamthorsen added feature Added or improved external functionality scope:agents labels Aug 11, 2026
@github-actions

Copy link
Copy Markdown

Dependency audit

Production dependency audit passed.

@williamthorsen williamthorsen self-assigned this Aug 11, 2026
@williamthorsen
williamthorsen marked this pull request as ready for review August 11, 2026 09:32
@williamthorsen
williamthorsen merged commit bb47e02 into main Aug 11, 2026
3 checks passed
@williamthorsen
williamthorsen deleted the 1280 branch August 11, 2026 09:51
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

feature Added or improved external functionality scope:agents

Projects

None yet

Development

Successfully merging this pull request may close these issues.

update-project-guidance cannot refresh an existing AGENTS.md without redrafting it

1 participant