Uh oh!
There was an error while loading. Please reload this page.
docs(agents): ablation requires rebuilding the ablated package — hard step + dist marker pre-flight - #8365
Merged
Conversation
… step + dist marker pre-flight packages/qa/dogfood resolves the code under test from each package's built dist/, deliberately — that is what covers packaging and export-surface defects. The two directions of forgetting to rebuild are not symmetric: an unbuilt fix is a false red that costs a lap and gets noticed, while an unbuilt ablation runs the pre-mutation build and stays GREEN, certifying an assertion that may never be able to fail. No later CI run can expose that, because CI builds correctly and the test is green there forever. - .claude/agents/os-dev.md: a standard clause making the rebuild a hard step of every ablation leg (mutate -> build -> prove -> run) and requiring the report to state the rebuild; the report template's tests field says so at the point the report is written. - .claude/skills/dogfood-verification/SKILL.md: the same hard step in the build/runtime-model section, naming the same command, so the two copies of the procedure stay structurally consistent. - scripts/ablation-dist-preflight.mjs: the pre-flight itself, mechanizing the manual dist grep that caught this by hand. Takes a package and a marker; exits non-zero unless the consumed dist/ really carries the mutation. Two modes for the two ablation shapes — default (a planted token must be PRESENT) and --absent (a deleted guard's literal must be GONE, which is also the restore leg). Sourcemap-only hits are RED, not green: a .map hit proves a sourcemap was regenerated, not that the executable artifact carries the mutation. Missing dist/, an unreadable dist/ and an unresolvable package name all fail by name — a pre-flight that shrugs is worse than none, because its exit 0 is read as proof. Self-test covers all ten verdict branches plus a real temp-dir scan of the sourcemap-only trap. Direction 2 of the source finding (resolving dogfood from src) is out of scope: dogfood tests the built artifact on purpose, so changing that is a semantic trade needing its own ruling. Claude-Session: https://claude.ai/code/session_01139NJ9Wg5pFeZi1Zh8WLg6 Co-authored-by: Claude <noreply@anthropic.com>
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
hotlong
commented
Aug 13, 2026
ContributorAuthor
PM review: ACCEPT — skills seat (#7623), session
Merge path: ADR-class surface — stays draft, the maintainer merges by hand. CI on the PR should be allowed to finish before merging. Generated by Claude Code |
This was referenced Aug 13, 2026
This was referenced Aug 13, 2026
hotlong
marked this pull request as ready for review
August 13, 2026 12:47
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Fixes#8246
packages/qa/dogfoodresolves the code under test from each package's builtdist/, deliberately — that is what covers packaging and export-surface defects. The two directions of forgetting to rebuild are not symmetric:The second one is the card. An ablation's whole purpose is to show the test goes red when the defect is present; run against the pre-mutation build it stays green, that green is written down as "ablation done, direction as predicted", and an assertion that may never be able to fail is left in the repo as a guard. No later CI run can expose it — CI builds correctly, so the test is green there forever. Three independent sessions hit this in one shift on three different packages (#8095 plugin-security, #8233 packages/rest, #8144 plugin-auth); the one that caught it did so by hand-grepping
dist/for the mutation marker.Scope is exactly as graded on the card: directions 1 + 3. Direction 2 (resolving dogfood from
src) is deliberately not addressed here — dogfood tests the built artifact on purpose, and changing that is a semantic trade needing its own decision card.What lands
1.
.claude/agents/os-dev.md— the hard step (direction 1). One standard clause, at the altitude of its neighbours, next to the other reverse-verification clauses: every ablation leg is mutate →pnpm --filter PKG build→ prove the mutation reached the artifact → run, and the report must state the rebuild happened. The report template'stestsfield says the same thing at the moment the report is written, so the requirement is visible where it is discharged, not only where it is read.2.
.claude/skills/dogfood-verification/SKILL.md— the same step in the skill. Its §2 already told the reader that packages load fromdistand must be rebuilt; what was missing is the asymmetry and the ablation-specific hard step. Added as one checkbox naming the same command, so the two copies of the procedure stay structurally consistent.3.
scripts/ablation-dist-preflight.mjs— the pre-flight (direction 3). The manualdistgrep, mechanized. Internal agent tooling inscripts/(whereos-dev.mdalready cites its tooling), not underpackages/qa— a landing next to the suite would re-route this card to another lane, per the grading note. Not wired as acheck:*gate either, and the header says why: it judges a deliberately mutated working tree at one specific moment between "mutate" and "run", which CI never has.Two modes for the two real ablation shapes:
dist/;--absent— the ablation deleted a guard, so there is nothing to plant and the assertion inverts: a literal unique to the deleted code must be GONE. This is also the restore leg, which matters more than it looks — a marker left behind indist/keeps mutated code live for every later suite run in that worktree.Design points worth reviewing:
.mapproves a sourcemap was regenerated, not that the executable artifact carries the mutation. Counting it would rebuild the exact false green this script exists to prevent, so.maphits are reported and excluded from the verdict.dist/, adist/with nothing readable in it, an unresolvable package name, a blank marker. A pre-flight that shrugs is worse than none, because its exit 0 is read as proof.pnpm --filter PKG build).Demonstration — both directions, real output
(a) marker never planted → non-zero (the pre-flight run before any mutation exists):
(b) the actual incident shape —
srcmutated,distnot rebuilt → non-zero.packages/formula/src/cel-engine.tshad its'empty expression'message mutated to carryOS_ABLATION_MARKER_8246, with no rebuild. This is the run that would otherwise have gone green on a vacuous test:(c) same mutation, after
pnpm --filter @objectstack/formula build→ zero, and the sourcemap hits are shown but not counted:(d)
--absenton the same tree → non-zero, then the restore leg:git restore packages/formula/src/cel-engine.ts+ rebuild → zero.The demo mutation was restored with
git restoreand the package rebuilt;dist/is gitignored, and the diff in this PR is the three files listed above and nothing else.Self-test (
node scripts/ablation-dist-preflight.mjs --self-test) — all ten verdict branches plus a real temp-dir scan that pins the sourcemap-only trap:Gates (all green locally)
pnpm check:agent-model-declaredos-dev.md → opus, 0 inheritspnpm check:doc-authoringpnpm --filter @objectstack/lint run check:doc-formula-expressionspnpm check:nul-bytespnpm check:pm-skill-id-lintos-dev.mdclause carries no issue IDspnpm check:pm-skill-ratchetpnpm check:skill-frame-syncnode scripts/check-skill-frame-freshness.mjsRe-derived after the fact against the actual changed paths —
node scripts/pm/dispatch-gates.mjs .claude/agents/os-dev.md .claude/skills/dogfood-verification/SKILL.md scripts/ablation-dist-preflight.mjsreturns exactly those eight, no additions. Alsonpx eslint scripts/ablation-dist-preflight.mjs --no-inline-config→ clean, and a control-byte self-scan over the three changed files → no hits.Merge path
ADR-class surface (
.claude/agent definition + skills root): stays draft, no auto-merge, no merge queue, no ready-flip — the maintainer merges by hand.skip-changeset: nothing user-visible ships. All three files are internal agent tooling — an agent definition, an internal skill (internal: true, never published vianpx skills add), and a dev-side script that is not wired into any published package or CI gate. No published package changes, so there is nothing to release.Generated by Claude Code