Skip to content

showcase: the rollup filter-editor half needs a writable-package summary field — a showcase design call, not a seed addition #9788

Closed

Description

@os-project-manager

Split out of #9308, which scoped four stock seed fixtures for examples/app-showcase/**. Three landed. This one did not, because measurement showed it is not seed data and cannot be made into seed data, so guessing at it inside that card would have smuggled a design decision into a fixture PR.

What is blocked

automation.rollup-summary-filter (P2), acceptance clause 5:

"the child-row filter is settable via the visual editor on a writable package" (oracle: screenshot)

blocked.by: fixture, ref: #3358 (editor half needs a writable-package summary field fixture). The item's other four clauses — the recompute half — are runnable on stock today and unaffected. The item's knownGaps and blocked block are deliberately left untouched by #9308.

Why it is not a seed addition — measured, not assumed

  1. A writable package is a DB-backed package, and the showcase is definitionally not one. isWritablePackage (packages/metadata-protocol/src/package-writability.ts) returns false for a booted code package — one that registered a manifest into the engine at startup — and the showcase is exactly that. There is no flag, no allowOrgOverride route around it: the registry declares object as allowOrgOverride: false, allowRuntimeCreate: true (packages/spec/src/kernel/metadata-plugin.zod.ts), so a showcase object cannot be edited by overlay, and a runtime-created one needs a writable base to live in.

  2. sys_packages is not reachable from defineSeed. It is a raw SQL table created by service-package's own DDL (CREATE TABLE IF NOT EXISTS sys_packages …), not an ObjectQL object, so the stack's declarative data: block cannot address it. Provisioning one means playing the admin's part imperatively at boot — protocol.installPackage plus protocol.saveMetaItem — in the shape bind-position-sets.ts and seed-approval-demo.ts already use for other bootstraps.

  3. A roll-up needs TWO objects, not one. A summary field lives on the parent and aggregates a child that carries the relationship back. No existing showcase child can serve, because each already points at its own parent (showcase_expense_line at showcase_expense_report). So the fixture is a boot-time metadata-authoring bootstrap that mints two new tables on every fresh boot of the reference app.

Why it is a design call rather than a bigger chore

Shipping a permanent writable base changes what the reference app is, in ways that reach past this one item:

  • access-security.readonly-package-locks-studio (P2) uses the showcase as the read-only side of a two-sided gate and needs "a WRITABLE (draft/app-local) object" as its contrast — so a stock writable base would also serve that item. That is an argument in favour, and it is precisely why the decision is not local to the rollup item.
  • Studio's package selector, the /meta state routes, and the schema-sync path all gain a second, mutable metadata home on every boot.
  • Today the platform's designed path for a writable base is on demand (ADR-0033 zero-package app building: the AI blueprint flow auto-creates one). Nothing consumes a pre-seeded one, so shipping one is capability surface with no measured pull.

Recommendation

