Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ opens a pull request with durable workflow state.
**Stack:** .NET 10 (C#) · GitHub MCP Server · Anthropic Claude · Polly

[![CI](https://github.com/Coding-Autopilot-System/gsd-orchestrator/actions/workflows/ci.yml/badge.svg)](https://github.com/Coding-Autopilot-System/gsd-orchestrator/actions/workflows/ci.yml)
[![Tests](https://img.shields.io/badge/tests-35%20passing-brightgreen)](https://github.com/Coding-Autopilot-System/gsd-orchestrator/actions/workflows/ci.yml)
[![.NET 10](https://img.shields.io/badge/.NET-10-512BD4)](https://dotnet.microsoft.com/download/dotnet/10.0)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)

Expand Down Expand Up @@ -39,6 +38,18 @@ not just "AI edits code." The stronger signal is the operational model around th

See [docs/portfolio-proof.md](docs/portfolio-proof.md) for a concise reviewer-oriented summary.

## Test Coverage

The CI `Test` step runs the full xUnit suite (`src/GsdOrchestrator.Tests`) via `dotnet test`
with `--collect:"XPlat Code Coverage"` and uploads the Cobertura results as a workflow
artifact, but `main` does not yet fail the build on a coverage regression. A ratcheted
branch-coverage gate is **in progress (PR #16)**: it adds a new `coverlet.runsettings`
collector config and an "Enforce coverage" CI step that reads `branch-rate` (not line-rate)
from the produced Cobertura XML and fails closed if it drops below a ratcheted baseline
(measured at ~0.73 branch-rate in the PR, up from a ~0.69 starting point), emitting CAS JSON
telemetry on pass/fail. Until PR #16 merges, coverage is collected and published as an
artifact but not enforced.

## How It Works

```text
Expand Down Expand Up @@ -232,3 +243,5 @@ GithubMCP/
|-- Models/
`-- States/
```

<!-- docs-verified: a01b130c98cb7833d45cc7406f6002009f33557a 2026-07-08 -->
95 changes: 95 additions & 0 deletions docs/wiki/Architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Architecture

## Goal state machine

The orchestrator is a durable `GsdStateMachine` built around the `WorkflowState` enum
(`src/GsdOrchestrator/Workflows/GsdStateMachine.cs`, `Models/WorkflowState.cs`). Every issue
run walks the same linear path unless it is triaged out early or a state raises an unhandled
exception, which transitions the workflow to `Failed`. State is checkpointed to disk after
every transition (`FileCheckpointStore`), so `--resume <workflow-id>` can continue an
interrupted run instead of restarting it.

```mermaid
stateDiagram-v2
direction LR
[*] --> Idle
Idle --> Triaging
Triaging --> Analyzing: actionable issue
Triaging --> Done: non-actionable or --triage
Analyzing --> Branching
Branching --> Editing
Editing --> TestGenerating
TestGenerating --> Validating
Validating --> Committing
Validating --> Failed: blocking gate
Committing --> PrCreating
PrCreating --> Reviewing
Reviewing --> Documenting: issue mode
[*] --> Reviewing: --pr mode
Reviewing --> Done: PR-review mode
Documenting --> Done
Done --> [*]
Failed --> [*]
```

<!-- 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" -->

## Failure handling on `main` today

`ResumeAsync` checks `ctx.CurrentState == WorkflowState.Failed`: if `ctx.FailedState` is set,
it clears the failure and re-enters that state for a retry; if the retry fails again it maps
the exception to a `TerminalStopReason` (`BudgetExhausted`, `NoProgress`, `RuntimeExceeded`,
or `Unknown`) and halts. On the primary path, an unhandled exception during a state currently
rolls the workflow back through the SDLC phase map (`Discovery` → `Design` → `Change` →
`Assurance` → `Closure`) before settling into `Failed`, recording the *rolled-back* state as
`FailedState` rather than the state where the exception actually occurred.

## Typed-failure retry/halt path (Phase 28-01 — not yet on `main`)

Phase 28-01 hardens this: transient `McpException` failures should bypass the SDLC rollback
cascade entirely and persist the *actual* failed state, so `ResumeAsync` retries the state
that really failed (once) before halting — proven by `FaultInjectionTests.cs` and
`CheckpointCorruptionTests.cs` (see [`28-01-SUMMARY.md`](../../.planning/phases/28-fault-injection-recovery/28-01-SUMMARY.md)
in the root workstation repo for the full design). **This work exists only on a local,
unpushed branch (`feat/phase-28-fault-injection`) in the operator's workstation checkout —
it is not present on `origin/main` and there is no open PR for it yet.** Treat the failure
handling described in the previous section as the current state of `main` until that branch
is pushed and reviewed.

## Component topology

```mermaid
flowchart LR
subgraph Orchestrator["GSD Orchestrator (.NET 10)"]
SM[GsdStateMachine]
MCP[McpStdioClient]
LLM[Anthropic.SDK]
CP[FileCheckpointStore]
end
subgraph GitHub["GitHub"]
MCPS[github-mcp-server.exe]
GHAPI[GitHub API]
end
subgraph Anthropic["Anthropic"]
CLAUDE[Claude API]
end
subgraph Storage["Local Storage"]
CKPT[.gsd/state/]
end
SM --> MCP
MCP -->|stdio| MCPS
MCPS --> GHAPI
SM --> LLM
LLM --> CLAUDE
SM --> CP
CP --> CKPT
```

## SDLC phase mapping

Beyond the linear states, the orchestrator maps operations to SDLC batches — `Discovery`
(Triaging, Analyzing), `Design`, `Change` (Branching, Editing, TestGenerating), `Assurance`
(Validating, Reviewing), `Closure` (Committing, PrCreating, Documenting). A `Block`-level
validation status triggers a `TerminalStopReason` and rolls the branch back.

<!-- docs-verified: a01b130c98cb7833d45cc7406f6002009f33557a 2026-07-08 -->
48 changes: 48 additions & 0 deletions docs/wiki/Decisions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Decisions

## ADR convention

`docs/adr/README.md` establishes the convention (sequential numbering, Context/Decision/
Consequences, mandatory for major technical decisions or new dependencies) but **no numbered
ADR files exist in the repo yet** — decisions to date live in phase plans/summaries under
`.planning/phases/` instead. This index points at those until the first formal ADR is filed.

## Phase history (`.planning/phases/`, this repo's own GSD project)

19 phases completed in this repo's local planning history, covering foundation setup through
portfolio polish:

| Phase | Topic |
|---|---|
| 01 | Foundation quick wins |
| 02 | CI diagrams |
| 03 | Wiki release |
| 04–05 | Promptimprover / autogen cross-repo polish |
| 06 | Coherence / personal profile |
| 07 | Emergency ci-autopilot fix |
| 08 | Secondary repos level A |
| 09–11 | Portfolio AI-reframe and cross-portfolio coherence |
| 12 | Robustness foundation |
| 13 | Smarter issue triage |
| 14 | Autonomous test generation |
| 15 | PR review loop |
| 16 | Multi-repo support |
| 17 | CI hardening |
| 18 | State/test coverage |
| 19 | Portfolio polish |

See each `.planning/phases/<NN-topic>/*-SUMMARY.md` for the detailed record of what shipped.

## Open decisions tracked in this Phase 36 refresh

- **PR #16** (`feat/phase-26-coverage-gates`) — ratchets CI to a `branch-rate` coverage gate;
open, not yet merged.
- **PR #17** (`fix/checkpoint-corruption`) — checkpoint corruption/replay-error hardening;
open, not yet merged.
- **PR #18** (`ci/sha-pin-and-least-privilege`) — pins third-party GitHub Actions to commit
SHAs and adds least-privilege permissions; open, not yet merged.
- **Phase 28-01 typed-failure retry/halt path** — designed and implemented locally
(`feat/phase-28-fault-injection`, unpushed) but not yet a PR; see
[Architecture](./Architecture.md) for the current-vs-designed failure-handling contrast.

<!-- docs-verified: a01b130c98cb7833d45cc7406f6002009f33557a 2026-07-08 -->
33 changes: 33 additions & 0 deletions docs/wiki/Home.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# gsd-orchestrator Wiki

## Role in the CAS portfolio

`gsd-orchestrator` is the **Control plane** of the Coding-Autopilot-System three-plane model
(Control / Execution / Governance — see the root [`docs/VISION.md`](https://github.com/OgeonX-Ai/cas-workstation)
architecture diagram). Its job: admit goals as typed, bounded, budgeted work items and drive
dependency-aware scheduling through a durable state machine — issue in, PR out, with every
step checkpointed so a crashed or interrupted run can be resumed rather than restarted.

| Plane | This repo's responsibility |
|---|---|
| Control | Goal admission, state-machine scheduling, checkpoint/resume, PR lifecycle |
| Execution | *(not this repo — see `autogen`)* |
| Governance | *(not this repo — see `Promptimprover`, `cas-contracts`, `cas-evals`)* |

## Quickstart

- [README.md](../../README.md) — setup, `.env` configuration, running the orchestrator against a real issue
- [docs/portfolio-proof.md](../portfolio-proof.md) — concise reviewer-oriented summary
- [Architecture](./Architecture.md) — state machine, component topology, typed-failure path
- [Operations](./Operations.md) — build, test, and CI commands (verified against the live tree)
- [Decisions](./Decisions.md) — index of phase summaries and the ADR convention

## Ecosystem links

Part of the [Coding-Autopilot-System](https://github.com/Coding-Autopilot-System) org:
[autogen](https://github.com/Coding-Autopilot-System/autogen) (execution plane) ·
[Promptimprover](https://github.com/Coding-Autopilot-System/Promptimprover) (prompt governance) ·
[cas-contracts](https://github.com/Coding-Autopilot-System/cas-contracts) (shared schemas) ·
[cas-evals](https://github.com/Coding-Autopilot-System/cas-evals) (evidence gate)

<!-- docs-verified: a01b130c98cb7833d45cc7406f6002009f33557a 2026-07-08 -->
52 changes: 52 additions & 0 deletions docs/wiki/Operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Operations

## Build

```bash
dotnet restore src/GsdOrchestrator/GsdOrchestrator.csproj
dotnet build src/GsdOrchestrator/GsdOrchestrator.csproj --no-restore --configuration Release
```

## Test

```bash
dotnet restore src/GsdOrchestrator.Tests/GsdOrchestrator.Tests.csproj
dotnet build src/GsdOrchestrator.Tests/GsdOrchestrator.Tests.csproj --no-restore --configuration Release
dotnet test src/GsdOrchestrator.Tests/GsdOrchestrator.Tests.csproj --configuration Release --no-build
```

Contract-compatibility gate only (consumer-side check against the pinned `cas-contracts` v1.1
release, fails red on drift):

```bash
dotnet test src/GsdOrchestrator.Tests/GsdOrchestrator.Tests.csproj --configuration Release --no-build --filter "FullyQualifiedName~ContractCompatibilityTests"
```

## CI (`.github/workflows/ci.yml`, `windows-latest`, 30-minute timeout)

1. `actions/checkout@v7`
2. `actions/setup-dotnet@v5` (.NET `10.0.1xx`)
3. Restore + build `GsdOrchestrator.csproj`
4. Restore + build `GsdOrchestrator.Tests.csproj`
5. **Contract compatibility** — `ContractCompatibilityTests` filter, fails red on pinned-contract drift
6. **Test** — full suite with `--collect:"XPlat Code Coverage"`, results to `./TestResults`
7. **Upload coverage** — `actions/upload-artifact@v7`, `coverage-results` artifact (always runs)

There is currently **no coverage-threshold enforcement step** on `main` — coverage is
collected and published as an artifact only. A ratcheted `branch-rate` gate is in progress;
see [Architecture — Test Coverage](../../README.md#test-coverage) and PR #16.

A separate `.github/workflows/codeql.yml` runs CodeQL analysis (badge in the root `README.md`).

## Run the orchestrator locally

```bash
cd src/GsdOrchestrator
dotnet run -- --issue 42
dotnet run -- --resume <workflow-id>
```

Requires `.env` with `GITHUB_PERSONAL_ACCESS_TOKEN`, `ANTHROPIC_API_KEY`,
`GSD_GITHUB_OWNER`, `GSD_GITHUB_REPO` set (copy from `.env.example`).

<!-- docs-verified: a01b130c98cb7833d45cc7406f6002009f33557a 2026-07-08 -->
Loading