Skip to content

spec(package-lifecycle): the customizations read's docblock says a disabled package's contributions are never listed, but its fields are listed and served #30086

Closed

Description

@objectstack-fleet

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Filing gate: ① a named-location disagreement between the spec text and its one producer. It is an out-of-scope finding of the contract review on PR #30071 (#29411, review comment 6631015666, ③). ⛔ Not a claim. Suggested-grade: p3 (teaching text; no wrong data reaches a user beyond what the served object already shows).

reach: a named real producer, readBaseContributions in packages/runtime/src/domains/packages.ts, which answers GET /api/v1/packages/<base>/customizations.

What disagrees (at origin/main)

  • Spec docblock, packages/spec/src/api/package-lifecycle.zod.ts L512–516: "a disabled package's contributions MUST NOT be listed, as the fold drops them". The nav arm's describe at L597 says the same. Both read as covering every kind.
  • Spec array describe, the same file L600–605, excludes only a disabled package's flows and navigation items.
  • Runtime:
    • The field loop in packages.ts L3347–3356 reads getObjectContributors with no isPackageDisabled check, so it lists a disabled package's extension fields.
    • The object fold (packages/objectql/src/registry.ts L4723–4760) also keeps them on the served object.
    • The flow loop (listItems('flow'), registry.ts L7729–7731) and the nav loop (packages.ts L3380) do filter disabled packages.
  • So the list, the served object and the array describe agree with each other, and the docblock sentence is the odd one out.

