Skip to content

Shared logical scene state for factory visualizations #299

Description

@williamthorsen

Problem

The factory visualization needs a stable API layer that derives workflow progress from run snapshots — what each agent is doing, what state each artifact is in, what the orchestrator is carrying — independent of any specific visualization's spatial layout. Currently, each visualization (catwalk, factory-floor) interprets CanonicalRunStatus directly with duplicated logic. Branch 295's tilemap implementation couples logical state derivation to a 5-room spatial layout that has since been superseded.

Context

Branch 295 implemented a complete 4-layer tilemap pipeline (state mapper, position resolver, differ, transition planner) but embedded logical interpretation (agent statuses, orchestrator behavior, artifact lifecycle) inside a tilemap-specific mapper that assigns entities to rooms and slots. When the layout changed from 5 rooms to 3 zones (#293), the logical interpretation remained sound but the spatial coupling made it fragile.

The architectural insight: the interpretation of CanonicalRunStatus into present-tense workflow state ("the architect is done, the planner is working, the orchestrator is carrying findings") is shared across all visualizations. Only the spatial mapping (rooms, slots, positions) is visualization-specific.

Salvageable code exists on branch 295-salvage. The shared utilities (agent-state-resolver.ts, artifact-utils.ts, orchestrator-utils.ts) and the logical derivation logic in run-to-tilemap.ts can be extracted and adapted.

Related: #301 (structured review findings — deferred), #302 (thought bubble cycling — deferred), #303 (tilemap 3-zone adapter — depends on this ticket)

See packages/factory/docs/visions/facility-architecture.md for the full spatial and behavioral architecture.

Solution

1. Extract shared utilities

Move visualization-agnostic utilities from branch 295-salvage into packages/factory/src/client/visualizations/shared/:

  • agent-state-resolver.ts — resolves AgentAnimationState from phase and run status
  • artifact-utils.ts — artifact color lookup, type guards, reviewer name extraction
  • orchestrator-utils.ts — carried artifacts, code badge derivation

2. Define LogicalSceneState

A visualization-agnostic snapshot of workflow progress. No rooms, no slots, no spatial concepts.

interface LogicalSceneState {
  runStatus: string;
  currentPhase: PhaseName | undefined;
  agents: LogicalAgentState[];
  orchestrator: LogicalOrchestratorState;
  artifacts: LogicalArtifactState[];
}
  • Agents: id, role, roleType, phase, status (idle/working/done/blocked/concerned)
  • Orchestrator: status (idle/dispatching/monitoring/delivering/done), carriedArtifacts, codeBadge, waiting
  • Artifacts: id, label, color, status (created/in_transit/delivered), producerPhase, iteration

3. Implement the mapper

mapRunToLogicalScene(status: CanonicalRunStatus): LogicalSceneState

Pure function. Reuses shared utilities for the non-trivial derivations. This is the extraction and generalization of the logical parts of branch 295's mapRunToTilemap(), minus room/slot assignment.

4. Artifact lifecycle rename

ArtifactStatus = 'created' | 'in_transit' | 'delivered' (was 'on_desk' | 'delivered' in branch 295).

Out of scope

Acceptance criteria

  • Shared utilities extracted to visualizations/shared/ and importable by any visualization
  • LogicalSceneState type defined with agent, orchestrator, and artifact state
  • mapRunToLogicalScene() correctly derives present-tense workflow state from CanonicalRunStatus
  • Artifact lifecycle uses created | in_transit | delivered
  • Comprehensive tests for the logical mapper
  • No spatial concepts (rooms, slots, positions) in the shared layer

Metadata

Metadata

Labels

refactoringImprovement to code without change in functionalityscope:factory

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions