@lumenflow/initiatives 1.0.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.
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Initiative Orchestrator (WU-1581, WU-1821)
3
+ *
4
+ * Core orchestration logic for parallel agent execution of initiative WUs.
5
+ * Builds execution plans based on WU dependencies and manages wave-based execution.
6
+ *
7
+ * Architecture:
8
+ * - Loads initiative(s) and their WUs
9
+ * - Builds dependency graph for topological ordering
10
+ * - Groups independent WUs into parallel execution waves
11
+ * - Generates spawn commands for agent delegation
12
+ *
13
+ * WU-1821 additions:
14
+ * - Checkpoint-per-wave pattern for context management
15
+ * - Wave manifest files for idempotent resumption
16
+ * - Compact output for token discipline
17
+ *
18
+ * @see {@link tools/orchestrate-initiative.mjs} - CLI entry point
19
+ * @see {@link tools/lib/initiative-yaml.mjs} - Initiative loading
20
+ * @see {@link tools/lib/dependency-graph.mjs} - Dependency graph utilities
21
+ */
22
+ import type { InitiativeDoc, WUEntry } from './initiative-yaml.js';
23
+ /**
24
+ * Options for checkpoint mode resolution.
25
+ */
26
+ export interface CheckpointOptions {
27
+ checkpointPerWave?: boolean;
28
+ noCheckpoint?: boolean;
29
+ dryRun?: boolean;
30
+ }
31
+ /**
32
+ * Result of checkpoint mode resolution.
33
+ */
34
+ export interface CheckpointModeResult {
35
+ enabled: boolean;
36
+ source: 'explicit' | 'override' | 'auto' | 'dryrun';
37
+ reason?: string;
38
+ }
39
+ /**
40
+ * Result of auto-detection for checkpoint mode.
41
+ */
42
+ export interface AutoCheckpointResult {
43
+ autoEnabled: boolean;
44
+ reason: string;
45
+ pendingCount: number;
46
+ waveCount: number;
47
+ }
48
+ /**
49
+ * Skipped WU entry with reason.
50
+ */
51
+ export interface SkippedWUEntry {
52
+ id: string;
53
+ reason: string;
54
+ }
55
+ /**
56
+ * Deferred WU entry with blockers.
57
+ */
58
+ export interface DeferredWUEntry {
59
+ id: string;
60
+ blockedBy: string[];
61
+ reason: string;
62
+ }
63
+ /**
64
+ * Execution plan result.
65
+ */
66
+ export interface ExecutionPlan {
67
+ waves: WUEntry[][];
68
+ skipped: string[];
69
+ skippedWithReasons: SkippedWUEntry[];
70
+ deferred: DeferredWUEntry[];
71
+ }
72
+ /**
73
+ * Progress statistics for WUs.
74
+ */
75
+ export interface ProgressStats {
76
+ total: number;
77
+ done: number;
78
+ active: number;
79
+ pending: number;
80
+ blocked: number;
81
+ percentage: number;
82
+ }
83
+ /**
84
+ * Bottleneck WU entry.
85
+ */
86
+ export interface BottleneckWU {
87
+ id: string;
88
+ title: string;
89
+ blocksCount: number;
90
+ }
91
+ /**
92
+ * Wave manifest WU entry.
93
+ */
94
+ export interface WaveManifestWU {
95
+ id: string;
96
+ lane?: string;
97
+ status?: string;
98
+ }
99
+ /**
100
+ * Wave manifest structure.
101
+ */
102
+ export interface WaveManifest {
103
+ initiative: string;
104
+ wave: number;
105
+ created_at?: string;
106
+ wus: WaveManifestWU[];
107
+ lane_validation?: string;
108
+ done_criteria?: string;
109
+ }
110
+ /**
111
+ * Checkpoint wave result.
112
+ */
113
+ export interface CheckpointWaveResult {
114
+ initiative: string;
115
+ wave: number;
116
+ wus: WaveManifestWU[];
117
+ manifestPath: string | null;
118
+ blockedBy?: string[];
119
+ waitingMessage?: string;
120
+ dryRun?: boolean;
121
+ }
122
+ /**
123
+ * Dependency filter result.
124
+ */
125
+ export interface DependencyFilterResult {
126
+ spawnable: WUEntry[];
127
+ blocked: WUEntry[];
128
+ blockingDeps: string[];
129
+ waitingMessage: string;
130
+ }
131
+ /**
132
+ * Log prefix for orchestrator messages.
133
+ */
134
+ declare const LOG_PREFIX = "[orchestrate:initiative]";
135
+ /**
136
+ * WU-1828: Auto-detection thresholds for checkpoint mode.
137
+ *
138
+ * These thresholds determine when checkpoint mode is automatically enabled
139
+ * to prevent "prompt too long" errors for large initiatives.
140
+ *
141
+ * @type {{WU_COUNT: number, WAVE_COUNT: number}}
142
+ */
143
+ export declare const CHECKPOINT_AUTO_THRESHOLDS: {
144
+ /** Auto-enable checkpoint mode if pending WU count exceeds this (>3 = 4+) */
145
+ WU_COUNT: number;
146
+ /** Auto-enable checkpoint mode if wave count exceeds this (>2 = 3+) */
147
+ WAVE_COUNT: number;
148
+ };
149
+ /**
150
+ * Load initiative and its WUs.
151
+ *
152
+ * @param {string} initRef - Initiative ID or slug
153
+ * @returns {{initiative: object, wus: Array<{id: string, doc: object}>}}
154
+ * @throws {Error} If initiative not found
155
+ */
156
+ export declare function loadInitiativeWUs(initRef: string): {
157
+ initiative: InitiativeDoc;
158
+ wus: WUEntry[];
159
+ };
160
+ /**
161
+ * Load multiple initiatives and combine their WUs.
162
+ *
163
+ * Used for cross-initiative parallel execution.
164
+ *
165
+ * @param {string[]} initRefs - Array of initiative IDs or slugs
166
+ * @returns {Array<{id: string, doc: object}>} Combined WUs from all initiatives
167
+ * @throws {Error} If any initiative not found
168
+ */
169
+ export declare function loadMultipleInitiatives(initRefs: string[]): WUEntry[];
170
+ /**
171
+ * Build execution plan from WUs.
172
+ *
173
+ * Groups WUs into waves based on dependencies:
174
+ * - Wave 0: All WUs with no blockers (can run in parallel)
175
+ * - Wave 1: WUs blocked by wave 0 WUs only
176
+ * - Wave N: WUs blocked by wave N-1 WUs
177
+ *
178
+ * WU-2430: Enhanced filtering:
179
+ * - Only schedules status: ready WUs (not blocked/in_progress)
180
+ * - Reports skipped WUs with reasons (skippedWithReasons)
181
+ * - Defers WUs with unstamped external dependencies (deferred)
182
+ *
183
+ * @param {Array<{id: string, doc: object}>} wus - WUs to plan
184
+ * @returns {{waves: Array<Array<{id: string, doc: object}>>, skipped: string[], skippedWithReasons: Array<{id: string, reason: string}>, deferred: Array<{id: string, blockedBy: string[], reason: string}>}}
185
+ * @throws {Error} If circular dependencies detected
186
+ */
187
+ export declare function buildExecutionPlan(wus: WUEntry[]): ExecutionPlan;
188
+ /**
189
+ * WU-1828: Determine if checkpoint mode should be auto-enabled based on initiative size.
190
+ *
191
+ * Auto-detection triggers checkpoint mode when:
192
+ * - Pending WU count exceeds WU_COUNT threshold (>3)
193
+ * - OR wave count exceeds WAVE_COUNT threshold (>2)
194
+ *
195
+ * This prevents "prompt too long" errors for large initiatives by using
196
+ * checkpoint-per-wave execution instead of polling mode.
197
+ *
198
+ * @param {Array<{id: string, doc: object}>} wus - WUs to analyse
199
+ * @returns {{autoEnabled: boolean, reason: string, pendingCount: number, waveCount: number}}
200
+ */
201
+ export declare function shouldAutoEnableCheckpoint(wus: WUEntry[]): AutoCheckpointResult;
202
+ /**
203
+ * WU-1828: Resolve checkpoint mode from CLI flags and auto-detection.
204
+ * WU-2430: Updated to suppress auto-detection in dry-run mode.
205
+ *
206
+ * Flag precedence:
207
+ * 1. --checkpoint-per-wave (-c): Explicitly enables checkpoint mode
208
+ * 2. --no-checkpoint: Explicitly disables checkpoint mode (overrides auto-detection)
209
+ * 3. --dry-run: Suppresses auto-detection (dry-run uses polling mode for preview)
210
+ * 4. Auto-detection: Enabled based on initiative size if no explicit flags
211
+ *
212
+ * @param {{checkpointPerWave?: boolean, noCheckpoint?: boolean, dryRun?: boolean}} options - CLI options
213
+ * @param {Array<{id: string, doc: object}>} wus - WUs for auto-detection
214
+ * @returns {{enabled: boolean, source: 'explicit'|'override'|'auto'|'dryrun', reason?: string}}
215
+ */
216
+ export declare function resolveCheckpointMode(options: CheckpointOptions, wus: WUEntry[]): CheckpointModeResult;
217
+ /**
218
+ * Get bottleneck WUs from a set of WUs based on how many downstream WUs they block.
219
+ * A bottleneck is a WU that blocks multiple other WUs.
220
+ *
221
+ * @param {Array<{id: string, doc: object}>} wus - WUs to analyse
222
+ * @param {number} [limit=5] - Maximum number of bottlenecks to return
223
+ * @returns {Array<{id: string, title: string, blocksCount: number}>} Bottleneck WUs sorted by impact
224
+ */
225
+ export declare function getBottleneckWUs(wus: WUEntry[], limit?: number): BottleneckWU[];
226
+ /**
227
+ * Format execution plan for display.
228
+ *
229
+ * WU-2430: Enhanced to show skippedWithReasons and deferred WUs.
230
+ *
231
+ * @param {object} initiative - Initiative document
232
+ * @param {{waves: Array<Array<{id: string, doc: object}>>, skipped: string[], skippedWithReasons?: Array<{id: string, reason: string}>, deferred?: Array<{id: string, blockedBy: string[], reason: string}>}} plan - Execution plan
233
+ * @returns {string} Formatted plan output
234
+ */
235
+ export declare function formatExecutionPlan(initiative: InitiativeDoc, plan: ExecutionPlan): string;
236
+ /**
237
+ * Generate spawn commands for a wave of WUs.
238
+ *
239
+ * @param {Array<{id: string, doc: object}>} wave - WUs in the wave
240
+ * @returns {string[]} Array of spawn command strings
241
+ */
242
+ export declare function generateSpawnCommands(wave: WUEntry[]): string[];
243
+ /**
244
+ * Calculate progress statistics for WUs.
245
+ *
246
+ * @param {Array<{id: string, doc: object}>} wus - WUs to calculate progress for
247
+ * @returns {{total: number, done: number, active: number, pending: number, blocked: number, percentage: number}}
248
+ */
249
+ export declare function calculateProgress(wus: WUEntry[]): ProgressStats;
250
+ /**
251
+ * Format progress for display.
252
+ *
253
+ * @param {{total: number, done: number, active: number, pending: number, blocked: number, percentage: number}} progress
254
+ * @returns {string} Formatted progress string
255
+ */
256
+ export declare function formatProgress(progress: ProgressStats): string;
257
+ /**
258
+ * WU-2040: Filter WUs by dependency stamp status.
259
+ *
260
+ * A WU is only spawnable if ALL its blocked_by dependencies have stamps.
261
+ * This implements the wait-for-completion pattern per Anthropic multi-agent research.
262
+ *
263
+ * @param {Array<{id: string, doc: {blocked_by?: string[], lane: string, status: string}}>} candidates - WU candidates
264
+ * @returns {{spawnable: Array<object>, blocked: Array<object>, blockingDeps: string[], waitingMessage: string}}
265
+ */
266
+ export declare function filterByDependencyStamps(candidates: WUEntry[]): DependencyFilterResult;
267
+ /**
268
+ * Validate checkpoint-per-wave flag combinations.
269
+ *
270
+ * WU-1828: Extended to validate --no-checkpoint flag combinations.
271
+ *
272
+ * @param {{checkpointPerWave?: boolean, dryRun?: boolean, noCheckpoint?: boolean}} options - CLI options
273
+ * @throws {Error} If invalid flag combination
274
+ */
275
+ export declare function validateCheckpointFlags(options: CheckpointOptions): void;
276
+ /**
277
+ * Build a checkpoint wave for an initiative.
278
+ *
279
+ * WU-1821: Creates a wave manifest file and returns spawn candidates.
280
+ * Implements idempotency: skips WUs with stamps or already in previous manifests.
281
+ *
282
+ * Idempotency precedence (single source of truth):
283
+ * 1. Stamp (highest): .beacon/stamps/WU-XXXX.done exists → WU is done
284
+ * 2. Manifest: WU already in previous wave manifest → skip
285
+ * 3. Status: Only spawn status: ready WUs
286
+ *
287
+ * @param {string} initRef - Initiative ID or slug
288
+ * @returns {{wave: number, wus: Array<{id: string, lane: string, status: string}>, manifestPath: string, initiative: string}|null}
289
+ * Wave data or null if all WUs complete
290
+ */
291
+ export declare function buildCheckpointWave(initRef: string, options?: CheckpointOptions): CheckpointWaveResult | null;
292
+ /**
293
+ * Format checkpoint wave output with Task invocations.
294
+ *
295
+ * WU-1821: Token discipline - keep output minimal for context management.
296
+ * WU-2040: Output full Task invocation blocks instead of pnpm wu:spawn meta-prompts.
297
+ * WU-2280: Prevent false wave spawned confusion - use markdown code blocks and ACTION REQUIRED banner.
298
+ * WU-2430: Handle dry-run mode - indicate preview mode clearly.
299
+ *
300
+ * @param {{initiative: string, wave: number, wus: Array<{id: string, lane: string}>, manifestPath: string, blockedBy?: string[], waitingMessage?: string, dryRun?: boolean}} waveData
301
+ * @returns {string} Formatted output with embedded Task invocations
302
+ */
303
+ export declare function formatCheckpointOutput(waveData: CheckpointWaveResult): string;
304
+ /**
305
+ * WU-2027: Generate embedded spawn prompt for a WU.
306
+ *
307
+ * Instead of outputting a meta-prompt like "Run: pnpm wu:spawn --id WU-XXX",
308
+ * this function runs the spawn logic internally and returns the full ~3KB
309
+ * prompt content ready for embedding in a Task invocation.
310
+ *
311
+ * This follows Anthropic guidance that sub-agent prompts must be fully
312
+ * self-contained to prevent delegation failures.
313
+ *
314
+ * @param {string} wuId - WU ID (e.g., 'WU-001')
315
+ * @returns {string} Escaped spawn prompt content ready for XML embedding
316
+ * @throws {Error} If WU file not found or cannot be parsed
317
+ */
318
+ export declare function generateEmbeddedSpawnPrompt(wuId: string): string;
319
+ /**
320
+ * WU-2027: Format a Task invocation with embedded spawn content for a WU.
321
+ *
322
+ * Creates a complete Task tool invocation block with the full spawn prompt
323
+ * embedded directly, rather than a meta-prompt referencing wu:spawn.
324
+ *
325
+ * @param {{id: string, doc: object}} wu - WU with id and YAML doc
326
+ * @returns {string} Complete Task invocation with embedded spawn content
327
+ */
328
+ export declare function formatTaskInvocationWithEmbeddedSpawn(wu: WUEntry): string;
329
+ /**
330
+ * WU-2027: Format execution plan with embedded spawns (no meta-prompts).
331
+ * WU-2280: Updated to use markdown code blocks and ACTION REQUIRED banner.
332
+ *
333
+ * Generates Task invocation blocks for all WUs in the execution plan,
334
+ * with full spawn content embedded directly. This replaces the meta-prompt
335
+ * pattern that was causing delegation failures.
336
+ *
337
+ * @param {{waves: Array<Array<{id: string, doc: object}>>, skipped: string[]}} plan - Execution plan
338
+ * @returns {string} Formatted output with embedded Task invocations
339
+ */
340
+ export declare function formatExecutionPlanWithEmbeddedSpawns(plan: ExecutionPlan): string;
341
+ export { LOG_PREFIX };