sequant 2.3.0 → 2.4.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +8 -5
- package/dist/bin/cli.js +46 -4
- package/dist/src/commands/abort.d.ts +36 -0
- package/dist/src/commands/abort.js +138 -0
- package/dist/src/commands/prompt.d.ts +7 -0
- package/dist/src/commands/prompt.js +101 -7
- package/dist/src/commands/run-progress.d.ts +11 -1
- package/dist/src/commands/run-progress.js +20 -3
- package/dist/src/commands/run.js +12 -2
- package/dist/src/commands/watch.d.ts +2 -0
- package/dist/src/commands/watch.js +67 -3
- package/dist/src/lib/assess-collision-detect.js +1 -1
- package/dist/src/lib/cli-ui/run-renderer-types.d.ts +39 -0
- package/dist/src/lib/cli-ui/run-renderer.d.ts +27 -1
- package/dist/src/lib/cli-ui/run-renderer.js +231 -14
- package/dist/src/lib/cli-ui/scrollback-harness.d.ts +112 -0
- package/dist/src/lib/cli-ui/scrollback-harness.js +294 -0
- package/dist/src/lib/merge-check/types.js +1 -1
- package/dist/src/lib/relay/archive.js +6 -0
- package/dist/src/lib/relay/types.d.ts +2 -0
- package/dist/src/lib/relay/types.js +9 -0
- package/dist/src/lib/workflow/batch-executor.js +34 -18
- package/dist/src/lib/workflow/drivers/agent-driver.d.ts +48 -1
- package/dist/src/lib/workflow/drivers/aider.d.ts +7 -1
- package/dist/src/lib/workflow/drivers/aider.js +9 -0
- package/dist/src/lib/workflow/drivers/claude-code.d.ts +17 -1
- package/dist/src/lib/workflow/drivers/claude-code.js +51 -2
- package/dist/src/lib/workflow/drivers/index.d.ts +1 -1
- package/dist/src/lib/workflow/event-emitter.d.ts +157 -0
- package/dist/src/lib/workflow/event-emitter.js +102 -0
- package/dist/src/lib/workflow/notice.d.ts +32 -0
- package/dist/src/lib/workflow/notice.js +38 -0
- package/dist/src/lib/workflow/phase-executor.d.ts +9 -21
- package/dist/src/lib/workflow/phase-executor.js +88 -115
- package/dist/src/lib/workflow/phase-mapper.d.ts +26 -13
- package/dist/src/lib/workflow/phase-mapper.js +55 -33
- package/dist/src/lib/workflow/phase-registry.d.ts +127 -0
- package/dist/src/lib/workflow/phase-registry.js +233 -0
- package/dist/src/lib/workflow/run-log-schema.d.ts +5 -55
- package/dist/src/lib/workflow/run-orchestrator.d.ts +32 -2
- package/dist/src/lib/workflow/run-orchestrator.js +125 -11
- package/dist/src/lib/workflow/state-manager.d.ts +19 -1
- package/dist/src/lib/workflow/state-manager.js +27 -1
- package/dist/src/lib/workflow/state-schema.d.ts +20 -35
- package/dist/src/lib/workflow/state-schema.js +28 -3
- package/dist/src/lib/workflow/types.d.ts +65 -15
- package/dist/src/lib/workflow/types.js +18 -13
- package/package.json +5 -4
- package/templates/hooks/post-tool.sh +81 -0
- package/templates/skills/assess/SKILL.md +28 -28
- package/templates/skills/assess/references/predicted-collision-detection.md +1 -1
- package/templates/skills/setup/SKILL.md +6 -6
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase registry — single source of truth for workflow phase definitions.
|
|
3
|
+
*
|
|
4
|
+
* Replaces scattered constants (`PHASE_PROMPTS`, `AIDER_PHASE_PROMPTS`,
|
|
5
|
+
* `ISOLATED_PHASES`, `UI_LABELS`, `SECURITY_LABELS`) with a uniform record
|
|
6
|
+
* per phase. All 9 built-in phases register here at module load — no
|
|
7
|
+
* special-casing inside consumer code.
|
|
8
|
+
*
|
|
9
|
+
* Built-in registrations live at the bottom of this file rather than in a
|
|
10
|
+
* separate `built-in-phases.ts` module. The colocated layout follows the
|
|
11
|
+
* existing `drivers/index.ts` pattern and avoids the ESM-cycle pitfall of
|
|
12
|
+
* a separate bootstrap module that re-imports the registry singleton
|
|
13
|
+
* before the singleton is fully initialized.
|
|
14
|
+
*
|
|
15
|
+
* User-extensibility (filesystem discovery of `.sequant/phases/`) is
|
|
16
|
+
* deliberately deferred — see issue #505 descoping comment.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Per-driver overrides for a phase. Today only `promptTemplate` is supported;
|
|
20
|
+
* extend the inner record when additional fields need per-driver values.
|
|
21
|
+
*/
|
|
22
|
+
export interface DriverOverride {
|
|
23
|
+
promptTemplate?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Retry policy for a single phase. Phases without this field fall back to
|
|
27
|
+
* the global cold-start retry defaults in `phase-executor.ts`. The fields
|
|
28
|
+
* are deliberately optional — a phase only needs to specify what differs.
|
|
29
|
+
*/
|
|
30
|
+
export interface RetryStrategy {
|
|
31
|
+
/** Override the cold-start retry attempt count for this phase. */
|
|
32
|
+
maxRetries?: number;
|
|
33
|
+
/** Initial backoff in ms before the first retry. */
|
|
34
|
+
backoffMs?: number;
|
|
35
|
+
/** Override the cold-start threshold (seconds). */
|
|
36
|
+
coldStartThreshold?: number;
|
|
37
|
+
/** Extra retries beyond cold-start (e.g. for transient API errors). */
|
|
38
|
+
extraRetries?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Auto-detection rules consumed by phase-mapper.ts.
|
|
42
|
+
* `labels` is an exact-match list (case-insensitive at the call site).
|
|
43
|
+
*/
|
|
44
|
+
export interface DetectRules {
|
|
45
|
+
labels?: string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Definition of a workflow phase. Registered at startup via
|
|
49
|
+
* `phaseRegistry.register(...)` and consumed by phase-executor, phase-mapper,
|
|
50
|
+
* and the CLI validator.
|
|
51
|
+
*/
|
|
52
|
+
export interface PhaseDefinition {
|
|
53
|
+
/** Phase name (matches the skill template directory + CLI `--phases` token). */
|
|
54
|
+
name: string;
|
|
55
|
+
/** Skill template directory under `templates/skills/<skill>/SKILL.md`. */
|
|
56
|
+
skill: string;
|
|
57
|
+
/**
|
|
58
|
+
* Natural-language prompt for the default (Claude Code) driver. The token
|
|
59
|
+
* `{issue}` is substituted with the GitHub issue number at execution time.
|
|
60
|
+
*/
|
|
61
|
+
promptTemplate: string;
|
|
62
|
+
/**
|
|
63
|
+
* When true, phase-executor runs this phase inside the issue worktree.
|
|
64
|
+
* `spec`, `verify`, and `merger` run in the main repo (no worktree).
|
|
65
|
+
*/
|
|
66
|
+
requiresWorktree: boolean;
|
|
67
|
+
/** Optional per-phase retry overrides. */
|
|
68
|
+
retryStrategy?: RetryStrategy;
|
|
69
|
+
/** Optional auto-detection rules. */
|
|
70
|
+
detect?: DetectRules;
|
|
71
|
+
/**
|
|
72
|
+
* Per-driver overrides. Keyed by agent name (e.g. `"aider"`). When the
|
|
73
|
+
* orchestrator runs a non-Claude driver, the corresponding override's
|
|
74
|
+
* `promptTemplate` (if present) replaces the default.
|
|
75
|
+
*/
|
|
76
|
+
driverOverrides?: Record<string, DriverOverride>;
|
|
77
|
+
/**
|
|
78
|
+
* Insertion order hint. Used by phase-mapper to sort label-detected phases
|
|
79
|
+
* into a deterministic pipeline position. Defaults to 0.
|
|
80
|
+
*/
|
|
81
|
+
order?: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* In-memory registry of phase definitions. Single mutable instance lives
|
|
85
|
+
* in this module — see the exported `phaseRegistry` constant.
|
|
86
|
+
*
|
|
87
|
+
* The class is intentionally minimal (no lifecycle hooks, no async). All
|
|
88
|
+
* mutations happen synchronously at module load by the built-in registrations
|
|
89
|
+
* at the bottom of this file.
|
|
90
|
+
*/
|
|
91
|
+
export declare class PhaseRegistry {
|
|
92
|
+
private readonly definitions;
|
|
93
|
+
/**
|
|
94
|
+
* Register a phase definition. Throws on duplicate names so misconfigured
|
|
95
|
+
* bootstrap modules surface immediately instead of silently overwriting.
|
|
96
|
+
*/
|
|
97
|
+
register(definition: PhaseDefinition): void;
|
|
98
|
+
/**
|
|
99
|
+
* Retrieve a phase by name. Throws with a "did you mean" list when the
|
|
100
|
+
* lookup fails — clearer than a downstream "undefined.promptTemplate".
|
|
101
|
+
*/
|
|
102
|
+
get(name: string): PhaseDefinition;
|
|
103
|
+
/** True when a phase with this name is registered. */
|
|
104
|
+
has(name: string): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* All registered phase definitions in insertion order. Insertion order
|
|
107
|
+
* is also the canonical pipeline order (see registrations below).
|
|
108
|
+
*/
|
|
109
|
+
list(): PhaseDefinition[];
|
|
110
|
+
/**
|
|
111
|
+
* All registered phase names in insertion order. Replaces the
|
|
112
|
+
* `PhaseSchema.options` array literal exposed by the previous typed-enum
|
|
113
|
+
* `PhaseSchema`.
|
|
114
|
+
*/
|
|
115
|
+
names(): string[];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Singleton registry instance. All consumer modules (phase-executor,
|
|
119
|
+
* phase-mapper, types.ts, CLI) read from this same instance — there is
|
|
120
|
+
* no second registry.
|
|
121
|
+
*/
|
|
122
|
+
export declare const phaseRegistry: PhaseRegistry;
|
|
123
|
+
/**
|
|
124
|
+
* Convenience accessor for the registered phase names. Used by Zod refines,
|
|
125
|
+
* tests, and CLI validation in place of the removed `PhaseSchema.options`.
|
|
126
|
+
*/
|
|
127
|
+
export declare function getPhaseNames(): string[];
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase registry — single source of truth for workflow phase definitions.
|
|
3
|
+
*
|
|
4
|
+
* Replaces scattered constants (`PHASE_PROMPTS`, `AIDER_PHASE_PROMPTS`,
|
|
5
|
+
* `ISOLATED_PHASES`, `UI_LABELS`, `SECURITY_LABELS`) with a uniform record
|
|
6
|
+
* per phase. All 9 built-in phases register here at module load — no
|
|
7
|
+
* special-casing inside consumer code.
|
|
8
|
+
*
|
|
9
|
+
* Built-in registrations live at the bottom of this file rather than in a
|
|
10
|
+
* separate `built-in-phases.ts` module. The colocated layout follows the
|
|
11
|
+
* existing `drivers/index.ts` pattern and avoids the ESM-cycle pitfall of
|
|
12
|
+
* a separate bootstrap module that re-imports the registry singleton
|
|
13
|
+
* before the singleton is fully initialized.
|
|
14
|
+
*
|
|
15
|
+
* User-extensibility (filesystem discovery of `.sequant/phases/`) is
|
|
16
|
+
* deliberately deferred — see issue #505 descoping comment.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* In-memory registry of phase definitions. Single mutable instance lives
|
|
20
|
+
* in this module — see the exported `phaseRegistry` constant.
|
|
21
|
+
*
|
|
22
|
+
* The class is intentionally minimal (no lifecycle hooks, no async). All
|
|
23
|
+
* mutations happen synchronously at module load by the built-in registrations
|
|
24
|
+
* at the bottom of this file.
|
|
25
|
+
*/
|
|
26
|
+
export class PhaseRegistry {
|
|
27
|
+
definitions = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Register a phase definition. Throws on duplicate names so misconfigured
|
|
30
|
+
* bootstrap modules surface immediately instead of silently overwriting.
|
|
31
|
+
*/
|
|
32
|
+
register(definition) {
|
|
33
|
+
if (this.definitions.has(definition.name)) {
|
|
34
|
+
throw new Error(`PhaseRegistry: phase "${definition.name}" is already registered`);
|
|
35
|
+
}
|
|
36
|
+
this.definitions.set(definition.name, definition);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Retrieve a phase by name. Throws with a "did you mean" list when the
|
|
40
|
+
* lookup fails — clearer than a downstream "undefined.promptTemplate".
|
|
41
|
+
*/
|
|
42
|
+
get(name) {
|
|
43
|
+
const def = this.definitions.get(name);
|
|
44
|
+
if (!def) {
|
|
45
|
+
const available = this.names().join(", ");
|
|
46
|
+
throw new Error(`PhaseRegistry: unknown phase "${name}". Available: ${available}`);
|
|
47
|
+
}
|
|
48
|
+
return def;
|
|
49
|
+
}
|
|
50
|
+
/** True when a phase with this name is registered. */
|
|
51
|
+
has(name) {
|
|
52
|
+
return this.definitions.has(name);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* All registered phase definitions in insertion order. Insertion order
|
|
56
|
+
* is also the canonical pipeline order (see registrations below).
|
|
57
|
+
*/
|
|
58
|
+
list() {
|
|
59
|
+
return [...this.definitions.values()];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* All registered phase names in insertion order. Replaces the
|
|
63
|
+
* `PhaseSchema.options` array literal exposed by the previous typed-enum
|
|
64
|
+
* `PhaseSchema`.
|
|
65
|
+
*/
|
|
66
|
+
names() {
|
|
67
|
+
return [...this.definitions.keys()];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Singleton registry instance. All consumer modules (phase-executor,
|
|
72
|
+
* phase-mapper, types.ts, CLI) read from this same instance — there is
|
|
73
|
+
* no second registry.
|
|
74
|
+
*/
|
|
75
|
+
export const phaseRegistry = new PhaseRegistry();
|
|
76
|
+
/**
|
|
77
|
+
* Convenience accessor for the registered phase names. Used by Zod refines,
|
|
78
|
+
* tests, and CLI validation in place of the removed `PhaseSchema.options`.
|
|
79
|
+
*/
|
|
80
|
+
export function getPhaseNames() {
|
|
81
|
+
return phaseRegistry.names();
|
|
82
|
+
}
|
|
83
|
+
// ─── Built-in phase registrations ────────────────────────────────────────
|
|
84
|
+
//
|
|
85
|
+
// Insertion order below IS the canonical pipeline order — preserved from the
|
|
86
|
+
// pre-registry `PhaseSchema` literal (`spec, security-review, exec, testgen,
|
|
87
|
+
// test, verify, qa, loop, merger`). Reordering these entries changes the
|
|
88
|
+
// order returned by `phaseRegistry.list()` / `getPhaseNames()` and the
|
|
89
|
+
// downstream `WORKFLOW_PHASES` constant in `state-schema.ts`.
|
|
90
|
+
// Spec — runs in the main repo (planning only, no worktree mutation)
|
|
91
|
+
phaseRegistry.register({
|
|
92
|
+
name: "spec",
|
|
93
|
+
skill: "spec",
|
|
94
|
+
promptTemplate: "Review GitHub issue #{issue} and create an implementation plan with verification criteria. Run the /spec {issue} workflow.",
|
|
95
|
+
requiresWorktree: false,
|
|
96
|
+
// Spec has a higher transient failure rate (~8.6%) than other phases due
|
|
97
|
+
// to GitHub API issues and rate limits. phase-executor.ts reads these
|
|
98
|
+
// values directly from the registry at module load (see
|
|
99
|
+
// SPEC_RETRY_BACKOFF_MS / SPEC_EXTRA_RETRIES).
|
|
100
|
+
retryStrategy: { extraRetries: 1, backoffMs: 5000 },
|
|
101
|
+
driverOverrides: {
|
|
102
|
+
aider: {
|
|
103
|
+
promptTemplate: `Read GitHub issue #{issue} using 'gh issue view #{issue}'.
|
|
104
|
+
Create a spec comment on the issue with:
|
|
105
|
+
1. Implementation plan
|
|
106
|
+
2. Acceptance criteria as a checklist
|
|
107
|
+
3. Risk assessment
|
|
108
|
+
Post the comment using 'gh issue comment #{issue} --body "<comment>"'.`,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
// Security review — worktree-isolated, label-triggered
|
|
113
|
+
phaseRegistry.register({
|
|
114
|
+
name: "security-review",
|
|
115
|
+
skill: "security-review",
|
|
116
|
+
promptTemplate: "Perform a deep security analysis for GitHub issue #{issue} focusing on auth, permissions, and sensitive operations. Run the /security-review {issue} workflow.",
|
|
117
|
+
requiresWorktree: true,
|
|
118
|
+
detect: {
|
|
119
|
+
labels: ["security", "auth", "authentication", "permissions", "admin"],
|
|
120
|
+
},
|
|
121
|
+
driverOverrides: {
|
|
122
|
+
aider: {
|
|
123
|
+
promptTemplate: `Perform a security review for GitHub issue #{issue}.
|
|
124
|
+
Read the issue with 'gh issue view #{issue}'.
|
|
125
|
+
Check for auth, permissions, injection, and sensitive data issues.
|
|
126
|
+
Post findings as a comment on the issue.`,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
// Exec — worktree-isolated
|
|
131
|
+
phaseRegistry.register({
|
|
132
|
+
name: "exec",
|
|
133
|
+
skill: "exec",
|
|
134
|
+
promptTemplate: "Implement the feature for GitHub issue #{issue} following the spec. Run the /exec {issue} workflow.",
|
|
135
|
+
requiresWorktree: true,
|
|
136
|
+
driverOverrides: {
|
|
137
|
+
aider: {
|
|
138
|
+
promptTemplate: `Implement the feature described in GitHub issue #{issue}.
|
|
139
|
+
Read the issue and any spec comments with 'gh issue view #{issue} --comments'.
|
|
140
|
+
Follow the implementation plan from the spec.
|
|
141
|
+
Write tests for new functionality.
|
|
142
|
+
Ensure the build passes with 'npm test' and 'npm run build'.`,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
// Testgen — worktree-isolated
|
|
147
|
+
phaseRegistry.register({
|
|
148
|
+
name: "testgen",
|
|
149
|
+
skill: "testgen",
|
|
150
|
+
promptTemplate: "Generate test stubs for GitHub issue #{issue} based on the specification. Run the /testgen {issue} workflow.",
|
|
151
|
+
requiresWorktree: true,
|
|
152
|
+
driverOverrides: {
|
|
153
|
+
aider: {
|
|
154
|
+
promptTemplate: `Generate test stubs for GitHub issue #{issue}.
|
|
155
|
+
Read the spec comments on the issue with 'gh issue view #{issue} --comments'.
|
|
156
|
+
Create test files with describe/it blocks covering the acceptance criteria.
|
|
157
|
+
Use the project's existing test framework.`,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
// Test — worktree-isolated, label-triggered (UI/frontend issues)
|
|
162
|
+
phaseRegistry.register({
|
|
163
|
+
name: "test",
|
|
164
|
+
skill: "test",
|
|
165
|
+
promptTemplate: "Execute structured browser-based testing for GitHub issue #{issue}. Run the /test {issue} workflow.",
|
|
166
|
+
requiresWorktree: true,
|
|
167
|
+
detect: { labels: ["ui", "frontend", "admin", "web", "browser"] },
|
|
168
|
+
driverOverrides: {
|
|
169
|
+
aider: {
|
|
170
|
+
promptTemplate: `Test the implementation for GitHub issue #{issue}.
|
|
171
|
+
Run 'npm test' and verify all tests pass.
|
|
172
|
+
Check for edge cases and error handling.`,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
// Verify — runs in main repo (CLI-only feature verification)
|
|
177
|
+
phaseRegistry.register({
|
|
178
|
+
name: "verify",
|
|
179
|
+
skill: "verify",
|
|
180
|
+
promptTemplate: "Verify the implementation for GitHub issue #{issue} by running commands and capturing output. Run the /verify {issue} workflow.",
|
|
181
|
+
requiresWorktree: false,
|
|
182
|
+
driverOverrides: {
|
|
183
|
+
aider: {
|
|
184
|
+
promptTemplate: `Verify the implementation for GitHub issue #{issue}.
|
|
185
|
+
Run relevant commands and capture their output for review.`,
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
// QA — worktree-isolated
|
|
190
|
+
phaseRegistry.register({
|
|
191
|
+
name: "qa",
|
|
192
|
+
skill: "qa",
|
|
193
|
+
promptTemplate: "Review the implementation for GitHub issue #{issue} against acceptance criteria. Run the /qa {issue} workflow.",
|
|
194
|
+
requiresWorktree: true,
|
|
195
|
+
driverOverrides: {
|
|
196
|
+
aider: {
|
|
197
|
+
promptTemplate: `Review the changes for GitHub issue #{issue}.
|
|
198
|
+
Run 'npm test' and 'npm run build' to verify everything works.
|
|
199
|
+
Check each acceptance criterion from the issue comments.
|
|
200
|
+
Output a verdict: READY_FOR_MERGE, AC_MET_BUT_NOT_A_PLUS, or AC_NOT_MET
|
|
201
|
+
with format "### Verdict: <VERDICT>" followed by an explanation.`,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
// Loop — worktree-isolated. `maxRetries: 0` encodes the
|
|
206
|
+
// "skip cold-start retries" rule consumed by phase-executor.ts (#488).
|
|
207
|
+
phaseRegistry.register({
|
|
208
|
+
name: "loop",
|
|
209
|
+
skill: "loop",
|
|
210
|
+
promptTemplate: "Parse test/QA findings for GitHub issue #{issue} and iterate until quality gates pass. Run the /loop {issue} workflow.",
|
|
211
|
+
requiresWorktree: true,
|
|
212
|
+
retryStrategy: { maxRetries: 0 },
|
|
213
|
+
driverOverrides: {
|
|
214
|
+
aider: {
|
|
215
|
+
promptTemplate: `Review test and QA findings for GitHub issue #{issue}.
|
|
216
|
+
Fix any issues identified in the QA feedback.
|
|
217
|
+
Re-run 'npm test' and 'npm run build' until all quality gates pass.`,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
// Merger — runs in main repo (multi-worktree integration)
|
|
222
|
+
phaseRegistry.register({
|
|
223
|
+
name: "merger",
|
|
224
|
+
skill: "merger",
|
|
225
|
+
promptTemplate: "Integrate and merge completed worktrees for GitHub issue #{issue}. Run the /merger {issue} workflow.",
|
|
226
|
+
requiresWorktree: false,
|
|
227
|
+
driverOverrides: {
|
|
228
|
+
aider: {
|
|
229
|
+
promptTemplate: `Integrate and merge completed worktrees for GitHub issue #{issue}.
|
|
230
|
+
Ensure all branches are up to date and merge cleanly.`,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
});
|
|
@@ -113,17 +113,7 @@ export type QaSummary = z.infer<typeof QaSummarySchema>;
|
|
|
113
113
|
* Log entry for a single phase execution
|
|
114
114
|
*/
|
|
115
115
|
export declare const PhaseLogSchema: z.ZodObject<{
|
|
116
|
-
phase: z.
|
|
117
|
-
qa: "qa";
|
|
118
|
-
loop: "loop";
|
|
119
|
-
verify: "verify";
|
|
120
|
-
spec: "spec";
|
|
121
|
-
"security-review": "security-review";
|
|
122
|
-
exec: "exec";
|
|
123
|
-
testgen: "testgen";
|
|
124
|
-
test: "test";
|
|
125
|
-
merger: "merger";
|
|
126
|
-
}>;
|
|
116
|
+
phase: z.ZodString;
|
|
127
117
|
issueNumber: z.ZodNumber;
|
|
128
118
|
startTime: z.ZodString;
|
|
129
119
|
endTime: z.ZodString;
|
|
@@ -199,17 +189,7 @@ export declare const IssueLogSchema: z.ZodObject<{
|
|
|
199
189
|
partial: "partial";
|
|
200
190
|
}>;
|
|
201
191
|
phases: z.ZodArray<z.ZodObject<{
|
|
202
|
-
phase: z.
|
|
203
|
-
qa: "qa";
|
|
204
|
-
loop: "loop";
|
|
205
|
-
verify: "verify";
|
|
206
|
-
spec: "spec";
|
|
207
|
-
"security-review": "security-review";
|
|
208
|
-
exec: "exec";
|
|
209
|
-
testgen: "testgen";
|
|
210
|
-
test: "test";
|
|
211
|
-
merger: "merger";
|
|
212
|
-
}>;
|
|
192
|
+
phase: z.ZodString;
|
|
213
193
|
issueNumber: z.ZodNumber;
|
|
214
194
|
startTime: z.ZodString;
|
|
215
195
|
endTime: z.ZodString;
|
|
@@ -280,17 +260,7 @@ export type IssueLog = z.infer<typeof IssueLogSchema>;
|
|
|
280
260
|
* Run configuration
|
|
281
261
|
*/
|
|
282
262
|
export declare const RunConfigSchema: z.ZodObject<{
|
|
283
|
-
phases: z.ZodArray<z.
|
|
284
|
-
qa: "qa";
|
|
285
|
-
loop: "loop";
|
|
286
|
-
verify: "verify";
|
|
287
|
-
spec: "spec";
|
|
288
|
-
"security-review": "security-review";
|
|
289
|
-
exec: "exec";
|
|
290
|
-
testgen: "testgen";
|
|
291
|
-
test: "test";
|
|
292
|
-
merger: "merger";
|
|
293
|
-
}>>;
|
|
263
|
+
phases: z.ZodArray<z.ZodString>;
|
|
294
264
|
sequential: z.ZodBoolean;
|
|
295
265
|
qualityLoop: z.ZodBoolean;
|
|
296
266
|
maxIterations: z.ZodNumber;
|
|
@@ -319,17 +289,7 @@ export declare const RunLogSchema: z.ZodObject<{
|
|
|
319
289
|
startTime: z.ZodString;
|
|
320
290
|
endTime: z.ZodString;
|
|
321
291
|
config: z.ZodObject<{
|
|
322
|
-
phases: z.ZodArray<z.
|
|
323
|
-
qa: "qa";
|
|
324
|
-
loop: "loop";
|
|
325
|
-
verify: "verify";
|
|
326
|
-
spec: "spec";
|
|
327
|
-
"security-review": "security-review";
|
|
328
|
-
exec: "exec";
|
|
329
|
-
testgen: "testgen";
|
|
330
|
-
test: "test";
|
|
331
|
-
merger: "merger";
|
|
332
|
-
}>>;
|
|
292
|
+
phases: z.ZodArray<z.ZodString>;
|
|
333
293
|
sequential: z.ZodBoolean;
|
|
334
294
|
qualityLoop: z.ZodBoolean;
|
|
335
295
|
maxIterations: z.ZodNumber;
|
|
@@ -346,17 +306,7 @@ export declare const RunLogSchema: z.ZodObject<{
|
|
|
346
306
|
partial: "partial";
|
|
347
307
|
}>;
|
|
348
308
|
phases: z.ZodArray<z.ZodObject<{
|
|
349
|
-
phase: z.
|
|
350
|
-
qa: "qa";
|
|
351
|
-
loop: "loop";
|
|
352
|
-
verify: "verify";
|
|
353
|
-
spec: "spec";
|
|
354
|
-
"security-review": "security-review";
|
|
355
|
-
exec: "exec";
|
|
356
|
-
testgen: "testgen";
|
|
357
|
-
test: "test";
|
|
358
|
-
merger: "merger";
|
|
359
|
-
}>;
|
|
309
|
+
phase: z.ZodString;
|
|
360
310
|
issueNumber: z.ZodNumber;
|
|
361
311
|
startTime: z.ZodString;
|
|
362
312
|
endTime: z.ZodString;
|
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
-
import type { ExecutionConfig, IssueResult, RunOptions, ProgressCallback } from "./types.js";
|
|
9
|
+
import type { ExecutionConfig, IssueResult, RunOptions, ProgressCallback, PhasePlanCallback, PhasePauseHandle } from "./types.js";
|
|
10
10
|
import type { RunSnapshot } from "./run-state.js";
|
|
11
11
|
import type { WorktreeInfo } from "./worktree-manager.js";
|
|
12
12
|
import { LogWriter } from "./log-writer.js";
|
|
13
13
|
import { StateManager } from "./state-manager.js";
|
|
14
14
|
import { ShutdownManager } from "../shutdown.js";
|
|
15
15
|
import type { LockFile } from "../locks/index.js";
|
|
16
|
+
import { WorkflowEventEmitter } from "./event-emitter.js";
|
|
16
17
|
import type { SequantSettings } from "../settings.js";
|
|
17
18
|
/**
|
|
18
19
|
* Build the stack-manifest line emitted into PR bodies under --stacked.
|
|
@@ -56,6 +57,14 @@ export interface OrchestratorConfig {
|
|
|
56
57
|
baseBranch?: string;
|
|
57
58
|
/** Per-phase progress callback (parallel mode) */
|
|
58
59
|
onProgress?: ProgressCallback;
|
|
60
|
+
/** #672 AC-2: phase-plan callback forwarded into per-issue contexts. */
|
|
61
|
+
onPhasePlan?: PhasePlanCallback;
|
|
62
|
+
/**
|
|
63
|
+
* Optional live-zone pause handle (#656). Forwarded to every issue's
|
|
64
|
+
* batch context so `executePhaseWithRetry` can quiesce the renderer
|
|
65
|
+
* around verbose Claude streaming.
|
|
66
|
+
*/
|
|
67
|
+
phasePauseHandle?: PhasePauseHandle;
|
|
59
68
|
}
|
|
60
69
|
/**
|
|
61
70
|
* High-level init config for full lifecycle execution.
|
|
@@ -75,6 +84,15 @@ export interface RunInit {
|
|
|
75
84
|
baseBranch?: string;
|
|
76
85
|
/** Per-phase progress callback */
|
|
77
86
|
onProgress?: ProgressCallback;
|
|
87
|
+
/** #672 AC-2: phase-plan callback. Fired once per issue once the executor
|
|
88
|
+
* has resolved the final phase pipeline. */
|
|
89
|
+
onPhasePlan?: PhasePlanCallback;
|
|
90
|
+
/**
|
|
91
|
+
* Optional live-zone pause handle (#656). Threaded through to the
|
|
92
|
+
* `OrchestratorConfig` so verbose Claude streaming pauses the renderer's
|
|
93
|
+
* live zone instead of redrawing over it.
|
|
94
|
+
*/
|
|
95
|
+
phasePauseHandle?: PhasePauseHandle;
|
|
78
96
|
/**
|
|
79
97
|
* Invoked once the orchestrator is constructed but before execution begins.
|
|
80
98
|
* Used by the experimental TUI to attach a snapshot poller to the active
|
|
@@ -146,8 +164,16 @@ export declare class RunOrchestrator {
|
|
|
146
164
|
private readonly cfg;
|
|
147
165
|
private readonly issueStates;
|
|
148
166
|
private readonly phaseStartTimes;
|
|
167
|
+
private readonly emitter;
|
|
149
168
|
private done;
|
|
150
169
|
constructor(config: OrchestratorConfig);
|
|
170
|
+
/**
|
|
171
|
+
* Returns the workflow event emitter. External consumers (TUI, MCP server,
|
|
172
|
+
* future webhooks) call `getEmitter().on(...)` to subscribe to lifecycle
|
|
173
|
+
* events. Subscribing is opt-in — the orchestrator runs unaware of who is
|
|
174
|
+
* listening (#504, AC-3).
|
|
175
|
+
*/
|
|
176
|
+
getEmitter(): WorkflowEventEmitter;
|
|
151
177
|
/**
|
|
152
178
|
* Point-in-time view of the entire run.
|
|
153
179
|
*
|
|
@@ -157,7 +183,11 @@ export declare class RunOrchestrator {
|
|
|
157
183
|
* observing torn writes.
|
|
158
184
|
*/
|
|
159
185
|
getSnapshot(): RunSnapshot;
|
|
160
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* Mark the run as completed so the dashboard can unmount and drop event
|
|
188
|
+
* subscribers. Drains the emitter to prevent leaks across multiple
|
|
189
|
+
* `run()` invocations in the same process (e.g. the MCP server).
|
|
190
|
+
*/
|
|
161
191
|
markDone(): void;
|
|
162
192
|
private initIssueStates;
|
|
163
193
|
private wrapProgress;
|