feat(spec): register the 13 orphan dogfood proofs — five advance the ADR-0054 ratchet, eight say why they can't - #3868
Merged
Conversation
…ratchet, eight say why they can't
The gate flagged 13 `@proof:` tags no class in proof-registry.mts claimed.
Silencing that is trivial and worthless; the useful question is the one ADR-0054
§3 asks: is there an authorable property whose `live` status this proof gates?
FIVE HAVE ONE — bound, taking the ratchet from 10 bound paths to 17:
attachments-permission-matrix -> object.enable.files
the #2727 opt-in gate in BOTH directions: the fixture carries a deliberate
non-declaring object (att_nofiles) that must be refused 403 FILES_DISABLED
showcase-d3-d4-capabilities -> permission.rowLevelSecurity.check
authors check:'owner == current_user.email', proves POST-image validation
(distinct from `using`, which filters the pre-image)
showcase-scope-depth -> permission.objects.readScope
authors unit / unit_and_below, proves the owner-match widens, cross-BU
stays isolated
owner-anchor-and-bulk-writes -> permission.objects.modifyAllRecords
member denied the transfer, privileged caller allowed
semantic-roles-served -> object.highlightFields/.stageField/.fieldGroups
all three survive defineStack -> artifact -> registry -> REST verbatim
EIGHT DO NOT — registered with an honest blockedReason, the shape the registry
already used for permission-set-projection: two guard properties already bound to
a sibling proof (one entry carries one `proof` ref); one needs the `app` type to
be governed; two are runtime principal-resolution invariants; two act on
stack-level roles/sharingRules; one is a breadth guard over all of ADR-0090.
One deliberate non-binding worth naming: owner-anchor-and-bulk-writes binds
modifyAllRecords, NOT the sibling allowTransfer — the proof only mentions
allowTransfer in a comment and never authors it. Binding a property a proof does
not exercise is the same false comfort as a preview renderer standing in for a
runtime consumer, which is what #3686 spent its length unwinding.
Verified the bound proofs run: the only skipIf among them covers the attachments
enterprise cross-tenant block, not the FILES_DISABLED assertion.
The gate now runs with ZERO warnings — the orphan list joins the stale-evidence
list at empty, so both mean something again. The README ratchet table was itself
stale (5 listed, 10 bound); now complete, with the unbound set and its reasons.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ajwvrmd1hDC9RBofYBhGuR
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
July 28, 2026 13:16
os-zhuang
added a commit
that referenced
this pull request
Jul 28, 2026
…just skills/ (#3882) check:skill-examples compiles the TypeScript in prose against the built spec, so an example that stops compiling fails CI instead of quietly teaching code that no longer works. It does its job — it caught the broken defineTool example in #3876. But it only ever walked skills/: skills/ 9 files with ts blocks, 9 compiled content/docs/ 124 files with ts blocks, 0 compiled The identical break in a docs page ships. Docs examples are copied verbatim by humans and AI exactly like skill examples — the same shape as the stale-evidence and orphan-proof warnings fixed in #3857 / #3868: a gate covering a fraction of the surface it appears to cover reads as coverage. The walker is now a SOURCE_ROOTS list, and this lands the first batch: 164 docs blocks across 63 pages, taking the gate from 32 to 196 checked examples. content/docs/references/ is excluded — build-docs.ts regenerates it from the schemas, so it cannot drift independently. THE MARKER IS NOW PER-FORMAT. MDX has no HTML comments: `<!-- os:check -->` in a .mdx does not degrade, it fails the fumadocs build outright ("Unexpected character `!`… to create a comment in MDX, use `{/* text */}`"). Found by building the docs site after the first attempt broke 60+ pages; nothing in the type-check gate would have said so, because block extraction is regex-level and never parses MDX. skills/**/*.md keeps `<!-- os:check -->`; content/docs/**/*.mdx uses `{/* os:check */}`. Both spellings are recognised for ORPHAN detection, so a wrong-format marker fails loudly instead of silently checking nothing. The batch was measured, not guessed: marking all 780 docs blocks and compiling showed which are self-contained. One subtlety — a block that "passes" inside a 780-file program can be leaning on globals declared by OTHER blocks (a file with no import/export is a global script), so the first pass's 564 "passing" blocks collapsed to 164 once compiled as the real, smaller set. Converged by recompiling and dropping newly-failing blocks until green. The remaining blocks are mostly fragments, which the opt-in design anticipates. Whether any are genuine rot is now answerable for the first time.
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 free
to 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.
Follow-up to #3857 — the gate's second permanently-non-empty warning.
The gate flagged 13
@proof:tags underpackages/qa/dogfood/test/**that no class inproof-registry.mtsclaimed. Silencing that is trivial and worthless. The useful question is the one ADR-0054 §3 actually asks: is there an authorable property whoselivestatus this proof gates? I re-read all 13 against it.Five had one — bound (ratchet: 10 → 17 bound paths)
A
liveclassification on these entries now requires its proof.attachments-permission-matrixobject.enable.filesatt_nofiles) that must be refused403 FILES_DISABLEDshowcase-d3-d4-capabilitiespermission.rowLevelSecurity.checkcheck: 'owner == current_user.email'and proves the write post-image is validated — distinct fromusing, which filters the pre-imageshowcase-scope-depthpermission.objects.readScopeunit/unit_and_belowprofiles, proves the owner-match widens and cross-BU stays isolatedowner-anchor-and-bulk-writespermission.objects.modifyAllRecordssemantic-roles-servedobject.highlightFields,.stageField,.fieldGroupsdefineStack → artifact → registry → RESTverbatim (incl.stageField: falseas a strictfalse, not dropped)Three of those five gate access-widening or capability properties —
readScope,modifyAllRecords,enable.files— where "declared but not applied" fails in the safe-looking direction and so goes unnoticed longest.Eight did not — registered with an honest reason
Same shape the registry already used for
permission-set-projection:flow-runas-schedule,showcase-scope-depth-fallback— guardflow.runAsandpermission.objects.readScope, both already bound to a sibling proof. A ledger entry carries oneproofref, so a second gate on the same property isn't representable; they run unconditionally instead.me-apps-and-everyone-baseline— enforcesapp.requiredPermissions/app.tabPermissions;appisn't a governed type yet (it's on the rollout list). Bind when it lands.showcase-agent-intersection,showcase-agent-scope-ceiling— runtime principal-resolution invariants (onBehalfOfreconstruction, OAuth scope → ceiling set), not authorable metadata.showcase-bu-hierarchy-sharing,showcase-declarative-rbac-seeding— act on stack-levelroles/sharingRules, not a per-type property surface.showcase-permission-zoo— a breadth guard over the whole ADR-0090 surface; binding it to any one entry would misrepresent both what it covers and what that entry is proven by.One deliberate non-binding worth naming
owner-anchor-and-bulk-writesbindsmodifyAllRecords, not the siblingallowTransfer. The proof only mentionsallowTransferin a header comment — it never authors it, and exercisesmodifyAllRecords ⇒ transferinstead. Binding a property a proof doesn't exercise is the same false comfort as a preview renderer standing in for a runtime consumer, which is the error #3686 spent its length unwinding. The temptation was real:allowTransferis the more obvious match by name.Verification
skipIfamong the five coversattachments-permission-matrix's enterprise cross-tenant block; theFILES_DISABLEDassertion the binding rests on runs unconditionally.pnpm --filter @objectstack/spec check:liveness— exits 0, and now prints zero warnings: the orphan list joins the stale-evidence list at empty, so both mean something again.pnpm --filter @objectstack/spec test— 262 files, 6821 tests passed.proof-registry.test.ts's bound-path contract test failed first (it pins the exact list — the ratchet working as designed) and was updated with the 7 new paths.Also: the README's ratchet table was itself stale — 5 classes listed against 10 actually bound. Now complete, with the unbound set and its reasons alongside.
Generated by Claude Code