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
metadata-protocol: fold the two overlay-write close predicates (namedBaseCloseSubject, packagelessCloseSubject) into one fix-can-be-taken predicate #29397
Source: the contract review of PR #29270 (#28905), record 6577747588, should-fix S6 (the dev's open question 3, answered A). #28904 has landed (#29258), which was the precondition.
namedBaseCloseSubject (protocol-packaged-base-refusal.ts, #28905) and packagelessCloseSubject (protocol-packageless-overlay-migration.ts, #28576) agree step for step on whether the pair fix can be taken: the pair id derives, customizationPairEnsureRefusal answers none, the base records a manifest.version, and the D2 gate admits the declared body. They differ only where intended: the named close reads no row and accepts a named package among several shippers, while the package-less close requires exactly one shipper and classifies the stored row.
Ask: one shared predicate for the common steps, with each close keeping its own intended difference. This is a refactor with no behaviour change: both closes' pins pass unchanged, and the sentence spelling (closedOverlayWriteClauses) is untouched. Serial with the S1 card (same module).
Read fresh. Fold the two overlay-write close predicates (namedBaseCloseSubject, packagelessCloseSubject) into one fix-can-be-taken predicate. A refactor, p3. ⛔ Move-only: no refusal may change.
Claim: PM loop round 1 · card thread · 2026-11-03T07:16Z
Session: session_01JQwxbXKRzgnVvjzxaYxLUf (the seat); the card thread is session_01JQwxbZz2XXsYuaJz9sPuGU
Account: os-warren
Branch: claude/project-thread-a7zbyk
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#2
File surface: packages/metadata-protocol/src/protocol-packaged-base-refusal.ts, protocol-packageless-overlay-migration.ts, their tests; call sites only in protocol.ts if any; a changeset only if published behaviour changes (expected none)
Container & model: card thread, mode:thread, model: TIER_DEFAULT (--tier names no path mandate), effort: project default
Clause-②: no
Metadata-protocol: none
Responsibility: metadata-protocol overlay-write closes (#28905 / #28576, this lane) | two predicates repeat the same four fix-can-be-taken steps, so a change to one can silently drift from the other | refactor, move-only: both closes' pins pass unchanged and no refusal sentence moves
Thread-read: 6592695895
Premise: holds (seat read on origin/main: namedBaseCloseSubject and packagelessCloseSubject both live and both referenced from protocol.ts)
Serial constraints cleared: #29479 (same module, the refusal sentence) is queued and not dispatched; if it is dispatched, the seat sequences the two. No open PR touches either module.
{
"issue": 29397,
"status": "done",
"branch": "claude/project-thread-a7zbyk",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29874",
"session": "session_01JQwxbZz2XXsYuaJz9sPuGU",
"premise_still_valid": true,
"summary": "Measured on main 42ff86f6 first: every step of namedBaseCloseSubject (protocol-packaged-base-refusal.ts:390-424) and packagelessCloseSubject (protocol-packageless-overlay-migration.ts:725-779) is common or intended-different; no step differs by accident (table in the PR body). Two spellings differ with the same answer: the base version (inline getPackage vs baseVersionOf re-reading engine.registry, one never-reassigned getter) and the member of the declared body (isPlainRecord(item) vs item !== undefined, equal for every JSON body; left per close). Folded into overlayPairFixOf (pair id, registry, ensure door, basedOn) and overlayPairFixAdmits (the D2 gate on the declared body) in protocol-packaged-base-refusal.ts, two halves so the package-less close's row read stays between them (call order and which failure wins unchanged); each close keeps only its own difference. protocol.ts, closedOverlayWriteClauses and every refusal sentence untouched; return shape { base, pair } unchanged; new functions not exported from src/index.ts. Three new pins (named close: no pair id, no base version with the pair installed, email_template at an unshipped locale), green on main before the fold; no existing pin edited. PR #29874, draft, head e1c8a104 (main merged in), patch changeset.",
"tests": "New pins first, on main: commit 0dc436c3 on 42ff86f6, protocol.named-base-overlay-write.test.ts 25/25 (VERDICT command-exit 0). Ablation on main via scripts/ablation-replace.mjs on protocol-packaged-base-refusal.ts (blob 410bf525 before, and 410bf525 = HEAD after every restore): pair-id return made a no-op, no-pair-id pin red (1 failed | 24 passed); gate refuse-return deleted, unshipped-locale pin red (1 | 24); basedOn given a fallback ?? '0.0.0', no-version pin red (1 | 24); basedOn check deleted alone stays green 25/25, because the gate refuses an overrides with no basedOn (OverrideDeclarationSchema rejects it, so the gate judges an undeclared same name), stated in Acceptance notes. At the head e1c8a104 under the lock: build of '@objectstack/metadata-protocol...' VERDICT command-exit 0; metadata-protocol typecheck && test VERDICT command-exit 0, Test Files 311 passed | 4 skipped (315), Tests 22314 passed | 26 skipped; objectql protocol-packageless-overlay-migration + environment-overlay-email-locale-restart + environment-overlay-five-types against the rebuilt dist (dist/index.js carries overlayPairFixOf): Test Files 3/3, Tests 105/105, VERDICT command-exit 0. Before the merge, at 408cc35c: 22308/22308 and 105/105. No ablation of the fold itself: refactor, no tested behaviour changed. packages/cli integration layer declared to CI.",
"gates": "At e1c8a104: node scripts/pm/dispatch-gates.mjs --commands, 59 derived, each run with its exit captured before any pipe; --ran: 59 derived, 58 run (all exit 0), 1 NOT MEASURED: node scripts/check-plugin-teardown-shape.mjs --self-test exit 3 PREREQUISITE NOT MET (fixture pinned to a commit outside the shallow clone; CI runs it). pnpm lint exit 0. First pass at 408cc35c+changeset: 56 run green, 3 NOT MEASURED (the teardown self-test, check:dual-build-cjs-loads and check:lean-entry-closure lacked dist before the merged build; both exit 0 on the second pass). PR check-runs: in_progress at report time, not awaited (os-dev contract).",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0 — no GitHub MCP read or write; card, claim and comments read through gh api REST",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay pr_create, run 41607845739, read-back 11507 bytes sent = stored) and this os-dev-report comment through scripts/pm/post-stamped.mjs; git push is not a REST write",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · the base-version step of the fix predicate is not separately observable at the doors today (the D2 gate refuses a declaration missing basedOn first); kept as it was, noted in the PR's Acceptance notes, not filed (not a defect class)"
],
"deviations": [
"Changeset: the order allowed skip-changeset if no published behaviour changed; AGENTS.md keeps skip-changeset for a diff that publishes nothing, and the shipped dist of @objectstack/metadata-protocol changes, so a patch changeset (.changeset/29397-overlay-pair-fix-one-predicate.md) carries Clause-② no / Metadata-protocol none.",
"A two-line test comment on the no-version pin landed in the refactor commit 408cc35c, not the pins commit 0dc436c3; no assertion changed.",
"Head e1c8a104 is 4 commits behind origin/main at report time (4b71a82b and three before it); git diff HEAD...origin/main -- packages/metadata-protocol is empty, so not merged again. PR #29797 (seat 5, same test file and protocol.ts) is still open; if it lands first, main needs merging and both closes' pins re-running.",
"No PR activity subscription and no reviewer/assignee step: the dispatch contract overrides the platform's PR-subscribe default and the order forbids reviewers."
]
}
What landed: the two overlay-write closes now share one fix predicate (overlayPairFixOf + overlayPairFixAdmits in protocol-packaged-base-refusal.ts). Each close keeps only the step that genuinely differs. It is a move-only refactor: refusals, codes and sentences are unchanged, and no existing pin was edited.
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p3 kept ·
domain:serverkept · 2026-11-03T01:09Z⛔ Not a claim.
namedBaseCloseSubject,packagelessCloseSubject) into one fix-can-be-taken predicate. A refactor, p3. ⛔ Move-only: no refusal may change.Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:server#2 · os-warren · session_01JQwxbXKRzgnVvjzxaYxLUf
Claim: PM loop round 1 · card thread · 2026-11-03T07:16Z
Session:
session_01JQwxbXKRzgnVvjzxaYxLUf(the seat); the card thread issession_01JQwxbZz2XXsYuaJz9sPuGUAccount:
os-warrenBranch:
claude/project-thread-a7zbykWorktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2File surface:
packages/metadata-protocol/src/protocol-packaged-base-refusal.ts,protocol-packageless-overlay-migration.ts, their tests; call sites only inprotocol.tsif any; a changeset only if published behaviour changes (expected none)Container & model: card thread,
mode:thread,model: TIER_DEFAULT(--tiernames no path mandate),effort: project defaultClause-②: no
Metadata-protocol: none
Responsibility:
metadata-protocol overlay-write closes (#28905 / #28576, this lane)|two predicates repeat the same four fix-can-be-taken steps, so a change to one can silently drift from the other|refactor, move-only: both closes' pins pass unchanged and no refusal sentence movesThread-read: 6592695895
Premise: holds (seat read on
origin/main:namedBaseCloseSubjectandpackagelessCloseSubjectboth live and both referenced fromprotocol.ts)Serial constraints cleared: #29479 (same module, the refusal sentence) is queued and not dispatched; if it is dispatched, the seat sequences the two. No open PR touches either module.
Order: project file pm-orders/server/seat2/order-29397.md.
Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:server#2 · os-warren · session_01JQwxbZz2XXsYuaJz9sPuGU
os-dev-report
{ "issue": 29397, "status": "done", "branch": "claude/project-thread-a7zbyk", "pr": "https://github.com/objectstack-ai/objectstack/pull/29874", "session": "session_01JQwxbZz2XXsYuaJz9sPuGU", "premise_still_valid": true, "summary": "Measured on main 42ff86f6 first: every step of namedBaseCloseSubject (protocol-packaged-base-refusal.ts:390-424) and packagelessCloseSubject (protocol-packageless-overlay-migration.ts:725-779) is common or intended-different; no step differs by accident (table in the PR body). Two spellings differ with the same answer: the base version (inline getPackage vs baseVersionOf re-reading engine.registry, one never-reassigned getter) and the member of the declared body (isPlainRecord(item) vs item !== undefined, equal for every JSON body; left per close). Folded into overlayPairFixOf (pair id, registry, ensure door, basedOn) and overlayPairFixAdmits (the D2 gate on the declared body) in protocol-packaged-base-refusal.ts, two halves so the package-less close's row read stays between them (call order and which failure wins unchanged); each close keeps only its own difference. protocol.ts, closedOverlayWriteClauses and every refusal sentence untouched; return shape { base, pair } unchanged; new functions not exported from src/index.ts. Three new pins (named close: no pair id, no base version with the pair installed, email_template at an unshipped locale), green on main before the fold; no existing pin edited. PR #29874, draft, head e1c8a104 (main merged in), patch changeset.", "tests": "New pins first, on main: commit 0dc436c3 on 42ff86f6, protocol.named-base-overlay-write.test.ts 25/25 (VERDICT command-exit 0). Ablation on main via scripts/ablation-replace.mjs on protocol-packaged-base-refusal.ts (blob 410bf525 before, and 410bf525 = HEAD after every restore): pair-id return made a no-op, no-pair-id pin red (1 failed | 24 passed); gate refuse-return deleted, unshipped-locale pin red (1 | 24); basedOn given a fallback ?? '0.0.0', no-version pin red (1 | 24); basedOn check deleted alone stays green 25/25, because the gate refuses an overrides with no basedOn (OverrideDeclarationSchema rejects it, so the gate judges an undeclared same name), stated in Acceptance notes. At the head e1c8a104 under the lock: build of '@objectstack/metadata-protocol...' VERDICT command-exit 0; metadata-protocol typecheck && test VERDICT command-exit 0, Test Files 311 passed | 4 skipped (315), Tests 22314 passed | 26 skipped; objectql protocol-packageless-overlay-migration + environment-overlay-email-locale-restart + environment-overlay-five-types against the rebuilt dist (dist/index.js carries overlayPairFixOf): Test Files 3/3, Tests 105/105, VERDICT command-exit 0. Before the merge, at 408cc35c: 22308/22308 and 105/105. No ablation of the fold itself: refactor, no tested behaviour changed. packages/cli integration layer declared to CI.", "gates": "At e1c8a104: node scripts/pm/dispatch-gates.mjs --commands, 59 derived, each run with its exit captured before any pipe; --ran: 59 derived, 58 run (all exit 0), 1 NOT MEASURED: node scripts/check-plugin-teardown-shape.mjs --self-test exit 3 PREREQUISITE NOT MET (fixture pinned to a commit outside the shallow clone; CI runs it). pnpm lint exit 0. First pass at 408cc35c+changeset: 56 run green, 3 NOT MEASURED (the teardown self-test, check:dual-build-cjs-loads and check:lean-entry-closure lacked dist before the merged build; both exit 0 on the second pass). PR check-runs: in_progress at report time, not awaited (os-dev contract).", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0 — no GitHub MCP read or write; card, claim and comments read through gh api REST", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay pr_create, run 41607845739, read-back 11507 bytes sent = stored) and this os-dev-report comment through scripts/pm/post-stamped.mjs; git push is not a REST write", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · the base-version step of the fix predicate is not separately observable at the doors today (the D2 gate refuses a declaration missing basedOn first); kept as it was, noted in the PR's Acceptance notes, not filed (not a defect class)" ], "deviations": [ "Changeset: the order allowed skip-changeset if no published behaviour changed; AGENTS.md keeps skip-changeset for a diff that publishes nothing, and the shipped dist of @objectstack/metadata-protocol changes, so a patch changeset (.changeset/29397-overlay-pair-fix-one-predicate.md) carries Clause-② no / Metadata-protocol none.", "A two-line test comment on the no-version pin landed in the refactor commit 408cc35c, not the pins commit 0dc436c3; no assertion changed.", "Head e1c8a104 is 4 commits behind origin/main at report time (4b71a82b and three before it); git diff HEAD...origin/main -- packages/metadata-protocol is empty, so not merged again. PR #29797 (seat 5, same test file and protocol.ts) is still open; if it lands first, main needs merging and both closes' pins re-running.", "No PR activity subscription and no reviewer/assignee step: the dispatch contract overrides the platform's PR-subscribe default and the order forbids reviewers." ] }objectstack-fleet commentedon Nov 3, 2026
domain:server#2 · os-warren · session_01JQwxbXKRzgnVvjzxaYxLUf
Landing record · #29397 · 2026-11-03T11:32Z
c55d300e089406998d25cbb886b07607b9e8bce1; headba4aaf11; this card closed byFixes.overlayPairFixOf+overlayPairFixAdmitsinprotocol-packaged-base-refusal.ts). Each close keeps only the step that genuinely differs. It is a move-only refactor: refusals, codes and sentences are unchanged, and no existing pin was edited.TIER_DEFAULT(declaration face, no spec path) one1c8a104. The PR was held until seat 5's PR fix(metadata-protocol)!: a package commit's plan and revert address the committing package's own row; a deleted row's restore asks the package-less close #29797 (metadata-protocol: a pair commit's revert beside a pre-close base-bound row answers success while writing nothing, because the commit plan and the restore both read any package's active row #29414, same module) merged at5f99582e. The thread then merged main toba4aaf11(clean) and re-ran both closes' pins (31/31). Seat ACCEPT 6602254840 →pr_ready+automerge_enableby the seat.Clause-②: no,Metadata-protocol: none,@objectstack/metadata-protocolpatch.os migrate packageless-overlays, the ceremony that now moves a base-bound row into its pair #29479 (the refusal sentence, same module) is next in line. It stays inpm:queueunopened under the maintainer's stand-down; its order is written atpm-orders/server/seat2/order-29479.md.pm:dispatchedremoved in the same stroke as this record.Generated by Claude Code