agent-dealer 1.2.7 → 1.2.8

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 (87) hide show
  1. package/bundle/server/dist/adapters/agent-deck-bind.js +16 -6
  2. package/bundle/server/dist/adapters/agent-deck-bind.test.js +74 -0
  3. package/bundle/server/dist/adapters/agent-health.js +14 -3
  4. package/bundle/server/dist/adapters/github.js +4 -1
  5. package/bundle/server/dist/adapters/muse-capability.js +443 -24
  6. package/bundle/server/dist/adapters/muse-capability.test.js +469 -25
  7. package/bundle/server/dist/adapters/muse-visual-qa.js +114 -0
  8. package/bundle/server/dist/adapters/muse-visual-qa.test.js +68 -0
  9. package/bundle/server/dist/capacity/muse-probe.js +56 -9
  10. package/bundle/server/dist/capacity/muse-probe.test.js +188 -1
  11. package/bundle/server/dist/coordinator/admission.js +14 -1
  12. package/bundle/server/dist/coordinator/admission.test.js +197 -4
  13. package/bundle/server/dist/coordinator/auto-merge.integration.test.js +276 -0
  14. package/bundle/server/dist/coordinator/auto-merge.js +39 -3
  15. package/bundle/server/dist/coordinator/commands.js +90 -5
  16. package/bundle/server/dist/coordinator/deck-outage.integration.test.js +4 -2
  17. package/bundle/server/dist/coordinator/developer-effect.js +79 -1
  18. package/bundle/server/dist/coordinator/execution-report.js +6 -0
  19. package/bundle/server/dist/coordinator/execution-report.test.js +7 -0
  20. package/bundle/server/dist/coordinator/failure-cause.js +64 -1
  21. package/bundle/server/dist/coordinator/failure-cause.test.js +92 -1
  22. package/bundle/server/dist/coordinator/failure-reason.js +7 -0
  23. package/bundle/server/dist/coordinator/failure-reason.test.js +14 -0
  24. package/bundle/server/dist/coordinator/human-resolution.js +17 -1
  25. package/bundle/server/dist/coordinator/merge-conflict-sync.js +647 -0
  26. package/bundle/server/dist/coordinator/merge-conflict-sync.test.js +121 -0
  27. package/bundle/server/dist/coordinator/muse-developer.integration.test.js +9 -4
  28. package/bundle/server/dist/coordinator/muse-spawn.js +122 -29
  29. package/bundle/server/dist/coordinator/muse-spawn.test.js +210 -0
  30. package/bundle/server/dist/coordinator/playbook-feedback.js +690 -0
  31. package/bundle/server/dist/coordinator/playbook-feedback.test.js +702 -0
  32. package/bundle/server/dist/coordinator/prompts-execution-contract.test.js +107 -0
  33. package/bundle/server/dist/coordinator/prompts.js +78 -2
  34. package/bundle/server/dist/coordinator/prompts.test.js +83 -0
  35. package/bundle/server/dist/coordinator/reflect-trigger.js +33 -169
  36. package/bundle/server/dist/coordinator/reflect-trigger.test.js +149 -200
  37. package/bundle/server/dist/coordinator/reviewer-effect.js +10 -1
  38. package/bundle/server/dist/coordinator/reviewer-result.js +6 -0
  39. package/bundle/server/dist/coordinator/routing.test.js +14 -0
  40. package/bundle/server/dist/coordinator/session-timeouts.js +30 -0
  41. package/bundle/server/dist/coordinator/usage-cap.integration.test.js +1 -1
  42. package/bundle/server/dist/coordinator/worker-loop.js +18 -4
  43. package/bundle/server/dist/db/index.js +5 -0
  44. package/bundle/server/dist/db/schema.sql +3 -0
  45. package/bundle/server/dist/docs-execution-analysis.test.js +1 -0
  46. package/bundle/server/dist/repository/artifacts-for-issue.js +3 -3
  47. package/bundle/server/dist/repository/human-actions.js +14 -0
  48. package/bundle/server/dist/repository/issues.js +29 -4
  49. package/bundle/server/dist/repository/worker-sessions.js +51 -2
  50. package/bundle/server/dist/routes/human-actions.js +10 -8
  51. package/bundle/server/dist/routes/issues-execution-contract.test.js +321 -0
  52. package/bundle/server/dist/routes/issues.js +19 -2
  53. package/bundle/server/dist/runners/muse-code-jsonl.js +106 -11
  54. package/bundle/server/dist/runners/muse-config-core.js +18 -1
  55. package/bundle/server/dist/runners/muse-config.test.js +37 -0
  56. package/bundle/server/dist/runners/muse-serve-session.js +5 -0
  57. package/bundle/server/dist/runners/spawn-cli.js +116 -0
  58. package/bundle/server/dist/runners/spawn-cli.test.js +124 -0
  59. package/bundle/server/package.json +2 -2
  60. package/bundle/server/static-ui/assets/{index-yLyxRd-7.js → index-B6SVCzMR.js} +14 -14
  61. package/bundle/server/static-ui/assets/{index-DyAJNyfV.css → index-K_YcYkQU.css} +1 -1
  62. package/bundle/server/static-ui/index.html +2 -2
  63. package/bundle/shared/dist/execution-analysis.d.ts +22 -22
  64. package/bundle/shared/dist/execution-contract.d.ts +117 -0
  65. package/bundle/shared/dist/execution-contract.js +307 -0
  66. package/bundle/shared/dist/execution-contract.test.d.ts +2 -0
  67. package/bundle/shared/dist/execution-contract.test.js +499 -0
  68. package/bundle/shared/dist/execution-report.d.ts +9 -9
  69. package/bundle/shared/dist/execution-report.js +2 -0
  70. package/bundle/shared/dist/failure-cause.d.ts +4 -4
  71. package/bundle/shared/dist/failure-cause.js +2 -0
  72. package/bundle/shared/dist/human-actions.d.ts +4 -4
  73. package/bundle/shared/dist/human-actions.js +9 -0
  74. package/bundle/shared/dist/index.d.ts +85 -84
  75. package/bundle/shared/dist/index.js +3 -0
  76. package/bundle/shared/dist/issues.d.ts +146 -16
  77. package/bundle/shared/dist/issues.js +8 -0
  78. package/bundle/shared/dist/issues.test.js +1 -0
  79. package/bundle/shared/dist/outbound-draft.d.ts +12 -12
  80. package/bundle/shared/dist/worker-sessions.d.ts +10 -0
  81. package/bundle/shared/dist/worker-sessions.js +8 -0
  82. package/bundle/shared/dist/worker-sessions.test.js +1 -0
  83. package/bundle/shared/dist/workflow.d.ts +4 -4
  84. package/bundle/shared/dist/workflow.js +10 -0
  85. package/bundle/shared/dist/workflow.test.js +2 -0
  86. package/bundle/shared/package.json +1 -1
  87. package/package.json +1 -1
