Skip to content

System Architecture

This document is the canonical architecture reference for the current LoopTroop application.

LoopTroop is not a thin chat wrapper around a coding model. It is a long-running workflow system with explicit planning phases, durable storage, isolated execution worktrees, and resumable OpenCode session ownership. The core architectural choice is simple: important state must live outside the model.

Mental Model

LoopTroop operates as a layered system:

  1. The React SPA renders the live ticket workspace and review tools.
  2. The Hono API exposes ticket, project, artifact, and streaming endpoints.
  3. Workflow actors and phase orchestrators drive tickets through planning, approval, execution, and delivery.
  4. OpenCode sessions do the model work, but only against tightly assembled context.
  5. SQLite, JSONL logs, and .ticket/** artifacts hold the durable truth.
  6. Git worktrees and GitHub delivery convert the plan into an isolated change set and then a PR outcome.

Runtime Actors

ActorResponsibilityPrimary modules
React SPATicket dashboard, workspace views, navigator, approvals, live logssrc/App.tsx, src/components/ticket/*, src/components/workspace/*
React Query hooksFetching, cache invalidation, optimistic updates, SSE integrationsrc/hooks/*
Hono APIREST routes and SSE endpoint under /apiserver/index.ts, server/routes/*
Workflow metadataCanonical phase list, UI view mapping, grouping, review metadatashared/workflowMeta.ts
Phase orchestratorsPlanning, approval, execution, PR delivery, retry and recovery logicserver/workflow/*, server/phases/*
OpenCode adapterSession creation, prompting, event streaming, questions, healthserver/opencode/adapter.ts
Session managerOwnership tracking, reconnect validation, completion and abandonmentserver/opencode/sessionManager.ts
SSE broadcasterTicket-scoped event fan-out plus replay buffer for reconnectserver/sse/broadcaster.ts
App databaseSingleton profile and attached-project registryserver/db/index.ts
Project databaseTickets, artifacts, sessions, attempts, history, error occurrencesserver/db/project.ts
Ticket filesystemHuman-readable and execution-time artifacts inside the ticket worktreeserver/storage/*, server/phases/*
Git and GitHub layerWorktrees, diffs, commits, PR creation, merge/close flowsserver/phases/execution/gitOps.ts, server/git/*, server/github/*

Authoritative Data Ownership

LoopTroop deliberately splits state across several storage layers. Each layer owns a different class of truth.

Storage locationCanonical contentsNotes
~/.config/looptroop/app.sqlite by defaultSingleton profile, attached projects, app metaConfigurable via LOOPTROOP_CONFIG_DIR or LOOPTROOP_APP_DB_PATH
<project>/.looptroop/db.sqliteProjects, tickets, phase artifacts, phase attempts, OpenCode sessions, status history, error occurrencesThis is the project-local operational database
<project>/.looptroop/worktrees/<ticket>/The isolated ticket worktree used for planning artifacts and code changesEach ticket gets its own worktree
.ticket/relevant-files.yamlRelevant file scan output used by later planning phasesReplaces older codebase-map.yaml terminology
.ticket/interview.yaml and .ticket/prd.yamlEditable review artifacts for the approved planning stagesThese are user-facing canonical documents
.ticket/beads/<flow>/.beads/issues.jsonlThe current bead plan for a given flow or base branchStored as line-oriented JSONL, but rewritten atomically on updates
.ticket/runtime/execution-log.jsonlDurable execution and phase log streamRead by /api/files/:ticketId/logs and folded for UI display
.ticket/runtime/state.yamlRuntime state projection for the active executionUsed for restart and status projection
.ticket/runtime/execution-setup-profile.jsonConcrete execution environment profileSeparate from the reviewable setup plan artifact
phase_artifacts tableStructured snapshots used by the API and UIHolds artifact content, phase, attempt number, timestamps

Note SQLite and the filesystem are complementary, not redundant. The database is optimized for querying and workflow bookkeeping; .ticket/** keeps artifacts inspectable, editable, and recoverable.

End-to-End Ticket Lifecycle

  1. A ticket starts in DRAFT with editable title, description, and priority.
  2. SCANNING_RELEVANT_FILES creates relevant-files.yaml from the ticket description and repo context.
  3. The interview council drafts, votes, refines the interview artifact, and iterates until interview coverage is good enough.
  4. The user approves the interview artifact.
  5. The PRD council drafts, votes, refines, and coverage-checks the spec.
  6. The user approves the PRD artifact.
  7. The beads council drafts, votes, refines, expands, and coverage-checks the execution plan.
  8. The user approves the beads artifact and then reviews the pre-implementation execution setup plan.
  9. Implementation runs bead by bead in an isolated ticket worktree, with bounded retry per bead.
  10. Post-implementation final testing, integration, PR creation, review follow-up, and cleanup drive the ticket to COMPLETED, CANCELED, or BLOCKED_ERROR.

The full phase map lives in State Machine.

Planning Flow

Planning is intentionally artifact-driven.

StagePrimary inputPrimary outputWhy it exists
Discovery scanTicket detailsrelevant-files.yamlGrounds planning in the actual codebase
Interview councilTicket details, relevant filesInterview document and answer sessionForces ambiguity out before specs
PRD councilTicket details, interview, relevant files, full answersPRD documentProduces the feature contract
Beads councilTicket details, PRD, relevant filesExecution bead planConverts the spec into execution units
Execution setup planningTicket details, PRD, beads, execution profileReviewable setup planMakes the coding environment explicit before code changes begin

The planning phases are not one long conversation. Each stage assembles a new context window from durable artifacts and runs in its own session scope.

Execution Flow

Execution is built around beads, not around one monolithic coding prompt.

  1. PRE_FLIGHT_CHECK verifies the ticket can enter pre-implementation setup.
  2. WAITING_EXECUTION_SETUP_APPROVAL pauses for setup-plan review before setup commands run.
  3. PREPARING_EXECUTION_ENV creates the temporary execution environment described by the approved setup plan.
  4. CODING selects the next runnable bead from the scheduler.
  5. executeBead() starts or reattaches to the owned OpenCode session for that bead attempt.
  6. The model must emit the expected structured bead status markers. Missing or malformed markers trigger a structured retry path.
  7. If the attempt stalls or fails, LoopTroop generates a context wipe note, resets the worktree to the bead start commit, and retries in fresh context.
  8. When the bead succeeds, LoopTroop captures a diff artifact and advances scheduler state.
  9. RUNNING_FINAL_TEST, INTEGRATING_CHANGES, and CREATING_PULL_REQUEST package the result for post-implementation delivery.

See Execution Loop and Beads.

Recovery Flow

Recovery is a first-class architectural concern.

Failure typeRecovery strategy
Browser reload, close, or reconnect gapREST state remains canonical; SSE reconnect includes the last event id and then refetches tickets, artifacts, bead state, interview state, and server logs
Frontend crash or tab closeInterview and approval drafts are persisted as ticket UI-state artifacts, with unload-time keepalive flushing for the latest unsaved snapshot
Invalid model outputRetry with repair or explicit re-prompt, depending on phase
Bead execution stallGenerate context wipe note, reset worktree, retry in fresh session
OpenCode reconnect gapValidate owned session against remote sessions and recreate if needed
Backend process restartValidate or reconstruct serialized actor snapshots, start actors from durable ticket state, and immediately process restored active snapshots
User edits approved planning artifactPrepare a planning restart from the affected approval boundary
Terminal blockageEnter BLOCKED_ERROR with persisted error occurrence history

LoopTroop tries hard to preserve the work product while discarding the bad conversational state that produced the failure.

If a resume point cannot be proven, recovery stops at BLOCKED_ERROR rather than falling back to DRAFT or continuing execution against unknown state. BLOCKED_ERROR retry requires a preserved previousStatus; CODING retry also requires a successful reset to the failed bead's beadStartCommit.

Restart And Session Ownership

LoopTroop tracks session ownership in the project database so it can decide whether a remote OpenCode session still belongs to the exact workflow slot that wants to use it.

Ownership keys can include:

  • ticketId
  • phase
  • phaseAttempt
  • memberId
  • beadId
  • iteration
  • step

This lets LoopTroop safely reconnect in cases like:

  • server restart while a ticket is still in the same phase
  • phase retry that should resume the currently owned session
  • multi-model council phases where each member has its own session identity
  • bead execution where iteration and bead identity both matter

It deliberately does not mean "resume any random prior stream." Reconnect only succeeds if the ticket is still in the same phase and the owned active session still exists remotely.

Prompt acquisition is bounded by timeout and abort signals. OpenCode create, list, and message-read calls are guarded so an OpenCode restart cannot indefinitely block the workflow runner.

Module Map

Frontend

AreaModules
App shell and routingsrc/App.tsx
Ticket workspacesrc/components/ticket/ActiveWorkspace.tsx, NavigatorPanel.tsx
Workspace viewssrc/components/workspace/*
Data hookssrc/hooks/useTickets.ts, useTicketArtifacts.ts, useWorkflowMeta.ts, useSSE.ts

API Surface

AreaModules
App entry and route mountingserver/index.ts
Ticket routesserver/routes/tickets.ts, server/routes/ticketHandlers.ts
Files, beads, streamingserver/routes/files.ts, beads.ts, stream.ts
Profile, projects, health, models, workflow metaserver/routes/profiles.ts, projects.ts, health.ts, models.ts, workflow.ts

Workflow Engine

AreaModules
Workflow runner and phase transitionsserver/workflow/*
Planning phasesserver/workflow/phases/*, server/phases/interview/*, server/phases/prd/*, server/phases/beads/*
Execution phasesserver/phases/execution/*, server/phases/executionSetup/*, server/phases/executionSetupPlan/*

Persistence

AreaModules
App DB bootstrapserver/db/index.ts
Project DB bootstrapserver/db/project.ts
Schemaserver/db/schema.ts
Ticket and project storage helpersserver/storage/*

OpenCode Integration

AreaModules
Adapter and factoryserver/opencode/adapter.ts, factory.ts
Context assemblyserver/opencode/contextBuilder.ts
Session ownership and reconnectserver/opencode/sessionManager.ts
Prompt runnerserver/workflow/runOpenCodePrompt.ts

ASCII Overview

text
User
  |
  v
React SPA
  |  REST (/api/*)                    SSE (/api/stream)
  |-------------------------------> Hono API <------------------+
  |                                                            |
  |                                                            v
  |                                                     SSE broadcaster
  |                                                            |
  v                                                            |
Workspace views <----------------------------------------------+
  |
  v
Workflow actors and phase orchestrators
  |            |                 |                 |
  |            |                 |                 |
  v            v                 v                 v
App DB     Project DB      Ticket worktree    OpenCode adapter/session manager
                               |                        |
                               v                        v
                         .ticket artifacts         OpenCode server
                         runtime JSONL/logs             |
                               |                        v
                               +-------------------- Provider models
  |
  v
git worktree, commits, PR creation, merge/close

Detailed Mermaid Diagram

LoopTroop documentation for the current runtime.