chore: mirror every Claude skill into .agents and guard the parity - #1373
Conversation
|
Design decision: the parity test reads the index blob, not The planned prototype resolved each symlink target with The first is that The second is consistency. The test derives its whole set from Worth flagging that One deviation from the planned text. The plan said to keep the |
vivek7405
left a comment
There was a problem hiding this comment.
Went looking for whatever the new ## Enforcement gates section gets wrong, since it is the one substantive claim this PR adds and the whole reason the hooks mirror was rejected. It turned out to be the weakest part of the change: it is the only sentence in the file a non-Claude agent would read to decide what actually blocks a merge, and it named the wrong checks.
The symlink half is solid. Ten mirrors, every target relative and self-naming, the teaching directory still a real 15-file directory, and the new test covers both drift directions rather than just the missing-symlink one that prompted the issue. Reading the sets from git ls-files instead of the filesystem is the right call, since it makes the machine-local omarchy link invisible by construction rather than by a special case that would rot.
What I would keep an eye on is that this file is now what a non-Claude agent trusts about enforcement, and nothing tests its factual claims the way the new test covers its skill list. Four problems inline, all in that one file. Line anchors are on the current head, so they point at the corrected text; each thread carries what the line said when I flagged it.
vivek7405
left a comment
There was a problem hiding this comment.
Delta pass over the fix commit, since correcting a facts section is exactly where a new wrong fact gets introduced. It had: the rewritten self-check paragraph reverse-engineered each hook's trigger condition and got two of them backwards.
The rest of that commit holds up. I re-derived the five required contexts against live branch protection and the hook inventory against the settings file, and both are byte-accurate now.
The lesson I am taking from two rounds on the same paragraph is that restating a derived trigger in a second place is the defect generator here, not any particular wording of it. So the fix stops paraphrasing the regexes and states the workflow requirement, pointing at root AGENTS.md for the conditions. That file is the thing that moves when a gate changes, and this one no longer claims to track it.
|
Deferred items closed in the PR rather than filed as follow-ups Three things were flagged during this work and pushed out. None of them is a follow-up issue now, they are all fixed here.
Root Three blog posts described the per-agent rule files and per-agent hook copies that the same change removed, listing The What I did not do, and why. The issue's Out of scope also rejected |
Three skills had no .agents/skills symlink and a fourth was symlinked but undocumented, so Antigravity saw a different skill set from Claude Code. Move the workspace rules to the path Antigravity actually reads, list all ten skills there, and add a repo-health test so the sets cannot drift again.
The new Enforcement gates section named the wrong CI checks as the merge gate, listed four of the seven tool-call hooks a non-Claude agent has to self-check, and described the hook directory as PreToolUse only. It also stated the worktree rule unconditionally while an older section above it still called it conditional, so the file said it two ways.
The self-check paragraph reverse-engineered each hook's trigger and got two wrong: staging packages/cli/lib satisfies the scaffold gate rather than tripping it, and the Bun gate needs a runtime-sensitive filename on top of the path. Two of the three "any edit" gates were scoped wrong too. State the workflow requirement and point at AGENTS.md, since restating a derived trigger in a second place is what rotted here twice.
Three things were flagged and pushed out rather than fixed. All are in scope now. no-committed-symlinks enumerated the index but resolved targets from HEAD, so a staged symlink threw a raw fatal instead of being judged, leaving the guard blind exactly when someone adds one. It reads the blob by oid now, matching the new parity test. Root AGENTS.md still advertised GEMINI.md and copilot-instructions.md as bridges the scaffold ships; both were removed in #1368, so CLAUDE.md is the only one left. Three blog posts still described the per-agent rule and hook files that same change deleted. Corrected, including the ai-first post's own open question, which this consolidation answered.
8aaecd2 to
59588bc
Compare
Closes #1372
Summary
Three committed Claude skills (
webjs-ready-for-dev,webjs-scaffold-sync,webjs-instagram-post) had no.agents/skillssymlink, so Antigravity loaded a different skill set from Claude Code. A fourth,webjs-blog-write, was symlinked but missing from the documented list, so the symlink set and the documented set had drifted apart independently. Nothing asserted the three sets agree, which is why the gap kept reopening.This adds the three missing relative symlinks, moves the workspace rules file to the path Antigravity actually reads, documents all ten skills there, and adds a repo-health test so the sets cannot drift again.
What changed
.agents/skills/, each storing the relative target../../.claude/skills/<name>, created withln -sso git records mode120000.git ls-files -s .agents/skillsnow shows exactly ten..agents/AGENTS.mdmoved to.agents/rules/workflow.md(git records a rename). Nothing documents reading.agents/AGENTS.md; Antigravity's rules reference names.agents/rules/, which is the path rootAGENTS.md:36already advertises and the filename the scaffold already ships. A grep found zero references to the old path from any test, script, workflow, or doc, so the move breaks nothing. The file is retitled, its provenance sentence corrected, its skill list grown from six entries to ten, and it gains an## Enforcement gatessection.test/repo-health/agent-skill-parity.test.mjs, six assertions covering both drift directions plus the two tracked exceptions.framework-dev.mddocuments the canonical-plus-mirror layout, theln -smode requirement, the two non-mirror entries, and why hooks stay Claude-only.Review
Two rounds. Round 1 found four wrong facts in the new
## Enforcement gatessection: it named the wrong CI checks as the merge gate, listed four of the seven tool-call hooks, described the hook directory asPreToolUseonly, and stated the worktree rule unconditionally while an older section above it still called it conditional. The delta round then found two more in the paragraph that fix rewrote, both from paraphrasing hook trigger regexes: stagingpackages/cli/libsatisfies the scaffold gate rather than tripping it, and two of the three gates called "any edit" are scoped much narrower than that.Both rounds landed on the same paragraph, which is the useful signal. Restating a derived trigger condition in a second file is the defect generator, so the final version states the workflow requirement and points at root
AGENTS.mdfor the conditions, rather than tracking regexes it cannot keep in sync. Every fact that survives was re-derived from live branch protection and.claude/settings.json.Deferred items, closed here
Nothing from this work is left as a follow-up. Three things flagged along the way are fixed in this PR:
test/repo-health/no-committed-symlinks.test.mjsenumerated tracked links from the index but resolved targets fromHEAD, so a STAGED symlink threw a rawfatal:instead of being judged, leaving the guard blind exactly when a link is being added. It reads the blob by oid now. Proven by staging an absolute symlink and watching it get reported rather than crash.AGENTS.mdstill advertisedGEMINI.mdand.github/copilot-instructions.mdas bridges the scaffold ships. Both were removed in feat(cli): remove redundant per-agent instruction files from webjs create templates #1368, soCLAUDE.mdis the only one left.blog/ai-first-is-plumbing.md,blog/stop-ai-agents-breaking-your-code.md, andblog/why-webjs.mddescribed the per-agent rule and hook files that same change deleted. Corrected, including the first post's own closing question, which this consolidation answered.Deliberately excluded
.agents/hooks.jsonand ascripts/sync-hooks.jsgenerator, both rejected on the merits in the issue. These are settled decisions rather than deferred findings, so building either would reverse a deliberate call, not close a gap. The two engines disagree on the blocking protocol, the context-injection shape, and the tool vocabulary, so a mirror is a protocol port rather than a config copy, and a committed generated copy would be the duplicated rule set rootAGENTS.mdrules out. Nothing under.claude/hooks/is touched. The underlying need is covered instead by the new## Enforcement gatessection, which names the two layers that already bind every agent regardless of engine.Test plan
node --test test/repo-health/agent-skill-parity.test.mjspasses, 6/6.every committed .claude skill is mirrorednamingwebjs-scaffold-sync, and reds the documented-set assertion from the other direction.## Custom Skills Usageredssymlinked but not listednamingwebjs-blog-write.test/repo-health/no-committed-symlinks.test.mjsandtest/hooks/route-skills.test.mjsstill pass, 26/26 together with the new file.5dba1e2cafter the doc rewrites, since those edits touched the very file the documented-set assertion reads. Still discriminating.npm test: 4277/4283 pass. The five failures are the known linked-worktree baseline (the twotest/bun/listener*files and threedifferential-elisionassertions); all five pass onmainin the primary checkout, and this branch touches no runtime code, so they are environmental.Browser, e2e, smoke, and Bun parity are N/A: this touches no framework runtime code, nothing under
packages/*/srcorpackages/cli/libis staged, and no served byte differs. Docs surfaces:.agents/rules/workflow.mdandframework-dev.mdupdated. RootAGENTS.md, the docs site, the marketing website,README.md,CONVENTIONS.md, and the scaffold templates need no change, since none describes this repo's internal agent-config mirror andwebjs createoutput is byte-identical.