maestro-flow 0.3.3 → 0.3.4
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/.claude/commands/quality-business-test.md +110 -0
- package/.codex/skills/quality-business-test/SKILL.md +223 -0
- package/chains/_intent-map.json +6 -0
- package/chains/_router.json +14 -0
- package/chains/full-lifecycle.json +15 -0
- package/chains/quality-loop.json +16 -1
- package/chains/singles/business-test.json +26 -0
- package/dashboard/dist-server/dashboard/src/server/agents/codex-cli-adapter.js +16 -2
- package/dashboard/dist-server/dashboard/src/server/agents/codex-cli-adapter.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.d.ts +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.js +25 -9
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.js.map +1 -1
- package/dashboard/dist-server/src/agents/cli-agent-runner.d.ts +3 -0
- package/dashboard/dist-server/src/agents/cli-agent-runner.js +78 -61
- package/dashboard/dist-server/src/agents/cli-agent-runner.js.map +1 -1
- package/dashboard/dist-server/src/agents/cli-history-store.d.ts +14 -1
- package/dashboard/dist-server/src/agents/cli-history-store.js +24 -2
- package/dashboard/dist-server/src/agents/cli-history-store.js.map +1 -1
- package/dashboard/dist-server/src/commands/delegate.js +142 -6
- package/dashboard/dist-server/src/commands/delegate.js.map +1 -1
- package/dist/src/agents/cli-agent-runner.d.ts +3 -0
- package/dist/src/agents/cli-agent-runner.d.ts.map +1 -1
- package/dist/src/agents/cli-agent-runner.js +72 -46
- package/dist/src/agents/cli-agent-runner.js.map +1 -1
- package/dist/src/agents/cli-history-store.d.ts +14 -1
- package/dist/src/agents/cli-history-store.d.ts.map +1 -1
- package/dist/src/agents/cli-history-store.js +24 -2
- package/dist/src/agents/cli-history-store.js.map +1 -1
- package/dist/src/commands/delegate.d.ts.map +1 -1
- package/dist/src/commands/delegate.js +65 -5
- package/dist/src/commands/delegate.js.map +1 -1
- package/dist/src/mcp/delegate-channel-relay.d.ts.map +1 -1
- package/dist/src/mcp/delegate-channel-relay.js +7 -2
- package/dist/src/mcp/delegate-channel-relay.js.map +1 -1
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +11 -2
- package/dist/src/tools/index.js.map +1 -1
- package/package.json +2 -2
- package/templates/business-test-report.json +68 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quality-business-test
|
|
3
|
+
description: PRD-forward business testing with requirement traceability, fixture generation, and multi-layer execution
|
|
4
|
+
argument-hint: "<phase> [--spec SPEC-xxx] [--layer L1|L2|L3] [--gen-code] [--dry-run] [--re-run] [--auto]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Bash
|
|
10
|
+
- Glob
|
|
11
|
+
- Grep
|
|
12
|
+
- Agent
|
|
13
|
+
- AskUserQuestion
|
|
14
|
+
---
|
|
15
|
+
<purpose>
|
|
16
|
+
Validate built features against PRD acceptance criteria through automated multi-layer business testing. Unlike quality-test (interactive UAT from code gaps) and quality-test-gen (generate tests from coverage gaps), this command starts from REQ-*.md acceptance criteria and works forward to verify business rules are satisfied.
|
|
17
|
+
|
|
18
|
+
Key mechanisms:
|
|
19
|
+
- **PRD-forward extraction**: Parse REQ-*.md acceptance criteria with RFC 2119 priority mapping
|
|
20
|
+
- **Three-tier fixture generation**: Schema-derived (valid/invalid/boundary), criteria-derived (expected outcomes), scenario-derived (multi-entity packs)
|
|
21
|
+
- **Progressive L1-L3 layers**: Interface Contract -> Business Rule -> Business Scenario (fail-fast on critical)
|
|
22
|
+
- **Generator-Critic loop**: Max 3 iterations per layer to distinguish test defects from code defects
|
|
23
|
+
- **Requirement traceability**: Every failure traces back to REQ-NNN:AC-N
|
|
24
|
+
- **Degraded mode**: Falls back to success_criteria + plan.json when no spec package exists
|
|
25
|
+
</purpose>
|
|
26
|
+
|
|
27
|
+
<required_reading>
|
|
28
|
+
@~/.maestro/workflows/business-test.md
|
|
29
|
+
</required_reading>
|
|
30
|
+
|
|
31
|
+
<context>
|
|
32
|
+
Phase: $ARGUMENTS (required -- phase number)
|
|
33
|
+
|
|
34
|
+
**Flags:**
|
|
35
|
+
- `--spec SPEC-xxx` -- Explicit spec reference (default: auto-detect from index.json.spec_ref)
|
|
36
|
+
- `--layer L1|L2|L3` -- Run only specific layer (default: progressive L1->L2->L3)
|
|
37
|
+
- `--gen-code` -- Generate framework-specific test classes (JUnit/RestAssured, supertest/vitest, pytest/httpx)
|
|
38
|
+
- `--dry-run` -- Extract scenarios and fixtures only, don't execute
|
|
39
|
+
- `--re-run` -- Re-run only previously failed/blocked scenarios
|
|
40
|
+
- `--auto` -- Skip interactive confirmations
|
|
41
|
+
|
|
42
|
+
**Layer definitions:**
|
|
43
|
+
|
|
44
|
+
| Layer | Name | Tests | Source |
|
|
45
|
+
|-------|------|-------|--------|
|
|
46
|
+
| L1 | Interface Contract | Single endpoint request/response, input validation, schema compliance | Architecture API endpoints + REQ AC |
|
|
47
|
+
| L2 | Business Rule | Multi-step logic, state transitions, business constraints, edge cases | REQ acceptance criteria + NFR |
|
|
48
|
+
| L3 | Business Scenario | Full user flows, multi-service chains, error propagation | Epic user stories |
|
|
49
|
+
|
|
50
|
+
**Priority mapping (RFC 2119):**
|
|
51
|
+
|
|
52
|
+
| Keyword | Priority | Failure = |
|
|
53
|
+
|---------|----------|-----------|
|
|
54
|
+
| MUST / SHALL | critical | blocker |
|
|
55
|
+
| SHOULD / RECOMMENDED | high | major |
|
|
56
|
+
| MAY / OPTIONAL | medium | minor |
|
|
57
|
+
|
|
58
|
+
Context files:
|
|
59
|
+
- `.workflow/.spec/SPEC-xxx/requirements/REQ-*.md` -- Functional requirements + acceptance criteria
|
|
60
|
+
- `.workflow/.spec/SPEC-xxx/requirements/NFR-*.md` -- Non-functional requirements
|
|
61
|
+
- `.workflow/.spec/SPEC-xxx/architecture/_index.md` -- API endpoints, data model, state machines
|
|
62
|
+
- `.workflow/.spec/SPEC-xxx/epics/EPIC-*.md` -- User stories for E2E scenarios
|
|
63
|
+
- `.workflow/phases/{NN}-{slug}/index.json` -- Phase metadata, success_criteria
|
|
64
|
+
- `.workflow/phases/{NN}-{slug}/plan.json` -- Task overview (degraded mode)
|
|
65
|
+
- `.workflow/phases/{NN}-{slug}/verification.json` -- Cross-reference for must_haves
|
|
66
|
+
- `.workflow/phases/{NN}-{slug}/.tests/business/` -- Previous business test artifacts
|
|
67
|
+
</context>
|
|
68
|
+
|
|
69
|
+
<execution>
|
|
70
|
+
Follow '~/.maestro/workflows/business-test.md' completely.
|
|
71
|
+
|
|
72
|
+
**Next-step routing on completion:**
|
|
73
|
+
- All requirements verified → Skill({ skill: "maestro-phase-transition", args: "{phase}" })
|
|
74
|
+
- Failures found → Skill({ skill: "quality-debug", args: "--from-business-test {phase}" })
|
|
75
|
+
- Re-run all pass → Skill({ skill: "maestro-verify", args: "{phase}" })
|
|
76
|
+
- Low coverage → Skill({ skill: "quality-test-gen", args: "{phase}" })
|
|
77
|
+
- Need integration tests → Skill({ skill: "quality-integration-test", args: "{phase}" })
|
|
78
|
+
</execution>
|
|
79
|
+
|
|
80
|
+
<error_codes>
|
|
81
|
+
| Code | Severity | Condition | Recovery |
|
|
82
|
+
|------|----------|-----------|----------|
|
|
83
|
+
| E001 | error | Phase number required | Prompt user for phase number |
|
|
84
|
+
| E002 | error | Phase directory not found | Verify phase exists in .workflow/phases/ |
|
|
85
|
+
| E003 | error | No spec package AND no success_criteria (can't extract scenarios) | Run maestro-spec-generate or maestro-plan first |
|
|
86
|
+
| E004 | error | L1 critical failures block L2/L3 progression | Fix blockers first via quality-debug |
|
|
87
|
+
| W001 | warning | Degraded mode (no spec package, using success_criteria) | Consider running maestro-spec-generate for full coverage |
|
|
88
|
+
| W002 | warning | Some requirements have no testable acceptance criteria | Note in report, suggest spec refinement |
|
|
89
|
+
| W003 | warning | Generator-Critic loop exhausted (3 iterations) without full convergence | Accept current state, proceed with known defects |
|
|
90
|
+
| W004 | warning | Mock services not available for L3 scenarios | Skip L3 or run with --gen-code for TestContainers |
|
|
91
|
+
</error_codes>
|
|
92
|
+
|
|
93
|
+
<success_criteria>
|
|
94
|
+
- [ ] Phase resolved and spec package loaded (or degraded mode activated)
|
|
95
|
+
- [ ] Business test scenarios extracted from REQ acceptance criteria
|
|
96
|
+
- [ ] RFC 2119 keywords mapped to test priorities
|
|
97
|
+
- [ ] Test fixtures generated (valid/invalid/boundary per REQ data model)
|
|
98
|
+
- [ ] business-test-plan.json written with layer distribution
|
|
99
|
+
- [ ] User confirmed plan (or --auto skipped confirmation)
|
|
100
|
+
- [ ] Test code generated if --gen-code (framework-appropriate)
|
|
101
|
+
- [ ] L1 executed with Generator-Critic loop (max 3 iterations)
|
|
102
|
+
- [ ] L2 executed if no L1 critical failures
|
|
103
|
+
- [ ] L3 executed if no L2 critical failures
|
|
104
|
+
- [ ] Traceability matrix built (every result -> REQ-NNN:AC-N)
|
|
105
|
+
- [ ] business-test-report.json written with requirement_coverage
|
|
106
|
+
- [ ] business-test-summary.md written (human-readable)
|
|
107
|
+
- [ ] index.json updated with business_test section
|
|
108
|
+
- [ ] Issues auto-created for failures (ISS-* in issues.jsonl with req_ref)
|
|
109
|
+
- [ ] Next step routed based on results
|
|
110
|
+
</success_criteria>
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maestro-business-test
|
|
3
|
+
description: PRD-forward business testing with requirement traceability, multi-layer execution (L1 Interface → L2 Business Rule → L3 Scenario), fixture generation, and feedback loop.
|
|
4
|
+
argument-hint: "<phase> [--spec SPEC-xxx] [--layer L1|L2|L3] [--gen-code] [--dry-run] [--re-run] [--auto]"
|
|
5
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, AskUserQuestion
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Auto Mode
|
|
9
|
+
|
|
10
|
+
`--auto` skips interactive confirmation of test plan. `--dry-run` extracts scenarios only without execution.
|
|
11
|
+
|
|
12
|
+
# Business Test (PRD-Forward)
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
$maestro-business-test "3" # test phase 3 against PRD
|
|
18
|
+
$maestro-business-test "3 --layer L1" # L1 interface tests only
|
|
19
|
+
$maestro-business-test "3 --gen-code" # generate framework-specific test classes
|
|
20
|
+
$maestro-business-test "3 --dry-run" # extract scenarios only, don't execute
|
|
21
|
+
$maestro-business-test "3 --re-run" # re-run only previously failed scenarios
|
|
22
|
+
$maestro-business-test "3 --spec SPEC-auth-2026-04" # explicit spec reference
|
|
23
|
+
$maestro-business-test "3 --auto" # skip plan confirmation
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Flags**:
|
|
27
|
+
- `<phase>`: Phase number (required)
|
|
28
|
+
- `--spec SPEC-xxx`: Explicit spec package reference (default: auto-detect from index.json)
|
|
29
|
+
- `--layer L1|L2|L3`: Run only specific layer
|
|
30
|
+
- `--gen-code`: Generate framework-specific test classes (JUnit/RestAssured, supertest/vitest, pytest/httpx)
|
|
31
|
+
- `--dry-run`: Extract scenarios and fixtures only, don't execute
|
|
32
|
+
- `--re-run`: Re-run only previously failed/blocked scenarios
|
|
33
|
+
- `--auto`: Skip interactive confirmations
|
|
34
|
+
|
|
35
|
+
**Output**: `{phase_dir}/.tests/business/business-test-plan.json` + `business-test-report.json` + `business-test-summary.md`
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Overview
|
|
40
|
+
|
|
41
|
+
Validate built features against PRD acceptance criteria through automated multi-layer business testing. Unlike quality-test (interactive UAT from code gaps) and quality-test-gen (generate tests from coverage gaps), this starts from REQ-*.md acceptance criteria and works forward.
|
|
42
|
+
|
|
43
|
+
**Three-track testing** (complementary, not replacements):
|
|
44
|
+
|
|
45
|
+
| Command | Input Source | Verification Angle |
|
|
46
|
+
|---------|-------------|-------------------|
|
|
47
|
+
| `quality-business-test` | REQ-*.md acceptance criteria | **PRD-forward** — are business rules satisfied? |
|
|
48
|
+
| `quality-test` | verification.json must_haves | **Code-backward** — does the code work? |
|
|
49
|
+
| `quality-test-gen` | validation.json gaps | **Coverage-backward** — is coverage sufficient? |
|
|
50
|
+
|
|
51
|
+
**Layer definitions:**
|
|
52
|
+
|
|
53
|
+
| Layer | Name | Tests | Source |
|
|
54
|
+
|-------|------|-------|--------|
|
|
55
|
+
| L1 | Interface Contract | Single endpoint request/response, input validation, schema compliance | Architecture API endpoints + REQ AC |
|
|
56
|
+
| L2 | Business Rule | Multi-step logic, state transitions, business constraints, edge cases | REQ acceptance criteria + NFR |
|
|
57
|
+
| L3 | Business Scenario | Full user flows, multi-service chains, error propagation | Epic user stories |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Implementation
|
|
62
|
+
|
|
63
|
+
### Step 1: Resolve Target & Load Spec Package
|
|
64
|
+
|
|
65
|
+
1. Parse `$ARGUMENTS` for phase number and flags
|
|
66
|
+
2. Set `PHASE_DIR = .workflow/phases/{NN}-{slug}/`
|
|
67
|
+
3. Load `index.json` -> find `spec_ref` -> locate `.workflow/.spec/SPEC-xxx/`
|
|
68
|
+
4. **Full mode**: Read `requirements/_index.md` + all `REQ-*.md` + `NFR-*.md` + `architecture/_index.md` + `epics/EPIC-*.md`
|
|
69
|
+
5. **Degraded mode** (no spec package): Read `index.json.success_criteria` + `plan.json` convergence criteria + `.summaries/TASK-*.md`
|
|
70
|
+
6. If `--re-run`: load previous `business-test-report.json`, filter to failed/blocked scenarios
|
|
71
|
+
|
|
72
|
+
### Step 2: Extract Business Test Scenarios from PRD
|
|
73
|
+
|
|
74
|
+
For each `REQ-NNN-{slug}.md`:
|
|
75
|
+
|
|
76
|
+
1. Parse `## Acceptance Criteria` section
|
|
77
|
+
2. Map RFC 2119 keywords to priority:
|
|
78
|
+
|
|
79
|
+
| Keyword | Priority | Failure = |
|
|
80
|
+
|---------|----------|-----------|
|
|
81
|
+
| MUST / SHALL | critical | blocker |
|
|
82
|
+
| SHOULD / RECOMMENDED | high | major |
|
|
83
|
+
| MAY / OPTIONAL | medium | minor |
|
|
84
|
+
|
|
85
|
+
3. Classify scenario into layer:
|
|
86
|
+
|
|
87
|
+
| Source | Layer | Category |
|
|
88
|
+
|--------|-------|----------|
|
|
89
|
+
| Architecture API endpoints + REQ AC about request/response | L1 | api_contract |
|
|
90
|
+
| REQ AC about business logic, validation, state changes | L2 | business_rule |
|
|
91
|
+
| Architecture state machine transitions | L2 | state_transition |
|
|
92
|
+
| Epic user stories (multi-step flows) | L3 | user_flow |
|
|
93
|
+
| NFR performance/security constraints | L2 | non_functional |
|
|
94
|
+
|
|
95
|
+
4. Generate scenario JSON with `id`, `req_ref` (REQ-NNN:AC-N), `layer`, `priority`, `name`, `category`, `endpoint`, `input`, `expected`, `preconditions`, `postconditions`, `mock_services`
|
|
96
|
+
|
|
97
|
+
**Degraded mode**: Extract from success_criteria (each -> L2 scenario), plan.json convergence criteria (each -> L1/L2), all default priority: high. No L3 in degraded mode.
|
|
98
|
+
|
|
99
|
+
### Step 3: Generate Test Data (Fixtures)
|
|
100
|
+
|
|
101
|
+
Three tiers:
|
|
102
|
+
|
|
103
|
+
**Tier 1 — Schema-derived**: From REQ data models, generate valid/invalid/boundary variants per entity:
|
|
104
|
+
- valid: satisfies all constraints
|
|
105
|
+
- invalid: violate each constraint individually (null, empty, overflow, wrong type)
|
|
106
|
+
- boundary: edge values (min, max, min-1, max+1)
|
|
107
|
+
|
|
108
|
+
**Tier 2 — Criteria-derived**: From "MUST return X when Y" -> `{ input: Y, expected: X }`. From "MUST validate Z" -> `{ input: invalid_Z, expected: error }`.
|
|
109
|
+
|
|
110
|
+
**Tier 3 — Scenario-derived (L3 only)**: From Epic user stories -> scenario packs with coordinated entity IDs across steps.
|
|
111
|
+
|
|
112
|
+
**Microservice mocks**: From architecture API contract -> request/response pairs for WireMock stubs.
|
|
113
|
+
|
|
114
|
+
### Step 4: Write Test Plan & Confirm
|
|
115
|
+
|
|
116
|
+
1. Archive previous `business-test-plan.json` to `.history/` if exists
|
|
117
|
+
2. Write `.tests/business/business-test-plan.json` with scenarios, fixtures, mock_contracts, requirement_coverage_plan
|
|
118
|
+
3. Display plan summary (scenario counts per layer, fixture counts, requirement coverage)
|
|
119
|
+
4. If not `--auto`: wait for user confirmation (yes/edit/cancel)
|
|
120
|
+
5. If `--dry-run`: stop here, report plan
|
|
121
|
+
|
|
122
|
+
### Step 5: Generate Test Code (if --gen-code)
|
|
123
|
+
|
|
124
|
+
Detect project tech stack from `.workflow/specs/project-tech.json` or codebase scan.
|
|
125
|
+
|
|
126
|
+
| Stack | L1 | L2 | L3 |
|
|
127
|
+
|-------|----|----|-----|
|
|
128
|
+
| Java/Spring Boot | RestAssured + MockMvc | JUnit 5 Parameterized + WireMock | TestContainers |
|
|
129
|
+
| TypeScript/Node | supertest + vitest | vitest + nock | playwright/cypress |
|
|
130
|
+
| Python | httpx + pytest | pytest + responses | pytest + selenium |
|
|
131
|
+
|
|
132
|
+
Each test method includes REQ-NNN:AC-N reference in display name. Test files placed in `.tests/business/{layer}/`.
|
|
133
|
+
|
|
134
|
+
If no `--gen-code`: scenarios stay as structured JSON for AI agent execution.
|
|
135
|
+
|
|
136
|
+
### Step 6: Execute Tests (Progressive L1 → L2 → L3)
|
|
137
|
+
|
|
138
|
+
**Fail-fast**: L1 critical failures -> STOP (don't run L2). L2 critical failures -> STOP (don't run L3).
|
|
139
|
+
|
|
140
|
+
**Generator-Critic loop per layer (max 3 iterations):**
|
|
141
|
+
|
|
142
|
+
| Iteration | Action |
|
|
143
|
+
|-----------|--------|
|
|
144
|
+
| 1 | Run all scenarios. Critic: classify failures as test_defect / code_defect / env_issue |
|
|
145
|
+
| 2 | Auto-fix test_defects, re-run ALL scenarios |
|
|
146
|
+
| 3 | Final confirmation. Remaining failures = confirmed code_defects |
|
|
147
|
+
|
|
148
|
+
**Execution modes:**
|
|
149
|
+
- `--gen-code`: run via test framework (`mvn test`, `npx vitest`, etc.)
|
|
150
|
+
- default: AI agent executes scenarios against running application
|
|
151
|
+
|
|
152
|
+
Record results in `.tests/business/test-results-iter-{N}.json`.
|
|
153
|
+
|
|
154
|
+
### Step 7: Build Traceability Matrix
|
|
155
|
+
|
|
156
|
+
Map each result to `REQ-NNN:AC-N`:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
FOR each REQ:
|
|
160
|
+
FOR each AC:
|
|
161
|
+
ac_status = "passed" if ALL scenarios passed
|
|
162
|
+
"failed" if ANY failed
|
|
163
|
+
"blocked" if ANY blocked (none failed)
|
|
164
|
+
"untested" if no scenarios mapped
|
|
165
|
+
verdict = "verified" if all MUST+SHOULD passed
|
|
166
|
+
"partial" if some failed
|
|
167
|
+
"unverified" if all failed/untested
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Step 8: Generate Reports
|
|
171
|
+
|
|
172
|
+
1. Archive previous report/summary to `.history/`
|
|
173
|
+
2. Write `.tests/business/business-test-report.json` with:
|
|
174
|
+
- `layers`: per-layer stats (total, passed, failed, blocked, pass_rate)
|
|
175
|
+
- `requirement_coverage`: per-REQ criteria results with failure details
|
|
176
|
+
- `failures`: each with req_ref, severity, expected/actual, fix_suggestion
|
|
177
|
+
- `summary`: total_requirements, fully_verified, partially_verified, unverified, coverage_pct
|
|
178
|
+
3. Write `.tests/business/business-test-summary.md` (human-readable tables)
|
|
179
|
+
4. Update `index.json` with `business_test` section
|
|
180
|
+
|
|
181
|
+
### Step 9: Feedback Loop
|
|
182
|
+
|
|
183
|
+
1. Auto-create issues from failures in `.workflow/issues/issues.jsonl` (each with `req_ref`, `source: "business-test"`)
|
|
184
|
+
2. Report results
|
|
185
|
+
3. Route next step:
|
|
186
|
+
|
|
187
|
+
| Result | Suggestion |
|
|
188
|
+
|--------|------------|
|
|
189
|
+
| All requirements verified | Skill({ skill: "maestro-phase-transition", args: "{phase}" }) |
|
|
190
|
+
| Failures found | Skill({ skill: "quality-debug", args: "--from-business-test {phase}" }) |
|
|
191
|
+
| `--re-run` all pass | Skill({ skill: "maestro-verify", args: "{phase}" }) |
|
|
192
|
+
| Low coverage (< 60%) | Skill({ skill: "quality-test-gen", args: "{phase}" }) |
|
|
193
|
+
|
|
194
|
+
**Closure criteria**: Requirement marked "verified" ONLY when ALL MUST+SHOULD acceptance criteria pass.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Error Handling
|
|
199
|
+
|
|
200
|
+
| Code | Severity | Condition | Recovery |
|
|
201
|
+
|------|----------|-----------|----------|
|
|
202
|
+
| E001 | error | Phase number required | Prompt user for phase number |
|
|
203
|
+
| E002 | error | Phase directory not found | Verify phase exists in .workflow/phases/ |
|
|
204
|
+
| E003 | error | No spec package AND no success_criteria | Run maestro-spec-generate or maestro-plan first |
|
|
205
|
+
| E004 | error | L1 critical failures block L2/L3 | Fix blockers via quality-debug |
|
|
206
|
+
| W001 | warning | Degraded mode (no spec package) | Consider running maestro-spec-generate |
|
|
207
|
+
| W002 | warning | Some REQs have no testable AC | Note in report |
|
|
208
|
+
| W003 | warning | Generator-Critic loop exhausted | Accept current state |
|
|
209
|
+
| W004 | warning | Mock services unavailable for L3 | Skip L3 or use --gen-code |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Core Rules
|
|
214
|
+
|
|
215
|
+
- **PRD is source of truth** -- business rules drive test scenarios, not code structure
|
|
216
|
+
- **RFC 2119 keyword priority** -- MUST = critical, SHOULD = high, MAY = medium
|
|
217
|
+
- **Fail-fast across layers** -- critical L1 failures block L2/L3
|
|
218
|
+
- **Generator-Critic loop max 3 iterations** per layer
|
|
219
|
+
- **Traceability on every result** -- every pass/fail maps to REQ-NNN:AC-N
|
|
220
|
+
- **Agent calls use `run_in_background: false`** for synchronous execution
|
|
221
|
+
- **Auto-create issues** in `.workflow/issues/issues.jsonl` for every failure
|
|
222
|
+
- **Degraded mode** works without spec package (from success_criteria + plan.json)
|
|
223
|
+
- **Never modify source code** -- this command tests, it doesn't fix
|
package/chains/_intent-map.json
CHANGED
|
@@ -92,6 +92,12 @@
|
|
|
92
92
|
"flags": "i",
|
|
93
93
|
"route": { "graph": "singles/debug" }
|
|
94
94
|
},
|
|
95
|
+
{
|
|
96
|
+
"type": "business_test",
|
|
97
|
+
"regex": "business.*test|PRD.*test|requirement.*test|业务.*测试|需求.*验证",
|
|
98
|
+
"flags": "i",
|
|
99
|
+
"route": { "graph": "singles/business-test" }
|
|
100
|
+
},
|
|
95
101
|
{
|
|
96
102
|
"type": "integration_test",
|
|
97
103
|
"regex": "integrat.*test|e2e|集成测试",
|
package/chains/_router.json
CHANGED
|
@@ -80,6 +80,15 @@
|
|
|
80
80
|
"type": "decision",
|
|
81
81
|
"eval": "ctx.project.verification_status",
|
|
82
82
|
"edges": [
|
|
83
|
+
{ "value": "passed", "target": "check_business_test" },
|
|
84
|
+
{ "default": true, "target": "to_quality_loop_partial" }
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"check_business_test": {
|
|
88
|
+
"type": "decision",
|
|
89
|
+
"eval": "ctx.project.business_test_status",
|
|
90
|
+
"edges": [
|
|
91
|
+
{ "value": null, "target": "to_business_test" },
|
|
83
92
|
{ "value": "passed", "target": "check_review_after_verify" },
|
|
84
93
|
{ "default": true, "target": "to_quality_loop_partial" }
|
|
85
94
|
]
|
|
@@ -145,6 +154,11 @@
|
|
|
145
154
|
"status": "delegate",
|
|
146
155
|
"delegate_graph": "singles/verify"
|
|
147
156
|
},
|
|
157
|
+
"to_business_test": {
|
|
158
|
+
"type": "terminal",
|
|
159
|
+
"status": "delegate",
|
|
160
|
+
"delegate_graph": "singles/business-test"
|
|
161
|
+
},
|
|
148
162
|
"to_review": {
|
|
149
163
|
"type": "terminal",
|
|
150
164
|
"status": "delegate",
|
|
@@ -38,6 +38,21 @@
|
|
|
38
38
|
"check_verify": {
|
|
39
39
|
"type": "decision",
|
|
40
40
|
"eval": "ctx.result.verification_status",
|
|
41
|
+
"edges": [
|
|
42
|
+
{ "value": "passed", "target": "business_test" },
|
|
43
|
+
{ "default": true, "target": "fix_plan" }
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"business_test": {
|
|
47
|
+
"type": "command",
|
|
48
|
+
"cmd": "quality-business-test",
|
|
49
|
+
"description": "PRD-forward business testing with requirement traceability",
|
|
50
|
+
"args": "{phase} --auto",
|
|
51
|
+
"next": "check_business_test"
|
|
52
|
+
},
|
|
53
|
+
"check_business_test": {
|
|
54
|
+
"type": "decision",
|
|
55
|
+
"eval": "ctx.result.business_test_status",
|
|
41
56
|
"edges": [
|
|
42
57
|
{ "value": "passed", "target": "review" },
|
|
43
58
|
{ "default": true, "target": "fix_plan" }
|
package/chains/quality-loop.json
CHANGED
|
@@ -26,10 +26,25 @@
|
|
|
26
26
|
"type": "decision",
|
|
27
27
|
"eval": "ctx.result.verification_status",
|
|
28
28
|
"edges": [
|
|
29
|
-
{ "value": "passed", "target": "
|
|
29
|
+
{ "value": "passed", "target": "business_test", "description": "Verification passed, run business tests" },
|
|
30
30
|
{ "default": true, "target": "plan_gaps", "description": "Verification failed" }
|
|
31
31
|
]
|
|
32
32
|
},
|
|
33
|
+
"business_test": {
|
|
34
|
+
"type": "command",
|
|
35
|
+
"cmd": "quality-business-test",
|
|
36
|
+
"description": "PRD-forward business testing with requirement traceability",
|
|
37
|
+
"args": "{phase} --auto",
|
|
38
|
+
"next": "check_business_test"
|
|
39
|
+
},
|
|
40
|
+
"check_business_test": {
|
|
41
|
+
"type": "decision",
|
|
42
|
+
"eval": "ctx.result.business_test_status",
|
|
43
|
+
"edges": [
|
|
44
|
+
{ "value": "passed", "target": "review", "description": "Business tests passed" },
|
|
45
|
+
{ "default": true, "target": "plan_gaps", "description": "Business test failures found" }
|
|
46
|
+
]
|
|
47
|
+
},
|
|
33
48
|
"review": {
|
|
34
49
|
"type": "command",
|
|
35
50
|
"cmd": "quality-review",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../chain-graph.schema.json",
|
|
3
|
+
"id": "singles/business-test",
|
|
4
|
+
"name": "Business Test",
|
|
5
|
+
"description": "PRD-forward business scenario testing with requirement traceability",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"tags": ["quality", "testing"],
|
|
8
|
+
"entry": "business_test",
|
|
9
|
+
"inputs": {
|
|
10
|
+
"phase": { "type": "string", "required": true }
|
|
11
|
+
},
|
|
12
|
+
"nodes": {
|
|
13
|
+
"business_test": {
|
|
14
|
+
"type": "command",
|
|
15
|
+
"cmd": "quality-business-test",
|
|
16
|
+
"args": "{phase}",
|
|
17
|
+
"description": "PRD-forward business testing with multi-layer execution and requirement traceability",
|
|
18
|
+
"next": "done",
|
|
19
|
+
"analyze": false
|
|
20
|
+
},
|
|
21
|
+
"done": {
|
|
22
|
+
"type": "terminal",
|
|
23
|
+
"status": "success"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -62,7 +62,8 @@ export class CodexCliAdapter extends BaseAgentAdapter {
|
|
|
62
62
|
monitor.heartbeat();
|
|
63
63
|
this.parseCodexMessage(line, processId);
|
|
64
64
|
});
|
|
65
|
-
// Stderr handling:
|
|
65
|
+
// Stderr handling: Codex sends warnings, reasoning, and progress to stderr.
|
|
66
|
+
// Try JSON parse first to detect structured messages (warnings/errors).
|
|
66
67
|
child.stderr.on('data', (chunk) => {
|
|
67
68
|
const text = chunk.toString().trim();
|
|
68
69
|
if (text.length === 0)
|
|
@@ -71,11 +72,24 @@ export class CodexCliAdapter extends BaseAgentAdapter {
|
|
|
71
72
|
const trimmed = line.trim();
|
|
72
73
|
if (trimmed.length === 0)
|
|
73
74
|
continue;
|
|
75
|
+
// Try to parse as JSON — Codex emits structured warnings/errors to stderr
|
|
76
|
+
try {
|
|
77
|
+
const json = JSON.parse(trimmed);
|
|
78
|
+
if (json && typeof json === 'object' && json.type === 'error') {
|
|
79
|
+
// Codex structured warning/error — emit as thinking (non-fatal info)
|
|
80
|
+
this.emitEntry(processId, EntryNormalizer.thinking(processId, json.message ?? trimmed));
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Not JSON — fall through to text classification
|
|
86
|
+
}
|
|
74
87
|
if (STDERR_ERROR_RE.test(trimmed)) {
|
|
75
88
|
this.emitEntry(processId, EntryNormalizer.error(processId, trimmed, 'stderr'));
|
|
76
89
|
}
|
|
77
90
|
else {
|
|
78
|
-
|
|
91
|
+
// Codex emits reasoning/progress text to stderr; treat as thinking, not output
|
|
92
|
+
this.emitEntry(processId, EntryNormalizer.thinking(processId, trimmed));
|
|
79
93
|
}
|
|
80
94
|
}
|
|
81
95
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-cli-adapter.js","sourceRoot":"","sources":["../../../../../src/server/agents/codex-cli-adapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"codex-cli-adapter.js","sourceRoot":"","sources":["../../../../../src/server/agents/codex-cli-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ export declare class StreamJsonAdapter extends BaseAgentAdapter {
|
|
|
5
5
|
private readonly executable;
|
|
6
6
|
private readonly childProcesses;
|
|
7
7
|
private readonly readlineInterfaces;
|
|
8
|
-
private readonly
|
|
8
|
+
private readonly lastCumulativeText;
|
|
9
9
|
private readonly toolIdNames;
|
|
10
10
|
private readonly stoppedEmitted;
|
|
11
11
|
private readonly streamMonitors;
|
|
@@ -17,7 +17,7 @@ export class StreamJsonAdapter extends BaseAgentAdapter {
|
|
|
17
17
|
executable;
|
|
18
18
|
childProcesses = new Map();
|
|
19
19
|
readlineInterfaces = new Map();
|
|
20
|
-
|
|
20
|
+
lastCumulativeText = new Map();
|
|
21
21
|
toolIdNames = new Map();
|
|
22
22
|
stoppedEmitted = new Set();
|
|
23
23
|
streamMonitors = new Map();
|
|
@@ -171,6 +171,9 @@ export class StreamJsonAdapter extends BaseAgentAdapter {
|
|
|
171
171
|
const status = isError ? 'failed' : 'completed';
|
|
172
172
|
const content = msg.content ?? msg.output;
|
|
173
173
|
this.emitEntry(processId, EntryNormalizer.toolUse(processId, name, {}, status, content));
|
|
174
|
+
// Reset cumulative text tracker so the next assistant message turn
|
|
175
|
+
// starts fresh instead of continuing from the previous turn.
|
|
176
|
+
this.lastCumulativeText.delete(processId);
|
|
174
177
|
break;
|
|
175
178
|
}
|
|
176
179
|
case 'result': {
|
|
@@ -209,17 +212,30 @@ export class StreamJsonAdapter extends BaseAgentAdapter {
|
|
|
209
212
|
}
|
|
210
213
|
}
|
|
211
214
|
if (msg.delta) {
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
// Auto-detect cumulative vs incremental delta:
|
|
216
|
+
// If new content starts with the previously seen text, it's cumulative
|
|
217
|
+
// (each message contains all text so far). Otherwise it's an actual
|
|
218
|
+
// incremental delta (each message is only the new portion).
|
|
219
|
+
const lastText = this.lastCumulativeText.get(processId);
|
|
220
|
+
if (lastText !== undefined && content.startsWith(lastText)) {
|
|
221
|
+
// Cumulative: extract only the new portion
|
|
222
|
+
const delta = content.slice(lastText.length);
|
|
223
|
+
this.lastCumulativeText.set(processId, content);
|
|
224
|
+
if (delta.length > 0) {
|
|
225
|
+
this.emitEntry(processId, EntryNormalizer.assistantMessage(processId, delta, true));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// First message or actual incremental delta
|
|
230
|
+
this.lastCumulativeText.set(processId, content);
|
|
231
|
+
if (content.length > 0) {
|
|
232
|
+
this.emitEntry(processId, EntryNormalizer.assistantMessage(processId, content, true));
|
|
233
|
+
}
|
|
218
234
|
}
|
|
219
235
|
}
|
|
220
236
|
else {
|
|
221
237
|
// Complete message — reset cumulative tracker and emit full content
|
|
222
|
-
this.
|
|
238
|
+
this.lastCumulativeText.delete(processId);
|
|
223
239
|
if (content.length > 0) {
|
|
224
240
|
this.emitEntry(processId, EntryNormalizer.assistantMessage(processId, content, false));
|
|
225
241
|
}
|
|
@@ -283,7 +299,7 @@ export class StreamJsonAdapter extends BaseAgentAdapter {
|
|
|
283
299
|
this.streamMonitors.delete(processId);
|
|
284
300
|
}
|
|
285
301
|
this.childProcesses.delete(processId);
|
|
286
|
-
this.
|
|
302
|
+
this.lastCumulativeText.delete(processId);
|
|
287
303
|
this.thinkingEmitted.delete(processId);
|
|
288
304
|
this.toolIdNames.clear();
|
|
289
305
|
// Note: stoppedEmitted is intentionally NOT cleared here — it must persist
|