valent-pipeline 0.2.25 → 0.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Claude Code Runtime Adapter
|
|
2
|
+
|
|
3
|
+
> **Provider:** Claude Code Agent Teams
|
|
4
|
+
> **Read by:** Lead agent when `runtime.provider` is `claude-code` in `pipeline-config.yaml`
|
|
5
|
+
> **Purpose:** Defines HOW to create teams, spawn agents, send signals, track tasks, and monitor liveness using Claude Code's native primitives.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Initialization
|
|
10
|
+
|
|
11
|
+
Use `TeamCreate` to create a named team for inbox routing:
|
|
12
|
+
|
|
13
|
+
- **Epic runs** (`{is_epic_run}` is true): `TeamCreate("valent-{epic_id}")` (lowercased). The team persists across stories so Knowledge Agent stays alive. If the team already exists (continuing an epic), proceed without recreating.
|
|
14
|
+
- **Standalone runs**: `TeamCreate("valent-{story_id}")` (lowercased).
|
|
15
|
+
|
|
16
|
+
**Clean up stale team:** If `TeamCreate` fails with an "Already leading team" error, call `TeamDelete` first, then retry. This handles cases where a prior run crashed before teardown.
|
|
17
|
+
|
|
18
|
+
**NEVER** spawn pipeline agents as anonymous subagents. Every agent must be a named teammate on the team so it can send and receive inbox messages with other teammates.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Task Registry
|
|
23
|
+
|
|
24
|
+
Use the shared task list API to create and track tasks:
|
|
25
|
+
|
|
26
|
+
1. **Create tasks:** For each task in the resolved task graph, call `TaskCreate` with `subject`, `description`, and `activeForm` from the template.
|
|
27
|
+
2. **Wire dependencies:** For each task with `blockedBy` refs, call `TaskUpdate` with `addBlockedBy` using the mapped real task IDs. If a `blockedBy` ref is in `skipped_refs`, omit it.
|
|
28
|
+
3. **Maintain ref map:** Keep a `ref -> taskId` map (e.g., `{ reqs: "1", uxa: "2", ... }`) and a `skipped_refs` set.
|
|
29
|
+
4. **Read task state:** Use `TaskList` and `TaskGet` to check task statuses during monitoring.
|
|
30
|
+
5. **Update status:** Use `TaskUpdate` to mark tasks `in_progress` on agent spawn and `completed` on agent handoff.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Agent Spawning
|
|
35
|
+
|
|
36
|
+
Use the `Agent` tool with `name` parameter to spawn named teammates onto the team. Set `run_in_background: true` so agents work autonomously.
|
|
37
|
+
|
|
38
|
+
### Spawn Pattern
|
|
39
|
+
|
|
40
|
+
1. Read the spawn template (a short ~15-line template from `.valent-pipeline/spawn-templates/`)
|
|
41
|
+
2. Substitute all `{{variables}}` with resolved values from config and the task graph
|
|
42
|
+
3. Pass the filled template as the Agent tool's `prompt` parameter
|
|
43
|
+
4. Set `name` to the agent's name from the manifest (e.g., `"REQS"`, `"UXA"`, `"Knowledge"`)
|
|
44
|
+
5. Set `run_in_background: true`
|
|
45
|
+
6. Set `model` per the `models` section in `pipeline-config.yaml` (match agent name to tier)
|
|
46
|
+
|
|
47
|
+
**DO NOT read the agent's prompt files, step files, or templates yourself.** The spawn template tells the teammate to read its own prompt and steps. Your job is ONLY to substitute variables in the template and pass it to the Agent tool.
|
|
48
|
+
|
|
49
|
+
### Templates
|
|
50
|
+
|
|
51
|
+
- `.valent-pipeline/spawn-templates/agent-spawn.template.md` — for all agents except Knowledge
|
|
52
|
+
- `.valent-pipeline/spawn-templates/knowledge-spawn.template.md` — for the Knowledge Agent
|
|
53
|
+
|
|
54
|
+
### Wave-Based Spawning
|
|
55
|
+
|
|
56
|
+
| Wave | Spawn Trigger | Agents |
|
|
57
|
+
|------|---------------|--------|
|
|
58
|
+
| 1 | At kick-off | Knowledge, REQS, UXA, QA-A, READINESS |
|
|
59
|
+
| 2 | QA-A sends `[HANDOFF]` | BEND, FEND, DATA, MCP-DEV, LIBDEV, DOCGEN, IAC, CRITIC (each only if not skipped) |
|
|
60
|
+
| 3 | CRITIC task becomes `in_progress` | QA-B, PMCP (if ui profile) |
|
|
61
|
+
| 4 | JUDGE bug-review task becomes `in_progress` | (reserved) |
|
|
62
|
+
|
|
63
|
+
**Pattern:** Spawn the next wave when the current blocking agent starts work, so downstream agents are initialized and ready the moment the blocker finishes.
|
|
64
|
+
|
|
65
|
+
### Knowledge Agent (Epic Mode)
|
|
66
|
+
|
|
67
|
+
If `{is_epic_run}` is true and a Knowledge teammate already exists in the current team, skip the spawn. Instead, send `SendMessage(to: "Knowledge")`: `[STORY-RESET] story_id={story_id}, pipeline_context={story_output_dir}/pipeline-context.md`. Wait for `[KNOWLEDGE-READY]` response.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Signal Delivery
|
|
72
|
+
|
|
73
|
+
Use `SendMessage` for all inter-agent communication. Messages are delivered to named teammate inboxes.
|
|
74
|
+
|
|
75
|
+
### Lead Outbound Messages
|
|
76
|
+
|
|
77
|
+
- `[SPAWN] Spawning {agent} for {story_id}. Role: {role}. Shared context: {story_output_dir}.`
|
|
78
|
+
- `[CHECK-IN] {agent}: task {task} has been in_progress for {minutes}min. Status?`
|
|
79
|
+
- `[REVIEW-READY] Story {story_id}` — sent to READINESS when a story reaches `readiness-review`
|
|
80
|
+
- `[TEARDOWN] Tearing down all teammates for {story_id}.`
|
|
81
|
+
- `shutdown_request` via SendMessage to each agent individually at teardown
|
|
82
|
+
|
|
83
|
+
### Agent-to-Agent (Peer-to-Peer)
|
|
84
|
+
|
|
85
|
+
Agents use `SendMessage` directly for:
|
|
86
|
+
- `[HANDOFF]` — completion signal to Lead and/or downstream agent
|
|
87
|
+
- `[CRITIC-REJECTION]` — CRITIC to BEND/FEND, CC Lead
|
|
88
|
+
- `[BUG]` — QA-B to BEND/FEND, CC Lead
|
|
89
|
+
- `[KNOWLEDGE-QUERY]` / `[KNOWLEDGE-RESPONSE]` — any agent to/from Knowledge
|
|
90
|
+
- `[DESIGN-COUNCIL]` / `[DESIGN-COUNCIL-RESPONSE]` — structured deliberation between 2-3 agents
|
|
91
|
+
- `[BLOCKER]` / `[ESCALATION]` — agent to Lead
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Monitoring
|
|
96
|
+
|
|
97
|
+
### Heartbeat Timer
|
|
98
|
+
|
|
99
|
+
At the start of Phase 2, create a `CronCreate` job that fires every 4 minutes. Each heartbeat triggers a liveness check: call `TaskList`, verify at least one non-Knowledge agent is `in_progress`. If uncompleted tasks exist but no agent is working, diagnose deadlock (stale blockers, missed unblocks, dead teammates) and act.
|
|
100
|
+
|
|
101
|
+
Create a separate 4-minute keep-alive ping for the Knowledge Agent to prevent prompt cache expiry.
|
|
102
|
+
|
|
103
|
+
### Monitoring Loop
|
|
104
|
+
|
|
105
|
+
1. Watch for task status changes (completed, blocked, failed)
|
|
106
|
+
2. Watch for wave spawn triggers (QA-A completion, CRITIC start)
|
|
107
|
+
3. Watch for inbox messages ([ESCALATION], [BLOCKER], [DESIGN-COUNCIL], [STATUS])
|
|
108
|
+
4. Track rejection counts per agent for circuit breaker
|
|
109
|
+
5. Track time-in-progress per task for stall detection (exempt: Knowledge Agent)
|
|
110
|
+
6. On every phase transition, capture timestamp and update `phase-timing.md`
|
|
111
|
+
|
|
112
|
+
### Stall Detection
|
|
113
|
+
|
|
114
|
+
When a task stays `in_progress` beyond `{stall_threshold_minutes}`:
|
|
115
|
+
1. Send `[CHECK-IN]` message to the teammate via SendMessage
|
|
116
|
+
2. If no response within reasonable time, classify per Headless Escalation Protocol
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Teardown
|
|
121
|
+
|
|
122
|
+
1. Send `shutdown_request` via `SendMessage` to each teammate individually (not broadcast)
|
|
123
|
+
2. Wait for each agent to write final state to its handoff file
|
|
124
|
+
3. Delete heartbeat and keep-alive cron jobs via `CronDelete`
|
|
125
|
+
4. Call `TeamDelete` to destroy the team and all inboxes
|
|
126
|
+
5. Write `story-report.md`
|
|
127
|
+
6. Commit and push to story branch
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Valent Pipeline — Codex Agent Instructions
|
|
2
|
+
|
|
3
|
+
> This file provides pipeline-wide rules for all agents running under OpenAI Codex.
|
|
4
|
+
> It is the Codex equivalent of project-level CLAUDE.md instructions.
|
|
5
|
+
|
|
6
|
+
## Communication Standard
|
|
7
|
+
|
|
8
|
+
All output follows the V3 Distilled Communication Standard:
|
|
9
|
+
- Write for machine consumption, not human readability
|
|
10
|
+
- Structured data (YAML, lists, key-value) over prose paragraphs
|
|
11
|
+
- Facts and decisions only — no filler sentences
|
|
12
|
+
- Section headers as semantic labels
|
|
13
|
+
- Explicit cross-references using file paths and section anchors
|
|
14
|
+
|
|
15
|
+
Full reference: `.valent-pipeline/docs/communication-standard.md`
|
|
16
|
+
|
|
17
|
+
## Output Format
|
|
18
|
+
|
|
19
|
+
Every handoff document must include:
|
|
20
|
+
1. **YAML frontmatter** — agent, story, status, stepsCompleted, pendingSteps, lastCheckpoint, inputsRead, outputsWritten, blockers
|
|
21
|
+
2. **Orchestrator Summary** — Agent, Story, Verdict (pass/fail/needs-review), State transition, Files created/modified, Flags
|
|
22
|
+
|
|
23
|
+
Full schema: `.valent-pipeline/docs/communication-standard.md#3` and `#4`
|
|
24
|
+
|
|
25
|
+
## Shared Context
|
|
26
|
+
|
|
27
|
+
At startup, every agent reads:
|
|
28
|
+
1. Its core prompt from `.valent-pipeline/prompts/{agent}.md`
|
|
29
|
+
2. Shared context from `{story_output_dir}/pipeline-context.md`
|
|
30
|
+
3. Step files at the point of execution (not before)
|
|
31
|
+
|
|
32
|
+
## File Conventions
|
|
33
|
+
|
|
34
|
+
- Write all output to `{story_output_dir}/`
|
|
35
|
+
- Use the appropriate template from `.valent-pipeline/templates/`
|
|
36
|
+
- Cross-reference files by path and section anchor: `file.md#section`
|
|
37
|
+
- Never reference implicit shared context — everything must be explicit
|
|
38
|
+
|
|
39
|
+
## Signal Delivery
|
|
40
|
+
|
|
41
|
+
In Codex mode, thread completion IS your handoff signal. Write your output files with the orchestrator summary verdict, then complete. Lead reads your verdict from the handoff file and routes accordingly.
|
|
42
|
+
|
|
43
|
+
Do NOT attempt to use `SendMessage` or inbox messaging — these are Claude Code primitives not available in Codex.
|
|
44
|
+
|
|
45
|
+
## Knowledge Queries
|
|
46
|
+
|
|
47
|
+
If you need knowledge context, check `{story_output_dir}/pipeline-context.md` for the knowledge mode:
|
|
48
|
+
- If `knowledge-context.md` exists in the story output dir, read it directly
|
|
49
|
+
- Otherwise, write your query to `{story_output_dir}/knowledge-queries/{your_name}-{n}.md` and note "pending knowledge query" in your handoff. Lead will relay the response.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Codex Runtime Adapter
|
|
2
|
+
|
|
3
|
+
> **Provider:** OpenAI Codex (CLI and Cloud)
|
|
4
|
+
> **Read by:** Lead agent when `runtime.provider` is `codex` in `pipeline-config.yaml`
|
|
5
|
+
> **Purpose:** Defines HOW to spawn agent threads, coordinate via steering, track tasks via file-based registry, and manage thread lifecycle using Codex's native primitives.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Initialization
|
|
10
|
+
|
|
11
|
+
No team API call needed. Ensure the story output directory exists:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
mkdir -p {story_output_dir}/
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
No `signals/` or `inbox/` directories needed. Codex thread management handles coordination natively:
|
|
18
|
+
- Agent completion is detected by thread state
|
|
19
|
+
- Parent-to-child communication uses steering (follow-up instructions to running threads)
|
|
20
|
+
- Child-to-parent communication is via thread completion + handoff file verdict
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Task Registry
|
|
25
|
+
|
|
26
|
+
Write `{story_output_dir}/task-registry.yaml` from the resolved task graph:
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
tasks:
|
|
30
|
+
reqs:
|
|
31
|
+
status: pending # pending | in_progress | completed | blocked
|
|
32
|
+
agent: REQS
|
|
33
|
+
blocked_by: []
|
|
34
|
+
started_at: null
|
|
35
|
+
completed_at: null
|
|
36
|
+
uxa:
|
|
37
|
+
status: pending
|
|
38
|
+
agent: UXA
|
|
39
|
+
blocked_by: [reqs]
|
|
40
|
+
started_at: null
|
|
41
|
+
completed_at: null
|
|
42
|
+
# ... all tasks from task graph, filtered by project type and testing profiles
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Update protocol:**
|
|
46
|
+
- Before spawning an agent: set its task status to `in_progress`, write `started_at`
|
|
47
|
+
- After agent thread completes: set status to `completed`, write `completed_at`, check if downstream tasks are unblocked
|
|
48
|
+
- Read the registry to determine next actions (replaces `TaskList`/`TaskGet`)
|
|
49
|
+
|
|
50
|
+
**Lead is the sole writer.** Agents never modify `task-registry.yaml`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Agent Spawning
|
|
55
|
+
|
|
56
|
+
Codex subagents run as **persistent threads**. Threads stay alive until explicitly closed. Lead spawns threads, steers them with follow-up instructions, and closes them at teardown.
|
|
57
|
+
|
|
58
|
+
### Agent Type Classification
|
|
59
|
+
|
|
60
|
+
| Agent | Type | Rationale |
|
|
61
|
+
|-------|------|-----------|
|
|
62
|
+
| REQS | explorer | Reads story inputs + codebase for context, produces spec only |
|
|
63
|
+
| UXA | worker | Translates specs, may scaffold component stubs |
|
|
64
|
+
| QA-A | explorer | Reads all specs + codebase patterns, produces test spec only |
|
|
65
|
+
| READINESS | explorer | Reads all spec artifacts, produces review only |
|
|
66
|
+
| BEND | worker | Writes production code + tests, runs builds |
|
|
67
|
+
| FEND | worker | Writes UI code + tests, runs builds |
|
|
68
|
+
| IAC | worker | Writes infrastructure code |
|
|
69
|
+
| CRITIC | explorer | Multi-pass code review — reads everything, writes review doc only |
|
|
70
|
+
| QA-B | worker | Runs test suites, writes bug reports, may modify test files |
|
|
71
|
+
| JUDGE | explorer | Reads all artifacts, produces ship/reject verdict only |
|
|
72
|
+
| Knowledge | default | Reactive service — reads knowledge base, writes responses |
|
|
73
|
+
|
|
74
|
+
### Sandbox Mode Per Agent
|
|
75
|
+
|
|
76
|
+
| Agent | Sandbox Mode | Notes |
|
|
77
|
+
|-------|-------------|-------|
|
|
78
|
+
| REQS, UXA, READINESS | `workspace-write` | Read files, write handoff docs |
|
|
79
|
+
| QA-A | `workspace-write` | Read files, write test spec |
|
|
80
|
+
| BEND, FEND, IAC | `workspace-write` | Read/write files, run shell (npm install, build, git). Network enabled for deps. |
|
|
81
|
+
| CRITIC, JUDGE | `read-only` | Only reads code. Override `writable_roots` for story output dir. |
|
|
82
|
+
| QA-B | `workspace-write` | Run test suites, start local servers. Network enabled, `allow_local_binding: true`. |
|
|
83
|
+
| PMCP | `workspace-write` | Run Playwright MCP. Network enabled, `allow_local_binding: true`. |
|
|
84
|
+
| Knowledge | `workspace-write` | Read knowledge files, write responses |
|
|
85
|
+
|
|
86
|
+
### Sequential Phases (Wave 1)
|
|
87
|
+
|
|
88
|
+
Spawn threads one at a time. Each reads predecessor output from disk.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Lead spawns REQS thread → REQS writes reqs-brief.md → completes
|
|
92
|
+
Lead reads handoff file verdict, updates task-registry.yaml
|
|
93
|
+
Lead spawns UXA thread → UXA reads reqs-brief.md, writes uxa-spec.md → completes
|
|
94
|
+
...
|
|
95
|
+
Lead spawns READINESS thread → reviews specs → completes
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Parallel Phases (Wave 2)
|
|
99
|
+
|
|
100
|
+
Spawn BEND, FEND, IAC as parallel threads. All read from approved specs on disk.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Lead spawns [BEND, FEND, IAC] as parallel threads
|
|
104
|
+
All three read from qa-test-spec.md + readiness-review.md on disk
|
|
105
|
+
All three write separate output files
|
|
106
|
+
Lead waits for all threads to complete
|
|
107
|
+
Lead updates task-registry.yaml for all three
|
|
108
|
+
Lead spawns CRITIC thread
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Wave Spawn Triggers
|
|
112
|
+
|
|
113
|
+
Same as Claude Code — spawn next wave when current blocking agent starts:
|
|
114
|
+
|
|
115
|
+
| Wave | Trigger | Agents |
|
|
116
|
+
|------|---------|--------|
|
|
117
|
+
| 1 | At kick-off | Knowledge, REQS, UXA, QA-A, READINESS |
|
|
118
|
+
| 2 | QA-A completes (READINESS approved) | BEND, FEND, IAC, CRITIC (each only if not skipped) |
|
|
119
|
+
| 3 | CRITIC starts | QA-B, PMCP (if ui profile) |
|
|
120
|
+
| 4 | JUDGE bug-review starts | (reserved) |
|
|
121
|
+
|
|
122
|
+
### Spawn Template
|
|
123
|
+
|
|
124
|
+
Each agent receives a prompt built from `.valent-pipeline/spawn-templates/agent-spawn.template.md` (same template as Claude Code, without SendMessage instructions). The template tells the agent to:
|
|
125
|
+
1. Read its core prompt
|
|
126
|
+
2. Read shared context
|
|
127
|
+
3. Execute steps
|
|
128
|
+
4. Write output files to `{story_output_dir}/`
|
|
129
|
+
5. Complete (Lead manages thread lifecycle)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Rejection Loop (Steering, Not Re-Spawning)
|
|
134
|
+
|
|
135
|
+
Because threads persist, rejection loops use steering instead of re-spawning:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
Lead spawns CRITIC thread → CRITIC writes critic-review.md → completes with verdict
|
|
139
|
+
If verdict == rejection:
|
|
140
|
+
Lead steers BEND thread with follow-up: "CRITIC rejected. See critic-review.md#finding-1. Fix."
|
|
141
|
+
BEND fixes in-place → completes
|
|
142
|
+
Lead steers CRITIC thread: "BEND pushed fixes. Re-review."
|
|
143
|
+
CRITIC re-reviews → completes
|
|
144
|
+
Loop until approved or circuit breaker
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This preserves agent context from the initial implementation — no re-loading of codebase or specs.
|
|
148
|
+
|
|
149
|
+
If a thread was already closed (crash, timeout), Lead spawns a new thread with recovery context from handoff frontmatter.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Knowledge Agent
|
|
154
|
+
|
|
155
|
+
### Option A: Persistent Thread via Steering (Default for CLI)
|
|
156
|
+
|
|
157
|
+
Lead spawns Knowledge thread at story start. Knowledge loads correction directives, curated knowledge, and ChromaDB/SQLite sources, then signals ready.
|
|
158
|
+
|
|
159
|
+
When another agent needs knowledge:
|
|
160
|
+
1. Agent writes query to `{story_output_dir}/knowledge-queries/{agent}-{n}.md`
|
|
161
|
+
2. Agent completes its current step and notes "pending knowledge query" in handoff
|
|
162
|
+
3. Lead steers Knowledge thread: "Answer query in `knowledge-queries/{agent}-{n}.md`"
|
|
163
|
+
4. Knowledge writes response to `{story_output_dir}/knowledge-responses/{agent}-{n}.md`
|
|
164
|
+
5. Lead steers the requesting agent: "Knowledge response ready at `knowledge-responses/{agent}-{n}.md`"
|
|
165
|
+
|
|
166
|
+
Hub-and-spoke: Lead relays between agents and Knowledge. No direct agent-to-Knowledge channel.
|
|
167
|
+
|
|
168
|
+
### Option B: Pre-Computed Context File (Default for Cloud)
|
|
169
|
+
|
|
170
|
+
Lead spawns a one-shot Knowledge thread that:
|
|
171
|
+
1. Reads ALL correction directives and ALL curated knowledge entries
|
|
172
|
+
2. Produces `{story_output_dir}/knowledge-context.md` — compiled reference
|
|
173
|
+
3. Completes
|
|
174
|
+
|
|
175
|
+
All downstream agents read `knowledge-context.md` directly. Zero relay overhead.
|
|
176
|
+
|
|
177
|
+
### Option C: MCP Tool (Advanced)
|
|
178
|
+
|
|
179
|
+
Configure knowledge retrieval as an MCP tool in `.codex/config.toml`:
|
|
180
|
+
```toml
|
|
181
|
+
[mcp.knowledge]
|
|
182
|
+
type = "stdio"
|
|
183
|
+
command = "node"
|
|
184
|
+
args = [".valent-pipeline/scripts/knowledge-mcp-server.js"]
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Agents call the knowledge tool directly. No relay through Lead.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Signal Delivery
|
|
192
|
+
|
|
193
|
+
### Agent → Lead (completion/verdict)
|
|
194
|
+
|
|
195
|
+
Thread completion IS the signal. When a thread completes, Lead reads the handoff file's YAML frontmatter (`status`) and orchestrator summary (`verdict`) to determine routing:
|
|
196
|
+
- `verdict: pass` → advance downstream task, update task-registry
|
|
197
|
+
- `verdict: fail` → route rejection per re-entry map
|
|
198
|
+
- `verdict: needs-review` → escalate per Headless Escalation Protocol
|
|
199
|
+
|
|
200
|
+
No signal files needed. Lead reads the handoff artifact directly.
|
|
201
|
+
|
|
202
|
+
### Lead → Agent (instructions, rejection context, steering)
|
|
203
|
+
|
|
204
|
+
Two channels:
|
|
205
|
+
- **At spawn:** Initial prompt via spawn template.
|
|
206
|
+
- **Mid-execution:** Steering via follow-up instructions to running thread. Used for rejection rework, knowledge query relay, and course correction.
|
|
207
|
+
|
|
208
|
+
### Agent → Agent (peer communication)
|
|
209
|
+
|
|
210
|
+
Not supported natively. Hub-and-spoke only. Two patterns:
|
|
211
|
+
|
|
212
|
+
**File-based (for data):** Agent writes to `{story_output_dir}/` and the consuming agent reads it when spawned or steered. This is how handoff documents already work.
|
|
213
|
+
|
|
214
|
+
**Lead relay (for coordination):** Lead reads output from one thread, steers another thread with the relevant information. Used for Design Council deliberation and Knowledge Agent query relay.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Monitoring
|
|
219
|
+
|
|
220
|
+
Lead drives execution as an orchestration loop, managing threads directly:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
while tasks remain:
|
|
224
|
+
next_batch = get_unblocked_tasks(task_registry)
|
|
225
|
+
if parallel_safe(next_batch):
|
|
226
|
+
spawn all as parallel threads, wait for all to complete
|
|
227
|
+
else:
|
|
228
|
+
spawn sequentially, wait for each
|
|
229
|
+
update task_registry
|
|
230
|
+
check circuit breaker thresholds
|
|
231
|
+
if rejection: steer agent threads for rework (see Rejection Loop)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Stall Detection
|
|
235
|
+
|
|
236
|
+
Lead can inspect running threads via `/agent` or by checking `job_max_runtime_seconds` timeout. If a thread exceeds the timeout, Codex kills it and Lead handles the timeout as a stall — spawn a replacement thread with recovery context from handoff frontmatter.
|
|
237
|
+
|
|
238
|
+
No heartbeat cron needed — Lead observes thread state directly.
|
|
239
|
+
|
|
240
|
+
### Thread Budget
|
|
241
|
+
|
|
242
|
+
`max_threads` defaults to 6 (configurable via `runtime.codex.max_concurrent_agents`). Lead's own thread does NOT count against this limit.
|
|
243
|
+
|
|
244
|
+
**Strategy:** Close completed spec agent threads (REQS, UXA, QA-A, READINESS) before spawning Wave 2 to free slots. For rejection loops, if slots are tight, close dev threads and re-spawn with recovery context.
|
|
245
|
+
|
|
246
|
+
If `max_threads` is hit, Codex queues excess spawns. Pipeline degrades to sequential execution — slower but not broken.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Teardown
|
|
251
|
+
|
|
252
|
+
Close all agent threads and clean up:
|
|
253
|
+
1. Close all completed agent threads (ask Codex to close each thread)
|
|
254
|
+
2. Stop any still-running threads (Knowledge Agent if using Option A)
|
|
255
|
+
3. Write `story-report.md`
|
|
256
|
+
4. Commit and push to story branch
|
package/src/lib/config-schema.js
CHANGED
|
@@ -95,6 +95,23 @@ export function validateConfig(config) {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
// Runtime section (optional — provider adapter configuration)
|
|
99
|
+
if (config.runtime) {
|
|
100
|
+
const validProviders = ['claude-code', 'codex'];
|
|
101
|
+
if (config.runtime.provider && !validProviders.includes(config.runtime.provider)) {
|
|
102
|
+
errors.push(`Invalid runtime.provider: "${config.runtime.provider}". Must be one of: ${validProviders.join(', ')}`);
|
|
103
|
+
}
|
|
104
|
+
if (config.runtime.codex) {
|
|
105
|
+
if (config.runtime.codex.max_concurrent_agents !== undefined && typeof config.runtime.codex.max_concurrent_agents !== 'number') {
|
|
106
|
+
errors.push(`runtime.codex.max_concurrent_agents must be a number, got: ${typeof config.runtime.codex.max_concurrent_agents}`);
|
|
107
|
+
}
|
|
108
|
+
const validSandboxModes = ['read-only', 'workspace-write', 'danger-full-access'];
|
|
109
|
+
if (config.runtime.codex.sandbox_mode && !validSandboxModes.includes(config.runtime.codex.sandbox_mode)) {
|
|
110
|
+
errors.push(`Invalid runtime.codex.sandbox_mode: "${config.runtime.codex.sandbox_mode}". Must be one of: ${validSandboxModes.join(', ')}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
98
115
|
if (config.knowledge?.mode === 'sqlite' && !config.knowledge?.sqlite_db_path) {
|
|
99
116
|
errors.push('knowledge.sqlite_db_path is required when knowledge.mode is "sqlite"');
|
|
100
117
|
}
|
|
@@ -168,4 +185,18 @@ export const defaults = {
|
|
|
168
185
|
auto_reprioritize: true,
|
|
169
186
|
auto_generate_gap_stories: false,
|
|
170
187
|
},
|
|
188
|
+
runtime: {
|
|
189
|
+
provider: 'claude-code',
|
|
190
|
+
codex: {
|
|
191
|
+
max_concurrent_agents: 6,
|
|
192
|
+
sandbox_mode: 'workspace-write',
|
|
193
|
+
model_map: {},
|
|
194
|
+
cloud: {
|
|
195
|
+
git_remote: 'origin',
|
|
196
|
+
internet_allowlist: [],
|
|
197
|
+
setup_script: '.codex/setup.sh',
|
|
198
|
+
commit_prefix: 'pipeline',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
171
202
|
};
|