@chllming/wave-orchestration 0.5.1

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 (68) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +549 -0
  3. package/docs/agents/wave-deploy-verifier-role.md +34 -0
  4. package/docs/agents/wave-documentation-role.md +30 -0
  5. package/docs/agents/wave-evaluator-role.md +43 -0
  6. package/docs/agents/wave-infra-role.md +34 -0
  7. package/docs/agents/wave-integration-role.md +32 -0
  8. package/docs/agents/wave-launcher-role.md +37 -0
  9. package/docs/context7/bundles.json +91 -0
  10. package/docs/plans/component-cutover-matrix.json +112 -0
  11. package/docs/plans/component-cutover-matrix.md +49 -0
  12. package/docs/plans/context7-wave-orchestrator.md +130 -0
  13. package/docs/plans/current-state.md +44 -0
  14. package/docs/plans/master-plan.md +16 -0
  15. package/docs/plans/migration.md +23 -0
  16. package/docs/plans/wave-orchestrator.md +254 -0
  17. package/docs/plans/waves/wave-0.md +165 -0
  18. package/docs/reference/github-packages-setup.md +52 -0
  19. package/docs/reference/migration-0.2-to-0.5.md +622 -0
  20. package/docs/reference/npmjs-trusted-publishing.md +55 -0
  21. package/docs/reference/repository-guidance.md +18 -0
  22. package/docs/reference/runtime-config/README.md +85 -0
  23. package/docs/reference/runtime-config/claude.md +105 -0
  24. package/docs/reference/runtime-config/codex.md +81 -0
  25. package/docs/reference/runtime-config/opencode.md +93 -0
  26. package/docs/research/agent-context-sources.md +57 -0
  27. package/docs/roadmap.md +626 -0
  28. package/package.json +53 -0
  29. package/releases/manifest.json +101 -0
  30. package/scripts/context7-api-check.sh +21 -0
  31. package/scripts/context7-export-env.sh +52 -0
  32. package/scripts/research/agent-context-archive.mjs +472 -0
  33. package/scripts/research/generate-agent-context-indexes.mjs +85 -0
  34. package/scripts/research/import-agent-context-archive.mjs +793 -0
  35. package/scripts/research/manifests/harness-and-blackboard-2026-03-21.mjs +201 -0
  36. package/scripts/wave-autonomous.mjs +13 -0
  37. package/scripts/wave-cli-bootstrap.mjs +27 -0
  38. package/scripts/wave-dashboard.mjs +11 -0
  39. package/scripts/wave-human-feedback.mjs +11 -0
  40. package/scripts/wave-launcher.mjs +11 -0
  41. package/scripts/wave-local-executor.mjs +13 -0
  42. package/scripts/wave-orchestrator/agent-state.mjs +416 -0
  43. package/scripts/wave-orchestrator/autonomous.mjs +367 -0
  44. package/scripts/wave-orchestrator/clarification-triage.mjs +605 -0
  45. package/scripts/wave-orchestrator/config.mjs +848 -0
  46. package/scripts/wave-orchestrator/context7.mjs +464 -0
  47. package/scripts/wave-orchestrator/coord-cli.mjs +286 -0
  48. package/scripts/wave-orchestrator/coordination-store.mjs +987 -0
  49. package/scripts/wave-orchestrator/coordination.mjs +768 -0
  50. package/scripts/wave-orchestrator/dashboard-renderer.mjs +254 -0
  51. package/scripts/wave-orchestrator/dashboard-state.mjs +473 -0
  52. package/scripts/wave-orchestrator/dep-cli.mjs +219 -0
  53. package/scripts/wave-orchestrator/docs-queue.mjs +75 -0
  54. package/scripts/wave-orchestrator/executors.mjs +385 -0
  55. package/scripts/wave-orchestrator/feedback.mjs +372 -0
  56. package/scripts/wave-orchestrator/install.mjs +540 -0
  57. package/scripts/wave-orchestrator/launcher.mjs +3879 -0
  58. package/scripts/wave-orchestrator/ledger.mjs +332 -0
  59. package/scripts/wave-orchestrator/local-executor.mjs +263 -0
  60. package/scripts/wave-orchestrator/replay.mjs +246 -0
  61. package/scripts/wave-orchestrator/roots.mjs +10 -0
  62. package/scripts/wave-orchestrator/routing-state.mjs +542 -0
  63. package/scripts/wave-orchestrator/shared.mjs +405 -0
  64. package/scripts/wave-orchestrator/terminals.mjs +209 -0
  65. package/scripts/wave-orchestrator/traces.mjs +1094 -0
  66. package/scripts/wave-orchestrator/wave-files.mjs +1923 -0
  67. package/scripts/wave.mjs +103 -0
  68. package/wave.config.json +115 -0
@@ -0,0 +1,542 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import {
4
+ appendCoordinationRecord,
5
+ isOpenCoordinationStatus,
6
+ materializeCoordinationState,
7
+ readCoordinationLog,
8
+ } from "./coordination-store.mjs";
9
+ import { compactSingleLine, toIsoTimestamp, writeTextAtomic } from "./shared.mjs";
10
+
11
+ function normalizeCapability(value) {
12
+ return String(value || "")
13
+ .trim()
14
+ .toLowerCase();
15
+ }
16
+
17
+ function targetSlug(value) {
18
+ return String(value || "")
19
+ .trim()
20
+ .toLowerCase()
21
+ .replace(/[^a-z0-9._:-]+/g, "-")
22
+ .replace(/-+/g, "-")
23
+ .replace(/^-+|-+$/g, "");
24
+ }
25
+
26
+ function openTaskCountForAgent(ledger, agentId) {
27
+ return (ledger?.tasks || []).filter(
28
+ (task) => task.owner === agentId && !["done", "closed", "resolved"].includes(task.state),
29
+ ).length;
30
+ }
31
+
32
+ function resolveTargetAssignment(target, agents, ledger, capabilityRouting = {}) {
33
+ const normalizedTarget = String(target || "").trim();
34
+ if (!normalizedTarget) {
35
+ return {
36
+ assignedAgentId: null,
37
+ target: normalizedTarget,
38
+ targetType: "unknown",
39
+ capability: null,
40
+ assignmentReason: "empty-target",
41
+ blocking: true,
42
+ detail: "Request target was empty.",
43
+ };
44
+ }
45
+
46
+ const agentsById = new Map((agents || []).map((agent) => [agent.agentId, agent]));
47
+ if (normalizedTarget.startsWith("agent:")) {
48
+ const agentId = normalizedTarget.slice("agent:".length).trim();
49
+ return {
50
+ assignedAgentId: agentsById.has(agentId) ? agentId : null,
51
+ target: normalizedTarget,
52
+ targetType: "agent",
53
+ capability: null,
54
+ assignmentReason: agentsById.has(agentId) ? "explicit-agent" : "missing-agent",
55
+ blocking: true,
56
+ detail: agentsById.has(agentId)
57
+ ? `Assigned explicitly to ${agentId}.`
58
+ : `No matching agent exists for ${normalizedTarget}.`,
59
+ };
60
+ }
61
+ if (agentsById.has(normalizedTarget)) {
62
+ return {
63
+ assignedAgentId: normalizedTarget,
64
+ target: normalizedTarget,
65
+ targetType: "agent",
66
+ capability: null,
67
+ assignmentReason: "exact-agent-id",
68
+ blocking: true,
69
+ detail: `Assigned directly to ${normalizedTarget}.`,
70
+ };
71
+ }
72
+ if (normalizedTarget.startsWith("capability:")) {
73
+ const capability = normalizeCapability(normalizedTarget.slice("capability:".length));
74
+ const preferredAgents = capabilityRouting?.preferredAgents?.[capability] || [];
75
+ for (const preferredAgentId of preferredAgents) {
76
+ const preferredAgent = agentsById.get(preferredAgentId);
77
+ if (
78
+ preferredAgent &&
79
+ Array.isArray(preferredAgent.capabilities) &&
80
+ preferredAgent.capabilities.includes(capability)
81
+ ) {
82
+ return {
83
+ assignedAgentId: preferredAgentId,
84
+ target: normalizedTarget,
85
+ targetType: "capability",
86
+ capability,
87
+ assignmentReason: "preferred-agent",
88
+ blocking: true,
89
+ detail: `Capability ${capability} routed to preferred agent ${preferredAgentId}.`,
90
+ };
91
+ }
92
+ }
93
+ const candidates = (agents || []).filter(
94
+ (agent) => Array.isArray(agent.capabilities) && agent.capabilities.includes(capability),
95
+ );
96
+ candidates.sort((left, right) => {
97
+ const taskDiff = openTaskCountForAgent(ledger, left.agentId) - openTaskCountForAgent(ledger, right.agentId);
98
+ if (taskDiff !== 0) {
99
+ return taskDiff;
100
+ }
101
+ return String(left.agentId).localeCompare(String(right.agentId));
102
+ });
103
+ if (candidates[0]) {
104
+ return {
105
+ assignedAgentId: candidates[0].agentId,
106
+ target: normalizedTarget,
107
+ targetType: "capability",
108
+ capability,
109
+ assignmentReason: "least-busy-capability",
110
+ blocking: true,
111
+ detail: `Capability ${capability} routed to ${candidates[0].agentId}.`,
112
+ };
113
+ }
114
+ return {
115
+ assignedAgentId: null,
116
+ target: normalizedTarget,
117
+ targetType: "capability",
118
+ capability,
119
+ assignmentReason: "missing-capability-owner",
120
+ blocking: true,
121
+ detail: `No agent advertises capability ${capability}.`,
122
+ };
123
+ }
124
+ return {
125
+ assignedAgentId: null,
126
+ target: normalizedTarget,
127
+ targetType: "unknown",
128
+ capability: null,
129
+ assignmentReason: "unsupported-target",
130
+ blocking: true,
131
+ detail: `Unsupported assignment target ${normalizedTarget}.`,
132
+ };
133
+ }
134
+
135
+ function isLauncherSeedRequest(record) {
136
+ return (
137
+ record?.source === "launcher" &&
138
+ /^wave-\d+-agent-[^-]+-request$/.test(String(record.id || "")) &&
139
+ !String(record.closureCondition || "").trim() &&
140
+ (!Array.isArray(record.dependsOn) || record.dependsOn.length === 0)
141
+ );
142
+ }
143
+
144
+ function assignmentStateForRecord(record) {
145
+ const status = String(record?.status || "").trim().toLowerCase();
146
+ if (["resolved", "closed", "superseded", "cancelled"].includes(status)) {
147
+ return "resolved";
148
+ }
149
+ if (status === "in_progress") {
150
+ return "in_progress";
151
+ }
152
+ if (status === "acknowledged") {
153
+ return "acknowledged";
154
+ }
155
+ return "open";
156
+ }
157
+
158
+ export function buildRequestAssignments({
159
+ coordinationState,
160
+ agents,
161
+ ledger = null,
162
+ capabilityRouting = {},
163
+ }) {
164
+ const assignments = [];
165
+ for (const record of coordinationState?.requests || []) {
166
+ if (isLauncherSeedRequest(record)) {
167
+ continue;
168
+ }
169
+ if (
170
+ record?.source === "launcher" &&
171
+ (!Array.isArray(record.dependsOn) || record.dependsOn.length === 0) &&
172
+ !String(record.closureCondition || "").trim()
173
+ ) {
174
+ continue;
175
+ }
176
+ const targets = Array.isArray(record.targets) ? record.targets : [];
177
+ if (targets.length === 0) {
178
+ continue;
179
+ }
180
+ for (const target of targets) {
181
+ const resolution = resolveTargetAssignment(target, agents, ledger, capabilityRouting);
182
+ assignments.push({
183
+ id: `assignment:${record.id}:${targetSlug(target) || "target"}`,
184
+ requestId: record.id,
185
+ recordId: record.id,
186
+ sourceKind: record.kind,
187
+ sourceAgentId: record.agentId,
188
+ summary: record.summary || "",
189
+ detail: record.detail || "",
190
+ priority: record.priority || "normal",
191
+ requestStatus: record.status,
192
+ state: assignmentStateForRecord(record),
193
+ target: resolution.target,
194
+ targetType: resolution.targetType,
195
+ capability: resolution.capability,
196
+ assignedAgentId: resolution.assignedAgentId,
197
+ assignmentReason: resolution.assignmentReason,
198
+ assignmentDetail: resolution.detail,
199
+ blocking: isOpenCoordinationStatus(record.status),
200
+ artifactRefs: Array.isArray(record.artifactRefs) ? record.artifactRefs : [],
201
+ dependsOn: Array.isArray(record.dependsOn) ? record.dependsOn : [],
202
+ closureCondition: String(record.closureCondition || ""),
203
+ createdAt: record.createdAt,
204
+ updatedAt: record.updatedAt,
205
+ });
206
+ }
207
+ }
208
+ return assignments;
209
+ }
210
+
211
+ function comparableRecordValue(record, key) {
212
+ return JSON.stringify(record?.[key]);
213
+ }
214
+
215
+ export function syncAssignmentRecords(filePath, { lane, wave, assignments }) {
216
+ const existing = readCoordinationLog(filePath);
217
+ const latestById = materializeCoordinationState(existing).byId;
218
+ const comparableKeys = [
219
+ "kind",
220
+ "wave",
221
+ "lane",
222
+ "agentId",
223
+ "targets",
224
+ "status",
225
+ "priority",
226
+ "artifactRefs",
227
+ "dependsOn",
228
+ "closureCondition",
229
+ "confidence",
230
+ "summary",
231
+ "detail",
232
+ "attempt",
233
+ "source",
234
+ "executorId",
235
+ "requesterLane",
236
+ "ownerLane",
237
+ "requesterWave",
238
+ "ownerWave",
239
+ "required",
240
+ ];
241
+ for (const assignment of assignments || []) {
242
+ const status =
243
+ assignment.state === "resolved"
244
+ ? "resolved"
245
+ : assignment.assignedAgentId
246
+ ? assignment.state === "in_progress"
247
+ ? "in_progress"
248
+ : assignment.state === "acknowledged"
249
+ ? "acknowledged"
250
+ : "open"
251
+ : "open";
252
+ const record = {
253
+ id: assignment.id,
254
+ kind: "decision",
255
+ lane,
256
+ wave,
257
+ agentId: "launcher",
258
+ targets: assignment.assignedAgentId ? [`agent:${assignment.assignedAgentId}`] : [],
259
+ status,
260
+ priority: assignment.priority || "normal",
261
+ artifactRefs: assignment.artifactRefs || [],
262
+ dependsOn: [assignment.requestId, ...(assignment.dependsOn || [])],
263
+ closureCondition: "",
264
+ confidence: assignment.assignedAgentId ? "high" : "medium",
265
+ summary: assignment.assignedAgentId
266
+ ? `Assignment for ${assignment.requestId}: ${assignment.assignedAgentId}`
267
+ : `Assignment unresolved for ${assignment.requestId}`,
268
+ detail: compactSingleLine(
269
+ `target=${assignment.target || "n/a"}; reason=${assignment.assignmentReason || "n/a"}; ${assignment.assignmentDetail || assignment.detail || "No detail."}`,
270
+ 240,
271
+ ),
272
+ source: "launcher",
273
+ };
274
+ const existingRecord = latestById.get(record.id);
275
+ const unchanged =
276
+ existingRecord &&
277
+ comparableKeys.every((key) => comparableRecordValue(existingRecord, key) === comparableRecordValue(record, key));
278
+ if (!unchanged) {
279
+ appendCoordinationRecord(filePath, record, {
280
+ createdAt: existingRecord?.createdAt || toIsoTimestamp(),
281
+ });
282
+ }
283
+ }
284
+ }
285
+
286
+ export function readAllDependencyTickets(dirPath) {
287
+ if (!dirPath || !fs.existsSync(dirPath)) {
288
+ return [];
289
+ }
290
+ return fs
291
+ .readdirSync(dirPath, { withFileTypes: true })
292
+ .filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl"))
293
+ .flatMap((entry) => readCoordinationLog(path.join(dirPath, entry.name)));
294
+ }
295
+
296
+ export function isRequiredDependencyTicket(record) {
297
+ return record?.required === true || String(record?.closureCondition || "").includes("required=true");
298
+ }
299
+
300
+ function isDependencyRelevantToWave(recordWave, waveNumber) {
301
+ return recordWave === null || recordWave === undefined || Number(recordWave) === Number(waveNumber);
302
+ }
303
+
304
+ function buildDependencyAssignment(record, agents, ledger, capabilityRouting) {
305
+ const targets = Array.isArray(record.targets) ? record.targets : [];
306
+ const resolutions = targets.map((target) =>
307
+ resolveTargetAssignment(target, agents, ledger, capabilityRouting),
308
+ );
309
+ const resolved = resolutions.find((item) => item.assignedAgentId);
310
+ return {
311
+ assignedAgentId: resolved?.assignedAgentId || null,
312
+ assignmentReason: resolved?.assignmentReason || (targets.length === 0 ? "untargeted" : "unresolved-target"),
313
+ assignmentDetail:
314
+ resolved?.detail ||
315
+ (targets.length === 0
316
+ ? "Dependency ticket is not targeted to a local agent or capability."
317
+ : resolutions.map((item) => item.detail).join(" ")),
318
+ };
319
+ }
320
+
321
+ function summarizeDependency(record, direction, assignment) {
322
+ return {
323
+ id: record.id,
324
+ direction,
325
+ lane: record.lane,
326
+ requesterLane: record.requesterLane || "",
327
+ ownerLane: record.ownerLane || "",
328
+ requesterWave: record.requesterWave ?? null,
329
+ ownerWave: record.ownerWave ?? null,
330
+ required: isRequiredDependencyTicket(record),
331
+ status: record.status,
332
+ summary: record.summary || "",
333
+ detail: record.detail || "",
334
+ priority: record.priority || "normal",
335
+ targets: Array.isArray(record.targets) ? record.targets : [],
336
+ artifactRefs: Array.isArray(record.artifactRefs) ? record.artifactRefs : [],
337
+ assignedAgentId: assignment?.assignedAgentId || null,
338
+ assignmentReason: assignment?.assignmentReason || null,
339
+ assignmentDetail: assignment?.assignmentDetail || "",
340
+ blocking:
341
+ isRequiredDependencyTicket(record) &&
342
+ isOpenCoordinationStatus(record.status),
343
+ createdAt: record.createdAt,
344
+ updatedAt: record.updatedAt,
345
+ };
346
+ }
347
+
348
+ export function buildDependencySnapshot({
349
+ dirPath,
350
+ lane,
351
+ waveNumber,
352
+ agents = [],
353
+ ledger = null,
354
+ capabilityRouting = {},
355
+ }) {
356
+ const allTickets = readAllDependencyTickets(dirPath);
357
+ const inbound = [];
358
+ const outbound = [];
359
+ for (const record of allTickets) {
360
+ if (
361
+ String(record.ownerLane || record.lane || "").trim() === String(lane).trim() &&
362
+ isDependencyRelevantToWave(record.ownerWave, waveNumber)
363
+ ) {
364
+ inbound.push(
365
+ summarizeDependency(
366
+ record,
367
+ "inbound",
368
+ buildDependencyAssignment(record, agents, ledger, capabilityRouting),
369
+ ),
370
+ );
371
+ }
372
+ if (
373
+ String(record.requesterLane || "").trim() === String(lane).trim() &&
374
+ isDependencyRelevantToWave(record.requesterWave, waveNumber)
375
+ ) {
376
+ outbound.push(summarizeDependency(record, "outbound", null));
377
+ }
378
+ }
379
+ const openInbound = inbound.filter((record) => isOpenCoordinationStatus(record.status));
380
+ const openOutbound = outbound.filter((record) => isOpenCoordinationStatus(record.status));
381
+ const requiredInbound = openInbound.filter((record) => record.required);
382
+ const requiredOutbound = openOutbound.filter((record) => record.required);
383
+ return {
384
+ lane,
385
+ wave: waveNumber,
386
+ generatedAt: toIsoTimestamp(),
387
+ inbound,
388
+ outbound,
389
+ openInbound,
390
+ openOutbound,
391
+ requiredInbound,
392
+ requiredOutbound,
393
+ unresolvedInboundAssignments: requiredInbound.filter((record) => !record.assignedAgentId),
394
+ };
395
+ }
396
+
397
+ export function renderDependencySnapshotMarkdown(snapshot) {
398
+ const renderEntries = (items) =>
399
+ items.length > 0
400
+ ? items.map(
401
+ (item) =>
402
+ `- [${item.priority}] ${item.id} ${item.status}${item.required ? " required" : ""}: ${compactSingleLine(item.summary || item.detail || "dependency", 160)}${item.assignedAgentId ? ` -> ${item.assignedAgentId}` : ""}`,
403
+ )
404
+ : ["- None."];
405
+ return [
406
+ `# Lane ${snapshot?.lane || "unknown"} Dependency Snapshot`,
407
+ "",
408
+ `- Wave: ${snapshot?.wave ?? "n/a"}`,
409
+ `- Generated: ${snapshot?.generatedAt || toIsoTimestamp()}`,
410
+ `- Open inbound: ${(snapshot?.openInbound || []).length}`,
411
+ `- Open outbound: ${(snapshot?.openOutbound || []).length}`,
412
+ `- Required inbound: ${(snapshot?.requiredInbound || []).length}`,
413
+ `- Required outbound: ${(snapshot?.requiredOutbound || []).length}`,
414
+ "",
415
+ "## Inbound",
416
+ ...renderEntries(snapshot?.inbound || []),
417
+ "",
418
+ "## Outbound",
419
+ ...renderEntries(snapshot?.outbound || []),
420
+ "",
421
+ ].join("\n");
422
+ }
423
+
424
+ export function writeDependencySnapshotMarkdown(filePath, snapshot) {
425
+ writeTextAtomic(filePath, `${renderDependencySnapshotMarkdown(snapshot)}\n`);
426
+ }
427
+
428
+ export function buildHelperTasks({
429
+ wave,
430
+ assignments = [],
431
+ dependencySnapshot = null,
432
+ docsQueue = null,
433
+ documentationAgentId = "A9",
434
+ }) {
435
+ const tasks = [];
436
+ for (const assignment of assignments) {
437
+ if (!assignment.blocking) {
438
+ continue;
439
+ }
440
+ tasks.push({
441
+ id: `helper:${assignment.id}`,
442
+ title: assignment.summary || `Follow-up for ${assignment.requestId}`,
443
+ owner: assignment.assignedAgentId || null,
444
+ kind: "helper",
445
+ dependsOn: [assignment.requestId],
446
+ state:
447
+ assignment.state === "resolved"
448
+ ? "done"
449
+ : assignment.assignedAgentId
450
+ ? assignment.state === "in_progress"
451
+ ? "in_progress"
452
+ : assignment.state === "acknowledged"
453
+ ? "acknowledged"
454
+ : "planned"
455
+ : "blocked",
456
+ proofState: "pending",
457
+ docState: "pending",
458
+ infraState: "n/a",
459
+ priority: assignment.priority || "normal",
460
+ artifactRefs: assignment.artifactRefs || [],
461
+ assignment: {
462
+ target: assignment.target,
463
+ targetType: assignment.targetType,
464
+ capability: assignment.capability,
465
+ assignmentReason: assignment.assignmentReason,
466
+ },
467
+ });
468
+ }
469
+ for (const dependency of dependencySnapshot?.inbound || []) {
470
+ if (!isOpenCoordinationStatus(dependency.status)) {
471
+ continue;
472
+ }
473
+ tasks.push({
474
+ id: `dependency:${dependency.id}`,
475
+ title: dependency.summary || `Inbound dependency ${dependency.id}`,
476
+ owner: dependency.assignedAgentId || null,
477
+ kind: "dependency",
478
+ dependsOn: [],
479
+ state:
480
+ dependency.required && !dependency.assignedAgentId
481
+ ? "blocked"
482
+ : dependency.status === "in_progress"
483
+ ? "in_progress"
484
+ : dependency.status === "acknowledged"
485
+ ? "acknowledged"
486
+ : "planned",
487
+ proofState: "pending",
488
+ docState: "pending",
489
+ infraState: "n/a",
490
+ priority: dependency.priority || "high",
491
+ artifactRefs: dependency.artifactRefs || [],
492
+ assignment: {
493
+ target: dependency.targets?.[0] || null,
494
+ targetType:
495
+ dependency.targets?.[0] && String(dependency.targets[0]).startsWith("capability:")
496
+ ? "capability"
497
+ : "agent",
498
+ capability:
499
+ dependency.targets?.[0] && String(dependency.targets[0]).startsWith("capability:")
500
+ ? normalizeCapability(String(dependency.targets[0]).slice("capability:".length))
501
+ : null,
502
+ assignmentReason: dependency.assignmentReason,
503
+ },
504
+ dependency,
505
+ });
506
+ }
507
+ for (const item of docsQueue?.items || []) {
508
+ if (!["shared-plan", "component-matrix"].includes(String(item.kind || ""))) {
509
+ continue;
510
+ }
511
+ tasks.push({
512
+ id: `doc-helper:${item.id}`,
513
+ title: item.summary || `Documentation follow-up for ${item.path || item.id}`,
514
+ owner: item.ownerAgentId || documentationAgentId,
515
+ kind: "documentation-helper",
516
+ dependsOn: [],
517
+ state: "planned",
518
+ proofState: "n/a",
519
+ docState: "pending",
520
+ infraState: "n/a",
521
+ priority: "high",
522
+ artifactRefs: item.path ? [item.path] : [],
523
+ assignment: null,
524
+ });
525
+ }
526
+ const outboundBlocking = (dependencySnapshot?.requiredOutbound || []).map((dependency) => ({
527
+ id: `dependency-outbound:${dependency.id}`,
528
+ title: dependency.summary || `Outbound dependency ${dependency.id}`,
529
+ owner: null,
530
+ kind: "dependency-outbound",
531
+ dependsOn: [],
532
+ state: "blocked",
533
+ proofState: "pending",
534
+ docState: "pending",
535
+ infraState: "n/a",
536
+ priority: dependency.priority || "high",
537
+ artifactRefs: dependency.artifactRefs || [],
538
+ assignment: null,
539
+ dependency,
540
+ }));
541
+ return [...tasks, ...outboundBlocking];
542
+ }