dock-state

The Dock's agent-state folds — one fenced source of truth in @kolu/terminal-vocab, the load-bearing order≠colour split, and the one "is something happening" question. Use when editing agentProjection

SKILL.md

GitHub

The Dock's agent-state folds

kolu's on-canvas Dock (packages/client/src/canvas/dock) renders agent state through fenced folds that live once in @kolu/terminal-vocab/agentProjection.

  • One source of truth. The agent-state vocabulary — how AgentInfo['state'] folds to a coarse class — lives once in agentProjection, as state satisfies never-fenced folds: agentUrgency (needs-you ranking), agentPaintClass (pip/glyph colour), attentionClass + attentionActive (which attention list a terminal is in, and whether something is happening in it), alertClass (notify membership). Never re-derive any of these with a hand-rolled switch over the state literals — import the fold. A new state literal must force one decision, in the fenced fold, not silently route through a copy.

  • The order≠colour split is load-bearing — don't collapse it. A just-finished waiting agent RANKS idle (agentUrgency) but PAINTS linger (agentPaintClass) — the dimmed "it just finished" cue, distinct from the full-strength awaiting a genuinely blocked agent wears. Every surface keeps that decoupling. Since #2141 no dock surface SORTS at all (row order is structural), so the live form of the split is select by paint, colour by paint, and never re-derive either from metadata: the pinned needs-you strip takes its membership from pip (the attention class), the same fold its violet capsule paints from — see statePipBind's asking, which names itself the ONE test for "blocked on you". awaiting_user (genuinely blocked) is what earns the strip; waiting (the post-turn lull) does not. agentUrgency remains the shared RANK vocabulary, still pinned by the dock parity test.

  • "Is something happening" is ONE question with ONE answer. attentionActive(attentionClass(agent, finished), live) decides a mark's MOTION and every count that summarises a scope — a host tab, a repo section header. Never fold your own notion of busy for a count: four such notions once coexisted, and every attention bug in PR #2019 was two of them disagreeing (a tab reading 2 beside three moving marks). It takes padi's EF2 finish verdict and raw byte motion as well as the agent state, so it lives beside — not inside — the state-only folds above.

  • The folds' home is settled — don't repatriate them. They live in the shared @kolu/terminal-vocab package even though the Dock is today their only paint consumer. That is history, not misplacement: the browser fleet mirror (pulam-web) they once also served died with the pulam world (the W2.3 burial deleted every pulam* package), and padi-tui is deliberately not a paint mirror (a thin uncoloured status/watch/wait/create CLI — no needs-you sort, no paint classes, no alert). Judging a fold's home by today's consumer count and "tidying" it into a kolu-local module is churn, not structure — and if a fleet mirror ever returns, it consumes these same folds, and the old two-surface sync contract (git history of this file) revives with it.