@chllming/wave-orchestration 0.5.4 → 0.6.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 (126) hide show
  1. package/CHANGELOG.md +46 -3
  2. package/README.md +33 -5
  3. package/docs/README.md +18 -4
  4. package/docs/agents/wave-cont-eval-role.md +36 -0
  5. package/docs/agents/{wave-evaluator-role.md → wave-cont-qa-role.md} +14 -11
  6. package/docs/agents/wave-documentation-role.md +1 -1
  7. package/docs/agents/wave-infra-role.md +1 -1
  8. package/docs/agents/wave-integration-role.md +3 -3
  9. package/docs/agents/wave-launcher-role.md +4 -3
  10. package/docs/agents/wave-security-role.md +40 -0
  11. package/docs/concepts/context7-vs-skills.md +1 -1
  12. package/docs/concepts/what-is-a-wave.md +56 -6
  13. package/docs/evals/README.md +166 -0
  14. package/docs/evals/benchmark-catalog.json +663 -0
  15. package/docs/guides/author-and-run-waves.md +135 -0
  16. package/docs/guides/planner.md +5 -0
  17. package/docs/guides/terminal-surfaces.md +2 -0
  18. package/docs/plans/component-cutover-matrix.json +1 -1
  19. package/docs/plans/component-cutover-matrix.md +1 -1
  20. package/docs/plans/current-state.md +19 -1
  21. package/docs/plans/examples/wave-example-live-proof.md +435 -0
  22. package/docs/plans/migration.md +42 -0
  23. package/docs/plans/wave-orchestrator.md +46 -7
  24. package/docs/plans/waves/wave-0.md +4 -4
  25. package/docs/reference/live-proof-waves.md +177 -0
  26. package/docs/reference/migration-0.2-to-0.5.md +26 -19
  27. package/docs/reference/npmjs-trusted-publishing.md +6 -5
  28. package/docs/reference/runtime-config/README.md +13 -3
  29. package/docs/reference/sample-waves.md +87 -0
  30. package/docs/reference/skills.md +110 -42
  31. package/docs/research/agent-context-sources.md +130 -11
  32. package/docs/research/coordination-failure-review.md +266 -0
  33. package/docs/roadmap.md +6 -2
  34. package/package.json +2 -2
  35. package/releases/manifest.json +20 -2
  36. package/scripts/research/agent-context-archive.mjs +83 -1
  37. package/scripts/research/manifests/agent-context-expanded-2026-03-22.mjs +811 -0
  38. package/scripts/wave-orchestrator/adhoc.mjs +1331 -0
  39. package/scripts/wave-orchestrator/agent-state.mjs +358 -6
  40. package/scripts/wave-orchestrator/artifact-schemas.mjs +173 -0
  41. package/scripts/wave-orchestrator/clarification-triage.mjs +10 -3
  42. package/scripts/wave-orchestrator/config.mjs +48 -12
  43. package/scripts/wave-orchestrator/context7.mjs +2 -0
  44. package/scripts/wave-orchestrator/coord-cli.mjs +51 -19
  45. package/scripts/wave-orchestrator/coordination-store.mjs +26 -4
  46. package/scripts/wave-orchestrator/coordination.mjs +83 -9
  47. package/scripts/wave-orchestrator/dashboard-state.mjs +20 -8
  48. package/scripts/wave-orchestrator/dep-cli.mjs +5 -2
  49. package/scripts/wave-orchestrator/docs-queue.mjs +8 -2
  50. package/scripts/wave-orchestrator/evals.mjs +451 -0
  51. package/scripts/wave-orchestrator/feedback.mjs +15 -1
  52. package/scripts/wave-orchestrator/install.mjs +32 -9
  53. package/scripts/wave-orchestrator/launcher-closure.mjs +281 -0
  54. package/scripts/wave-orchestrator/launcher-runtime.mjs +334 -0
  55. package/scripts/wave-orchestrator/launcher.mjs +709 -601
  56. package/scripts/wave-orchestrator/ledger.mjs +123 -20
  57. package/scripts/wave-orchestrator/local-executor.mjs +99 -12
  58. package/scripts/wave-orchestrator/planner.mjs +177 -42
  59. package/scripts/wave-orchestrator/replay.mjs +6 -3
  60. package/scripts/wave-orchestrator/role-helpers.mjs +84 -0
  61. package/scripts/wave-orchestrator/shared.mjs +75 -11
  62. package/scripts/wave-orchestrator/skills.mjs +637 -106
  63. package/scripts/wave-orchestrator/traces.mjs +71 -48
  64. package/scripts/wave-orchestrator/wave-files.mjs +947 -101
  65. package/scripts/wave.mjs +9 -0
  66. package/skills/README.md +202 -0
  67. package/skills/provider-aws/SKILL.md +111 -0
  68. package/skills/provider-aws/adapters/claude.md +1 -0
  69. package/skills/provider-aws/adapters/codex.md +1 -0
  70. package/skills/provider-aws/references/service-verification.md +39 -0
  71. package/skills/provider-aws/skill.json +50 -1
  72. package/skills/provider-custom-deploy/SKILL.md +59 -0
  73. package/skills/provider-custom-deploy/skill.json +46 -1
  74. package/skills/provider-docker-compose/SKILL.md +90 -0
  75. package/skills/provider-docker-compose/adapters/local.md +1 -0
  76. package/skills/provider-docker-compose/skill.json +49 -1
  77. package/skills/provider-github-release/SKILL.md +116 -1
  78. package/skills/provider-github-release/adapters/claude.md +1 -0
  79. package/skills/provider-github-release/adapters/codex.md +1 -0
  80. package/skills/provider-github-release/skill.json +51 -1
  81. package/skills/provider-kubernetes/SKILL.md +137 -0
  82. package/skills/provider-kubernetes/adapters/claude.md +1 -0
  83. package/skills/provider-kubernetes/adapters/codex.md +1 -0
  84. package/skills/provider-kubernetes/references/kubectl-patterns.md +58 -0
  85. package/skills/provider-kubernetes/skill.json +48 -1
  86. package/skills/provider-railway/SKILL.md +118 -1
  87. package/skills/provider-railway/references/verification-commands.md +39 -0
  88. package/skills/provider-railway/skill.json +67 -1
  89. package/skills/provider-ssh-manual/SKILL.md +91 -0
  90. package/skills/provider-ssh-manual/skill.json +50 -1
  91. package/skills/repo-coding-rules/SKILL.md +84 -0
  92. package/skills/repo-coding-rules/skill.json +30 -1
  93. package/skills/role-cont-eval/SKILL.md +90 -0
  94. package/skills/role-cont-eval/adapters/codex.md +1 -0
  95. package/skills/role-cont-eval/skill.json +36 -0
  96. package/skills/role-cont-qa/SKILL.md +93 -0
  97. package/skills/role-cont-qa/adapters/claude.md +1 -0
  98. package/skills/role-cont-qa/skill.json +36 -0
  99. package/skills/role-deploy/SKILL.md +90 -0
  100. package/skills/role-deploy/skill.json +32 -1
  101. package/skills/role-documentation/SKILL.md +66 -0
  102. package/skills/role-documentation/skill.json +32 -1
  103. package/skills/role-implementation/SKILL.md +62 -0
  104. package/skills/role-implementation/skill.json +32 -1
  105. package/skills/role-infra/SKILL.md +74 -0
  106. package/skills/role-infra/skill.json +32 -1
  107. package/skills/role-integration/SKILL.md +79 -1
  108. package/skills/role-integration/skill.json +32 -1
  109. package/skills/role-research/SKILL.md +58 -0
  110. package/skills/role-research/skill.json +32 -1
  111. package/skills/role-security/SKILL.md +60 -0
  112. package/skills/role-security/skill.json +36 -0
  113. package/skills/runtime-claude/SKILL.md +60 -1
  114. package/skills/runtime-claude/skill.json +32 -1
  115. package/skills/runtime-codex/SKILL.md +52 -1
  116. package/skills/runtime-codex/skill.json +32 -1
  117. package/skills/runtime-local/SKILL.md +39 -0
  118. package/skills/runtime-local/skill.json +32 -1
  119. package/skills/runtime-opencode/SKILL.md +51 -0
  120. package/skills/runtime-opencode/skill.json +32 -1
  121. package/skills/wave-core/SKILL.md +107 -0
  122. package/skills/wave-core/references/marker-syntax.md +62 -0
  123. package/skills/wave-core/skill.json +31 -1
  124. package/wave.config.json +35 -6
  125. package/skills/role-evaluator/SKILL.md +0 -6
  126. package/skills/role-evaluator/skill.json +0 -5
@@ -1,13 +1,20 @@
1
1
  import {
2
+ DEFAULT_CONT_EVAL_AGENT_ID,
2
3
  DEFAULT_DOCUMENTATION_AGENT_ID,
3
- DEFAULT_EVALUATOR_AGENT_ID,
4
+ DEFAULT_CONT_QA_AGENT_ID,
4
5
  DEFAULT_INTEGRATION_AGENT_ID,
5
6
  } from "./config.mjs";
6
7
  import {
8
+ validateContEvalSummary,
7
9
  validateDocumentationClosureSummary,
8
- validateEvaluatorSummary,
10
+ validateContQaSummary,
9
11
  validateImplementationSummary,
12
+ validateSecuritySummary,
10
13
  } from "./agent-state.mjs";
14
+ import {
15
+ isContEvalImplementationOwningAgent,
16
+ isSecurityReviewAgent,
17
+ } from "./role-helpers.mjs";
11
18
  import { openClarificationLinkedRequests } from "./coordination-store.mjs";
12
19
  import { buildHelperTasks } from "./routing-state.mjs";
13
20
  import { readJsonOrNull, toIsoTimestamp, writeJsonAtomic } from "./shared.mjs";
@@ -40,19 +47,24 @@ function openClarifications(state) {
40
47
  export function buildSeedWaveLedger({
41
48
  lane,
42
49
  wave,
43
- evaluatorAgentId = DEFAULT_EVALUATOR_AGENT_ID,
50
+ contQaAgentId = DEFAULT_CONT_QA_AGENT_ID,
51
+ contEvalAgentId = DEFAULT_CONT_EVAL_AGENT_ID,
44
52
  integrationAgentId = DEFAULT_INTEGRATION_AGENT_ID,
45
53
  documentationAgentId = DEFAULT_DOCUMENTATION_AGENT_ID,
46
54
  }) {
47
55
  const tasks = [];
48
56
  for (const agent of wave.agents) {
49
57
  const kind =
50
- agent.agentId === evaluatorAgentId
51
- ? "evaluator"
58
+ agent.agentId === contQaAgentId
59
+ ? "cont-qa"
60
+ : agent.agentId === contEvalAgentId
61
+ ? "cont-eval"
52
62
  : agent.agentId === integrationAgentId
53
63
  ? "integration"
54
- : agent.agentId === documentationAgentId
64
+ : agent.agentId === documentationAgentId
55
65
  ? "documentation"
66
+ : isSecurityReviewAgent(agent)
67
+ ? "security"
56
68
  : "implementation";
57
69
  tasks.push({
58
70
  id: taskId(kind, agent.agentId),
@@ -73,6 +85,8 @@ export function buildSeedWaveLedger({
73
85
  role: agent.executorResolved.role,
74
86
  profile: agent.executorResolved.profile,
75
87
  selectedBy: agent.executorResolved.selectedBy,
88
+ retryPolicy: agent.executorResolved.retryPolicy || null,
89
+ allowFallbackOnRetry: agent.executorResolved.allowFallbackOnRetry !== false,
76
90
  fallbacks: agent.executorResolved.fallbacks || [],
77
91
  fallbackUsed: agent.executorResolved.fallbackUsed === true,
78
92
  }
@@ -107,9 +121,11 @@ export function buildSeedWaveLedger({
107
121
  clarificationLinkedRequests: [],
108
122
  humanFeedback: [],
109
123
  humanEscalations: [],
124
+ contEvalState: "pending",
125
+ securityState: "pending",
110
126
  integrationState: "pending",
111
127
  docClosureState: "pending",
112
- evaluatorState: "pending",
128
+ contQaState: "pending",
113
129
  updatedAt: toIsoTimestamp(),
114
130
  };
115
131
  }
@@ -117,8 +133,10 @@ export function buildSeedWaveLedger({
117
133
  function derivePhase({
118
134
  tasks,
119
135
  integrationSummary,
136
+ contEvalValidation,
137
+ securityValidation,
120
138
  docValidation,
121
- evaluatorValidation,
139
+ contQaValidation,
122
140
  state,
123
141
  dependencySnapshot = null,
124
142
  }) {
@@ -149,14 +167,20 @@ function derivePhase({
149
167
  if (!allImplementationDone) {
150
168
  return "running";
151
169
  }
170
+ if (tasks.some((task) => task.kind === "cont-eval") && !contEvalValidation?.ok) {
171
+ return "cont-eval";
172
+ }
173
+ if (tasks.some((task) => task.kind === "security") && !securityValidation?.ok) {
174
+ return "security-review";
175
+ }
152
176
  if (integrationSummary?.recommendation !== "ready-for-doc-closure") {
153
177
  return "integrating";
154
178
  }
155
179
  if (!docValidation?.ok) {
156
180
  return "docs-closure";
157
181
  }
158
- if (!evaluatorValidation?.ok) {
159
- return "evaluator-closure";
182
+ if (!contQaValidation?.ok) {
183
+ return "cont-qa-closure";
160
184
  }
161
185
  return "completed";
162
186
  }
@@ -169,16 +193,19 @@ export function deriveWaveLedger({
169
193
  integrationSummary = null,
170
194
  docsQueue = null,
171
195
  attempt = 0,
172
- evaluatorAgentId = DEFAULT_EVALUATOR_AGENT_ID,
196
+ contQaAgentId = DEFAULT_CONT_QA_AGENT_ID,
197
+ contEvalAgentId = DEFAULT_CONT_EVAL_AGENT_ID,
173
198
  integrationAgentId = DEFAULT_INTEGRATION_AGENT_ID,
174
199
  documentationAgentId = DEFAULT_DOCUMENTATION_AGENT_ID,
200
+ benchmarkCatalogPath = null,
175
201
  capabilityAssignments = [],
176
202
  dependencySnapshot = null,
177
203
  }) {
178
204
  const seed = buildSeedWaveLedger({
179
205
  lane,
180
206
  wave,
181
- evaluatorAgentId,
207
+ contQaAgentId,
208
+ contEvalAgentId,
182
209
  integrationAgentId,
183
210
  documentationAgentId,
184
211
  });
@@ -203,8 +230,38 @@ export function deriveWaveLedger({
203
230
  docState: validation.ok ? "closed" : "open",
204
231
  };
205
232
  }
206
- if (task.kind === "evaluator" && agent) {
207
- const validation = validateEvaluatorSummary(agent, summary);
233
+ if (task.kind === "cont-eval" && agent) {
234
+ const evalValidation = validateContEvalSummary(agent, summary, {
235
+ mode: "live",
236
+ evalTargets: wave.evalTargets,
237
+ benchmarkCatalogPath,
238
+ });
239
+ const implementationValidation = isContEvalImplementationOwningAgent(agent, {
240
+ contEvalAgentId,
241
+ })
242
+ ? validateImplementationSummary(agent, summary)
243
+ : { ok: true, statusCode: "pass", detail: "cont-EVAL is report-only." };
244
+ const validation = !evalValidation.ok ? evalValidation : implementationValidation;
245
+ return {
246
+ ...task,
247
+ state: taskStateFromValidation(validation),
248
+ proofState: validation.ok ? "met" : "gap",
249
+ docState: "n/a",
250
+ };
251
+ }
252
+ if (task.kind === "cont-qa" && agent) {
253
+ const validation = validateContQaSummary(agent, summary, {
254
+ mode: "live",
255
+ });
256
+ return {
257
+ ...task,
258
+ state: taskStateFromValidation(validation),
259
+ proofState: validation.ok ? "met" : "gap",
260
+ docState: "n/a",
261
+ };
262
+ }
263
+ if (task.kind === "security" && agent) {
264
+ const validation = validateSecuritySummary(agent, summary);
208
265
  return {
209
266
  ...task,
210
267
  state: taskStateFromValidation(validation),
@@ -255,12 +312,54 @@ export function deriveWaveLedger({
255
312
  });
256
313
  const tasks = [...primaryTasks, ...helperTasks];
257
314
  const docAgent = wave.agents.find((agent) => agent.agentId === documentationAgentId);
258
- const evaluatorAgent = wave.agents.find((agent) => agent.agentId === evaluatorAgentId);
315
+ const contEvalAgent = wave.agents.find((agent) => agent.agentId === contEvalAgentId);
316
+ const contQaAgent = wave.agents.find((agent) => agent.agentId === contQaAgentId);
317
+ const securityAgents = (wave.agents || []).filter((agent) => isSecurityReviewAgent(agent));
318
+ const contEvalValidation = (() => {
319
+ if (!contEvalAgent) {
320
+ return { ok: true };
321
+ }
322
+ const summary = summariesByAgentId[contEvalAgentId];
323
+ const evalValidation = validateContEvalSummary(contEvalAgent, summary, {
324
+ mode: "live",
325
+ evalTargets: wave.evalTargets,
326
+ benchmarkCatalogPath,
327
+ });
328
+ if (!evalValidation.ok) {
329
+ return evalValidation;
330
+ }
331
+ if (
332
+ isContEvalImplementationOwningAgent(contEvalAgent, {
333
+ contEvalAgentId,
334
+ })
335
+ ) {
336
+ return validateImplementationSummary(contEvalAgent, summary);
337
+ }
338
+ return evalValidation;
339
+ })();
259
340
  const docValidation = docAgent
260
341
  ? validateDocumentationClosureSummary(docAgent, summariesByAgentId[documentationAgentId])
261
342
  : { ok: true };
262
- const evaluatorValidation = evaluatorAgent
263
- ? validateEvaluatorSummary(evaluatorAgent, summariesByAgentId[evaluatorAgentId])
343
+ const securityValidation = (() => {
344
+ if (securityAgents.length === 0) {
345
+ return { ok: true, statusCode: "pass" };
346
+ }
347
+ for (const agent of securityAgents) {
348
+ const validation = validateSecuritySummary(agent, summariesByAgentId[agent.agentId]);
349
+ if (!validation.ok) {
350
+ return validation;
351
+ }
352
+ }
353
+ return securityAgents.some(
354
+ (agent) => summariesByAgentId[agent.agentId]?.security?.state === "concerns",
355
+ )
356
+ ? { ok: true, statusCode: "security-concerns" }
357
+ : { ok: true, statusCode: "pass" };
358
+ })();
359
+ const contQaValidation = contQaAgent
360
+ ? validateContQaSummary(contQaAgent, summariesByAgentId[contQaAgentId], {
361
+ mode: "live",
362
+ })
264
363
  : { ok: true };
265
364
  return {
266
365
  wave: wave.wave,
@@ -269,8 +368,10 @@ export function deriveWaveLedger({
269
368
  phase: derivePhase({
270
369
  tasks,
271
370
  integrationSummary,
371
+ contEvalValidation,
372
+ securityValidation,
272
373
  docValidation,
273
- evaluatorValidation,
374
+ contQaValidation,
274
375
  state: coordinationState,
275
376
  dependencySnapshot,
276
377
  }),
@@ -311,14 +412,16 @@ export function deriveWaveLedger({
311
412
  .map((record) => record.id),
312
413
  ...(coordinationState?.humanEscalations || [])
313
414
  .filter((record) => ["open", "acknowledged", "in_progress"].includes(record.status))
314
- .map((record) => record.id),
415
+ .map((record) => record.id),
315
416
  ],
316
417
  humanEscalations: (coordinationState?.humanEscalations || [])
317
418
  .filter((record) => ["open", "acknowledged", "in_progress"].includes(record.status))
318
419
  .map((record) => record.id),
420
+ contEvalState: contEvalValidation.ok ? "pass" : "open",
421
+ securityState: securityValidation.ok ? securityValidation.statusCode || "pass" : "open",
319
422
  integrationState: integrationSummary?.recommendation || "pending",
320
423
  docClosureState: docValidation.ok ? "closed" : "open",
321
- evaluatorState: evaluatorValidation.ok ? "pass" : "open",
424
+ contQaState: contQaValidation.ok ? "pass" : "open",
322
425
  updatedAt: toIsoTimestamp(),
323
426
  };
324
427
  }
@@ -1,6 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { REPO_ROOT, ensureDirectory } from "./shared.mjs";
4
+ import { isContEvalReportPath } from "./role-helpers.mjs";
4
5
 
5
6
  function titleFromPath(relPath) {
6
7
  return path
@@ -22,7 +23,8 @@ function extractAgentId(rawPrompt) {
22
23
  }
23
24
 
24
25
  function extractRoleAgentIds(rawPrompt) {
25
- const evaluatorMatch = String(rawPrompt || "").match(/- Evaluator agent id:\s*([A-Za-z0-9.]+)/);
26
+ const contQaMatch = String(rawPrompt || "").match(/- cont-QA agent id:\s*([A-Za-z0-9.]+)/);
27
+ const contEvalMatch = String(rawPrompt || "").match(/- cont-EVAL agent id:\s*([A-Za-z0-9.]+)/);
26
28
  const integrationMatch = String(rawPrompt || "").match(
27
29
  /- Integration steward agent id:\s*([A-Za-z0-9.]+)/,
28
30
  );
@@ -30,7 +32,8 @@ function extractRoleAgentIds(rawPrompt) {
30
32
  /- Documentation steward agent id:\s*([A-Za-z0-9.]+)/,
31
33
  );
32
34
  return {
33
- evaluatorAgentId: evaluatorMatch ? evaluatorMatch[1].trim() : "A0",
35
+ contQaAgentId: contQaMatch ? contQaMatch[1].trim() : "A0",
36
+ contEvalAgentId: contEvalMatch ? contEvalMatch[1].trim() : "E0",
34
37
  integrationAgentId: integrationMatch ? integrationMatch[1].trim() : "A8",
35
38
  documentationAgentId: documentationMatch ? documentationMatch[1].trim() : "A9",
36
39
  };
@@ -114,6 +117,62 @@ function extractDeliverables(rawPrompt, promptText) {
114
117
  return Array.from(new Set(out));
115
118
  }
116
119
 
120
+ function extractFileOwnershipPaths(promptText) {
121
+ return Array.from(
122
+ new Set(extractDeliverablesFromList(promptText, /^\s*File ownership\b/i)),
123
+ );
124
+ }
125
+
126
+ function extractEvalMarkerPayload(rawPrompt) {
127
+ const lines = String(rawPrompt || "").split(/\r?\n/);
128
+ const targetIds = [];
129
+ const benchmarkIds = [];
130
+ let inTargets = false;
131
+ for (const line of lines) {
132
+ if (/^\s*Eval targets for this wave:\s*$/i.test(line)) {
133
+ inTargets = true;
134
+ continue;
135
+ }
136
+ if (inTargets && !line.trim()) {
137
+ break;
138
+ }
139
+ if (!inTargets) {
140
+ continue;
141
+ }
142
+ const match = line.match(/^\s*-\s+([a-z0-9._-]+):\s+(.+)\s*$/i);
143
+ if (!match) {
144
+ continue;
145
+ }
146
+ targetIds.push(match[1].toLowerCase());
147
+ const payload = match[2];
148
+ const benchmarkMatch =
149
+ payload.match(/\bbenchmarks=([a-z0-9._\-,\s]+)/i) ||
150
+ payload.match(/\ballowed-benchmarks=([a-z0-9._\-,\s]+)/i);
151
+ if (!benchmarkMatch) {
152
+ continue;
153
+ }
154
+ for (const benchmarkId of benchmarkMatch[1].split(",")) {
155
+ const normalized = benchmarkId.trim().toLowerCase();
156
+ if (normalized) {
157
+ benchmarkIds.push(normalized);
158
+ }
159
+ }
160
+ }
161
+ return {
162
+ targetIds: Array.from(new Set(targetIds)).sort(),
163
+ benchmarkIds: Array.from(new Set(benchmarkIds)).sort(),
164
+ };
165
+ }
166
+
167
+ function formatWaveEvalLine(evalMarker, detail) {
168
+ const targetIds = Array.isArray(evalMarker?.targetIds) ? evalMarker.targetIds : [];
169
+ const benchmarkIds = Array.isArray(evalMarker?.benchmarkIds) ? evalMarker.benchmarkIds : [];
170
+ const targetIdSegment = targetIds.length > 0 ? ` target_ids=${targetIds.join(",")}` : "";
171
+ const benchmarkIdSegment =
172
+ benchmarkIds.length > 0 ? ` benchmark_ids=${benchmarkIds.join(",")}` : "";
173
+ return `[wave-eval] state=satisfied targets=${targetIds.length} benchmarks=${benchmarkIds.length} regressions=0${targetIdSegment}${benchmarkIdSegment} detail=${detail}`;
174
+ }
175
+
117
176
  export function resolveRepoOwnedDeliverablePath(relPath) {
118
177
  if (!relPath || path.isAbsolute(relPath)) {
119
178
  throw new Error(`Unsafe deliverable path: ${String(relPath || "")}`);
@@ -146,7 +205,7 @@ function markdownTemplate(relPath, promptText, options = {}) {
146
205
  ? requirements.map((item) => `- ${item}`)
147
206
  : ["- Derived from assigned wave prompt."]),
148
207
  "",
149
- ...(options.evaluatorReport ? ["## Verdict", "Verdict: PASS", ""] : []),
208
+ ...(options.contQaReport ? ["## Verdict", "Verdict: PASS", ""] : []),
150
209
  "## Note",
151
210
  "- Replace this placeholder with real implementation work before relying on it.",
152
211
  "",
@@ -170,12 +229,12 @@ function writeDeliverable(relPath, promptText, options = {}) {
170
229
  return "exists";
171
230
  }
172
231
  if (/\.(md|mdx)$/i.test(absPath)) {
173
- const evaluatorReport =
174
- options.evaluatorAgent === true &&
175
- /(?:^|\/)(?:reviews?|.*evaluator).*\.(md|mdx)$/i.test(relPath);
232
+ const contQaReport =
233
+ options.contQaAgent === true &&
234
+ /(?:^|\/)(?:reviews?|.*cont[-_]?qa).*\.(md|mdx)$/i.test(relPath);
176
235
  fs.writeFileSync(
177
236
  absPath,
178
- `${markdownTemplate(relPath, promptText, { evaluatorReport })}\n`,
237
+ `${markdownTemplate(relPath, promptText, { contQaReport })}\n`,
179
238
  "utf8",
180
239
  );
181
240
  return "created";
@@ -213,19 +272,34 @@ export function runLocalExecutorCli(argv) {
213
272
  }
214
273
  const rawPrompt = fs.readFileSync(options.promptFile, "utf8");
215
274
  const agentId = extractAgentId(rawPrompt);
216
- const { evaluatorAgentId, integrationAgentId, documentationAgentId } = extractRoleAgentIds(rawPrompt);
217
- const evaluatorAgent = agentId === evaluatorAgentId;
275
+ const { contQaAgentId, contEvalAgentId, integrationAgentId, documentationAgentId } =
276
+ extractRoleAgentIds(rawPrompt);
277
+ const contQaAgent = agentId === contQaAgentId;
278
+ const contEvalAgent = agentId === contEvalAgentId;
218
279
  const integrationAgent = agentId === integrationAgentId;
219
280
  const ownedComponents = extractOwnedComponents(rawPrompt);
220
281
  const assignedPrompt = extractAssignedPrompt(rawPrompt);
282
+ const ownedPaths = extractFileOwnershipPaths(assignedPrompt);
221
283
  const deliverables = extractDeliverables(rawPrompt, assignedPrompt);
284
+ const evalMarker = extractEvalMarkerPayload(rawPrompt);
285
+ const contEvalImplementationOwning =
286
+ contEvalAgent &&
287
+ ownedPaths.some((ownedPath) => !isContEvalReportPath(ownedPath));
222
288
  if (deliverables.length === 0) {
223
289
  console.log("[local-executor] no deliverables detected; nothing to do.");
224
- if (evaluatorAgent) {
290
+ if (contQaAgent) {
225
291
  console.log(
226
292
  "[wave-gate] architecture=pass integration=pass durability=pass live=pass docs=pass detail=local-executor-no-deliverables",
227
293
  );
228
294
  console.log("[wave-verdict] pass detail=local-executor-no-deliverables");
295
+ } else if (contEvalAgent) {
296
+ console.log(formatWaveEvalLine(evalMarker, "local-executor-no-deliverables"));
297
+ if (contEvalImplementationOwning) {
298
+ console.log(
299
+ "[wave-proof] completion=contract durability=none proof=unit state=met detail=local-executor-no-deliverables",
300
+ );
301
+ console.log("[wave-doc-delta] state=none detail=local-executor-no-deliverables");
302
+ }
229
303
  } else if (integrationAgent) {
230
304
  console.log(
231
305
  "[wave-integration] state=ready-for-doc-closure claims=0 conflicts=0 blockers=0 detail=local-executor-no-deliverables",
@@ -249,14 +323,27 @@ export function runLocalExecutorCli(argv) {
249
323
  console.log(`[local-executor] deliverables=${deliverables.join(", ")}`);
250
324
  for (const deliverable of deliverables) {
251
325
  console.log(
252
- `[local-executor] ${writeDeliverable(deliverable, assignedPrompt, { evaluatorAgent })}: ${deliverable}`,
326
+ `[local-executor] ${writeDeliverable(deliverable, assignedPrompt, { contQaAgent })}: ${deliverable}`,
253
327
  );
254
328
  }
255
- if (evaluatorAgent) {
329
+ if (contQaAgent) {
256
330
  console.log(
257
331
  "[wave-gate] architecture=pass integration=pass durability=pass live=pass docs=pass detail=local-executor-smoke",
258
332
  );
259
333
  console.log("[wave-verdict] pass detail=local-executor-smoke");
334
+ } else if (contEvalAgent) {
335
+ console.log(formatWaveEvalLine(evalMarker, "local-executor-smoke"));
336
+ if (contEvalImplementationOwning) {
337
+ console.log(
338
+ "[wave-proof] completion=contract durability=none proof=unit state=met detail=local-executor-smoke",
339
+ );
340
+ console.log("[wave-doc-delta] state=none detail=local-executor-smoke");
341
+ for (const component of ownedComponents) {
342
+ console.log(
343
+ `[wave-component] component=${component.componentId} level=${component.level || "repo-landed"} state=met detail=local-executor-smoke`,
344
+ );
345
+ }
346
+ }
260
347
  } else if (integrationAgent) {
261
348
  console.log(
262
349
  "[wave-integration] state=ready-for-doc-closure claims=0 conflicts=0 blockers=0 detail=local-executor-smoke",