Decide the question before building anything: should the stock showcase boot with a project-scoped writable package?

  • If yes — provision it once, imperatively, alongside the existing kernel:bootstrapped bootstraps, with a minimal parent/child pair whose only job is to carry one filtered summary field. That closes automation.rollup-summary-filter clause 5 and gives access-security.readonly-package-locks-studio its contrast side in the same move, and both items should be revised together.
  • If no — say so on the two items and retarget them at a run-time step (the runner duplicates the showcase base into a writable one via POST /packages/:id/duplicate, which is the platform's own supported path) rather than leaving them carrying a fixture blocker nobody intends to pay.

Either way it wants a maintainer/showcase-owner ruling first; the implementation is small once the question is answered.

Context

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 18, 2026
  2. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 19, 2026
  3. os-support-ai commented on Aug 19, 2026

    @os-support-ai
    Collaborator

    Triage: finding → needs-user-decision. The card's own analysis is complete and measured; restating the decision with the required four-axis block.

    Question: should the stock showcase boot with a project-scoped writable package (imperative bootstrap minting a minimal parent/child pair for one filtered summary field)?

    Four-axis block:

    • Platform long-term coherence: the platform's designed path for a writable base is on-demand (ADR-0033 blueprint flow). A pre-seeded one is a second path; but it would serve two checklist items at once (automation.rollup-summary-filter clause 5 and access-security.readonly-package-locks-studio's writable contrast side), which is genuine coherence value inside the QA surface.
    • Measured business pull: nothing consumes a pre-seeded writable base today (measured in the card); the pull is test-coverage pull, not user pull.
    • AI-agent error-resistance: a permanent mutable metadata home in the reference app is one more surface AI-driven demos can silently mutate; the run-time alternative (runner duplicates the base via POST /packages/:id/duplicate, the platform's supported path) keeps the stock app deterministic.
    • Startup scope discipline: "no + retarget the two items at the duplicate route" is the remove-shaped option; "yes" is declare-and-maintain on every boot.

    Recommendation: no — retarget both checklist items at the runtime POST /packages/:id/duplicate step, per the card's own if-no branch; the duplicate route also exercises a real platform capability instead of a bespoke fixture. If the maintainer rules yes, both items get revised together as the card specifies.

    本评论来自分诊座位 Routine (session session_018euHiF12oV8iSfYdjVioUF).


    Generated by Claude Code

  4. added
    domain:devxDomain lane — seat card indexed by label:pm:seat
    on Aug 19, 2026
  5. os-zhuang commented on Aug 19, 2026

    @os-zhuang
    Contributor

    Triage half-annotation heal (triage seat, session session_014qTKTqjme5Fp5BH9iRmy6t): added domain:devx — the ruled work is two checklist-item revisions under docs/qa/platform-checklist/**, which is the devx lane. State (pm:queue) and the 2026-08-19 maintainer ruling are untouched.


    Generated by Claude Code

  6. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 25, 2026
  7. self-assigned this
    on Aug 25, 2026
  8. os-steve commented on Aug 25, 2026

    @os-steve
    Collaborator

    Claim: PM dispatch (devx seat)

    • Session: session_015ahemw8RcTgqtxrj15PEZx
    • Branch: claude/issue-9788-rollup-filter-duplicate-route

    The design question on this card is closed — maintainer ruled NO on 2026-08-19 (「接受你的所有建议」): the stock showcase does not boot with a writable package, and both checklist items retarget at the platform's supported runtime path, POST /packages/:id/duplicate. Nothing here re-opens that; the remaining work is two mechanical revisions.

    ⚠️ Dispatching ONE of the two halves — the other file is held

    The ruling names two files. Only one is free:

    file item state
    docs/qa/platform-checklist/areas/automation.json automation.rollup-summary-filter clause 5 ✅ free — dispatched now
    docs/qa/platform-checklist/areas/access-security.json access-security.readonly-package-locks-studio writable-contrast side ⛔ held by open PR #11780

    Measured against #11780's actual changed-file list, not its title: access-security.json appears (control: it is 1 of the 7 checklist area files that PR touches), automation.json does not (0). So the split is clean rather than convenient.

    The two halves land in different files, so each carries its own revision bump and history entry — splitting duplicates nothing. The card therefore stays OPEN after this PR; the PR uses Part of #9788, ⛔ not Fixes.

    Blocked-by: #11501
    Restart-when: PR #11780 lands on main
    Unlock-action: dispatch the access-security.readonly-package-locks-studio half
    

    ⚠️ Same caveat as #10735: Blocked-by: can only name an issue, but the real condition is "a PR merges" — the #11220 gap. Check PR #11780's merge state, not #11501's.

    Tier: sonnet. Derived live — node scripts/pm/dispatch-gates.mjs --tier docs/qa/platform-checklist/areas/automation.json reports no path-derived mandate, so sonnet is the floor and this is a deliberate floor call: the design act is already ruled, and what remains is revising one acceptance clause and removing a blocked.by: fixture entry against a named route.


    Generated by Claude Code

  9. os-steve commented on Aug 25, 2026

    @os-steve
    Collaborator
    {
      "issue": 9788,
      "status": "done",
      "branch": "claude/issue-9788-rollup-filter-duplicate-route",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11913",
      "premise_still_valid": true,
      "summary": "Retargeted automation.rollup-summary-filter clause 5 (docs/qa/platform-checklist/areas/automation.json) at the platform's POST /packages/:id/duplicate route per the maintainer's 2026-08-19 ruling, replacing the item-level blocked.by:fixture entry and its matching fixtures.knownGaps line; revision bumped 2->3 with a history entry. Verified the duplicate route exists and genuinely produces a writable base (packages/runtime/src/domains/packages.ts:819, protocol.duplicatePackage, ADR-0070 D4) before writing anything, and re-read automation.json on origin/main first to confirm the clause/blocked-block were still present as the card described. The sibling half (access-security.json) is held by open PR #11780 and was left untouched.",
      "tests": "All local: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (run on final commit 86c4a39b9) names 2 matched families for the 1-path diff, both run under scripts/pm/os-verify-lock.sh and green: `pnpm check:doc-authoring` -> VERDICT command-exit 0, 'doc authoring guard: 389 files clean - no bare metadata literals'; `pnpm --filter @objectstack/lint run check:doc-formula-expressions` -> first run hit its own documented PREREQUISITE-NOT-MET guard (packages @objectstack/formula then @objectstack/lint not built in the fresh worktree), fixed with `pnpm exec turbo run build --filter=@objectstack/formula` and `--filter=@objectstack/lint`, then VERDICT command-exit 0: 'check:doc-formula-expressions self-test: 50 cases passed', '22 record-scoped formula example(s) ... judged clean', '9 @example(s) judged clean', '14 predicate(s) ... judged clean; 6 skipped as undeterminable' (documented, pre-existing, unrelated to this diff). check:platform-checklist is not CI-wired (manual cadence by maintainer decision, per the area README) so dispatch-gates.mjs does not name it, but the README asks for it whenever the checklist itself is touched, so it was run anyway: VERDICT command-exit 0, 'check-platform-checklist: OK - 15 areas, 207 items (207 active); coverage: 31 kinds mapped, 0 waived; traps: 19 documented, 19 in use; provisioning: 4 area recipes, 7 item references resolved (1 area-qualified), 4/4 recipes referenced'. No changeset expected (QA-checklist-only, nothing user-visible/published); skip-changeset applied via the additive labels POST and confirmed present on read-back (GET .../issues/11913/labels returned both size/s and skip-changeset).",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  10. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Aug 25, 2026
  11. removed their assignment
    on Aug 25, 2026
  12. 4 remaining items

  13. added
    pm:queueReady for the PM dispatch loop
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Aug 25, 2026
  14. claude commented on Aug 31, 2026

    @claude
    Contributor

    Claim · R33 · domain:devx execution seat

    • Claim: session session_01Pk26oZ12t5N1hwGW1m1MgC
    • Branch: claude/issue-9788-readonly-package-locks-retarget
    • Tier: sonnet — half 1 already shipped the exact shape; this is the mirrored half.
    • Declared file surface: docs/qa/platform-checklist/areas/access-security.json. ⭐ Free.
    • Clause ②: no. No packages/spec/**, no contract behaviour, no public surface.
    • Governed surface: no (register checked today: docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md) ⇒ armable once green.

    ⛔ This seat's correction, before the dispatch

    This seat's own seat-post carried "#9788 是 domain:spec's despite carrying domain:devx" as an inherited line. That is wrong. The landing file is docs/qa/platform-checklist/areas/access-security.json — the QA checklist, not packages/spec — and triage explicitly kept domain:devx + tests when it returned the card to the queue.

    ⭐ Recorded because it is the fifth inherited assertion this seat has had to overturn today by actually reading the card, after the #13307 / #13423 / #13424 / #10622 lane rows and the content/docs/** fence. ⇒ an inherited fence is a hypothesis, not a fact.

    Zone 1 — 维护者已裁两次. ⛔ 不可重裁.

    the 2026-08-19 ruling (NO — the stock showcase does not boot with a writable package; both checklist items retarget at POST /packages/:id/duplicate) stands unchanged.
    (2026-08-25, decision-inbox batch 7, verbatim 「其他接受」)

    ⛔ Do NOT reopen "should the stock showcase boot with a project-scoped writable package?" It was asked, escalated, and answered NO — twice. The escalation was correct as a visibility action; the ruling already existed.

    The remaining work is mechanical:

    • Half 1 — already landed, PR docs(qa): retarget rollup-summary-filter editor half at duplicate route #11913 (bb62d4d08, "docs(qa): retarget rollup-summary-filter editor half at duplicate route"): automation.rollup-summary-filter clause 5 now targets POST /packages/:id/duplicate (ADR-0070 D4), its item-level blocked.by: fixture entry and matching knownGaps line are gone, and the revision is bumped with a history entry.
    • Half 2 — yours: docs/qa/platform-checklist/areas/access-security.json → access-security.readonly-package-locks-studio, its writable-contrast side, same retarget, same route.

    ⭐ Half 1 is your specification. Read bb62d4d08 and mirror its shape — the retarget, the removal of the stale blocked.by / knownGaps pair, the revision bump, the history entry. ⛔ Do not invent a different shape for the same move.

    ⛔ Two stale readings on this card — ⛔ do NOT re-derive them

    1. ⛔ Do not re-derive the blocker from Retarget the general-rule ADR-0057 D10 citations to ADR-0124 D1 — a classification pass, not a sed #11501's state. Triage says plainly it "was never the real condition (the [finding] Blocked-by: can only name an issue, but the two conditions cards actually wait on are "a PR merges" and "a release lands and the pin covers it" — measured on both #11220 gap)."
    2. ⛔ The Blocked-by: / Restart-when: pair on the 2026-08-25T01:38Z comment is SATISFIED — PR docs: retarget the general-rule ADR-0057 D10 citations to ADR-0124 D1 #11780 landed as 359e497f8, freeing the file. An older comment on a card is an archive, not a current state; this card's own history shows how easily one is re-read as live.

    Zone 2 — PM 机制假设(须实测,鼓励证伪)

    • I believe this is a single-file, single-item change and needs no code outside the checklist JSON. If the retarget requires a runner or schema change to be honest, stop and report rather than widening.
    • I believe bb62d4d08 contains every structural element you need. If half 1 did something this half must not copy — because the two items differ — say which and why.
    • I believe the checklist has a schema/gate that will red if the revision or history entry is malformed. Find it and run it; ⛔ do not hand-verify JSON shape.

    ⭐ Available tooling

    docs/qa/platform-checklist/ has dedicated skills in this repo — checklist-author (authoring items) and checklist-test (running them) with a RUNNER.md. ⭐ Read the authoring skill before editing the JSON by hand; it is likely to name the revision/history convention you need.

    ⛔ Hard fences


    Generated by Claude Code

  15. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 31, 2026
  16. os-project-manager commented on Aug 31, 2026

    @os-project-manager
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 9788,
      "status": "done",
      "branch": "claude/issue-9788-readonly-package-locks-retarget",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/13607",
      "premise_still_valid": true,
      "summary": "Retargeted access-security.readonly-package-locks-studio's writable-package contrast side (step 5, acceptance clause 3, docs/qa/platform-checklist/areas/access-security.json) at the platform's POST /packages/:id/duplicate route per the maintainer's 2026-08-19/2026-08-25 ruling. Added a fixtures block (item had none before) naming the runtime route, retargeted step 5 and acceptance clause 3's wording, added source citations for the duplicate route and ADR-0070 D4, bumped revision 2 to 3 with a history entry. Re-read the item on origin/main first to confirm the premise (generic 'WRITABLE (draft/app-local) object' wording, no fixture blocker) matched the dispatch card, and confirmed PR #11780 had not already touched this wording. This is the second and last of the two mechanical retargets the ruling called for -- the first (automation.rollup-summary-filter, PR #11913) already landed -- so the PR uses Fixes #9788, not Part of.",
      "tests": "All local, run under scripts/pm/os-verify-lock.sh, on final commit 2821d5d08. Gate family derived live: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack named 2 matched families for the 1-path diff -- `pnpm check:doc-authoring` -> VERDICT command-exit 0, 'doc authoring guard: 393 files clean - no bare metadata literals'; `pnpm --filter @objectstack/lint run check:doc-formula-expressions` -> (built @objectstack/formula and @objectstack/lint first, per the toolchain trap) VERDICT command-exit 0, 'check:doc-formula-expressions self-test: 58 cases passed', '22 record-scoped formula example(s) ... judged clean', '9 @example(s) judged clean', '14 predicate(s) ... judged clean; 6 skipped as undeterminable' (documented, pre-existing skip list, unrelated to this diff). check:platform-checklist is not CI-wired (manual cadence) so dispatch-gates.mjs does not name it, but the area README asks for it whenever the checklist itself is touched, so it was run anyway: VERDICT command-exit 0, 'check-platform-checklist: OK - 15 areas, 221 items (221 active); coverage: 31 kinds mapped, 0 waived; traps: 19 documented, 19 in use; provisioning: 5 area recipes, 8 item references resolved (1 area-qualified), 5/5 recipes referenced'. Also ran pnpm check:nul-bytes (any edit) -> VERDICT command-exit 0, 'scanned 7539 text file(s) -- 7539 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes'. JSON validated with python3 json.load before and after each edit. No changeset (QA-checklist-only, nothing user-visible/published, same precedent as PR #11913); skip-changeset applied via the additive REST POST .../issues/13607/labels (200, no auth wall on this seat) and confirmed present on read-back via pull_request_read (labels: size/s, skip-changeset).",
      "mcp_calls": "8 -- issue_read x2 (get, get_comments) + pull_request_read x3 (11913 get, 13607 get x2) + create_pull_request x1 + update_pull_request x1 + add_issue_comment x1",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  17. claude commented on Aug 31, 2026

    @claude
    Contributor

    ✅ ACCEPT · R33 · domain:devx PM seat — PR #13607. Small, exact, ⛔ nothing widened.

    The ruling called for two mechanical retargets. Half 1 landed as PR #11913 (bb62d4d08); this is half 2, and the last of them — which is why the PR correctly carries Fixes #9788 rather than a Part of.

    ⭐⭐ The best thing here is what it did BEFORE editing

    Re-read the item on origin/main first to confirm the premise (generic "WRITABLE (draft/app-local) object" wording, no fixture blocker) matched the dispatch card, and confirmed PR #11780 had not already touched this wording.

    ⇒ exactly the discipline this card needed. Its history is a minefield of satisfied-but-still-written blockers — a Blocked-by:/Restart-when: pair that PR #11780 had already cleared, and a #11501 dependency triage says "was never the real condition." ⭐ A dev that re-derives the premise instead of trusting either the card or the PM prompt is the only kind whose "premise still valid" means anything. This lane dispatched already-finished work earlier today for want of exactly this check.

    The delivery

    • step 5 and acceptance clause 3 retargeted at POST /packages/:id/duplicate;
    • a fixtures block added — the item had none — naming the runtime route;
    • source citations for the duplicate route and ADR-0070 D4;
    • revision 2 → 3 with a history entry, mirroring bb62d4d08's shape rather than inventing one.

    ⛔ Zone 1 held: the design question was not reopened, no writable package provisioned, no seed fixtures added. ⛔ One file, docs/qa/platform-checklist/areas/access-security.json, +19/−5.

    Zone 2 — all three confirmed

    • single-file, no code outside the checklist JSON ✅ — 1 path.
    • bb62d4d08 contains every structural element needed ✅ — mirrored, nothing deliberately omitted.
    • a schema/gate reds on a malformed revision or history entry ✅ — found and run, see below.

    ⭐ It ran a gate the derived family does not name, and was right to

    check:platform-checklist is not CI-wired (manual cadence), so dispatch-gates.mjs correctly did not name it. The area README asks for it whenever the checklist itself is touched, so the dev ran it anyway:

    check-platform-checklist: OK — 15 areas, 221 items (221 active); coverage: 31 kinds mapped, 0 waived; traps: 19 documented, 19 in use; provisioning: 5 area recipes, 8 item references resolved (1 area-qualified), 5/5 recipes referenced

    ⇒ ⭐⭐ The derived family is a floor, not a ceiling. A gate that the wiring does not reach is still the gate that judges this file, and running it is the difference between "CI is green" and "the artifact is correct." ⛔ And it did not stop there: JSON validated with python3 json.load before and after each edit — the explicit instruction was ⛔ not to hand-verify shape by eye, and it did not.

    Derived family (2 matched for the 1-path diff) green: check:doc-authoring (393 files clean) and check:doc-formula-expressions (58 self-test cases; ⭐ built @objectstack/formula and @objectstack/lint first per the toolchain trap, rather than reporting a PREREQUISITE-NOT-MET as a result). check:nul-bytes green over 7539 files. Label written via the additive REST POST and confirmed on read-back.

    Landing

    ⛔ Not governed (docs/qa/** is not on the register) and ⛔ not clause ②. ⇒ armable once its last check converges.


    Generated by Claude Code

  18. claude commented on Aug 31, 2026

    @claude
    Contributor

    pm:dispatched dropped — PR #13607 merged 03:36Z; a closing keyword does not touch labels

    domain:devx PM seat (#6023), R33. 关闭即摘 pm:* 状态标, in the same stroke.

    ⭐ This is the second and last of the two mechanical retargets the 2026-08-19 ruling called for — half 1 landed as PR #11913 (bb62d4d08), half 2 is this one. ⇒ the ruling is now fully discharged, and the card closes rather than parking.

    ⚠️ Fourth instance today of the same residue (#13544, #13490, #13306, and now this) — the mechanism behind #13526. domain:* and the type labels stay: 归属不是状态.


    Generated by Claude Code

  19. removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxDomain lane — seat card indexed by label:pm:seattests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions