substrate-ai 0.2.23 → 0.2.24
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/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-
|
|
2
|
+
import { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-CT8B9gG9.js";
|
|
3
3
|
import { createLogger, deepMask } from "../logger-D2fS2ccL.js";
|
|
4
4
|
import { AdapterRegistry, ConfigError, ConfigIncompatibleFormatError } from "../errors-CswS7Mzg.js";
|
|
5
5
|
import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator } from "../version-manager-impl-CZ6KF1Ds.js";
|
|
@@ -2842,7 +2842,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
2842
2842
|
const expDb = expDbWrapper.db;
|
|
2843
2843
|
const { runRunAction: runPipeline } = await import(
|
|
2844
2844
|
/* @vite-ignore */
|
|
2845
|
-
"../run-
|
|
2845
|
+
"../run-DoxsPIlD.js"
|
|
2846
2846
|
);
|
|
2847
2847
|
const runStoryFn = async (opts) => {
|
|
2848
2848
|
const exitCode = await runPipeline({
|
|
@@ -676,7 +676,8 @@ const PackManifestSchema = z.object({
|
|
|
676
676
|
phases: z.array(PhaseDefinitionSchema),
|
|
677
677
|
prompts: z.record(z.string(), z.string()),
|
|
678
678
|
constraints: z.record(z.string(), z.string()),
|
|
679
|
-
templates: z.record(z.string(), z.string())
|
|
679
|
+
templates: z.record(z.string(), z.string()),
|
|
680
|
+
conflictGroups: z.record(z.string(), z.string()).optional()
|
|
680
681
|
});
|
|
681
682
|
const ConstraintSeveritySchema = z.enum([
|
|
682
683
|
"required",
|
|
@@ -5806,33 +5807,6 @@ function makeBatch(batchIndex, tasks) {
|
|
|
5806
5807
|
//#endregion
|
|
5807
5808
|
//#region src/modules/implementation-orchestrator/conflict-detector.ts
|
|
5808
5809
|
/**
|
|
5809
|
-
* Maps story key prefix patterns to module directory names.
|
|
5810
|
-
*
|
|
5811
|
-
* The heuristic: stories whose numeric prefix belongs to the same epic
|
|
5812
|
-
* (same first digit) and whose known mapping points to the same module are
|
|
5813
|
-
* considered conflicting. Unknown prefixes default to the story key itself
|
|
5814
|
-
* (each unknown story is in its own group).
|
|
5815
|
-
*
|
|
5816
|
-
* Format: prefix (e.g. "10-") → module name
|
|
5817
|
-
*/
|
|
5818
|
-
const STORY_PREFIX_TO_MODULE = {
|
|
5819
|
-
"1-": "core",
|
|
5820
|
-
"2-": "core",
|
|
5821
|
-
"3-": "core",
|
|
5822
|
-
"4-": "core",
|
|
5823
|
-
"5-": "core",
|
|
5824
|
-
"6-": "task-graph",
|
|
5825
|
-
"7-": "worker-pool",
|
|
5826
|
-
"8-": "monitor",
|
|
5827
|
-
"9-": "bmad-context-engine",
|
|
5828
|
-
"10-1": "compiled-workflows",
|
|
5829
|
-
"10-2": "compiled-workflows",
|
|
5830
|
-
"10-3": "compiled-workflows",
|
|
5831
|
-
"10-4": "implementation-orchestrator",
|
|
5832
|
-
"10-5": "cli",
|
|
5833
|
-
"11-": "pipeline-phases"
|
|
5834
|
-
};
|
|
5835
|
-
/**
|
|
5836
5810
|
* Determine the module prefix for a story key.
|
|
5837
5811
|
*
|
|
5838
5812
|
* Checks most-specific prefix first (e.g., "10-1" before "10-"), then falls
|
|
@@ -5840,10 +5814,11 @@ const STORY_PREFIX_TO_MODULE = {
|
|
|
5840
5814
|
* itself for unknown stories so each gets its own group.
|
|
5841
5815
|
*
|
|
5842
5816
|
* @param storyKey - e.g. "10-1", "10-2-dev-story", "5-3-something"
|
|
5843
|
-
* @param effectiveMap - The resolved prefix-to-module map
|
|
5817
|
+
* @param effectiveMap - The resolved prefix-to-module map
|
|
5844
5818
|
* @returns module name string used for conflict grouping
|
|
5845
5819
|
*/
|
|
5846
5820
|
function resolveModulePrefix(storyKey, effectiveMap) {
|
|
5821
|
+
if (Object.keys(effectiveMap).length === 0) return storyKey;
|
|
5847
5822
|
const sortedKeys = Object.keys(effectiveMap).sort((a, b) => b.length - a.length);
|
|
5848
5823
|
for (const prefix of sortedKeys) if (storyKey.startsWith(prefix)) return effectiveMap[prefix];
|
|
5849
5824
|
return storyKey;
|
|
@@ -5855,26 +5830,33 @@ function resolveModulePrefix(storyKey, effectiveMap) {
|
|
|
5855
5830
|
* group and will be serialized. Stories with different prefixes can run in
|
|
5856
5831
|
* parallel.
|
|
5857
5832
|
*
|
|
5833
|
+
* When no `moduleMap` is configured, every story key is placed in its own
|
|
5834
|
+
* conflict group (maximum parallelism). This is the default for cross-project
|
|
5835
|
+
* runs where the story key prefixes are not known in advance.
|
|
5836
|
+
*
|
|
5858
5837
|
* @param storyKeys - Array of story key strings
|
|
5859
|
-
* @param config - Optional configuration; supply `moduleMap` to
|
|
5860
|
-
*
|
|
5861
|
-
*
|
|
5838
|
+
* @param config - Optional configuration; supply `moduleMap` to define
|
|
5839
|
+
* prefix-to-module mappings. Without this config, each story
|
|
5840
|
+
* gets its own group (maximum parallelism).
|
|
5862
5841
|
* @returns Array of conflict groups; each inner array is a list of story keys
|
|
5863
5842
|
* that must be processed sequentially
|
|
5864
5843
|
*
|
|
5865
5844
|
* @example
|
|
5866
|
-
*
|
|
5867
|
-
*
|
|
5845
|
+
* // Without a moduleMap, all stories run in parallel
|
|
5846
|
+
* detectConflictGroups(['4-1', '4-2', '4-3'])
|
|
5847
|
+
* // => [['4-1'], ['4-2'], ['4-3']]
|
|
5848
|
+
*
|
|
5849
|
+
* @example
|
|
5850
|
+
* // With a moduleMap, matching stories are serialized
|
|
5851
|
+
* detectConflictGroups(['10-1', '10-2', '10-4'], { moduleMap: { '10-1': 'compiled-workflows', '10-2': 'compiled-workflows', '10-4': 'implementation-orchestrator' } })
|
|
5852
|
+
* // => [['10-1', '10-2'], ['10-4']]
|
|
5868
5853
|
*
|
|
5869
5854
|
* @example
|
|
5870
5855
|
* detectConflictGroups(['12-1', '12-2'], { moduleMap: { '12-': 'my-module' } })
|
|
5871
5856
|
* // => [['12-1', '12-2']]
|
|
5872
5857
|
*/
|
|
5873
5858
|
function detectConflictGroups(storyKeys, config) {
|
|
5874
|
-
const effectiveMap = {
|
|
5875
|
-
...STORY_PREFIX_TO_MODULE,
|
|
5876
|
-
...config?.moduleMap ?? {}
|
|
5877
|
-
};
|
|
5859
|
+
const effectiveMap = { ...config?.moduleMap ?? {} };
|
|
5878
5860
|
const moduleToStories = new Map();
|
|
5879
5861
|
for (const key of storyKeys) {
|
|
5880
5862
|
const module = resolveModulePrefix(key, effectiveMap);
|
|
@@ -7148,31 +7130,61 @@ function createImplementationOrchestrator(deps) {
|
|
|
7148
7130
|
const fixModel = taskType === "major-rework" ? "claude-opus-4-6" : void 0;
|
|
7149
7131
|
try {
|
|
7150
7132
|
let fixPrompt;
|
|
7133
|
+
const isMajorRework = taskType === "major-rework";
|
|
7134
|
+
const templateName = isMajorRework ? "rework-story" : "fix-story";
|
|
7151
7135
|
try {
|
|
7152
|
-
const fixTemplate = await pack.getPrompt(
|
|
7136
|
+
const fixTemplate = await pack.getPrompt(templateName);
|
|
7153
7137
|
const storyContent = await readFile$1(storyFilePath ?? "", "utf-8");
|
|
7154
7138
|
let reviewFeedback;
|
|
7155
|
-
if (issueList.length === 0) reviewFeedback = [
|
|
7139
|
+
if (issueList.length === 0) reviewFeedback = isMajorRework ? [
|
|
7140
|
+
`Verdict: ${verdict}`,
|
|
7141
|
+
"Issues: The reviewer flagged fundamental issues but did not provide specifics.",
|
|
7142
|
+
"Instructions: Re-read the story file carefully, re-implement from scratch addressing all acceptance criteria."
|
|
7143
|
+
].join("\n") : [
|
|
7156
7144
|
`Verdict: ${verdict}`,
|
|
7157
7145
|
"Issues: The reviewer flagged this as needing work but did not provide specific issues.",
|
|
7158
7146
|
"Instructions: Re-read the story file carefully, compare each acceptance criterion against the current implementation, and fix any gaps you find.",
|
|
7159
7147
|
"Focus on: unimplemented ACs, missing tests, incorrect behavior, and incomplete task checkboxes."
|
|
7160
7148
|
].join("\n");
|
|
7161
|
-
else
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7149
|
+
else {
|
|
7150
|
+
const issueHeader = isMajorRework ? "Issues from previous review that MUST be addressed" : "Issues";
|
|
7151
|
+
reviewFeedback = [
|
|
7152
|
+
`Verdict: ${verdict}`,
|
|
7153
|
+
`${issueHeader} (${issueList.length}):`,
|
|
7154
|
+
...issueList.map((issue, i) => {
|
|
7155
|
+
const iss = issue;
|
|
7156
|
+
return ` ${i + 1}. [${iss.severity ?? "unknown"}] ${iss.description ?? "no description"}${iss.file ? ` (${iss.file}${iss.line ? `:${iss.line}` : ""})` : ""}`;
|
|
7157
|
+
})
|
|
7158
|
+
].join("\n");
|
|
7159
|
+
}
|
|
7169
7160
|
let archConstraints = "";
|
|
7170
7161
|
try {
|
|
7171
7162
|
const decisions = getDecisionsByPhase(db, "solutioning");
|
|
7172
7163
|
const constraints = decisions.filter((d) => d.category === "architecture");
|
|
7173
7164
|
archConstraints = constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
|
|
7174
7165
|
} catch {}
|
|
7175
|
-
const sections = [
|
|
7166
|
+
const sections = isMajorRework ? [
|
|
7167
|
+
{
|
|
7168
|
+
name: "story_content",
|
|
7169
|
+
content: storyContent,
|
|
7170
|
+
priority: "required"
|
|
7171
|
+
},
|
|
7172
|
+
{
|
|
7173
|
+
name: "review_findings",
|
|
7174
|
+
content: reviewFeedback,
|
|
7175
|
+
priority: "required"
|
|
7176
|
+
},
|
|
7177
|
+
{
|
|
7178
|
+
name: "arch_constraints",
|
|
7179
|
+
content: archConstraints,
|
|
7180
|
+
priority: "optional"
|
|
7181
|
+
},
|
|
7182
|
+
{
|
|
7183
|
+
name: "git_diff",
|
|
7184
|
+
content: "",
|
|
7185
|
+
priority: "optional"
|
|
7186
|
+
}
|
|
7187
|
+
] : [
|
|
7176
7188
|
{
|
|
7177
7189
|
name: "story_content",
|
|
7178
7190
|
content: storyContent,
|
|
@@ -7199,12 +7211,19 @@ function createImplementationOrchestrator(deps) {
|
|
|
7199
7211
|
});
|
|
7200
7212
|
}
|
|
7201
7213
|
incrementDispatches(storyKey);
|
|
7202
|
-
const handle = dispatcher.dispatch({
|
|
7214
|
+
const handle = isMajorRework ? dispatcher.dispatch({
|
|
7215
|
+
prompt: fixPrompt,
|
|
7216
|
+
agent: "claude-code",
|
|
7217
|
+
taskType,
|
|
7218
|
+
...fixModel !== void 0 ? { model: fixModel } : {},
|
|
7219
|
+
outputSchema: DevStoryResultSchema,
|
|
7220
|
+
...projectRoot !== void 0 ? { workingDirectory: projectRoot } : {}
|
|
7221
|
+
}) : dispatcher.dispatch({
|
|
7203
7222
|
prompt: fixPrompt,
|
|
7204
7223
|
agent: "claude-code",
|
|
7205
7224
|
taskType,
|
|
7206
7225
|
...fixModel !== void 0 ? { model: fixModel } : {},
|
|
7207
|
-
workingDirectory: projectRoot
|
|
7226
|
+
...projectRoot !== void 0 ? { workingDirectory: projectRoot } : {}
|
|
7208
7227
|
});
|
|
7209
7228
|
const fixResult = await handle.result;
|
|
7210
7229
|
eventBus.emit("orchestrator:story-phase-complete", {
|
|
@@ -7236,11 +7255,34 @@ function createImplementationOrchestrator(deps) {
|
|
|
7236
7255
|
persistState();
|
|
7237
7256
|
return;
|
|
7238
7257
|
}
|
|
7239
|
-
if (fixResult.status === "failed")
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7258
|
+
if (fixResult.status === "failed") {
|
|
7259
|
+
if (isMajorRework) {
|
|
7260
|
+
logger$20.warn("Major rework dispatch failed — escalating story", {
|
|
7261
|
+
storyKey,
|
|
7262
|
+
exitCode: fixResult.exitCode
|
|
7263
|
+
});
|
|
7264
|
+
endPhase(storyKey, "code-review");
|
|
7265
|
+
updateStory(storyKey, {
|
|
7266
|
+
phase: "ESCALATED",
|
|
7267
|
+
error: "major-rework-dispatch-failed",
|
|
7268
|
+
completedAt: new Date().toISOString()
|
|
7269
|
+
});
|
|
7270
|
+
writeStoryMetricsBestEffort(storyKey, "escalated", reviewCycles + 1);
|
|
7271
|
+
emitEscalation({
|
|
7272
|
+
storyKey,
|
|
7273
|
+
lastVerdict: verdict,
|
|
7274
|
+
reviewCycles: reviewCycles + 1,
|
|
7275
|
+
issues: issueList
|
|
7276
|
+
});
|
|
7277
|
+
persistState();
|
|
7278
|
+
return;
|
|
7279
|
+
}
|
|
7280
|
+
logger$20.warn("Fix dispatch failed", {
|
|
7281
|
+
storyKey,
|
|
7282
|
+
taskType,
|
|
7283
|
+
exitCode: fixResult.exitCode
|
|
7284
|
+
});
|
|
7285
|
+
}
|
|
7244
7286
|
} catch (err) {
|
|
7245
7287
|
logger$20.warn("Fix dispatch failed, continuing to next review", {
|
|
7246
7288
|
storyKey,
|
|
@@ -7323,7 +7365,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
7323
7365
|
skippedCategories: seedResult.skippedCategories
|
|
7324
7366
|
}, "Methodology context seeded from planning artifacts");
|
|
7325
7367
|
}
|
|
7326
|
-
const groups = detectConflictGroups(storyKeys);
|
|
7368
|
+
const groups = detectConflictGroups(storyKeys, { moduleMap: pack.manifest.conflictGroups });
|
|
7327
7369
|
logger$20.info("Orchestrator starting", {
|
|
7328
7370
|
storyCount: storyKeys.length,
|
|
7329
7371
|
groupCount: groups.length,
|
|
@@ -12525,4 +12567,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
12525
12567
|
|
|
12526
12568
|
//#endregion
|
|
12527
12569
|
export { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
|
|
12528
|
-
//# sourceMappingURL=run-
|
|
12570
|
+
//# sourceMappingURL=run-CT8B9gG9.js.map
|
package/package.json
CHANGED
package/packs/bmad/manifest.yaml
CHANGED
|
@@ -191,6 +191,7 @@ prompts:
|
|
|
191
191
|
dev-story: prompts/dev-story.md
|
|
192
192
|
code-review: prompts/code-review.md
|
|
193
193
|
fix-story: prompts/fix-story.md
|
|
194
|
+
rework-story: prompts/rework-story.md
|
|
194
195
|
# Multi-step phase decomposition prompts
|
|
195
196
|
analysis-step-1-vision: prompts/analysis-step-1-vision.md
|
|
196
197
|
analysis-step-2-scope: prompts/analysis-step-2-scope.md
|
|
@@ -228,3 +229,25 @@ constraints:
|
|
|
228
229
|
|
|
229
230
|
templates:
|
|
230
231
|
story: templates/story.md
|
|
232
|
+
|
|
233
|
+
# Conflict group mappings for the implementation orchestrator.
|
|
234
|
+
# Stories whose prefixes map to the same module name are serialized within
|
|
235
|
+
# a conflict group. This map covers substrate's own epic numbering so that
|
|
236
|
+
# self-pipeline runs preserve correct serialization (e.g., epics 1-5 share
|
|
237
|
+
# 'core', stories 10-1/10-2/10-3 share 'compiled-workflows').
|
|
238
|
+
conflictGroups:
|
|
239
|
+
'1-': core
|
|
240
|
+
'2-': core
|
|
241
|
+
'3-': core
|
|
242
|
+
'4-': core
|
|
243
|
+
'5-': core
|
|
244
|
+
'6-': task-graph
|
|
245
|
+
'7-': worker-pool
|
|
246
|
+
'8-': monitor
|
|
247
|
+
'9-': bmad-context-engine
|
|
248
|
+
'10-1': compiled-workflows
|
|
249
|
+
'10-2': compiled-workflows
|
|
250
|
+
'10-3': compiled-workflows
|
|
251
|
+
'10-4': implementation-orchestrator
|
|
252
|
+
'10-5': cli
|
|
253
|
+
'11-': pipeline-phases
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# BMAD Compiled Rework-Story Agent
|
|
2
|
+
|
|
3
|
+
## Context (pre-assembled by pipeline)
|
|
4
|
+
|
|
5
|
+
### Story File Content
|
|
6
|
+
{{story_content}}
|
|
7
|
+
|
|
8
|
+
### Issues from Previous Review that MUST be Addressed
|
|
9
|
+
{{review_findings}}
|
|
10
|
+
|
|
11
|
+
### Architecture Constraints
|
|
12
|
+
{{arch_constraints}}
|
|
13
|
+
|
|
14
|
+
### Previous Implementation Diff
|
|
15
|
+
{{git_diff}}
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Mission
|
|
20
|
+
|
|
21
|
+
This is a FULL re-implementation. The previous implementation had fundamental issues identified in a code review. You must address ALL review findings above while implementing the story from scratch.
|
|
22
|
+
|
|
23
|
+
Do NOT patch the existing implementation. Re-implement the story completely, using the review findings as guidance on what went wrong previously.
|
|
24
|
+
|
|
25
|
+
## Instructions
|
|
26
|
+
|
|
27
|
+
1. **Parse the review findings** to understand:
|
|
28
|
+
- Each issue's severity (blocker, major, minor)
|
|
29
|
+
- Each issue's description, file, and line number (if provided)
|
|
30
|
+
- The root causes that led to the previous implementation's failure
|
|
31
|
+
|
|
32
|
+
2. **Re-read the story file** to understand:
|
|
33
|
+
- Acceptance Criteria (AC1, AC2, etc.)
|
|
34
|
+
- Tasks/Subtasks (ordered list with `[ ]` checkboxes)
|
|
35
|
+
- Dev Notes (file paths, import patterns, test requirements)
|
|
36
|
+
|
|
37
|
+
3. **Re-implement each task in order** (Red-Green-Refactor):
|
|
38
|
+
- Write failing tests first
|
|
39
|
+
- Make tests pass with minimal code
|
|
40
|
+
- Refactor while keeping tests green
|
|
41
|
+
- Ensure each review finding is addressed
|
|
42
|
+
|
|
43
|
+
4. **After each task**:
|
|
44
|
+
- Verify tests pass
|
|
45
|
+
- Run the full test suite to check for regressions
|
|
46
|
+
- Mark the task `[x]` in the story file
|
|
47
|
+
- Update the story File List with all new/modified files
|
|
48
|
+
|
|
49
|
+
5. **After all tasks complete**:
|
|
50
|
+
- Run the full test suite one final time
|
|
51
|
+
- Verify ALL review findings have been addressed
|
|
52
|
+
- Update story Status to `review`
|
|
53
|
+
|
|
54
|
+
## CRITICAL: Output Contract Emission
|
|
55
|
+
|
|
56
|
+
**You MUST emit the YAML output block (see Output Contract below) as the very last thing you produce.** The downstream pipeline depends on `files_modified` to generate scoped code-review diffs. If you exhaust your turns without emitting the YAML block, the pipeline cannot review your work properly.
|
|
57
|
+
|
|
58
|
+
- If you are running low on turns, **stop implementation and emit the YAML block immediately** with whatever progress you have made. A partial `files_modified` list is far more valuable than none at all.
|
|
59
|
+
- The YAML block must be the final output — no summary text, no explanation after it.
|
|
60
|
+
|
|
61
|
+
## HALT Conditions (stop and report as failed)
|
|
62
|
+
|
|
63
|
+
- New dependency required beyond story spec
|
|
64
|
+
- 3 consecutive implementation failures with no progress
|
|
65
|
+
- Story requirements are ambiguous with no way to resolve
|
|
66
|
+
- Review findings contradict the story requirements
|
|
67
|
+
|
|
68
|
+
## Output Contract
|
|
69
|
+
|
|
70
|
+
After completing all tasks (or hitting a HALT condition), emit ONLY this YAML block — no other text:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
result: success
|
|
74
|
+
ac_met:
|
|
75
|
+
- AC1
|
|
76
|
+
- AC2
|
|
77
|
+
ac_failures: []
|
|
78
|
+
files_modified:
|
|
79
|
+
- <absolute path to modified file>
|
|
80
|
+
tests: pass
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If a HALT condition was hit:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
result: failed
|
|
87
|
+
ac_met: []
|
|
88
|
+
ac_failures:
|
|
89
|
+
- <which AC could not be met>
|
|
90
|
+
files_modified: []
|
|
91
|
+
tests: fail
|
|
92
|
+
notes: <reason for failure>
|
|
93
|
+
```
|