Backlog item: BI-C2C16582
Epic: EP-WORK-CONVERGENCE
Status: Current
Definition/instance realization: shipped in PR #4648 under EP-WORK-CONVERGENCE; design and plan in the workroom definition projection spec
Founder-directed 2026-08-15: Workroom is the canonical name for what we claim and how we work. This page is the single place that says what the word means at each layer, so the two vocabularies that merged here do not re-diverge.
The three layers
| Layer | Name | What it is | Where it lives |
|---|---|---|---|
| Durable record | Workroom | The claim. Names the backlog item, holds the lease, records branch / base SHA / worktree / PR, accumulates evidence. | Workroom + WorkroomActivity Prisma models |
| Projection | WorkCase | The business-language projection of a unit of work, whatever produced it. | WORK_CASE_SOURCE_REGISTRY |
| Surface | Workroom view | What a person sees and acts in: participants, cycles, outcome packet, structure. | WorkroomView, WorkroomCycle, WorkroomOutcomePacket, apps/web/components/workspace/workroom/ |
Read it as one sentence: a Workroom is claimed as a record, projected as a WorkCase, and rendered as a Workroom view.
Definition and instance are an orthogonal axis
The three layers above describe how actual work is coordinated. They do not by themselves distinguish a reusable room design from one place where that design is used. At the business surface, use these two qualified phrases:
| Business phrase | Formal architecture | Meaning |
|---|---|---|
| Workroom definition | A projection of WorkUnitDefinition, its owning OperatingFlow / Stage, archetype profile, and WORK_CASE_SOURCE_REGISTRY policy |
The versioned blueprint for work that can recur. It defines the intended outcome, trigger, work shape, controls, default participants, evidence, measures, and composition policy. It is not an occurrence, lease, branch, or second work ledger. |
| Workroom instance | A WorkOccurrence projected through a WorkCase; a Workroom record is attached when durable coordination is required |
The actual place where work happens for one trigger and context. It carries effective assignments, cycles, sub-rooms, decisions, evidence, actual measures, and outcome. |
These are not new competing nouns. Definition and instance qualify the
canonical word Workroom; WorkUnitDefinition and WorkOccurrence remain the
formal exchange terms. The source registry is the present runtime definition
projection. It must be refactored toward the complete definition contract rather
than copied into a second registry or a new template subsystem.
Implemented projection seam
The Workspace adapter now realizes the first definition/instance slice without adding another work ledger or route:
WORK_CASE_SOURCE_REGISTRYowns each source definition’s stable key, positive version, label, finite or standing mode, and decision scope;buildWorkroomViewprojects that definition identity together with one Work Case-derived instance identity and occurrence trace;- the occurrence trace links the primary source, current cycle, and active work carriers when they exist; repository, worktree, and PR evidence remains optional; and
/workspace/cases/[caseKey]shows the definition and occurrence posture in Overview, while Details reveals activity, participants, evidence, receipts, and technical references.
This is an adapter seam, not the complete definition contract below. Later refactoring should deepen the same registry and read model rather than create a parallel Workroom-definition surface.
A Workroom definition has a stable key and version. At minimum it declares:
- outcome, trigger classes, eligibility, and finite or standing instance policy;
- the applicable archetype and value-stream / lifecycle position;
- the four work-shape axes, owning decision scope, authority, review, escalation, and completion rules;
- accountable and contributing roles, skills, resources, and default allocation pattern without pre-assigning a person or agent to every future instance;
- planned sub-room and cycle composition plus event-triggered spawn rules;
- required outcome-packet categories, measures, budget / estimate policy, and evidence retention; and
- primary coordinated portfolio role plus directional portfolio dependencies.
A Workroom instance references the exact definition version and snapshots any
approved tailoring needed to interpret its history. It adds the actual trigger,
source WorkCase, objective and outcome anchor, participants and assignments,
times, costs, token / tool use when applicable, actions, receipts, exceptions,
and closure evidence. A repository, backlog item, worktree, commit, PR, or CI run
is linked delivery evidence for a development instance; none is required for an
ordinary business instance.
Composition, duration, and evidence
A sub-room is a Workroom instance with its own objective or control boundary that is structurally contained by another instance. It is not a nested chat and not merely a task row. A cycle is a bounded operating interval inside a standing instance; it becomes a sub-room only when it needs independent accountability, authority, lifecycle, or outcome evidence.
Work coordination uses explicit relationships rather than treating every link as parent / child:
| Relationship | Meaning |
|---|---|
contains |
structural composition of a room and its sub-room |
spawned-from |
provenance from a schedule, event, exception, or prior room |
depends-on |
the subject cannot meet its outcome without the referenced work or capacity |
blocks |
current state prevents progress in the referenced room |
contributes-to |
outcome evidence advances a broader room without structural containment |
These are work-coordination relationships. Four-portfolio dependencies keep the directional enterprise semantics in the FPAW standard; the UI must not silently convert one relation family into the other.
Finite instances seal when their acceptance and evidence requirements are met. Standing instances remain durable and contain bounded cycles or spawned sub-rooms. Teardown removes temporary execution resources, not history: the definition version, instance identity, actions, receipts, outcome packet, estimates versus actuals, linked BIs / worktrees / PRs, and retained metrics stay queryable after the room is sealed or archived.
Example: Restaurant Day is a scheduled, finite Workroom definition. Each day
creates an instance containing planned opening, kitchen, dining-service, staffing,
receiving, and closing sub-rooms. A complaint or oven failure spawns an event
sub-room. The oven remains a canonical Manufacturing and Delivery asset (or a
Foundational shared-facility aspect where appropriate), linked through a typed
dependency; it is not recreated as a child record every day. A standing
Restaurant Operations instance can receive each day’s outcome packet through
contributes-to without owning every operational record.
Human accountability is not coordination, execution, or access
Who answers for a room’s outcome is a separate axis from who coordinates it, who executes it, who requested it, and who holds its lease. They are separate identities with separate labels, and an AI coordinator can be absent while a human remains accountable. Resolving accountability grants no capability to anyone and never widens what a principal can read or write.
resolveEffectiveHumanAccountability in
apps/web/lib/work-management/human-accountability.ts
is the single place that answers it. Order: an explicit accountable principal on
the room, then the nearest ancestor along containment, then the organization’s
recorded owner. A solo founder is the ordinary case of that last step.
Two rules matter more than the order.
Responsibility travels only along contains and spawned-from. The other three
relation kinds — depends-on, blocks, contributes-to — describe execution
order, and treating one as an ownership edge would make whoever a room waits on
answerable for it.
When nothing resolves, the result is a setup state naming what is missing. It never falls back to the room’s creator, requester, lease holder, or the first administrator on the install. A guessed accountable is worse than a visible gap, because it reads as a decision somebody made. Ambiguity is reported the same way: two accountable principals on one room, two containers for one room, or a containment cycle each return a correctable state rather than an arbitrary answer.
The organization’s recorded owner is not yet persisted on this schema. Until it is, rooms with no explicit assignment resolve to that setup state, which is the intended behaviour rather than a defect. Recording it is a schema change with its own migration acceptance.
What an activity symbol is allowed to claim
A count is not an answer. “12 rooms” tells an operator nothing they can act on, so a collapsed branch carries a bounded set of concrete statements — what is being done, or what is waiting — chosen attention-first, not a bare number.
A symbol must be earned. Motion means fresh evidence of execution right now. A
held lease, a claimed shape, a successful tool call and a completed task are not
that. deriveActivitySignal in
apps/web/lib/work-management/portfolio-activity-projection.ts
resolves one of seven states — executing, waiting on a person, queued, blocked,
completed, stale, unknown — and only executing animates.
Three distinctions carry the intent. A verified receipt and a blocker are
statements about the work and hold regardless of how recently anything was
observed, so neither is overridden by a fresh heartbeat. No evidence at all is
unknown, which is not the same as old evidence, which is stale; a
disconnected client ages into stale rather than spinning indefinitely. And every
representative statement carries the canonical destination of the room it
describes, so a summary is always one click from the thing it summarises.
Reads are bounded and ordered deterministically. Rooms are deduplicated by identity before counting, so a room reachable through two links is counted once, and rooms needing attention are counted separately from the branch total. A page that does not cover the estate reports itself as partial and hands back a cursor, rather than presenting its own size as a total.
Authorization happens before projection, never after: filtering a rendered list would let hidden work leak through a count or a representative summary.
An executor is a teammate, not a surface
The same worker reached through Claude Code, Codex, Grok or the portal is one identity with one session on the room. A roster deduplicates by identity rather than listing a row per connection, and multi-agent orchestration rolls up the same way: a planner and its specialists are one worker with subagents beneath it, never N peers competing for attention.
rollUpNamedWorkers in
apps/web/lib/work-management/worker-rollup.ts
performs that rollup. A worker is described from its freshest observation, and
working is a claim about now: without a recent progress observation it
degrades to idle, and with none at all to unknown. waiting and idle are not
claims about now and are reported as given.
Delegation is not dependency. A worker’s parent is the worker that delegated it,
recorded at delegation time. Where that was never recorded the parentage stays
unknown, and where two surfaces name different delegators it collapses to
unknown rather than taking a vote. A child whose parent is not visible — hidden
by authorization, or simply not loaded — is never promoted to a root, because
that would present a subagent as an independent worker.
A hundred subagents stay inspectable without either extreme: hiding them behind a running count answers nothing, and giving each a top-level destination floods navigation. They are grouped under the worker that delegated them, paged, and searchable by name or by what they are currently doing.
Expansion is not selection
The activity tree separates two things a compact view usually conflates. The chevron discloses a branch’s rooms; it does not change what the inspector shows. Selecting an activity does not collapse, reorder, or scroll anything. An operator who looks at one room must not lose their place in the estate.
A collapsed branch already carries its representative activity, so the tree is readable without expanding anything, and each representative line carries the canonical destination of the room it describes. A summary is always one click from the thing it summarises, never a prompt to go hunting through ancestors.
Counts supplement statements; they never replace them. A branch row shows how many rooms it holds and how many need attention, beside the concrete statements, not instead of them.
Symbols are rendered from the server-decided signal, each with an accessible
name, and only the executing state animates — stilled under reduced motion. See
PortfolioActivityTree.tsx.
Naming rules
- One stem, one casing:
Workroom— neverWorkRoom,work-roomorWORK_ROOM. The compound is a single word, likeWorkspace. - The record is
Workroom. Do not call it a capsule in new prose or new code. - A view type keeps its role in the name:
WorkroomView,WorkroomCycleView,WorkroomParticipantView. The suffix is what distinguishes a projection from the record, now that both share a stem. - WorkCase keeps its own name. It is the business-language layer and is not a Workroom synonym.
A known tension, accepted deliberately
WORK_CASE_SOURCE_REGISTRY currently carries 13 sources, each with its own
roomProjection policy:
task-node · backlog-item · work-capsule · approval · data-control-operation
manual-task · scheduled · engagement · opportunity · booking
storefront-booking · activity · field-service-job
The room is therefore a container that renders for any of those sources, while
the claim record is one of them (work-capsule). Converging both onto the name
Workroom means one source shares the container’s name, and a booking, an
opportunity or a field-service job renders in something called a Workroom.
This was raised before the convergence landed and the direction was reaffirmed (2026-08-15). It is recorded here rather than left implicit, because it is the thing most likely to confuse a reader later.
The practical rule that keeps it workable: when the word is ambiguous in a sentence, say which layer you mean — “the Workroom record”, “the WorkCase”, or “the Workroom view”. Do not disambiguate by inventing a new noun.
If the ambiguity later proves costly, the reversible move is to rename the
container (the view layer) rather than the record, because the record’s name is
founder-directed. That would be a follow-on BI under EP-WORK-CONVERGENCE, not a
silent drift.
What is deliberately NOT renamed yet
⟦runtime: these lag the vocabulary on purpose — check before assuming drift⟧
- MCP tool names — DONE (
BI-0702869B). The canonical names are nowcreate_workroom,claim_workroom_scope,heartbeat_workroomand the rest. Every legacy*_capsule_*name stays callable but unadvertised for the alias window, because external Claude / Codex / Grok clients and peer installs hold them. Both names carry identical grants —TOOL_TO_GRANTSdenies unlisted tools, so an alias without a grant row is an authorization failure. Two tools keep their names deliberately:adopt_worktreeandclaim_backlog_item_for_workcarry no capsule token. - Prisma field vocabulary —
workCapsuleIdforeign keys, thecapsule/workCapsulerelation fields, and thecapsuleIdsemantic key with itsWC-*values. The models carry@@mapto their original physical tables, so the columns are unchanged on disk. - Dated specs and plans under
docs/superpowers/keep their original filenames and wording. They are the record of what was decided when, not live contracts. - Agent-facing MCP copy — tool descriptions and error payloads under
apps/web/lib/mcp/packs/still say “Work Capsule” (27 occurrences, recorded inscripts/prose-lint-baseline.json). They are read by clients inside the alias window, not by an operator, so they retire with the aliases through the existing alias-retirement follow-on.
What a human reads is renamed, and now guarded
⟦runtime: enforced by pnpm check:prose-lint — a new “capsule” in owner copy fails CI⟧
The owner-copy cleanup moved the model, view types, tools, and doctrine, but
eleven owner-facing strings kept saying capsule — the portal
context strip, the Build Studio work-control table and panel, the change-lane
facet and its blocker text, the delivery nav, and the MCP token-template
description. Phase 2’s only UX gate was workspace/cases/[caseKey], so no gate
ever looked at them.
The list above is what this page can promise stays unrenamed. Owner-facing
copy is not on it and never was — that omission is what let the drift read as
deliberate. It is now mechanical rather than aspirational: the
retiredVocabulary axis of scripts/check-prose-lint.ts carries a
RETIRED_TERMS registry, and the term capsule is in it.
Two properties of that guard are load-bearing:
- It scans
apps/web/lib/as well asapp/andcomponents/. The string the owner actually reported (actionLabel: "Open capsule") is built inlib/portal-context/work-resolver.ts, which an app+components sweep cannot see. - It matches camelCase copy props case-insensitively. The original bare-prop
regex could not see
actionLabelat all, which is the mechanical reason four shipped phases walked past the defect.
Renaming anything else on this page means adding its term to RETIRED_TERMS
in the same PR. Landing the copy change without the registry row leaves the
old word free to come back, which is exactly how this one survived.
Related
- Work shapes and the decision gate — the shape axes, where the kernel gates autonomy, and what the shape does next
- Claim a workroom before you work
- Workroom participation and channel continuity
- Plan:
docs/superpowers/plans/2026-08-15-workroom-canonical-rename.md
A disclosure control discloses
Expanding a branch of the portfolio activity tree replaces its summary with the
rooms it carries. This is stated because the first implementation did not do it:
the chevron flipped aria-expanded, swapped its own glyph, and left the list
below unchanged, so the control announced a disclosure it never performed. A
control that changes only its own appearance is worse than no control, because
an operator reads the absence of new rows as “this branch has nothing more”.
Disclosure is bounded. A portfolio holding a thousand rooms discloses the first
DEFAULT_DISCLOSURE_LIMIT of them in the order it was already summarising, then
says how many it is not listing. Opening a branch never empties a portfolio into
the page, and never reshuffles the rows the operator was reading.
A count says what it counted
A branch count describes the rooms the page read, not the rooms that exist. The page reads a bounded number of Workrooms; when that read hits its limit the tree renders “N rooms read” and states the bound. Measured against 1,001 rooms and a 200-room read, an unqualified “51 rooms” understated the portfolio five-fold while looking exactly like a total.
A statement names its room
Every activity line carries its room’s title alongside the action or blocker. Blockers are frequently generic and shared: at scale, several rooms blocked on one liveness reason rendered as identical lines with no way to tell which room each described, or that they were different rooms at all.
The room inspector renders what the projections resolve
Accountability and the worker roster were computable before they were visible. The room inspector is where they surface, and it keeps three claims apart.
A human is accountable: answerable for the work, defaulting to the organization’s recorded owner and inherited down the responsibility graph unless a room records its own. The panel states where the answer came from — this room, a room N steps up, or the organization — because “who is accountable” and “why them” are different questions and the second one is how an operator corrects a wrong answer.
Inheritance follows responsibility relations only. contains and spawned-from
delegate answerability; every other relation links two rooms without delegating
anything, and walking one would inherit an owner from a room that never owned
this work.
Competing responsibility parents require correction; they do not establish the organization owner as the effective answer. The reader also preserves the unresolved frontier when its ten-level bound is reached. If no explicit assignment resolves before that frontier, the panel reports incomplete lineage. An explicit assignment at a known room still takes precedence. The drive and inspector share this resolution, so neither invents accountability from a partial graph.
Coordination and execution are not accountability. A named worker is one identity across every surface it was reached through, its subagents are grouped under whoever delegated them, and none of that moves answerability from the accountable human.
Where nothing was recorded, the panel says so. A participant row records who is
in a room and what they said they are doing; it is not a progress observation,
so a worker’s state reads as not recorded rather than being derived from a row’s
updatedAt — which changes on any edit and is not evidence that anyone is
working. Unrecorded delegation reads as unknown parentage, never as a plausible
parent.
A room with no WorkItem is its own case
a-room-is-reachable-by-construction says the read model resolves a room
through the foreign key that anchors it, and that a room which exists can be
opened. Both held only for anchored rooms. Measured on a live install: 464
Workrooms, 290 of them — 62% — carry no workItemId, and every one served the
not-found boundary when opened from the portfolio activity tree.
The tree composed those links correctly. The failure was one layer down: the
canonical resolver needs an anchor to redirect to and returns null without one,
and the case loader then looks for a WorkItem whose source type is
work-capsule, which nothing is.
A room with no WorkItem is not a broken anchor — it is a room that is its own unit of work, so it is its own case. An anchored room still resolves to its item’s case and never reaches this path, so one unit of work keeps one case.
Such a case states what the room does not carry. Where no objective was recorded the boundary says so instead of restating the title as though it were intent, and urgency, effort and assignment read as not recorded rather than being given a plausible default.