@lumenflow/cli 4.21.0 → 4.22.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/README.md +30 -27
- package/dist/delegation-list.js +86 -53
- package/dist/delegation-list.js.map +1 -1
- package/dist/gates-plan-resolvers.js +24 -1
- package/dist/gates-plan-resolvers.js.map +1 -1
- package/dist/init-templates.js +13 -0
- package/dist/init-templates.js.map +1 -1
- package/dist/initiative-create.js +1 -1
- package/dist/orchestrate-init-status.js +24 -31
- package/dist/orchestrate-init-status.js.map +1 -1
- package/dist/orchestrate-initiative.js +31 -2
- package/dist/orchestrate-initiative.js.map +1 -1
- package/dist/orchestrate-monitor.js +433 -1
- package/dist/orchestrate-monitor.js.map +1 -1
- package/dist/public-manifest.js +4 -4
- package/dist/public-manifest.js.map +1 -1
- package/package.json +8 -8
- package/packs/agent-runtime/.turbo/turbo-build.log +1 -1
- package/packs/agent-runtime/package.json +1 -1
- package/packs/sidekick/.turbo/turbo-build.log +1 -1
- package/packs/sidekick/package.json +1 -1
- package/packs/software-delivery/.turbo/turbo-build.log +1 -1
- package/packs/software-delivery/package.json +1 -1
- package/templates/core/LUMENFLOW.md.template +5 -3
- package/templates/core/ai/onboarding/first-wu-mistakes.md.template +2 -2
- package/templates/core/ai/onboarding/initiative-orchestration.md.template +83 -27
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +5 -5
- package/templates/core/ai/onboarding/starting-prompt.md.template +1 -1
- package/templates/core/ai/onboarding/vendor-support.md.template +13 -0
|
@@ -16,12 +16,28 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { Command } from 'commander';
|
|
18
18
|
import chalk from 'chalk';
|
|
19
|
-
import { loadInitiativeWUs, loadMultipleInitiatives, buildExecutionPlanWithLockPolicy, resolveLaneConfigsFromConfig, formatExecutionPlan, formatExecutionPlanWithEmbeddedSpawns, calculateProgress, formatProgress, buildCheckpointWave, formatCheckpointOutput, validateCheckpointFlags, resolveCheckpointModeAsync, LOG_PREFIX, } from '@lumenflow/initiatives';
|
|
19
|
+
import { loadInitiativeWUs, loadMultipleInitiatives, buildExecutionPlanWithLockPolicy, resolveLaneConfigsFromConfig, formatExecutionPlan, formatExecutionPlanWithEmbeddedSpawns, calculateProgress, formatProgress, buildCheckpointWave, formatCheckpointOutput, writeExecutionPlanArtifacts, validateCheckpointFlags, resolveCheckpointModeAsync, LOG_PREFIX, } from '@lumenflow/initiatives';
|
|
20
20
|
import { EXIT_CODES } from '@lumenflow/core/wu-constants';
|
|
21
21
|
import { getConfig } from '@lumenflow/core/config';
|
|
22
22
|
import { getErrorMessage, ProcessExitError } from '@lumenflow/core/error-handler';
|
|
23
23
|
import { runCLI } from './cli-entry-point.js';
|
|
24
|
+
import { loadInitiativeExecutionSummary, } from './orchestrate-monitor.js';
|
|
24
25
|
const VALID_CLIENTS = ['claude-code', 'codex-cli', 'gemini-cli', 'cursor', 'windsurf'];
|
|
26
|
+
function mapExecutionSummaryToCheckpointEvidence(summary) {
|
|
27
|
+
return summary.wus.map((wu) => ({
|
|
28
|
+
wuId: wu.wuId,
|
|
29
|
+
handoffEmitted: wu.state === 'handoff_emitted' || wu.launchReceipt !== undefined,
|
|
30
|
+
active: wu.state === 'active',
|
|
31
|
+
workerReturned: wu.state === 'worker_returned',
|
|
32
|
+
stampPresent: wu.stampPresent,
|
|
33
|
+
worktreePresent: wu.worktreePresent,
|
|
34
|
+
logicalWave: wu.logicalWave,
|
|
35
|
+
launchAttempt: wu.launchAttempt,
|
|
36
|
+
blockedReason: wu.state === 'blocked' ? wu.reason : undefined,
|
|
37
|
+
readyForFinish: wu.state === 'worker_returned' && wu.worktreePresent,
|
|
38
|
+
needsRelaunch: wu.state === 'worker_returned' && !wu.worktreePresent,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
25
41
|
const program = new Command()
|
|
26
42
|
.name('orchestrate-initiative')
|
|
27
43
|
.description('Orchestrate initiative execution with parallel agent spawning')
|
|
@@ -91,7 +107,13 @@ const program = new Command()
|
|
|
91
107
|
console.error(chalk.red(message));
|
|
92
108
|
throw new ProcessExitError(message, EXIT_CODES.ERROR);
|
|
93
109
|
}
|
|
94
|
-
const
|
|
110
|
+
const executionSummary = await loadInitiativeExecutionSummary(process.cwd(), initIds[0], wus);
|
|
111
|
+
const checkpointEvidence = mapExecutionSummaryToCheckpointEvidence(executionSummary);
|
|
112
|
+
const waveData = buildCheckpointWave(initIds[0], {
|
|
113
|
+
dryRun,
|
|
114
|
+
clientName,
|
|
115
|
+
executionEvidence: checkpointEvidence,
|
|
116
|
+
});
|
|
95
117
|
if (!waveData) {
|
|
96
118
|
console.log(chalk.green(`${LOG_PREFIX} All WUs are complete! Nothing to spawn.`));
|
|
97
119
|
return;
|
|
@@ -150,6 +172,13 @@ const program = new Command()
|
|
|
150
172
|
}
|
|
151
173
|
// WU-1202: Output spawn content for actual execution (not dry-run)
|
|
152
174
|
// WU-2375: Format varies by client capability (XML for Claude, markdown for others)
|
|
175
|
+
if (initIds.length === 1) {
|
|
176
|
+
const launchArtifacts = writeExecutionPlanArtifacts(initIds[0], wus, plan, { clientName });
|
|
177
|
+
console.log(chalk.cyan(`${LOG_PREFIX} Wrote plan/launch/status artifacts for launch attempt ${launchArtifacts.launchAttempt}`));
|
|
178
|
+
console.log(` Plan: ${launchArtifacts.planPath}`);
|
|
179
|
+
console.log(` Launch: ${launchArtifacts.launchPath}`);
|
|
180
|
+
console.log(` Status: ${launchArtifacts.statusPath}`);
|
|
181
|
+
}
|
|
153
182
|
console.log('');
|
|
154
183
|
console.log(chalk.bold('Spawn Commands:'));
|
|
155
184
|
console.log(formatExecutionPlanWithEmbeddedSpawns(plan, clientName));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrate-initiative.js","sourceRoot":"","sources":["../src/orchestrate-initiative.ts"],"names":[],"mappings":";AACA,iCAAiC;AACjC,yCAAyC;AAEzC;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,gCAAgC,EAChC,4BAA4B,EAC5B,mBAAmB,EACnB,qCAAqC,EACrC,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,UAAU,GAGX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"orchestrate-initiative.js","sourceRoot":"","sources":["../src/orchestrate-initiative.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,11 @@ import { Command } from 'commander';
|
|
|
25
25
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
26
26
|
import { join } from 'node:path';
|
|
27
27
|
import { EXIT_CODES, LUMENFLOW_PATHS, DelegationRegistryStore, analyzeDelegations, detectStuckDelegations, checkZombieLocks, generateSuggestions, formatMonitorOutput, formatRecoveryResults, runRecovery, processDelegationFailureSignals, formatSignalHandlerOutput, DEFAULT_THRESHOLD_MINUTES, calculateBackoff, } from '@lumenflow/core';
|
|
28
|
+
import { DelegationStatus } from '@lumenflow/core/delegation-registry-schema';
|
|
29
|
+
import { defaultWorktreeFrom } from '@lumenflow/core/wu-paths';
|
|
30
|
+
import { loadInitiativeWUs } from '@lumenflow/initiatives';
|
|
31
|
+
import { loadSignals } from '@lumenflow/memory/signal';
|
|
32
|
+
import { loadMemory } from '@lumenflow/memory/store';
|
|
28
33
|
import { ProcessExitError, createError, ErrorCodes } from '@lumenflow/core/error-handler';
|
|
29
34
|
import chalk from 'chalk';
|
|
30
35
|
import ms, {} from 'ms';
|
|
@@ -45,6 +50,424 @@ export const MIN_WATCH_INTERVAL_MS = 60 * 1000;
|
|
|
45
50
|
*/
|
|
46
51
|
export const MAX_BACKOFF_MS = 60 * 60 * 1000;
|
|
47
52
|
const LOG_PREFIX = '[orchestrate:monitor]';
|
|
53
|
+
const ORCHESTRATION_ARTIFACT_DIR = '.lumenflow/artifacts/orchestration';
|
|
54
|
+
const ATTEMPT_PREFIX = 'attempt-';
|
|
55
|
+
const LAUNCH_FILENAME = 'launch.json';
|
|
56
|
+
const STATUS_FILENAME = 'status.json';
|
|
57
|
+
const TRIGGER_SUBAGENT_STOP = 'subagent-stop';
|
|
58
|
+
const FALLBACK_SIGNAL_COMPATIBILITY_MODE = 'skip-legacy';
|
|
59
|
+
const SIGNAL_BLOCKER_PATTERN = /\b(gate|blocked|blocker|fail|failed|error|timeout|crash)\b/i;
|
|
60
|
+
export const EXECUTION_STATES = {
|
|
61
|
+
READY: 'ready',
|
|
62
|
+
HANDOFF_EMITTED: 'handoff_emitted',
|
|
63
|
+
ACTIVE: 'active',
|
|
64
|
+
WORKER_RETURNED: 'worker_returned',
|
|
65
|
+
BLOCKED: 'blocked',
|
|
66
|
+
DONE: 'done',
|
|
67
|
+
};
|
|
68
|
+
function normalizeWuStatus(value) {
|
|
69
|
+
return typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
70
|
+
}
|
|
71
|
+
function parseAttemptNumber(name) {
|
|
72
|
+
if (!name.startsWith(ATTEMPT_PREFIX)) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const parsed = Number.parseInt(name.slice(ATTEMPT_PREFIX.length), 10);
|
|
76
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
77
|
+
}
|
|
78
|
+
function readJsonFileIfExists(filePath) {
|
|
79
|
+
if (!existsSync(filePath)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(readFileSync(filePath, 'utf8'));
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function getLatestAttemptInfo(baseDir, initiativeId) {
|
|
90
|
+
const rootDir = join(baseDir, ORCHESTRATION_ARTIFACT_DIR, initiativeId);
|
|
91
|
+
if (!existsSync(rootDir)) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
let latestAttempt = null;
|
|
95
|
+
for (const entry of readdirSync(rootDir, { withFileTypes: true })) {
|
|
96
|
+
if (!entry.isDirectory()) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const parsed = parseAttemptNumber(entry.name);
|
|
100
|
+
if (parsed === null) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
latestAttempt = latestAttempt === null ? parsed : Math.max(latestAttempt, parsed);
|
|
104
|
+
}
|
|
105
|
+
if (latestAttempt === null) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
attempt: latestAttempt,
|
|
110
|
+
attemptDir: join(rootDir, `${ATTEMPT_PREFIX}${latestAttempt}`),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function getSignalMessage(signal) {
|
|
114
|
+
return signal.message.trim();
|
|
115
|
+
}
|
|
116
|
+
function isBlockerSignal(signal) {
|
|
117
|
+
const signalText = `${signal.type ?? ''} ${signal.message}`.trim();
|
|
118
|
+
return SIGNAL_BLOCKER_PATTERN.test(signalText);
|
|
119
|
+
}
|
|
120
|
+
function getLatestCheckpoint(nodes) {
|
|
121
|
+
return ([...nodes]
|
|
122
|
+
.filter((node) => node.type === 'checkpoint')
|
|
123
|
+
.sort((left, right) => new Date(right.created_at).getTime() - new Date(left.created_at).getTime())[0] ?? null);
|
|
124
|
+
}
|
|
125
|
+
function getLatestSignal(signals) {
|
|
126
|
+
return ([...signals].sort((left, right) => new Date(right.created_at).getTime() - new Date(left.created_at).getTime())[0] ?? null);
|
|
127
|
+
}
|
|
128
|
+
function getWorktreeRelativePath(wu) {
|
|
129
|
+
if (typeof wu.doc.worktree_path === 'string' && wu.doc.worktree_path.trim().length > 0) {
|
|
130
|
+
return wu.doc.worktree_path.trim();
|
|
131
|
+
}
|
|
132
|
+
if (typeof wu.doc.lane !== 'string' || wu.doc.lane.trim().length === 0) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
return defaultWorktreeFrom({
|
|
136
|
+
lane: wu.doc.lane,
|
|
137
|
+
id: wu.id,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function deriveWuExecutionState(input) {
|
|
141
|
+
const { yamlStatus, stampPresent, worktreePresent, launchReceipt, delegation, blockerSignals } = input;
|
|
142
|
+
const latestCheckpoint = input.latestCheckpoint;
|
|
143
|
+
const checkpointTrigger = typeof latestCheckpoint?.metadata?.trigger === 'string'
|
|
144
|
+
? latestCheckpoint.metadata.trigger
|
|
145
|
+
: '';
|
|
146
|
+
const latestBlocker = blockerSignals[0];
|
|
147
|
+
if (stampPresent || yamlStatus === 'done') {
|
|
148
|
+
return {
|
|
149
|
+
state: EXECUTION_STATES.DONE,
|
|
150
|
+
reason: stampPresent ? 'done stamp present' : 'WU YAML status is done',
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (yamlStatus === 'blocked') {
|
|
154
|
+
return {
|
|
155
|
+
state: EXECUTION_STATES.BLOCKED,
|
|
156
|
+
reason: 'WU YAML status is blocked',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (latestBlocker) {
|
|
160
|
+
return {
|
|
161
|
+
state: EXECUTION_STATES.BLOCKED,
|
|
162
|
+
reason: `blocker signal: ${getSignalMessage(latestBlocker)}`,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (checkpointTrigger === TRIGGER_SUBAGENT_STOP ||
|
|
166
|
+
delegation?.status === DelegationStatus.COMPLETED) {
|
|
167
|
+
return {
|
|
168
|
+
state: EXECUTION_STATES.WORKER_RETURNED,
|
|
169
|
+
reason: checkpointTrigger === TRIGGER_SUBAGENT_STOP
|
|
170
|
+
? 'sub-agent stop checkpoint recorded without completion'
|
|
171
|
+
: 'delegation registry marked completed without a completion stamp',
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
if (worktreePresent || yamlStatus === 'in_progress' || Boolean(delegation?.pickedUpAt)) {
|
|
175
|
+
return {
|
|
176
|
+
state: EXECUTION_STATES.ACTIVE,
|
|
177
|
+
reason: worktreePresent
|
|
178
|
+
? 'worktree present'
|
|
179
|
+
: delegation?.pickedUpAt
|
|
180
|
+
? 'delegation pickup recorded'
|
|
181
|
+
: 'WU YAML status is in_progress',
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (launchReceipt || delegation) {
|
|
185
|
+
return {
|
|
186
|
+
state: EXECUTION_STATES.HANDOFF_EMITTED,
|
|
187
|
+
reason: launchReceipt
|
|
188
|
+
? `handoff emitted in attempt ${launchReceipt.launch_attempt ?? 'unknown'}`
|
|
189
|
+
: 'delegation record exists without pickup evidence',
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
state: EXECUTION_STATES.READY,
|
|
194
|
+
reason: 'no launch or execution evidence',
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function buildProgress(wus) {
|
|
198
|
+
const progress = {
|
|
199
|
+
total: wus.length,
|
|
200
|
+
done: 0,
|
|
201
|
+
active: 0,
|
|
202
|
+
pending: 0,
|
|
203
|
+
blocked: 0,
|
|
204
|
+
percentage: 0,
|
|
205
|
+
handoffEmitted: 0,
|
|
206
|
+
workerReturned: 0,
|
|
207
|
+
};
|
|
208
|
+
for (const wu of wus) {
|
|
209
|
+
switch (wu.state) {
|
|
210
|
+
case EXECUTION_STATES.DONE:
|
|
211
|
+
progress.done += 1;
|
|
212
|
+
break;
|
|
213
|
+
case EXECUTION_STATES.BLOCKED:
|
|
214
|
+
progress.blocked += 1;
|
|
215
|
+
break;
|
|
216
|
+
case EXECUTION_STATES.HANDOFF_EMITTED:
|
|
217
|
+
progress.pending += 1;
|
|
218
|
+
progress.handoffEmitted += 1;
|
|
219
|
+
break;
|
|
220
|
+
case EXECUTION_STATES.WORKER_RETURNED:
|
|
221
|
+
progress.active += 1;
|
|
222
|
+
progress.workerReturned += 1;
|
|
223
|
+
break;
|
|
224
|
+
case EXECUTION_STATES.ACTIVE:
|
|
225
|
+
progress.active += 1;
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
progress.pending += 1;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
progress.percentage =
|
|
233
|
+
progress.total === 0 ? 0 : Math.round((progress.done / progress.total) * 100);
|
|
234
|
+
return progress;
|
|
235
|
+
}
|
|
236
|
+
export function formatExecutionStateLabel(state) {
|
|
237
|
+
return state;
|
|
238
|
+
}
|
|
239
|
+
function formatExecutionStateToken(state) {
|
|
240
|
+
switch (state) {
|
|
241
|
+
case EXECUTION_STATES.DONE:
|
|
242
|
+
return chalk.green('✓ done');
|
|
243
|
+
case EXECUTION_STATES.BLOCKED:
|
|
244
|
+
return chalk.red('⛔ blocked');
|
|
245
|
+
case EXECUTION_STATES.WORKER_RETURNED:
|
|
246
|
+
return chalk.yellow('↩ worker_returned');
|
|
247
|
+
case EXECUTION_STATES.ACTIVE:
|
|
248
|
+
return chalk.yellow('⟳ active');
|
|
249
|
+
case EXECUTION_STATES.HANDOFF_EMITTED:
|
|
250
|
+
return chalk.cyan('↗ handoff_emitted');
|
|
251
|
+
default:
|
|
252
|
+
return chalk.gray('○ ready');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function filterSignalsByWu(signals, wuId) {
|
|
256
|
+
return signals.filter((signal) => signal.wu_id === wuId);
|
|
257
|
+
}
|
|
258
|
+
function mapDelegationsByTarget(delegations) {
|
|
259
|
+
const mapped = new Map();
|
|
260
|
+
for (const delegation of delegations) {
|
|
261
|
+
mapped.set(delegation.targetWuId, delegation);
|
|
262
|
+
}
|
|
263
|
+
return mapped;
|
|
264
|
+
}
|
|
265
|
+
async function loadDelegationMap(baseDir) {
|
|
266
|
+
const store = new DelegationRegistryStore(join(baseDir, LUMENFLOW_PATHS.STATE_DIR));
|
|
267
|
+
try {
|
|
268
|
+
await store.load();
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
return new Map();
|
|
272
|
+
}
|
|
273
|
+
return mapDelegationsByTarget(store.getAllDelegations());
|
|
274
|
+
}
|
|
275
|
+
async function loadIndexedMemory(baseDir) {
|
|
276
|
+
try {
|
|
277
|
+
return await loadMemory(join(baseDir, LUMENFLOW_PATHS.MEMORY_DIR));
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async function loadAllSignals(baseDir) {
|
|
284
|
+
try {
|
|
285
|
+
return await loadSignals(baseDir, {
|
|
286
|
+
compatibilityMode: FALLBACK_SIGNAL_COMPATIBILITY_MODE,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function getStampedWuIds(baseDir) {
|
|
294
|
+
const stamped = new Set();
|
|
295
|
+
const stampDir = join(baseDir, LUMENFLOW_PATHS.STAMPS_DIR);
|
|
296
|
+
if (!existsSync(stampDir)) {
|
|
297
|
+
return stamped;
|
|
298
|
+
}
|
|
299
|
+
for (const file of readdirSync(stampDir)) {
|
|
300
|
+
if (!file.endsWith('.done')) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
stamped.add(file.slice(0, -'.done'.length));
|
|
304
|
+
}
|
|
305
|
+
return stamped;
|
|
306
|
+
}
|
|
307
|
+
export async function loadInitiativeExecutionSummary(baseDir, initiativeId, wus) {
|
|
308
|
+
const latestAttemptInfo = getLatestAttemptInfo(baseDir, initiativeId);
|
|
309
|
+
const launchData = latestAttemptInfo
|
|
310
|
+
? readJsonFileIfExists(join(latestAttemptInfo.attemptDir, LAUNCH_FILENAME))
|
|
311
|
+
: null;
|
|
312
|
+
const statusData = latestAttemptInfo
|
|
313
|
+
? readJsonFileIfExists(join(latestAttemptInfo.attemptDir, STATUS_FILENAME))
|
|
314
|
+
: null;
|
|
315
|
+
const launchReceipts = launchData?.handoffs ?? [];
|
|
316
|
+
const statusEntries = statusData?.wus ?? [];
|
|
317
|
+
const launchReceiptByWu = new Map(launchReceipts.map((receipt) => [receipt.wu_id, receipt]));
|
|
318
|
+
const memory = await loadIndexedMemory(baseDir);
|
|
319
|
+
const signals = await loadAllSignals(baseDir);
|
|
320
|
+
const delegationMap = await loadDelegationMap(baseDir);
|
|
321
|
+
const stampedWuIds = getStampedWuIds(baseDir);
|
|
322
|
+
const liveWus = wus.map((wu) => {
|
|
323
|
+
const launchReceipt = launchReceiptByWu.get(wu.id);
|
|
324
|
+
const delegation = delegationMap.get(wu.id) ?? null;
|
|
325
|
+
const wuNodes = memory?.byWu.get(wu.id) ?? [];
|
|
326
|
+
const checkpoints = wuNodes.filter((node) => node.type === 'checkpoint');
|
|
327
|
+
const latestCheckpoint = getLatestCheckpoint(checkpoints);
|
|
328
|
+
const wuSignals = filterSignalsByWu(signals, wu.id);
|
|
329
|
+
const blockerSignals = wuSignals.filter(isBlockerSignal);
|
|
330
|
+
const latestSignal = getLatestSignal(wuSignals);
|
|
331
|
+
const stampPresent = stampedWuIds.has(wu.id);
|
|
332
|
+
const worktreeRelativePath = getWorktreeRelativePath(wu);
|
|
333
|
+
const worktreePresent = worktreeRelativePath !== null && existsSync(join(baseDir, worktreeRelativePath));
|
|
334
|
+
const yamlStatus = normalizeWuStatus(wu.doc.status);
|
|
335
|
+
const derived = deriveWuExecutionState({
|
|
336
|
+
yamlStatus,
|
|
337
|
+
stampPresent,
|
|
338
|
+
worktreePresent,
|
|
339
|
+
launchReceipt,
|
|
340
|
+
delegation,
|
|
341
|
+
blockerSignals,
|
|
342
|
+
latestCheckpoint,
|
|
343
|
+
});
|
|
344
|
+
return {
|
|
345
|
+
wuId: wu.id,
|
|
346
|
+
title: wu.doc.title ?? wu.id,
|
|
347
|
+
lane: wu.doc.lane ?? 'unknown',
|
|
348
|
+
state: derived.state,
|
|
349
|
+
reason: derived.reason,
|
|
350
|
+
yamlStatus,
|
|
351
|
+
stampPresent,
|
|
352
|
+
worktreePresent,
|
|
353
|
+
logicalWave: launchReceipt?.logical_wave,
|
|
354
|
+
launchAttempt: launchReceipt?.launch_attempt ?? launchData?.launch_attempt ?? undefined,
|
|
355
|
+
launchReceipt,
|
|
356
|
+
delegation,
|
|
357
|
+
checkpointCount: checkpoints.length,
|
|
358
|
+
latestCheckpointAt: latestCheckpoint?.created_at,
|
|
359
|
+
latestCheckpointTrigger: typeof latestCheckpoint?.metadata?.trigger === 'string'
|
|
360
|
+
? latestCheckpoint.metadata.trigger
|
|
361
|
+
: undefined,
|
|
362
|
+
signalCount: wuSignals.length,
|
|
363
|
+
latestSignalMessage: latestSignal ? getSignalMessage(latestSignal) : undefined,
|
|
364
|
+
blockerSignals,
|
|
365
|
+
};
|
|
366
|
+
});
|
|
367
|
+
return {
|
|
368
|
+
initiativeId,
|
|
369
|
+
launchAttempt: launchData?.launch_attempt ?? latestAttemptInfo?.attempt ?? null,
|
|
370
|
+
logicalWaves: launchData?.logical_waves ?? statusData?.logical_waves ?? [],
|
|
371
|
+
launchReceipts,
|
|
372
|
+
statusEntries,
|
|
373
|
+
wus: liveWus,
|
|
374
|
+
progress: buildProgress(liveWus),
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
export function applyExecutionSummaryToWus(wus, summary) {
|
|
378
|
+
const stateByWu = new Map(summary.wus.map((wu) => [wu.wuId, wu.state]));
|
|
379
|
+
return wus.map((wu) => {
|
|
380
|
+
const state = stateByWu.get(wu.id);
|
|
381
|
+
if (!state) {
|
|
382
|
+
return wu;
|
|
383
|
+
}
|
|
384
|
+
const reconciledStatus = state === EXECUTION_STATES.DONE
|
|
385
|
+
? 'done'
|
|
386
|
+
: state === EXECUTION_STATES.BLOCKED
|
|
387
|
+
? 'blocked'
|
|
388
|
+
: state === EXECUTION_STATES.READY || state === EXECUTION_STATES.HANDOFF_EMITTED
|
|
389
|
+
? 'ready'
|
|
390
|
+
: 'in_progress';
|
|
391
|
+
return {
|
|
392
|
+
...wu,
|
|
393
|
+
doc: {
|
|
394
|
+
...wu.doc,
|
|
395
|
+
status: reconciledStatus,
|
|
396
|
+
},
|
|
397
|
+
};
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function shouldIncludeExecutionSummary(summary) {
|
|
401
|
+
if (summary.launchReceipts.length > 0) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
return summary.wus.some((wu) => wu.state !== EXECUTION_STATES.READY);
|
|
405
|
+
}
|
|
406
|
+
export async function loadAllInitiativeExecutionSummaries(baseDir, wuId) {
|
|
407
|
+
const orchestrationRoot = join(baseDir, ORCHESTRATION_ARTIFACT_DIR);
|
|
408
|
+
if (!existsSync(orchestrationRoot)) {
|
|
409
|
+
return [];
|
|
410
|
+
}
|
|
411
|
+
const summaries = [];
|
|
412
|
+
for (const entry of readdirSync(orchestrationRoot, { withFileTypes: true })) {
|
|
413
|
+
if (!entry.isDirectory() || !entry.name.startsWith('INIT-')) {
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
const { wus } = loadInitiativeWUs(entry.name);
|
|
418
|
+
const summary = await loadInitiativeExecutionSummary(baseDir, entry.name, wus);
|
|
419
|
+
const filteredSummary = wuId && wuId.trim().length > 0
|
|
420
|
+
? {
|
|
421
|
+
...summary,
|
|
422
|
+
wus: summary.wus.filter((wu) => wu.wuId === wuId),
|
|
423
|
+
}
|
|
424
|
+
: summary;
|
|
425
|
+
if (filteredSummary.wus.length === 0 || !shouldIncludeExecutionSummary(filteredSummary)) {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
const filteredLaunchReceipts = wuId && wuId.trim().length > 0
|
|
429
|
+
? summary.launchReceipts.filter((receipt) => receipt.wu_id === wuId)
|
|
430
|
+
: summary.launchReceipts;
|
|
431
|
+
const normalizedSummary = {
|
|
432
|
+
...filteredSummary,
|
|
433
|
+
launchReceipts: filteredLaunchReceipts,
|
|
434
|
+
progress: buildProgress(filteredSummary.wus),
|
|
435
|
+
};
|
|
436
|
+
summaries.push(normalizedSummary);
|
|
437
|
+
}
|
|
438
|
+
catch {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return summaries.sort((left, right) => left.initiativeId.localeCompare(right.initiativeId));
|
|
443
|
+
}
|
|
444
|
+
export function formatExecutionEvidenceSection(executionEvidence) {
|
|
445
|
+
if (executionEvidence.length === 0) {
|
|
446
|
+
return '';
|
|
447
|
+
}
|
|
448
|
+
const lines = [];
|
|
449
|
+
lines.push(chalk.bold('Execution Evidence:'));
|
|
450
|
+
for (const summary of executionEvidence) {
|
|
451
|
+
const launchLabel = summary.launchAttempt === null ? 'unknown' : summary.launchAttempt.toString();
|
|
452
|
+
const logicalWaveLabel = summary.logicalWaves.length === 0 ? 'n/a' : summary.logicalWaves.join(', ');
|
|
453
|
+
lines.push(` ${summary.initiativeId}: attempt=${launchLabel}, logical_waves=${logicalWaveLabel}, done=${summary.progress.done}, active=${summary.progress.active}, pending=${summary.progress.pending}, blocked=${summary.progress.blocked}`);
|
|
454
|
+
for (const wu of summary.wus) {
|
|
455
|
+
const details = [];
|
|
456
|
+
if (typeof wu.logicalWave === 'number') {
|
|
457
|
+
details.push(`logical wave ${wu.logicalWave}`);
|
|
458
|
+
}
|
|
459
|
+
details.push(wu.reason);
|
|
460
|
+
if (wu.latestCheckpointTrigger) {
|
|
461
|
+
details.push(`checkpoint=${wu.latestCheckpointTrigger}`);
|
|
462
|
+
}
|
|
463
|
+
if (wu.latestSignalMessage && wu.state === EXECUTION_STATES.BLOCKED) {
|
|
464
|
+
details.push(wu.latestSignalMessage);
|
|
465
|
+
}
|
|
466
|
+
lines.push(` - ${wu.wuId}: ${formatExecutionStateToken(wu.state)} (${details.join('; ')})`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return lines.join('\n');
|
|
470
|
+
}
|
|
48
471
|
/**
|
|
49
472
|
* Runs the delegation monitor.
|
|
50
473
|
*
|
|
@@ -52,7 +475,7 @@ const LOG_PREFIX = '[orchestrate:monitor]';
|
|
|
52
475
|
* @returns MonitorResult with analysis data
|
|
53
476
|
*/
|
|
54
477
|
export async function runMonitor(options = {}) {
|
|
55
|
-
const { baseDir = process.cwd(), thresholdMinutes = DEFAULT_THRESHOLD_MINUTES, recover = false, dryRun = false, } = options;
|
|
478
|
+
const { baseDir = process.cwd(), thresholdMinutes = DEFAULT_THRESHOLD_MINUTES, recover = false, dryRun = false, wuId, } = options;
|
|
56
479
|
// Load delegation registry
|
|
57
480
|
// WU-1278: Use full LUMENFLOW_PATHS.STATE_DIR without stripping .lumenflow/ prefix
|
|
58
481
|
const stateDir = join(baseDir, LUMENFLOW_PATHS.STATE_DIR);
|
|
@@ -77,6 +500,10 @@ export async function runMonitor(options = {}) {
|
|
|
77
500
|
suggestions,
|
|
78
501
|
dryRun,
|
|
79
502
|
};
|
|
503
|
+
const executionEvidence = await loadAllInitiativeExecutionSummaries(baseDir, wuId);
|
|
504
|
+
if (executionEvidence.length > 0) {
|
|
505
|
+
result.executionEvidence = executionEvidence;
|
|
506
|
+
}
|
|
80
507
|
// Run recovery if requested
|
|
81
508
|
if (recover) {
|
|
82
509
|
const recoveryResults = await runRecovery(stuckDelegations, { baseDir, dryRun });
|
|
@@ -100,6 +527,10 @@ export function formatOutput(result) {
|
|
|
100
527
|
lines.push('');
|
|
101
528
|
lines.push(formatRecoveryResults(result.recoveryResults));
|
|
102
529
|
}
|
|
530
|
+
if (result.executionEvidence && result.executionEvidence.length > 0) {
|
|
531
|
+
lines.push('');
|
|
532
|
+
lines.push(formatExecutionEvidenceSection(result.executionEvidence));
|
|
533
|
+
}
|
|
103
534
|
// Add dry-run notice if applicable
|
|
104
535
|
if (result.dryRun) {
|
|
105
536
|
lines.push('');
|
|
@@ -203,6 +634,7 @@ async function runDelegationMonitoring(opts) {
|
|
|
203
634
|
thresholdMinutes,
|
|
204
635
|
recover: opts.recover,
|
|
205
636
|
dryRun: opts.dryRun,
|
|
637
|
+
wuId: opts.wu,
|
|
206
638
|
});
|
|
207
639
|
console.log(formatOutput(result));
|
|
208
640
|
if (opts.recover) {
|