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. 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

  2. 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

  3. 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

  4. 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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions