Skip to content

feat(spec): register the 13 orphan dogfood proofs — five advance the ADR-0054 ratchet, eight say why they can't - #3868

Merged
os-zhuang merged 1 commit into
mainfrom
claude/action-undoable-experimental-j8g24i
Jul 28, 2026
Merged

feat(spec): register the 13 orphan dogfood proofs — five advance the ADR-0054 ratchet, eight say why they can't#3868
os-zhuang merged 1 commit into
mainfrom
claude/action-undoable-experimental-j8g24i

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Follow-up to #3857 — the gate's second permanently-non-empty warning.

The gate flagged 13 @proof: tags under packages/qa/dogfood/test/** that no class in proof-registry.mts claimed. Silencing that is trivial and worthless. The useful question is the one ADR-0054 §3 actually asks: is there an authorable property whose live status this proof gates? I re-read all 13 against it.

Five had one — bound (ratchet: 10 → 17 bound paths)

A live classification on these entries now requires its proof.

Proof Now gates Why it qualifies
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' and proves the write post-image is validated — distinct from using, which filters the pre-image
showcase-scope-depth permission.objects.readScope authors unit / unit_and_below profiles, proves the owner-match widens and 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 (incl. stageField: false as a strict false, 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 — guard flow.runAs and permission.objects.readScope, both already bound to a sibling proof. A ledger entry carries one proof ref, so a second gate on the same property isn't representable; they run unconditionally instead.
  • me-apps-and-everyone-baseline — enforces app.requiredPermissions / app.tabPermissions; app isn'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 (onBehalfOf reconstruction, OAuth scope → ceiling set), not authorable metadata.
  • showcase-bu-hierarchy-sharing, showcase-declarative-rbac-seeding — act on stack-level roles/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-writes binds modifyAllRecords, not the sibling allowTransfer. The proof only mentions allowTransfer in a header comment — it never authors it, and exercises modifyAllRecords ⇒ transfer instead. 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: allowTransfer is the more obvious match by name.

Verification

  • Confirmed the bound proofs actually run — a bound-but-skipped proof would be precisely the false comfort this ratchet exists to prevent. The only skipIf among the five covers attachments-permission-matrix's enterprise cross-tenant block; the FILES_DISABLED assertion 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

…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
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 28, 2026 1:01pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 28, 2026 13:16
@os-zhuang
os-zhuang merged commit 5b79a34 into main Jul 28, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/action-undoable-experimental-j8g24i branch 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants