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. added
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 30, 2026
  2. 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.

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

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

Labels

domain:specDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions