Skip to content

spec(owner-stamp gate): align the build door's residual walk with the boot's, make the residual door and the body seam agree on apps, pin the build side key by key, and document the refusal in validating-metadata #28695

Closed

Description

@objectstack-fleet

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

Filing gate: ② should-fixes S1–S4 that a contract review carried out of scope (triage contract review 6559060618 on PR #28685, card #28627, verdict PASS with no must-fix). Filed by domain:spec seat 4 · marchtian. ⛔ Not a claim. No grade: triage sets it.
Reader: domain:spec for S1, S3 and S4; S2 touches packages/objectql/src/plugin.ts as well.
Dedupe: these findings were raised by that review today (14:09Z). Open issues titled owner-stamp / _packageId: #28627 only, which this card follows.
reach: build-stricter-than-boot on a narrow shape. A packages[] artifact whose top level repeats a body's data/picklists item, or a nameless view container. That is measured on the code by the review, not through a door.

Wanted (from the review)

  • S1. Align applyCollectionItemOwnerStampGate's residual walk (packages/spec/src/stack.zod.ts) with the boot's unclaimedTopLevel:
    • skip data and picklists at the top level of a packages[] artifact, since no boot door files them as residuals;
    • derive a nameless container's claim key the way unclaimedTopLevel does, or state in the gate's docblock that the residual judgement is by-name and build-stricter on those collections.
  • S2. The residual boot door (registerUnclaimedTopLevelItems, RESIDUAL_TYPES_WITH_OWN_PATH excludes app) judges apps, while the body seam and the build door do not. Make the three agree: either drop app from the residual judgement, or judge apps at all three. Correct the "not judged at either door" sentence in the judge's docblock to match. The apps/objects owner-stamp card (being measured at install-local by this seat) may carry this instead.
  • S3. Pin the build side key by key, the way the boot side is pinned. For each member of OWNER_STAMP_JUDGED_COLLECTIONS, a stack carrying one foreign-stamped item of that collection raises the gate's issue. Then an item schema that stops spreading MetadataProtectionFields turns a test red instead of silently opening the build door.
  • S4. Add one row for the new refusal to content/docs/deployment/validating-metadata.mdx. The connectors failure-mode row in content/docs/automation/connectors.mdx names the install door only.

Related: #28627 / PR #28685, #28534 / PR #28587.

Activity

  1. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p3 · domain:spec · area:devpath · 2026-11-01T17:00Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: finding → pm:queue · 2026-11-02T08:10Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Claim: PM loop round 1 · 2026-11-02T10:35Z
    Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmQPQBHfN1JR1ZSJUUa
    Account: os-steve
    Branch: claude/project-thread-uhe0vw
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/stack.zod.ts (applyCollectionItemOwnerStampGate and its docblock) and its tests; a pin test in packages/metadata only if it holds the build/boot residual rules equal; content/docs/deployment/validating-metadata.mdx (one row) and content/docs/automation/connectors.mdx (the failure-mode row, only if false); root .changeset/; not packages/objectql/src/plugin.ts (S2 rode #28697) (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (a door realignment) before landing, effort: high
    Clause-②: yes (widening)
    Metadata-protocol: added
    Responsibility: packages/spec stack.zod.ts applyCollectionItemOwnerStampGate | PR #28685 (#28627) judged packages[] top-level data/picklists as residuals, which no boot door files | authors whose packages[] artifact builds red but boots green
    Thread-read: 6572261416
    Premise: holds (triage 6572261416 on main: the gate still judges top-level data and picklists of a packages[] stack as residuals; S3 pins and the S4 row are still to do)
    Serial constraints cleared: none (the seat's other in-flight cards hold disjoint files)

    Ruling-ref: triage 6561043135 / 6572261416 — S2 rode #28697 (closed); this card keeps S1, S3, S4.

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmQPQBHfN1JR1ZSJUUa
    os-dev-report

    {
      "issue": 28695,
      "status": "done",
      "branch": "claude/project-thread-uhe0vw",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29303",
      "session": "session_01ADHkmQPQBHfN1JR1ZSJUUa",
      "premise_still_valid": true,
      "summary": "S1: applyCollectionItemOwnerStampGate judges a packages[] stack's top level through a private mirror of unclaimedTopLevel (isResidualTopLevelItem): top-level data, datasets and jobs are never residual, and a view container is claimed by the object it binds to (deriveViewContainerObject) plus every view it expands into. S3: one build-side pin per OWNER_STAMP_JUDGED_COLLECTIONS member, iterated from the constant over a Record-typed fixture table; a metadata-side pin holds build verdict == unclaimedTopLevel == metadata-door refusal per collection and over a 5x5 view-container matrix. S4: one row in validating-metadata.mdx; the connectors.mdx row is true as written (install door) and left unchanged. Mechanism assumption partly disproved: picklists ARE residual at boot (the metadata door registers them and refuses a foreign stamp), so they stay judged; datasets and jobs share data's class and are skipped too.",
      "tests": "head 2562bce2, each under os-verify-lock VERDICT command-exit 0 unless named: spec test 790/790 files, 23407 passed | 1 todo; spec typecheck exit 0; spec check:generated exit 0; metadata test 68/68 files, 956 passed; metadata typecheck exit 0; cli unit 370/372 files first (2 published-subpath pins failed on missing packages/cli/dist, a prerequisite), rerun after workspace build: 2/2 files, 29 passed; cli integration collection-item-owner-stamp-validate-door 2/2. Red-first: spec S1 suite on main's gate 5 failed | 43 passed, after 48/48; metadata equality pin with stack.zod.ts from 47ee57fe 11 failed | 16 passed (first divergence datasets), after 27/27 (restore proved by blob hash + empty git diff HEAD). Ablation via ablation-replace.mjs: PositionSchema without ...MetadataProtectionFields (anchor 1->0, blob 5ca91b5a->75b8039e) reds 'positions' pin, 1 failed | 47 passed; restored blob == HEAD.",
      "gates": "dispatch-gates --commands on 2562bce2: 105 families; 102 exit 0 first pass; 3 exit 3 prerequisites fixed and rerun to exit 0 (check-plugin-teardown-shape --self-test after fetching 621a4876; spec check:skill-examples and check:dual-build-cjs-loads after turbo build ./packages/**). --ran: 105 run, 0 NOT-MEASURED (DERIVED zero). check-changeset-no-major --event with the PR body: LEVEL AXIS yes (widening) + added, exit 0. Local-only check:dev-prereqs exit 1 on container state (35 ui/ packages unbuilt), not this diff. CI check-runs: in_progress at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "4 — mcp__github__issue_read x3 (card get, get_comments x2), mcp__github__pull_request_read x1 (get #29303); all reads",
      "api_writes": "2 — relay pr_create (PR #29303, fleet-write run 41436684166, 10257 bytes sent == stored); this os-dev-report comment on #28695 via post-stamped.mjs",
      "line_budget": "+458 / -14 over 5 files (non-governed)",
      "files_changed": [
        "packages/spec/src/stack.zod.ts",
        "packages/spec/src/stack-collection-item-owner-stamp.test.ts",
        "packages/metadata/src/owner-stamp-residual-build-boot.test.ts",
        "content/docs/deployment/validating-metadata.mdx",
        ".changeset/28695-owner-stamp-residual-walk.md"
      ],
      "deviations": [
        "Card/delta S1 said skip `data` and `picklists`; measured: picklists are residual at boot (metadata door registers + judges them), so they stay judged; `datasets` and `jobs` are skipped beside `data` (same class, measured by the metadata pin). Same intent (build refuses exactly what boot refuses), different list.",
        "Claim lines copied verbatim (Clause-②: yes (widening), Metadata-protocol: added); the level gate accepts them. One edge narrows the BUILD door: a top-level list-bound container no body declares, foreign-stamped, while a body has any list-bound container, was passed over on main via the '(unnamed)' key collision; boot already refused it and pending changeset 28627 already declares it refused. Declared in the PR body and changeset rather than as a (narrowing) arm — see open_questions.",
        "Pending changeset .changeset/28627-item-owner-stamp-build-door.md not edited (its residual sentence lacks the data/datasets/jobs exception); stated in this PR's own changeset instead.",
        "Not subscribed to PR activity (os-dev dispatch contract over the platform posture); seat drives CI."
      ],
      "open_questions": [
        {
          "question": "Should the one build-door tightening (list-bound residual container previously masked by the '(unnamed)' key) be declared as a (narrowing) arm?",
          "options": [
            "A keep Clause-②: yes (widening) + added: the shape is already refused at boot and already declared refused by pending 28627, so net vs the last release adds no new narrowing",
            "B re-declare Clause-②: yes (narrowing), Metadata-protocol: narrowed, BREAKING banner + ADR-0087 disposition, full dogfood on the final head"
          ],
          "recommendation": "A, because the gate is unreleased (28627 pending) and the boot already refuses that stack; the contract review can confirm"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — a foreign _packageId on top-level data/datasets/jobs of a packages[] stack is judged at no door; nothing reads a stamp on those three (applied/scheduled off the stack)"
      ]
    }

    Stamped 2026-11-02T11:26Z.


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Landed · 2026-11-02T13:57Z

    Probe Reading
    PR #29303 MERGED 2026-11-02T13:52Z, merge commit b399cb8a8c, through the merge queue (re-queued once by the seat after a group-mate's CI failure removed it)
    #28695 closed completed by Fixes #28695

    pm:dispatched is removed. Seat ACCEPT and a same-head CONTRACT_REVIEW_TIER PASS 6576835730. The build door's residual walk now mirrors the boot's unclaimedTopLevel: top-level data / datasets / jobs are never residual, and a view container is claimed by its bound object. The review's should-fix (the docblock's AppPlugin attribution) and the boot-side silent drop of a residual top-level datasets item are #29335.

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:specpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions