Repository navigation
fix(metadata-protocol): S5 carry-overs — per-term boot report isolation, one naming of a code-datasource row, seal TSDoc wordings, two changeset rows - #22833
Conversation
…boot report; correct three seal TSDoc wordings; complete the changeset's FROM → TO table - reportUnhydratableOrgScopedRows: the sys_metadata read and each of the three ledger counts is its own term. A term whose read fails for any reason but a missing table is printed NOT MEASURED with its reason; the other terms are reported as measured, and the line no longer vanishes. - TSDoc of declinesStoredRow, refusePackagedBaseRemoval and isSealedManagedItem: the seal's reach is every type without an overlay channel (permission excepted), and removing a merge-at-read row changes what is served for permission alone. - .changeset/15206-reads-environment-only.md: two rows the table lacked (projectPermissionMutation's evt.organizationId and SysMetadataRepository.listDrafts' row organizationId). Claude-Session: https://claude.ai/code/session_01JfJfBUC3cQ6hhgm9MQK76T Co-authored-by: Claude <noreply@anthropic.com>
…ation boot report A ledger count that fails costs its own term only: the sys_metadata rows and the other ledgers are still reported, and the failing term is NOT MEASURED with its reason. The failing-probe case now asserts the failed read is said rather than swallowed. Claude-Session: https://claude.ai/code/session_01JfJfBUC3cQ6hhgm9MQK76T Co-authored-by: Claude <noreply@anthropic.com>
…urce name once at boot Measured on a real showcase boot over a database file: an environment sys_metadata row under the showcase's code-declared datasource name was named twice, by [metadata_sealed_overlay_unserved] and by the datasource restore's boot warning, with two different remedies. loadMetaFromDb now leaves a row whose name the host's code-datasource set holds to the restore's warning (isHostCodeDatasource, the first half of isDeclaredCodeDatasource, which now reads through it). A datasource only a package manifest declares is still listed. reportSealedOverlayRows' TSDoc states the seal's whole reach and this exception; the lifecycle page says where such a row is named; a metadata-protocol patch changeset covers this and the per-term isolation of the legacy-organization report. Claude-Session: https://claude.ai/code/session_01JfJfBUC3cQ6hhgm9MQK76T Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 15 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 8 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 11 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin ee88a3ac1aee62f302a361e60553113de54fc68a && git checkout ee88a3ac1aee62f302a361e60553113de54fc68a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin efcbac73cc58510278b970949ac3b65cb9712815 75b4c850fa3d6eec9790f37ccbb422edfc5eca38 && git checkout -B drift-repro efcbac73cc58510278b970949ac3b65cb9712815 && git merge --no-ff 75b4c850fa3d6eec9790f37ccbb422edfc5eca38
node scripts/docs-audit/affected-docs.mjs --json efcbac73cc58510278b970949ac3b65cb9712815
|
…k disposition main has The sentence said a stored fork of a code-declared permission set keeps its ruling "(detection reading and Discard Overlay)" and is still served. The Discard Overlay action was retired in the same pending release line; the disposition on main is that the reads do not decline such a fork, a cold boot refuses a deployment holding one (ADR-0048), and the offline `os migrate security-catalog-overlays` removes it. Only that sentence moves. Claude-Session: https://claude.ai/code/session_01JfJfBUC3cQ6hhgm9MQK76T Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs: card #15206's triage unlock 6107774330, the claim 6108222334, the os-dev-reports 6108953446 (round 1) and 6109357048 (round 2); S5's ACCEPT 6097795222 and contract review 6097501912 for what was carried; card #22835's body; PR #22833 (its body, its 6-file list, and the net diff against the merge base ① Derived judgmentsGate verdicts on this head, as read. 42 check-runs, all
Nothing is deleted or rewritten. No added line calls a store write; the two reads the diff wraps are the same ② Semver level
③ Boundary flags
The open question (ruled A), judged. The implementation is A exactly: the sealed line leaves out the host's code-datasource set and nothing more, through the one helper that names the restore's set; a manifest-declared name is still listed; both kinds are declined at every read (①2). B would reverse the #21922 "code wins on collision" warning in Deviations, both reports, each answered. Round 1: (a) the #22835 as the carrier, and
Check-runs red or in progress. Red: Not a ground, for the seat: the NOT MEASURED-only line's closing sentence (①1, cosmetic); the stated limit of item 2 for a custom host without the datasource-admin plugin (every read still declines the row; both shipped compositions name it); engine doubles without Verdict grounds, all on this head: every required context is green and the one red check is the by-design DELIBERATE CORRECTION refusal, attributed to the foreign changeset rule alone and confirmed sentence by sentence above; the per-term isolation prints NOT MEASURED and never a zero and leaves the boot verdict alone; the host-code leave-out declines both kinds at every read and keeps manifest-only names listed; the four TSDoc wordings and the docs sentence state what the code does; both inserted rows and the rewritten sentence are true at the head and the old sentence was Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Queued with one red check, by design:
Generated by Claude Code |
Part of #15206
Clause-②: no
The carry-over PR of #15206: what the S5 records carried out of the stage (ACCEPT 6097795222 "Carried", contract review 6097501912 ③, landing record 6098305643), scoped by the triage unlock 6107774330, plus the seat's round-2 rulings on this PR. #15206 stays open after this lands: the gap round 1 measured — the datasource restore reads stored datasource rows with no environment predicate, so a legacy organization-scoped row is loaded and served — is #15206's own promise, and its derived child #22835 carries it. ⛔ This PR does not touch it. Not here either: S6 and the registry's bare copy of a non-
objectsealed row (both #15211, C7), and S7 (the ADR-0005 / ADR-0029 D9 note, Tier H, the maintainer's).What changes
[metadata_org_scoped_unserved](reportUnhydratableOrgScopedRows,packages/metadata-protocol/src/protocol.ts). The projectedsys_metadataread and each of the three ledger counts (sys_metadata_commit,sys_metadata_history,sys_metadata_audit) is its own term. A term whose read fails for any reason but a missing table is printedNOT MEASUREDwith its reason, next to the terms that were measured; before, one failing read took the whole line,sys_metadatadetail included, with it. A missing table still reads as zero (isMissingTableError, unchanged). Nothing is invented as a zero and the boot verdict (storeUnavailable) is untouched.loadMetaFromDb, new privateisHostCodeDatasource,protocol.ts). The row is left to the datasource restore's boot warning (restoreRuntimeDatasources,@objectstack/service-datasource), which names it with its own remedy and is the reporterdeclinesStoredRow's own TSDoc already designates (the seat's ruling on this PR's open question: this arm, A). The exclusion is exactly the host's code-datasource set, the set the restore reads;isDeclaredCodeDatasourcenow reads that set through the new helper (one reading). A datasource that only a package manifest declares is still listed by[metadata_sealed_overlay_unserved]. Every read still declines both (pinned).reportSealedOverlayRows,declinesStoredRow,refusePackagedBaseRemoval— now state the seal's reach as the code does (isSealedManagedItem=isArtifactBacked && !registryAllowsOverlay: every type but the five regime-O ones,permissionexcepted), and that removing a merge-at-read row changes what is served forpermissionalone. TheisUnservedSealedOverlayparagraph feat(plugin-security,rest,spec)!: retire the permission-set overlay discard (ADR-0131 cutover stage 7-pre) #22776 rewrote is untouched. Comments only..changeset/15206-reads-environment-only.md— two FROM → TO rows inserted and one sentence corrected; the section below lists each.[metadata_org_scoped_unserved](6097501912 ③, optional) — taken, below.A new
patchchangeset for@objectstack/metadata-protocol(.changeset/15206-boot-report-carry-overs.md) covers items 1 and 2.content/docs/concepts/metadata-lifecycle.mdxgains one sentence, because item 2 made its "boot names each such row" false for a code-defined datasource.check-empty-changesetis red on purpose — DELIBERATE CORRECTION of one pending release noteThe gate's refusal names one file,
.changeset/15206-reads-environment-only.md: it exists on the merge base and this PR edits it. Nothing in it is deleted or restored; no other open PR touches it. ⛔ Noskip-changeset: the gate stays red and this section is the input for the sentence-by-sentence review. Three edits, each of which must ride this PR:ListDraftsResponserowSysMetadataRepository.listDraftsroworganizationId(@objectstack/metadata-protocol) → gone: every listed row is an environment draft, whichever repository asksc8b062f011^each row carriedorganizationId; onb7cd1af9dfnone does and the read ispackageScopedRowWhere('draft', …)=organization_id: null.MetadataAuthoringGateContext.organizationIdroworganizationIdonprojectPermissionMutation'sevt(@objectstack/plugin-security) → drop it: the projection reads the environment → code layered read, whatever organization the event namesc8b062f011^theevttype carriedorganizationIdand forwarded it togetMetaItemLayered; onb7cd1af9dfneither.[Triage ruling Q1 → C]bullet, its last sentenceos migrate security-catalog-overlaysremoves it."main's (isUnservedSealedOverlay's TSDoc as #22776 left it; the cold-boot refusal isObjectQLPlugin.refuseEnvironmentHeldSecurityCatalogNames, ADR-0048). Round-2 seat ruling: folded into this PR.Every other line of that note is unchanged. Left as it stands, pending #22835: the first bullet's "A row stored organization-scoped by an earlier release is served by no read and loaded by no boot", and the boot line's own "no read serves them, boot does not load them" — both become true with #22835's fix of the datasource restore, so neither is edited here.
Measured
Real boot — the showcase through
bootShowcase(@objectstack/verify, sqlite-wasm driver) over a database file: rows planted with the system context between two boots, lines read from the second boot, a temporary uncommitted dogfood file (deleted).baaa75e036: an environment row under the showcase's code-declared datasource name was named twice —[metadata_sealed_overlay_unserved] … datasource×1 (…)with the clone/delete remedies, anddatasource restore: sys_metadata holds a stored row for '…'with theDELETE /api/v1/meta/datasource/…remedy.1fec8e5dd0: the datasource restore's warning alone names it; no[metadata_sealed_overlay_unserved]line (no other sealed row was planted).[metadata_org_scoped_unserved]on both trees named the planted legacy organization row per type, and printed noNOT MEASUREDterm: the threeengine.countledger reads answered on the real engine. This closes the NOT MEASURED of 6097501912 ①7.Pins (
packages/metadata-protocol/src):protocol.org-scoped-cold-boot-audit.test.ts— new case: a ledger count that throws costs its own term; thesys_metadatadetail and the other two ledgers are reported, the failing one isNOT MEASUREDwith its reason. The existing failing-probe case keeps its boot-verdict assertions and now asserts the failed read is said (it pinned the silence before).protocol.reads-environment-only.test.ts— new case: a host-set datasource row is not listed by the sealed line, a manifest-only one is, and both are declined at read.baaa75e036,scripts/ablation-replace.mjsWRAP mode, the subject is./protocol.jsfromsrc, so no build is in the path): the per-term catch made to rethrow (the pre-fix behaviour) — anchor 1 → 0, blobe09bc9f2578c→c9b85129dc0b→ 2 failed / 5 passed (both isolation cases red: no line at all); restore proven, blob == HEAD andgit diff HEADempty.Suites (on
1fec8e5dd0; round 2 changes only the changeset text):@objectstack/metadata-protocoltest225 files passed / 3 skipped, 28,131 tests passed / 19 skipped;typecheckexit 0, and--listFilesshows both edited test files in the program. Consumers of the boot report (every test file outside the package that callsloadMetaFromDb/restoreMetadataFromDb), against the rebuiltdist:@objectstack/objectql15 files / 302 tests,@objectstack/runtime3 / 36,@objectstack/plugin-email1 / 40,@objectstack/plugin-security1 / 30,@objectstack/service-automation1 / 14,@objectstack/metadata1 / 9,@objectstack/dogfood4 files / 22 tests (datasource-restore-code-wins,meta-door-code-datasource,permission-set-clone-boot-unowned-warning,showcase-object-extension-scalar-divergence) — all green.Gates: re-derived on the round-2 head
75b4c850fawithnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 95 families, the same list as round 1 (the dispatch-time 59 plus the docs and test-file families). All 95 run one by one, each exit code captured before any pipe;--ranreconciles 95 derived / 95 run / 0 NOT-MEASURED. 94 exit 0;check-empty-changesetexits 1, the DELIBERATE CORRECTION verdict on.changeset/15206-reads-environment-only.mdexplained above. The derivation warned that the tree is three commits behindmainand thatscripts/sdui-manifest.record.jsonmoved there; no gate in this list reads that file's content (check-changeset-no-majornames the path only, to assert the console build does not copy it), and CI judges the merge ref withmainanyway.Lint:
eslint --no-inline-config --format jsonover the three edited TypeScript files — 3 files, 0 errors, 0 warnings.eslint.config.mjsenables no type-aware linting (noparserOptions.project), so this diff cannot move a verdict on an untouched file; the repo-wide run is CI's.Size
6 files, +153 / −34 = 187 changed lines.
protocol.ts+83 / −31, of which code +40 / −18 (most of the −18 / +17 is the re-indent of the two reads wrapped in the per-term helper) and comments +41 / −13.Acceptance notes
countnow produce a[metadata_org_scoped_unserved]line naming the three ledgersNOT MEASURED(this.engine.count is not a function) where they produced nothing before: 32 such lines in the objectql run above, every test green. A real engine hascount(the reading above). Recorded, not filed.sys_metadataread is isolated as a term too (the hypothesis named the three ledgers; one failing read silenced the line through it the same way);isSealedManagedItem's TSDoc carried the same "restores the managed definition" wording asrefusePackagedBaseRemovaland is corrected in the same stroke (same file, comments only); the docs sentence and the new patch changeset above.b7cd1af9df.mainhas since moved three commits (security(mcp): a nested-relation filter condition through the MCP stdio data bridge is evaluated without asking the target's exposure (census row 8 of #22661) #22777 among them); the branch merges cleanly with it and was pushed fast-forward only, per the seat.Generated by Claude Code