Skip to content

Kanban config cannot hide an always-empty lane or choose its lanes #28018

Closed

Description

@objectstack-fleet

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

Filing gate: ③ triage-directed. The order on #27386 said: take what is ui-only, card the rest. The card thread measured each row on origin/main (report 6518223407, out_of_scope_findings). Rows 2 and 4 are taken in PR #28017.
Reach: any board grouped on a select field whose view filter keeps an option empty. HotCRM's Task Board always shows an empty Completed lane (#27386 row 1).
Reader who acts: domain:spec first (the config key), then domain:ui (plugin-kanban's lane builder).
Duplicate search: search_issues "kanban hide empty lanes choose lane list hideEmptyLanes" → #13692 (fallback lane for empty values, closed) and #27099 (drop-blocked lane), neither this.

Observed

KanbanConfigSchema declares groupByField, summarizeField, titleField and columns only. A board grouped on a select field draws one lane per option, including a lane the view's own filter always keeps empty.

Wanted

  • Spec: a lane key on the kanban config: an ordered lane list (the option values to draw, in order), or a boolean hideEmptyLanes. Landing: packages/spec ui/view.zod.ts KanbanConfigSchema.
  • Console: ui/packages/plugin-kanban's lane builder reads it. The spec half lands first.

Dedupe words: kanban hideEmptyLanes, kanban lane list, kanban empty column hide.

Related: #27386 (row 1).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibx5r5nhDMwpRs4SL6D

    Claim: PM loop round 2
    Session: session_01L9qibx5r5nhDMwpRs4SL6D
    Account: os-tesla
    Branch: claude/project-thread-iomqnj (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-28018
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: packages/spec/src/ui/view.zod.ts (KanbanConfigSchema region and its publish check), tests, regenerated spec artefacts and reference docs, changeset (@objectstack/spec minor). The ui half is a follow-up domain:ui card the seat files when the key lands; ⛔ no ui/** and no governed path (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: TIER_DEFAULT (Clause-②: yes ⇒ default judgment tier to build; the contract review at CONTRACT_REVIEW_TIER is the seat's own, on the maintainer's 「你有 fable,可以自己契约复审」), effort: high
    Clause-②: yes
    Metadata-protocol: added
    Responsibility: n/a — not a defect card
    Thread-read: none
    Premise: holds (re-read at origin/main 9f13ee81; the declaration named on the card still lacks the key)
    Serial constraints cleared: open PR #28138 (seat 4, calendar.initialDate) edits view.zod.ts in the calendar region: ordinary concurrency, the later lander merges main
    Ruling-ref: none on the shape; dispatch authority = the maintainer's 「p3 也可以开发」 (2026-10-30T12:41Z) and 「每个座位并发可以5」 (2026-10-30T15:04Z); the card's filing gate ③ (triage-directed)

    Dispatched 2026-10-30T15:12Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.

  2. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibx5r5nhDMwpRs4SL6D

    Claim amendment · file surface · #28018 · 2026-10-30T15:13Z

    Amends claim 6526161926 (same session, same branch claude/project-thread-iomqnj). The card thread measured that spec cannot see the object, so the publish refusal of a lane value that is not an option of groupByField can only live where groupByField is already checked against the object: packages/lint/src/validate-list-view-field-refs.ts (the reference-integrity suite the runtime publish gate runs). The seat takes it in this PR (option A).

    File surface adds: packages/lint/src/validate-list-view-field-refs.ts (or a sibling rule), its rule-explanations entry, tests, @objectstack/lint changeset. Serial constraints for the added files: none (no open PR touches them, open PR list read at this stamp).

  3. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-tesla · session_01L9qibxL3MYcTjfshb8eeK3

    os-dev-report

    {
      "issue": 28018,
      "status": "done",
      "branch": "claude/project-thread-iomqnj",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28196",
      "session": "session_01L9qibxL3MYcTjfshb8eeK3",
      "premise_still_valid": true,
      "head": "ea4b11b5",
      "summary": "KanbanConfigSchema gains optional kanban.lanes: an ordered list of stored option values of groupByField (SystemIdentifier entries, min 1, no default; a record whose value is not listed lands in Uncategorized, never hidden). The object-aware half lives in @objectstack/lint validate-list-view-field-refs.ts (surface amended by the seat, option A): list-view-kanban-lane-unknown (error, a lane that is not an inline option of the group field, with Did-you-mean) and list-view-kanban-lane-repeated (error, at the second entry, judged with no field map); both explained in os explain. liveness kanban row notes lanes at planned strength.",
      "tests": "head ea4b11b5: lint test 179 files 7650 passed 5 skipped; spec vitest src/ui + form reconciliation + type-alias pin 167 files 5950 passed; lint + spec typecheck exit 0; new files lint 11/11, spec 5/5. Ablation via ablation-replace.mjs: membership short-circuit -> 3 failed/8 passed; repeat never fires -> 3 failed/8 passed; both legs restored to HEAD blob 34aa7c35, git diff HEAD empty.",
      "gates": {
        "derived": 104,
        "ran": 104,
        "not_measured": 0,
        "unrun": 0,
        "nonzero": [],
        "reconcile": "dispatch-gates --ran: 104 derived, 104 run, 0 NOT-MEASURED, 0 UNRUN",
        "local_only": [
          "node scripts/check-dev-prereqs.mjs :: exit 1 (ui/ packages unbuilt locally; diff touches no ui/**)"
        ],
        "ran_list": [
          "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
          "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
          "node scripts/check-adr-links.mjs :: exit 0",
          "node scripts/check-adr-links.mjs --self-test :: exit 0",
          "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
          "node scripts/check-closing-keyword-parity.mjs :: exit 0",
          "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
          "node scripts/check-comment-mask-adoption.mjs :: exit 0",
          "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
          "node scripts/check-comment-mask-corpus.mjs :: exit 0",
          "node scripts/check-dev-prereqs.mjs --self-test :: exit 0",
          "node scripts/check-doc-route-spelling.mjs --advisory :: exit 0",
          "node scripts/check-doc-route-spelling.mjs --self-test :: exit 0",
          "node scripts/check-docs-section-name.mjs :: exit 0",
          "node scripts/check-docs-section-name.mjs --self-test :: exit 0",
          "node scripts/check-dts-emitted.mjs --self-test :: exit 0",
          "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
          "node scripts/check-empty-changeset.mjs --self-test :: exit 0",
          "node scripts/check-issue-citations.mjs :: exit 0",
          "node scripts/check-plugin-teardown-shape.mjs :: exit 0",
          "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
          "node scripts/check-section-landing-index.mjs :: exit 0",
          "node scripts/check-section-landing-index.mjs --self-test :: exit 0",
          "node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0",
          "node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0",
          "node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0",
          "node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
          "node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
          "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
          "node scripts/release-pending-publish.mjs --self-test :: exit 0",
          "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
          "pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0",
          "pnpm --filter @objectstack/spec run check:api-surface :: exit 0",
          "pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0",
          "pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0",
          "pnpm --filter @objectstack/spec run check:docs :: exit 0",
          "pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0",
          "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
          "pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
          "pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0",
          "pnpm --filter @objectstack/spec run check:export-origins :: exit 0",
          "pnpm --filter @objectstack/spec run check:exported-any :: exit 0",
          "pnpm --filter @objectstack/spec run check:generated :: exit 0",
          "pnpm --filter @objectstack/spec run check:liveness :: exit 0",
          "pnpm --filter @objectstack/spec run check:llms-txt :: exit 0",
          "pnpm --filter @objectstack/spec run check:skill-examples :: exit 0",
          "pnpm --filter @objectstack/spec run check:skill-refs :: exit 0",
          "pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
          "pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
          "pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
          "pnpm check:changeset-gate-self-tests :: exit 0",
          "pnpm check:ci-filter-parity :: exit 0",
          "pnpm check:closed-ceremony-text :: exit 0",
          "pnpm check:corpus-claim-drift :: exit 0",
          "pnpm check:cross-package-test-inputs :: exit 0",
          "pnpm check:dispatcher-error-vocabulary :: exit 0",
          "pnpm check:doc-anchors :: exit 0",
          "pnpm check:doc-authoring :: exit 0",
          "pnpm check:doc-frontmatter :: exit 0",
          "pnpm check:docs-audit-scope :: exit 0",
          "pnpm check:docs-redirects :: exit 0",
          "pnpm check:docs-single-h1 :: exit 0",
          "pnpm check:docs-spec-enumerations :: exit 0",
          "pnpm check:docs-transcript-drift :: exit 0",
          "pnpm check:driver-memory-census :: exit 0",
          "pnpm check:dts-closure :: exit 0",
          "pnpm check:dual-build-cjs-loads :: exit 0",
          "pnpm check:engine-double-contract :: exit 0",
          "pnpm check:gitlink-declared :: exit 0",
          "pnpm check:issue-citations :: exit 0",
          "pnpm check:keyed-text-bounds :: exit 0",
          "pnpm check:lean-entry-closure :: exit 0",
          "pnpm check:logger-receiver-detach :: exit 0",
          "pnpm check:merge-driver :: exit 0",
          "pnpm check:nul-bytes :: exit 0",
          "pnpm check:objectql-double-limit :: exit 0",
          "pnpm check:org-identifier :: exit 0",
          "pnpm check:page-declaration-shape :: exit 0",
          "pnpm check:platform-checklist :: exit 0",
          "pnpm check:platform-object-tenancy-census :: exit 0",
          "pnpm check:pm-changeset-deadline-census :: exit 0",
          "pnpm check:pm-prior-rulings :: exit 0",
          "pnpm check:published-files :: exit 0",
          "pnpm check:published-readme-links :: exit 0",
          "pnpm check:query-options-erasure :: exit 0",
          "pnpm check:react-page-adapter-contract :: exit 0",
          "pnpm check:refd-timer-probe :: exit 0",
          "pnpm check:registry-log-declared :: exit 0",
          "pnpm check:rest-log-spy-declared :: exit 0",
          "pnpm check:role-word :: exit 0",
          "pnpm check:skill-identifier-liveness :: exit 0",
          "pnpm check:slot-lookup :: exit 0",
          "pnpm check:sourcemap-no-sources-content :: exit 0",
          "pnpm check:spec-docblock-symbol-anchors :: exit 0",
          "pnpm check:spec-parsed-alias :: exit 0",
          "pnpm check:system-context-census :: exit 0",
          "pnpm check:test-source-alias :: exit 0",
          "pnpm check:tier-file-adoption :: exit 0",
          "pnpm check:type-check-coverage :: exit 0",
          "pnpm check:type-check-debt :: exit 0",
          "pnpm check:undeclared-dep-imports :: exit 0",
          "pnpm check:vendor-version-stamps :: exit 0",
          "pnpm check:watch-hint-literal :: exit 0",
          "pnpm check:where-matcher :: exit 0"
        ],
        "ci": "in_progress at report time; seat reads PR check-runs"
      },
      "line_budget": {
        "files": 12,
        "additions": 457,
        "deletions": 11,
        "changed_lines": 468,
        "generated": [
          "content/docs/references/api/protocol.mdx",
          "content/docs/references/data/object.mdx",
          "content/docs/references/ui/view.mdx",
          "packages/spec/authorable-surface/ui.json"
        ]
      },
      "files_changed": [
        ".changeset/28018-kanban-lanes.md",
        "content/docs/references/api/protocol.mdx",
        "content/docs/references/data/object.mdx",
        "content/docs/references/ui/view.mdx",
        "packages/lint/src/index.ts",
        "packages/lint/src/rule-explanations.ts",
        "packages/lint/src/validate-list-view-field-refs.ts",
        "packages/lint/src/validate-list-view-kanban-lanes.test.ts",
        "packages/spec/authorable-surface/ui.json",
        "packages/spec/liveness/view.json",
        "packages/spec/src/ui/kanban-config-lanes.test.ts",
        "packages/spec/src/ui/view.zod.ts"
      ],
      "deviations": [
        "packages/lint/src/index.ts (2 export lines + comment) is outside the amended surface: rule-explanations.test.ts requires every explained rule id to be a barrel-exported constant.",
        "Duplicate-lane check placed in lint, not as a superRefine in view.zod.ts: the superRefine made the spec build refuse (new sites in 16 entries of the shrink-only dropped-refinements.baseline.json); spec keeps only JSON-Schema-projectable checks (minItems, identifier pattern).",
        "Session-context post-PR step (assign os-tesla, request review via MCP) not performed: FRAME forbids MCP writes, assigning and requesting review; the seat lands."
      ],
      "decision_for_maintainer": "Shape taken: ordered lane list kanban.lanes. Not taken: hideEmptyLanes boolean, because it hides lanes as data moves (an empty lane stops being a drop target) and cannot order lanes; the list answers both choose and order for the HotCRM task board.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "3 — mcp__github__issue_read x3 (get, get_comments x2); 0 write tools",
      "api_writes": "2 — fleet-write relay pr_create (objectstack-ai/objectstack#28196); post-stamped os-dev-report comment on #28018",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: the seat · follow-up domain:ui card: ui/packages/plugin-kanban ObjectKanban.tsx#effectiveColumns reads kanban.lanes (draw only the listed lanes, in order; off-lane cards to Uncategorized), then the liveness kanban note drops planned · dedupe words: kanban lanes renderer, plugin-kanban lane list, kanban.lanes console",
        "carrier: the seat · Skills-docs follow-up owed: skills/objectstack-ui/rules/list-views.md kanban example teaches lanes once the console reads it · dedupe words: kanban lanes skill, list-views kanban lanes",
        "carrier: none · noted, not filed · membership not judged for picklist-bound or option-less group fields (stated in docblock and os explain)"
      ]
    }
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