|
| 1 | +--- |
| 2 | +dun: |
| 3 | + id: TP-015 |
| 4 | + depends_on: |
| 5 | + - TD-011 |
| 6 | +--- |
| 7 | +# TP-015: Agent Quorum + Synthesis Implementation Plan |
| 8 | + |
| 9 | +**User Story**: US-011 |
| 10 | +**Version**: 1.0.0 |
| 11 | +**Date**: 2026-02-03 |
| 12 | +**Status**: Draft |
| 13 | +**Author**: codex |
| 14 | + |
| 15 | +## 1. Scope |
| 16 | + |
| 17 | +This test plan verifies the implementation-plan specific work in IP-015: |
| 18 | +- One-shot quorum commands (`dun quorum`, `dun synth`). |
| 19 | +- Persona-aware harness selection (`name@persona`). |
| 20 | +- Synthesis meta-harness execution. |
| 21 | +- Deterministic quorum summary metadata. |
| 22 | +- Shared quorum engine between `dun loop --quorum` and one-shot commands. |
| 23 | + |
| 24 | +## 2. Acceptance Criteria |
| 25 | + |
| 26 | +| ID | Acceptance Criterion | |
| 27 | +|----|---------------------| |
| 28 | +| AC-1 | `dun quorum` parses `--task`, `--quorum`, `--harnesses`, and conflict flags | |
| 29 | +| AC-2 | `dun synth` is a shorthand for `dun quorum --synthesize` | |
| 30 | +| AC-3 | `name@persona` parses and is passed through to harness execution | |
| 31 | +| AC-4 | Synthesis mode runs a meta-harness and returns merged output | |
| 32 | +| AC-5 | Quorum summary metadata is emitted deterministically | |
| 33 | +| AC-6 | `dun loop --quorum` uses the same quorum engine as one-shot commands | |
| 34 | + |
| 35 | +## 3. Existing Test Coverage |
| 36 | + |
| 37 | +| AC | Existing Test | File | Status | |
| 38 | +|----|---------------|------|--------| |
| 39 | +| AC-1 | Quorum flag parsing | `docs/helix/03-test/test-plans/TP-011-agent-quorum.md` | Partial | |
| 40 | +| AC-2 | None | - | Missing | |
| 41 | +| AC-3 | None | - | Missing | |
| 42 | +| AC-4 | None | - | Missing | |
| 43 | +| AC-5 | None | - | Missing | |
| 44 | +| AC-6 | None | - | Missing | |
| 45 | + |
| 46 | +## 4. Test Gaps |
| 47 | + |
| 48 | +| Gap ID | Description | Priority | Acceptance Criteria | |
| 49 | +|--------|-------------|----------|---------------------| |
| 50 | +| GAP-015-01 | One-shot command parsing and output tests | P0 | AC-1, AC-2 | |
| 51 | +| GAP-015-02 | Persona parsing and passthrough tests | P0 | AC-3 | |
| 52 | +| GAP-015-03 | Synthesis mode integration test | P0 | AC-4 | |
| 53 | +| GAP-015-04 | Quorum summary metadata determinism | P1 | AC-5 | |
| 54 | +| GAP-015-05 | Loop uses shared quorum engine | P1 | AC-6 | |
| 55 | + |
| 56 | +## 5. Proposed Test Cases |
| 57 | + |
| 58 | +### 5.1 CLI Parsing |
| 59 | + |
| 60 | +#### TC-015-01: Quorum command parsing |
| 61 | +**File**: `cmd/dun/quorum_test.go` |
| 62 | +**Priority**: P0 |
| 63 | +**Covers**: AC-1 |
| 64 | + |
| 65 | +```go |
| 66 | +func TestQuorumCommandParsing(t *testing.T) { |
| 67 | + // Given: dun quorum --task "spec" --quorum 2 --harnesses a,b |
| 68 | + // Then: parsed config includes task, quorum, harnesses |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +#### TC-015-02: Synth shorthand parsing |
| 73 | +**File**: `cmd/dun/quorum_test.go` |
| 74 | +**Priority**: P0 |
| 75 | +**Covers**: AC-2 |
| 76 | + |
| 77 | +```go |
| 78 | +func TestSynthCommandShorthand(t *testing.T) { |
| 79 | + // Given: dun synth --task "spec" --harnesses a,b --synthesizer a |
| 80 | + // Then: synthesize mode is enabled and synthesizer is set |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +### 5.2 Persona Parsing |
| 85 | + |
| 86 | +#### TC-015-03: Harness persona parsing |
| 87 | +**File**: `internal/dun/quorum_test.go` |
| 88 | +**Priority**: P0 |
| 89 | +**Covers**: AC-3 |
| 90 | + |
| 91 | +```go |
| 92 | +func TestParseHarnessSpecPersona(t *testing.T) { |
| 93 | + // Given: "codex@architect" |
| 94 | + // Then: Name=codex, Persona=architect |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +### 5.3 Synthesis Mode |
| 99 | + |
| 100 | +#### TC-015-04: Synthesis meta-harness invoked |
| 101 | +**File**: `internal/dun/quorum_test.go` |
| 102 | +**Priority**: P0 |
| 103 | +**Covers**: AC-4 |
| 104 | + |
| 105 | +```go |
| 106 | +func TestSynthesisModeInvokesMetaHarness(t *testing.T) { |
| 107 | + // Given: multiple harness drafts |
| 108 | + // Then: synthesizer runs and returns merged output |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +### 5.4 Summary Metadata |
| 113 | + |
| 114 | +#### TC-015-05: Deterministic quorum summary |
| 115 | +**File**: `internal/dun/quorum_test.go` |
| 116 | +**Priority**: P1 |
| 117 | +**Covers**: AC-5 |
| 118 | + |
| 119 | +```go |
| 120 | +func TestQuorumSummaryDeterministic(t *testing.T) { |
| 121 | + // Given: stable inputs |
| 122 | + // Then: summary fields are ordered and deterministic |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +### 5.5 Loop Integration |
| 127 | + |
| 128 | +#### TC-015-06: Loop uses shared quorum engine |
| 129 | +**File**: `cmd/dun/main_test.go` |
| 130 | +**Priority**: P1 |
| 131 | +**Covers**: AC-6 |
| 132 | + |
| 133 | +```go |
| 134 | +func TestLoopUsesSharedQuorumEngine(t *testing.T) { |
| 135 | + // Given: loop with --quorum |
| 136 | + // Then: shared quorum engine is invoked |
| 137 | +} |
| 138 | +``` |
0 commit comments