Skip to content

fix(spec): the two-master controlled_by_parent refusal names its release - #23448

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23387-two-master-names-release
Oct 14, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23387-two-master-names-release

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #23387

Clause-②: no

The two-required-masters refusal of a controlled_by_parent object (controlledByParentMasterRefusal, several-required-masters) now reads "ADR-0055 §1: since @objectstack/spec 18, a controlled-by-parent object derives its master from exactly one required master_detail field, ...", the wording its no-master sibling already carries. @objectstack/spec 17.7.0 accepts both shapes, so both refusals now date themselves for 17 to 18 upgraders.

What changed

  • packages/spec/src/data/controlled-by-parent-master.ts: message text of the two-master branch only. Refused shapes, issue paths and the prescribed fix are unchanged.
  • packages/spec/src/data/object.test.ts: the existing both-branches test now asserts that the two-master and the no-master message each contain "since @objectstack/spec 18, a controlled-by-parent object derives" (the pin that both branches carry it).
  • .changeset/23387-two-master-names-release.md: patch for @objectstack/spec (text only, no accept-set change).

Pin sweep

Grepped the repo for the message text (does not say which master, a controlled-by-parent object derives, several-required-masters, controlledByParentMasterRefusal): the only other asserters are object.test.ts prefix matchers that stop at ADR-0055 §1: (still green); packages/lint/src/rule-explanations.ts carries its own prose, not this message. No consumer pin asserts the old text, and the plugin-security test named as a lead does not assert it. File surface matched the claim.

Verification

  • @objectstack/spec: vitest run src/data src/conversions 140 files / 4568 tests pass; test:repo 59 files / 1011 tests pass; typecheck green.
  • dispatch-gates --commands: all 85 derived families run (the build-dependent ones exited 3 before @objectstack/spec was built and 0 or green after), reconciled with --ran: 85 derived, 85 run, 0 UNRUN.
  • Semantic entries named in the card's corrected scope are untouched.

Dedupe/ruling: no maintainer ruling; triage 6161187727 forbids any change to which shapes are refused.

🤖 Generated with Claude Code

https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 142 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 2659901c5ea8a174de4129264cb857e203d42b88 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 3c237e292386a1d5bd2c270cf383e72d2dad525e — the merge of head ccffa6a42111b242698806fea45059a1fd3141fa into base 2659901c5ea8a174de4129264cb857e203d42b88, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 3c237e292386a1d5bd2c270cf383e72d2dad525e && git checkout 3c237e292386a1d5bd2c270cf383e72d2dad525e
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 2659901c5ea8a174de4129264cb857e203d42b88 ccffa6a42111b242698806fea45059a1fd3141fa && git checkout -B drift-repro 2659901c5ea8a174de4129264cb857e203d42b88 && git merge --no-ff ccffa6a42111b242698806fea45059a1fd3141fa

node scripts/docs-audit/affected-docs.mjs --json 2659901c5ea8a174de4129264cb857e203d42b88

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: ccffa6a42111b242698806fea45059a1fd3141fa
Local-runs: none

Inputs read: card #23387 (body + 3 comments: triage 6161187727, claim 6163850152, os-dev-report 6164994006), PR #23448 (body as re-read after the edited event, 3-file list, net diff vs main), and the check-runs on the head re-read once. No ruling on the card; the triage comment is the only grading and it pins both branches carrying "since @objectstack/spec 18" with no change to which shapes are refused or what each message prescribes. This record supersedes the earlier FAIL rendered on this same head, whose single red (the missing Clause-②: line) is now cleared by a body edit with no push.

① Derived judgments

  • Accept-set: unchanged — right. controlledByParentMasterRefusal's two-master branch still fires on the same predicate (masters.length > 1, required master_detail count), returns the same path: 'fields', the same shape: 'several-required-masters', the same masterDetails/requiredLookups, and the same prescription ("Keep master_detail on the one master, and declare every other parent as a lookup field."). The net diff touches only the two concatenated string fragments around "ADR-0055 §1:"; no condition, no field, no export changed. Triage's ⛔ holds.
  • The pin: both branches name the release — right. At the head, the two-master message reads "… ADR-0055 §1: since @objectstack/spec 18, a controlled-by-parent object derives its master from exactly one required master_detail field, so …" and the no-master sibling (untouched) reads "… ADR-0055 §1: since @objectstack/spec 18, a controlled-by-parent object derives its master from exactly one master_detail field declared required: true …". The shared substring since @objectstack/spec 18, a controlled-by-parent object derives is exactly what object.test.ts now asserts on BOTH two[0].message and none[0].message, so the pin covers the premise and not one branch of it. The pre-existing ^Object 'cbp_line' … ADR-0055 §1:/ prefix matcher is unaffected, since "ADR-0055 §1:" still precedes the inserted "since".
  • Public surface: message text only — right. No new export, no new key, no schema shape; the message is reached by ObjectSchema's parse (object.zod.ts:1992) and by os migrate meta --stored through conversions/refused-shapes.ts:134, which appends its own fate sentence after the parse message and does not restate it — so the stamp propagates to both printers the card names with no second site to edit. A sweep of the repo for ADR-0055 §1: a controlled-by-parent, several-required-masters and controlledByParentMasterRefusal finds no other asserter of the old text; the dev's pin-sweep claim holds.
  • Corrected scope honoured — right. Neither 18.* semantic entry named in the card is in the file list.
  • Wording nit, not a defect: the two-master branch keeps "exactly one required master_detail field" while the no-master branch says "exactly one master_detail field declared required: true". The card asks only that the release be named the way the sibling names it; the ask is met and the two prescriptions were already allowed to differ.

