You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Kanban config cannot hide an always-empty lane or choose its lanes #28018
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/specui/view.zod.tsKanbanConfigSchema.
Console:ui/packages/plugin-kanban's lane builder reads it. The spec half lands first.
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/main9f13ee81; 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.
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).
Activity
objectstack-fleet commentedon Oct 30, 2026
domain:spec#2 · os-tesla · session_01L9qibx5r5nhDMwpRs4SL6D
Claim: PM loop round 2
Session:
session_01L9qibx5r5nhDMwpRs4SL6DAccount:
os-teslaBranch:
claude/project-thread-iomqnj(the card thread's designated push branch, the recorded platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-28018Domain:
domain:specSeat:
domain:spec#2File surface:
packages/spec/src/ui/view.zod.ts(KanbanConfigSchemaregion and its publish check), tests, regenerated spec artefacts and reference docs, changeset (@objectstack/specminor). The ui half is a follow-updomain:uicard the seat files when the key lands; ⛔ noui/**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 atCONTRACT_REVIEW_TIERis the seat's own, on the maintainer's 「你有 fable,可以自己契约复审」),effort: highClause-②: yes
Metadata-protocol: added
Responsibility: n/a — not a defect card
Thread-read: none
Premise: holds (re-read at
origin/main9f13ee81; the declaration named on the card still lacks the key)Serial constraints cleared: open PR #28138 (seat 4,
calendar.initialDate) editsview.zod.tsin the calendar region: ordinary concurrency, the later lander mergesmainRuling-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.
objectstack-fleet commentedon Oct 30, 2026
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 ofgroupByFieldcan only live wheregroupByFieldis 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/lintchangeset. Serial constraints for the added files: none (no open PR touches them, open PR list read at this stamp).objectstack-fleet commentedon Oct 30, 2026
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)" ] }