Skip to content

spec(dashboard): the duplicate globalFilters key refusal (#29023) has no stored-row detector and no save-door pin #29212

Closed

Description

@objectstack-fleet

domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

Filing gate: ① a follow-up the #29023 implementer named (os-dev-report 6572629846, open_questions[1] and [2]), kept out of PR #29162 to hold that PR to its claimed surface. The seat chose option A on both. ⛔ Not a claim. No grade: triage sets it.

What is missing once PR #29162 lands

  • Stored-row listing. DashboardSchema.globalFilters now refuses two entries under one filter key (name, else field) with the predicate in packages/spec/src/ui/duplicate-global-filter-names.ts. os migrate meta --stored does not list a stored dashboard this refuses. The sibling refusal for objects has a detector, objectDuplicateActionName in packages/spec/src/conversions/refused-shapes.ts (REFUSED_STORED_SHAPES), that reads its predicate. Add dashboardDuplicateGlobalFilterName the same way, with its pinning test.
  • Save-door pin. The implementer measured the door: PUT /api/v1/meta/dashboard answers 422 INVALID_METADATA at globalFilters.1.name in default, publish and draft mode, and stores nothing. Nothing pins it in packages/metadata-protocol. Add a test shaped like packages/metadata-protocol/src/protocol.object-duplicate-action-name-refusal.test.ts.

Measured blast radius: 0 authored dashboards repeat a key (95 globalFilters arrays, 14 with more than one entry). So both items are guards, not migrations.

Reader who acts: domain:spec (the detector) and domain:server / metadata-protocol owners (the door pin), as one card or two, at triage's call. Wait for PR #29162 to merge, since both read its predicate.

Dedupe: searched duplicate global filter detector refused-shapes, globalFilters REFUSED_STORED_SHAPES. Only #29023 and its PR. New.

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p3 · domain:spec · pm:queue (from finding) · 2026-11-02T09:56Z

    ⛔ Not a claim.


    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 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

    Claim: PM loop round 1 · 2026-11-02T12:06Z
    Session: session_01ADHkmSduNGC2SZXszyrNut (seat); dev = card thread session_01ADHkmQfSq34mnnkWb6STfV
    Account: os-steve
    Branch: claude/project-thread-jprd1x
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: packages/spec/src/conversions/refused-shapes.ts (a dashboardDuplicateGlobalFilterName detector calling the #29162 predicate) and its pinning test; one new test file packages/metadata-protocol/src/protocol.dashboard-duplicate-global-filter-name-refusal.test.ts (test-only in that package); any ledger/listing a gate names; root .changeset/; ⛔ not duplicate-global-filter-names.ts or dashboard.zod.ts (sibling #29213) (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); a detector and a door pin for a published refusal, one CONTRACT_REVIEW_TIER review by the seat before landing, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: packages/spec conversions/refused-shapes.ts lists no stored dashboard #29162 refuses; packages/metadata-protocol pins no save-door 422 for it | the boot warning and Studio badge show it, os migrate meta --stored does not | operators migrating stored rows; measured blast radius 0 authored dashboards (card body)
    Thread-read: 6574212312
    Premise: holds (on origin/main after 38a278b7, REFUSED_STORED_SHAPES registers objectDuplicateActionName and no dashboard detector; no packages/metadata-protocol test pins the dashboard duplicate-key 422); the dev re-measures the --stored listing first
    Serial constraints cleared: #29162 (seat 1, the predicate) merged as 38a278b7; sibling #29213 (this seat, parallel) holds the predicate module and dashboard.zod.ts, disjoint; if it lands first and changes the predicate, this branch merges main and follows it

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmQfSq34mnnkWb6STfV
    os-dev-report

    {
      "issue": 29212,
      "status": "done",
      "branch": "claude/project-thread-jprd1x",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29399",
      "session": "session_01ADHkmQfSq34mnnkWb6STfV",
      "premise_still_valid": true,
      "summary": "Added dashboardDuplicateGlobalFilterName to REFUSED_STORED_SHAPES (id ui-dashboard-global-filter-duplicate-name-refused, the #29023 D3 entry); it calls duplicateGlobalFilterNames, copies no logic, and reports at dashboards[i].globalFilters[j].name or .field, the site the parse refuses. Added protocol.dashboard-duplicate-global-filter-name-refusal.test.ts pinning 422 INVALID_METADATA at globalFilters.1.name with nothing stored in no-mode, publish and draft, plus a distinct-name control per mode. Premise measured on 5a2bdf9c: a stored dashboard with two filters named r gave 0 TODOs, the object control gave 1. Patch changeset for @objectstack/spec.",
      "tests": "head 0b17ca15 (after one origin/main merge): spec test 791/791 files, 23394 passed; spec check:generated all 14 up to date; metadata-protocol test 304 passed 4 skipped, 22142 passed; cli unit meta.report-order 21/21. At b057b3f2: spec + metadata-protocol typecheck exit 0, same suites green. New spec cases 3 (refused-shapes.test.ts 83/83), new door file 6/6. Ablation: ablation-replace --delete on the registry line gives 3 failed | 80 passed (83), restored blob == HEAD, git diff HEAD empty (two earlier --replacement attempts refused by the script as no-ops, nothing mutated).",
      "gates": "dispatch-gates --commands derived 86 families from 5 paths, identical on b057b3f2 and 0b17ca15; --ran on each head: 86 derived, 86 run, 0 NOT-MEASURED, 0 UNRUN (exit 0). check:engine-double-contract needed --write (3 pinned rows committed), then exit 0. check:dual-build-cjs-loads exit 3 on round 1 (unbuilt packages), exit 0 after building them and exit 0 on the merged head. eslint on the 3 changed files exit 0. Offline check-changeset-no-major --event exit 0 (no / none, patch); check-partof-closing-keyword exit 0. CI check-runs: in_progress at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "files_changed": [
        "packages/spec/src/conversions/refused-shapes.ts",
        "packages/spec/src/conversions/refused-shapes.test.ts",
        "packages/metadata-protocol/src/protocol.dashboard-duplicate-global-filter-name-refusal.test.ts",
        "scripts/engine-double-contract.pinned.json",
        ".changeset/29212-dashboard-duplicate-filter-stored-listing.md"
      ],
      "line_budget": "+222 / -1 across 5 files (under the 3000-line human-merge threshold)",
      "deviations": [
        "scripts/engine-double-contract.pinned.json: off the claimed surface by name, written by the gate's own --write for the new test file's three pinned doubles (claim covers 'any ledger a gate names').",
        "PR opened with no assignee or reviewer: the session harness asks for an MCP issue_write/update_pull_request, which the standard order and os-dev.md forbid; skipped.",
        "Merged origin/main once (27 commits) before pr_create and re-ran consumers and all 86 gates on the merge head."
      ],
      "mcp_calls": "4 — mcp__github__issue_read x2 (card comments), mcp__github__pull_request_read x2 (#29370 get, #29399 get); no write tools",
      "api_writes": "2 — fleet relay pr_create (objectstack-ai/objectstack#29399), post-stamped issue comment on #29212 (this report)",
      "open_questions": [
        {
          "question": "The #29023 D3 entry's acceptanceCriteria (18.ui-dashboard-global-filter-duplicate-name-refused.ts) does not say os migrate meta --stored lists the row, unlike the object sibling's. Add the sentence?",
          "options": ["A: add one sentence in a follow-up spec edit (entry is unreleased, its changeset is still pending)", "B: leave it; the changeset of this PR states the listing"],
          "recommendation": "A, because the upgrade guide reads the D3 entry, not the changeset; it was outside the claimed file surface so this PR left it alone."
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "class: b · reach: exception: maintainer (seat-directed carrier) · PR #29370 (card #29213) adds reservedDateRangeGlobalFilters, a second refusal with its own D3 entry ui-dashboard-global-filter-reserved-date-range-refused; REFUSED_STORED_SHAPES does not list it, and #29370 was an open draft when #29399 opened, so no predicate on main to call · dedupe words: reserved dateRange stored listing, refused-shapes dateRange, migrate meta stored dateRange · carrier: seat follow-up"
      ]
    }

    Stamped 2026-11-02T14:05Z.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

    Landed: PR #29399, merged as 8b65633d at 2026-11-02T14:54Z.
    ACCEPT → PR #29399 comment 6579765109 · contract review PASS 6579729026 (0b17ca15).
    Follow-up: the #29023 D3 entry's acceptanceCriteria sentence ("--stored lists the row") rides on the stored-row detector card for #29213's reservedDateRange refusal, which the seat files when PR #29370 lands.

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

Metadata

Metadata

Assignees

Labels

domain: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