@exaudeus/workrail 3.74.3 → 3.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/console-ui/assets/index-DFZjlsUM.js +28 -0
- package/dist/console-ui/index.html +1 -1
- package/dist/coordinators/adaptive-pipeline.d.ts +8 -0
- package/dist/coordinators/context-assembly.d.ts +4 -0
- package/dist/coordinators/context-assembly.js +156 -0
- package/dist/coordinators/modes/full-pipeline.d.ts +1 -1
- package/dist/coordinators/modes/full-pipeline.js +140 -27
- package/dist/coordinators/modes/implement-shared.d.ts +3 -2
- package/dist/coordinators/modes/implement-shared.js +16 -6
- package/dist/coordinators/modes/implement.js +49 -3
- package/dist/coordinators/pipeline-run-context.d.ts +1811 -0
- package/dist/coordinators/pipeline-run-context.js +114 -0
- package/dist/infrastructure/storage/schema-validating-workflow-storage.js +25 -2
- package/dist/manifest.json +54 -30
- package/dist/trigger/coordinator-deps.js +131 -0
- package/dist/v2/durable-core/domain/artifact-contract-validator.js +99 -0
- package/dist/v2/durable-core/schemas/artifacts/discovery-handoff.d.ts +39 -0
- package/dist/v2/durable-core/schemas/artifacts/discovery-handoff.js +10 -1
- package/dist/v2/durable-core/schemas/artifacts/index.d.ts +2 -1
- package/dist/v2/durable-core/schemas/artifacts/index.js +12 -1
- package/dist/v2/durable-core/schemas/artifacts/phase-handoff.d.ts +89 -0
- package/dist/v2/durable-core/schemas/artifacts/phase-handoff.js +56 -0
- package/docs/authoring-v2.md +12 -0
- package/docs/ideas/backlog.md +409 -1
- package/package.json +1 -1
- package/workflows/coding-task-workflow-agentic.json +9 -6
- package/workflows/mr-review-workflow.agentic.v2.json +2 -2
- package/workflows/routines/tension-driven-design.json +12 -12
- package/workflows/workflow-for-workflows.json +5 -11
- package/workflows/wr.discovery.json +20 -17
- package/workflows/wr.shaping.json +7 -4
- package/dist/console-ui/assets/index-ByqIsoyt.js +0 -28
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PipelineRunContextSchema = exports.ReviewPhaseRecordSchema = exports.CodingPhaseRecordSchema = exports.ShapingPhaseRecordSchema = exports.DiscoveryPhaseRecordSchema = exports.MIN_NOTES_LENGTH_FOR_PHASE_RESULT = void 0;
|
|
4
|
+
exports.buildPhaseResult = buildPhaseResult;
|
|
5
|
+
exports.parsePipelineRunContext = parsePipelineRunContext;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
const neverthrow_1 = require("neverthrow");
|
|
8
|
+
const index_js_1 = require("../v2/durable-core/schemas/artifacts/index.js");
|
|
9
|
+
exports.MIN_NOTES_LENGTH_FOR_PHASE_RESULT = 50;
|
|
10
|
+
function buildPhaseResult(artifact, recapMarkdown) {
|
|
11
|
+
if (artifact !== null) {
|
|
12
|
+
const maybeConf = artifact.confidenceBand;
|
|
13
|
+
const confidenceBand = maybeConf === 'high' || maybeConf === 'medium' || maybeConf === 'low'
|
|
14
|
+
? maybeConf
|
|
15
|
+
: null;
|
|
16
|
+
return { kind: 'full', artifact, confidenceBand, recapMarkdown };
|
|
17
|
+
}
|
|
18
|
+
if (recapMarkdown !== null && recapMarkdown.trim().length > exports.MIN_NOTES_LENGTH_FOR_PHASE_RESULT) {
|
|
19
|
+
return { kind: 'partial', recapMarkdown: recapMarkdown.trim() };
|
|
20
|
+
}
|
|
21
|
+
return { kind: 'fallback', recapMarkdown };
|
|
22
|
+
}
|
|
23
|
+
const PhaseResultFullDiscoverySchema = zod_1.z.object({
|
|
24
|
+
kind: zod_1.z.literal('full'),
|
|
25
|
+
artifact: index_js_1.DiscoveryHandoffArtifactV1Schema,
|
|
26
|
+
confidenceBand: zod_1.z.enum(['high', 'medium', 'low']).nullable(),
|
|
27
|
+
recapMarkdown: zod_1.z.string().nullable(),
|
|
28
|
+
});
|
|
29
|
+
const PhaseResultFullShapingSchema = zod_1.z.object({
|
|
30
|
+
kind: zod_1.z.literal('full'),
|
|
31
|
+
artifact: index_js_1.ShapingHandoffArtifactV1Schema,
|
|
32
|
+
confidenceBand: zod_1.z.enum(['high', 'medium', 'low']).nullable(),
|
|
33
|
+
recapMarkdown: zod_1.z.string().nullable(),
|
|
34
|
+
});
|
|
35
|
+
const PhaseResultFullCodingSchema = zod_1.z.object({
|
|
36
|
+
kind: zod_1.z.literal('full'),
|
|
37
|
+
artifact: index_js_1.CodingHandoffArtifactV1Schema,
|
|
38
|
+
confidenceBand: zod_1.z.enum(['high', 'medium', 'low']).nullable(),
|
|
39
|
+
recapMarkdown: zod_1.z.string().nullable(),
|
|
40
|
+
});
|
|
41
|
+
const PhaseResultFullReviewSchema = zod_1.z.object({
|
|
42
|
+
kind: zod_1.z.literal('full'),
|
|
43
|
+
artifact: index_js_1.ReviewVerdictArtifactV1Schema,
|
|
44
|
+
confidenceBand: zod_1.z.enum(['high', 'medium', 'low']).nullable(),
|
|
45
|
+
recapMarkdown: zod_1.z.string().nullable(),
|
|
46
|
+
});
|
|
47
|
+
const PhaseResultPartialSchema = zod_1.z.object({
|
|
48
|
+
kind: zod_1.z.literal('partial'),
|
|
49
|
+
recapMarkdown: zod_1.z.string(),
|
|
50
|
+
});
|
|
51
|
+
const PhaseResultFallbackSchema = zod_1.z.object({
|
|
52
|
+
kind: zod_1.z.literal('fallback'),
|
|
53
|
+
recapMarkdown: zod_1.z.string().nullable(),
|
|
54
|
+
});
|
|
55
|
+
exports.DiscoveryPhaseRecordSchema = zod_1.z.object({
|
|
56
|
+
completedAt: zod_1.z.string(),
|
|
57
|
+
sessionHandle: zod_1.z.string().min(1),
|
|
58
|
+
result: zod_1.z.discriminatedUnion('kind', [
|
|
59
|
+
PhaseResultFullDiscoverySchema,
|
|
60
|
+
PhaseResultPartialSchema,
|
|
61
|
+
PhaseResultFallbackSchema,
|
|
62
|
+
]),
|
|
63
|
+
});
|
|
64
|
+
exports.ShapingPhaseRecordSchema = zod_1.z.object({
|
|
65
|
+
completedAt: zod_1.z.string(),
|
|
66
|
+
sessionHandle: zod_1.z.string().min(1),
|
|
67
|
+
result: zod_1.z.discriminatedUnion('kind', [
|
|
68
|
+
PhaseResultFullShapingSchema,
|
|
69
|
+
PhaseResultPartialSchema,
|
|
70
|
+
PhaseResultFallbackSchema,
|
|
71
|
+
]),
|
|
72
|
+
});
|
|
73
|
+
exports.CodingPhaseRecordSchema = zod_1.z.object({
|
|
74
|
+
completedAt: zod_1.z.string(),
|
|
75
|
+
sessionHandle: zod_1.z.string().min(1),
|
|
76
|
+
result: zod_1.z.discriminatedUnion('kind', [
|
|
77
|
+
PhaseResultFullCodingSchema,
|
|
78
|
+
PhaseResultPartialSchema,
|
|
79
|
+
PhaseResultFallbackSchema,
|
|
80
|
+
]),
|
|
81
|
+
});
|
|
82
|
+
exports.ReviewPhaseRecordSchema = zod_1.z.object({
|
|
83
|
+
completedAt: zod_1.z.string(),
|
|
84
|
+
sessionHandle: zod_1.z.string().min(1),
|
|
85
|
+
result: zod_1.z.discriminatedUnion('kind', [
|
|
86
|
+
PhaseResultFullReviewSchema,
|
|
87
|
+
PhaseResultPartialSchema,
|
|
88
|
+
PhaseResultFallbackSchema,
|
|
89
|
+
]),
|
|
90
|
+
});
|
|
91
|
+
exports.PipelineRunContextSchema = zod_1.z.object({
|
|
92
|
+
runId: zod_1.z.string().min(1),
|
|
93
|
+
goal: zod_1.z.string().min(1),
|
|
94
|
+
workspace: zod_1.z.string().min(1),
|
|
95
|
+
startedAt: zod_1.z.string(),
|
|
96
|
+
pipelineMode: zod_1.z.enum(['FULL', 'IMPLEMENT', 'REVIEW_ONLY', 'QUICK_REVIEW']),
|
|
97
|
+
status: zod_1.z.enum(['in_progress', 'completed']).optional(),
|
|
98
|
+
phases: zod_1.z.object({
|
|
99
|
+
discovery: exports.DiscoveryPhaseRecordSchema.optional(),
|
|
100
|
+
shaping: exports.ShapingPhaseRecordSchema.optional(),
|
|
101
|
+
coding: exports.CodingPhaseRecordSchema.optional(),
|
|
102
|
+
review: exports.ReviewPhaseRecordSchema.optional(),
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
function parsePipelineRunContext(raw) {
|
|
106
|
+
const result = exports.PipelineRunContextSchema.safeParse(raw);
|
|
107
|
+
if (!result.success) {
|
|
108
|
+
const issues = result.error.issues
|
|
109
|
+
.map((i) => `${i.path.join('.')}: ${i.message}`)
|
|
110
|
+
.join('; ');
|
|
111
|
+
return (0, neverthrow_1.err)(`PipelineRunContext parse failed: ${issues}`);
|
|
112
|
+
}
|
|
113
|
+
return (0, neverthrow_1.ok)(result.data);
|
|
114
|
+
}
|
|
@@ -21,6 +21,29 @@ const VALIDATION_ERROR_PREFIX = '[ValidationError]';
|
|
|
21
21
|
function reportValidationFailure(workflowId, sourceKind, error) {
|
|
22
22
|
console.error(`${VALIDATION_ERROR_PREFIX} ${sourceKind}/${workflowId}: ${error}`);
|
|
23
23
|
}
|
|
24
|
+
function extractValidationErrors(err) {
|
|
25
|
+
if (err instanceof error_handler_1.MCPError && typeof err.data?.details === 'string') {
|
|
26
|
+
try {
|
|
27
|
+
const ajvErrors = JSON.parse(err.data.details);
|
|
28
|
+
if (Array.isArray(ajvErrors) && ajvErrors.length > 0) {
|
|
29
|
+
return ajvErrors.map((e) => {
|
|
30
|
+
const location = e.instancePath ? `at '${e.instancePath}'` : 'at root';
|
|
31
|
+
const detail = (() => {
|
|
32
|
+
if (e.keyword === 'additionalProperties' && e.params && typeof e.params === 'object') {
|
|
33
|
+
const prop = e.params.additionalProperty;
|
|
34
|
+
return `additional property '${String(prop)}' is not allowed`;
|
|
35
|
+
}
|
|
36
|
+
return e.message ?? e.keyword ?? 'unknown error';
|
|
37
|
+
})();
|
|
38
|
+
return `${location}: ${detail}`;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return [err instanceof Error ? err.message : String(err)];
|
|
46
|
+
}
|
|
24
47
|
class SchemaValidatingWorkflowStorage {
|
|
25
48
|
constructor(inner) {
|
|
26
49
|
this.inner = inner;
|
|
@@ -71,7 +94,7 @@ class SchemaValidatingWorkflowStorage {
|
|
|
71
94
|
warnings.push({
|
|
72
95
|
workflowId: workflow.definition.id,
|
|
73
96
|
sourceKind: workflow.source.kind,
|
|
74
|
-
errors:
|
|
97
|
+
errors: extractValidationErrors(err),
|
|
75
98
|
});
|
|
76
99
|
}
|
|
77
100
|
}
|
|
@@ -158,7 +181,7 @@ class SchemaValidatingCompositeWorkflowStorage {
|
|
|
158
181
|
warnings.push({
|
|
159
182
|
workflowId: workflow.definition.id,
|
|
160
183
|
sourceKind: workflow.source.kind,
|
|
161
|
-
errors:
|
|
184
|
+
errors: extractValidationErrors(err),
|
|
162
185
|
});
|
|
163
186
|
}
|
|
164
187
|
}
|
package/dist/manifest.json
CHANGED
|
@@ -473,16 +473,16 @@
|
|
|
473
473
|
"sha256": "5fe866e54f796975dec5d8ba9983aefd86074db212d3fccd64eed04bc9f0b3da",
|
|
474
474
|
"bytes": 8011
|
|
475
475
|
},
|
|
476
|
-
"console-ui/assets/index-
|
|
477
|
-
"sha256": "
|
|
478
|
-
"bytes":
|
|
476
|
+
"console-ui/assets/index-DFZjlsUM.js": {
|
|
477
|
+
"sha256": "32444c14f8151326508fdfd00dd46abffc2034064849a411fac1e779da707eca",
|
|
478
|
+
"bytes": 767524
|
|
479
479
|
},
|
|
480
480
|
"console-ui/assets/index-DHrKiMCf.css": {
|
|
481
481
|
"sha256": "40290b50e21ee7e82433efe13b1aa31c1ea608bd057a5c4e324982f284bc928b",
|
|
482
482
|
"bytes": 60673
|
|
483
483
|
},
|
|
484
484
|
"console-ui/index.html": {
|
|
485
|
-
"sha256": "
|
|
485
|
+
"sha256": "1c656cb35c24495d9db4392e51d43d0f07f800e724c1e901df5fd48a43e2418d",
|
|
486
486
|
"bytes": 417
|
|
487
487
|
},
|
|
488
488
|
"console/standalone-console.d.ts": {
|
|
@@ -526,36 +526,44 @@
|
|
|
526
526
|
"bytes": 77
|
|
527
527
|
},
|
|
528
528
|
"coordinators/adaptive-pipeline.d.ts": {
|
|
529
|
-
"sha256": "
|
|
530
|
-
"bytes":
|
|
529
|
+
"sha256": "1ab143720fd019202368715d774a045b55cf953827571570d1396a62d9cacda0",
|
|
530
|
+
"bytes": 3512
|
|
531
531
|
},
|
|
532
532
|
"coordinators/adaptive-pipeline.js": {
|
|
533
533
|
"sha256": "afac18f8fc5fd75bc5ddd32cb3aaf8e02c22210c4ece001a4dd3c69ac2c10c8a",
|
|
534
534
|
"bytes": 4588
|
|
535
535
|
},
|
|
536
|
+
"coordinators/context-assembly.d.ts": {
|
|
537
|
+
"sha256": "ce8e19d9c2902329a96d2447d7d7c6489bafdafc9c8cfdb23423994524640d14",
|
|
538
|
+
"bytes": 466
|
|
539
|
+
},
|
|
540
|
+
"coordinators/context-assembly.js": {
|
|
541
|
+
"sha256": "6f8f3480b4cd42af02e279d9a67587eb0ce55b32611a94ce8dccf57a6589b71d",
|
|
542
|
+
"bytes": 7937
|
|
543
|
+
},
|
|
536
544
|
"coordinators/modes/full-pipeline.d.ts": {
|
|
537
|
-
"sha256": "
|
|
538
|
-
"bytes":
|
|
545
|
+
"sha256": "88230513db280be8b63106fef82a408499ba16a7acfbe5fa69f86af0a0c3ae04",
|
|
546
|
+
"bytes": 450
|
|
539
547
|
},
|
|
540
548
|
"coordinators/modes/full-pipeline.js": {
|
|
541
|
-
"sha256": "
|
|
542
|
-
"bytes":
|
|
549
|
+
"sha256": "99dc73260d66bb5c9e5c8f477467f5f934aad81b171d0e1cbe661109e939f9e7",
|
|
550
|
+
"bytes": 20365
|
|
543
551
|
},
|
|
544
552
|
"coordinators/modes/implement-shared.d.ts": {
|
|
545
|
-
"sha256": "
|
|
546
|
-
"bytes":
|
|
553
|
+
"sha256": "3203d8cb8a51dfe0cf88f3ab29d2dd5e0e60ae3b9c9dcc9f426a8581f55e71ff",
|
|
554
|
+
"bytes": 918
|
|
547
555
|
},
|
|
548
556
|
"coordinators/modes/implement-shared.js": {
|
|
549
|
-
"sha256": "
|
|
550
|
-
"bytes":
|
|
557
|
+
"sha256": "ef9385ab3881aafcf677a9a8823b139f1b197436276c448ff67cc3b4500acf98",
|
|
558
|
+
"bytes": 14254
|
|
551
559
|
},
|
|
552
560
|
"coordinators/modes/implement.d.ts": {
|
|
553
561
|
"sha256": "23919c24d62a0bf15296a52fbc594cca8b1b34e6f8d98dcf7dede8d97ad4cabb",
|
|
554
562
|
"bytes": 347
|
|
555
563
|
},
|
|
556
564
|
"coordinators/modes/implement.js": {
|
|
557
|
-
"sha256": "
|
|
558
|
-
"bytes":
|
|
565
|
+
"sha256": "e779f11315f4e911aa71318271070d7ffc7f2cc243c33669285b6f10b7c0d901",
|
|
566
|
+
"bytes": 8265
|
|
559
567
|
},
|
|
560
568
|
"coordinators/modes/quick-review.d.ts": {
|
|
561
569
|
"sha256": "03a4f29a07047b0bf788d84f8e0ebab63d64c8eb98aa57087943a8fb84563998",
|
|
@@ -573,6 +581,14 @@
|
|
|
573
581
|
"sha256": "a7da0b06ea4b16ae71b3d08a559dade91b01ffe1270633eb8ac1c355d57126eb",
|
|
574
582
|
"bytes": 1198
|
|
575
583
|
},
|
|
584
|
+
"coordinators/pipeline-run-context.d.ts": {
|
|
585
|
+
"sha256": "8fc743a1458e4d7a0971c968d51749d55a3bc114b286efe6b2030eb062809589",
|
|
586
|
+
"bytes": 68469
|
|
587
|
+
},
|
|
588
|
+
"coordinators/pipeline-run-context.js": {
|
|
589
|
+
"sha256": "5489319764a0dbd1b037521e014784fab518c4ff4f9137e045129e6845793e55",
|
|
590
|
+
"bytes": 4790
|
|
591
|
+
},
|
|
576
592
|
"coordinators/pr-review.d.ts": {
|
|
577
593
|
"sha256": "0dba830dd29cd82c58300ca9fdfb4c29d0acd0b257740ce3e65f2360239a106b",
|
|
578
594
|
"bytes": 4501
|
|
@@ -1026,8 +1042,8 @@
|
|
|
1026
1042
|
"bytes": 2023
|
|
1027
1043
|
},
|
|
1028
1044
|
"infrastructure/storage/schema-validating-workflow-storage.js": {
|
|
1029
|
-
"sha256": "
|
|
1030
|
-
"bytes":
|
|
1045
|
+
"sha256": "06a8dd9b05f3186dc305d39436b49c6c13e08b30b1fa9ae1f3d6161789c3b993",
|
|
1046
|
+
"bytes": 8878
|
|
1031
1047
|
},
|
|
1032
1048
|
"infrastructure/storage/storage.d.ts": {
|
|
1033
1049
|
"sha256": "481c5c0ef797baa7f18cff6a468a1de6d1ef34dd4b35f53e318e30b825b31e63",
|
|
@@ -1794,8 +1810,8 @@
|
|
|
1794
1810
|
"bytes": 854
|
|
1795
1811
|
},
|
|
1796
1812
|
"trigger/coordinator-deps.js": {
|
|
1797
|
-
"sha256": "
|
|
1798
|
-
"bytes":
|
|
1813
|
+
"sha256": "ceff71f1fd76b8ce7c490eee80fb2c13496d53adc321b85be525784eeafe930a",
|
|
1814
|
+
"bytes": 29393
|
|
1799
1815
|
},
|
|
1800
1816
|
"trigger/delivery-action.d.ts": {
|
|
1801
1817
|
"sha256": "bba98a08e35653304b604cd3ec126374cb731620db27ee2c8d6782d5b5b31207",
|
|
@@ -2058,8 +2074,8 @@
|
|
|
2058
2074
|
"bytes": 1343
|
|
2059
2075
|
},
|
|
2060
2076
|
"v2/durable-core/domain/artifact-contract-validator.js": {
|
|
2061
|
-
"sha256": "
|
|
2062
|
-
"bytes":
|
|
2077
|
+
"sha256": "f3b3e7505a820ab3870b19994d9a4d8e61d9051452a28d86feef737d24c144a3",
|
|
2078
|
+
"bytes": 10619
|
|
2063
2079
|
},
|
|
2064
2080
|
"v2/durable-core/domain/assessment-consequence-event-builder.d.ts": {
|
|
2065
2081
|
"sha256": "be91245e615888ae4675c093a9f323500099dbe6d1250ced4726764e1029e9ad",
|
|
@@ -2414,20 +2430,20 @@
|
|
|
2414
2430
|
"bytes": 1242
|
|
2415
2431
|
},
|
|
2416
2432
|
"v2/durable-core/schemas/artifacts/discovery-handoff.d.ts": {
|
|
2417
|
-
"sha256": "
|
|
2418
|
-
"bytes":
|
|
2433
|
+
"sha256": "36b933327a0aed2b767834c4567c7bc51209f9f39e844f3a2503ddccc70ec93e",
|
|
2434
|
+
"bytes": 2323
|
|
2419
2435
|
},
|
|
2420
2436
|
"v2/durable-core/schemas/artifacts/discovery-handoff.js": {
|
|
2421
|
-
"sha256": "
|
|
2422
|
-
"bytes":
|
|
2437
|
+
"sha256": "2c8e2f51df1691a34e64bfb4ecfbfd8b4447ca961824612c366f9a30092bfe9b",
|
|
2438
|
+
"bytes": 1624
|
|
2423
2439
|
},
|
|
2424
2440
|
"v2/durable-core/schemas/artifacts/index.d.ts": {
|
|
2425
|
-
"sha256": "
|
|
2426
|
-
"bytes":
|
|
2441
|
+
"sha256": "016e3d46d2eac61e12caf851f8b9d46512b2a3a186bbab7d672127f7f48eb168",
|
|
2442
|
+
"bytes": 1976
|
|
2427
2443
|
},
|
|
2428
2444
|
"v2/durable-core/schemas/artifacts/index.js": {
|
|
2429
|
-
"sha256": "
|
|
2430
|
-
"bytes":
|
|
2445
|
+
"sha256": "55392c70481c4a89aebf42ad7b1becb17e128d575b3bd832f7fd8f2b85ae89b9",
|
|
2446
|
+
"bytes": 7493
|
|
2431
2447
|
},
|
|
2432
2448
|
"v2/durable-core/schemas/artifacts/loop-control.d.ts": {
|
|
2433
2449
|
"sha256": "95dabfdcedb1a71c58c38a805dcf24c76254783bc0b2c7d429a3b8ffb94202ed",
|
|
@@ -2437,6 +2453,14 @@
|
|
|
2437
2453
|
"sha256": "c4b2ed38f9fdda3fbe3e4b68b0a228890fd9a7c73117a6d202928acabe6fc0f9",
|
|
2438
2454
|
"bytes": 2115
|
|
2439
2455
|
},
|
|
2456
|
+
"v2/durable-core/schemas/artifacts/phase-handoff.d.ts": {
|
|
2457
|
+
"sha256": "e56371b1e7e5ca83c2867c04d9e1c4b9f24ca654905c5c24d2577acc48a005c4",
|
|
2458
|
+
"bytes": 3228
|
|
2459
|
+
},
|
|
2460
|
+
"v2/durable-core/schemas/artifacts/phase-handoff.js": {
|
|
2461
|
+
"sha256": "05e038285bcd4a140a22b71e7bf1a53ee123de8f23b021b4e9cb9164e266b02a",
|
|
2462
|
+
"bytes": 2651
|
|
2463
|
+
},
|
|
2440
2464
|
"v2/durable-core/schemas/artifacts/review-verdict.d.ts": {
|
|
2441
2465
|
"sha256": "2b9f7ae6b3fafe6c26f266bb249c8c286144eb1f753c803d4358ef81e30d1736",
|
|
2442
2466
|
"bytes": 2211
|
|
@@ -38,10 +38,12 @@ const fs = __importStar(require("node:fs"));
|
|
|
38
38
|
const os = __importStar(require("node:os"));
|
|
39
39
|
const path = __importStar(require("node:path"));
|
|
40
40
|
const node_crypto_1 = require("node:crypto");
|
|
41
|
+
const neverthrow_1 = require("neverthrow");
|
|
41
42
|
const start_js_1 = require("../mcp/handlers/v2-execution/start.js");
|
|
42
43
|
const v2_token_ops_js_1 = require("../mcp/handlers/v2-token-ops.js");
|
|
43
44
|
const index_js_1 = require("../context-assembly/index.js");
|
|
44
45
|
const infra_js_1 = require("../context-assembly/infra.js");
|
|
46
|
+
const pipeline_run_context_js_1 = require("../coordinators/pipeline-run-context.js");
|
|
45
47
|
function createCoordinatorDeps(deps) {
|
|
46
48
|
const { ctx, execFileAsync, consoleService } = deps;
|
|
47
49
|
let dispatch = null;
|
|
@@ -485,5 +487,134 @@ function createCoordinatorDeps(deps) {
|
|
|
485
487
|
}
|
|
486
488
|
return 'timeout';
|
|
487
489
|
},
|
|
490
|
+
generateRunId: () => (0, node_crypto_1.randomUUID)(),
|
|
491
|
+
readActiveRunId: async (workspace) => {
|
|
492
|
+
const runsDir = path.join(workspace, '.workrail', 'pipeline-runs');
|
|
493
|
+
try {
|
|
494
|
+
const entries = await fs.promises.readdir(runsDir);
|
|
495
|
+
const candidates = [];
|
|
496
|
+
for (const entry of entries) {
|
|
497
|
+
if (!entry.endsWith('-context.json'))
|
|
498
|
+
continue;
|
|
499
|
+
try {
|
|
500
|
+
const raw = await fs.promises.readFile(path.join(runsDir, entry), 'utf-8');
|
|
501
|
+
const ctx = JSON.parse(raw);
|
|
502
|
+
if (typeof ctx !== 'object' || ctx === null)
|
|
503
|
+
continue;
|
|
504
|
+
const c = ctx;
|
|
505
|
+
if (typeof c['runId'] !== 'string')
|
|
506
|
+
continue;
|
|
507
|
+
if (c['status'] === 'completed')
|
|
508
|
+
continue;
|
|
509
|
+
candidates.push({ runId: c['runId'], startedAt: String(c['startedAt'] ?? '') });
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (candidates.length === 0)
|
|
516
|
+
return (0, neverthrow_1.ok)(null);
|
|
517
|
+
candidates.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
518
|
+
if (candidates.length > 1) {
|
|
519
|
+
process.stderr.write(`[WARN coordinator] ${candidates.length} in-progress pipeline runs found -- resuming newest (${candidates[0].runId}). ` +
|
|
520
|
+
`Others: ${candidates.slice(1).map(c => c.runId).join(', ')}. Run 'worktrain cleanup' to clear stale runs.\n`);
|
|
521
|
+
}
|
|
522
|
+
return (0, neverthrow_1.ok)(candidates[0].runId);
|
|
523
|
+
}
|
|
524
|
+
catch (e) {
|
|
525
|
+
if (e.code === 'ENOENT')
|
|
526
|
+
return (0, neverthrow_1.ok)(null);
|
|
527
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
528
|
+
process.stderr.write(`[WARN coordinator] readActiveRunId failed -- crash recovery skipped: ${msg}\n`);
|
|
529
|
+
return (0, neverthrow_1.err)(`readActiveRunId failed: ${msg}`);
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
markPipelineRunComplete: async (workspace, runId) => {
|
|
533
|
+
const runsDir = path.join(workspace, '.workrail', 'pipeline-runs');
|
|
534
|
+
const filePath = path.join(runsDir, `${runId}-context.json`);
|
|
535
|
+
const tmpPath = filePath + '.tmp';
|
|
536
|
+
try {
|
|
537
|
+
const raw = await fs.promises.readFile(filePath, 'utf-8');
|
|
538
|
+
const existing = JSON.parse(raw);
|
|
539
|
+
const updated = { ...existing, status: 'completed' };
|
|
540
|
+
await fs.promises.writeFile(tmpPath, JSON.stringify(updated, null, 2) + '\n', 'utf-8');
|
|
541
|
+
await fs.promises.rename(tmpPath, filePath);
|
|
542
|
+
return (0, neverthrow_1.ok)(undefined);
|
|
543
|
+
}
|
|
544
|
+
catch (e) {
|
|
545
|
+
try {
|
|
546
|
+
await fs.promises.unlink(tmpPath);
|
|
547
|
+
}
|
|
548
|
+
catch { }
|
|
549
|
+
return (0, neverthrow_1.err)(`markPipelineRunComplete failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
readPipelineContext: async (workspace, runId) => {
|
|
553
|
+
const runsDir = path.join(workspace, '.workrail', 'pipeline-runs');
|
|
554
|
+
const filePath = path.join(runsDir, `${runId}-context.json`);
|
|
555
|
+
try {
|
|
556
|
+
const raw = await fs.promises.readFile(filePath, 'utf-8');
|
|
557
|
+
const parsed = JSON.parse(raw);
|
|
558
|
+
return (0, pipeline_run_context_js_1.parsePipelineRunContext)(parsed);
|
|
559
|
+
}
|
|
560
|
+
catch (e) {
|
|
561
|
+
if (e.code === 'ENOENT') {
|
|
562
|
+
return (0, neverthrow_1.ok)(null);
|
|
563
|
+
}
|
|
564
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
565
|
+
return (0, neverthrow_1.err)(`readPipelineContext failed: ${msg}`);
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
createPipelineContext: async (workspace, runId, goal, pipelineMode) => {
|
|
569
|
+
const runsDir = path.join(workspace, '.workrail', 'pipeline-runs');
|
|
570
|
+
const filePath = path.join(runsDir, `${runId}-context.json`);
|
|
571
|
+
const tmpPath = filePath + '.tmp';
|
|
572
|
+
try {
|
|
573
|
+
await fs.promises.mkdir(runsDir, { recursive: true });
|
|
574
|
+
const initial = { runId, goal, workspace, startedAt: new Date().toISOString(), pipelineMode, phases: {} };
|
|
575
|
+
await fs.promises.writeFile(tmpPath, JSON.stringify(initial, null, 2) + '\n', 'utf-8');
|
|
576
|
+
await fs.promises.rename(tmpPath, filePath);
|
|
577
|
+
return (0, neverthrow_1.ok)(undefined);
|
|
578
|
+
}
|
|
579
|
+
catch (e) {
|
|
580
|
+
try {
|
|
581
|
+
await fs.promises.unlink(tmpPath);
|
|
582
|
+
}
|
|
583
|
+
catch { }
|
|
584
|
+
return (0, neverthrow_1.err)(`createPipelineContext failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
writePhaseRecord: async (workspace, runId, entry) => {
|
|
588
|
+
const runsDir = path.join(workspace, '.workrail', 'pipeline-runs');
|
|
589
|
+
const filePath = path.join(runsDir, `${runId}-context.json`);
|
|
590
|
+
const tmpPath = filePath + '.tmp';
|
|
591
|
+
try {
|
|
592
|
+
await fs.promises.mkdir(runsDir, { recursive: true });
|
|
593
|
+
const raw = await fs.promises.readFile(filePath, 'utf-8');
|
|
594
|
+
const parsed = JSON.parse(raw);
|
|
595
|
+
const existing = (0, pipeline_run_context_js_1.parsePipelineRunContext)(parsed);
|
|
596
|
+
if (existing.isErr() || existing.value === null) {
|
|
597
|
+
return (0, neverthrow_1.err)(`writePhaseRecord: context file missing or invalid for runId=${runId}`);
|
|
598
|
+
}
|
|
599
|
+
const updated = {
|
|
600
|
+
...existing.value,
|
|
601
|
+
phases: {
|
|
602
|
+
...existing.value.phases,
|
|
603
|
+
[entry.phase]: entry.record,
|
|
604
|
+
},
|
|
605
|
+
};
|
|
606
|
+
await fs.promises.writeFile(tmpPath, JSON.stringify(updated, null, 2) + '\n', 'utf-8');
|
|
607
|
+
await fs.promises.rename(tmpPath, filePath);
|
|
608
|
+
return (0, neverthrow_1.ok)(undefined);
|
|
609
|
+
}
|
|
610
|
+
catch (e) {
|
|
611
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
612
|
+
try {
|
|
613
|
+
await fs.promises.unlink(tmpPath);
|
|
614
|
+
}
|
|
615
|
+
catch { }
|
|
616
|
+
return (0, neverthrow_1.err)(`writePhaseRecord failed: ${msg}`);
|
|
617
|
+
}
|
|
618
|
+
},
|
|
488
619
|
};
|
|
489
620
|
}
|
|
@@ -25,6 +25,12 @@ function validateArtifactContract(artifacts, contract) {
|
|
|
25
25
|
return validateCoordinatorSignalContract(artifacts, contractRef, required);
|
|
26
26
|
case index_js_1.REVIEW_VERDICT_CONTRACT_REF:
|
|
27
27
|
return validateReviewVerdictContract(artifacts, contractRef, required);
|
|
28
|
+
case index_js_1.DISCOVERY_HANDOFF_CONTRACT_REF:
|
|
29
|
+
return validateDiscoveryHandoffContract(artifacts, contractRef, required);
|
|
30
|
+
case index_js_1.SHAPING_HANDOFF_CONTRACT_REF:
|
|
31
|
+
return validateShapingHandoffContract(artifacts, contractRef, required);
|
|
32
|
+
case index_js_1.CODING_HANDOFF_CONTRACT_REF:
|
|
33
|
+
return validateCodingHandoffContract(artifacts, contractRef, required);
|
|
28
34
|
default:
|
|
29
35
|
return {
|
|
30
36
|
valid: false,
|
|
@@ -129,6 +135,99 @@ function validateReviewVerdictContract(artifacts, contractRef, required) {
|
|
|
129
135
|
}
|
|
130
136
|
return { valid: true, artifact: parseResult.data };
|
|
131
137
|
}
|
|
138
|
+
function validateDiscoveryHandoffContract(artifacts, contractRef, required) {
|
|
139
|
+
const handoffArtifacts = artifacts.filter(index_js_1.isDiscoveryHandoffArtifact);
|
|
140
|
+
if (handoffArtifacts.length === 0) {
|
|
141
|
+
if (required) {
|
|
142
|
+
return {
|
|
143
|
+
valid: false,
|
|
144
|
+
error: {
|
|
145
|
+
code: 'MISSING_REQUIRED_ARTIFACT',
|
|
146
|
+
contractRef,
|
|
147
|
+
message: `Required artifact missing: ${contractRef}. Agent must provide an artifact with kind='wr.discovery_handoff'.`,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { valid: true, artifact: null };
|
|
152
|
+
}
|
|
153
|
+
const artifact = handoffArtifacts[0];
|
|
154
|
+
const parseResult = index_js_1.DiscoveryHandoffArtifactV1Schema.safeParse(artifact);
|
|
155
|
+
if (!parseResult.success) {
|
|
156
|
+
const issues = parseResult.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`);
|
|
157
|
+
return {
|
|
158
|
+
valid: false,
|
|
159
|
+
error: {
|
|
160
|
+
code: 'INVALID_ARTIFACT_SCHEMA',
|
|
161
|
+
contractRef,
|
|
162
|
+
message: `Artifact schema validation failed for ${contractRef}`,
|
|
163
|
+
issues,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return { valid: true, artifact: parseResult.data };
|
|
168
|
+
}
|
|
169
|
+
function validateShapingHandoffContract(artifacts, contractRef, required) {
|
|
170
|
+
const handoffArtifacts = artifacts.filter(index_js_1.isShapingHandoffArtifact);
|
|
171
|
+
if (handoffArtifacts.length === 0) {
|
|
172
|
+
if (required) {
|
|
173
|
+
return {
|
|
174
|
+
valid: false,
|
|
175
|
+
error: {
|
|
176
|
+
code: 'MISSING_REQUIRED_ARTIFACT',
|
|
177
|
+
contractRef,
|
|
178
|
+
message: `Required artifact missing: ${contractRef}. Agent must provide an artifact with kind='wr.shaping_handoff'.`,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return { valid: true, artifact: null };
|
|
183
|
+
}
|
|
184
|
+
const artifact = handoffArtifacts[0];
|
|
185
|
+
const parseResult = index_js_1.ShapingHandoffArtifactV1Schema.safeParse(artifact);
|
|
186
|
+
if (!parseResult.success) {
|
|
187
|
+
const issues = parseResult.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`);
|
|
188
|
+
return {
|
|
189
|
+
valid: false,
|
|
190
|
+
error: {
|
|
191
|
+
code: 'INVALID_ARTIFACT_SCHEMA',
|
|
192
|
+
contractRef,
|
|
193
|
+
message: `Artifact schema validation failed for ${contractRef}`,
|
|
194
|
+
issues,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return { valid: true, artifact: parseResult.data };
|
|
199
|
+
}
|
|
200
|
+
function validateCodingHandoffContract(artifacts, contractRef, required) {
|
|
201
|
+
const handoffArtifacts = artifacts.filter(index_js_1.isCodingHandoffArtifact);
|
|
202
|
+
if (handoffArtifacts.length === 0) {
|
|
203
|
+
if (required) {
|
|
204
|
+
return {
|
|
205
|
+
valid: false,
|
|
206
|
+
error: {
|
|
207
|
+
code: 'MISSING_REQUIRED_ARTIFACT',
|
|
208
|
+
contractRef,
|
|
209
|
+
message: `Required artifact missing: ${contractRef}. Agent must provide an artifact with kind='wr.coding_handoff'.`,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return { valid: true, artifact: null };
|
|
214
|
+
}
|
|
215
|
+
const artifact = handoffArtifacts[0];
|
|
216
|
+
const parseResult = index_js_1.CodingHandoffArtifactV1Schema.safeParse(artifact);
|
|
217
|
+
if (!parseResult.success) {
|
|
218
|
+
const issues = parseResult.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`);
|
|
219
|
+
return {
|
|
220
|
+
valid: false,
|
|
221
|
+
error: {
|
|
222
|
+
code: 'INVALID_ARTIFACT_SCHEMA',
|
|
223
|
+
contractRef,
|
|
224
|
+
message: `Artifact schema validation failed for ${contractRef}`,
|
|
225
|
+
issues,
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
return { valid: true, artifact: parseResult.data };
|
|
230
|
+
}
|
|
132
231
|
function requiresArtifactValidation(outputContract) {
|
|
133
232
|
if (!outputContract)
|
|
134
233
|
return false;
|
|
@@ -7,6 +7,27 @@ export declare const DiscoveryHandoffArtifactV1Schema: z.ZodObject<{
|
|
|
7
7
|
designDocPath: z.ZodString;
|
|
8
8
|
confidenceBand: z.ZodEnum<["high", "medium", "low"]>;
|
|
9
9
|
keyInvariants: z.ZodArray<z.ZodString, "many">;
|
|
10
|
+
rejectedDirections: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
11
|
+
direction: z.ZodString;
|
|
12
|
+
reason: z.ZodString;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
reason: string;
|
|
15
|
+
direction: string;
|
|
16
|
+
}, {
|
|
17
|
+
reason: string;
|
|
18
|
+
direction: string;
|
|
19
|
+
}>, "many">>;
|
|
20
|
+
implementationConstraints: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
21
|
+
keyCodebaseLocations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
22
|
+
path: z.ZodString;
|
|
23
|
+
relevance: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
path: string;
|
|
26
|
+
relevance: string;
|
|
27
|
+
}, {
|
|
28
|
+
path: string;
|
|
29
|
+
relevance: string;
|
|
30
|
+
}>, "many">>;
|
|
10
31
|
}, "strict", z.ZodTypeAny, {
|
|
11
32
|
kind: "wr.discovery_handoff";
|
|
12
33
|
version: 1;
|
|
@@ -14,6 +35,15 @@ export declare const DiscoveryHandoffArtifactV1Schema: z.ZodObject<{
|
|
|
14
35
|
designDocPath: string;
|
|
15
36
|
confidenceBand: "low" | "high" | "medium";
|
|
16
37
|
keyInvariants: string[];
|
|
38
|
+
rejectedDirections?: {
|
|
39
|
+
reason: string;
|
|
40
|
+
direction: string;
|
|
41
|
+
}[] | undefined;
|
|
42
|
+
implementationConstraints?: string[] | undefined;
|
|
43
|
+
keyCodebaseLocations?: {
|
|
44
|
+
path: string;
|
|
45
|
+
relevance: string;
|
|
46
|
+
}[] | undefined;
|
|
17
47
|
}, {
|
|
18
48
|
kind: "wr.discovery_handoff";
|
|
19
49
|
version: 1;
|
|
@@ -21,6 +51,15 @@ export declare const DiscoveryHandoffArtifactV1Schema: z.ZodObject<{
|
|
|
21
51
|
designDocPath: string;
|
|
22
52
|
confidenceBand: "low" | "high" | "medium";
|
|
23
53
|
keyInvariants: string[];
|
|
54
|
+
rejectedDirections?: {
|
|
55
|
+
reason: string;
|
|
56
|
+
direction: string;
|
|
57
|
+
}[] | undefined;
|
|
58
|
+
implementationConstraints?: string[] | undefined;
|
|
59
|
+
keyCodebaseLocations?: {
|
|
60
|
+
path: string;
|
|
61
|
+
relevance: string;
|
|
62
|
+
}[] | undefined;
|
|
24
63
|
}>;
|
|
25
64
|
export type DiscoveryHandoffArtifactV1 = z.infer<typeof DiscoveryHandoffArtifactV1Schema>;
|
|
26
65
|
export declare function isDiscoveryHandoffArtifact(artifact: unknown): artifact is {
|
|
@@ -12,7 +12,16 @@ exports.DiscoveryHandoffArtifactV1Schema = zod_1.z
|
|
|
12
12
|
selectedDirection: zod_1.z.string().min(1),
|
|
13
13
|
designDocPath: zod_1.z.string(),
|
|
14
14
|
confidenceBand: zod_1.z.enum(['high', 'medium', 'low']),
|
|
15
|
-
keyInvariants: zod_1.z.array(zod_1.z.string().min(1)),
|
|
15
|
+
keyInvariants: zod_1.z.array(zod_1.z.string().min(1).max(200)).max(12),
|
|
16
|
+
rejectedDirections: zod_1.z.array(zod_1.z.object({
|
|
17
|
+
direction: zod_1.z.string().min(1).max(200),
|
|
18
|
+
reason: zod_1.z.string().min(1).max(300),
|
|
19
|
+
})).max(5).optional(),
|
|
20
|
+
implementationConstraints: zod_1.z.array(zod_1.z.string().min(1).max(200)).max(8).optional(),
|
|
21
|
+
keyCodebaseLocations: zod_1.z.array(zod_1.z.object({
|
|
22
|
+
path: zod_1.z.string().min(1).max(300),
|
|
23
|
+
relevance: zod_1.z.string().min(1).max(150),
|
|
24
|
+
})).max(10).optional(),
|
|
16
25
|
})
|
|
17
26
|
.strict();
|
|
18
27
|
function isDiscoveryHandoffArtifact(artifact) {
|