@@ -0,0 +1,499 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { compileExecutionContract, ExecutionContractError, hasExecutionContractSignal, renderContractAcceptanceCriteria, resolveIssueContractFields, } from "./execution-contract.js";
4
+ /** Planner-authored Linear ticket carrying every contract-v1 heading. */
5
+ export const FULL_CONTRACT_DESCRIPTION = `Ship the frozen execution contract for Planner tickets.
6
+
7
+ ## Builder execution mode
8
+ feature
9
+
10
+ ## Non-goals
11
+ - Selecting a playbook or reasoning about implementation architecture
12
+ - Adding a generic workflow/schema editor
13
+
14
+ ## Exit predicate
15
+ Importing a Planner-authored Linear ticket yields a versioned frozen execution contract visible in Dealer and both worker prompts.
16
+
17
+ ## One-PR stopping point
18
+ Stop after the contract compiles from ticket Markdown, persists/freezes with the Issue workflow, appears read-only in Issue Detail, and renders in developer/reviewer prompts.
19
+
20
+ ## Acceptance criteria
21
+ - [ ] Full ticket imports into the exact structured schema
22
+ Evidence: shared compiler fixtures | run the compiler test | every field asserted
23
+ - [ ] Legacy issues without headings still start
24
+ Evidence: migration tests | run the legacy suite | green
25
+ `;
26
+ test("a full contract description compiles into the exact structured schema", () => {
27
+ const { contract, acceptanceCriteria, hasContractHeadings } = compileExecutionContract(FULL_CONTRACT_DESCRIPTION);
28
+ assert.equal(hasContractHeadings, true);
29
+ assert.deepStrictEqual(contract, {
30
+ version: "v1",
31
+ executionMode: "feature",
32
+ nonGoals: [
33
+ "Selecting a playbook or reasoning about implementation architecture",
34
+ "Adding a generic workflow/schema editor",
35
+ ],
36
+ exitPredicate: "Importing a Planner-authored Linear ticket yields a versioned frozen execution contract visible in Dealer and both worker prompts.",
37
+ onePrStoppingPoint: "Stop after the contract compiles from ticket Markdown, persists/freezes with the Issue workflow, appears read-only in Issue Detail, and renders in developer/reviewer prompts.",
38
+ acceptanceCriteria: [
39
+ {
40
+ text: "Full ticket imports into the exact structured schema",
41
+ evidence: "shared compiler fixtures | run the compiler test | every field asserted",
42
+ },
43
+ {
44
+ text: "Legacy issues without headings still start",
45
+ evidence: "migration tests | run the legacy suite | green",
46
+ },
47
+ ],
48
+ });
49
+ assert.equal(acceptanceCriteria, [
50
+ "- [ ] Full ticket imports into the exact structured schema",
51
+ " Evidence: shared compiler fixtures | run the compiler test | every field asserted",
52
+ "- [ ] Legacy issues without headings still start",
53
+ " Evidence: migration tests | run the legacy suite | green",
54
+ ].join("\n"));
55
+ });
56
+ /**
57
+ * Verbatim copy of the NOT-306 ticket's contract sections: `Feature.` mode
58
+ * (trailing full stop, as Planner writes it) and nested `* Evidence:` bullets
59
+ * (the Planner/Linear list format). The full task message repeats some
60
+ * headings in its trailing checklist, so verbatim here means the ticket's
61
+ * contract sections exactly as authored — one of each canonical heading.
62
+ */
63
+ const NOT306_VERBATIM_DESCRIPTION = `Compile a Planner-authored Linear ticket into a frozen, machine-readable Agent Dealer execution contract without asking the operator to fill another technical form.
64
+
65
+ ## Builder execution mode
66
+ Feature.
67
+
68
+ ## Non-goals
69
+ * Making Dealer select a playbook or reason about implementation architecture.
70
+ * Adding a generic workflow/schema editor.
71
+ * Requiring the structured contract for every historical/manual issue.
72
+ * Rewriting the Linear ticket from Dealer.
73
+ * Automatically executing evidence commands in the coordinator.
74
+ * Changing product scope after a workflow starts.
75
+
76
+ ## Exit predicate
77
+ Importing a Planner-authored Linear ticket yields a versioned frozen execution contract visible in Dealer and both worker prompts, while legacy tickets still work and the operator is never asked to duplicate the brief manually.
78
+
79
+ ## One-PR stopping point
80
+ Execution-contract v1 compiles from ticket Markdown, persists/freezes with the Issue workflow, appears read-only in Issue Detail, and renders in developer/reviewer prompts. Stop before generic workflow templates or automatic evidence execution.
81
+
82
+ ## Acceptance criteria
83
+ - [ ] A Linear description containing all contract-v1 headings imports into the exact structured schema while preserving the original Markdown unchanged.
84
+ * Evidence: shared compiler fixtures assert every field and the untouched source.
85
+ - [ ] Web, API, and CLI creation paths use the same compiler; the page-local acceptance-criteria regex is removed.
86
+ * Evidence: contract tests cover equivalent requests through each intake path.
87
+ - [ ] Issues with no contract-v1 headings retain current behavior and remain startable under existing readiness rules.
88
+ * Evidence: legacy issue and migration tests pass unchanged.
89
+ - [ ] Once any contract heading is present, duplicate headings, unknown execution modes, empty exit predicates, duplicate AC text, and malformed Evidence lines return an actionable validation error.
90
+ * Evidence: table-driven parser tests cover each invalid case.
91
+ - [ ] Starting a workflow freezes the compiled contract; later source edits do not alter an active workflow, while an allowed parked re-freeze updates source and compiled contract atomically.
92
+ * Evidence: coordinator snapshot and NOT-185 regression tests.
93
+ - [ ] Developer and reviewer prompts render execution mode, non-goals, exit predicate, one-PR boundary, and per-criterion evidence without instructing the worker to rediscover them.
94
+ * Evidence: exact prompt tests for both roles.
95
+ - [ ] Issue Detail shows the compiled contract read-only and does not introduce a second technical form.
96
+ * Evidence: focused component test and rendered UI smoke.
97
+ - [ ] \`npm test\`, type-check, and package build pass.
98
+ `;
99
+ test("NOT-306 ticket verbatim (`Feature.` mode, nested `* Evidence:` bullets) imports", () => {
100
+ const source = NOT306_VERBATIM_DESCRIPTION;
101
+ const { contract, hasContractHeadings } = compileExecutionContract(source);
102
+ assert.equal(hasContractHeadings, true);
103
+ assert.equal(source, NOT306_VERBATIM_DESCRIPTION);
104
+ assert.deepStrictEqual(contract, {
105
+ version: "v1",
106
+ executionMode: "feature",
107
+ nonGoals: [
108
+ "Making Dealer select a playbook or reason about implementation architecture.",
109
+ "Adding a generic workflow/schema editor.",
110
+ "Requiring the structured contract for every historical/manual issue.",
111
+ "Rewriting the Linear ticket from Dealer.",
112
+ "Automatically executing evidence commands in the coordinator.",
113
+ "Changing product scope after a workflow starts.",
114
+ ],
115
+ exitPredicate: "Importing a Planner-authored Linear ticket yields a versioned frozen execution contract visible in Dealer and both worker prompts, while legacy tickets still work and the operator is never asked to duplicate the brief manually.",
116
+ onePrStoppingPoint: "Execution-contract v1 compiles from ticket Markdown, persists/freezes with the Issue workflow, appears read-only in Issue Detail, and renders in developer/reviewer prompts. Stop before generic workflow templates or automatic evidence execution.",
117
+ acceptanceCriteria: [
118
+ {
119
+ text: "A Linear description containing all contract-v1 headings imports into the exact structured schema while preserving the original Markdown unchanged.",
120
+ evidence: "shared compiler fixtures assert every field and the untouched source.",
121
+ },
122
+ {
123
+ text: "Web, API, and CLI creation paths use the same compiler; the page-local acceptance-criteria regex is removed.",
124
+ evidence: "contract tests cover equivalent requests through each intake path.",
125
+ },
126
+ {
127
+ text: "Issues with no contract-v1 headings retain current behavior and remain startable under existing readiness rules.",
128
+ evidence: "legacy issue and migration tests pass unchanged.",
129
+ },
130
+ {
131
+ text: "Once any contract heading is present, duplicate headings, unknown execution modes, empty exit predicates, duplicate AC text, and malformed Evidence lines return an actionable validation error.",
132
+ evidence: "table-driven parser tests cover each invalid case.",
133
+ },
134
+ {
135
+ text: "Starting a workflow freezes the compiled contract; later source edits do not alter an active workflow, while an allowed parked re-freeze updates source and compiled contract atomically.",
136
+ evidence: "coordinator snapshot and NOT-185 regression tests.",
137
+ },
138
+ {
139
+ text: "Developer and reviewer prompts render execution mode, non-goals, exit predicate, one-PR boundary, and per-criterion evidence without instructing the worker to rediscover them.",
140
+ evidence: "exact prompt tests for both roles.",
141
+ },
142
+ {
143
+ text: "Issue Detail shows the compiled contract read-only and does not introduce a second technical form.",
144
+ evidence: "focused component test and rendered UI smoke.",
145
+ },
146
+ {
147
+ text: "`npm test`, type-check, and package build pass.",
148
+ evidence: null,
149
+ },
150
+ ],
151
+ });
152
+ });
153
+ test("a criterion without an Evidence line keeps a null evidence", () => {
154
+ const { contract } = compileExecutionContract([
155
+ "## Builder execution mode",
156
+ "refactor",
157
+ "",
158
+ "## Non-goals",
159
+ "- nothing",
160
+ "",
161
+ "## Exit predicate",
162
+ "The refactor lands with no behavior change.",
163
+ "",
164
+ "## One-PR stopping point",
165
+ "Stop at the refactor.",
166
+ "",
167
+ "## Acceptance criteria",
168
+ "- [ ] Behavior is unchanged",
169
+ "- [x] Types still check",
170
+ "",
171
+ ].join("\n"));
172
+ assert.deepStrictEqual(contract?.acceptanceCriteria, [
173
+ { text: "Behavior is unchanged", evidence: null },
174
+ { text: "Types still check", evidence: null },
175
+ ]);
176
+ });
177
+ test("compilation preserves the original Markdown — the contract is derived data", () => {
178
+ const source = FULL_CONTRACT_DESCRIPTION;
179
+ compileExecutionContract(source);
180
+ assert.equal(source, FULL_CONTRACT_DESCRIPTION);
181
+ const { acceptanceCriteria } = compileExecutionContract(source);
182
+ assert.ok(acceptanceCriteria);
183
+ // The derived text is a rendering of the criteria, not a rewrite of the ticket.
184
+ assert.ok(!acceptanceCriteria.includes("## Non-goals"));
185
+ });
186
+ test("a description with no contract headings stays a compatible legacy issue", () => {
187
+ for (const description of [null, undefined, "", " ", "Just a plain description.", "# Title\n\nSome *other* sections."]) {
188
+ const compiled = compileExecutionContract(description);
189
+ assert.equal(compiled.contract, null);
190
+ assert.equal(compiled.acceptanceCriteria, null);
191
+ assert.equal(compiled.hasContractHeadings, false);
192
+ }
193
+ assert.equal(hasExecutionContractSignal("plain text"), false);
194
+ assert.equal(hasExecutionContractSignal(null), false);
195
+ });
196
+ test("an Acceptance-criteria-only ticket keeps the legacy raw-text extraction", () => {
197
+ const compiled = compileExecutionContract(["Ship it.", "", "## Acceptance criteria", "It works and it ships.", ""].join("\n"));
198
+ assert.equal(compiled.contract, null);
199
+ assert.equal(compiled.hasContractHeadings, true);
200
+ assert.equal(compiled.acceptanceCriteria, "It works and it ships.");
201
+ assert.equal(hasExecutionContractSignal("## Acceptance criteria\nIt works."), false);
202
+ });
203
+ test("each signal heading marks a contract ticket", () => {
204
+ assert.equal(hasExecutionContractSignal("## Builder execution mode\nfeature"), true);
205
+ assert.equal(hasExecutionContractSignal("## Non-goals\n- x"), true);
206
+ assert.equal(hasExecutionContractSignal("## Exit predicate\ndone when done"), true);
207
+ assert.equal(hasExecutionContractSignal("## One-PR stopping point\nstop here"), true);
208
+ });
209
+ test("execution mode accepts case/whitespace/punctuation variants of the enum", () => {
210
+ const build = (mode) => [
211
+ "## Builder execution mode",
212
+ mode,
213
+ "",
214
+ "## Non-goals",
215
+ "- x",
216
+ "",
217
+ "## Exit predicate",
218
+ "Done.",
219
+ "",
220
+ "## One-PR stopping point",
221
+ "Stop.",
222
+ "",
223
+ "## Acceptance criteria",
224
+ "- [ ] Done",
225
+ "",
226
+ ].join("\n");
227
+ assert.equal(compileExecutionContract(build("Feature")).contract?.executionMode, "feature");
228
+ assert.equal(compileExecutionContract(build("Feature.")).contract?.executionMode, "feature");
229
+ assert.equal(compileExecutionContract(build(" BUG-FIX ")).contract?.executionMode, "bug fix");
230
+ assert.equal(compileExecutionContract(build("bugfix")).contract?.executionMode, "bug fix");
231
+ assert.equal(compileExecutionContract(build("Refactor")).contract?.executionMode, "refactor");
232
+ assert.equal(compileExecutionContract(build("INVESTIGATION")).contract?.executionMode, "investigation");
233
+ assert.equal(compileExecutionContract(build("split child")).contract?.executionMode, "split child");
234
+ assert.equal(compileExecutionContract(build("Split-Child")).contract?.executionMode, "split child");
235
+ });
236
+ test("heading names match case-insensitively and across hyphen variants", () => {
237
+ const { contract } = compileExecutionContract([
238
+ "## BUILDER EXECUTION MODE",
239
+ "feature",
240
+ "",
241
+ "## Non goals",
242
+ "- x",
243
+ "",
244
+ "## exit predicate",
245
+ "Done.",
246
+ "",
247
+ "## One PR stopping point",
248
+ "Stop.",
249
+ "",
250
+ "## ACCEPTANCE CRITERIA",
251
+ "- [ ] Done",
252
+ "",
253
+ ].join("\n"));
254
+ assert.equal(contract?.executionMode, "feature");
255
+ assert.deepStrictEqual(contract?.nonGoals, ["x"]);
256
+ });
257
+ /** Every invalid shape returns an actionable error instead of dropping fields. */
258
+ const INVALID_CASES = [
259
+ {
260
+ name: "duplicate headings",
261
+ description: [
262
+ "## Builder execution mode",
263
+ "feature",
264
+ "",
265
+ "## Builder execution mode",
266
+ "refactor",
267
+ "",
268
+ "## Non-goals",
269
+ "- x",
270
+ "",
271
+ "## Exit predicate",
272
+ "Done.",
273
+ "",
274
+ "## One-PR stopping point",
275
+ "Stop.",
276
+ "",
277
+ "## Acceptance criteria",
278
+ "- [ ] Done",
279
+ "",
280
+ ].join("\n"),
281
+ match: /duplicate.*Builder execution mode/i,
282
+ },
283
+ {
284
+ name: "duplicate acceptance-criteria heading",
285
+ description: ["## Acceptance criteria", "A.", "", "## Acceptance criteria", "B.", ""].join("\n"),
286
+ match: /duplicate.*Acceptance criteria/i,
287
+ },
288
+ {
289
+ name: "unknown execution mode",
290
+ description: [
291
+ "## Builder execution mode",
292
+ "teleport",
293
+ "",
294
+ "## Non-goals",
295
+ "- x",
296
+ "",
297
+ "## Exit predicate",
298
+ "Done.",
299
+ "",
300
+ "## One-PR stopping point",
301
+ "Stop.",
302
+ "",
303
+ "## Acceptance criteria",
304
+ "- [ ] Done",
305
+ "",
306
+ ].join("\n"),
307
+ match: /unknown execution mode.*feature \| bug fix \| refactor \| investigation \| split child/i,
308
+ },
309
+ {
310
+ name: "missing execution mode section",
311
+ description: [
312
+ "## Non-goals",
313
+ "- x",
314
+ "",
315
+ "## Exit predicate",
316
+ "Done.",
317
+ "",
318
+ "## One-PR stopping point",
319
+ "Stop.",
320
+ "",
321
+ "## Acceptance criteria",
322
+ "- [ ] Done",
323
+ "",
324
+ ].join("\n"),
325
+ match: /missing.*Builder execution mode/i,
326
+ },
327
+ {
328
+ name: "empty exit predicate",
329
+ description: [
330
+ "## Builder execution mode",
331
+ "feature",
332
+ "",
333
+ "## Non-goals",
334
+ "- x",
335
+ "",
336
+ "## Exit predicate",
337
+ "",
338
+ "## One-PR stopping point",
339
+ "Stop.",
340
+ "",
341
+ "## Acceptance criteria",
342
+ "- [ ] Done",
343
+ "",
344
+ ].join("\n"),
345
+ match: /Exit predicate.*observable completion statement/i,
346
+ },
347
+ {
348
+ name: "empty one-PR stopping point",
349
+ description: [
350
+ "## Builder execution mode",
351
+ "feature",
352
+ "",
353
+ "## Non-goals",
354
+ "- x",
355
+ "",
356
+ "## Exit predicate",
357
+ "Done.",
358
+ "",
359
+ "## One-PR stopping point",
360
+ " ",
361
+ "",
362
+ "## Acceptance criteria",
363
+ "- [ ] Done",
364
+ "",
365
+ ].join("\n"),
366
+ match: /One-PR stopping point.*boundary/i,
367
+ },
368
+ {
369
+ name: "empty non-goals",
370
+ description: [
371
+ "## Builder execution mode",
372
+ "feature",
373
+ "",
374
+ "## Non-goals",
375
+ "",
376
+ "## Exit predicate",
377
+ "Done.",
378
+ "",
379
+ "## One-PR stopping point",
380
+ "Stop.",
381
+ "",
382
+ "## Acceptance criteria",
383
+ "- [ ] Done",
384
+ "",
385
+ ].join("\n"),
386
+ match: /Non-goals.*at least one/i,
387
+ },
388
+ {
389
+ name: "duplicate acceptance-criterion text",
390
+ description: [
391
+ "## Builder execution mode",
392
+ "feature",
393
+ "",
394
+ "## Non-goals",
395
+ "- x",
396
+ "",
397
+ "## Exit predicate",
398
+ "Done.",
399
+ "",
400
+ "## One-PR stopping point",
401
+ "Stop.",
402
+ "",
403
+ "## Acceptance criteria",
404
+ "- [ ] Ship it",
405
+ "- [ ] SHIP IT",
406
+ "",
407
+ ].join("\n"),
408
+ match: /duplicate criterion/i,
409
+ },
410
+ {
411
+ name: "empty Evidence line",
412
+ description: [
413
+ "## Builder execution mode",
414
+ "feature",
415
+ "",
416
+ "## Non-goals",
417
+ "- x",
418
+ "",
419
+ "## Exit predicate",
420
+ "Done.",
421
+ "",
422
+ "## One-PR stopping point",
423
+ "Stop.",
424
+ "",
425
+ "## Acceptance criteria",
426
+ "- [ ] Ship it",
427
+ " Evidence:",
428
+ "",
429
+ ].join("\n"),
430
+ match: /empty.*Evidence/i,
431
+ },
432
+ {
433
+ name: "orphan Evidence line",
434
+ description: [
435
+ "## Builder execution mode",
436
+ "feature",
437
+ "",
438
+ "## Non-goals",
439
+ "- x",
440
+ "",
441
+ "## Exit predicate",
442
+ "Done.",
443
+ "",
444
+ "## One-PR stopping point",
445
+ "Stop.",
446
+ "",
447
+ "## Acceptance criteria",
448
+ " Evidence: somewhere | do thing | see result",
449
+ "- [ ] Ship it",
450
+ "",
451
+ ].join("\n"),
452
+ match: /Evidence.*before any criterion/i,
453
+ },
454
+ {
455
+ name: "free-text acceptance-criteria line",
456
+ description: [
457
+ "## Builder execution mode",
458
+ "feature",
459
+ "",
460
+ "## Non-goals",
461
+ "- x",
462
+ "",
463
+ "## Exit predicate",
464
+ "Done.",
465
+ "",
466
+ "## One-PR stopping point",
467
+ "Stop.",
468
+ "",
469
+ "## Acceptance criteria",
470
+ "Just ship it, somehow.",
471
+ "",
472
+ ].join("\n"),
473
+ match: /checkbox items.*Evidence/i,
474
+ },
475
+ ];
476
+ for (const { name, description, match } of INVALID_CASES) {
477
+ test(`invalid contract is rejected with an actionable error: ${name}`, () => {
478
+ assert.throws(() => compileExecutionContract(description), (err) => {
479
+ assert.ok(err instanceof ExecutionContractError, `expected ExecutionContractError, got ${err}`);
480
+ assert.match(err.message, match);
481
+ return true;
482
+ });
483
+ });
484
+ }
485
+ test("resolveIssueContractFields never silently drops an explicit value", () => {
486
+ const explicit = "Operator-typed criteria";
487
+ const resolved = resolveIssueContractFields(FULL_CONTRACT_DESCRIPTION, explicit);
488
+ assert.ok(resolved.executionContract);
489
+ assert.equal(resolved.acceptanceCriteria, explicit);
490
+ const derived = resolveIssueContractFields(FULL_CONTRACT_DESCRIPTION, undefined);
491
+ assert.ok(derived.executionContract);
492
+ assert.equal(derived.acceptanceCriteria, renderContractAcceptanceCriteria(derived.executionContract));
493
+ const legacy = resolveIssueContractFields("plain", " kept ");
494
+ assert.equal(legacy.executionContract, null);
495
+ assert.equal(legacy.acceptanceCriteria, " kept ");
496
+ const legacyDerived = resolveIssueContractFields("## Acceptance criteria\nRaw text.", "");
497
+ assert.equal(legacyDerived.executionContract, null);
498
+ assert.equal(legacyDerived.acceptanceCriteria, "Raw text.");
499
+ });
@@ -24,7 +24,7 @@ export declare function defaultExecutionReportWindow(now?: number): {
24
24
  export declare const ExecutionReportRole: z.ZodEnum<["developer", "reviewer", "legacy"]>;
25
25
  export type ExecutionReportRole = z.infer<typeof ExecutionReportRole>;
26
26
  /** Failure codes: the closed taxonomy from docs/EXECUTION_ANALYSIS.md §7. */
27
- export declare const ExecutionFailureCode: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
27
+ export declare const ExecutionFailureCode: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "muse_no_progress", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
28
28
  export type ExecutionFailureCode = z.infer<typeof ExecutionFailureCode>;
29
29
  export declare const ExecutionFailureDomain: z.ZodEnum<["task", "infrastructure", "unknown"]>;
30
30
  export type ExecutionFailureDomain = z.infer<typeof ExecutionFailureDomain>;
@@ -454,7 +454,7 @@ export declare const CohortRow: z.ZodObject<{
454
454
  }>;
455
455
  export type CohortRow = z.infer<typeof CohortRow>;
456
456
  export declare const FailureDistributionEntry: z.ZodObject<{
457
- code: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
457
+ code: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "muse_no_progress", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
458
458
  domain: z.ZodEnum<["task", "infrastructure", "unknown"]>;
459
459
  count: z.ZodNumber;
460
460
  share: z.ZodNullable<z.ZodNumber>;
@@ -462,14 +462,14 @@ export declare const FailureDistributionEntry: z.ZodObject<{
462
462
  issueIds: z.ZodArray<z.ZodString, "many">;
463
463
  issueTotal: z.ZodNumber;
464
464
  }, "strip", z.ZodTypeAny, {
465
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
465
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
466
466
  domain: "unknown" | "task" | "infrastructure";
467
467
  issueIds: string[];
468
468
  count: number;
469
469
  share: number | null;
470
470
  issueTotal: number;
471
471
  }, {
472
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
472
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
473
473
  domain: "unknown" | "task" | "infrastructure";
474
474
  issueIds: string[];
475
475
  count: number;
@@ -1986,7 +1986,7 @@ export declare const ExecutionReportResponse: z.ZodObject<{
1986
1986
  };
1987
1987
  }>, "many">;
1988
1988
  failures: z.ZodArray<z.ZodObject<{
1989
- code: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
1989
+ code: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "muse_no_progress", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
1990
1990
  domain: z.ZodEnum<["task", "infrastructure", "unknown"]>;
1991
1991
  count: z.ZodNumber;
1992
1992
  share: z.ZodNullable<z.ZodNumber>;
@@ -1994,14 +1994,14 @@ export declare const ExecutionReportResponse: z.ZodObject<{
1994
1994
  issueIds: z.ZodArray<z.ZodString, "many">;
1995
1995
  issueTotal: z.ZodNumber;
1996
1996
  }, "strip", z.ZodTypeAny, {
1997
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
1997
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
1998
1998
  domain: "unknown" | "task" | "infrastructure";
1999
1999
  issueIds: string[];
2000
2000
  count: number;
2001
2001
  share: number | null;
2002
2002
  issueTotal: number;
2003
2003
  }, {
2004
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
2004
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
2005
2005
  domain: "unknown" | "task" | "infrastructure";
2006
2006
  issueIds: string[];
2007
2007
  count: number;
@@ -2404,7 +2404,7 @@ export declare const ExecutionReportResponse: z.ZodObject<{
2404
2404
  }[];
2405
2405
  };
2406
2406
  failures: {
2407
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
2407
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
2408
2408
  domain: "unknown" | "task" | "infrastructure";
2409
2409
  issueIds: string[];
2410
2410
  count: number;
@@ -2760,7 +2760,7 @@ export declare const ExecutionReportResponse: z.ZodObject<{
2760
2760
  }[];
2761
2761
  };
2762
2762
  failures: {
2763
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
2763
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
2764
2764
  domain: "unknown" | "task" | "infrastructure";
2765
2765
  issueIds: string[];
2766
2766
  count: number;
@@ -32,6 +32,8 @@ export const ExecutionFailureCode = z.enum([
32
32
  "provider_capacity_rate_limit",
33
33
  "agent_cli_crash",
34
34
  "tool_test_timeout",
35
+ // NOT-307: an idle-watchdog kill, not an ambiguous timeout (docs/EXECUTION_ANALYSIS.md §7).
36
+ "muse_no_progress",
35
37
  "coordinator_crash",
36
38
  "validation_failure",
37
39
  "publish_git_failure",
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  /** Closed failure taxonomy (EXECUTION_ANALYSIS.md §7). */
3
- export declare const FailureCauseCode: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
3
+ export declare const FailureCauseCode: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "muse_no_progress", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
4
4
  export type FailureCauseCode = z.infer<typeof FailureCauseCode>;
5
5
  export declare const FailureCauseDomain: z.ZodEnum<["task", "infrastructure", "unknown"]>;
6
6
  export type FailureCauseDomain = z.infer<typeof FailureCauseDomain>;
@@ -12,7 +12,7 @@ export type FailureEvidenceSource = z.infer<typeof FailureEvidenceSource>;
12
12
  export declare const FailureCauseQuality: z.ZodEnum<["exact", "inferred"]>;
13
13
  export type FailureCauseQuality = z.infer<typeof FailureCauseQuality>;
14
14
  export declare const FailureCause: z.ZodObject<{
15
- code: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
15
+ code: z.ZodEnum<["authentication_configuration", "provider_capacity_rate_limit", "agent_cli_crash", "tool_test_timeout", "muse_no_progress", "coordinator_crash", "validation_failure", "publish_git_failure", "agent_deck_unavailable", "host_sleep_liveness", "unknown"]>;
16
16
  domain: z.ZodEnum<["task", "infrastructure", "unknown"]>;
17
17
  /** First chronological actionable cause within the attempt; later causes are consequences. */
18
18
  primary: z.ZodBoolean;
@@ -31,7 +31,7 @@ export declare const FailureCause: z.ZodObject<{
31
31
  /** "inferred" marks backfill-on-read for legacy rows; fresh writes are "exact". */
32
32
  quality: z.ZodEnum<["exact", "inferred"]>;
33
33
  }, "strip", z.ZodTypeAny, {
34
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
34
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
35
35
  logPath: string | null;
36
36
  domain: "unknown" | "task" | "infrastructure";
37
37
  primary: boolean;
@@ -45,7 +45,7 @@ export declare const FailureCause: z.ZodObject<{
45
45
  eventType: string | null;
46
46
  quality: "exact" | "inferred";
47
47
  }, {
48
- code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
48
+ code: "unknown" | "authentication_configuration" | "provider_capacity_rate_limit" | "agent_cli_crash" | "tool_test_timeout" | "muse_no_progress" | "coordinator_crash" | "validation_failure" | "publish_git_failure" | "agent_deck_unavailable" | "host_sleep_liveness";
49
49
  logPath: string | null;
50
50
  domain: "unknown" | "task" | "infrastructure";
51
51
  primary: boolean;
@@ -11,6 +11,7 @@ export const FailureCauseCode = z.enum([
11
11
  "provider_capacity_rate_limit",
12
12
  "agent_cli_crash",
13
13
  "tool_test_timeout",
14
+ "muse_no_progress",
14
15
  "coordinator_crash",
15
16
  "validation_failure",
16
17
  "publish_git_failure",
@@ -58,6 +59,7 @@ export const FAILURE_CAUSE_DEFAULT_DOMAIN = {
58
59
  provider_capacity_rate_limit: "infrastructure",
59
60
  agent_cli_crash: "infrastructure",
60
61
  tool_test_timeout: "task",
62
+ muse_no_progress: "infrastructure",
61
63
  coordinator_crash: "infrastructure",
62
64
  validation_failure: "task",
63
65
  publish_git_failure: "infrastructure",