|
| 1 | +# Architecture |
| 2 | + |
| 3 | +## Goal state machine |
| 4 | + |
| 5 | +The orchestrator is a durable `GsdStateMachine` built around the `WorkflowState` enum |
| 6 | +(`src/GsdOrchestrator/Workflows/GsdStateMachine.cs`, `Models/WorkflowState.cs`). Every issue |
| 7 | +run walks the same linear path unless it is triaged out early or a state raises an unhandled |
| 8 | +exception, which transitions the workflow to `Failed`. State is checkpointed to disk after |
| 9 | +every transition (`FileCheckpointStore`), so `--resume <workflow-id>` can continue an |
| 10 | +interrupted run instead of restarting it. |
| 11 | + |
| 12 | +```mermaid |
| 13 | +stateDiagram-v2 |
| 14 | + direction LR |
| 15 | + [*] --> Idle |
| 16 | + Idle --> Triaging |
| 17 | + Triaging --> Analyzing: actionable issue |
| 18 | + Triaging --> Done: non-actionable or --triage |
| 19 | + Analyzing --> Branching |
| 20 | + Branching --> Editing |
| 21 | + Editing --> TestGenerating |
| 22 | + TestGenerating --> Validating |
| 23 | + Validating --> Committing |
| 24 | + Validating --> Failed: blocking gate |
| 25 | + Committing --> PrCreating |
| 26 | + PrCreating --> Reviewing |
| 27 | + Reviewing --> Documenting: issue mode |
| 28 | + [*] --> Reviewing: --pr mode |
| 29 | + Reviewing --> Done: PR-review mode |
| 30 | + Documenting --> Done |
| 31 | + Done --> [*] |
| 32 | + Failed --> [*] |
| 33 | +``` |
| 34 | + |
| 35 | +<!-- codex:generate-image prompt="A conveyor-belt state machine: a glowing token labeled ISSUE travels through eleven numbered gates (Idle, Triaging, Analyzing, Branching, Editing, TestGenerating, Validating, Committing, PrCreating, Reviewing, Documenting) each rendered as a small illuminated archway, ending at a checkered-flag PR gate; one side-branch peels off downward into a red Failed gate with a retry arrow looping back; isometric, enterprise blue/graphite palette" style="isometric, enterprise, clean" replaces="mermaid-above" --> |
| 36 | + |
| 37 | +## Failure handling on `main` today |
| 38 | + |
| 39 | +`ResumeAsync` checks `ctx.CurrentState == WorkflowState.Failed`: if `ctx.FailedState` is set, |
| 40 | +it clears the failure and re-enters that state for a retry; if the retry fails again it maps |
| 41 | +the exception to a `TerminalStopReason` (`BudgetExhausted`, `NoProgress`, `RuntimeExceeded`, |
| 42 | +or `Unknown`) and halts. On the primary path, an unhandled exception during a state currently |
| 43 | +rolls the workflow back through the SDLC phase map (`Discovery` → `Design` → `Change` → |
| 44 | +`Assurance` → `Closure`) before settling into `Failed`, recording the *rolled-back* state as |
| 45 | +`FailedState` rather than the state where the exception actually occurred. |
| 46 | + |
| 47 | +## Typed-failure retry/halt path (Phase 28-01 — not yet on `main`) |
| 48 | + |
| 49 | +Phase 28-01 hardens this: transient `McpException` failures should bypass the SDLC rollback |
| 50 | +cascade entirely and persist the *actual* failed state, so `ResumeAsync` retries the state |
| 51 | +that really failed (once) before halting — proven by `FaultInjectionTests.cs` and |
| 52 | +`CheckpointCorruptionTests.cs` (see [`28-01-SUMMARY.md`](../../.planning/phases/28-fault-injection-recovery/28-01-SUMMARY.md) |
| 53 | +in the root workstation repo for the full design). **This work exists only on a local, |
| 54 | +unpushed branch (`feat/phase-28-fault-injection`) in the operator's workstation checkout — |
| 55 | +it is not present on `origin/main` and there is no open PR for it yet.** Treat the failure |
| 56 | +handling described in the previous section as the current state of `main` until that branch |
| 57 | +is pushed and reviewed. |
| 58 | + |
| 59 | +## Component topology |
| 60 | + |
| 61 | +```mermaid |
| 62 | +flowchart LR |
| 63 | + subgraph Orchestrator["GSD Orchestrator (.NET 10)"] |
| 64 | + SM[GsdStateMachine] |
| 65 | + MCP[McpStdioClient] |
| 66 | + LLM[Anthropic.SDK] |
| 67 | + CP[FileCheckpointStore] |
| 68 | + end |
| 69 | + subgraph GitHub["GitHub"] |
| 70 | + MCPS[github-mcp-server.exe] |
| 71 | + GHAPI[GitHub API] |
| 72 | + end |
| 73 | + subgraph Anthropic["Anthropic"] |
| 74 | + CLAUDE[Claude API] |
| 75 | + end |
| 76 | + subgraph Storage["Local Storage"] |
| 77 | + CKPT[.gsd/state/] |
| 78 | + end |
| 79 | + SM --> MCP |
| 80 | + MCP -->|stdio| MCPS |
| 81 | + MCPS --> GHAPI |
| 82 | + SM --> LLM |
| 83 | + LLM --> CLAUDE |
| 84 | + SM --> CP |
| 85 | + CP --> CKPT |
| 86 | +``` |
| 87 | + |
| 88 | +## SDLC phase mapping |
| 89 | + |
| 90 | +Beyond the linear states, the orchestrator maps operations to SDLC batches — `Discovery` |
| 91 | +(Triaging, Analyzing), `Design`, `Change` (Branching, Editing, TestGenerating), `Assurance` |
| 92 | +(Validating, Reviewing), `Closure` (Committing, PrCreating, Documenting). A `Block`-level |
| 93 | +validation status triggers a `TerminalStopReason` and rolls the branch back. |
| 94 | + |
| 95 | +<!-- docs-verified: a01b130c98cb7833d45cc7406f6002009f33557a 2026-07-08 --> |
0 commit comments