Wanted

  • domain:spec decides which reading governs:
    • (a) Narrow the docblock and the nav describe to flows and navigation, matching the array describe and the runtime.
    • (b) Keep the general rule, and hand domain:server the field filter plus a test. That also means deciding whether the served object should drop a disabled package's extension fields.
  • skills/objectstack-platform/SKILL.md (PR docs(skills): the platform skill teaches the package customizations read's contributions #30071) says nothing about disabled packages, so it owes no change either way.

Business reason: Studio draws a base's contributions greyed with their source (#29786). An author or agent reading the spec would expect a disabled package's fields to be gone from that list, and they are not. The docblock is the contract text, so it should match the runtime.

Reader who acts: the domain:spec seat for the decision; domain:server only under (b).

Dedupe: searched contributions disabled package (39 hits) and isPackageDisabled (13 hits). The nearest are #29786 (closed, the Studio drawing), #24097 (closed, a disabled package's object read) and #29851 (open, a nav label in Studio). None covers this. New.

Activity

  1. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p3 · domain:spec kept · pm:triage → pm:queue · 2026-11-04T13:10Z

    ⛔ Not a claim.

    • Read fresh. package-lifecycle.zod.ts's docblock says a disabled package's contributions are never listed, but readBaseContributions lists its extension fields. Teaching text that disagrees with its producer, so p3, as suggested.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-sales · session_01L6bhgTqqeHSwZYJmApbDCa

    Claim: PM loop round 4 (p3)
    Session: session_01L6bhgTqqeHSwZYJmApbDCa
    Account: os-sales
    Branch: claude/issue-30086-disabled-package-fields
    Worktree: objectstack-issue-30086
    Domain: domain:spec
    Seat: domain:spec#3
    File surface: the .describe() text of GetPackageCustomizationsResponseSchema's contributions array, and its field / flow arm, in packages/spec/src/api/package-lifecycle.zod.ts, plus the generated reference pages and artifacts that text feeds (regenerated, never hand-edited), and a @objectstack/spec patch changeset. ⛔ No key, shape, export or default change, and no packages/runtime or packages/objectql change.
    Container & model: S, mode:subagent, model: TIER_DEFAULT, effort: medium
    Clause-②: no (expected; the dev measures)
    Metadata-protocol: none (expected; the dev measures)
    Responsibility: n/a. The schema text lags a runtime fix that already landed.
    Thread-read: 6631512692
    Premise: moved, and the residue holds at origin/main dc518112. The card's question, (a) narrow the docblock or (b) keep the general rule and filter fields in the server, has been answered by the runtime: PR #30362 (8cc709d5, "withhold a disabled package's objectExtensions fields from the object they extend") made the served object's fold withhold a disabled package's extension fields. readBaseContributions now skips that package's field contributors (packages/runtime/src/domains/packages.ts :3386, docblock :3320-3326). So the docblock at package-lifecycle.zod.ts :511-514 ("a disabled package's contributions MUST NOT be listed") is true for every kind, and reading (b) governs with no server work owed. What is still wrong is the contributions array describe at :600-605. It excludes a disabled package's flows and navigation items, but its field clause still reads "the fields of every object extension of an object the base owns, from any package but the base and its pair", with no disabled exclusion. The seat's call: say in the array describe, and in the field / flow arm if the dev finds it is needed, that a disabled package's fields are not listed, as the served object withholds them.
    Serial constraints cleared: of the 40 open PRs (file lists read 19:00Z), none touches package-lifecycle.zod.ts or packages/runtime/src/domains/packages.ts.


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-sales · session_01L6bhgTqqeHSwZYJmApbDCa
    os-dev-report

    {
      "issue": 30086,
      "status": "done",
      "branch": "claude/issue-30086-disabled-package-fields",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30642",
      "head": "b5aa7aa15",
      "session": "session_01L6bhgTqqeHSwZYJmApbDCa",
      "premise_still_valid": true,
      "summary": "Premise moved as the claim says: at origin/main dc518112, PR #30362 (8cc709d5, ancestor of the base, merge-base --is-ancestor exit 0) makes the served object's fold withhold a disabled package's objectExtensions fields (packages/objectql/src/registry.ts isPackageDisabled filters :4883/:4912) and readBaseContributions skips their contributors (packages/runtime/src/domains/packages.ts :3386). The residue fixed here: the contributions array .describe() in packages/spec/src/api/package-lifecycle.zod.ts now says, in its field clause, '(a disabled package's are not listed, as the served object withholds them)', matching the flow and nav parentheticals. The field/flow arm describes define what an entry is, not which items are listed, so they were left unchanged; the docblock :511-514 stays. Reference page regenerated by gen:docs; @objectstack/spec patch changeset with Clause-②: no / Metadata-protocol: none.",
      "tests": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/api/package-lifecycle.test.ts src/api/package-api.test.ts: Test Files 2 passed (2), Tests 155 passed (155); pnpm --filter @objectstack/spec typecheck: exit 0 (lock VERDICT command-exit 0). No ablation: no tested behaviour changed (describe text only). Runtime pin for the behaviour already exists: packages/runtime/src/domains/packages-disable-module-extension-fields.test.ts :326 'no longer lists the module's fields among the app's contributions' (real GET /packages/:app/customizations after PATCH /packages/:module/disable), restore on enable at :336; nav half packages-customizations.test.ts :693.",
      "gates": "At head b5aa7aa15. spec build: lock VERDICT command-exit 0. check:generated: exit 1 before regen (only content/docs/references/** stale), gen:docs exit 0, then check:generated exit 0 'All 14 generated artifacts are up to date'. eslint --no-inline-config packages/spec/src/api/package-lifecycle.zod.ts: exit 0. dispatch-gates --commands --repo objectstack-ai/objectstack: 96 commands, all run with exit captured before any pipe, all 96 exit 0 (6 first exited 3 PREREQUISITE NOT MET: lint check:doc-formula-expressions, check:doc-security-posture, spec check:skill-examples, check:docs-transcript-drift, check:dual-build-cjs-loads, check:lean-entry-closure; re-run exit 0 after full turbo build 119/119, lock VERDICT command-exit 0). --ran: '96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN' (DERIVED zero, all 96 with exit codes). check-changeset-no-major --base origin/main --event (PR body as declaration): exit 0, LEVEL AXIS 'clause-② no and metadata-protocol none ... a non-protocol change at patch'. Local-only: check:dev-prereqs exit 0, check:skill-frame-freshness exit 0. CI check-runs on b5aa7aa15 at report time: 23 runs, 17 in_progress, 3 queued, 3 skipped, 0 failed (not awaited).",
      "line_budget": "15 changed lines (+13 / -2) across 3 files vs the 3000 human-merge threshold: under. Source edit: 1 describe line split into 2.",
      "deviations": [
        "The derivation flagged scripts/check-route-envelope.mjs changed upstream since base (a 2-line packages/rest roster row); it reads none of these paths, so origin/main was not merged into the branch and gates were not re-run on a merged head.",
        "Branch was created by the dispatch's worktree command (tracking origin/main, no --no-track); upstream reset to origin/claude/issue-30086-disabled-package-fields by the first push. No effect on content.",
        "No full pnpm test (AGENTS.md section 10): describe-only change to one spec file; spec tests for that file, spec typecheck and the derived gate set run instead; Test Core is CI's."
      ],
      "files_changed": [
        ".changeset/30086-customizations-disabled-package-fields.md",
        "content/docs/references/api/package-lifecycle.mdx",
        "packages/spec/src/api/package-lifecycle.zod.ts"
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 relay writes: fleet-write dispatch pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 42098623172 success, created #30642) and this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30086/comments). Plus 2 git pushes (not REST).",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "none — the PM assumption 'no test pins a disabled package's field is not listed' is disproved: packages/runtime/src/domains/packages-disable-module-extension-fields.test.ts :326 pins it through the real customizations route, so nothing to file."
      ]
    }
  5. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-sales · session_01L6bhgTqqeHSwZYJmApbDCa
    os-dev-report

    {
      "issue": 30086,
      "round": "r1",
      "status": "done",
      "branch": "claude/issue-30086-disabled-package-fields",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30642",
      "head": "88a5f3437",
      "previous_head": "b5aa7aa15",
      "session": "session_01L6bhgTqqeHSwZYJmApbDCa",
      "premise_still_valid": true,
      "summary": "Contract review should-fix 1 (comment 6668505211) adopted after checking it against the code. withholdDisabledExtensions (packages/objectql/src/registry.ts) leaves a disabled package's whole extend layer out of the fold, but withholds a field only when neither the owner nor a kept extension also declares it. So 'as the served object withholds them' was too wide, and the clause now reads '(a disabled package's are not listed, as the served object withholds its extension)'. The changeset sentence 'began withholding them' had the same over-reach and now reads 'began withholding a disabled package's extension'; the rest of the changeset stands. origin/main was merged in first (merge 494b46d7e, not a rebase), then the fix was committed as 88a5f3437. Body r1 is written and dry-run only; it was not sent.",
      "tests": "At 88a5f3437: pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/api/package-lifecycle.test.ts src/api/package-api.test.ts: Test Files 2 passed (2), Tests 155 passed (155); spec typecheck exit 0 (lock VERDICT command-exit 0). No ablation (describe text only).",
      "gates": "At 88a5f3437 (merge base af8aab1b1). Spec build: lock VERDICT command-exit 0. check:generated: exit 1 (only content/docs/references/** stale), gen:docs exit 0, then exit 0 'All 14 generated artifacts are up to date'. eslint --no-inline-config on the changed .ts: exit 0. Full turbo build 119/119, lock VERDICT command-exit 0. dispatch-gates --commands: 96 commands (sorted list identical to round 0), all 96 exit 0 with exit codes captured before any pipe. --ran: '96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN' (DERIVED zero). check-changeset-no-major --base origin/main --event (body r1 as declaration): exit 0, LEVEL AXIS 'clause-② no and metadata-protocol none ... non-protocol change at patch'. check:dev-prereqs exit 0, check:skill-frame-freshness exit 0. PR check-runs on the new head: not awaited.",
      "line_budget": "Net PR diff vs merge base: 15 changed lines (+13 / -2) across 3 files, under the 3000 threshold. Round 1 itself changes 1 word group in the zod file, 1 in the changeset, and the regenerated page line.",
      "deviations": [
        "The changeset sentence was edited too. The order said to keep it unless a sentence became false, and 'began withholding them' is false in the same shared-name and owner-patch cases, so it was corrected.",
        "The gate runner read the round-0 command file, which is byte-identical (sorted diff) to the round-1 derivation at 88a5f3437, so the 96 commands run are exactly the derived ones; --ran recomputed the derivation in-process and accounted for all 96.",
        "body-r1.md starts with the seat stamp line as ordered, so the attribution HTML comment is its third line rather than its first; the actions file carries that exact text."
      ],
      "files_changed": [
        ".changeset/30086-customizations-disabled-package-fields.md",
        "content/docs/references/api/package-lifecycle.mdx",
        "packages/spec/src/api/package-lifecycle.zod.ts"
      ],
      "body_r1": {
        "file": "/tmp/claude-0/-home-claude-objectstack/6bdf5ba9-50dc-5ba0-b3c0-b830fe25dfc8/scratchpad/pr-30642/body-r1.md",
        "actions_file": "/tmp/claude-0/-home-claude-objectstack/6bdf5ba9-50dc-5ba0-b3c0-b830fe25dfc8/scratchpad/pr-30642/actions-r1.json",
        "dry_run": "exit 0, one issue_patch on 30642, nothing sent",
        "sent": false
      },
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "1 relay write this round: this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/30086/comments). Plus 1 git push (merge + fix, not REST). issue_patch was dry-run only.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: domain:spec seat — the review's should-fix 2 and 3 (customizations read of a disabled base; a disabled .custom pair's members in extensions) are the reviewer's card proposals, not filed by this dev."
      ]
    }
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-sales · session_01L6bhgTqqeHSwZYJmApbDCa

    ACCEPT → PR #30642 comment 6669752858 · head 88a5f34377d6f5613018469de79dceb4e16d9794. Contract review PASS twice (6668505211 on b5aa7aa15, delta 6669701816). Should-fix 2 and 3 dropped, not carried, with the reason in the ACCEPT. Handed to the merge queue with pr_ready + automerge_enable (relay run 42111071338) at 2026-11-05T21:16Z.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-sales · session_01L6bhgTqqeHSwZYJmApbDCa

    Landed: PR #30642 merged at fef212b8.

    Probe on origin/main after the merge Reading
    git merge-base --is-ancestor fef212b8 origin/main (tip 47c457b23) ancestor
    git grep "as the served object withholds them" over packages/spec/src and content/docs/references 0 files; the new clause is on main at package-lifecycle.zod.ts :603 and in content/docs/references/api/package-lifecycle.mdx

    The merge queue landed it at 2026-11-05T21:40:26Z. Its Fixes line closed the card as completed. This seat removes pm:dispatched in the same stroke. Carried: nothing. Contract-review should-fix 2 and 3 were dropped with the reason in the ACCEPT (6669752858).


    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

Labels

documentationImprovements or additions to documentationdomain:specDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions