@chllming/wave-orchestration 0.8.5 → 0.8.7
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/CHANGELOG.md +46 -0
- package/README.md +14 -9
- package/docs/README.md +3 -1
- package/docs/context7/bundles.json +19 -20
- package/docs/context7/planner-agent/README.md +4 -1
- package/docs/guides/author-and-run-waves.md +4 -1
- package/docs/guides/planner.md +3 -1
- package/docs/guides/signal-wrappers.md +165 -0
- package/docs/guides/terminal-surfaces.md +15 -0
- package/docs/plans/context7-wave-orchestrator.md +24 -7
- package/docs/plans/current-state.md +7 -3
- package/docs/plans/end-state-architecture.md +16 -4
- package/docs/plans/examples/wave-example-design-handoff.md +1 -1
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +179 -72
- package/docs/plans/wave-orchestrator.md +11 -5
- package/docs/reference/cli-reference.md +21 -4
- package/docs/reference/coordination-and-closure.md +26 -5
- package/docs/reference/live-proof-waves.md +9 -0
- package/docs/reference/npmjs-trusted-publishing.md +2 -2
- package/docs/reference/runtime-config/README.md +9 -3
- package/docs/reference/sample-waves.md +5 -5
- package/docs/reference/skills.md +9 -1
- package/docs/reference/wave-control.md +18 -0
- package/docs/reference/wave-planning-lessons.md +7 -1
- package/docs/research/coordination-failure-review.md +6 -6
- package/package.json +1 -1
- package/releases/manifest.json +38 -0
- package/scripts/context7-api-check.sh +57 -13
- package/scripts/wave-orchestrator/agent-state.mjs +42 -0
- package/scripts/wave-orchestrator/autonomous.mjs +42 -6
- package/scripts/wave-orchestrator/clarification-triage.mjs +4 -3
- package/scripts/wave-orchestrator/control-cli.mjs +145 -11
- package/scripts/wave-orchestrator/control-plane.mjs +12 -1
- package/scripts/wave-orchestrator/coordination-store.mjs +124 -4
- package/scripts/wave-orchestrator/coordination.mjs +35 -0
- package/scripts/wave-orchestrator/executors.mjs +11 -6
- package/scripts/wave-orchestrator/gate-engine.mjs +5 -5
- package/scripts/wave-orchestrator/install.mjs +2 -0
- package/scripts/wave-orchestrator/launcher-runtime.mjs +12 -1
- package/scripts/wave-orchestrator/launcher.mjs +236 -0
- package/scripts/wave-orchestrator/ledger.mjs +14 -12
- package/scripts/wave-orchestrator/reducer-snapshot.mjs +8 -6
- package/scripts/wave-orchestrator/retry-engine.mjs +19 -11
- package/scripts/wave-orchestrator/routing-state.mjs +50 -3
- package/scripts/wave-orchestrator/session-supervisor.mjs +119 -10
- package/scripts/wave-orchestrator/shared.mjs +1 -0
- package/scripts/wave-orchestrator/signals.mjs +681 -0
- package/scripts/wave-orchestrator/task-entity.mjs +4 -4
- package/scripts/wave-orchestrator/terminals.mjs +14 -14
- package/scripts/wave-orchestrator/wave-control-schema.mjs +2 -0
- package/scripts/wave-orchestrator/wave-files.mjs +15 -21
- package/scripts/wave-orchestrator/wave-state-reducer.mjs +72 -5
- package/scripts/wave-status.sh +200 -0
- package/scripts/wave-watch.sh +200 -0
- package/skills/README.md +3 -0
- package/skills/signal-hygiene/SKILL.md +51 -0
- package/skills/signal-hygiene/skill.json +20 -0
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
readWaveDependencyBarrier,
|
|
11
11
|
} from "./gate-engine.mjs";
|
|
12
12
|
import {
|
|
13
|
-
|
|
13
|
+
coordinationRecordBlocksWave,
|
|
14
14
|
openClarificationLinkedRequests,
|
|
15
15
|
} from "./coordination-store.mjs";
|
|
16
16
|
import {
|
|
@@ -197,6 +197,7 @@ export function relaunchReasonBuckets(runs, failures, derivedState) {
|
|
|
197
197
|
const selectedAgentIds = new Set((runs || []).map((run) => run.agent.agentId));
|
|
198
198
|
return {
|
|
199
199
|
clarification: openClarificationLinkedRequests(derivedState?.coordinationState)
|
|
200
|
+
.filter((record) => coordinationRecordBlocksWave(record))
|
|
200
201
|
.flatMap((record) => record.targets || [])
|
|
201
202
|
.some((target) => {
|
|
202
203
|
const agentId = String(target || "").startsWith("agent:")
|
|
@@ -212,7 +213,7 @@ export function relaunchReasonBuckets(runs, failures, derivedState) {
|
|
|
212
213
|
)),
|
|
213
214
|
blocker: (derivedState?.coordinationState?.blockers || []).some(
|
|
214
215
|
(record) =>
|
|
215
|
-
|
|
216
|
+
coordinationRecordBlocksWave(record) &&
|
|
216
217
|
(selectedAgentIds.has(record.agentId) ||
|
|
217
218
|
(record.targets || []).some((target) => {
|
|
218
219
|
const agentId = String(target || "").startsWith("agent:")
|
|
@@ -239,7 +240,10 @@ const HUMAN_INPUT_BLOCKER_KINDS = new Set([
|
|
|
239
240
|
]);
|
|
240
241
|
|
|
241
242
|
function isHumanInputBlocker(blocker) {
|
|
242
|
-
return
|
|
243
|
+
return (
|
|
244
|
+
blocker?.blocking !== false &&
|
|
245
|
+
HUMAN_INPUT_BLOCKER_KINDS.has(String(blocker?.kind || "").trim().toLowerCase())
|
|
246
|
+
);
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
function normalizeRetryTargets(retryTargetSet) {
|
|
@@ -672,10 +676,10 @@ function resolveRelaunchRunsLegacy(agentRuns, failures, derivedState, lanePaths,
|
|
|
672
676
|
const roleBindings = resolveWaveRoleBindings(waveDefinition, lanePaths, waveDefinition?.agents);
|
|
673
677
|
const runsByAgentId = new Map(agentRuns.map((run) => [run.agent.agentId, run]));
|
|
674
678
|
const pendingFeedback = (derivedState?.coordinationState?.humanFeedback || []).filter((record) =>
|
|
675
|
-
|
|
679
|
+
coordinationRecordBlocksWave(record),
|
|
676
680
|
);
|
|
677
681
|
const pendingHumanEscalations = (derivedState?.coordinationState?.humanEscalations || []).filter(
|
|
678
|
-
(record) =>
|
|
682
|
+
(record) => coordinationRecordBlocksWave(record),
|
|
679
683
|
);
|
|
680
684
|
if (pendingFeedback.length > 0 || pendingHumanEscalations.length > 0) {
|
|
681
685
|
return { runs: [], barrier: null };
|
|
@@ -693,7 +697,9 @@ function resolveRelaunchRunsLegacy(agentRuns, failures, derivedState, lanePaths,
|
|
|
693
697
|
return { runs: [], barrier: retryBarrier };
|
|
694
698
|
}
|
|
695
699
|
const clarificationTargets = new Set();
|
|
696
|
-
for (const record of openClarificationLinkedRequests(derivedState?.coordinationState))
|
|
700
|
+
for (const record of openClarificationLinkedRequests(derivedState?.coordinationState).filter((entry) =>
|
|
701
|
+
coordinationRecordBlocksWave(entry),
|
|
702
|
+
)) {
|
|
697
703
|
for (const target of record.targets || []) {
|
|
698
704
|
if (String(target).startsWith("agent:")) {
|
|
699
705
|
clarificationTargets.add(String(target).slice("agent:".length));
|
|
@@ -782,7 +788,7 @@ function resolveRelaunchRunsLegacy(agentRuns, failures, derivedState, lanePaths,
|
|
|
782
788
|
}
|
|
783
789
|
const blockerAgentIds = new Set();
|
|
784
790
|
for (const record of derivedState?.coordinationState?.blockers || []) {
|
|
785
|
-
if (!
|
|
791
|
+
if (!coordinationRecordBlocksWave(record)) {
|
|
786
792
|
continue;
|
|
787
793
|
}
|
|
788
794
|
blockerAgentIds.add(record.agentId);
|
|
@@ -867,10 +873,10 @@ function resolveRelaunchRunsFromWaveState(
|
|
|
867
873
|
) {
|
|
868
874
|
const roleBindings = resolveWaveRoleBindings(waveDefinition, lanePaths, waveDefinition?.agents);
|
|
869
875
|
const pendingFeedback = (waveState?.coordinationState?.humanFeedback || []).filter((record) =>
|
|
870
|
-
|
|
876
|
+
coordinationRecordBlocksWave(record),
|
|
871
877
|
);
|
|
872
878
|
const pendingHumanEscalations = (waveState?.coordinationState?.humanEscalations || []).filter(
|
|
873
|
-
(record) =>
|
|
879
|
+
(record) => coordinationRecordBlocksWave(record),
|
|
874
880
|
);
|
|
875
881
|
if (pendingFeedback.length > 0 || pendingHumanEscalations.length > 0) {
|
|
876
882
|
return { runs: [], barrier: null };
|
|
@@ -890,7 +896,9 @@ function resolveRelaunchRunsFromWaveState(
|
|
|
890
896
|
}
|
|
891
897
|
|
|
892
898
|
const clarificationTargets = new Set();
|
|
893
|
-
for (const record of openClarificationLinkedRequests(waveState?.coordinationState))
|
|
899
|
+
for (const record of openClarificationLinkedRequests(waveState?.coordinationState).filter((entry) =>
|
|
900
|
+
coordinationRecordBlocksWave(entry),
|
|
901
|
+
)) {
|
|
894
902
|
for (const target of record.targets || []) {
|
|
895
903
|
if (String(target).startsWith("agent:")) {
|
|
896
904
|
clarificationTargets.add(String(target).slice("agent:".length));
|
|
@@ -967,7 +975,7 @@ function resolveRelaunchRunsFromWaveState(
|
|
|
967
975
|
|
|
968
976
|
const blockerAgentIds = new Set();
|
|
969
977
|
for (const record of waveState?.coordinationState?.blockers || []) {
|
|
970
|
-
if (!
|
|
978
|
+
if (!coordinationRecordBlocksWave(record)) {
|
|
971
979
|
continue;
|
|
972
980
|
}
|
|
973
981
|
blockerAgentIds.add(record.agentId);
|
|
@@ -2,6 +2,8 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
appendCoordinationRecord,
|
|
5
|
+
coordinationBlockerSeverity,
|
|
6
|
+
coordinationRecordBlocksWave,
|
|
5
7
|
isOpenCoordinationStatus,
|
|
6
8
|
materializeCoordinationState,
|
|
7
9
|
readCoordinationLog,
|
|
@@ -29,6 +31,32 @@ function openTaskCountForAgent(ledger, agentId) {
|
|
|
29
31
|
).length;
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
function completedTaskCountForAgent(ledger, agentId) {
|
|
35
|
+
return (ledger?.tasks || []).filter(
|
|
36
|
+
(task) => task.owner === agentId && ["done", "closed", "resolved"].includes(task.state),
|
|
37
|
+
).length;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function completedCapabilityCountForAgent(ledger, agentId, capability) {
|
|
41
|
+
const normalizedCapability = normalizeCapability(capability);
|
|
42
|
+
if (!normalizedCapability) {
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
const taskCount = (ledger?.tasks || []).filter(
|
|
46
|
+
(task) =>
|
|
47
|
+
task.owner === agentId &&
|
|
48
|
+
["done", "closed", "resolved"].includes(task.state) &&
|
|
49
|
+
normalizeCapability(task.capability) === normalizedCapability,
|
|
50
|
+
).length;
|
|
51
|
+
const assignmentCount = (ledger?.capabilityAssignments || []).filter(
|
|
52
|
+
(assignment) =>
|
|
53
|
+
assignment.assignedAgentId === agentId &&
|
|
54
|
+
["done", "closed", "resolved"].includes(String(assignment.state || "").trim().toLowerCase()) &&
|
|
55
|
+
normalizeCapability(assignment.capability) === normalizedCapability,
|
|
56
|
+
).length;
|
|
57
|
+
return taskCount + assignmentCount;
|
|
58
|
+
}
|
|
59
|
+
|
|
32
60
|
function resolveTargetAssignment(target, agents, ledger, capabilityRouting = {}) {
|
|
33
61
|
const normalizedTarget = String(target || "").trim();
|
|
34
62
|
if (!normalizedTarget) {
|
|
@@ -94,6 +122,12 @@ function resolveTargetAssignment(target, agents, ledger, capabilityRouting = {})
|
|
|
94
122
|
(agent) => Array.isArray(agent.capabilities) && agent.capabilities.includes(capability),
|
|
95
123
|
);
|
|
96
124
|
candidates.sort((left, right) => {
|
|
125
|
+
const capabilityCompletionDiff =
|
|
126
|
+
completedCapabilityCountForAgent(ledger, right.agentId, capability) -
|
|
127
|
+
completedCapabilityCountForAgent(ledger, left.agentId, capability);
|
|
128
|
+
if (capabilityCompletionDiff !== 0) {
|
|
129
|
+
return capabilityCompletionDiff;
|
|
130
|
+
}
|
|
97
131
|
const taskDiff = openTaskCountForAgent(ledger, left.agentId) - openTaskCountForAgent(ledger, right.agentId);
|
|
98
132
|
if (taskDiff !== 0) {
|
|
99
133
|
return taskDiff;
|
|
@@ -101,14 +135,25 @@ function resolveTargetAssignment(target, agents, ledger, capabilityRouting = {})
|
|
|
101
135
|
return String(left.agentId).localeCompare(String(right.agentId));
|
|
102
136
|
});
|
|
103
137
|
if (candidates[0]) {
|
|
138
|
+
const demonstratedCapabilityCompletions = completedCapabilityCountForAgent(
|
|
139
|
+
ledger,
|
|
140
|
+
candidates[0].agentId,
|
|
141
|
+
capability,
|
|
142
|
+
);
|
|
104
143
|
return {
|
|
105
144
|
assignedAgentId: candidates[0].agentId,
|
|
106
145
|
target: normalizedTarget,
|
|
107
146
|
targetType: "capability",
|
|
108
147
|
capability,
|
|
109
|
-
assignmentReason:
|
|
148
|
+
assignmentReason:
|
|
149
|
+
demonstratedCapabilityCompletions > 0
|
|
150
|
+
? "same-wave-capability-owner"
|
|
151
|
+
: "least-busy-capability",
|
|
110
152
|
blocking: true,
|
|
111
|
-
detail:
|
|
153
|
+
detail:
|
|
154
|
+
demonstratedCapabilityCompletions > 0
|
|
155
|
+
? `Capability ${capability} routed to ${candidates[0].agentId} based on demonstrated same-wave capability work (${demonstratedCapabilityCompletions}).`
|
|
156
|
+
: `Capability ${capability} routed to ${candidates[0].agentId}.`,
|
|
112
157
|
};
|
|
113
158
|
}
|
|
114
159
|
return {
|
|
@@ -265,6 +310,7 @@ export function buildRequestAssignments({
|
|
|
265
310
|
});
|
|
266
311
|
const resolvedByPolicy = Boolean(resolvedByPolicyRecord);
|
|
267
312
|
const effectiveStatus = resolvedByPolicy ? "resolved" : record.status;
|
|
313
|
+
const blocking = !resolvedByPolicy && coordinationRecordBlocksWave(record);
|
|
268
314
|
assignments.push({
|
|
269
315
|
id: assignmentId,
|
|
270
316
|
requestId: record.id,
|
|
@@ -282,7 +328,8 @@ export function buildRequestAssignments({
|
|
|
282
328
|
assignedAgentId: resolution.assignedAgentId,
|
|
283
329
|
assignmentReason: resolution.assignmentReason,
|
|
284
330
|
assignmentDetail: resolution.detail,
|
|
285
|
-
blocking
|
|
331
|
+
blocking,
|
|
332
|
+
blockerSeverity: coordinationBlockerSeverity(record),
|
|
286
333
|
artifactRefs: Array.isArray(record.artifactRefs) ? record.artifactRefs : [],
|
|
287
334
|
dependsOn: Array.isArray(record.dependsOn) ? record.dependsOn : [],
|
|
288
335
|
closureCondition: String(record.closureCondition || ""),
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
writeJsonAtomic,
|
|
28
28
|
} from "./shared.mjs";
|
|
29
29
|
import {
|
|
30
|
+
createWaveAgentSessionName,
|
|
30
31
|
killTmuxSessionIfExists,
|
|
31
32
|
terminalSurfaceUsesTerminalRegistry,
|
|
32
33
|
pruneOrphanLaneTemporaryTerminalEntries,
|
|
@@ -40,6 +41,13 @@ import {
|
|
|
40
41
|
launchAgentSession as launchAgentSessionImpl,
|
|
41
42
|
waitForWaveCompletion as waitForWaveCompletionImpl,
|
|
42
43
|
} from "./launcher-runtime.mjs";
|
|
44
|
+
import {
|
|
45
|
+
agentUsesSignalHygiene,
|
|
46
|
+
buildSignalStatusLine,
|
|
47
|
+
residentSignalAckPath,
|
|
48
|
+
residentSignalPath,
|
|
49
|
+
syncWaveSignalProjections,
|
|
50
|
+
} from "./signals.mjs";
|
|
43
51
|
|
|
44
52
|
function isProcessAlive(pid) {
|
|
45
53
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
@@ -342,9 +350,10 @@ export function buildResidentOrchestratorRun({
|
|
|
342
350
|
executorResolved,
|
|
343
351
|
};
|
|
344
352
|
const baseName = `wave-${wave.wave}-resident-orchestrator`;
|
|
345
|
-
const sessionName =
|
|
346
|
-
|
|
347
|
-
|
|
353
|
+
const sessionName = createWaveAgentSessionName(
|
|
354
|
+
lanePaths,
|
|
355
|
+
wave.wave,
|
|
356
|
+
"resident_orchestrator",
|
|
348
357
|
);
|
|
349
358
|
return {
|
|
350
359
|
run: {
|
|
@@ -363,6 +372,8 @@ export function buildResidentOrchestratorRun({
|
|
|
363
372
|
sharedSummaryPath: derivedState.sharedSummaryPath,
|
|
364
373
|
dashboardPath,
|
|
365
374
|
triagePath: derivedState.clarificationTriage?.triagePath || null,
|
|
375
|
+
signalStatePath: residentSignalPath(lanePaths, wave.wave),
|
|
376
|
+
signalAckPath: residentSignalAckPath(lanePaths, wave.wave),
|
|
366
377
|
rolePrompt: agent.prompt,
|
|
367
378
|
}),
|
|
368
379
|
},
|
|
@@ -434,15 +445,9 @@ function isWaveDashboardBackedByLiveSession(lanePaths, dashboardPath, activeSess
|
|
|
434
445
|
if (!Number.isFinite(waveNumber)) {
|
|
435
446
|
return false;
|
|
436
447
|
}
|
|
437
|
-
const dashboardState = readJsonOrNull(dashboardPath);
|
|
438
|
-
const runTag = String(dashboardState?.runTag || "").trim();
|
|
439
448
|
const agentPrefix = `${lanePaths.tmuxSessionPrefix}${waveNumber}_`;
|
|
440
|
-
const dashboardPrefix = `${lanePaths.tmuxDashboardSessionPrefix}${waveNumber}_`;
|
|
441
449
|
for (const sessionName of activeSessionNames) {
|
|
442
|
-
if (
|
|
443
|
-
continue;
|
|
444
|
-
}
|
|
445
|
-
if (!runTag || sessionName.endsWith(`_${runTag}`)) {
|
|
450
|
+
if (sessionName.startsWith(agentPrefix)) {
|
|
446
451
|
return true;
|
|
447
452
|
}
|
|
448
453
|
}
|
|
@@ -777,3 +782,107 @@ export function monitorWaveHumanFeedback({
|
|
|
777
782
|
}
|
|
778
783
|
return changed;
|
|
779
784
|
}
|
|
785
|
+
|
|
786
|
+
export function syncLiveWaveSignals({
|
|
787
|
+
lanePaths,
|
|
788
|
+
wave,
|
|
789
|
+
statusPayload,
|
|
790
|
+
agentRuns,
|
|
791
|
+
residentEnabled = false,
|
|
792
|
+
recordCombinedEvent,
|
|
793
|
+
appendCoordination,
|
|
794
|
+
}) {
|
|
795
|
+
const activeSignalAgents = new Set(
|
|
796
|
+
(Array.isArray(agentRuns) ? agentRuns : [])
|
|
797
|
+
.filter((run) => agentUsesSignalHygiene(run?.agent))
|
|
798
|
+
.map((run) => run.agent.agentId),
|
|
799
|
+
);
|
|
800
|
+
const syncResult = syncWaveSignalProjections({
|
|
801
|
+
lanePaths,
|
|
802
|
+
wave,
|
|
803
|
+
statusPayload,
|
|
804
|
+
includeResident: residentEnabled,
|
|
805
|
+
});
|
|
806
|
+
if (syncResult.wave?.changed) {
|
|
807
|
+
appendWaveControlEvent(lanePaths, wave.wave, {
|
|
808
|
+
entityType: "wave_signal",
|
|
809
|
+
entityId: `wave-${wave.wave}`,
|
|
810
|
+
action: "updated",
|
|
811
|
+
source: "session-supervisor",
|
|
812
|
+
actor: "session-supervisor",
|
|
813
|
+
data: syncResult.wave.snapshot,
|
|
814
|
+
});
|
|
815
|
+
if (typeof recordCombinedEvent === "function") {
|
|
816
|
+
recordCombinedEvent({
|
|
817
|
+
level: syncResult.wave.snapshot.shouldWake ? "warn" : "info",
|
|
818
|
+
message: `Wave signal updated: ${buildSignalStatusLine(syncResult.wave.snapshot)}`,
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
for (const agentResult of syncResult.agents || []) {
|
|
823
|
+
if (!agentResult.changed) {
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
appendWaveControlEvent(lanePaths, wave.wave, {
|
|
827
|
+
entityType: "agent_signal",
|
|
828
|
+
entityId: `wave-${wave.wave}-agent-${agentResult.agentId}`,
|
|
829
|
+
action: "updated",
|
|
830
|
+
source: "session-supervisor",
|
|
831
|
+
actor: "session-supervisor",
|
|
832
|
+
data: agentResult.snapshot,
|
|
833
|
+
});
|
|
834
|
+
if (
|
|
835
|
+
agentResult.snapshot?.shouldWake &&
|
|
836
|
+
activeSignalAgents.has(agentResult.agentId) &&
|
|
837
|
+
typeof recordCombinedEvent === "function"
|
|
838
|
+
) {
|
|
839
|
+
recordCombinedEvent({
|
|
840
|
+
level: "info",
|
|
841
|
+
agentId: agentResult.agentId,
|
|
842
|
+
message: `Signal changed: ${buildSignalStatusLine(agentResult.snapshot, {
|
|
843
|
+
lane: lanePaths.lane,
|
|
844
|
+
wave: wave.wave,
|
|
845
|
+
agentId: agentResult.agentId,
|
|
846
|
+
})}`,
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
if (syncResult.resident?.changed) {
|
|
851
|
+
appendWaveControlEvent(lanePaths, wave.wave, {
|
|
852
|
+
entityType: "agent_signal",
|
|
853
|
+
entityId: `wave-${wave.wave}-agent-resident-orchestrator`,
|
|
854
|
+
action: "updated",
|
|
855
|
+
source: "session-supervisor",
|
|
856
|
+
actor: "session-supervisor",
|
|
857
|
+
data: syncResult.resident.snapshot,
|
|
858
|
+
});
|
|
859
|
+
if (syncResult.resident.snapshot?.shouldWake && typeof recordCombinedEvent === "function") {
|
|
860
|
+
recordCombinedEvent({
|
|
861
|
+
level: "info",
|
|
862
|
+
agentId: "ORCH",
|
|
863
|
+
message: `Resident orchestrator signal changed: ${buildSignalStatusLine(
|
|
864
|
+
syncResult.resident.snapshot,
|
|
865
|
+
{
|
|
866
|
+
lane: lanePaths.lane,
|
|
867
|
+
wave: wave.wave,
|
|
868
|
+
agentId: "resident-orchestrator",
|
|
869
|
+
},
|
|
870
|
+
)}`,
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
if (
|
|
874
|
+
syncResult.resident.snapshot?.shouldWake &&
|
|
875
|
+
typeof appendCoordination === "function"
|
|
876
|
+
) {
|
|
877
|
+
appendCoordination({
|
|
878
|
+
event: "resident_signal_updated",
|
|
879
|
+
waves: [wave.wave],
|
|
880
|
+
status: "running",
|
|
881
|
+
details: syncResult.resident.snapshot.reason || syncResult.resident.snapshot.signal,
|
|
882
|
+
actionRequested:
|
|
883
|
+
"Resident orchestrator should re-read the signal snapshot, shared summary, dashboard, and coordination log.",
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return syncResult;
|
|
888
|
+
}
|
|
@@ -199,6 +199,7 @@ export function buildLanePaths(laneInput = DEFAULT_WAVE_LANE, options = {}) {
|
|
|
199
199
|
telemetryDir: path.join(stateDir, "control-plane", "telemetry"),
|
|
200
200
|
assignmentsDir: path.join(stateDir, "assignments"),
|
|
201
201
|
inboxesDir: path.join(stateDir, "inboxes"),
|
|
202
|
+
signalsDir: path.join(stateDir, "signals"),
|
|
202
203
|
ledgerDir: path.join(stateDir, "ledger"),
|
|
203
204
|
integrationDir: path.join(stateDir, "integration"),
|
|
204
205
|
resultsDir: path.join(stateDir, "results"),
|