Uh oh!
There was an error while loading. Please reload this page.
chore(spec): register the eleven unregistered dogfood proof tags, and propose their ledger bindings - #10934
Conversation
…roof-registry.mts check:liveness warned on 11 `@proof:` tags present in packages/qa/dogfood/test but absent from the ADR-0054 proof registry. A proof tag on disk but not in the registry is a proof no ledger entry can cite, and the drift accumulates one warning line at a time without anything going red. Each of the eleven files was re-read to ask whether an authorable property's `live` status it actually gates exists. None is bound here: three have a fitting ledger entry and are proposed for binding in the PR body (adoption is a ledger edit and therefore a review decision), and the other eight record which surface they guard instead of faking a binding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4h3medzvhB9rpfoja9jcw
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
os-elon
commented
Aug 21, 2026
Review: ACCEPT (reviewer of record: PM seat domain:spec, session_01B4h3medzvhB9rpfoja9jcw) Verified against GitHub, not the report:
Adjudication of the two open questions (my call as reviewer of record — recorded here, executed by a follow-up card since every one of them is a ledger edit and therefore outside this PR's surface):
Landing: in the merge queue. On merge: drop Generated by Claude Code |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 32537776134 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Fixes#10773
Registers the eleven dogfood
@proof:tags thatcheck:livenessreported asunregistered, and proposes — without adopting — the ledger bindings three of them
could carry. Per the triage ruling (13:11Z) the registration is the mechanical half
and the binding decision is the spec seat's review, so no liveness-ledger entry is
edited in this PR.
Premise re-verified on today's
main— no deltaThe card measured on base
dd8172ee2. Re-measured on a fresh worktree offorigin/main@3d7deb7000: the same eleven tags, byte-identical list, noneregistered since and none new. Each tag's file was confirmed by grep before it was
registered — all eleven resolve to exactly one
packages/qa/dogfood/test/*.dogfood.test.tsfile, and the gate's own
validateProofRefre-checks thefile#idpair.Positive control — before / after
check:livenesspasses in both states (this is its warning channel, not afailure), so the readout is the warning line, not the exit code.
Before (
pnpm --filter @objectstack/spec check:livenesson the untouched worktree):After:
diffof the two full gate outputs shows one change: the thirteen-line warningblock is deleted. Nothing else moved — the bound-class list, the 364/364 evidence-path
resolution and the state-count check are identical, which is the check that this PR
registered proofs without silently binding any.
Reverse leg
Removing one entry (
fls-read-strip) from the committed registry and re-running:The mutation was confirmed on disk before the gate ran (the
id: 'fls-read-strip'anchor went 1 → 0 and
git diff --statshows the 24 deleted lines) — an editor'sexit code is not evidence a mutation landed. Restore ran from an
EXIT INT TERMtrapand is byte-identical (
git status --porcelainempty), and the gate is green againwith zero unregistered lines. No rebuild leg applies:
check:livenessrunstsx scripts/liveness/check-liveness.mts, which imports the registry from source —there is no
dist/between the edit and the measurement.The eleven entries
All are registered
bound: falsewith ablockedReason, the shape the file alreadyuses for a proof with no authorable property to gate.
admin-credential-lifecycleadmin-route-nonadmin-refusal/admin/route refuses a non-admin, over a route population derived from the live stack rather than hardcodedattachments-parent-rls-count-paritytotaltoo —totalcomes fromengine.count(), so a rows-only suite stays green with the count path unfilteredattachments-parent-rls-scan-capREAD_SCAN_LIMIT = 2000the truncated candidate set falls CLOSED (rows lost, never admitted unfiltered), and logsattachments-public-read-aclacl: 'public_read'reopens the anonymous capability URL — the OPEN side, which a denial-only suite cannot seeattachments-unscoped-delete-gateno-active-organization-write-refusalorg-scoped-sharing-rule-listingsharing-rule-org-less-callermanage_sharingholder with no active org does not get the SYSTEM read scope (#8158), measured over two organizationsshowcase-crud-persona-matrixshowcase-fls-read-mask-stripreadable: falsefield is STRIPPED (key absent), not masked and not nulledBinding proposals — for review, not adopted here
Three have a fitting ledger entry; eight have none. Every "no" names the surface the
proof actually guards rather than asserting the absence.
showcase-fls-read-mask-strippermission.fields.readable(live, no proof)readable: falseand asserts the runtime outcome both ways — key absence on the wire, entitled contrast on the same field/row/request. That is exactly the property whoselivestatus it gates. ⛔ Notfields.editablealongside it: the file authors that key but asserts its refusal as a consequence of unreadability, not as the write-deny axis (showcase-permission-zoopins that half) — binding it would repeat the owner-anchor/allowTransfermistake.showcase-crud-persona-matrixpermission.objects.allowCreate/allowRead/allowEdit/allowDelete(all live, none with a proof)semantic-rolesbinds three). Open question for the seat: four entries, or a chosen subset — a persona-breadth matrix anchoring four properties may claim more than one entry should cite.sharing-rule-org-less-callerpermission.systemPermissions(live, no proof)system_permissions: ['manage_sharing']and proves it is a real data-layer boundary. But that entry's note reads "PARTIAL — app-entry/nav visibility only, not a general capability gate", with evidence inhono-plugin.ts— narrower than what this proof measures (ADR-0111 D6 admits the capability at the sharing service). Re-verifying the note is part of the binding decision; binding it as it stands would cite an entry describing a different consumer.admin-credential-lifecycleisPlatformAdmin/positions[]). No authorable per-type property.admin-route-nonadmin-refusalpermission-model-zoo, which the registry already declines to bind for this reason.attachments-parent-rls-count-parityobject.enable.files→attachments-permission-matrix,permission.rowLevelSecurity.using→rls-by-id-write; one entry carries oneproofref.attachments-parent-rls-scan-capREAD_SCAN_LIMITis a service constant with no metadata key declaring it.attachments-public-read-aclaclis a column on thesys_attachmentRECORD — agrep -w acl packages/spec/liveness/*.jsonfinds no node anywhere.object.publicSharingis the share-link policy, a different mechanism this proof never authors.attachments-unscoped-delete-gateno-active-organization-write-refusaltenancySERVICE's ownposture/isolationActive; it never authors or variesobject.tenancy.enabled. Binding there would cite a proof for a property it does not exercise.org-scoped-sharing-rule-listingshowcase-bu-hierarchy-sharing/sharing-rule-criteria-required: rules are authored at STACK level (sharingRules), not a governed metadata type, and what this pins is a read-scope filter insideSharingRuleService.Changeset
None — re-derived rather than assumed.
packages/spec's publishedfilesset isdist,json-schema,liveness,prompts,llms.txt,README.md,src/**/*.zod.ts,CHANGELOG.md,api-surface,spec-changes.json. The onlychanged file is
packages/spec/scripts/liveness/proof-registry.mts, underscripts/,which is not in that set — and
livenessin the list is the ledger JSON directorypackages/spec/liveness/, untouched here. Nothing consumer-visible ships, so thiscarries the
skip-changesetlabel.Gates — derived at HEAD
23e27af370Union derived with
node scripts/pm/dispatch-gates.mjs(no hand-fed paths; it tookthe change set from the merge base itself — 1 path, committed). 12 families matched,
all run locally, exit codes captured to files before any pipe:
@objectstack/spec check:liveness@objectstack/spec check:empty-state@objectstack/spec check:strictness-ledger@objectstack/spec check:variant-docspnpm check:merge-driverpnpm check:slot-lookuppnpm check:test-source-aliaspnpm check:type-source-resolutionscripts/check-ci-filter-parity.mjsscripts/check-plugin-teardown-shape.mjsscripts/docs-audit/check-affected-docs.mjsscripts/check-dev-prereqs.mjs --self-test✓ every verdict reachable … (16 cases)scripts/check-nul-bytes.mjsPlus the affected package, through the shared verify lock:
pnpm --filter @objectstack/spec test—Test Files 415 passed (415)/Tests 11062 passed (11062); lockVERDICT command-exit 0 · held 435s. Package banner@objectstack/spec@17.1.0 testconfirms the filter matched (not a zero-match green).pnpm --filter @objectstack/spec typecheck— 0 across all three legs (tsc --noEmit,check:scripts-typecheckwhich is what compiles this.mts,check:test-typecheck); lockVERDICT command-exit 0 · held 67s.No dependency-closure build was needed:
packages/specdeclares no workspacedependencies (
pg-connection-string,zodonly).Declared narrowing, one item.
check:dev-prereqs's scan half reds on thisworktree — "67 of 67 workspace packages declare an entry point under
dist/that isnot on disk". That is an unbuilt-worktree precondition, not a finding: it is
independent of a diff that adds no package and touches one script file. It is also
not what CI runs —
lint.ymlinvokesnode scripts/check-dev-prereqs.mjs --self-testunder the step name "Self-test the dev-prereqs gate (self-test half only, never the
scan)", and its own comment states the step "vouches for the gate's verdict paths,
never for this workspace". The CI form is green above. Repo-wide
pnpm lintwas notrun locally — it is CI's run.
Generated by Claude Code