You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
platform-object-names: CLOUD_PROVIDED_OBJECT_NAMES omits sys_package_version, so sys_metadata.package_version_id (shipped metadata-core lookup) is classed as a fictional platform object #16745
packages/spec/src/system/constants/platform-object-names.ts declares the curated cloud list with this contract:
Objects contributed by the CLOUD runtime (@objectstack/service-tenant, defined in the separate cloud repository). … Listed here so a cloud-targeted stack is not told its references are fictional.
CLOUD_PROVIDED_OBJECT_NAMES carries sys_package and sys_package_installation — but not sys_package_version, the middle table of the same family that packages/spec/src/cloud/package.zod.ts declares:
sys_package — identity (one row per logical package)
sys_package_version — immutable release snapshots (see package-version.zod.ts)
sys_package_installation — env ↔ version pairing (see environment-package.zod.ts)
packages/spec/src/cloud/package-version.zod.ts is the row schema for it ("One row in sys_package_version — a sealed, versioned release of a package").
Where it bites
Shipped platform metadata references the object: packages/metadata-core/src/objects/sys-metadata.object.ts:76 — package_version_id: Field.lookup('sys_package_version', …) on sys_metadata.
The object-reference ladder (packages/lint/src/validate-object-references.ts, isPlatformProvidedObjectName) classes that name as rung 4 — platform-prefixed, registered by nothing — i.e. the object-reference-unregistered-platform advisory that exists for fictional names like sys_approval_process. Measured while enrolling field references in that ladder for #16611 (branch claude/issue-16611-lookup-reference-target-gate, commit c9164c0d, corpus: every *.object.ts under packages/ + examples/ at origin/main5e53d73, 116 objects, 137 relationship fields): exactly one finding across the whole universe, and it is this one —
WARNING object-reference-unregistered-platform · objects[34].fields.package_version_id.reference :: lookup target "sys_package_version" carries a platform namespace prefix, but no platform package, official plugin, or cloud runtime object registers that name
Today the same misclassification would hit any dataset object, action param reference, dashboard filter optionsFrom.object or nav requiresObject naming sys_package_version.
Prescription
Add sys_package_version to CLOUD_PROVIDED_OBJECT_NAMES (one line), with the cloud repo's conformance half confirming that @objectstack/service-tenant registers it — the header says that half is owned there and cannot be tested from this repo. Same class as the closed finding on sys_license (#13842).
Filed unassigned from the #16611 measurement; not part of that card.
packages/metadata-core/src/objects/sys-metadata.object.ts:76 package_version_id: Field.lookup('sys_package_version', {
:73 * FK → sys_package_version (UUID). Set for metadata that belongs to a specific
:80 'Foreign key to sys_package_version (UUID). Null = platform-built-in or env-level override.',
with the cloud repo's conformance half confirming that @objectstack/service-tenant registers it — the header says that half is owned there and cannot be tested from this repo.
File surface: packages/spec/src/system/constants/platform-object-names.ts plus its test, and the changeset. ⛔ Nothing under packages/lint — the ladder is correct; it is the list that is short.
⛔ Clause-②: yes — CORRECTED 2026-09-09T19:2xZ; my original no here was WRONG
Clause-②: yes
⚠️This section originally declared no with a Contract-text: citation. Both are withdrawn. The full reversal, with the measured reading that overturned it, is comment 5607037446 on this card. It is edited here rather than only appended because check-clause2-carriers's C5 row reads its declaration from this claim comment through cardDeclaration() — ⛔ not from the PR body and ⛔ not from a later seat comment, however clearly written. The declaration IS the judgement, so only the claiming seat can move it, and a correction that lives anywhere else does not exist to the checker.
What the measurement said:
node scripts/pm/check-clause2-carriers.mjs --pair 17214 -> EXIT 4
T2 packages/spec/src/system/constants/platform-object-names.ts:156
-- a new member of a closed set -- the accept set gains a value
+ 'sys_package_version',
⭐ Why the original reasoning failed: the header I cited declares why the list exists ("so a cloud-targeted stack is not told its references are fictional"), ⛔ not that this name belongs to it. The carve-out I invoked requires the published text to itself deny the refusal being deleted, and that text denies nothing about this name. The lint ladder now accepts a name it previously warned on. That is a widening.
⇒ needs:contract-review is hung on both carriers, and the changeset moves patch -> minor to keep the declaration and the grade consistent.
Premise re-checked on origin/main, ⛔ not carried from the card
Triage verified this at origin/main on 2026-09-08; main has moved many times since, so the dev re-derives before touching anything. Both halves must still hold:
CLOUD_PROVIDED_OBJECT_NAMES carries sys_package and sys_package_installation but not sys_package_version — the head and tail of one three-table family in the list, the middle absent.
packages/metadata-core/src/objects/sys-metadata.object.ts still declares package_version_id: Field.lookup('sys_package_version', …), so platform metadata that ships with the product references the name the list calls fictional.
⛔ If either has been fixed since, stop and report rather than re-landing it.
⚠️ The half that cannot be tested from this repository
The card's own prescription says the cloud-side conformance half — that @objectstack/service-tenant actually registers sys_package_version — is owned in the cloud repository and cannot be verified here. That repository is not reachable from this session.
⇒ Record it as NOT MEASURED with that reason stated, ⛔ never as verified, and ⛔ never soften the claim to something this repo can prove instead. Report it as an out-of-scope finding so this seat can file the cross-repo card with a named reader; ⛔ do not file it yourself.
⭐ Worth naming because it is the whole reason this card exists: a curated allowlist is a second source of truth about what the other repository provides, and it drifted from the first one silently. The fix restores the entry; it does not close the class.
Changeset
Judge it yourself. platform-object-names.ts is not a .zod.ts, so it does not ship as source under files[], but it does ship compiled if exported — check whether it is, and grade accordingly. My reading is @objectstack/spec at patch (a shipped list stops misjudging a name it always meant to carry), but ⛔ re-derive rather than inherit: the sibling card on this lane broke its gate twice on an inherited grade.
Scope fence
⛔ One line plus its test. Sibling absences in the same list are not in scope — if the sweep finds another family member missing, report it as an out-of-scope finding with a named 承接者 rather than widening the PR. Precedent named on the card: the closed sys_license finding.
{
"issue": 16745,
"status": "done",
"branch": "claude/issue-16745-cloud-provided-package-version",
"pr": "https://github.com/objectstack-ai/objectstack/pull/17214",
"premise_still_valid": true,
"summary": "RESUMED after the predecessor died on a model-scoped limit. The single inherited commit f4415dc86 contained exactly three files and nothing else: one line ('sys_package_version') added to CLOUD_PROVIDED_OBJECT_NAMES in packages/spec/src/system/constants/platform-object-names.ts, a 17-line pin case in the sibling platform-object-names.test.ts asserting the whole three-table family resolves, and a patch changeset for @objectstack/spec. The predecessor's own framing ('needs (a) proof the pin file was in the run, (b) readings spliced into the body, then (c) PR creation') was checked rather than inherited and was partly stale: the PR existed AND the body already carried readings, so what was actually outstanding was (a) plus re-deriving every claim in that body on a current head. Both premise halves were re-verified at origin/main before any work. origin/main (4261fbc80) was then merged in via scripts/pm/os-regen-merge.sh; no os-regen path needed a side taken and no generated artifact moved. Final head 87751f84e, pushed. PR stays draft, base main, body line 1 is the closing line naming this card, 'Clause-2: no' and its mandatory 'Contract-text:' citation each on their own line, needs:contract-review NOT hung. No second claim posted; assignee untouched.",
"tests": "FULL PACKAGE SUITE, one run, no --project filter and no file list, under os-verify-lock (slot issue-16745-resume): 'pnpm --filter @objectstack/spec exec vitest run --reporter=verbose --maxWorkers=2' -> Test Files 498 passed (498), Tests 13609 passed (13609), Duration 490.99s; lock printed 'VERDICT command-exit 0 · held the lock 779s · waited 339s'. PROOF THE PIN FILE RAN (the point of item (a)): platform-object-names.test.ts is entry 27 of the 28 in vitest.repo-tests.json, so the 'local' project EXCLUDES it and 'pnpm test' alone would never have run it — the verbose reporter shows all 9 of its cases tagged '|repo|', including by name 'resolves the middle table of the cloud package family', with the pre-existing sys_license sibling case lit beside it as control. ABLATION (predecessor declined it; run here, direction predicted as 'turns red' before running, both legs under the lock with a bash trap on EXIT INT TERM calling a restore function and absolute paths): HEAD blob f691ad79; marker count 1 -> 0 proving the edit reached disk; the mutated file hashed to 6aff7752, byte-identical to the pre-fix blob this PR replaced; MUTATED leg exit 1 with 'Tests 1 failed | 8 passed (9)' and 'AssertionError: sys_package_version: expected false to be true'; restore anchored at HEAD reproduced f691ad79 with an empty 'git diff HEAD'; RESTORED leg exit 0 with 9 passed (9). Exactly one of nine cases moved and it is the new one. OTHER (same acquisition, exit codes landed to disk before being read): build 0, typecheck 0, check:generated 0 with git status clean. Closure (1) is empty by construction — @objectstack/spec declares no @objectstack/* workspace dependency. GATES (3)/(4): derived mechanically, never hand-fed — 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' at 87751f84e produced 77 commands from a 3-path change set vs merge base 4261fbc80; all 77 run; reconciliation 'dispatch-gates --ran: 77 derived famil(ies) accounted for — 77 run, 0 NOT-MEASURED, 0 UNRUN'. 73 exited 0. FOUR exited 3 = PREREQUISITE NOT MET, recorded NOT MEASURED, neither green nor red, all for absent built output of OTHER packages that CI builds fresh: lint check:doc-formula-expressions (@objectstack/formula not built), check:dual-build-cjs-loads, check:lean-entry-closure (packages/objectql/dist/core.mjs), check:type-check-debt. One earlier ablation attempt returned the lock's exit 99 queue-timeout — discarded as NOT MEASURED, never as a pass; the tree was verified untouched and the run was re-taken on the SAME slot, which resumed the place rather than re-queueing. check:nul-bytes 0, plus an independent grep -naP control-character sweep over the three changed files: clean. Repo-wide 'pnpm lint' is CI's run, not attempted here. CHANGESET RE-DERIVED, not inherited: platform-object-names.ts is not a .zod.ts so it ships no source under files[], but src/system/constants/index.ts re-exports it, so it ships COMPILED in dist (which IS in files[]) — measured on the rebuilt dist, 1 hit in each of dist/system/index.mjs, dist/system/index.js, dist/index.mjs, dist/browser/system/index.mjs, control sys_license 1 each, negative control 0. Published behaviour moves, so skip-changeset does NOT apply; no export added or removed and no authorable key changes, so patch. CI's Check Changeset is green on this grade at the merged head. CI READ MYSELF, newest run per check name on the final head 87751f84e (not the raw run list, not the required subset): 9 success, 5 skipped, 17 in_progress, ZERO failures at report time — Check Changeset, Governed Surface Queue Guard, Part-of PR must not also close its card, Spec property liveness and the claim guards already green. The pre-merge head f4415dc86 had previously gone fully green: 31 success, 3 skipped, 0 failure.",
"mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (probe returned 200) plus git; no MCP GitHub tool was called",
"open_questions": [],
"out_of_scope_findings": [
"NOT MEASURED, for the seat to file cross-repo (⛔ not filed by me, per dispatch): that @objectstack/service-tenant actually registers sys_package_version. That half lives in the `cloud` repository, which is NOT REACHABLE from this session, and the list's own header says it cannot be conformance-tested from this repo. It is recorded as NOT MEASURED — never as verified, and nothing this repo can prove was substituted for it. 承接者: the seat, filing the cross-repo conformance card against `cloud`.",
"noted, not filed: scope-fence sweep for sibling absences found NONE. Re-run on the rebuilt dist against PLATFORM_PROVIDED_OBJECT_NAMES over 112 shipped *.object.ts files under packages/ + examples/: 135 reference targets, 109 platform-prefixed, 0 unregistered. Controls lit: sys_user appears 61 times, registry.has('sys_definitely_not_real') false, registry.has('sys_package_version') true (the last also proving the dist read was the rebuilt one). This reproduces the card's 'exactly one finding in the whole universe' measurement and brings it to zero. The PR was NOT widened. 承接者: none needed — nothing found.",
"noted, not filed: packages/spec/src/cloud/environment.zod.ts names sys_environment_credential and tenant.zod.ts names the deprecated sys_tenant_database; neither is in CLOUD_PROVIDED_OBJECT_NAMES and both are referenced by ZERO shipped *.object.ts files, so no false refusal reproduces today — that absence of a shipped reference is exactly what separates them from this card and is why they are not filed. 承接者: the seat filing the cross-repo card carries the question alongside.",
"noted, not filed: check-widening-tells' T2 matcher fires on this diff and check-clause2-carriers --pair 17214 exits 4, because the tell reads ADDED LINES ONLY and has no notion of direction — it cannot see that adding a name to a curated allowlist DELETES a false refusal. Reading re-taken on this head after origin/main moved that script by 143 lines, so it is current, not inherited. Not a CI red: lint.yml wires only --self-test for both check:pm-clause2-carriers and check:pm-widening-tells, and its own comment calls --pair 'deliberately not a merge gate'. Per the gate's own header the repair for a demonstrated false positive belongs in the matcher, not in the declaration. 承接者: the seat that owns scripts/pm/check-widening-tells.mjs.",
"noted, not filed (platform reading, may be worth the fleet's ledger): updating a PR body via REST PATCH /pulls/{n} APPENDED a second, bare-form '_Generated by [Claude Code](https://claude.ai/code)_' footer BELOW the session-URL footer that was sent, even though the sent block carried its rule line in the correct form. Caught only by the mandatory full read-back; the body content itself survived byte-for-byte (all probes present, line 1 still the closing line naming this card). Left as-is rather than re-patched, since re-posting footers in a loop is exactly what the contract forbids. 承接者: the seat maintaining pm-dispatch references/platform-readings.md."
]
}
⛔ My Clause-②: no was WRONG — reversed to yes, gate hung on both carriers
domain:spec seat, session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-09T18:4xZ. The delivery is sound; the defect is in my dispatch order, for the fourth time this shift and by the same mechanism.
The reading that overturned me — run by this seat, ⛔ not taken from the report
node scripts/pm/check-clause2-carriers.mjs --pair 17214 → EXIT 4
✗ C5 — card #16745 declares `Clause-②: no` while its diff carries 1 widening tell
T2 packages/spec/src/system/constants/platform-object-names.ts:156
— a new member of a closed set — the accept set gains a value
+ 'sys_package_version',
Landing pre-check ② requires exit 0. This is exit 4. ⇒ ⛔ This PR cannot land on my declaration, and the standing rule says it plainly: a no that hits a new member is refused, with file:line. The tell names the member and the line.
⭐ Why the tell is right and I was not
My claim comment argued the addition "deletes a false refusal rather than widening an accept set", and cited the list header as Contract-text:. I re-read that header today:
Objects contributed by the CLOUD runtime … Listed here so a cloud-targeted stack is not told its references are fictional. They cannot be conformance-tested from this repo — the cloud repo owns that half of the contract.
⚠️ That text declares why the list exists. It does ⛔ not declare that sys_package_version is a member of it. The clause-② carve-out I invoked requires the published text to itself deny the refusal being deleted — and this text denies nothing about this name. It states a purpose, and a purpose is not an enumeration.
⇒ Mechanically and substantively, the lint ladder now accepts a name it previously warned on. The accept set gains a value. That is a widening, and it takes yes.
⛔ I also checked whether the checker's "or explain in the claim" offers a machine-readable waiver. It does not — that phrase is guidance to a reader, and no marker in the script parses an explanation. So a prose argument, however good, cannot clear C5. It should not be able to.
⚠️ What this costs, stated plainly because I told the maintainer otherwise
I reported to the maintainer twice that this was "the only card in flight that can land without contract-review-tier budget". That is false. With yes it needs a CONTRACT_REVIEW_TIER PASS exactly like its three siblings, and that tier is currently exhausted. ⇒ Nothing in this lane lands until Fable budget returns, and I removed the one exception by getting it wrong rather than by anything changing.
Same root as my three earlier defects this shift: I decided a declaration from the consequence I was thinking about, and did not re-derive it against the mechanical rule that already had an answer. The pattern is now four for four, and the fix is not more care — it is running --pair at claim time rather than at landing time, which would have caught this before a dev spent a round on it.
Carriers, read back after the write
needs:contract-review hung on both: card ['bug','domain:spec','finding','needs:contract-review','pm:dispatched','priority:p3'] with assignee intact, PR #17214['documentation','needs:contract-review','protocol:system','size/s','tests','tooling'].
⛔ The changeset must move with the declaration
Clause-②: yes against a diff that moves packages/spec/src/** requires the changeset at minor or above; it is at patch. Leaving the declaration and the grade inconsistent is a hard Check Changeset red — the exact failure this lane hit twice today. ⇒ A narrow patch round follows to move both together, and the level is the dev's to derive, with minor as the floor the gate imposes.
⭐ What the delivery got right, recorded so it is not lost in a reversal
The ablation was run, and its predecessor had declined it: one mutation, marker count 1 → 0 proving the edit reached disk, the mutated file hashing byte-identical to the pre-fix blob, the mutated leg failing exactly one of nine cases by name, restore anchored at HEAD reproducing the original blob with an empty git diff. Exactly one case moved and it is the new one.
The item (a) proof is the good kind.platform-object-names.test.ts is entry 27 of 28 in vitest.repo-tests.json, so the local project excludes it and pnpm test alone would never have run it. The full suite was run instead — 498 files, 13609 tests — and the verbose reporter shows all nine of its cases tagged |repo| by name, with the sys_license sibling lit beside them as control. ⇒ That is a proof the file ran, not an assertion that it did.
A queue-timeout was discarded as NOT MEASURED, never as a pass, and the run re-taken on the same slot.
The scope-fence sweep found nothing, with controls lit, and reproduced the card's "exactly one finding in the whole universe" measurement — now zero. The PR was ⛔ not widened.
Out-of-scope items this seat now owes
The cross-repo conformance card against cloud — that @objectstack/service-tenant registers sys_package_version. Correctly recorded NOT MEASURED, ⛔ never verified and ⛔ never substituted with something this repo can prove. cloud is unreachable from this session, so it lands here as a seam card with a named reader.
Carried with it: sys_environment_credential and the deprecated sys_tenant_database are also absent from the list, and referenced by zero shipped *.object.ts files — which is precisely why they are not this card. That absence is the discriminator and it belongs in the same question.
A card against scripts/pm/check-widening-tells.mjs's owner. ⚠️ ⛔ Not as a false-positive report — the tell was right here. As the narrower point the delivery actually established: T2 reads added lines only and has no notion of direction, so it cannot distinguish a widening from a narrowing on a curated list. That is worth knowing even when, as today, the direction it assumes is the correct one.
A platform-readings.md line: a REST PATCH /pulls/{n} appends a second bare footer beneath a sent session-URL footer. Caught only by the mandatory read-back; ⛔ correctly left rather than re-patched.
{
"issue": 16745,
"status": "blocked",
"branch": "claude/issue-16745-cloud-provided-package-version",
"pr": "https://github.com/objectstack-ai/objectstack/pull/17214",
"premise_still_valid": true,
"summary": "The three narrow edits landed on head df37e6564 and nothing else in the PR moved: the PR body now carries a line-start `Clause-②: yes` with the `Contract-text:` line and its backing sentence removed, and the changeset is regraded `@objectstack/spec: minor` with prose that no longer frames the addition as restoring something the published header already promised. The source line, the pin, the ablation and the sweep are untouched — both source blobs hash identically at 87751f84e and df37e6564 (platform-object-names.ts f691ad7939dac77330995e3d9db49e95182ad5db, its test b2a4cde719761206871181f1ff358753b2371ab9), so this round's whole diff against the previous head is one .changeset/*.md. BLOCKED on one PM-only act, and it falsifies a mechanism assumption in the dispatch order: `--pair` still exits 4, because C5 does NOT read the PR body. Its declaration limb is `cardDeclaration()` over the CARD's comment thread, and the single claim-shaped comment on card #16745 is 5605472270 (the seat's dispatch claim), which still carries a line-start `Clause-②: no`. Measured, with a lit control: `cardDeclaration()` over the real thread returns {state: declared, value: no}; the same reader over the same thread with that one line flipped returns {state: declared, value: yes}. The seat's reversal comment 5607037446 is not claim-shaped, so it carries no declaration for this reader. The checker's own header forbids me from writing it (\"do not write the declaration on the claiming seat's behalf; the declaration IS the judgement\"), and the brief forbids a second Claim, so it is reported rather than routed around. Only the claiming seat editing comment 5605472270 (or posting a newer governing claim) moves `--pair` to 0. PR left draft, `needs:contract-review` untouched on both carriers, not enqueued.",
"tests": "CHANGESET LEVEL, derived not taken: floor #1 — pr-automation.yml 'WHICH LEVEL' (maintainer ruling 2026-09-04, batch #35 on #15294): a purely additive widening of a published package's public surface, 'a new accepted key OR VALUE', takes at least `minor`; floor #2 — check-changeset-no-major.mjs level axis: a PR declaring clause ② must grade at least one package whose published src it moves `minor` or above, and @objectstack/spec is the only package this diff moves; ceiling — `major` is refused outright by the same script's launch-window guard, no `allow-major` label on the PR and no .changeset/pre.json so the RC exemption is not in effect. Floor meets ceiling at `minor`, the only legal grade. No ADR-0087 disposition owed: that gate's breaking signals are a `major` bump or a `**BREAKING` / `BREAKING CHANGE` body marker, and this changeset carries neither (gate's own line: 'this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)'). || --pair EXIT CODE: 4, both before and after the edits (scripts/pm/check-clause2-carriers.mjs --pair 17214), same C5/T2 row at platform-object-names.ts:156. Cause proven above with a lit control, not argued. || CHECK CHANGESET, read by me as newest-run-per-check-name on head df37e6564: conclusion SUCCESS (run started 19:17:59Z, the `edited` trigger my body write fired; the earlier 18:55:14Z run on the same head is also success). Its own log line, quoted from job 102609774531: '✓ LEVEL AXIS: this PR declares clause-② `yes`, and no package whose `packages/**/src/**` it moves is graded `patch`. · carrier: `needs:contract-review` IS on this PR · declaration line: `Clause-②: yes`'. So the axis FIRED and read the new body line — it did not stand down into a silent green. || LEVEL-AXIS CONTROL, lit locally on the live payload: the same script run with --event built from the PR as read back after the write exits 0 with the identical 'LEVEL AXIS' line. A first ablation attempt mutating the changeset in the WORKING TREE was a NO-OP and is reported as such rather than silently re-run: marker minor 1 to 0 and the hash moved, proving the edit reached disk, yet the verdict did not move — this gate reads git blobs, not the tree. Restored, hash back to the HEAD blob, `git diff HEAD` empty. The control was then built correctly as a real commit object with `git commit-tree` over a temporary index (real HEAD and index never touched, `git diff HEAD` empty throughout): same tree, changeset graded `patch`, exit 1, verdict 'This PR declares clause-② YES, and it grades NO package ... at `minor` or above'. The commit is dangling, on no branch, never pushed. || MERGE: origin/main had moved to bccf31110; merged through scripts/pm/os-regen-merge.sh, merge commit df37e6564, no os-regen path needed a side taken, no generated artifact moved, `git status` clean. || ② PACKAGE LEVEL on the final head, under os-verify-lock slot issue-16745-patch, exit codes echoed individually rather than read from the wrapper's `;`-batch verdict: BUILD_EXIT=0, TYPECHECK_EXIT=0 (tsc + scripts tsconfig + check:test-typecheck). Full suite re-taken on df37e6564, NOT carried over: `pnpm --filter @objectstack/spec exec vitest run --reporter=verbose --maxWorkers=2` — Test Files 498 passed (498), Tests 13609 passed (13609), Duration 561.78s, 'VERDICT command-exit 0 · held the lock 563s · waited 0s'. All nine cases of platform-object-names.test.ts appear tagged |repo| by name, including the new 'resolves the middle table of the cloud package family' and the sys_license sibling beside it as control — that file is a vitest.repo-tests.json entry the `local` project excludes, so this is proof it RAN. || ① dependency closure: @objectstack/spec declares no @objectstack/* workspace dependency, so the closure build is empty by construction; the package itself was built. || ③/④ GATE FAMILIES, derived mechanically with no hand-fed path list: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at commit df37e6564, change set 3 paths vs merge base bccf31110 (three-dot), 77 commands. All 77 run on the final head with each exit code landed to a file BEFORE being read: 73 exited 0, 4 exited 3 = PREREQUISITE NOT MET, recorded NOT MEASURED (neither green nor red) — lint check:doc-formula-expressions, check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt, all four because they read built output for packages this worktree has not built. Reconciled: `dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.txt` → '77 derived famil(ies) accounted for — 77 run, 0 NOT-MEASURED, 0 UNRUN.' check:nul-bytes exited 0. Repo-wide `pnpm lint` is CI's run and was not attempted. || NO QUEUE-TIMEOUT was read as a pass: the only lock waits this round were 63s and 0s, both ACQUIRED. || CI on df37e6564, newest run per check name: Check Changeset success, Build Core success, Test Core success (all 6 shards), TypeScript Type Check success, all four Type Check jobs success, Dogfood Regression Gate success (all 3 shards), Dogfood Verify CLI success, Temporal Conformance success, Governed Surface Queue Guard success, Spec property liveness success, the three PR-hygiene guards success; 'Lint & Repo Gates' is in_progress at report time and is reported as in_progress, not as green. || PR BODY read back after the write: the 14412 bytes I sent survived byte-identical; GitHub appended one extra bare footer beneath the session-URL footer, which is the already-recorded REST PATCH /pulls/{n} behaviour — left as-is rather than re-patched in a loop. Body confirmed still draft, labels unchanged including needs:contract-review, exactly one line-start `Clause-②:` line and it reads `yes`, no `Contract-text:` line, no angle-bracket-shaped fragment anywhere in the text.",
"mcp_calls": "1 — one get_job_logs to quote CI's own LEVEL AXIS line; every other GitHub read and the PR body write went through the container's REST channel (repo-scoped probe http=200 at the start of the round).",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: the two clause-② readers take DIFFERENT carriers, and nothing warns an operator who conflates them. check-changeset-no-major.mjs's level axis reads the PR body plus labels from the pull_request payload (by design, so it needs no token in a required gate); check-clause2-carriers.mjs's C5 reads the card's governing claim comment and nothing else. Editing only the PR body therefore turns Check Changeset green while leaving --pair at 4, which is exactly the state this PR is now in. Neither reader is wrong and each documents its own choice in its own header, so this is not a defect and is not filed. 承接者: the seat, alongside the check-widening-tells.mjs card it already owes.",
"noted, not filed: check-changeset-no-major.mjs reads head-side changeset content from git blobs, not from the working tree, so the ordinary working-tree ablation shape is a silent no-op against it — the mutation reaches disk, the marker count moves, and the verdict does not. Measured here, reported rather than re-run until something landed. The working control is a commit object built with `git commit-tree` over a temporary index. 承接者: the next agent asked to ablate a changeset-scoped gate.",
"noted, not filed: the C5 remedy text prints 'or explain in the claim why this addition does not widen', and the seat measured that no marker in the script parses such an explanation. An operator taking the second branch of that printed remedy gets no change in verdict. Recorded here as a second sighting; the seat has it. 承接者: the seat's owed check-widening-tells.mjs card.",
"noted, not filed: the REST PATCH /pulls/{n} duplicate-footer behaviour reproduced again on this round's body write — one bare footer appended beneath the session-URL footer I sent. Caught by the mandatory read-back, left rather than re-patched. 承接者: the seat's owed platform-readings.md line, which already names it."
]
}
⭐ The round found a mechanism I had wrong, and refused to route around it
I assumed flipping the PR body would clear C5. It does not. check-clause2-carriers's C5 reads its declaration limb through cardDeclaration() over this card's claim comment — ⛔ not the PR body, and ⛔ not a later seat comment however clearly written. So my reversal comment 5607037446 carried no declaration for that reader, and the governing claim 5605472270 still said no.
The dev proved it with a lit control rather than arguing it: cardDeclaration() over the real thread returned {declared, no}; the same reader over the same thread with that one line flipped returned {declared, yes}.
⭐ And then it stopped. The checker's own header forbids writing the declaration on the claiming seat's behalf — "the declaration IS the judgement" — so it reported the block instead of clearing it. That is exactly right: an agent that had "helpfully" edited my claim would have issued my judgement for me, which is the 自查放行 failure the header exists to prevent.
What I did, and why it is an edit rather than a new comment
Corrected the declaration in claim comment 5605472270 itself, because that is the only carrier the checker reads. The withdrawn reasoning is not erased: the comment now says plainly that its original no and its Contract-text: citation are withdrawn, quotes the measurement that overturned them, and points at 5607037446. Editing keeps exactly one claim-shaped comment on the card, which avoids handing cardDeclaration() an ambiguity to resolve.
Read back after the write: one line-start Clause-②: yes, ⛔ no Contract-text: line, Claim: intact.
Landing pre-checks now
pre-check
reading
② dual carriers, machine-read
node scripts/pm/check-clause2-carriers.mjs --pair 17214 → exit 0, "the declaration is readable in the fixed spelling and both carriers agree" (was 4)
③ every check green
34 distinct names on df37e6564, newest run per name: 29 success + 5 skipped, 0 red, 0 in progress
changeset grade
"@objectstack/spec": minor — consistent with the yes
① at-tier PASS
⛔ NOT on record. Owed, and blocked: the contract-review tier is exhausted
⇒ Two of three pre-checks pass. ⛔ The PR does not land until a CONTRACT_REVIEW_TIER PASS exists. The quota exemption covers dispatch, never review.
⭐ How the grade was derived, which is the part worth reusing
Not chosen — bracketed. Floor one: the maintainer's 2026-09-04 ruling that a purely additive widening of a published surface, "a new accepted key or value", takes at least minor. Floor two: the changeset gate's own level axis, which requires a clause-② yes to grade at least one moved-src package at minor or above. Ceiling: major is refused outright by the launch-window guard, with no allow-major label and no pre.json. Floor meets ceiling at exactly one legal grade.
And the gate was confirmed to have actually judged it rather than standing down into a silent green — its own log line reads ✓ LEVEL AXIS: this PR declares clause-② 'yes', and no package whose packages/**/src/** it moves is graded 'patch'. This lane has been burned twice today by a green that never asked the question.
⚠️ A measurement trap this round mapped, worth carrying
The first ablation attempt mutated the changeset in the working tree and was a silent no-op: the marker count moved, the file hash moved, and the verdict did not — because that gate reads git blobs, not the tree. Rather than re-run until something moved, the round reported the no-op and rebuilt the control properly with git commit-tree over a temporary index (real HEAD and index untouched, dangling commit, never pushed). Then it failed correctly: exit 1, "declares clause-② YES, and it grades NO package … at minor or above".
⇒ A control that does not move the verdict is a broken control, ⛔ not a passing gate.
Two carriers, two readers, one operator trap
The round named the thing that actually cost this card a round: the two clause-② readers take different carriers. The changeset gate's level axis reads the PR body and labels from the payload, by design, so it needs no token in a required gate. C5 reads the card's claim comment. ⇒ Editing only the PR body turns Check Changeset green while leaving --pair at 4 — precisely the state this PR sat in for half an hour.
Neither reader is wrong and each documents its own choice. ⛔ Not filed as a defect. It goes into the check-widening-tells.mjs card this seat already owes, as the operator-facing half.
我明确要求它「⛔ 不要把这段历史当成权威定案」,若认为 no 才对就带读数说出来。它照做了,先替 no 辩护——然后驳回,理由是读数而非权威:
阶梯头注把 ④ 定义为「prefixed, NOT in the registry → WARNING」,registry 是「curated set of real names」;列表头注只陈述目的,不枚举成员,已发布文本中没有任何一句「否认」对该名的告警。⇒「假拒绝」是对同一动作的价值判断,不是对方向的判断;clause-② 问的是方向。
packages/objectql/src/engine.ts:7792resolvePrimaryDatasource() 是运行时消费者,遍历这个 Set 为「主数据源」投票。changeset 写的是「every surface that consults the predicate」——而这一处读的是 Set 本身,不走谓词。
packages/lint/src/validate-nav-access.ts:162 — continue;但紧随的 :163 if (!ownObjects.has(objectName)) continue; 对非本 stack 对象一样跳过,此处行为无净变化。
packages/objectql/src/engine.ts:7792 — 运行时消费者,resolvePrimaryDatasource() 遍历该 Set,对本部署已注册的平台对象投票。⚠️ changeset 只写「every surface that consults the predicate」,遗漏了这个读 Set 而非谓词的运行时面(见 ③ 第 5 条)。
git show origin/main:.github/workflows/pr-automation.yml | sed -n '712,725p':「A purely additive widening of a published package's public surface (a new exported symbol on an index, a new accepted key or value) takes at least minor… Ruled by the maintainer on 2026-09-04 (decision batch #35) on #15294」
地板 = 天花板 = minor;changeset 头 "@objectstack/spec": minor(git show df37e6564:.changeset/spec-cloud-provided-package-version.md)
derived,不是 chosen
level axis 确实判了,没有 stand down:get_job_logs 102609774531 原文——
✓ LEVEL AXIS: this PR declares clause-② `yes`, and no package whose `packages/**/src/**` it moves is graded `patch`.
· carrier: `needs:contract-review` IS on this PR
· declaration line: `Clause-②: yes`
C5 双载体: 我自己跑了(git archive origin/main scripts package.json 导出到 scratchpad,node scripts/pm/check-clause2-carriers.mjs --pair 17214)→ ✓ … the clause-② declaration is readable in the fixed spelling and both carriers agree.EXIT=0,token 路径 3 reads。读 cardDeclaration(:696-740):先取 governing claim(5605472270,已编辑为 line-start Clause-②: yes),再读整线程——与席位的读数一致。其他 changeset gate 在 CI 同 job:check-empty-changeset ✓ (1 declaring), check-adr-0087-registration ✓ (1 non-breaking), ✓ This diff introduces no major bump。
C. Pin。 读 git show df37e6564:…/platform-object-names.test.ts 全文:新 case 循环三名,expect(isPlatformProvidedObjectName(name), name).toBe(true)。消融推演:去掉那一行后,sys_package 通过、sys_package_version 抛 sys_package_version: expected false to be true(vitest 把第二参数作为前缀,与报告的断言文本逐字一致);其余 8 例——cloud-only names… 只遍历列表现有成员,every registered name… 只查前缀,registers exactly the objects each package declares 只比 PLATFORM_OBJECTS_BY_PACKAGE——都不读缺失的名字,故恰好 1/9 变红。修复后 cloud-only names are registered but not declared in this repo 要求 sys_package_version 不被任何 packages/**/*.object.ts 声明:我的 sweep declared own names: 110,其中不含该名(它在 pre-fix 落入 UNREGISTERED 而非 own)。vitest.repo-tests.json 第 28 行为该文件,vitest.config.tslocal 项目 exclude: [...REPO_TESTS]——实现者对「pnpm test 不跑它」的判断成立;全套件运行本身 NOT MEASURED(无 node_modules),我以 CI Test Core (1/6..6/6) 六片 success + 源码推演替代判断,不替代运行。
PR body 准确性(F): body 中「⚠️--pair still exits 4 on this head」一段已过时——席位编辑 claim 后我测得 exit 0。body 是 edited 事件前写的,描述的是当时状态,不构成误导,但合并前顺手删掉更干净(非绑定)。changeset 第 10 行「The name was previously refused」与第 12 行「used to warn on」自相矛盾:阶梯 ④ 是 severity: 'warning',不是拒绝(非绑定措辞)。
Activity
os-zhuang commentedon Sep 8, 2026
分诊:
domain:spec/Bug/priority:p3/pm:queue域 —— 要改的一行在
packages/spec/src/system/constants/platform-object-names.ts,按车道表packages/spec整包 ⇒domain:spec。当刻复核(
origin/main)—— 逐字成立⇒
sys_package_version不在其中,而sys_package和sys_package_installation都在 —— 同一个三表家族的头尾在册、中间那张不在。被引用的那一处也成立:
⇒ 随平台发布的元数据自己引用着这个名字,而清单说它不存在。
类型
Bug按类型判据「违背已声明契约 ⇒ Bug」。这里被违背的契约是
CLOUD_PROVIDED_OBJECT_NAMES自陈的目的:一个随平台一起发布的
Field.lookup目标被这张清单判成 fictional ⇒ 清单没有做到它声明要做的事。⛔ 不是 Feature(不扩大接受集,只是把一个本就该在册的名字补上)。等级
p3object-reference-unregistered-platform),不是拒绝、不是崩溃、不是数据问题。object、action 参数reference、dashboard 过滤器optionsFrom.object、navrequiresObject里写sys_package_version的地方。卡面的处方里藏着一个跨仓条件,本席把它提为硬条件:
⇒ 在
cloud仓确认@objectstack/service-tenant确实注册了sys_package_version之前,⛔ 不要加这一行。 否则这张卡就是把一个假阳性换成一个假阴性 —— 清单声称某个名字由 cloud 提供,而实际没有,那比现在更难查。⭐ 这正是
sys_license(#13842,已闭)走过的路,卡面把它认作同类是对的:照那张卡的做法走,包括它的 cloud 侧确认步骤。cloud仓验证这一条 —— 这是本席读数的边界,不是一个已确认的事实。认领席自己去验。交给认领席
claude/issue-16611-lookup-reference-target-gatecommitc9164c0d,语料取自origin/main 5e53d73。当刻origin/main已前移;清单本身当刻仍是上面那六个(本席刚验),但 finding 计数(「整个宇宙只此一条」)没有在当刻重测。若要引用那个「1」,先自己重跑。referencenames an object that exists nowhere — the dangling target is found only at runtime #16611 的测量里掉出来,⛔ 不属于那张卡;validate / lint / build accept a lookup or master_detail whosereferencenames an object that exists nowhere — the dangling target is found only at runtime #16611 当刻是needs-user-decision,本卡不受它阻塞。分诊席声明:本席只分类/定级/路由,⛔ 不认领、⛔ 不派工、⛔ 不写码、⛔ 不合并、⛔ 不裁决决策箱卡。
Generated by Claude Code
os-bill commentedon Sep 9, 2026
Claim: PM loop —
domain:specseat,session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-09T16:4xZ. Dispatchingos-devon branchclaude/issue-16745-cloud-provided-package-version. Container & model:mode:subagent,claude-fable-5-1.File surface:
packages/spec/src/system/constants/platform-object-names.tsplus its test, and the changeset. ⛔ Nothing underpackages/lint— the ladder is correct; it is the list that is short.⛔ Clause-②: yes — CORRECTED 2026-09-09T19:2xZ; my original
nohere was WRONGnowith aContract-text:citation. Both are withdrawn. The full reversal, with the measured reading that overturned it, is comment5607037446on this card. It is edited here rather than only appended becausecheck-clause2-carriers's C5 row reads its declaration from this claim comment throughcardDeclaration()— ⛔ not from the PR body and ⛔ not from a later seat comment, however clearly written. The declaration IS the judgement, so only the claiming seat can move it, and a correction that lives anywhere else does not exist to the checker.What the measurement said:
⭐ Why the original reasoning failed: the header I cited declares why the list exists ("so a cloud-targeted stack is not told its references are fictional"), ⛔ not that this name belongs to it. The carve-out I invoked requires the published text to itself deny the refusal being deleted, and that text denies nothing about this name. The lint ladder now accepts a name it previously warned on. That is a widening.
⇒
needs:contract-reviewis hung on both carriers, and the changeset movespatch->minorto keep the declaration and the grade consistent.Premise re-checked on
origin/main, ⛔ not carried from the cardTriage verified this at
origin/mainon 2026-09-08; main has moved many times since, so the dev re-derives before touching anything. Both halves must still hold:CLOUD_PROVIDED_OBJECT_NAMEScarriessys_packageandsys_package_installationbut notsys_package_version— the head and tail of one three-table family in the list, the middle absent.packages/metadata-core/src/objects/sys-metadata.object.tsstill declarespackage_version_id: Field.lookup('sys_package_version', …), so platform metadata that ships with the product references the name the list calls fictional.⛔ If either has been fixed since, stop and report rather than re-landing it.
The card's own prescription says the cloud-side conformance half — that
@objectstack/service-tenantactually registerssys_package_version— is owned in thecloudrepository and cannot be verified here. That repository is not reachable from this session.⇒ Record it as NOT MEASURED with that reason stated, ⛔ never as verified, and ⛔ never soften the claim to something this repo can prove instead. Report it as an out-of-scope finding so this seat can file the cross-repo card with a named reader; ⛔ do not file it yourself.
⭐ Worth naming because it is the whole reason this card exists: a curated allowlist is a second source of truth about what the other repository provides, and it drifted from the first one silently. The fix restores the entry; it does not close the class.
Changeset
Judge it yourself.
platform-object-names.tsis not a.zod.ts, so it does not ship as source underfiles[], but it does ship compiled if exported — check whether it is, and grade accordingly. My reading is@objectstack/specatpatch(a shipped list stops misjudging a name it always meant to carry), but ⛔ re-derive rather than inherit: the sibling card on this lane broke its gate twice on an inherited grade.Scope fence
⛔ One line plus its test. Sibling absences in the same list are not in scope — if the sweep finds another family member missing, report it as an out-of-scope finding with a named 承接者 rather than widening the PR. Precedent named on the card: the closed
sys_licensefinding.Generated by Claude Code
os-bill commentedon Sep 9, 2026
os-dev-report
{ "issue": 16745, "status": "done", "branch": "claude/issue-16745-cloud-provided-package-version", "pr": "https://github.com/objectstack-ai/objectstack/pull/17214", "premise_still_valid": true, "summary": "RESUMED after the predecessor died on a model-scoped limit. The single inherited commit f4415dc86 contained exactly three files and nothing else: one line ('sys_package_version') added to CLOUD_PROVIDED_OBJECT_NAMES in packages/spec/src/system/constants/platform-object-names.ts, a 17-line pin case in the sibling platform-object-names.test.ts asserting the whole three-table family resolves, and a patch changeset for @objectstack/spec. The predecessor's own framing ('needs (a) proof the pin file was in the run, (b) readings spliced into the body, then (c) PR creation') was checked rather than inherited and was partly stale: the PR existed AND the body already carried readings, so what was actually outstanding was (a) plus re-deriving every claim in that body on a current head. Both premise halves were re-verified at origin/main before any work. origin/main (4261fbc80) was then merged in via scripts/pm/os-regen-merge.sh; no os-regen path needed a side taken and no generated artifact moved. Final head 87751f84e, pushed. PR stays draft, base main, body line 1 is the closing line naming this card, 'Clause-2: no' and its mandatory 'Contract-text:' citation each on their own line, needs:contract-review NOT hung. No second claim posted; assignee untouched.", "tests": "FULL PACKAGE SUITE, one run, no --project filter and no file list, under os-verify-lock (slot issue-16745-resume): 'pnpm --filter @objectstack/spec exec vitest run --reporter=verbose --maxWorkers=2' -> Test Files 498 passed (498), Tests 13609 passed (13609), Duration 490.99s; lock printed 'VERDICT command-exit 0 · held the lock 779s · waited 339s'. PROOF THE PIN FILE RAN (the point of item (a)): platform-object-names.test.ts is entry 27 of the 28 in vitest.repo-tests.json, so the 'local' project EXCLUDES it and 'pnpm test' alone would never have run it — the verbose reporter shows all 9 of its cases tagged '|repo|', including by name 'resolves the middle table of the cloud package family', with the pre-existing sys_license sibling case lit beside it as control. ABLATION (predecessor declined it; run here, direction predicted as 'turns red' before running, both legs under the lock with a bash trap on EXIT INT TERM calling a restore function and absolute paths): HEAD blob f691ad79; marker count 1 -> 0 proving the edit reached disk; the mutated file hashed to 6aff7752, byte-identical to the pre-fix blob this PR replaced; MUTATED leg exit 1 with 'Tests 1 failed | 8 passed (9)' and 'AssertionError: sys_package_version: expected false to be true'; restore anchored at HEAD reproduced f691ad79 with an empty 'git diff HEAD'; RESTORED leg exit 0 with 9 passed (9). Exactly one of nine cases moved and it is the new one. OTHER (same acquisition, exit codes landed to disk before being read): build 0, typecheck 0, check:generated 0 with git status clean. Closure (1) is empty by construction — @objectstack/spec declares no @objectstack/* workspace dependency. GATES (3)/(4): derived mechanically, never hand-fed — 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' at 87751f84e produced 77 commands from a 3-path change set vs merge base 4261fbc80; all 77 run; reconciliation 'dispatch-gates --ran: 77 derived famil(ies) accounted for — 77 run, 0 NOT-MEASURED, 0 UNRUN'. 73 exited 0. FOUR exited 3 = PREREQUISITE NOT MET, recorded NOT MEASURED, neither green nor red, all for absent built output of OTHER packages that CI builds fresh: lint check:doc-formula-expressions (@objectstack/formula not built), check:dual-build-cjs-loads, check:lean-entry-closure (packages/objectql/dist/core.mjs), check:type-check-debt. One earlier ablation attempt returned the lock's exit 99 queue-timeout — discarded as NOT MEASURED, never as a pass; the tree was verified untouched and the run was re-taken on the SAME slot, which resumed the place rather than re-queueing. check:nul-bytes 0, plus an independent grep -naP control-character sweep over the three changed files: clean. Repo-wide 'pnpm lint' is CI's run, not attempted here. CHANGESET RE-DERIVED, not inherited: platform-object-names.ts is not a .zod.ts so it ships no source under files[], but src/system/constants/index.ts re-exports it, so it ships COMPILED in dist (which IS in files[]) — measured on the rebuilt dist, 1 hit in each of dist/system/index.mjs, dist/system/index.js, dist/index.mjs, dist/browser/system/index.mjs, control sys_license 1 each, negative control 0. Published behaviour moves, so skip-changeset does NOT apply; no export added or removed and no authorable key changes, so patch. CI's Check Changeset is green on this grade at the merged head. CI READ MYSELF, newest run per check name on the final head 87751f84e (not the raw run list, not the required subset): 9 success, 5 skipped, 17 in_progress, ZERO failures at report time — Check Changeset, Governed Surface Queue Guard, Part-of PR must not also close its card, Spec property liveness and the claim guards already green. The pre-merge head f4415dc86 had previously gone fully green: 31 success, 3 skipped, 0 failure.", "mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (probe returned 200) plus git; no MCP GitHub tool was called", "open_questions": [], "out_of_scope_findings": [ "NOT MEASURED, for the seat to file cross-repo (⛔ not filed by me, per dispatch): that @objectstack/service-tenant actually registers sys_package_version. That half lives in the `cloud` repository, which is NOT REACHABLE from this session, and the list's own header says it cannot be conformance-tested from this repo. It is recorded as NOT MEASURED — never as verified, and nothing this repo can prove was substituted for it. 承接者: the seat, filing the cross-repo conformance card against `cloud`.", "noted, not filed: scope-fence sweep for sibling absences found NONE. Re-run on the rebuilt dist against PLATFORM_PROVIDED_OBJECT_NAMES over 112 shipped *.object.ts files under packages/ + examples/: 135 reference targets, 109 platform-prefixed, 0 unregistered. Controls lit: sys_user appears 61 times, registry.has('sys_definitely_not_real') false, registry.has('sys_package_version') true (the last also proving the dist read was the rebuilt one). This reproduces the card's 'exactly one finding in the whole universe' measurement and brings it to zero. The PR was NOT widened. 承接者: none needed — nothing found.", "noted, not filed: packages/spec/src/cloud/environment.zod.ts names sys_environment_credential and tenant.zod.ts names the deprecated sys_tenant_database; neither is in CLOUD_PROVIDED_OBJECT_NAMES and both are referenced by ZERO shipped *.object.ts files, so no false refusal reproduces today — that absence of a shipped reference is exactly what separates them from this card and is why they are not filed. 承接者: the seat filing the cross-repo card carries the question alongside.", "noted, not filed: check-widening-tells' T2 matcher fires on this diff and check-clause2-carriers --pair 17214 exits 4, because the tell reads ADDED LINES ONLY and has no notion of direction — it cannot see that adding a name to a curated allowlist DELETES a false refusal. Reading re-taken on this head after origin/main moved that script by 143 lines, so it is current, not inherited. Not a CI red: lint.yml wires only --self-test for both check:pm-clause2-carriers and check:pm-widening-tells, and its own comment calls --pair 'deliberately not a merge gate'. Per the gate's own header the repair for a demonstrated false positive belongs in the matcher, not in the declaration. 承接者: the seat that owns scripts/pm/check-widening-tells.mjs.", "noted, not filed (platform reading, may be worth the fleet's ledger): updating a PR body via REST PATCH /pulls/{n} APPENDED a second, bare-form '_Generated by [Claude Code](https://claude.ai/code)_' footer BELOW the session-URL footer that was sent, even though the sent block carried its rule line in the correct form. Caught only by the mandatory full read-back; the body content itself survived byte-for-byte (all probes present, line 1 still the closing line naming this card). Left as-is rather than re-patched, since re-posting footers in a loop is exactly what the contract forbids. 承接者: the seat maintaining pm-dispatch references/platform-readings.md." ] }Generated by Claude Code
os-bill commentedon Sep 9, 2026
⛔ My
Clause-②: nowas WRONG — reversed toyes, gate hung on both carriersdomain:specseat,session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-09T18:4xZ. The delivery is sound; the defect is in my dispatch order, for the fourth time this shift and by the same mechanism.The reading that overturned me — run by this seat, ⛔ not taken from the report
Landing pre-check ② requires exit 0. This is exit 4. ⇒ ⛔ This PR cannot land on my declaration, and the standing rule says it plainly: a
nothat hits a new member is refused, with file:line. The tell names the member and the line.⭐ Why the tell is right and I was not
My claim comment argued the addition "deletes a false refusal rather than widening an accept set", and cited the list header as
Contract-text:. I re-read that header today:sys_package_versionis a member of it. The clause-② carve-out I invoked requires the published text to itself deny the refusal being deleted — and this text denies nothing about this name. It states a purpose, and a purpose is not an enumeration.⇒ Mechanically and substantively, the lint ladder now accepts a name it previously warned on. The accept set gains a value. That is a widening, and it takes
yes.⛔ I also checked whether the checker's "or explain in the claim" offers a machine-readable waiver. It does not — that phrase is guidance to a reader, and no marker in the script parses an explanation. So a prose argument, however good, cannot clear C5. It should not be able to.
I reported to the maintainer twice that this was "the only card in flight that can land without contract-review-tier budget". That is false. With
yesit needs aCONTRACT_REVIEW_TIERPASS exactly like its three siblings, and that tier is currently exhausted. ⇒ Nothing in this lane lands until Fable budget returns, and I removed the one exception by getting it wrong rather than by anything changing.Same root as my three earlier defects this shift: I decided a declaration from the consequence I was thinking about, and did not re-derive it against the mechanical rule that already had an answer. The pattern is now four for four, and the fix is not more care — it is running
--pairat claim time rather than at landing time, which would have caught this before a dev spent a round on it.Carriers, read back after the write
needs:contract-reviewhung on both: card['bug','domain:spec','finding','needs:contract-review','pm:dispatched','priority:p3']with assignee intact, PR #17214['documentation','needs:contract-review','protocol:system','size/s','tests','tooling'].⛔ The changeset must move with the declaration
Clause-②: yesagainst a diff that movespackages/spec/src/**requires the changeset atminoror above; it is atpatch. Leaving the declaration and the grade inconsistent is a hardCheck Changesetred — the exact failure this lane hit twice today. ⇒ A narrow patch round follows to move both together, and the level is the dev's to derive, withminoras the floor the gate imposes.⭐ What the delivery got right, recorded so it is not lost in a reversal
git diff. Exactly one case moved and it is the new one.platform-object-names.test.tsis entry 27 of 28 invitest.repo-tests.json, so thelocalproject excludes it andpnpm testalone would never have run it. The full suite was run instead — 498 files, 13609 tests — and the verbose reporter shows all nine of its cases tagged|repo|by name, with thesys_licensesibling lit beside them as control. ⇒ That is a proof the file ran, not an assertion that it did.Out-of-scope items this seat now owes
cloud— that@objectstack/service-tenantregisterssys_package_version. Correctly recorded NOT MEASURED, ⛔ never verified and ⛔ never substituted with something this repo can prove.cloudis unreachable from this session, so it lands here as a seam card with a named reader.sys_environment_credentialand the deprecatedsys_tenant_databaseare also absent from the list, and referenced by zero shipped*.object.tsfiles — which is precisely why they are not this card. That absence is the discriminator and it belongs in the same question.scripts/pm/check-widening-tells.mjs's owner.platform-readings.mdline: a RESTPATCH /pulls/{n}appends a second bare footer beneath a sent session-URL footer. Caught only by the mandatory read-back; ⛔ correctly left rather than re-patched.Generated by Claude Code
os-bill commentedon Sep 9, 2026
os-dev-report
{ "issue": 16745, "status": "blocked", "branch": "claude/issue-16745-cloud-provided-package-version", "pr": "https://github.com/objectstack-ai/objectstack/pull/17214", "premise_still_valid": true, "summary": "The three narrow edits landed on head df37e6564 and nothing else in the PR moved: the PR body now carries a line-start `Clause-②: yes` with the `Contract-text:` line and its backing sentence removed, and the changeset is regraded `@objectstack/spec: minor` with prose that no longer frames the addition as restoring something the published header already promised. The source line, the pin, the ablation and the sweep are untouched — both source blobs hash identically at 87751f84e and df37e6564 (platform-object-names.ts f691ad7939dac77330995e3d9db49e95182ad5db, its test b2a4cde719761206871181f1ff358753b2371ab9), so this round's whole diff against the previous head is one .changeset/*.md. BLOCKED on one PM-only act, and it falsifies a mechanism assumption in the dispatch order: `--pair` still exits 4, because C5 does NOT read the PR body. Its declaration limb is `cardDeclaration()` over the CARD's comment thread, and the single claim-shaped comment on card #16745 is 5605472270 (the seat's dispatch claim), which still carries a line-start `Clause-②: no`. Measured, with a lit control: `cardDeclaration()` over the real thread returns {state: declared, value: no}; the same reader over the same thread with that one line flipped returns {state: declared, value: yes}. The seat's reversal comment 5607037446 is not claim-shaped, so it carries no declaration for this reader. The checker's own header forbids me from writing it (\"do not write the declaration on the claiming seat's behalf; the declaration IS the judgement\"), and the brief forbids a second Claim, so it is reported rather than routed around. Only the claiming seat editing comment 5605472270 (or posting a newer governing claim) moves `--pair` to 0. PR left draft, `needs:contract-review` untouched on both carriers, not enqueued.", "tests": "CHANGESET LEVEL, derived not taken: floor #1 — pr-automation.yml 'WHICH LEVEL' (maintainer ruling 2026-09-04, batch #35 on #15294): a purely additive widening of a published package's public surface, 'a new accepted key OR VALUE', takes at least `minor`; floor #2 — check-changeset-no-major.mjs level axis: a PR declaring clause ② must grade at least one package whose published src it moves `minor` or above, and @objectstack/spec is the only package this diff moves; ceiling — `major` is refused outright by the same script's launch-window guard, no `allow-major` label on the PR and no .changeset/pre.json so the RC exemption is not in effect. Floor meets ceiling at `minor`, the only legal grade. No ADR-0087 disposition owed: that gate's breaking signals are a `major` bump or a `**BREAKING` / `BREAKING CHANGE` body marker, and this changeset carries neither (gate's own line: 'this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)'). || --pair EXIT CODE: 4, both before and after the edits (scripts/pm/check-clause2-carriers.mjs --pair 17214), same C5/T2 row at platform-object-names.ts:156. Cause proven above with a lit control, not argued. || CHECK CHANGESET, read by me as newest-run-per-check-name on head df37e6564: conclusion SUCCESS (run started 19:17:59Z, the `edited` trigger my body write fired; the earlier 18:55:14Z run on the same head is also success). Its own log line, quoted from job 102609774531: '✓ LEVEL AXIS: this PR declares clause-② `yes`, and no package whose `packages/**/src/**` it moves is graded `patch`. · carrier: `needs:contract-review` IS on this PR · declaration line: `Clause-②: yes`'. So the axis FIRED and read the new body line — it did not stand down into a silent green. || LEVEL-AXIS CONTROL, lit locally on the live payload: the same script run with --event built from the PR as read back after the write exits 0 with the identical 'LEVEL AXIS' line. A first ablation attempt mutating the changeset in the WORKING TREE was a NO-OP and is reported as such rather than silently re-run: marker minor 1 to 0 and the hash moved, proving the edit reached disk, yet the verdict did not move — this gate reads git blobs, not the tree. Restored, hash back to the HEAD blob, `git diff HEAD` empty. The control was then built correctly as a real commit object with `git commit-tree` over a temporary index (real HEAD and index never touched, `git diff HEAD` empty throughout): same tree, changeset graded `patch`, exit 1, verdict 'This PR declares clause-② YES, and it grades NO package ... at `minor` or above'. The commit is dangling, on no branch, never pushed. || MERGE: origin/main had moved to bccf31110; merged through scripts/pm/os-regen-merge.sh, merge commit df37e6564, no os-regen path needed a side taken, no generated artifact moved, `git status` clean. || ② PACKAGE LEVEL on the final head, under os-verify-lock slot issue-16745-patch, exit codes echoed individually rather than read from the wrapper's `;`-batch verdict: BUILD_EXIT=0, TYPECHECK_EXIT=0 (tsc + scripts tsconfig + check:test-typecheck). Full suite re-taken on df37e6564, NOT carried over: `pnpm --filter @objectstack/spec exec vitest run --reporter=verbose --maxWorkers=2` — Test Files 498 passed (498), Tests 13609 passed (13609), Duration 561.78s, 'VERDICT command-exit 0 · held the lock 563s · waited 0s'. All nine cases of platform-object-names.test.ts appear tagged |repo| by name, including the new 'resolves the middle table of the cloud package family' and the sys_license sibling beside it as control — that file is a vitest.repo-tests.json entry the `local` project excludes, so this is proof it RAN. || ① dependency closure: @objectstack/spec declares no @objectstack/* workspace dependency, so the closure build is empty by construction; the package itself was built. || ③/④ GATE FAMILIES, derived mechanically with no hand-fed path list: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at commit df37e6564, change set 3 paths vs merge base bccf31110 (three-dot), 77 commands. All 77 run on the final head with each exit code landed to a file BEFORE being read: 73 exited 0, 4 exited 3 = PREREQUISITE NOT MET, recorded NOT MEASURED (neither green nor red) — lint check:doc-formula-expressions, check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt, all four because they read built output for packages this worktree has not built. Reconciled: `dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.txt` → '77 derived famil(ies) accounted for — 77 run, 0 NOT-MEASURED, 0 UNRUN.' check:nul-bytes exited 0. Repo-wide `pnpm lint` is CI's run and was not attempted. || NO QUEUE-TIMEOUT was read as a pass: the only lock waits this round were 63s and 0s, both ACQUIRED. || CI on df37e6564, newest run per check name: Check Changeset success, Build Core success, Test Core success (all 6 shards), TypeScript Type Check success, all four Type Check jobs success, Dogfood Regression Gate success (all 3 shards), Dogfood Verify CLI success, Temporal Conformance success, Governed Surface Queue Guard success, Spec property liveness success, the three PR-hygiene guards success; 'Lint & Repo Gates' is in_progress at report time and is reported as in_progress, not as green. || PR BODY read back after the write: the 14412 bytes I sent survived byte-identical; GitHub appended one extra bare footer beneath the session-URL footer, which is the already-recorded REST PATCH /pulls/{n} behaviour — left as-is rather than re-patched in a loop. Body confirmed still draft, labels unchanged including needs:contract-review, exactly one line-start `Clause-②:` line and it reads `yes`, no `Contract-text:` line, no angle-bracket-shaped fragment anywhere in the text.", "mcp_calls": "1 — one get_job_logs to quote CI's own LEVEL AXIS line; every other GitHub read and the PR body write went through the container's REST channel (repo-scoped probe http=200 at the start of the round).", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the two clause-② readers take DIFFERENT carriers, and nothing warns an operator who conflates them. check-changeset-no-major.mjs's level axis reads the PR body plus labels from the pull_request payload (by design, so it needs no token in a required gate); check-clause2-carriers.mjs's C5 reads the card's governing claim comment and nothing else. Editing only the PR body therefore turns Check Changeset green while leaving --pair at 4, which is exactly the state this PR is now in. Neither reader is wrong and each documents its own choice in its own header, so this is not a defect and is not filed. 承接者: the seat, alongside the check-widening-tells.mjs card it already owes.", "noted, not filed: check-changeset-no-major.mjs reads head-side changeset content from git blobs, not from the working tree, so the ordinary working-tree ablation shape is a silent no-op against it — the mutation reaches disk, the marker count moves, and the verdict does not. Measured here, reported rather than re-run until something landed. The working control is a commit object built with `git commit-tree` over a temporary index. 承接者: the next agent asked to ablate a changeset-scoped gate.", "noted, not filed: the C5 remedy text prints 'or explain in the claim why this addition does not widen', and the seat measured that no marker in the script parses such an explanation. An operator taking the second branch of that printed remedy gets no change in verdict. Recorded here as a second sighting; the seat has it. 承接者: the seat's owed check-widening-tells.mjs card.", "noted, not filed: the REST PATCH /pulls/{n} duplicate-footer behaviour reproduced again on this round's body write — one bare footer appended beneath the session-URL footer I sent. Caught by the mandatory read-back, left rather than re-patched. 承接者: the seat's owed platform-readings.md line, which already names it." ] }Generated by Claude Code
os-bill commentedon Sep 9, 2026
--pair 17214now exit 0 — the block was a PM-only act, and the dev was right to refuse itdomain:specseat,session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-09T19:2xZ.⭐ The round found a mechanism I had wrong, and refused to route around it
I assumed flipping the PR body would clear C5. It does not.
check-clause2-carriers's C5 reads its declaration limb throughcardDeclaration()over this card's claim comment — ⛔ not the PR body, and ⛔ not a later seat comment however clearly written. So my reversal comment5607037446carried no declaration for that reader, and the governing claim5605472270still saidno.The dev proved it with a lit control rather than arguing it:
cardDeclaration()over the real thread returned{declared, no}; the same reader over the same thread with that one line flipped returned{declared, yes}.⭐ And then it stopped. The checker's own header forbids writing the declaration on the claiming seat's behalf — "the declaration IS the judgement" — so it reported the block instead of clearing it. That is exactly right: an agent that had "helpfully" edited my claim would have issued my judgement for me, which is the 自查放行 failure the header exists to prevent.
What I did, and why it is an edit rather than a new comment
Corrected the declaration in claim comment
5605472270itself, because that is the only carrier the checker reads. The withdrawn reasoning is not erased: the comment now says plainly that its originalnoand itsContract-text:citation are withdrawn, quotes the measurement that overturned them, and points at5607037446. Editing keeps exactly one claim-shaped comment on the card, which avoids handingcardDeclaration()an ambiguity to resolve.Read back after the write: one line-start
Clause-②: yes, ⛔ noContract-text:line,Claim:intact.Landing pre-checks now
node scripts/pm/check-clause2-carriers.mjs --pair 17214→ exit 0, "the declaration is readable in the fixed spelling and both carriers agree" (was 4)df37e6564, newest run per name: 29 success + 5 skipped, 0 red, 0 in progress"@objectstack/spec": minor— consistent with theyes⇒ Two of three pre-checks pass. ⛔ The PR does not land until a
CONTRACT_REVIEW_TIERPASS exists. The quota exemption covers dispatch, never review.⭐ How the grade was derived, which is the part worth reusing
Not chosen — bracketed. Floor one: the maintainer's 2026-09-04 ruling that a purely additive widening of a published surface, "a new accepted key or value", takes at least
minor. Floor two: the changeset gate's own level axis, which requires a clause-②yesto grade at least one moved-src package atminoror above. Ceiling:majoris refused outright by the launch-window guard, with noallow-majorlabel and nopre.json. Floor meets ceiling at exactly one legal grade.And the gate was confirmed to have actually judged it rather than standing down into a silent green — its own log line reads
✓ LEVEL AXIS: this PR declares clause-② 'yes', and no package whose packages/**/src/** it moves is graded 'patch'. This lane has been burned twice today by a green that never asked the question.The first ablation attempt mutated the changeset in the working tree and was a silent no-op: the marker count moved, the file hash moved, and the verdict did not — because that gate reads git blobs, not the tree. Rather than re-run until something moved, the round reported the no-op and rebuilt the control properly with
git commit-treeover a temporary index (real HEAD and index untouched, dangling commit, never pushed). Then it failed correctly: exit 1, "declares clause-② YES, and it grades NO package … atminoror above".⇒ A control that does not move the verdict is a broken control, ⛔ not a passing gate.
Two carriers, two readers, one operator trap
The round named the thing that actually cost this card a round: the two clause-② readers take different carriers. The changeset gate's level axis reads the PR body and labels from the payload, by design, so it needs no token in a required gate. C5 reads the card's claim comment. ⇒ Editing only the PR body turns
Check Changesetgreen while leaving--pairat 4 — precisely the state this PR sat in for half an hour.Neither reader is wrong and each documents its own choice. ⛔ Not filed as a defect. It goes into the
check-widening-tells.mjscard this seat already owes, as the operator-facing half.Generated by Claude Code
os-bill commentedon Sep 9, 2026
达档契约复核判 PASS —— 无绑定项;⭐ 复核先替我的
no辩护,再驳回它domain:spec席,session_01MkQhmuuJAVDjmeWNixwDDH,2026-09-09T22:1xZ。档位熔断:transcript 中 harness 逐消息盖章 59 条claude-fable-5-1,零其它值(对照"type":"assistant"51 条)。⇒ 达档,逐字采信,⛔ 未改写。⭐ 它没有采信本席的反转,而是自己重判了方向
我明确要求它「⛔ 不要把这段历史当成权威定案」,若认为
no才对就带读数说出来。它照做了,先替no辩护——然后驳回,理由是读数而非权威:⇒ 与本席
5607037446的自我推翻同结论,但路径独立。谓词接受集 90 → 91,四个消费者中三个行为随之变化。⭐ 它还找到了一个本席和实现者都漏掉的消费者面
packages/objectql/src/engine.ts:7792resolvePrimaryDatasource()是运行时消费者,遍历这个 Set 为「主数据源」投票。changeset 写的是「every surface that consults the predicate」——而这一处读的是 Set 本身,不走谓词。system-objects-split。三表同插件注册时不可能分裂,但这恰好是本仓测不到的那一半。⇒ 已按裁决建议补问,见下。它给 #17233 的起读点(⛔ 仍不是读数)
git show origin/main:CHANGELOG.md | sed -n '1163p'有分裂前的仓内条目,记createTenantPlugin()注册sys_package、sys_package_version、sys_package_installation;ADR-0003:194 记 service-tenant 于473fce590(2026-05-21)迁出本仓。⛔ 这仍是 NOT MEASURED——分裂前的历史不是当刻 cloud 的读数——但 cloud 席可以从这里起读,省一次摸索。三处 NOT MEASURED 的措辞被逐处查过
PR body、changeset、测试注释三处都写明未验证,且 ⛔ 没有任何一处拿
cloud/package-version.zod.ts当注册证据(那是形状声明,不是注册)。这是本席最担心的替换,复核确认没有发生。裁决另附两项非绑定(#17233 追加 datasource 一问、PR body 里一段已过时的
--pairexit 4 描述与 changeset「refused/warn」措辞不一致)。⛔ 均不阻塞落地。下文自
PASS起为裁决原文。PASS
① derived judgments — 每处 accept-set / published-face 变化
git diff --stat $(git merge-base df37e6564 origin/main)...df37e6564→.changeset/spec-cloud-provided-package-version.md +28,platform-object-names.test.ts +17,platform-object-names.ts +1;merge-base =bccf31110(与 PR base 一致)。blob:platform-object-names.ts在 headf691ad79…、在 base6aff7752…(与实现者报的消融前后哈希一致)。CLOUD_PROVIDED_OBJECT_NAMES增一员 ⇒PLATFORM_PROVIDED_OBJECT_NAMESSet 增一员 ⇒isPlatformProvidedObjectName('sys_package_version')false→true。 已发布面:git grep … origin/main -- packages/spec/api-surface/system.json列CLOUD_PROVIDED_OBJECT_NAMES (const)第 87 行、PLATFORM_PROVIDED_OBJECT_NAMES (const)第 482 行、isPlatformProvidedObjectName (function)第 790 行;export-origins/system.json同。三个符号均已发布,值变、符号不变,check:generated无产物需动(CILint & Repo Gatessuccess)。git grep -nP "isPlatformProvidedObjectName|PLATFORM_PROVIDED_OBJECT_NAMES" origin/main -- packages …):packages/lint/src/validate-object-references.ts:226— 阶梯 ③return;此前该名落 ④severity: 'warning'(:231)object-reference-unregistered-platform。这是卡面所述的那一处。packages/lint/src/validate-translation-references.ts:803— 以该名为键的翻译子树从 orphan 变为 skip。同向 widening。packages/lint/src/validate-nav-access.ts:162—continue;但紧随的:163 if (!ownObjects.has(objectName)) continue;对非本 stack 对象一样跳过,此处行为无净变化。packages/objectql/src/engine.ts:7792— 运行时消费者,resolvePrimaryDatasource()遍历该 Set,对本部署已注册的平台对象投票。yes是对的,T2 在此不是误报。 我试图为no辩护:「删除一个假拒绝」。读数不支持——阶梯头注(validate-object-references.ts:56-70)把 ④ 定义为「prefixed, NOT in the registry → WARNING」,registry 是「curated set of real names」(platform-object-names.ts:19);列表头注只陈述目的,不枚举成员,已发布文本中没有任何一句「否认」对该名的告警。谓词的接受集从 90 个名字变成 91 个(我的 sweep 读数registry size: 90 → 91),四个消费者中三个的行为随之变化。「假拒绝」是对同一动作的价值判断,不是对方向的判断;clause-② 问的是方向。⇒yes,T2 命中正确。[finding] Clause ② is read from two different documents by two gates with nothing joining them — a card declaringnoand a PR body declaringyespasses both, and--pair's green line says 「both carriers agree」 about the LABELS, not the declarations #16770 上的 direction-blindness 观察仍成立(T2 只读+行),但这里方向恰好与其假设一致。origin/main(fetch 后87ad73b06)上重推:git show origin/main:…/platform-object-names.ts | sed -n '149,156p'→ 六个成员,sys_package与sys_package_installation在,sys_package_version不在。git grep -nP "\bsys_package_version\b" origin/main -- packages/metadata-core/src/objects/sys-metadata.object.ts→ 3 hits::73是 docblock,:80是 description 字符串,:76是package_version_id: Field.lookup('sys_package_version', {——我看了每一条命中,只有:76是活代码,且位于ObjectSchema.create({ name: 'sys_metadata', … fields: { … } })之内(sed -n '1,20p;60,95p'),不是注释也不是墓碑。控件:同文件Field.lookup('sys_\w+'另有sys_organization/sys_environment/sys_user×2。该对象已发布:packages/metadata-core/src/objects/index.ts:19导出SysMetadataObject,package.json files[]含dist。② semver 定级 — 等级 vs 声明;每个 gate 是「判了」还是「没触发」
git show origin/main:.github/workflows/pr-automation.yml | sed -n '712,725p':「A purely additive widening of a published package's public surface (a new exported symbol on anindex, a new accepted key or value) takes at leastminor… Ruled by the maintainer on 2026-09-04 (decision batch #35) on #15294」check-changeset-no-major.mjsjudgeLevel(sed -n '1380,1440p'):refusable = offenders.length > 0 && raised.length === 0;declaration.value === 'yes'且 refusable ⇒verdict: 'enforce'exit 1。@objectstack/spec是唯一被移动packages/**/src/**的包 ⇒patch必红minor,机制成立sed -n '705,725p':case 'enforce'对majorexit 1,除非allow-majorlabel 或pre.json mode: pre。CI job102609774531日志:Labels on PR #17214 right now: documentation size/s tests tooling needs:contract-review protocol:system(无allow-major);git ls-tree --name-only df37e6564 .changeset/ | grep -c '^\.changeset/pre\.json$'→ 0(控件README.md→ 1)major被拒minor;changeset 头"@objectstack/spec": minor(git show df37e6564:.changeset/spec-cloud-provided-package-version.md)level axis 确实判了,没有 stand down:
get_job_logs 102609774531原文——按
renderLevel(sed -n '1470,1560p'),这一行只在verdict: 'clean'分支打印,而'clean'只在declaration.value === 'yes'且offenders.length === 0时返回;「declaration line: …」只在line.kind === 'declared'时推入(:1298)。三个 not-measured / no-pull-request 分支各有不同措辞,此处均未出现。C5 双载体: 我自己跑了(
git archive origin/main scripts package.json导出到 scratchpad,node scripts/pm/check-clause2-carriers.mjs --pair 17214)→✓ … the clause-② declaration is readable in the fixed spelling and both carriers agree.EXIT=0,token 路径 3 reads。读cardDeclaration(:696-740):先取 governing claim(5605472270,已编辑为 line-startClause-②: yes),再读整线程——与席位的读数一致。其他 changeset gate 在 CI 同 job:check-empty-changeset ✓ (1 declaring),check-adr-0087-registration ✓ (1 non-breaking),✓ This diff introduces no major bump。C. Pin。 读
git show df37e6564:…/platform-object-names.test.ts全文:新 case 循环三名,expect(isPlatformProvidedObjectName(name), name).toBe(true)。消融推演:去掉那一行后,sys_package通过、sys_package_version抛sys_package_version: expected false to be true(vitest 把第二参数作为前缀,与报告的断言文本逐字一致);其余 8 例——cloud-only names…只遍历列表现有成员,every registered name…只查前缀,registers exactly the objects each package declares只比PLATFORM_OBJECTS_BY_PACKAGE——都不读缺失的名字,故恰好 1/9 变红。修复后cloud-only names are registered but not declared in this repo要求sys_package_version不被任何packages/**/*.object.ts声明:我的 sweepdeclared own names: 110,其中不含该名(它在 pre-fix 落入 UNREGISTERED 而非 own)。vitest.repo-tests.json第 28 行为该文件,vitest.config.tslocal项目exclude: [...REPO_TESTS]——实现者对「pnpm test不跑它」的判断成立;全套件运行本身 NOT MEASURED(无node_modules),我以 CITest Core (1/6..6/6)六片 success + 源码推演替代判断,不替代运行。③ 边界旗处置
@objectstack/service-tenantactually registersys_package_version? The spec-side allowlist now says it does, and this repo cannot check #17233)。 读 PR body、changeset、test 注释三处:body「NOT MEASURED here — not verified, and not substituted」;changeset「is not asserted from here」;test「is not asserted here」。⛔ 无一处把package-version.zod.ts当注册证据(body 只用它论证「家族中间表」)。[seam → cloud] Does@objectstack/service-tenantactually registersys_package_version? The spec-side allowlist now says it does, and this repo cannot check #17233 已开,repo:cloud,命名读者 cloud seat,且明确拒绝了 zod 替代。答:处置正确。 ⭐ 补一条给 [seam → cloud] Does@objectstack/service-tenantactually registersys_package_version? The spec-side allowlist now says it does, and this repo cannot check #17233 的指针(非替代):git show origin/main:CHANGELOG.md | sed -n '1163p'有历史条目「@objectstack/service-tenant— system objects now actually register —createTenantPlugin()… (sys_project, …,sys_package,sys_package_version,sys_package_installation,sys_tenant_database)」,且 ADR-0003:194 记 service-tenant 于473fce590(2026-05-21)迁出本仓。这是分裂前的仓内证据,仍不是当刻 cloud 的读数——仍 NOT MEASURED,但 cloud seat 可从此处起读。sweep.mjs走 git tree(不碰工作树):node sweep.mjs origin/main→ 112 个*.object.ts(110 去掉 qa/create-objectstack)、139 个引用目标、113 平台前缀、1 unregistered =sys_package_version←sys-metadata.object.ts;node sweep.mjs df37e6564→ 0;node sweep.mjs origin/main df37e6564(当刻 main 语料 + 修后常量)→ 0。控件:sys_user65、registry.has(sys_definitely_not_real)=false、registry.has(sys_approval_process)=false、registry.has(sys_package_version)false→true。我的 139/113/65 比实现者的 135/109/61 各多 4——我额外计入reference: '…'键与Field.user();结论同一:没有第二个缺失成员,围栏没有过紧。sys_environment_credential/sys_tenant_database——已并入 [seam → cloud] Does@objectstack/service-tenantactually registersys_package_version? The spec-side allowlist now says it does, and this repo cannot check #17233 表格;我的 sweep 在*.object.ts中对二者零命中(同一控件点亮)。答:处置正确。noand a PR body declaringyespasses both, and--pair's green line says 「both carriers agree」 about the LABELS, not the declarations #16770):见 ①;本例方向恰对,观察本身成立。无需本 PR 动作。engine.ts:7792 resolvePrimaryDatasource()运行时面。 该 Set 增员后,cloud 部署中若 service-tenant 注册了sys_package_version,它开始参与「主数据源」投票;若其 datasource binding 与sys_package/sys_package_installation不同 ⇒system-objects-split⇒ 按裁定向 draining 失败。三表同插件注册时不可能分裂,但这恰是 [seam → cloud] Does@objectstack/service-tenantactually registersys_package_version? The spec-side allowlist now says it does, and this repo cannot check #17233 无法从本仓测的另一半。建议 [seam → cloud] Does@objectstack/service-tenantactually registersys_package_version? The spec-side allowlist now says it does, and this repo cannot check #17233 追加一问:三表绑定同一 datasource。 changeset 的「every surface that consults the predicate」措辞漏了这个读 Set 的消费者。--pairstill exits 4 on this head」一段已过时——席位编辑 claim 后我测得 exit 0。body 是edited事件前写的,描述的是当时状态,不构成误导,但合并前顺手删掉更干净(非绑定)。changeset 第 10 行「The name was previously refused」与第 12 行「used to warn on」自相矛盾:阶梯 ④ 是severity: 'warning',不是拒绝(非绑定措辞)。cli.mdx:1712、publish-and-preview.mdx:144:两处都把sys_package_version当 cloud 表叙述,与新列表一致;git grep -c sys_environment_member df37e6564 -- content/docs docs显示无任何文档逐条枚举六名列表,无文档需改。needs:contract-review、assigneeos-bill;唯一 claim 形注释5605472270,分支名匹配 PR head ref;PR labels 含needs:contract-review;Part-of PR must not also close its cardsuccess(body 首行Fixes #16745,是 closing PR 而非 part-of)。node_modules);sys_license前例 commit(checkout 为 shallow,git log … | wc -l= 1)——从 test 内注释判断同类,未读原 PR。非绑定项汇总: ③-5(#17233 追加 datasource 一问,changeset 措辞漏运行时面)、③-6(body 过时段落、changeset「refused」措辞)。无绑定发现。
Generated by Claude Code