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.
Files changed (54) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +8 -5
  4. package/dist/bin/cli.js +46 -4
  5. package/dist/src/commands/abort.d.ts +36 -0
  6. package/dist/src/commands/abort.js +138 -0
  7. package/dist/src/commands/prompt.d.ts +7 -0
  8. package/dist/src/commands/prompt.js +101 -7
  9. package/dist/src/commands/run-progress.d.ts +11 -1
  10. package/dist/src/commands/run-progress.js +20 -3
  11. package/dist/src/commands/run.js +12 -2
  12. package/dist/src/commands/watch.d.ts +2 -0
  13. package/dist/src/commands/watch.js +67 -3
  14. package/dist/src/lib/assess-collision-detect.js +1 -1
  15. package/dist/src/lib/cli-ui/run-renderer-types.d.ts +39 -0
  16. package/dist/src/lib/cli-ui/run-renderer.d.ts +27 -1
  17. package/dist/src/lib/cli-ui/run-renderer.js +231 -14
  18. package/dist/src/lib/cli-ui/scrollback-harness.d.ts +112 -0
  19. package/dist/src/lib/cli-ui/scrollback-harness.js +294 -0
  20. package/dist/src/lib/merge-check/types.js +1 -1
  21. package/dist/src/lib/relay/archive.js +6 -0
  22. package/dist/src/lib/relay/types.d.ts +2 -0
  23. package/dist/src/lib/relay/types.js +9 -0
  24. package/dist/src/lib/workflow/batch-executor.js +34 -18
  25. package/dist/src/lib/workflow/drivers/agent-driver.d.ts +48 -1
  26. package/dist/src/lib/workflow/drivers/aider.d.ts +7 -1
  27. package/dist/src/lib/workflow/drivers/aider.js +9 -0
  28. package/dist/src/lib/workflow/drivers/claude-code.d.ts +17 -1
  29. package/dist/src/lib/workflow/drivers/claude-code.js +51 -2
  30. package/dist/src/lib/workflow/drivers/index.d.ts +1 -1
  31. package/dist/src/lib/workflow/event-emitter.d.ts +157 -0
  32. package/dist/src/lib/workflow/event-emitter.js +102 -0
  33. package/dist/src/lib/workflow/notice.d.ts +32 -0
  34. package/dist/src/lib/workflow/notice.js +38 -0
  35. package/dist/src/lib/workflow/phase-executor.d.ts +9 -21
  36. package/dist/src/lib/workflow/phase-executor.js +88 -115
  37. package/dist/src/lib/workflow/phase-mapper.d.ts +26 -13
  38. package/dist/src/lib/workflow/phase-mapper.js +55 -33
  39. package/dist/src/lib/workflow/phase-registry.d.ts +127 -0
  40. package/dist/src/lib/workflow/phase-registry.js +233 -0
  41. package/dist/src/lib/workflow/run-log-schema.d.ts +5 -55
  42. package/dist/src/lib/workflow/run-orchestrator.d.ts +32 -2
  43. package/dist/src/lib/workflow/run-orchestrator.js +125 -11
  44. package/dist/src/lib/workflow/state-manager.d.ts +19 -1
  45. package/dist/src/lib/workflow/state-manager.js +27 -1
  46. package/dist/src/lib/workflow/state-schema.d.ts +20 -35
  47. package/dist/src/lib/workflow/state-schema.js +28 -3
  48. package/dist/src/lib/workflow/types.d.ts +65 -15
  49. package/dist/src/lib/workflow/types.js +18 -13
  50. package/package.json +5 -4
  51. package/templates/hooks/post-tool.sh +81 -0
  52. package/templates/skills/assess/SKILL.md +28 -28
  53. package/templates/skills/assess/references/predicted-collision-detection.md +1 -1
  54. 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.ZodEnum<{
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.ZodEnum<{
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.ZodEnum<{
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.ZodEnum<{
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.ZodEnum<{
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
- /** Mark the run as completed so the dashboard can unmount. */
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;