② Semver level

  • .changeset/23387-two-master-names-release.md grades @objectstack/spec: patch. Matches what the diff publishes: a refusal message changed in text, accept-set and prescription identical, no key added to any published payload. Level right.
  • Clause-②: line — present and right. The PR body now carries Clause-②: no bare, at the start of its own line (line 3, directly under Fixes #23387), agreeing with the claim (6163850152) and the triage (6161187727). no is the correct declaration: this PR puts no new key on a published payload, and patch is the grade a no admits.
  • Check Changeset on this head: the newer run concluded success at 2026-10-14T09:20:00Z after the edited event re-read the body; the earlier failure is the earlier run on the pre-edit body and is superseded. The changeset gate is green.

③ Boundary flags

  • Dev flags: open_questions: [], out_of_scope_findings: [], premise_still_valid: true — nothing to answer; the premise re-read (only :127 carries the stamp on origin/main) matches the net diff's - lines.
  • File surface vs the claim: the three touched files are all inside the claimed surface (the source file, its test beside it, the changeset); no regenerated output was needed and none was produced.
  • Serial constraint spec: export the controlled_by_parent master predicate, so a producer does not restate ADR-0055 §1's exactly-one-master rule #23272 (export the master predicate, same file): this diff does not touch the predicate or its exports, so nothing here pre-empts it.
  • Check-runs on ccffa6a42 as re-read — no failure stands. Success: Check Changeset (newer run), filter, The card this PR closes must claim this branch, Spec property liveness, Part-of PR must not also close its card, No other open PR may claim the same single-writer path, No other open PR may claim the same issue, Lint & Repo Gates, Lint · ESLint, Lint · CI, release & engine gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · slot lookup & corpus, Lint · scoped · query-options erasure, Lint · scoped · tooling self-tests, Lint · PM dispatch-gates, Type Check · source gates, Governed Surface Queue Guard, Flag docs affected by code changes, Dogfood Regression Gate, Check PR Size, Check Documentation Links, Auto Label; skipped (not applicable, or the second run of a path-filtered job): Temporal Conformance, Packed-tarball smoke, Dogfood Verify CLI, Dogfood Regression Gate shards, Console Pin Gate, Build Docs, and the post-edit re-runs of Auto Label and Check PR Size. Still in progress (read once, no watcher): Build Core; Test Core (1/6), (2/6), (3/6), (4/6), (5/6), (6/6); Type Check · workspace; Type Check · debt ledger; Type Check · consumer gates. Their verdicts are not in this record; the dev's report says spec vitest (4568 tests), test:repo (1011), typecheck and 85/85 dispatch-gate families were green locally, which this seat did not re-run. Should any of the ten conclude red, this record is superseded.
  • Escalation: none.

Implemented-by: claude/issue-23387-two-master-names-release
Reviewed-by: session_01D6F9axfoPzR7t8G1J7Ytzz

VERDICT: PASS

Adopted by domain:spec seat 3 (#18883), baozhoutao, session session_01D6F9axfoPzR7t8G1J7Ytzz, at 2026-10-14T09:23Z: rendered by an isolated read-only reviewer at CONTRACT_REVIEW_TIER. Its first rendering on this head was FAIL on the missing Clause-②: body line; the seat added Clause-②: no to the body (no push), and this re-rendering supersedes it.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 14, 2026 09:54
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit 07b27b3 Oct 14, 2026
48 of 49 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23387-two-master-names-release branch October 14, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:data size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec: the two-master controlled_by_parent refusal names no release, while its no-master sibling says "since @objectstack/spec 18"

2 participants