Uh oh!
There was an error while loading. Please reload this page.
fix(qa-checklist): resolve provisioning.use against its own area's recipes (#10593 gap 1) - #10810
Merged
Merged
Conversation
… recipes `docs/qa/platform-checklist/README.md` recorded option C from #7716 as deliberately deferred (tracked at #7720, which landed only the documentation half), "to be revisited if the recipe shape spreads to more areas". It has: recipes now live in three area files and six items carry a `provisioning.use`. Until now a `use` naming a key its area does not define validated clean — measured on 112a8c6, a typo'd `qa-media-constraint` and a cross-area `qa-contributor-bound-member` each exited 0 with the untouched OK line. An item that reads as provisioned and is not costs the run the clauses the recipe was meant to unblock, mid-run and on a live boot. The resolve mirrors the existing `supersededBy` check — same `err(file, id, …)` reporting, same "points at unknown" wording — and reuses the trap checker's did-you-mean, since a typo of a real recipe is the drift shape review is worst at. It carries its own inline positive-control battery (14 assertions) for the reason the trap battery does: this gate is not CI-wired, so a check that quietly stopped firing would restore exactly the green it replaced. Scope is gap 1 of #10593 only. Cross-area reuse still has no spelling, so the resolve is same-area only and the unreferenced-recipe direction is deliberately NOT checked — redding it would settle that convention question by accident. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
os-zhuang
marked this pull request as ready for review
August 21, 2026 13:18
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.
Part of #10593 — gap 1 only.⚠️ Deliberately NOT a closing keyword: gap 2 (cross-area recipe reuse) is still open on that card, and
Fixeswould close it on merge regardless of this sentence. Gap 2 (cross-area recipe reuse) is untouched and is left open on purpose; the reasoning and a proposed shape are at the bottom.The defect
docs/qa/platform-checklist/README.mdrecorded option C from #7716 as deliberately deferred (tracked at #7720, which landed only the documentation half):That condition is met: recipes live in three area files and six items carry a
provisioning.use.Reproduced on
origin/mainat112a8c6731, before touching the validator. Two shapes, injected one at a time into an otherwise clean tree:"use": "qa-media-constraint"(a typo ofqa-media-constraints,attachments-storage.json)exit 0—OK — 15 areas, 205 items (205 active); …, byte-identical to the untouched run"use": "qa-contributor-bound-member"onrecords-forms.crud-roundtrip(a real recipe key, owned by another area)exit 0— same OK lineNothing reported, either time. An item that reads as provisioned and is not costs the run the clauses the recipe was meant to unblock, and it discovers that mid-run, on a live boot.
What this PR does
scripts/check-platform-checklist.mjsnow resolves everyfixtures.provisioning.useagainst the recipe keys of its own area's area-levelfixturesblock. It mirrors thesupersededBycheck that already lives in the file — sameerr(file, item.id, …)reporting, same "points at unknown" wording — and reuses the trap checker's did-you-mean, because a typo of a real recipe is the drift shape review is worst at.$-prefixed keys ($comment) are annotations, not recipes.Same input, after:
The clean tree stays green, and the OK line now states what the new check ran on, so a green says something:
The README paragraph that documented the deferral is rewritten to document the check, both of its deliberate limits, and the cadence caveat below.
.github/workflows/lint.ymlstates it plainly, and this PR honours it rather than changing it:So adding this check does not make it run on pull requests. A typo'd
useis now caught at the next manual sweep — before a release, after a large platform surface lands — not on the PR that introduces it. That is a real narrowing of the win versus what "a green check" normally implies, and it is why the check carries its own inline positive-control battery: on a gate nobody runs per-PR, a check that quietly stopped firing would restore exactly the green it replaced, and no CI run would ever contradict it. CI-wiring it would reverse a recorded maintainer decision and is not on this card.Evidence
Everything below on
20d61f7e55(the tip of this branch).Census. Six
provisioning.usevalues across all 15 area files, every one resolving on the base — matching the count on the card:attachments-storage.jsonqa-scratch-authz,qa-media-constraintsautomation.jsonqa-flow-status-doorssearch.jsonqa-contributor-bound-memberThe gate's own OK line reports the same numbers independently:
4 area recipes, 6 item references resolved.records-forms.crud-roundtripclause 7 stays green, by running. The item has noprovisioningblock at all (#10236 cross-referenced the recipe by name inknownGapsinstead), so there is nothing for the resolve to dangle on:node scripts/check-platform-checklist.mjsexits 0 with all 205 items, the item included, andnode scripts/checklist-select.mjs records-forms.crud-roundtripstill selects it. The green is not vacuous — the second repro row above is that exact item, and it does red when a cross-areauseis added to it, which is what proves the check visits it.Ablation. Mutated
provisioningProblems()to return[]immediately, confirmed on disk by anchor count (old anchor 1 to 0, marker 0 to 1,grep -c= 1 at line 269), not by an editor exit code. There is no rebuild leg here: the gate runsnode scripts/check-platform-checklist.mjsagainst the source file itself, so nodist/can hold a stale copy.areaRecipeKeysonly) stay green. And the gate refusing on the real tree rather than going quietly green.--self-testexit 1,10 failure(s), the named set U4-U13. The full gate exit 1 withthe provisioning-resolve check's own positive control FAILED — a "use" that resolves to nothing would pass, which is the exact defect this check was added to close.git checkout --: marker absent (grep -c= 0),sha256identical to the pre-mutation file (39d95f98…6e746e), tree clean, gate green again.Gates. Derived with
node scripts/pm/dispatch-gates.mjs(no paths passed — it takes the change set from the merge base itself), re-run on the final commit. Every exit code captured withcmd > file 2>&1; ec=$?, never through a pipe:pnpm check:cross-package-test-inputs(andnode scripts/check-cross-package-test-inputs.mjs,--self-test)pnpm check:doc-authoring(+--self-test)pnpm --filter @objectstack/lint run check:doc-formula-expressions(+--self-test)pnpm check:entry-guard(+--self-test) — by hand, dispatch-gates cannot reachscripts/**gatespnpm check:parse-guard(+--self-test) — likewise; dispatch-gates prints it as unreachable by constructionpnpm check:nul-bytes(+--self-test)pnpm check:platform-checklist(the alias this PR changes, both halves)eslint scripts/check-platform-checklist.mjsWhat is deliberately left open — gap 2
Cross-area reuse still has no spelling.
records-forms.crud-roundtripclause 7 needs the personaqa-contributor-bound-memberprovisions; that recipe lives inareas/search.json;usenames a key in the item's own area — so the item cannot reference it, and #10236 handled it by naming the recipe inknownGapsprose with an explicit instruction not to fork a copy.This PR does not decide that, and is built so it cannot decide it by accident. Two things the resolve deliberately does not do:
usepointing at another area's recipe key fails, and the message says why rather than pretending the reference works.Open question for triage — the three candidate answers, and what this PR learned about them. The card lists a qualified
use(search:qa-contributor-bound-member), a sharedareas/_fixtures.json, or ruling that recipes stay area-local with a pinned back-reference.Doing gap 1 sharpened the choice in one respect worth recording: the resolve's universe is now a per-area key set, computed per file. A qualified
useneeds only that universe widened to a two-level lookup and would keep every existing spelling valid — the smallest diff of the three, and the only one that makes the existing cross-area pointer machine-checkable where it already sits. A shared_fixtures.jsonmoves recipes away from the area that proved them, which is where theprovenancefield points and where a runner looks. The area-local ruling is the cheapest to write and the only one that leaves the prose pointer permanently unverifiable — the drift the card was filed about. My recommendation is the qualifieduse, but it is a convention decision and belongs to the maintainer, so it is stated here rather than implemented. Two references would use it today.Also not in this PR
Filed as #10809: the same two cross-area pointers carry
knownGapsprose asserting the validator does not resolveuse"either way" — true when written, inverted by this change, and now reading as permission to write the one spelling the gate rejects. Correcting it is a semantic edit to two items, so it needs arevisionbump and ahistoryentry each, which is not a rider on a gate PR; it also wants to be written once, after gap 2 lands.No changeset: this changes gate tooling and a QA ledger README, and publishes nothing.
Generated by Claude Code
Generated by Claude Code