mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 10:23:24 +08:00
feat: add templates for epics, product brief, and requirements PRD
- Created a new directory structure for epics and stories with templates for individual epics and an index file. - Added a product brief template for generating product brief documents in Phase 2. - Introduced a requirements PRD template for generating a Product Requirements Document as a directory of individual requirement files in Phase 3. feat: implement V2PipelineTab component for Memory V2 management - Developed the V2PipelineTab component to manage extraction and consolidation processes. - Included ExtractionCard and ConsolidationCard components to handle respective functionalities. - Added JobsList component to display job statuses and allow filtering by job kind. feat: create hooks for Memory V2 pipeline - Implemented custom hooks for managing extraction and consolidation statuses, as well as job listings. - Added mutation hooks to trigger extraction and consolidation processes with automatic query invalidation on success.
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
# Phase 1: Requirement Clarification
|
||||
|
||||
> **COMPACT PROTECTION**: This is an execution document. After context compression, phase instructions become summaries only. You MUST immediately re-read this file via `Read("~/.codex/skills/team-lifecycle/phases/01-requirement-clarification.md")` before continuing. Never execute based on summaries.
|
||||
|
||||
## Objective
|
||||
|
||||
Parse user input, detect execution mode, apply frontend auto-detection, and gather all parameters needed for pipeline initialization. No agents are spawned in this phase -- it is purely orchestrator-local work.
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| User arguments | `$ARGUMENTS` (raw user input) | Yes |
|
||||
| Project root | Current working directory | Yes |
|
||||
| Existing sessions | `.workflow/.team/TLS-*/team-session.json` | No (checked for resume) |
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1.1: Session Resume Check (Phase 0)
|
||||
|
||||
Before requirement parsing, scan for interrupted sessions.
|
||||
|
||||
```javascript
|
||||
// Scan for active/paused sessions
|
||||
const sessionFiles = Glob(".workflow/.team/TLS-*/team-session.json")
|
||||
|
||||
// Filter to active or paused
|
||||
const activeSessions = sessionFiles
|
||||
.map(f => JSON.parse(Read(f)))
|
||||
.filter(s => s.status === "active" || s.status === "paused")
|
||||
```
|
||||
|
||||
**Decision table**:
|
||||
|
||||
| Active Sessions | Action |
|
||||
|----------------|--------|
|
||||
| 0 | Proceed to Step 1.2 (new session) |
|
||||
| 1 | Ask user: "Found active session <session-id>. Resume? (yes/no)" |
|
||||
| 2+ | Ask user to select: "Multiple active sessions found: <list>. Which to resume? (or 'new' for fresh start)" |
|
||||
|
||||
If user chooses to resume:
|
||||
- Read the selected session's state file
|
||||
- Proceed to Session Reconciliation (see orchestrator.md Session Resume section)
|
||||
- Skip remaining Phase 1 steps, jump directly to Phase 4
|
||||
|
||||
If user chooses new session:
|
||||
- Continue to Step 1.2
|
||||
|
||||
### Step 1.2: Parse Arguments
|
||||
|
||||
Extract explicit settings from user input.
|
||||
|
||||
**Recognized parameters** (from argument text or flags):
|
||||
|
||||
| Parameter | Detection | Values |
|
||||
|-----------|-----------|--------|
|
||||
| mode | Explicit mention or `--mode` flag | spec-only, impl-only, full-lifecycle, fe-only, fullstack, full-lifecycle-fe |
|
||||
| scope | Main content of user description | Free text |
|
||||
| focus | `--focus` flag or explicit mention | Comma-separated areas |
|
||||
| depth | `--depth` flag | shallow, normal, deep |
|
||||
| execution | `--parallel` or `--sequential` flag | sequential, parallel |
|
||||
| spec-path | `--spec` flag (impl-only mode) | File path to existing spec |
|
||||
|
||||
**Parsing logic**:
|
||||
|
||||
```
|
||||
Parse user input text:
|
||||
+- Contains "--mode <value>"? -> extract mode
|
||||
+- Contains "--focus <areas>"? -> extract focus areas
|
||||
+- Contains "--depth <level>"? -> extract depth
|
||||
+- Contains "--parallel"? -> execution = parallel
|
||||
+- Contains "--sequential"? -> execution = sequential
|
||||
+- Contains "--spec <path>"? -> extract spec path
|
||||
+- Remaining text after flag removal -> scope description
|
||||
```
|
||||
|
||||
### Step 1.3: Ask for Missing Parameters
|
||||
|
||||
If critical parameters are not extractable from the input, ask the user.
|
||||
|
||||
**Required parameters and fallback defaults**:
|
||||
|
||||
| Parameter | Required | Default | Ask If Missing |
|
||||
|-----------|----------|---------|----------------|
|
||||
| mode | Yes | (none) | Yes - "Which pipeline mode? (spec-only / impl-only / full-lifecycle / fe-only / fullstack / full-lifecycle-fe)" |
|
||||
| scope | Yes | (none) | Yes - "Please describe the project scope" |
|
||||
| execution | No | parallel | No - use default |
|
||||
| depth | No | normal | No - use default |
|
||||
| spec-path | Conditional | (none) | Yes, only if mode is impl-only - "Path to existing specification?" |
|
||||
|
||||
**Ask format** (output to user, then wait for response):
|
||||
|
||||
```
|
||||
[orchestrator] Phase 1: Requirement Clarification
|
||||
|
||||
Missing parameter: <parameter-name>
|
||||
<question-text>
|
||||
|
||||
Options: <option-list>
|
||||
```
|
||||
|
||||
### Step 1.4: Frontend Auto-Detection
|
||||
|
||||
For `impl-only` and `full-lifecycle` modes, check if the user description or project structure indicates frontend work.
|
||||
|
||||
**Detection signals**:
|
||||
|
||||
| Signal | Detection Method | Result |
|
||||
|--------|-----------------|--------|
|
||||
| FE keywords in scope | Match against keyword list (see below) | FE detected |
|
||||
| BE keywords in scope | Match against keyword list | BE detected |
|
||||
| FE framework in package.json | Read package.json, check for react/vue/svelte/next dependencies | FE framework present |
|
||||
| FE file patterns in project | Glob for *.tsx, *.jsx, *.vue, *.svelte | FE files exist |
|
||||
|
||||
**FE keyword list**: component, page, UI, frontend, CSS, HTML, React, Vue, Tailwind, Svelte, Next.js, Nuxt, shadcn, design system, responsive, layout, form, dialog, modal, sidebar, navbar, theme, dark mode, animation
|
||||
|
||||
**BE keyword list**: API, database, server, endpoint, backend, middleware, migration, schema, REST, GraphQL, authentication, authorization, queue, worker, cron
|
||||
|
||||
**Upgrade decision table**:
|
||||
|
||||
| Current Mode | FE Detected | BE Detected | Upgrade To |
|
||||
|-------------|-------------|-------------|------------|
|
||||
| impl-only | Yes | No | fe-only |
|
||||
| impl-only | Yes | Yes | fullstack |
|
||||
| impl-only | No | Yes | (no change) |
|
||||
| full-lifecycle | Yes | - | full-lifecycle-fe |
|
||||
| full-lifecycle | No | - | (no change) |
|
||||
| spec-only | - | - | (no change, spec is mode-agnostic) |
|
||||
| fe-only | - | - | (no change) |
|
||||
| fullstack | - | - | (no change) |
|
||||
|
||||
If an upgrade is detected, inform the user:
|
||||
|
||||
```
|
||||
[orchestrator] Frontend auto-detection: upgraded mode from <old> to <new>
|
||||
Detected signals: <signal-list>
|
||||
To override, specify --mode explicitly.
|
||||
```
|
||||
|
||||
### Step 1.5: Impl-Only Pre-Check
|
||||
|
||||
If mode is `impl-only`, verify that a specification exists:
|
||||
|
||||
```
|
||||
Mode is impl-only?
|
||||
+- spec-path provided? -> validate file exists -> proceed
|
||||
+- spec-path not provided?
|
||||
+- Scan session dir for existing spec artifacts -> found? use them
|
||||
+- Not found -> error: "impl-only requires existing spec. Provide --spec <path> or use full-lifecycle mode."
|
||||
```
|
||||
|
||||
### Step 1.6: Store Requirements
|
||||
|
||||
Assemble the final requirements object. This will be passed to Phase 2.
|
||||
|
||||
```javascript
|
||||
const requirements = {
|
||||
mode: "<finalized-mode>",
|
||||
scope: "<scope-description>",
|
||||
focus: ["<area1>", "<area2>"],
|
||||
depth: "<shallow | normal | deep>",
|
||||
execution: "<sequential | parallel>",
|
||||
spec_path: "<path-or-null>",
|
||||
frontend_detected: true | false,
|
||||
frontend_signals: ["<signal1>", "<signal2>"],
|
||||
raw_input: "<original-user-input>"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
| Output | Type | Destination |
|
||||
|--------|------|-------------|
|
||||
| requirements | Object | Passed to Phase 2 |
|
||||
| resume_session | Object or null | If resuming, session state passed to Phase 4 |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- All required parameters captured (mode, scope)
|
||||
- Mode finalized (including auto-detection upgrades)
|
||||
- If impl-only: spec path validated
|
||||
- If resuming: session state loaded and reconciled
|
||||
- No ambiguity remaining in execution parameters
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Unknown mode value | Report supported modes, ask user to clarify |
|
||||
| Spec path not found (impl-only) | Error with suggestion to use full-lifecycle |
|
||||
| User provides contradictory flags | Report conflict, ask user to resolve |
|
||||
| Session file corrupt during resume check | Skip corrupt session, proceed with new |
|
||||
| No user response to question | Wait indefinitely (interactive mode) |
|
||||
|
||||
---
|
||||
|
||||
## Next Phase
|
||||
|
||||
Proceed to [Phase 2: Team Initialization](02-team-initialization.md) with the `requirements` object.
|
||||
205
.codex/skills/team-lifecycle/phases/02-team-initialization.md
Normal file
205
.codex/skills/team-lifecycle/phases/02-team-initialization.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# Phase 2: Team Initialization
|
||||
|
||||
> **COMPACT PROTECTION**: This is an execution document. After context compression, phase instructions become summaries only. You MUST immediately re-read this file via `Read("~/.codex/skills/team-lifecycle/phases/02-team-initialization.md")` before continuing. Never execute based on summaries.
|
||||
|
||||
## Objective
|
||||
|
||||
Create the session directory structure, initialize the state file (`team-session.json`), set up wisdom and exploration cache directories. No agents are spawned in this phase.
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| requirements | Phase 1 output | Yes |
|
||||
| requirements.mode | Finalized pipeline mode | Yes |
|
||||
| requirements.scope | Project scope description | Yes |
|
||||
| requirements.execution | sequential or parallel | Yes |
|
||||
| Project root | Current working directory | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 2.1: Generate Session ID
|
||||
|
||||
```javascript
|
||||
// Generate slug from scope description (max 20 chars, kebab-case)
|
||||
const slug = requirements.scope
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-|-$/g, '')
|
||||
.slice(0, 20)
|
||||
|
||||
// Date in YYYY-MM-DD format
|
||||
const date = new Date().toISOString().slice(0, 10)
|
||||
|
||||
const sessionId = `TLS-${slug}-${date}`
|
||||
const sessionDir = `.workflow/.team/${sessionId}`
|
||||
```
|
||||
|
||||
### Step 2.2: Create Directory Structure
|
||||
|
||||
```bash
|
||||
mkdir -p "<session-dir>/spec/requirements"
|
||||
mkdir -p "<session-dir>/spec/architecture"
|
||||
mkdir -p "<session-dir>/spec/epics"
|
||||
mkdir -p "<session-dir>/discussions"
|
||||
mkdir -p "<session-dir>/plan/tasks"
|
||||
mkdir -p "<session-dir>/explorations"
|
||||
mkdir -p "<session-dir>/architecture"
|
||||
mkdir -p "<session-dir>/analysis"
|
||||
mkdir -p "<session-dir>/qa"
|
||||
mkdir -p "<session-dir>/wisdom"
|
||||
```
|
||||
|
||||
**Directory purpose reference**:
|
||||
|
||||
| Directory | Purpose | Written By |
|
||||
|-----------|---------|-----------|
|
||||
| spec/ | Specification artifacts (briefs, PRDs, architecture, epics) | analyst, writer |
|
||||
| discussions/ | Discussion records from inline discuss subagent | discuss subagent |
|
||||
| plan/ | Implementation plan and task breakdown | planner |
|
||||
| explorations/ | Shared codebase exploration cache | explore subagent |
|
||||
| architecture/ | Architect assessments, design tokens | architect |
|
||||
| analysis/ | Analyst design intelligence (UI mode) | analyst |
|
||||
| qa/ | QA audit reports | fe-qa |
|
||||
| wisdom/ | Cross-task knowledge accumulation | all agents |
|
||||
|
||||
### Step 2.3: Initialize Wisdom Directory
|
||||
|
||||
Create the four wisdom files with empty starter content:
|
||||
|
||||
```javascript
|
||||
// learnings.md
|
||||
Write("<session-dir>/wisdom/learnings.md",
|
||||
"# Learnings\n\nPatterns and insights discovered during this session.\n")
|
||||
|
||||
// decisions.md
|
||||
Write("<session-dir>/wisdom/decisions.md",
|
||||
"# Decisions\n\nArchitecture and design decisions made during this session.\n")
|
||||
|
||||
// conventions.md
|
||||
Write("<session-dir>/wisdom/conventions.md",
|
||||
"# Conventions\n\nCodebase conventions identified during this session.\n")
|
||||
|
||||
// issues.md
|
||||
Write("<session-dir>/wisdom/issues.md",
|
||||
"# Issues\n\nKnown risks and issues flagged during this session.\n")
|
||||
```
|
||||
|
||||
### Step 2.4: Initialize Explorations Cache
|
||||
|
||||
```javascript
|
||||
Write("<session-dir>/explorations/cache-index.json",
|
||||
JSON.stringify({ entries: [] }, null, 2))
|
||||
```
|
||||
|
||||
### Step 2.5: Initialize Shared Memory
|
||||
|
||||
```javascript
|
||||
Write("<session-dir>/shared-memory.json",
|
||||
JSON.stringify({
|
||||
design_intelligence: null,
|
||||
design_token_registry: null,
|
||||
component_inventory: null,
|
||||
style_decisions: null,
|
||||
qa_history: null,
|
||||
industry_context: null,
|
||||
exploration_cache: null
|
||||
}, null, 2))
|
||||
```
|
||||
|
||||
### Step 2.6: Determine Task Counts
|
||||
|
||||
Compute expected task counts based on mode:
|
||||
|
||||
| Mode | Tasks | Pipeline Composition |
|
||||
|------|-------|---------------------|
|
||||
| spec-only | 6 | Spec pipeline (6) |
|
||||
| impl-only | 4 | Impl pipeline (4) |
|
||||
| fe-only | 3 | FE pipeline (3) + possible GC loop tasks |
|
||||
| fullstack | 6 | Fullstack pipeline (6) |
|
||||
| full-lifecycle | 10 | Spec (6) + Impl (4) |
|
||||
| full-lifecycle-fe | 12 | Spec (6) + Fullstack (6) + possible GC loop tasks |
|
||||
|
||||
### Step 2.7: Write State File (team-session.json)
|
||||
|
||||
```javascript
|
||||
const state = {
|
||||
session_id: sessionId,
|
||||
mode: requirements.mode,
|
||||
scope: requirements.scope,
|
||||
focus: requirements.focus || [],
|
||||
depth: requirements.depth || "normal",
|
||||
execution: requirements.execution || "parallel",
|
||||
status: "active",
|
||||
started_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
tasks_total: taskCount, // from Step 2.6
|
||||
tasks_completed: 0,
|
||||
pipeline: [], // populated in Phase 3
|
||||
active_agents: [],
|
||||
completed_tasks: [],
|
||||
revision_chains: {},
|
||||
wisdom_entries: [],
|
||||
checkpoints_hit: [],
|
||||
gc_loop_count: 0,
|
||||
frontend_detected: requirements.frontend_detected || false,
|
||||
spec_path: requirements.spec_path || null,
|
||||
raw_input: requirements.raw_input
|
||||
}
|
||||
|
||||
Write("<session-dir>/team-session.json",
|
||||
JSON.stringify(state, null, 2))
|
||||
```
|
||||
|
||||
### Step 2.8: Output Confirmation
|
||||
|
||||
```
|
||||
[orchestrator] Phase 2: Session initialized
|
||||
Session ID: <session-id>
|
||||
Session directory: <session-dir>
|
||||
Mode: <mode> (<task-count> tasks)
|
||||
Scope: <scope-summary>
|
||||
Execution: <sequential | parallel>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
| Output | Type | Destination |
|
||||
|--------|------|-------------|
|
||||
| sessionId | String | Passed to Phase 3 |
|
||||
| sessionDir | String | Passed to Phase 3 |
|
||||
| state | Object | Written to team-session.json, passed to Phase 3 |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- Session directory created with all subdirectories
|
||||
- Wisdom files initialized (4 files)
|
||||
- Explorations cache-index.json created (empty entries)
|
||||
- Shared-memory.json created
|
||||
- team-session.json written with correct mode, scope, task count
|
||||
- State file is valid JSON and readable
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Directory already exists with same session ID | Append random suffix to slug to ensure uniqueness |
|
||||
| Write permission denied | Report error, suggest alternative directory |
|
||||
| Disk space insufficient | Report error, suggest cleanup |
|
||||
| Invalid mode in requirements | Should not happen (Phase 1 validates), but fail with message |
|
||||
|
||||
---
|
||||
|
||||
## Next Phase
|
||||
|
||||
Proceed to [Phase 3: Task Chain Creation](03-task-chain-creation.md) with `sessionId`, `sessionDir`, and `state`.
|
||||
251
.codex/skills/team-lifecycle/phases/03-task-chain-creation.md
Normal file
251
.codex/skills/team-lifecycle/phases/03-task-chain-creation.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# Phase 3: Task Chain Creation
|
||||
|
||||
> **COMPACT PROTECTION**: This is an execution document. After context compression, phase instructions become summaries only. You MUST immediately re-read this file via `Read("~/.codex/skills/team-lifecycle/phases/03-task-chain-creation.md")` before continuing. Never execute based on summaries.
|
||||
|
||||
## Objective
|
||||
|
||||
Build the full pipeline task chain based on the selected mode, write all tasks to the state file (`team-session.json`). Each task entry contains its ID, owner agent, dependencies, description, and inline discuss metadata. No agents are spawned in this phase.
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| sessionId | Phase 2 output | Yes |
|
||||
| sessionDir | Phase 2 output | Yes |
|
||||
| state | Phase 2 output (team-session.json) | Yes |
|
||||
| state.mode | Pipeline mode | Yes |
|
||||
| state.scope | Project scope | Yes |
|
||||
| state.spec_path | Spec file path (impl-only) | Conditional |
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 3.1: Mode-to-Pipeline Routing
|
||||
|
||||
Select the pipeline definition based on mode.
|
||||
|
||||
| Mode | Pipeline | First Task | Checkpoint |
|
||||
|------|----------|------------|------------|
|
||||
| spec-only | Spec pipeline (6 tasks) | RESEARCH-001 | None |
|
||||
| impl-only | Impl pipeline (4 tasks) | PLAN-001 | None |
|
||||
| fe-only | FE pipeline (3 tasks) | PLAN-001 | None |
|
||||
| fullstack | Fullstack pipeline (6 tasks) | PLAN-001 | None |
|
||||
| full-lifecycle | Spec (6) + Impl (4) | RESEARCH-001 | After QUALITY-001 |
|
||||
| full-lifecycle-fe | Spec (6) + Fullstack (6) | RESEARCH-001 | After QUALITY-001 |
|
||||
|
||||
### Step 3.2: Build Task Entries
|
||||
|
||||
For each task in the selected pipeline, create a task entry object.
|
||||
|
||||
**Task entry schema**:
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: "<TASK-ID>",
|
||||
owner: "<agent-role>",
|
||||
status: "pending",
|
||||
blocked_by: ["<dependency-task-id>", ...],
|
||||
description: "<task description>",
|
||||
inline_discuss: "<DISCUSS-NNN or null>",
|
||||
agent_id: null,
|
||||
artifact_path: null,
|
||||
discuss_verdict: null,
|
||||
discuss_severity: null,
|
||||
started_at: null,
|
||||
completed_at: null,
|
||||
revision_of: null,
|
||||
revision_count: 0,
|
||||
is_checkpoint_after: false
|
||||
}
|
||||
```
|
||||
|
||||
**Task description template** (every task gets this format):
|
||||
|
||||
```
|
||||
<task-description-from-pipeline-table>
|
||||
Session: <session-dir>
|
||||
Scope: <scope>
|
||||
InlineDiscuss: <DISCUSS-NNN or none>
|
||||
```
|
||||
|
||||
### Step 3.3: Spec Pipeline Tasks
|
||||
|
||||
Used by: spec-only, full-lifecycle, full-lifecycle-fe
|
||||
|
||||
| # | ID | Owner | BlockedBy | Description | InlineDiscuss |
|
||||
|---|-----|-------|-----------|-------------|---------------|
|
||||
| 1 | RESEARCH-001 | analyst | (none) | Seed analysis and context gathering | DISCUSS-001 |
|
||||
| 2 | DRAFT-001 | writer | RESEARCH-001 | Generate Product Brief | DISCUSS-002 |
|
||||
| 3 | DRAFT-002 | writer | DRAFT-001 | Generate Requirements/PRD | DISCUSS-003 |
|
||||
| 4 | DRAFT-003 | writer | DRAFT-002 | Generate Architecture Document | DISCUSS-004 |
|
||||
| 5 | DRAFT-004 | writer | DRAFT-003 | Generate Epics and Stories | DISCUSS-005 |
|
||||
| 6 | QUALITY-001 | reviewer | DRAFT-004 | 5-dimension spec quality + sign-off | DISCUSS-006 |
|
||||
|
||||
QUALITY-001 has `is_checkpoint_after: true` for full-lifecycle and full-lifecycle-fe modes (signals orchestrator to pause for user confirmation before impl phase).
|
||||
|
||||
### Step 3.4: Impl Pipeline Tasks
|
||||
|
||||
Used by: impl-only, full-lifecycle (PLAN-001 blockedBy QUALITY-001)
|
||||
|
||||
| # | ID | Owner | BlockedBy | Description | InlineDiscuss |
|
||||
|---|-----|-------|-----------|-------------|---------------|
|
||||
| 1 | PLAN-001 | planner | (none) | Multi-angle exploration and planning | none |
|
||||
| 2 | IMPL-001 | executor | PLAN-001 | Code implementation | none |
|
||||
| 3 | TEST-001 | tester | IMPL-001 | Test-fix cycles | none |
|
||||
| 4 | REVIEW-001 | reviewer | IMPL-001 | 4-dimension code review | none |
|
||||
|
||||
For full-lifecycle mode: PLAN-001 `blocked_by` includes `QUALITY-001`.
|
||||
|
||||
TEST-001 and REVIEW-001 both depend on IMPL-001 and can run in parallel.
|
||||
|
||||
### Step 3.5: FE Pipeline Tasks
|
||||
|
||||
Used by: fe-only
|
||||
|
||||
| # | ID | Owner | BlockedBy | Description | InlineDiscuss |
|
||||
|---|-----|-------|-----------|-------------|---------------|
|
||||
| 1 | PLAN-001 | planner | (none) | Planning (frontend focus) | none |
|
||||
| 2 | DEV-FE-001 | fe-developer | PLAN-001 | Frontend implementation | none |
|
||||
| 3 | QA-FE-001 | fe-qa | DEV-FE-001 | 5-dimension frontend QA | none |
|
||||
|
||||
GC loop: if QA-FE-001 verdict is NEEDS_FIX, the orchestrator dynamically creates DEV-FE-002 and QA-FE-002 during Phase 4. These are NOT pre-created here.
|
||||
|
||||
### Step 3.6: Fullstack Pipeline Tasks
|
||||
|
||||
Used by: fullstack, full-lifecycle-fe (PLAN-001 blockedBy QUALITY-001)
|
||||
|
||||
| # | ID | Owner | BlockedBy | Description | InlineDiscuss |
|
||||
|---|-----|-------|-----------|-------------|---------------|
|
||||
| 1 | PLAN-001 | planner | (none) | Fullstack planning | none |
|
||||
| 2 | IMPL-001 | executor | PLAN-001 | Backend implementation | none |
|
||||
| 3 | DEV-FE-001 | fe-developer | PLAN-001 | Frontend implementation | none |
|
||||
| 4 | TEST-001 | tester | IMPL-001 | Backend test-fix cycles | none |
|
||||
| 5 | QA-FE-001 | fe-qa | DEV-FE-001 | Frontend QA | none |
|
||||
| 6 | REVIEW-001 | reviewer | TEST-001, QA-FE-001 | Full code review | none |
|
||||
|
||||
IMPL-001 and DEV-FE-001 run in parallel (both depend only on PLAN-001).
|
||||
TEST-001 and QA-FE-001 run in parallel (each depends on its respective impl).
|
||||
REVIEW-001 is a sync barrier -- depends on both TEST-001 and QA-FE-001.
|
||||
|
||||
For full-lifecycle-fe: PLAN-001 `blocked_by` includes `QUALITY-001`.
|
||||
|
||||
### Step 3.7: Composite Mode Assembly
|
||||
|
||||
For composite modes, concatenate pipelines and adjust cross-pipeline dependencies.
|
||||
|
||||
**full-lifecycle** = Spec (6) + Impl (4):
|
||||
|
||||
```
|
||||
Spec pipeline tasks (Step 3.3)
|
||||
+
|
||||
Impl pipeline tasks (Step 3.4)
|
||||
with: PLAN-001.blocked_by = ["QUALITY-001"]
|
||||
with: QUALITY-001.is_checkpoint_after = true
|
||||
```
|
||||
|
||||
**full-lifecycle-fe** = Spec (6) + Fullstack (6):
|
||||
|
||||
```
|
||||
Spec pipeline tasks (Step 3.3)
|
||||
+
|
||||
Fullstack pipeline tasks (Step 3.6)
|
||||
with: PLAN-001.blocked_by = ["QUALITY-001"]
|
||||
with: QUALITY-001.is_checkpoint_after = true
|
||||
```
|
||||
|
||||
### Step 3.8: Impl-Only Pre-Check
|
||||
|
||||
If mode is `impl-only`, verify specification exists:
|
||||
|
||||
```
|
||||
state.spec_path is set?
|
||||
+- YES -> read spec file -> include path in PLAN-001 description
|
||||
+- NO -> error: "impl-only requires existing spec"
|
||||
```
|
||||
|
||||
Add to PLAN-001 description: `Spec: <spec-path>`
|
||||
|
||||
### Step 3.9: Write Pipeline to State File
|
||||
|
||||
```javascript
|
||||
// Read current state
|
||||
const state = JSON.parse(Read("<session-dir>/team-session.json"))
|
||||
|
||||
// Set pipeline
|
||||
state.pipeline = taskEntries // array of task entry objects from steps above
|
||||
state.tasks_total = taskEntries.length
|
||||
state.updated_at = new Date().toISOString()
|
||||
|
||||
// Write back
|
||||
Write("<session-dir>/team-session.json",
|
||||
JSON.stringify(state, null, 2))
|
||||
```
|
||||
|
||||
### Step 3.10: Validation
|
||||
|
||||
Before proceeding, validate the constructed pipeline.
|
||||
|
||||
| Check | Criteria | On Failure |
|
||||
|-------|----------|-----------|
|
||||
| Task count | Matches expected count for mode | Error with mismatch details |
|
||||
| Dependencies | Every blocked_by reference exists as a task ID in the pipeline | Error with dangling reference |
|
||||
| No cycles | Topological sort succeeds (no circular dependencies) | Error with cycle details |
|
||||
| Owner assignment | Each task owner matches a valid agent from Agent Registry | Error with unknown agent |
|
||||
| Unique IDs | No duplicate task IDs | Error with duplicate ID |
|
||||
| Inline discuss | Spec tasks have correct DISCUSS-NNN assignment per round config | Warning if mismatch |
|
||||
| Session reference | Every task description contains `Session: <session-dir>` | Fix missing references |
|
||||
|
||||
### Step 3.11: Output Confirmation
|
||||
|
||||
```
|
||||
[orchestrator] Phase 3: Task chain created
|
||||
Mode: <mode>
|
||||
Tasks: <count>
|
||||
Pipeline:
|
||||
<task-id> (<owner>) [blocked_by: <deps>]
|
||||
<task-id> (<owner>) [blocked_by: <deps>]
|
||||
...
|
||||
First ready task(s): <task-ids with empty blocked_by>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
| Output | Type | Destination |
|
||||
|--------|------|-------------|
|
||||
| state (updated) | Object | Written to team-session.json |
|
||||
| state.pipeline | Array | Task chain with all entries |
|
||||
| Ready task IDs | Array | Tasks with empty blocked_by (passed to Phase 4) |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- Pipeline array written to state file with correct task count
|
||||
- All dependencies are valid (no dangling, no cycles)
|
||||
- Each task has owner, description, blocked_by, inline_discuss
|
||||
- Composite modes have correct cross-pipeline dependencies
|
||||
- Spec tasks have inline discuss metadata
|
||||
- At least one task has empty blocked_by (pipeline can start)
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Unknown mode | Should not happen (Phase 1 validates), fail with supported mode list |
|
||||
| Missing spec for impl-only | Error, suggest spec-only or full-lifecycle |
|
||||
| Dependency cycle detected | Report cycle, halt pipeline creation |
|
||||
| State file read/write error | Report error, suggest re-initialization |
|
||||
| Duplicate task ID | Skip duplicate, log warning |
|
||||
|
||||
---
|
||||
|
||||
## Next Phase
|
||||
|
||||
Proceed to [Phase 4: Pipeline Coordination](04-pipeline-coordination.md) with the ready task IDs.
|
||||
719
.codex/skills/team-lifecycle/phases/04-pipeline-coordination.md
Normal file
719
.codex/skills/team-lifecycle/phases/04-pipeline-coordination.md
Normal file
@@ -0,0 +1,719 @@
|
||||
# Phase 4: Pipeline Coordination
|
||||
|
||||
> **COMPACT PROTECTION**: This is an execution document. After context compression, phase instructions become summaries only. You MUST immediately re-read this file via `Read("~/.codex/skills/team-lifecycle/phases/04-pipeline-coordination.md")` before continuing. Never execute based on summaries.
|
||||
|
||||
## Objective
|
||||
|
||||
Execute the main spawn/wait/close coordination loop. This is the core phase where the orchestrator spawns agents for pipeline tasks, waits for results, processes outputs (including consensus severity routing), handles checkpoints, and advances the pipeline through fast-advance or sequential beats until all tasks complete.
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| sessionDir | Phase 2/3 output | Yes |
|
||||
| state | team-session.json (current) | Yes |
|
||||
| state.pipeline | Task chain from Phase 3 | Yes |
|
||||
| state.mode | Pipeline mode | Yes |
|
||||
| state.execution | sequential or parallel | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Constants
|
||||
|
||||
| Constant | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| SPEC_AGENT_TIMEOUT | 900000 (15 min) | Timeout for spec pipeline agents (analyst, writer, reviewer) |
|
||||
| IMPL_AGENT_TIMEOUT | 1800000 (30 min) | Timeout for impl pipeline agents (executor, tester, planner) |
|
||||
| CONVERGENCE_WAIT | 120000 (2 min) | Additional wait after sending convergence request |
|
||||
| MAX_RETRIES_PER_TASK | 3 | Maximum retries for a failing task before escalation |
|
||||
| MAX_GC_ROUNDS | 2 | Maximum QA-FE fix-retest iterations |
|
||||
| ORPHAN_THRESHOLD | 300000 (5 min) | Time before orphaned in_progress task is reset |
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 4.1: Compute Ready Tasks
|
||||
|
||||
Read the state file and find all tasks that can be started.
|
||||
|
||||
```javascript
|
||||
// Read current state
|
||||
const state = JSON.parse(Read("<session-dir>/team-session.json"))
|
||||
|
||||
// Compute sets
|
||||
const completedIds = state.pipeline
|
||||
.filter(t => t.status === "completed")
|
||||
.map(t => t.id)
|
||||
|
||||
const inProgressIds = state.pipeline
|
||||
.filter(t => t.status === "in_progress")
|
||||
.map(t => t.id)
|
||||
|
||||
const readyTasks = state.pipeline.filter(t =>
|
||||
t.status === "pending"
|
||||
&& t.blocked_by.every(dep => completedIds.includes(dep))
|
||||
)
|
||||
```
|
||||
|
||||
**Decision table** (what to do with ready tasks):
|
||||
|
||||
| Ready Count | In-Progress Count | Action |
|
||||
|-------------|-------------------|--------|
|
||||
| 0 | >0 | Wait for running agents (enter wait loop) |
|
||||
| 0 | 0 | Pipeline complete -> proceed to Phase 5 |
|
||||
| 1 | 0 | Spawn single agent, enter wait loop |
|
||||
| 1+ | 0 | Spawn all ready agents (parallel or sequential per config), enter wait loop |
|
||||
| 1+ | >0 | Spawn ready agents alongside running, enter wait loop |
|
||||
|
||||
### Step 4.2: Checkpoint Check
|
||||
|
||||
Before spawning, check if a checkpoint was just reached.
|
||||
|
||||
```javascript
|
||||
// Check if the most recently completed task has is_checkpoint_after = true
|
||||
const justCompleted = state.pipeline.filter(t => t.status === "completed")
|
||||
const lastCompleted = justCompleted[justCompleted.length - 1]
|
||||
|
||||
if (lastCompleted && lastCompleted.is_checkpoint_after
|
||||
&& !state.checkpoints_hit.includes(lastCompleted.id)) {
|
||||
// Checkpoint reached
|
||||
state.checkpoints_hit.push(lastCompleted.id)
|
||||
// Write state
|
||||
// Output checkpoint message and pause
|
||||
}
|
||||
```
|
||||
|
||||
**Checkpoint behavior**:
|
||||
|
||||
| Checkpoint Task | Message | Resume Condition |
|
||||
|----------------|---------|-----------------|
|
||||
| QUALITY-001 | "SPEC PHASE COMPLETE. Review spec artifacts before proceeding to implementation. Type 'resume' to continue." | User types 'resume' |
|
||||
| DISCUSS-006 HIGH | "Final sign-off blocked with HIGH severity. Review divergences and decide. Type 'resume' to proceed or 'revise' to create revision." | User command |
|
||||
|
||||
When paused at checkpoint:
|
||||
1. Update state: `status = "paused"`
|
||||
2. Write state file
|
||||
3. Output checkpoint message
|
||||
4. Yield -- orchestrator stops, waits for user
|
||||
|
||||
When user resumes from checkpoint:
|
||||
1. Update state: `status = "active"`
|
||||
2. Proceed to spawn ready tasks
|
||||
|
||||
### Step 4.3: Spawn Agents
|
||||
|
||||
For each ready task, spawn an agent using the agent spawn template.
|
||||
|
||||
```javascript
|
||||
const spawnedAgents = []
|
||||
|
||||
for (const task of readyTasks) {
|
||||
// Determine timeout based on pipeline phase
|
||||
const timeout = isSpecTask(task.id) ? SPEC_AGENT_TIMEOUT : IMPL_AGENT_TIMEOUT
|
||||
|
||||
// Build predecessor context
|
||||
const predecessorContext = task.blocked_by.map(depId => {
|
||||
const depTask = state.pipeline.find(t => t.id === depId)
|
||||
return `${depId}: ${depTask.artifact_path || "(no artifact)"}`
|
||||
}).join("\n")
|
||||
|
||||
// Spawn agent
|
||||
const agentId = spawn_agent({
|
||||
message: `
|
||||
## TASK ASSIGNMENT
|
||||
|
||||
### MANDATORY FIRST STEPS (Agent Execute)
|
||||
1. **Read role definition**: ~/.codex/agents/${task.owner}.md (MUST read first)
|
||||
2. Read session state: ${sessionDir}/team-session.json
|
||||
3. Read wisdom files: ${sessionDir}/wisdom/*.md (if exists)
|
||||
|
||||
---
|
||||
|
||||
## Session
|
||||
Session directory: ${sessionDir}
|
||||
Task ID: ${task.id}
|
||||
Pipeline mode: ${state.mode}
|
||||
|
||||
## Scope
|
||||
${state.scope}
|
||||
|
||||
## Task
|
||||
${task.description}
|
||||
|
||||
## InlineDiscuss
|
||||
${task.inline_discuss || "none"}
|
||||
|
||||
## Dependencies (completed predecessors)
|
||||
${predecessorContext || "(none - this is the first task)"}
|
||||
|
||||
## Constraints
|
||||
- Only process ${task.id} (prefix: ${task.id.split('-')[0]}-*)
|
||||
- All output prefixed with [${task.owner}] tag
|
||||
- Write artifacts to ${sessionDir}/${getArtifactSubdir(task)}
|
||||
- Read wisdom files for cross-task knowledge before starting
|
||||
- After completion, append discoveries to wisdom files
|
||||
- If InlineDiscuss is set, spawn discuss subagent after primary artifact creation
|
||||
(Read ~/.codex/agents/discuss-agent.md for protocol)
|
||||
- If codebase exploration is needed, spawn explore subagent
|
||||
(Read ~/.codex/agents/explore-agent.md for protocol)
|
||||
|
||||
## Completion Protocol
|
||||
When work is complete, output EXACTLY:
|
||||
|
||||
TASK_COMPLETE:
|
||||
- task_id: ${task.id}
|
||||
- status: <success | failed | partial>
|
||||
- artifact: <path-to-primary-artifact>
|
||||
- discuss_verdict: <consensus_reached | consensus_blocked | none>
|
||||
- discuss_severity: <HIGH | MEDIUM | LOW | none>
|
||||
- summary: <one-line summary>
|
||||
`
|
||||
})
|
||||
|
||||
// Record in state
|
||||
task.status = "in_progress"
|
||||
task.agent_id = agentId
|
||||
task.started_at = new Date().toISOString()
|
||||
|
||||
spawnedAgents.push({ agentId, taskId: task.id, owner: task.owner, timeout })
|
||||
|
||||
state.active_agents.push({
|
||||
agent_id: agentId,
|
||||
task_id: task.id,
|
||||
owner: task.owner,
|
||||
spawned_at: new Date().toISOString()
|
||||
})
|
||||
}
|
||||
|
||||
// Update state file
|
||||
state.updated_at = new Date().toISOString()
|
||||
Write("<session-dir>/team-session.json", JSON.stringify(state, null, 2))
|
||||
```
|
||||
|
||||
**Agent-to-artifact-subdirectory mapping** (`getArtifactSubdir`):
|
||||
|
||||
| Agent / Task Prefix | Subdirectory |
|
||||
|---------------------|-------------|
|
||||
| analyst / RESEARCH-* | spec/ |
|
||||
| writer / DRAFT-* | spec/ |
|
||||
| reviewer / QUALITY-* | spec/ |
|
||||
| planner / PLAN-* | plan/ |
|
||||
| executor / IMPL-* | (project root - code changes) |
|
||||
| tester / TEST-* | qa/ |
|
||||
| reviewer / REVIEW-* | qa/ |
|
||||
| architect / ARCH-* | architecture/ |
|
||||
| fe-developer / DEV-FE-* | (project root - code changes) |
|
||||
| fe-qa / QA-FE-* | qa/ |
|
||||
|
||||
### Step 4.4: Wait Loop
|
||||
|
||||
Enter the main wait loop. Wait for all spawned agents, then process results.
|
||||
|
||||
```javascript
|
||||
// Collect all active agent IDs
|
||||
const activeAgentIds = spawnedAgents.map(a => a.agentId)
|
||||
|
||||
// Determine timeout (use the maximum among spawned agents)
|
||||
const maxTimeout = Math.max(...spawnedAgents.map(a => a.timeout))
|
||||
|
||||
// Wait for all agents
|
||||
const results = wait({ ids: activeAgentIds, timeout_ms: maxTimeout })
|
||||
```
|
||||
|
||||
### Step 4.5: Timeout Handling
|
||||
|
||||
If any agent timed out, send convergence request and retry.
|
||||
|
||||
```javascript
|
||||
if (results.timed_out) {
|
||||
for (const agent of spawnedAgents) {
|
||||
if (!results.status[agent.agentId]?.completed) {
|
||||
// Send convergence request
|
||||
send_input({
|
||||
id: agent.agentId,
|
||||
message: `
|
||||
## TIMEOUT NOTIFICATION
|
||||
|
||||
Execution timeout reached for task ${agent.taskId}. Please:
|
||||
1. Save all current progress to artifact files
|
||||
2. Output TASK_COMPLETE with status: partial
|
||||
3. Include summary of completed vs remaining work
|
||||
`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Wait additional convergence period
|
||||
const convergenceResults = wait({
|
||||
ids: activeAgentIds.filter(id => !results.status[id]?.completed),
|
||||
timeout_ms: CONVERGENCE_WAIT
|
||||
})
|
||||
|
||||
// Merge results
|
||||
// Agents still not complete after convergence -> force close
|
||||
for (const agent of spawnedAgents) {
|
||||
const agentResult = results.status[agent.agentId]?.completed
|
||||
|| convergenceResults.status?.[agent.agentId]?.completed
|
||||
|
||||
if (!agentResult) {
|
||||
// Force close and mark as failed
|
||||
close_agent({ id: agent.agentId })
|
||||
handleTaskFailure(agent.taskId, "timeout after convergence request")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4.6: Process Agent Results
|
||||
|
||||
For each completed agent, extract TASK_COMPLETE data and update state.
|
||||
|
||||
```javascript
|
||||
for (const agent of spawnedAgents) {
|
||||
const output = results.status[agent.agentId]?.completed
|
||||
if (!output) continue // handled in timeout section
|
||||
|
||||
// Parse TASK_COMPLETE from output
|
||||
const taskResult = parseTaskComplete(output)
|
||||
|
||||
if (!taskResult) {
|
||||
// Malformed output - treat as partial success
|
||||
handleMalformedOutput(agent.taskId, output)
|
||||
continue
|
||||
}
|
||||
|
||||
// Update task in state
|
||||
const task = state.pipeline.find(t => t.id === agent.taskId)
|
||||
task.status = taskResult.status === "failed" ? "failed" : "completed"
|
||||
task.artifact_path = taskResult.artifact
|
||||
task.discuss_verdict = taskResult.discuss_verdict
|
||||
task.discuss_severity = taskResult.discuss_severity
|
||||
task.completed_at = new Date().toISOString()
|
||||
|
||||
// Remove from active agents
|
||||
state.active_agents = state.active_agents.filter(
|
||||
a => a.agent_id !== agent.agentId
|
||||
)
|
||||
|
||||
// Add to completed
|
||||
if (task.status === "completed") {
|
||||
state.completed_tasks.push(task.id)
|
||||
state.tasks_completed++
|
||||
}
|
||||
|
||||
// Close agent
|
||||
close_agent({ id: agent.agentId })
|
||||
|
||||
// Route by consensus verdict
|
||||
if (taskResult.discuss_verdict === "consensus_blocked") {
|
||||
handleConsensusBlocked(task, taskResult)
|
||||
}
|
||||
}
|
||||
|
||||
// Write updated state
|
||||
state.updated_at = new Date().toISOString()
|
||||
Write("<session-dir>/team-session.json", JSON.stringify(state, null, 2))
|
||||
```
|
||||
|
||||
### Step 4.7: Consensus Severity Routing
|
||||
|
||||
Handle consensus_blocked results from agents with inline discuss.
|
||||
|
||||
```javascript
|
||||
function handleConsensusBlocked(task, taskResult) {
|
||||
const severity = taskResult.discuss_severity
|
||||
|
||||
switch (severity) {
|
||||
case "LOW":
|
||||
// Treat as consensus_reached with notes
|
||||
// No special action needed, proceed normally
|
||||
break
|
||||
|
||||
case "MEDIUM":
|
||||
// Log warning to wisdom/issues.md
|
||||
appendToFile("<session-dir>/wisdom/issues.md",
|
||||
`\n## ${task.id} - Consensus Warning (MEDIUM)\n`
|
||||
+ `Divergences: ${taskResult.divergences || "see discussion record"}\n`
|
||||
+ `Action items: ${taskResult.action_items || "see discussion record"}\n`)
|
||||
// Proceed normally
|
||||
break
|
||||
|
||||
case "HIGH":
|
||||
// Check if this is DISCUSS-006 (final sign-off)
|
||||
if (task.inline_discuss === "DISCUSS-006") {
|
||||
// Always pause for user decision
|
||||
state.status = "paused"
|
||||
state.checkpoints_hit.push(`${task.id}-DISCUSS-006-HIGH`)
|
||||
// Output will include pause message
|
||||
return // Do not advance pipeline
|
||||
}
|
||||
|
||||
// Check revision limit
|
||||
if (task.revision_count >= 1) {
|
||||
// Already revised once, escalate to user
|
||||
state.status = "paused"
|
||||
// Output escalation message
|
||||
return
|
||||
}
|
||||
|
||||
// Create revision task
|
||||
const revisionTask = {
|
||||
id: `${task.id}-R1`,
|
||||
owner: task.owner,
|
||||
status: "pending",
|
||||
blocked_by: [],
|
||||
description: `Revision of ${task.id}: address consensus-blocked divergences.\n`
|
||||
+ `Session: ${sessionDir}\n`
|
||||
+ `Original artifact: ${task.artifact_path}\n`
|
||||
+ `Divergences: ${taskResult.divergences || "see discussion record"}\n`
|
||||
+ `Action items: ${taskResult.action_items || "see discussion record"}\n`
|
||||
+ `InlineDiscuss: ${task.inline_discuss}`,
|
||||
inline_discuss: task.inline_discuss,
|
||||
agent_id: null,
|
||||
artifact_path: null,
|
||||
discuss_verdict: null,
|
||||
discuss_severity: null,
|
||||
started_at: null,
|
||||
completed_at: null,
|
||||
revision_of: task.id,
|
||||
revision_count: task.revision_count + 1,
|
||||
is_checkpoint_after: task.is_checkpoint_after
|
||||
}
|
||||
|
||||
// Insert revision into pipeline (after the original task)
|
||||
const taskIndex = state.pipeline.findIndex(t => t.id === task.id)
|
||||
state.pipeline.splice(taskIndex + 1, 0, revisionTask)
|
||||
state.tasks_total++
|
||||
|
||||
// Update dependent tasks: anything blocked_by task.id should now be blocked_by revision.id
|
||||
for (const t of state.pipeline) {
|
||||
const depIdx = t.blocked_by.indexOf(task.id)
|
||||
if (depIdx !== -1) {
|
||||
t.blocked_by[depIdx] = revisionTask.id
|
||||
}
|
||||
}
|
||||
|
||||
// Track revision chain
|
||||
state.revision_chains[task.id] = revisionTask.id
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4.8: GC Loop Handling (Frontend QA)
|
||||
|
||||
When QA-FE agent completes with verdict NEEDS_FIX:
|
||||
|
||||
```javascript
|
||||
function handleGCLoop(qaTask, taskResult) {
|
||||
if (state.gc_loop_count >= MAX_GC_ROUNDS) {
|
||||
// Max rounds reached, stop loop
|
||||
// Output: "QA-FE max rounds reached. Latest report: <artifact-path>"
|
||||
return
|
||||
}
|
||||
|
||||
state.gc_loop_count++
|
||||
const round = state.gc_loop_count + 1
|
||||
|
||||
// Create DEV-FE-NNN (fix task)
|
||||
const devFeTask = {
|
||||
id: `DEV-FE-${String(round).padStart(3, '0')}`,
|
||||
owner: "fe-developer",
|
||||
status: "pending",
|
||||
blocked_by: [qaTask.id],
|
||||
description: `Frontend fix round ${round}: address QA findings.\n`
|
||||
+ `Session: ${sessionDir}\n`
|
||||
+ `QA Report: ${qaTask.artifact_path}\n`
|
||||
+ `Scope: ${state.scope}`,
|
||||
inline_discuss: null,
|
||||
agent_id: null,
|
||||
artifact_path: null,
|
||||
discuss_verdict: null,
|
||||
discuss_severity: null,
|
||||
started_at: null,
|
||||
completed_at: null,
|
||||
revision_of: null,
|
||||
revision_count: 0,
|
||||
is_checkpoint_after: false
|
||||
}
|
||||
|
||||
// Create QA-FE-NNN (retest task)
|
||||
const qaFeTask = {
|
||||
id: `QA-FE-${String(round).padStart(3, '0')}`,
|
||||
owner: "fe-qa",
|
||||
status: "pending",
|
||||
blocked_by: [devFeTask.id],
|
||||
description: `Frontend QA round ${round}: retest after fixes.\n`
|
||||
+ `Session: ${sessionDir}\n`
|
||||
+ `Scope: ${state.scope}`,
|
||||
inline_discuss: null,
|
||||
agent_id: null,
|
||||
artifact_path: null,
|
||||
discuss_verdict: null,
|
||||
discuss_severity: null,
|
||||
started_at: null,
|
||||
completed_at: null,
|
||||
revision_of: null,
|
||||
revision_count: 0,
|
||||
is_checkpoint_after: false
|
||||
}
|
||||
|
||||
// Add to pipeline
|
||||
state.pipeline.push(devFeTask, qaFeTask)
|
||||
state.tasks_total += 2
|
||||
|
||||
// Update downstream dependencies (e.g., REVIEW-001 blocked_by QA-FE-001 -> QA-FE-NNN)
|
||||
for (const t of state.pipeline) {
|
||||
const depIdx = t.blocked_by.indexOf(qaTask.id)
|
||||
if (depIdx !== -1 && t.id !== devFeTask.id) {
|
||||
t.blocked_by[depIdx] = qaFeTask.id
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4.9: Fast-Advance Check
|
||||
|
||||
After processing all results, determine whether to fast-advance or yield.
|
||||
|
||||
```javascript
|
||||
// Recompute ready tasks after processing
|
||||
const newReadyTasks = state.pipeline.filter(t =>
|
||||
t.status === "pending"
|
||||
&& t.blocked_by.every(dep =>
|
||||
state.pipeline.find(p => p.id === dep)?.status === "completed"
|
||||
)
|
||||
)
|
||||
|
||||
const stillRunning = state.active_agents.length > 0
|
||||
```
|
||||
|
||||
**Fast-advance decision table**:
|
||||
|
||||
| Ready Count | Still Running | Checkpoint Pending | Action |
|
||||
|-------------|---------------|-------------------|--------|
|
||||
| 0 | Yes | No | Yield, wait for running agents |
|
||||
| 0 | No | No | Pipeline complete -> Phase 5 |
|
||||
| 0 | No | Yes | Paused at checkpoint, yield |
|
||||
| 1 | No | No | Fast-advance: spawn immediately, re-enter Step 4.3 |
|
||||
| 1 | Yes | No | Spawn alongside running, re-enter wait loop |
|
||||
| 2+ | Any | No | Spawn all ready (batch), re-enter wait loop |
|
||||
| Any | Any | Yes | Paused at checkpoint, yield |
|
||||
|
||||
```javascript
|
||||
if (state.status === "paused") {
|
||||
// Checkpoint or escalation - yield
|
||||
// Output pause message
|
||||
return
|
||||
}
|
||||
|
||||
if (newReadyTasks.length === 0 && state.active_agents.length === 0) {
|
||||
// Pipeline complete
|
||||
// Proceed to Phase 5
|
||||
return "PIPELINE_COMPLETE"
|
||||
}
|
||||
|
||||
if (newReadyTasks.length > 0) {
|
||||
// Fast-advance: loop back to Step 4.3 with new ready tasks
|
||||
readyTasks = newReadyTasks
|
||||
// Continue to Step 4.3 (spawn agents)
|
||||
}
|
||||
|
||||
if (newReadyTasks.length === 0 && state.active_agents.length > 0) {
|
||||
// Wait for running agents
|
||||
// Re-enter Step 4.4 (wait loop)
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4.10: Orphan Detection
|
||||
|
||||
When processing a resume command or between beats, check for orphaned tasks.
|
||||
|
||||
```javascript
|
||||
function detectOrphans(state) {
|
||||
const now = Date.now()
|
||||
|
||||
for (const task of state.pipeline) {
|
||||
if (task.status !== "in_progress") continue
|
||||
|
||||
// Check if there is an active agent for this task
|
||||
const hasAgent = state.active_agents.some(a => a.task_id === task.id)
|
||||
|
||||
if (!hasAgent) {
|
||||
// Task is in_progress but no agent is tracking it
|
||||
const elapsed = now - new Date(task.started_at).getTime()
|
||||
|
||||
if (elapsed > ORPHAN_THRESHOLD) {
|
||||
// Orphaned task (likely fast-advance failure)
|
||||
task.status = "pending"
|
||||
task.agent_id = null
|
||||
task.started_at = null
|
||||
|
||||
// Log to wisdom
|
||||
appendToFile("<session-dir>/wisdom/issues.md",
|
||||
`\n## Orphaned Task Reset: ${task.id}\n`
|
||||
+ `Task was in_progress for ${Math.round(elapsed / 1000)}s with no active agent. Reset to pending.\n`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4.11: Status Output
|
||||
|
||||
After each beat cycle, output a status summary.
|
||||
|
||||
```
|
||||
[orchestrator] Beat complete
|
||||
Completed this beat: <task-ids>
|
||||
Still running: <task-ids> (<agent-roles>)
|
||||
Ready to spawn: <task-ids>
|
||||
Progress: <completed>/<total> (<percent>%)
|
||||
Next action: <spawning | waiting | checkpoint-paused | pipeline-complete>
|
||||
```
|
||||
|
||||
### Step 4.12: User Command Handling
|
||||
|
||||
During Phase 4, user may issue commands.
|
||||
|
||||
**`check` / `status`**:
|
||||
|
||||
```
|
||||
Read state file -> output status graph (see orchestrator.md User Commands) -> yield
|
||||
No pipeline advancement.
|
||||
```
|
||||
|
||||
**`resume` / `continue`**:
|
||||
|
||||
```
|
||||
Read state file
|
||||
+- status === "paused"?
|
||||
| +- YES -> update status to "active" -> detectOrphans -> Step 4.1 (compute ready)
|
||||
| +- NO -> detectOrphans -> Step 4.1 (compute ready)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pipeline Execution Patterns
|
||||
|
||||
### Spec-only (6 linear beats)
|
||||
|
||||
```javascript
|
||||
// Beat 1: RESEARCH-001 (analyst)
|
||||
analyst = spawn_agent(analystPrompt)
|
||||
result = wait([analyst]) -> close_agent(analyst)
|
||||
// Process discuss result (DISCUSS-001)
|
||||
// Fast-advance to beat 2
|
||||
|
||||
// Beat 2: DRAFT-001 (writer)
|
||||
writer1 = spawn_agent(writerPromptForDRAFT001)
|
||||
result = wait([writer1]) -> close_agent(writer1)
|
||||
// Process discuss result (DISCUSS-002)
|
||||
// Fast-advance to beat 3
|
||||
|
||||
// Beats 3-5: DRAFT-002, DRAFT-003, DRAFT-004 (same pattern)
|
||||
// Each: spawn writer -> wait -> close -> process discuss -> fast-advance
|
||||
|
||||
// Beat 6: QUALITY-001 (reviewer)
|
||||
reviewer = spawn_agent(reviewerPromptForQUALITY001)
|
||||
result = wait([reviewer]) -> close_agent(reviewer)
|
||||
// Process discuss result (DISCUSS-006)
|
||||
// If full-lifecycle: CHECKPOINT -> pause for user
|
||||
// If spec-only: PIPELINE_COMPLETE -> Phase 5
|
||||
```
|
||||
|
||||
### Impl-only (3 beats with parallel window)
|
||||
|
||||
```javascript
|
||||
// Beat 1: PLAN-001 (planner)
|
||||
planner = spawn_agent(plannerPrompt)
|
||||
result = wait([planner]) -> close_agent(planner)
|
||||
|
||||
// Beat 2: IMPL-001 (executor)
|
||||
executor = spawn_agent(executorPrompt)
|
||||
result = wait([executor]) -> close_agent(executor)
|
||||
|
||||
// Beat 3: TEST-001 || REVIEW-001 (parallel)
|
||||
tester = spawn_agent(testerPrompt)
|
||||
reviewer = spawn_agent(reviewerPrompt)
|
||||
results = wait([tester, reviewer]) // batch wait
|
||||
close_agent(tester)
|
||||
close_agent(reviewer)
|
||||
// PIPELINE_COMPLETE -> Phase 5
|
||||
```
|
||||
|
||||
### Fullstack (4 beats with dual parallel)
|
||||
|
||||
```javascript
|
||||
// Beat 1: PLAN-001
|
||||
planner = spawn_agent(plannerPrompt)
|
||||
result = wait([planner]) -> close_agent(planner)
|
||||
|
||||
// Beat 2: IMPL-001 || DEV-FE-001 (parallel)
|
||||
executor = spawn_agent(executorPrompt)
|
||||
feDev = spawn_agent(feDevPrompt)
|
||||
results = wait([executor, feDev])
|
||||
close_agent(executor)
|
||||
close_agent(feDev)
|
||||
|
||||
// Beat 3: TEST-001 || QA-FE-001 (parallel)
|
||||
tester = spawn_agent(testerPrompt)
|
||||
feQa = spawn_agent(feQaPrompt)
|
||||
results = wait([tester, feQa])
|
||||
close_agent(tester)
|
||||
close_agent(feQa)
|
||||
// Handle GC loop if QA-FE verdict is NEEDS_FIX
|
||||
|
||||
// Beat 4: REVIEW-001 (sync barrier)
|
||||
reviewer = spawn_agent(reviewerPrompt)
|
||||
result = wait([reviewer]) -> close_agent(reviewer)
|
||||
// PIPELINE_COMPLETE -> Phase 5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
| Output | Type | Destination |
|
||||
|--------|------|-------------|
|
||||
| state (final) | Object | Updated in team-session.json throughout |
|
||||
| Pipeline status | String | "PIPELINE_COMPLETE" or "PAUSED" |
|
||||
| All task artifacts | Files | Written by agents to session subdirectories |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- All pipeline tasks reach "completed" status (or "partial" with user acknowledgment)
|
||||
- State file reflects accurate pipeline status at all times
|
||||
- Checkpoints are properly enforced (spec-to-impl transition)
|
||||
- Consensus severity routing executed correctly
|
||||
- GC loop respects maximum round limit
|
||||
- No orphaned tasks at pipeline end
|
||||
- All agents properly closed
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Detection | Resolution |
|
||||
|-------|-----------|------------|
|
||||
| Agent timeout | wait() returns timed_out | Send convergence via send_input, wait 2 min, force close |
|
||||
| Agent crash | wait() returns error | Reset task to pending, respawn (max 3 retries) |
|
||||
| 3+ retries on same task | retry_count in task state | Pause pipeline, report to user |
|
||||
| Orphaned task | in_progress + no agent + elapsed > 5 min | Reset to pending, respawn |
|
||||
| Malformed TASK_COMPLETE | parseTaskComplete returns null | Treat as partial, log warning |
|
||||
| State file write conflict | Write error | Retry once, fail on second error |
|
||||
| Pipeline stall | No ready + no running + has pending | Inspect blocked_by, report to user |
|
||||
| DISCUSS-006 HIGH | Parsed from reviewer output | Always pause for user |
|
||||
| Revision also blocked | Revision task returns HIGH | Pause, escalate to user |
|
||||
| GC loop exceeded | gc_loop_count >= MAX_GC_ROUNDS | Stop loop, report QA state |
|
||||
|
||||
---
|
||||
|
||||
## Next Phase
|
||||
|
||||
When pipeline completes (all tasks done, no paused checkpoint), proceed to [Phase 5: Completion Report](05-completion-report.md).
|
||||
288
.codex/skills/team-lifecycle/phases/05-completion-report.md
Normal file
288
.codex/skills/team-lifecycle/phases/05-completion-report.md
Normal file
@@ -0,0 +1,288 @@
|
||||
# Phase 5: Completion Report
|
||||
|
||||
> **COMPACT PROTECTION**: This is an execution document. After context compression, phase instructions become summaries only. You MUST immediately re-read this file via `Read("~/.codex/skills/team-lifecycle/phases/05-completion-report.md")` before continuing. Never execute based on summaries.
|
||||
|
||||
## Objective
|
||||
|
||||
Summarize pipeline results, list all deliverable artifacts, update session status to completed, close any remaining agents, and present the user with next-step options.
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
| Input | Source | Required |
|
||||
|-------|--------|----------|
|
||||
| sessionDir | Phase 2 output | Yes |
|
||||
| state | team-session.json (final) | Yes |
|
||||
| state.pipeline | All tasks with final status | Yes |
|
||||
| state.mode | Pipeline mode | Yes |
|
||||
| state.started_at | Session start timestamp | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 5.1: Load Final State
|
||||
|
||||
```javascript
|
||||
const state = JSON.parse(Read("<session-dir>/team-session.json"))
|
||||
```
|
||||
|
||||
### Step 5.2: Agent Cleanup
|
||||
|
||||
Close any remaining active agents (defensive -- should be none at this point).
|
||||
|
||||
```javascript
|
||||
for (const agentEntry of state.active_agents) {
|
||||
try {
|
||||
close_agent({ id: agentEntry.agent_id })
|
||||
} catch (e) {
|
||||
// Agent already closed, ignore
|
||||
}
|
||||
}
|
||||
state.active_agents = []
|
||||
```
|
||||
|
||||
### Step 5.3: Compute Summary Statistics
|
||||
|
||||
```javascript
|
||||
const totalTasks = state.pipeline.length
|
||||
const completedTasks = state.pipeline.filter(t => t.status === "completed").length
|
||||
const failedTasks = state.pipeline.filter(t => t.status === "failed").length
|
||||
const partialTasks = state.pipeline.filter(t => t.status === "partial").length
|
||||
const revisionTasks = state.pipeline.filter(t => t.revision_of !== null).length
|
||||
|
||||
const startTime = new Date(state.started_at)
|
||||
const endTime = new Date()
|
||||
const durationMs = endTime - startTime
|
||||
const durationMin = Math.round(durationMs / 60000)
|
||||
|
||||
const successRate = totalTasks > 0
|
||||
? Math.round((completedTasks / totalTasks) * 100)
|
||||
: 0
|
||||
```
|
||||
|
||||
### Step 5.4: Collect Deliverable Artifacts
|
||||
|
||||
Scan completed tasks for artifact paths. Group by pipeline phase.
|
||||
|
||||
```javascript
|
||||
const artifacts = {
|
||||
spec: [],
|
||||
plan: [],
|
||||
impl: [],
|
||||
test: [],
|
||||
review: [],
|
||||
discussions: [],
|
||||
qa: []
|
||||
}
|
||||
|
||||
for (const task of state.pipeline) {
|
||||
if (task.status !== "completed" || !task.artifact_path) continue
|
||||
|
||||
if (task.id.startsWith("RESEARCH") || task.id.startsWith("DRAFT") || task.id.startsWith("QUALITY")) {
|
||||
artifacts.spec.push({ task_id: task.id, path: task.artifact_path })
|
||||
} else if (task.id.startsWith("PLAN")) {
|
||||
artifacts.plan.push({ task_id: task.id, path: task.artifact_path })
|
||||
} else if (task.id.startsWith("IMPL") || task.id.startsWith("DEV-FE")) {
|
||||
artifacts.impl.push({ task_id: task.id, path: task.artifact_path })
|
||||
} else if (task.id.startsWith("TEST")) {
|
||||
artifacts.test.push({ task_id: task.id, path: task.artifact_path })
|
||||
} else if (task.id.startsWith("REVIEW")) {
|
||||
artifacts.review.push({ task_id: task.id, path: task.artifact_path })
|
||||
} else if (task.id.startsWith("QA-FE")) {
|
||||
artifacts.qa.push({ task_id: task.id, path: task.artifact_path })
|
||||
}
|
||||
}
|
||||
|
||||
// Also collect discussion records
|
||||
const discussionFiles = Glob("<session-dir>/discussions/*.md")
|
||||
for (const df of discussionFiles) {
|
||||
artifacts.discussions.push({ path: df })
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5.5: Collect Wisdom Summary
|
||||
|
||||
Read wisdom files to include key findings in the report.
|
||||
|
||||
```javascript
|
||||
const wisdomSummary = {
|
||||
learnings: Read("<session-dir>/wisdom/learnings.md") || "(none)",
|
||||
decisions: Read("<session-dir>/wisdom/decisions.md") || "(none)",
|
||||
conventions: Read("<session-dir>/wisdom/conventions.md") || "(none)",
|
||||
issues: Read("<session-dir>/wisdom/issues.md") || "(none)"
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5.6: Check for Consensus Warnings
|
||||
|
||||
Collect any consensus-blocked results across the pipeline.
|
||||
|
||||
```javascript
|
||||
const consensusIssues = state.pipeline
|
||||
.filter(t => t.discuss_verdict === "consensus_blocked")
|
||||
.map(t => ({
|
||||
task_id: t.id,
|
||||
severity: t.discuss_severity,
|
||||
revision: t.revision_of ? `revised as ${state.revision_chains[t.revision_of]}` : null
|
||||
}))
|
||||
```
|
||||
|
||||
### Step 5.7: Update Session Status
|
||||
|
||||
```javascript
|
||||
state.status = "completed"
|
||||
state.updated_at = new Date().toISOString()
|
||||
state.completed_at = new Date().toISOString()
|
||||
|
||||
Write("<session-dir>/team-session.json",
|
||||
JSON.stringify(state, null, 2))
|
||||
```
|
||||
|
||||
### Step 5.8: Output Completion Report
|
||||
|
||||
Format and display the final report to the user.
|
||||
|
||||
```
|
||||
==============================================================
|
||||
[orchestrator] PIPELINE COMPLETE
|
||||
==============================================================
|
||||
|
||||
Session: <session-id>
|
||||
Mode: <mode>
|
||||
Duration: <duration-min> minutes
|
||||
Progress: <completed>/<total> tasks (<success-rate>%)
|
||||
|
||||
--------------------------------------------------------------
|
||||
TASK SUMMARY
|
||||
--------------------------------------------------------------
|
||||
| Task ID | Agent | Status | Discuss | Artifact |
|
||||
|---------|-------|--------|---------|----------|
|
||||
| RESEARCH-001 | analyst | V | DISCUSS-001: reached | spec/discovery-context.json |
|
||||
| DRAFT-001 | writer | V | DISCUSS-002: reached | spec/product-brief.md |
|
||||
| ... | ... | ... | ... | ... |
|
||||
|
||||
V=completed X=failed ~=partial R=revision
|
||||
|
||||
--------------------------------------------------------------
|
||||
DELIVERABLES
|
||||
--------------------------------------------------------------
|
||||
|
||||
Specification:
|
||||
<artifact-list from artifacts.spec>
|
||||
|
||||
Plan:
|
||||
<artifact-list from artifacts.plan>
|
||||
|
||||
Implementation:
|
||||
<artifact-list from artifacts.impl>
|
||||
|
||||
Testing:
|
||||
<artifact-list from artifacts.test>
|
||||
|
||||
Review:
|
||||
<artifact-list from artifacts.review>
|
||||
|
||||
Discussions:
|
||||
<discussion-file-list>
|
||||
|
||||
QA:
|
||||
<artifact-list from artifacts.qa>
|
||||
|
||||
--------------------------------------------------------------
|
||||
CONSENSUS NOTES
|
||||
--------------------------------------------------------------
|
||||
<if consensusIssues.length > 0>
|
||||
<for each issue>
|
||||
<task-id>: consensus_blocked (<severity>) <revision-note>
|
||||
<end>
|
||||
<else>
|
||||
All discussions reached consensus.
|
||||
<end>
|
||||
|
||||
--------------------------------------------------------------
|
||||
WISDOM HIGHLIGHTS
|
||||
--------------------------------------------------------------
|
||||
Key learnings: <summary from wisdom/learnings.md>
|
||||
Key decisions: <summary from wisdom/decisions.md>
|
||||
Issues flagged: <summary from wisdom/issues.md>
|
||||
|
||||
--------------------------------------------------------------
|
||||
NEXT STEPS
|
||||
--------------------------------------------------------------
|
||||
Available actions:
|
||||
1. Exit - session complete
|
||||
2. View artifacts - read specific deliverable files
|
||||
3. Extend - add more tasks to this pipeline
|
||||
4. New session - start a fresh lifecycle
|
||||
5. Generate lite-plan - create a lightweight implementation plan from spec
|
||||
|
||||
Session directory: <session-dir>
|
||||
==============================================================
|
||||
```
|
||||
|
||||
### Step 5.9: Handle User Response
|
||||
|
||||
After presenting the report, wait for user input.
|
||||
|
||||
| User Choice | Action |
|
||||
|-------------|--------|
|
||||
| exit / done | Final cleanup, orchestrator stops |
|
||||
| view `<artifact-path>` | Read and display the specified artifact |
|
||||
| extend `<description>` | Re-enter Phase 1 with extend context, resume session |
|
||||
| new `<description>` | Start fresh Phase 1 (new session) |
|
||||
| lite-plan | Generate implementation plan from completed spec |
|
||||
|
||||
For "extend": the orchestrator reads the existing session, appends new requirements, and re-enters Phase 3 to create additional tasks appended to the existing pipeline.
|
||||
|
||||
For "view": simply read the requested file and display contents, then re-present the next steps menu.
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
| Output | Type | Destination |
|
||||
|--------|------|-------------|
|
||||
| Completion report | Text | Displayed to user |
|
||||
| Updated state | JSON | team-session.json with status="completed" |
|
||||
| User choice | String | Determines post-pipeline action |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- All agents closed (no orphaned agents)
|
||||
- State file updated to status="completed"
|
||||
- All artifact paths verified (files exist)
|
||||
- Completion report includes all task statuses
|
||||
- Consensus issues documented
|
||||
- Wisdom highlights extracted
|
||||
- Next steps presented to user
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| State file read error | Attempt to reconstruct from available artifacts |
|
||||
| Artifact file missing | Report as "(artifact missing)" in deliverables list |
|
||||
| Agent close failure | Ignore (agent already closed) |
|
||||
| Wisdom file empty | Report "(no entries)" for that category |
|
||||
| User input not recognized | Re-present available options |
|
||||
|
||||
---
|
||||
|
||||
## Post-Pipeline
|
||||
|
||||
This is the final phase. The orchestrator either stops (exit) or loops back to an earlier phase based on user choice.
|
||||
|
||||
```
|
||||
User choice routing:
|
||||
exit -> orchestrator stops
|
||||
view -> display file -> re-present Step 5.9
|
||||
extend -> Phase 1 (with resume context) -> Phase 3 -> Phase 4 -> Phase 5
|
||||
new -> Phase 1 (fresh) -> Phase 2 -> Phase 3 -> Phase 4 -> Phase 5
|
||||
lite-plan -> generate plan from spec artifacts -> present to user
|
||||
```
|
||||
Reference in New Issue
Block a user