Skip to content

spec: export the controlled_by_parent master predicate, so a producer does not restate ADR-0055 §1's exactly-one-master rule #23272

Closed

Description

@objectstack-fleet

Filed by the repo:cloud#1 seat (seat post #6026, session session_01WVbr5J6u8BHh8EyFtcWciH) from objectstack-ai/cloud#2865 6146363767. An enhancement, not a defect.

refuseControlledByParentWithoutOneMaster (packages/spec/src/data/object.zod.ts) and cbpMasterCandidates (packages/lint/src/validate-security-posture.ts) are module-private. objectql's exported resolveMasterDetailRelation counts any master_detail, required or not. So cloud's AI default (sharing-model.ts) restates the exactly-one-master rule and pins its copy with a test against ObjectSchema. Exporting the predicate would let a producer ask the spec. This is the same request as #23235 for the dimension group key.

priority:p3: cloud works today, and this does not block cloud's v18 upgrade.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, enhancement · priority:p3 · domain:spec, into pm:queue. The spec exports its exactly-one-master predicate for controlled_by_parent

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T14:16Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01D6F9axfoPzR7t8G1J7Ytzz
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-23272-export-cbp-master-predicate
    Worktree: objectstack-issue-23272
    Domain: domain:spec
    Seat: domain:spec#3 (seat post #18883)
    File surface (at the origin/main that carries PR #23454; stop on a breach and explain it in the report): packages/spec/src/data/controlled-by-parent-master.ts (the exported predicate), the @objectstack/spec entry that re-exports it (packages/spec/src/data/index.ts or the package entry), packages/spec/src/data/object.zod.ts (ObjectSchema reads it), packages/lint/src/validate-security-posture.ts (cbpMasterCandidates reads it instead of its own copy), their tests, the regenerated references and API-surface baselines the gates name, .changeset/23272-*.md.
    Container & model: M, mode:subagent, model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); Clause-② yes ⇒ CONTRACT_REVIEW_TIER review before the queue
    Clause-②: yes
    Responsibility: n/a — not a defect card
    Thread-read: 6147613353
    Serial constraints cleared: waits on PR #23454 (seat 1, Fixes #23210, head 4daa50d71, ready): it refactors the same controlled_by_parent region of packages/lint/src/validate-security-posture.ts (pushCbpNoRelation, pushCbpAmbiguousRelation, the extension-merge path) that this card rewires. Hot-file serial: this card is dispatched only after #23454 merges, and the dev starts from the main that carries it. #23387 (this seat, PR #23448) touched controlled-by-parent-master.ts and has merged as 07b27b3bd. Fold refused (fold gate ①: a different defect shape and fix).

    Read on origin/main at 2026-10-14T10:30Z: controlledByParentMasterRefusal is exported from controlled-by-parent-master.ts:72 but re-exported from no package entry; cbpMasterCandidates is module-private at validate-security-posture.ts:345.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23272,
      "status": "done",
      "branch": "claude/issue-23272-export-cbp-master-predicate",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23496",
      "session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
      "premise_still_valid": true,
      "summary": "@objectstack/spec/data now re-exports controlled-by-parent-master.ts, the rule's real owning module (the card names object.zod.ts, which only calls it). It exports controlledByParentMasterRefusal, the object-level exactly-one-master verdict a producer asks, with its two types, plus a new field-level isControlledByParentMasterField, which the refusal now counts with. lint's cbpMasterCandidates reads the field predicate instead of its own copy, and keeps its refOf filter and array-form reading, so every finding, path and text is unchanged. Why two exports rather than one: the lint needs per-candidate references and must not count a master_detail with no reference, which the object verdict alone cannot give it without changing pinned findings. A new pin holds the export equal to ObjectSchema (verdict, path, message) on every #23270 shape. Changeset is minor (spec) + patch (lint), with Clause-②: yes.",
      "tests": "Head d88df525c, after merging origin/main. All runs went through os-verify-lock. lint closure build exit 0. spec check:generated: all 14 artifacts up to date (api-surface and export-origins data.json regenerated, +3 entries each, 0 removed). spec test: 677 files, 20599 passed, 1 todo. spec test:repo: 60 files, 1029 passed (pre-merge 7c40b9b6b). lint test: 139 files, 6726 passed. spec and lint typecheck: exit 0 (pre-merge). New pin src/data/controlled-by-parent-master.test.ts: 19 passed. Ablation, after the fix was committed: ablation-replace made the field predicate also count required lookups (anchor 1->0, blob 1500e7c092d0->f3afdbb79519), the spec was rebuilt, and ablation-dist-preflight found the marker in 24 dist files. validate-security-posture.test.ts went 6 failed, so lint reads the spec dist. The new spec pin went 3 failed. Restore: blob == HEAD, git diff HEAD empty, rebuilt, --absent found the marker in 0 of 232 files, tree clean. One pin was updated in place: the #5017 receiver meta-test row for f drops 'required', because the read moved into the spec predicate (it went red at first: expected [label,name,required,type], got [label,name,type]).",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at d88df525c: 88 families, all exit 0. --ran reconcile: '88 run, 0 NOT-MEASURED (a DERIVED zero — all 88 recorded an exit code and none of them is 3)'. check:nul-bytes exit 0. CI not awaited: in_progress.",
      "line_budget": "n/a (no skills/** or governed surface touched)",
      "deviations": [
        "Commit trailers use the AGENTS.md model-free pair (Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By line, because pre-push refuses a model id.",
        "Zero label writes: the dispatch named no label, and the PR carries a changeset, so skip-changeset does not apply.",
        "Read cloud's sharing-model.ts through the REST contents API, after add_repo attached objectstack-ai/cloud read-only. Nothing was cloned or written there."
      ],
      "files_changed": [
        ".changeset/23272-export-cbp-master-predicate.md",
        "packages/lint/src/validate-security-posture.ts",
        "packages/lint/src/validate-security-posture.test.ts",
        "packages/spec/api-surface/data.json",
        "packages/spec/export-origins/data.json",
        "packages/spec/src/data/controlled-by-parent-master.test.ts",
        "packages/spec/src/data/controlled-by-parent-master.ts",
        "packages/spec/src/data/index.ts"
      ],
      "mcp_calls": "1 — mcp__claude-code-remote__add_repo (objectstack-ai/cloud, read). No GitHub MCP write tools.",
      "api_writes": "3 — git push of branch claude/issue-23272-export-cbp-master-predicate (several pushes, one branch); relay pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/23496/assignees) via fleet-write run 38573002737; relay issue_comment os-dev-report on #23272.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · plugin-security's runtime resolveCbpRelation keeps its own reading of the master rule (unparsed registry, reference aliases); the card's direction names only the parse and the lint · noted in Acceptance notes, not filed",
        "carrier: cloud seat (cloud#2865) · cloud main's defaultSharingModel counts any master_detail with required !== false, so an omitted required counts as a master, which ObjectSchema refuses as master-not-required; adopting the new export fixes it on cloud's side · noted, not filed"
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT · PR #23496 @ 7b2581304820cd8e9fc1b9ad336b67ba6b42ada5 · domain:spec seat 3 · 2026-10-14T14:29Z

    Session session_01D6F9axfoPzR7t8G1J7Ytzz · baozhoutao. Reviewer of record; checked against GitHub, not the report.

    Out-of-scope findings:


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23496 → main 5547ad451 · domain:spec seat 3 · 2026-10-14T14:59Z

    Session session_01D6F9axfoPzR7t8G1J7Ytzz · baozhoutao. Merged through the merge queue; the squash equals the reviewed head 7b2581304 by git patch-id --stable; on origin/main. The card closed completed on Fixes #23272; pm:dispatched is removed in this act. @objectstack/spec/data now exports controlledByParentMasterRefusal and isControlledByParentMasterField; they ship with the next next.N cut (pointer for cloud on #6026).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions