@agentic-coding-framework/orchestrator-core 0.1.0
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.d.ts +15 -0
- package/dist/cli.js +199 -0
- package/dist/dispatch.d.ts +192 -0
- package/dist/dispatch.js +729 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +47 -0
- package/dist/rules.d.ts +65 -0
- package/dist/rules.js +366 -0
- package/dist/state.d.ts +81 -0
- package/dist/state.js +160 -0
- package/package.json +41 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic Coding Protocol — Orchestrator Core
|
|
3
|
+
*
|
|
4
|
+
* Three modules, one pipeline:
|
|
5
|
+
* state.ts → STATE.json types + I/O
|
|
6
|
+
* rules.ts → Step transition rules table (pure data)
|
|
7
|
+
* dispatch.ts → State machine + prompt builder + handoff parser
|
|
8
|
+
*/
|
|
9
|
+
export { type State, type Step, type Status, type Reason, type TaskType, type TestResult, createInitialState, readState, writeState, initState, validate, isTimedOut, isMaxedOut, markRunning, markCompleted, } from "./state";
|
|
10
|
+
export { type StepRule, type FailRouting, type TeamRole, type TeamRoles, type DispatchMode, STEP_RULES, BOOTSTRAP_RULE, DEFAULT_TEAM_ROLES, DISPATCH_MODES, getRule, resolvePaths, getDispatchMode, getFailTarget, getStepSequence, } from "./rules";
|
|
11
|
+
export { type DispatchResult, type HandoffResult, dispatch, buildPrompt, parseHandoff, applyHandoff, runPostCheck, approveReview, rejectReview, startStory, startCustom, type ProjectStatus, type FrameworkDetection, type ProjectEntry, detectFramework, queryProjectStatus, listProjects, } from "./dispatch";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agentic Coding Protocol — Orchestrator Core
|
|
4
|
+
*
|
|
5
|
+
* Three modules, one pipeline:
|
|
6
|
+
* state.ts → STATE.json types + I/O
|
|
7
|
+
* rules.ts → Step transition rules table (pure data)
|
|
8
|
+
* dispatch.ts → State machine + prompt builder + handoff parser
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.listProjects = exports.queryProjectStatus = exports.detectFramework = exports.startCustom = exports.startStory = exports.rejectReview = exports.approveReview = exports.runPostCheck = exports.applyHandoff = exports.parseHandoff = exports.buildPrompt = exports.dispatch = exports.getStepSequence = exports.getFailTarget = exports.getDispatchMode = exports.resolvePaths = exports.getRule = exports.DISPATCH_MODES = exports.DEFAULT_TEAM_ROLES = exports.BOOTSTRAP_RULE = exports.STEP_RULES = exports.markCompleted = exports.markRunning = exports.isMaxedOut = exports.isTimedOut = exports.validate = exports.initState = exports.writeState = exports.readState = exports.createInitialState = void 0;
|
|
12
|
+
// State
|
|
13
|
+
var state_1 = require("./state");
|
|
14
|
+
Object.defineProperty(exports, "createInitialState", { enumerable: true, get: function () { return state_1.createInitialState; } });
|
|
15
|
+
Object.defineProperty(exports, "readState", { enumerable: true, get: function () { return state_1.readState; } });
|
|
16
|
+
Object.defineProperty(exports, "writeState", { enumerable: true, get: function () { return state_1.writeState; } });
|
|
17
|
+
Object.defineProperty(exports, "initState", { enumerable: true, get: function () { return state_1.initState; } });
|
|
18
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return state_1.validate; } });
|
|
19
|
+
Object.defineProperty(exports, "isTimedOut", { enumerable: true, get: function () { return state_1.isTimedOut; } });
|
|
20
|
+
Object.defineProperty(exports, "isMaxedOut", { enumerable: true, get: function () { return state_1.isMaxedOut; } });
|
|
21
|
+
Object.defineProperty(exports, "markRunning", { enumerable: true, get: function () { return state_1.markRunning; } });
|
|
22
|
+
Object.defineProperty(exports, "markCompleted", { enumerable: true, get: function () { return state_1.markCompleted; } });
|
|
23
|
+
// Rules
|
|
24
|
+
var rules_1 = require("./rules");
|
|
25
|
+
Object.defineProperty(exports, "STEP_RULES", { enumerable: true, get: function () { return rules_1.STEP_RULES; } });
|
|
26
|
+
Object.defineProperty(exports, "BOOTSTRAP_RULE", { enumerable: true, get: function () { return rules_1.BOOTSTRAP_RULE; } });
|
|
27
|
+
Object.defineProperty(exports, "DEFAULT_TEAM_ROLES", { enumerable: true, get: function () { return rules_1.DEFAULT_TEAM_ROLES; } });
|
|
28
|
+
Object.defineProperty(exports, "DISPATCH_MODES", { enumerable: true, get: function () { return rules_1.DISPATCH_MODES; } });
|
|
29
|
+
Object.defineProperty(exports, "getRule", { enumerable: true, get: function () { return rules_1.getRule; } });
|
|
30
|
+
Object.defineProperty(exports, "resolvePaths", { enumerable: true, get: function () { return rules_1.resolvePaths; } });
|
|
31
|
+
Object.defineProperty(exports, "getDispatchMode", { enumerable: true, get: function () { return rules_1.getDispatchMode; } });
|
|
32
|
+
Object.defineProperty(exports, "getFailTarget", { enumerable: true, get: function () { return rules_1.getFailTarget; } });
|
|
33
|
+
Object.defineProperty(exports, "getStepSequence", { enumerable: true, get: function () { return rules_1.getStepSequence; } });
|
|
34
|
+
// Dispatch
|
|
35
|
+
var dispatch_1 = require("./dispatch");
|
|
36
|
+
Object.defineProperty(exports, "dispatch", { enumerable: true, get: function () { return dispatch_1.dispatch; } });
|
|
37
|
+
Object.defineProperty(exports, "buildPrompt", { enumerable: true, get: function () { return dispatch_1.buildPrompt; } });
|
|
38
|
+
Object.defineProperty(exports, "parseHandoff", { enumerable: true, get: function () { return dispatch_1.parseHandoff; } });
|
|
39
|
+
Object.defineProperty(exports, "applyHandoff", { enumerable: true, get: function () { return dispatch_1.applyHandoff; } });
|
|
40
|
+
Object.defineProperty(exports, "runPostCheck", { enumerable: true, get: function () { return dispatch_1.runPostCheck; } });
|
|
41
|
+
Object.defineProperty(exports, "approveReview", { enumerable: true, get: function () { return dispatch_1.approveReview; } });
|
|
42
|
+
Object.defineProperty(exports, "rejectReview", { enumerable: true, get: function () { return dispatch_1.rejectReview; } });
|
|
43
|
+
Object.defineProperty(exports, "startStory", { enumerable: true, get: function () { return dispatch_1.startStory; } });
|
|
44
|
+
Object.defineProperty(exports, "startCustom", { enumerable: true, get: function () { return dispatch_1.startCustom; } });
|
|
45
|
+
Object.defineProperty(exports, "detectFramework", { enumerable: true, get: function () { return dispatch_1.detectFramework; } });
|
|
46
|
+
Object.defineProperty(exports, "queryProjectStatus", { enumerable: true, get: function () { return dispatch_1.queryProjectStatus; } });
|
|
47
|
+
Object.defineProperty(exports, "listProjects", { enumerable: true, get: function () { return dispatch_1.listProjects; } });
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rules.ts — Step Transition Rules Table
|
|
3
|
+
*
|
|
4
|
+
* Pure data, zero logic. Direct translation of the Protocol's Step Transition
|
|
5
|
+
* Rules YAML into TypeScript. The orchestrator looks up this table to decide:
|
|
6
|
+
* what files the executor reads, what it writes, what post-check to run,
|
|
7
|
+
* max attempts, timeout, and where to go on pass/fail.
|
|
8
|
+
*
|
|
9
|
+
* Projects can override defaults via `.ai/step-rules.yaml` (future).
|
|
10
|
+
*/
|
|
11
|
+
import type { Step, Reason } from "./state";
|
|
12
|
+
/** Reason-based routing: maps failure reason → target step */
|
|
13
|
+
export type FailRouting = {
|
|
14
|
+
/** Fallback when reason is null or unrecognized */
|
|
15
|
+
default: Step;
|
|
16
|
+
} & Partial<Record<Reason, Step>>;
|
|
17
|
+
/** Complete rule definition for a single step */
|
|
18
|
+
export interface StepRule {
|
|
19
|
+
/** Display name for dispatch prompt */
|
|
20
|
+
display_name: string;
|
|
21
|
+
/** Step to advance to on success */
|
|
22
|
+
next_on_pass: Step;
|
|
23
|
+
/** Reason-based routing on failure */
|
|
24
|
+
on_fail: FailRouting;
|
|
25
|
+
/** Maximum attempts before marking as blocked */
|
|
26
|
+
max_attempts: number;
|
|
27
|
+
/** Timeout in minutes for executor session */
|
|
28
|
+
timeout_min: number;
|
|
29
|
+
/** Whether this step requires human input (pauses pipeline) */
|
|
30
|
+
requires_human: boolean;
|
|
31
|
+
/** Files executor should read at this step.
|
|
32
|
+
* Supports {story} placeholder for current Story ID. */
|
|
33
|
+
claude_reads: string[];
|
|
34
|
+
/** Files/patterns executor may write at this step */
|
|
35
|
+
claude_writes: string[];
|
|
36
|
+
/** Shell command to run after executor exits (null = none).
|
|
37
|
+
* Deterministic check, zero LLM tokens. */
|
|
38
|
+
post_check: string | null;
|
|
39
|
+
/** Fixed instruction for the dispatch prompt */
|
|
40
|
+
step_instruction: string;
|
|
41
|
+
}
|
|
42
|
+
/** Role definition for multi-executor team dispatch */
|
|
43
|
+
export interface TeamRole {
|
|
44
|
+
claude_reads: string[];
|
|
45
|
+
claude_writes: string[];
|
|
46
|
+
}
|
|
47
|
+
/** Optional team_roles extension for multi-executor steps */
|
|
48
|
+
export type TeamRoles = Record<string, TeamRole>;
|
|
49
|
+
/** Dispatch mode based on story complexity */
|
|
50
|
+
export type DispatchMode = "single" | "auto" | "team";
|
|
51
|
+
/** Complexity-to-dispatch-mode mapping */
|
|
52
|
+
export declare const DISPATCH_MODES: Record<string, DispatchMode>;
|
|
53
|
+
export declare const STEP_RULES: Record<Exclude<Step, "bootstrap" | "done">, StepRule>;
|
|
54
|
+
export declare const BOOTSTRAP_RULE: StepRule;
|
|
55
|
+
export declare const DEFAULT_TEAM_ROLES: Record<string, TeamRoles>;
|
|
56
|
+
/** Get the rule for a given step */
|
|
57
|
+
export declare function getRule(step: Step): StepRule;
|
|
58
|
+
/** Resolve {story} placeholders in file paths */
|
|
59
|
+
export declare function resolvePaths(paths: string[], storyId: string): string[];
|
|
60
|
+
/** Determine dispatch mode from complexity marker */
|
|
61
|
+
export declare function getDispatchMode(complexity: string, parallelCount?: number): DispatchMode;
|
|
62
|
+
/** Get the next step after a failure, using reason-based routing */
|
|
63
|
+
export declare function getFailTarget(step: Step, reason: Reason | null): Step;
|
|
64
|
+
/** Get ordered step sequence for the micro-waterfall loop */
|
|
65
|
+
export declare function getStepSequence(): Step[];
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* rules.ts — Step Transition Rules Table
|
|
4
|
+
*
|
|
5
|
+
* Pure data, zero logic. Direct translation of the Protocol's Step Transition
|
|
6
|
+
* Rules YAML into TypeScript. The orchestrator looks up this table to decide:
|
|
7
|
+
* what files the executor reads, what it writes, what post-check to run,
|
|
8
|
+
* max attempts, timeout, and where to go on pass/fail.
|
|
9
|
+
*
|
|
10
|
+
* Projects can override defaults via `.ai/step-rules.yaml` (future).
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.DEFAULT_TEAM_ROLES = exports.BOOTSTRAP_RULE = exports.STEP_RULES = exports.DISPATCH_MODES = void 0;
|
|
14
|
+
exports.getRule = getRule;
|
|
15
|
+
exports.resolvePaths = resolvePaths;
|
|
16
|
+
exports.getDispatchMode = getDispatchMode;
|
|
17
|
+
exports.getFailTarget = getFailTarget;
|
|
18
|
+
exports.getStepSequence = getStepSequence;
|
|
19
|
+
/** Complexity-to-dispatch-mode mapping */
|
|
20
|
+
exports.DISPATCH_MODES = {
|
|
21
|
+
S: "single",
|
|
22
|
+
M: "auto", // check [P] count, enable team only if ≥ 2
|
|
23
|
+
L: "team",
|
|
24
|
+
};
|
|
25
|
+
// ─── Step Rules Table ────────────────────────────────────────────────────────
|
|
26
|
+
exports.STEP_RULES = {
|
|
27
|
+
bdd: {
|
|
28
|
+
display_name: "BDD Scenario Writing",
|
|
29
|
+
next_on_pass: "sdd-delta",
|
|
30
|
+
on_fail: { default: "bdd" },
|
|
31
|
+
max_attempts: 3,
|
|
32
|
+
timeout_min: 5,
|
|
33
|
+
requires_human: false,
|
|
34
|
+
claude_reads: [
|
|
35
|
+
"PROJECT_CONTEXT.md",
|
|
36
|
+
"PROJECT_MEMORY.md",
|
|
37
|
+
".ai/HANDOFF.md",
|
|
38
|
+
],
|
|
39
|
+
claude_writes: ["docs/bdd/US-{story}.md"],
|
|
40
|
+
post_check: null,
|
|
41
|
+
step_instruction: "Based on MEMORY's NOW/NEXT, write BDD scenarios for this Story. " +
|
|
42
|
+
"Use RFC 2119 language, tag test levels (@unit, @integration, @component, @e2e, @perf(ID)). " +
|
|
43
|
+
"Mark unclear items [NEEDS CLARIFICATION]. " +
|
|
44
|
+
"Include Non-Goals section.",
|
|
45
|
+
},
|
|
46
|
+
"sdd-delta": {
|
|
47
|
+
display_name: "SDD Delta Spec",
|
|
48
|
+
next_on_pass: "contract",
|
|
49
|
+
on_fail: { default: "sdd-delta" },
|
|
50
|
+
max_attempts: 3,
|
|
51
|
+
timeout_min: 5,
|
|
52
|
+
requires_human: false,
|
|
53
|
+
claude_reads: [
|
|
54
|
+
"PROJECT_CONTEXT.md",
|
|
55
|
+
"PROJECT_MEMORY.md",
|
|
56
|
+
"docs/bdd/US-{story}.md",
|
|
57
|
+
"docs/sdd.md",
|
|
58
|
+
".ai/HANDOFF.md",
|
|
59
|
+
],
|
|
60
|
+
claude_writes: ["docs/deltas/US-{story}.md"],
|
|
61
|
+
post_check: null,
|
|
62
|
+
step_instruction: "Based on BDD scenarios, analyze affected modules, produce Delta Spec " +
|
|
63
|
+
"(ADDED / MODIFIED / REMOVED). Include Non-Goals / Out of Scope section. " +
|
|
64
|
+
"Never rewrite the entire SDD.",
|
|
65
|
+
},
|
|
66
|
+
contract: {
|
|
67
|
+
display_name: "API Contract Update",
|
|
68
|
+
next_on_pass: "review",
|
|
69
|
+
on_fail: { default: "contract" },
|
|
70
|
+
max_attempts: 2,
|
|
71
|
+
timeout_min: 5,
|
|
72
|
+
requires_human: false,
|
|
73
|
+
claude_reads: [
|
|
74
|
+
"docs/sdd.md",
|
|
75
|
+
"docs/deltas/US-{story}.md",
|
|
76
|
+
"docs/api/openapi.yaml",
|
|
77
|
+
".ai/HANDOFF.md",
|
|
78
|
+
],
|
|
79
|
+
claude_writes: ["docs/api/openapi.yaml"],
|
|
80
|
+
post_check: null,
|
|
81
|
+
step_instruction: "Based on Delta Spec, update affected endpoints/events in OpenAPI/AsyncAPI contracts. " +
|
|
82
|
+
"Only add or modify affected parts; don't rewrite the entire contract.",
|
|
83
|
+
},
|
|
84
|
+
review: {
|
|
85
|
+
display_name: "Review Checkpoint",
|
|
86
|
+
next_on_pass: "scaffold",
|
|
87
|
+
on_fail: {
|
|
88
|
+
default: "bdd",
|
|
89
|
+
needs_clarification: "bdd",
|
|
90
|
+
constitution_violation: "sdd-delta",
|
|
91
|
+
scope_warning: "sdd-delta",
|
|
92
|
+
},
|
|
93
|
+
max_attempts: 1,
|
|
94
|
+
timeout_min: 0, // human-paced, no timeout
|
|
95
|
+
requires_human: true,
|
|
96
|
+
claude_reads: [],
|
|
97
|
+
claude_writes: [],
|
|
98
|
+
post_check: null,
|
|
99
|
+
step_instruction: "", // not dispatched to executor
|
|
100
|
+
},
|
|
101
|
+
scaffold: {
|
|
102
|
+
display_name: "Test Scaffolding",
|
|
103
|
+
next_on_pass: "impl",
|
|
104
|
+
on_fail: { default: "scaffold" },
|
|
105
|
+
max_attempts: 2,
|
|
106
|
+
timeout_min: 5,
|
|
107
|
+
requires_human: false,
|
|
108
|
+
claude_reads: [
|
|
109
|
+
"docs/bdd/US-{story}.md",
|
|
110
|
+
"docs/nfr.md",
|
|
111
|
+
"docs/api/openapi.yaml",
|
|
112
|
+
".ai/HANDOFF.md",
|
|
113
|
+
],
|
|
114
|
+
claude_writes: ["*_test.go", "*.spec.ts"],
|
|
115
|
+
post_check: null, // Project-specific: configure via .ai/step-rules.yaml
|
|
116
|
+
step_instruction: "Based on BDD scenario tags and NFR table, produce corresponding test " +
|
|
117
|
+
"skeleton. All tests must fail (red). Use require for Given (preconditions), " +
|
|
118
|
+
"assert for Then (verification). Use Table-Driven tests for Scenario Outlines.",
|
|
119
|
+
},
|
|
120
|
+
impl: {
|
|
121
|
+
display_name: "Implementation",
|
|
122
|
+
next_on_pass: "verify",
|
|
123
|
+
on_fail: {
|
|
124
|
+
default: "impl",
|
|
125
|
+
constitution_violation: "sdd-delta",
|
|
126
|
+
needs_clarification: "review",
|
|
127
|
+
scope_warning: "review",
|
|
128
|
+
},
|
|
129
|
+
max_attempts: 5,
|
|
130
|
+
timeout_min: 10,
|
|
131
|
+
requires_human: false,
|
|
132
|
+
claude_reads: [
|
|
133
|
+
"docs/bdd/US-{story}.md",
|
|
134
|
+
"docs/sdd.md",
|
|
135
|
+
"docs/api/openapi.yaml",
|
|
136
|
+
".ai/HANDOFF.md",
|
|
137
|
+
],
|
|
138
|
+
claude_writes: ["*.go", "*.ts", "*.tsx"],
|
|
139
|
+
post_check: null, // Project-specific: configure via .ai/step-rules.yaml
|
|
140
|
+
step_instruction: "Read failing tests, write minimal code to make tests pass, then refactor. " +
|
|
141
|
+
"Only modify affected files and functions (Diff-Only principle). " +
|
|
142
|
+
"Don't refactor unrelated code.",
|
|
143
|
+
},
|
|
144
|
+
verify: {
|
|
145
|
+
display_name: "Verify (Quality Gate)",
|
|
146
|
+
next_on_pass: "update-memory",
|
|
147
|
+
on_fail: { default: "impl" },
|
|
148
|
+
max_attempts: 2,
|
|
149
|
+
timeout_min: 5,
|
|
150
|
+
requires_human: false,
|
|
151
|
+
claude_reads: [
|
|
152
|
+
"docs/bdd/US-{story}.md",
|
|
153
|
+
"docs/deltas/US-{story}.md",
|
|
154
|
+
"docs/sdd.md",
|
|
155
|
+
"docs/api/openapi.yaml",
|
|
156
|
+
"docs/constitution.md",
|
|
157
|
+
".ai/HANDOFF.md",
|
|
158
|
+
],
|
|
159
|
+
claude_writes: [],
|
|
160
|
+
post_check: null,
|
|
161
|
+
step_instruction: "Execute triple check: " +
|
|
162
|
+
"Completeness (all BDD scenarios have tests, all Delta items implemented), " +
|
|
163
|
+
"Correctness (tests pass, NFR thresholds met), " +
|
|
164
|
+
"Coherence (SDD merged Delta, contracts consistent, Constitution not violated). " +
|
|
165
|
+
"Merge Delta Spec into main SDD after all checks pass.",
|
|
166
|
+
},
|
|
167
|
+
"update-memory": {
|
|
168
|
+
display_name: "Update Memory",
|
|
169
|
+
next_on_pass: "done",
|
|
170
|
+
on_fail: { default: "update-memory" },
|
|
171
|
+
max_attempts: 2,
|
|
172
|
+
timeout_min: 3,
|
|
173
|
+
requires_human: false,
|
|
174
|
+
claude_reads: ["PROJECT_MEMORY.md", ".ai/HANDOFF.md"],
|
|
175
|
+
claude_writes: ["PROJECT_MEMORY.md", ".ai/history.md"],
|
|
176
|
+
post_check: null,
|
|
177
|
+
step_instruction: "Update MEMORY's NOW/NEXT based on completed work. " +
|
|
178
|
+
"Append DONE + LOG entry to .ai/history.md (session archive). " +
|
|
179
|
+
"Overwrite .ai/HANDOFF.md with latest session summary. " +
|
|
180
|
+
"Record current git commit hash.",
|
|
181
|
+
},
|
|
182
|
+
custom: {
|
|
183
|
+
display_name: "Custom Task",
|
|
184
|
+
next_on_pass: "update-memory",
|
|
185
|
+
on_fail: { default: "custom" },
|
|
186
|
+
max_attempts: 3,
|
|
187
|
+
timeout_min: 15,
|
|
188
|
+
requires_human: false,
|
|
189
|
+
claude_reads: [
|
|
190
|
+
"PROJECT_CONTEXT.md",
|
|
191
|
+
"PROJECT_MEMORY.md",
|
|
192
|
+
"docs/sdd.md",
|
|
193
|
+
"docs/constitution.md",
|
|
194
|
+
".ai/HANDOFF.md",
|
|
195
|
+
],
|
|
196
|
+
claude_writes: ["*"],
|
|
197
|
+
post_check: null,
|
|
198
|
+
step_instruction: "Execute the custom task described in the Human Instruction section above. " +
|
|
199
|
+
"Follow the project's Constitution constraints. " +
|
|
200
|
+
"Only modify files relevant to the task — don't refactor unrelated code. " +
|
|
201
|
+
"If the task is unclear, fill reason with needs_clarification.",
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
// ─── Custom Task Use Cases ──────────────────────────────────────────────────
|
|
205
|
+
//
|
|
206
|
+
// The "custom" step is a generic passthrough that lets OpenClaw forward ANY
|
|
207
|
+
// instruction to Claude Code with full project context. Common use cases:
|
|
208
|
+
//
|
|
209
|
+
// ── Refactoring ──
|
|
210
|
+
// "Extract authentication logic into a separate auth module"
|
|
211
|
+
// "Rename all UserDTO references to UserResponse"
|
|
212
|
+
// "Convert class components to functional components with hooks"
|
|
213
|
+
// "Split monolithic service.ts into domain-specific modules"
|
|
214
|
+
//
|
|
215
|
+
// ── Code Review ──
|
|
216
|
+
// "Review src/api/ for security vulnerabilities"
|
|
217
|
+
// "Review PR #42 changes and list potential issues"
|
|
218
|
+
// "Check all error handling paths in the payment flow"
|
|
219
|
+
// "Audit dependencies for known CVEs"
|
|
220
|
+
//
|
|
221
|
+
// ── Bug Fix (hotfix, not full story) ──
|
|
222
|
+
// "Fix the race condition in WebSocket reconnection"
|
|
223
|
+
// "Debug why /api/users returns 500 on empty query"
|
|
224
|
+
// "Fix memory leak in event listener cleanup"
|
|
225
|
+
//
|
|
226
|
+
// ── DevOps / Infrastructure ──
|
|
227
|
+
// "Add GitHub Actions CI pipeline for lint + test + build"
|
|
228
|
+
// "Create Dockerfile and docker-compose.yml for local dev"
|
|
229
|
+
// "Set up pre-commit hooks for linting and formatting"
|
|
230
|
+
// "Configure Renovate for automated dependency updates"
|
|
231
|
+
//
|
|
232
|
+
// ── Documentation ──
|
|
233
|
+
// "Add JSDoc comments to all exported functions in src/api/"
|
|
234
|
+
// "Update README with current API endpoints and examples"
|
|
235
|
+
// "Generate OpenAPI spec from existing route handlers"
|
|
236
|
+
// "Write architecture decision record for database choice"
|
|
237
|
+
//
|
|
238
|
+
// ── Testing ──
|
|
239
|
+
// "Add unit tests for utils/validation.ts (target 90% coverage)"
|
|
240
|
+
// "Write integration tests for the checkout flow"
|
|
241
|
+
// "Add snapshot tests for all React components in src/ui/"
|
|
242
|
+
// "Set up E2E tests with Playwright for critical user paths"
|
|
243
|
+
//
|
|
244
|
+
// ── Dependency / Migration ──
|
|
245
|
+
// "Upgrade React from v17 to v18, fix breaking changes"
|
|
246
|
+
// "Migrate from Express to Fastify"
|
|
247
|
+
// "Replace moment.js with date-fns"
|
|
248
|
+
// "Migrate database schema: add soft delete to all entities"
|
|
249
|
+
//
|
|
250
|
+
// ── Performance ──
|
|
251
|
+
// "Profile and optimize the dashboard query (currently 3s)"
|
|
252
|
+
// "Add Redis caching for /api/products endpoint"
|
|
253
|
+
// "Implement virtual scrolling for the transaction list"
|
|
254
|
+
// "Lazy-load all route components with React.lazy"
|
|
255
|
+
//
|
|
256
|
+
// ── Security ──
|
|
257
|
+
// "Add rate limiting to all authentication endpoints"
|
|
258
|
+
// "Implement CSRF protection for form submissions"
|
|
259
|
+
// "Sanitize all user inputs in the search endpoint"
|
|
260
|
+
// "Add Content-Security-Policy headers"
|
|
261
|
+
//
|
|
262
|
+
// ── Cleanup ──
|
|
263
|
+
// "Remove all unused imports and dead code"
|
|
264
|
+
// "Standardize error response format across all endpoints"
|
|
265
|
+
// "Replace console.log with structured logger"
|
|
266
|
+
// "Fix all TypeScript strict mode errors"
|
|
267
|
+
//
|
|
268
|
+
// ─── Bootstrap Rule (special: one-time, not in the micro-waterfall loop) ─────
|
|
269
|
+
exports.BOOTSTRAP_RULE = {
|
|
270
|
+
display_name: "Bootstrap",
|
|
271
|
+
next_on_pass: "bdd",
|
|
272
|
+
on_fail: { default: "bootstrap" },
|
|
273
|
+
max_attempts: 1,
|
|
274
|
+
timeout_min: 10,
|
|
275
|
+
requires_human: false,
|
|
276
|
+
claude_reads: [],
|
|
277
|
+
claude_writes: [
|
|
278
|
+
"PROJECT_CONTEXT.md",
|
|
279
|
+
"docs/sdd.md",
|
|
280
|
+
"docs/constitution.md",
|
|
281
|
+
"PROJECT_MEMORY.md",
|
|
282
|
+
],
|
|
283
|
+
post_check: null,
|
|
284
|
+
step_instruction: "Set up the project using the Agentic Coding Framework. Produce: " +
|
|
285
|
+
"PROJECT_CONTEXT.md (Why/Who/What + tech stack + project structure), " +
|
|
286
|
+
"docs/sdd.md (module division + data model skeleton + inter-module interfaces), " +
|
|
287
|
+
"docs/constitution.md (3-5 inviolable architectural principles), " +
|
|
288
|
+
"PROJECT_MEMORY.md (initial state). " +
|
|
289
|
+
"Create directory structure: docs/bdd/, docs/deltas/, docs/api/, docs/ddd/ (if multi-domain).",
|
|
290
|
+
};
|
|
291
|
+
// ─── Team Roles (Multi-Executor, optional) ───────────────────────────────────
|
|
292
|
+
exports.DEFAULT_TEAM_ROLES = {
|
|
293
|
+
impl: {
|
|
294
|
+
backend: {
|
|
295
|
+
claude_reads: [
|
|
296
|
+
"docs/sdd.md",
|
|
297
|
+
"docs/api/openapi.yaml",
|
|
298
|
+
"internal/**/*.go",
|
|
299
|
+
],
|
|
300
|
+
claude_writes: ["*.go"],
|
|
301
|
+
},
|
|
302
|
+
frontend: {
|
|
303
|
+
claude_reads: ["docs/api/openapi.yaml", "src/components/**"],
|
|
304
|
+
claude_writes: ["*.ts", "*.tsx"],
|
|
305
|
+
},
|
|
306
|
+
test: {
|
|
307
|
+
claude_reads: [
|
|
308
|
+
"docs/bdd/US-{story}.md",
|
|
309
|
+
"docs/api/openapi.yaml",
|
|
310
|
+
"docs/nfr.md",
|
|
311
|
+
],
|
|
312
|
+
claude_writes: ["*_test.go", "*.spec.ts"],
|
|
313
|
+
},
|
|
314
|
+
verify: {
|
|
315
|
+
claude_reads: [
|
|
316
|
+
"docs/bdd/US-{story}.md",
|
|
317
|
+
"docs/deltas/US-{story}.md",
|
|
318
|
+
"docs/api/openapi.yaml",
|
|
319
|
+
"docs/constitution.md",
|
|
320
|
+
],
|
|
321
|
+
claude_writes: [],
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
// ─── Lookup Helpers ──────────────────────────────────────────────────────────
|
|
326
|
+
/** Get the rule for a given step */
|
|
327
|
+
function getRule(step) {
|
|
328
|
+
if (step === "bootstrap")
|
|
329
|
+
return exports.BOOTSTRAP_RULE;
|
|
330
|
+
if (step === "done")
|
|
331
|
+
throw new Error('No rule for "done" — story is complete');
|
|
332
|
+
return exports.STEP_RULES[step];
|
|
333
|
+
}
|
|
334
|
+
/** Resolve {story} placeholders in file paths */
|
|
335
|
+
function resolvePaths(paths, storyId) {
|
|
336
|
+
return paths.map((p) => p.replace(/\{story\}/g, storyId));
|
|
337
|
+
}
|
|
338
|
+
/** Determine dispatch mode from complexity marker */
|
|
339
|
+
function getDispatchMode(complexity, parallelCount = 0) {
|
|
340
|
+
const mode = exports.DISPATCH_MODES[complexity] ?? "single";
|
|
341
|
+
if (mode === "auto") {
|
|
342
|
+
return parallelCount >= 2 ? "team" : "single";
|
|
343
|
+
}
|
|
344
|
+
return mode;
|
|
345
|
+
}
|
|
346
|
+
/** Get the next step after a failure, using reason-based routing */
|
|
347
|
+
function getFailTarget(step, reason) {
|
|
348
|
+
const rule = getRule(step);
|
|
349
|
+
if (reason && rule.on_fail[reason]) {
|
|
350
|
+
return rule.on_fail[reason];
|
|
351
|
+
}
|
|
352
|
+
return rule.on_fail.default;
|
|
353
|
+
}
|
|
354
|
+
/** Get ordered step sequence for the micro-waterfall loop */
|
|
355
|
+
function getStepSequence() {
|
|
356
|
+
return [
|
|
357
|
+
"bdd",
|
|
358
|
+
"sdd-delta",
|
|
359
|
+
"contract",
|
|
360
|
+
"review",
|
|
361
|
+
"scaffold",
|
|
362
|
+
"impl",
|
|
363
|
+
"verify",
|
|
364
|
+
"update-memory",
|
|
365
|
+
];
|
|
366
|
+
}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* state.ts — STATE.json Type Definitions + Read / Write / Validate
|
|
3
|
+
*
|
|
4
|
+
* Maps directly to the Agentic Coding Protocol's STATE.json field specifications.
|
|
5
|
+
* All operations are synchronous file I/O — zero LLM tokens.
|
|
6
|
+
*/
|
|
7
|
+
/** Micro-waterfall steps, matching Protocol's valid step values */
|
|
8
|
+
export type Step = "bootstrap" | "bdd" | "sdd-delta" | "contract" | "review" | "scaffold" | "impl" | "verify" | "update-memory" | "custom" | "done";
|
|
9
|
+
/** Task type determines which pipeline to follow */
|
|
10
|
+
export type TaskType = "story" | "custom";
|
|
11
|
+
/** STATE.json status state machine:
|
|
12
|
+
* pending → running → pass | failing | timeout | needs_human */
|
|
13
|
+
export type Status = "pending" | "running" | "pass" | "failing" | "needs_human" | "timeout";
|
|
14
|
+
/** Reason codes extracted from HANDOFF.md, driving reason-based routing */
|
|
15
|
+
export type Reason = "constitution_violation" | "needs_clarification" | "nfr_missing" | "scope_warning" | "test_timeout";
|
|
16
|
+
/** Test result summary */
|
|
17
|
+
export interface TestResult {
|
|
18
|
+
pass: number;
|
|
19
|
+
fail: number;
|
|
20
|
+
skip: number;
|
|
21
|
+
}
|
|
22
|
+
/** Complete STATE.json schema — every field from the Protocol spec */
|
|
23
|
+
export interface State {
|
|
24
|
+
/** Project identifier */
|
|
25
|
+
project: string;
|
|
26
|
+
/** Current User Story ID (e.g., "US-005") */
|
|
27
|
+
story: string | null;
|
|
28
|
+
/** Current micro-waterfall step */
|
|
29
|
+
step: Step;
|
|
30
|
+
/** Attempt count for current step (1-indexed) */
|
|
31
|
+
attempt: number;
|
|
32
|
+
/** Maximum attempts allowed (from rules table) */
|
|
33
|
+
max_attempts: number;
|
|
34
|
+
/** Current status */
|
|
35
|
+
status: Status;
|
|
36
|
+
/** Failure reason code (null = general failure/success) */
|
|
37
|
+
reason: Reason | null;
|
|
38
|
+
/** ISO 8601 timestamp when executor was dispatched */
|
|
39
|
+
dispatched_at: string | null;
|
|
40
|
+
/** ISO 8601 timestamp when executor completed */
|
|
41
|
+
completed_at: string | null;
|
|
42
|
+
/** Timeout in minutes (from rules table) */
|
|
43
|
+
timeout_min: number;
|
|
44
|
+
/** Test result summary */
|
|
45
|
+
tests: TestResult | null;
|
|
46
|
+
/** Names of failing tests */
|
|
47
|
+
failing_tests: string[];
|
|
48
|
+
/** Whether linting passed */
|
|
49
|
+
lint_pass: boolean | null;
|
|
50
|
+
/** Files modified in this run */
|
|
51
|
+
files_changed: string[];
|
|
52
|
+
/** Story IDs that block this story */
|
|
53
|
+
blocked_by: string[];
|
|
54
|
+
/** Human instruction transcribed from communication channel */
|
|
55
|
+
human_note: string | null;
|
|
56
|
+
/** Task type: "story" for micro-waterfall, "custom" for ad-hoc tasks */
|
|
57
|
+
task_type: TaskType;
|
|
58
|
+
}
|
|
59
|
+
/** Create a blank STATE.json for a new project */
|
|
60
|
+
export declare function createInitialState(project: string): State;
|
|
61
|
+
/** Resolve the STATE.json path for a project root */
|
|
62
|
+
export declare function statePath(projectRoot: string): string;
|
|
63
|
+
/** Read STATE.json from disk. Throws if file doesn't exist. */
|
|
64
|
+
export declare function readState(projectRoot: string): State;
|
|
65
|
+
/** Write STATE.json to disk. Creates .ai/ directory if needed. */
|
|
66
|
+
export declare function writeState(projectRoot: string, state: State): void;
|
|
67
|
+
/** Initialize .ai/STATE.json for a new project. No-op if already exists. */
|
|
68
|
+
export declare function initState(projectRoot: string, project: string): {
|
|
69
|
+
created: boolean;
|
|
70
|
+
state: State;
|
|
71
|
+
};
|
|
72
|
+
/** Validate a State object. Throws on invalid fields. */
|
|
73
|
+
export declare function validate(state: State): void;
|
|
74
|
+
/** Check if a step has exceeded its timeout */
|
|
75
|
+
export declare function isTimedOut(state: State): boolean;
|
|
76
|
+
/** Check if current step has exhausted all attempts */
|
|
77
|
+
export declare function isMaxedOut(state: State): boolean;
|
|
78
|
+
/** Mark state as running with dispatch timestamp */
|
|
79
|
+
export declare function markRunning(state: State): State;
|
|
80
|
+
/** Mark state as completed (pass or failing) with timestamp */
|
|
81
|
+
export declare function markCompleted(state: State, status: "pass" | "failing" | "needs_human", reason?: Reason | null): State;
|