@dailephd/my-dev-kit-lab 0.4.2 → 0.4.4

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 (113) hide show
  1. package/README.md +28 -113
  2. package/benchmarks/contracts/todo-behavior.md +1 -1
  3. package/benchmarks/projects/task-analytics-large-mixed/README.md +2 -0
  4. package/benchmarks/projects/task-workflow-medium-ts/README.md +3 -1
  5. package/dist/src/evaluation/stageContextDeterminism/calculateStageContextDeterminism.js +52 -0
  6. package/dist/src/evaluation/stageContextDeterminism/canonicalizeStageContextRun.js +53 -0
  7. package/dist/src/evaluation/stageContextDeterminism/index.js +2 -0
  8. package/dist/src/evaluation/stageContextDeterminism/types.js +1 -0
  9. package/dist/src/evaluation/stageContextExpectations/index.js +2 -0
  10. package/dist/src/evaluation/stageContextExpectations/producerReadinessExpectationTypes.js +8 -0
  11. package/dist/src/evaluation/stageContextExpectations/readStageContextExpectationFixtureV1.js +50 -0
  12. package/dist/src/evaluation/stageContextExpectations/readTypes.js +1 -0
  13. package/dist/src/evaluation/stageContextExpectations/types.js +1 -0
  14. package/dist/src/evaluation/stageContextExpectations/validation.js +768 -0
  15. package/dist/src/evaluation/stageContextMetrics/calculateAllocationMetrics.js +96 -0
  16. package/dist/src/evaluation/stageContextMetrics/calculateArtifactStateMetrics.js +130 -0
  17. package/dist/src/evaluation/stageContextMetrics/calculateContextSizeMetrics.js +85 -0
  18. package/dist/src/evaluation/stageContextMetrics/calculateCriticalityMetrics.js +112 -0
  19. package/dist/src/evaluation/stageContextMetrics/calculateExpectationMetrics.js +103 -0
  20. package/dist/src/evaluation/stageContextMetrics/calculateOwnerMetrics.js +84 -0
  21. package/dist/src/evaluation/stageContextMetrics/calculateReadinessAgreement.js +152 -0
  22. package/dist/src/evaluation/stageContextMetrics/calculateResponsibilityMappingMetrics.js +36 -0
  23. package/dist/src/evaluation/stageContextMetrics/calculateSupplementalRawAgreement.js +50 -0
  24. package/dist/src/evaluation/stageContextMetrics/calculateTruncationClassification.js +44 -0
  25. package/dist/src/evaluation/stageContextMetrics/collectContextCapsuleEvidence.js +312 -0
  26. package/dist/src/evaluation/stageContextMetrics/collectRetrievalAuditEvidence.js +35 -0
  27. package/dist/src/evaluation/stageContextMetrics/collectWorkflowInstructionEvidence.js +137 -0
  28. package/dist/src/evaluation/stageContextMetrics/evaluateProducerReadinessBridge.js +127 -0
  29. package/dist/src/evaluation/stageContextMetrics/evaluateV043StageContextExecution.js +247 -0
  30. package/dist/src/evaluation/stageContextMetrics/index.js +17 -0
  31. package/dist/src/evaluation/stageContextMetrics/matchStageContextExpectations.js +38 -0
  32. package/dist/src/evaluation/stageContextMetrics/producerReadinessMetricTypes.js +1 -0
  33. package/dist/src/evaluation/stageContextMetrics/targetKeys.js +35 -0
  34. package/dist/src/evaluation/stageContextMetrics/types.js +1 -0
  35. package/dist/src/evaluation/stageContextSelectors/contextArtifactConsistency.js +89 -0
  36. package/dist/src/evaluation/stageContextSelectors/contextCapsuleSelectors.js +126 -0
  37. package/dist/src/evaluation/stageContextSelectors/index.js +4 -0
  38. package/dist/src/evaluation/stageContextSelectors/retrievalAuditRecordSelectors.js +54 -0
  39. package/dist/src/evaluation/stageContextSelectors/workflowInstructionPacketSelectors.js +51 -0
  40. package/dist/src/evaluation/targetImmutability/captureTargetSnapshot.js +208 -0
  41. package/dist/src/evaluation/targetImmutability/compareTargetSnapshots.js +56 -0
  42. package/dist/src/evaluation/targetImmutability/index.js +3 -0
  43. package/dist/src/evaluation/targetImmutability/types.js +1 -0
  44. package/dist/src/evaluation/targetImmutability/validateTargetImmutabilityConfig.js +130 -0
  45. package/dist/src/evaluation/upstreamArtifacts/artifactReadTypes.js +1 -0
  46. package/dist/src/evaluation/upstreamArtifacts/index.js +9 -0
  47. package/dist/src/evaluation/upstreamArtifacts/jsonTypes.js +1 -0
  48. package/dist/src/evaluation/upstreamArtifacts/myDevKitClassificationTypesV1.js +1 -0
  49. package/dist/src/evaluation/upstreamArtifacts/myDevKitContextArtifactsV1.js +1 -0
  50. package/dist/src/evaluation/upstreamArtifacts/myDevKitSemanticTypesV1.js +1 -0
  51. package/dist/src/evaluation/upstreamArtifacts/orchestratorContextReadinessResultV1.js +247 -0
  52. package/dist/src/evaluation/upstreamArtifacts/orchestratorWorkflowInstructionPacketV1.js +1 -0
  53. package/dist/src/evaluation/upstreamArtifacts/readImplementationContextPacketV1.js +9 -0
  54. package/dist/src/evaluation/upstreamArtifacts/readImplementationContextRetrievalReportV1.js +9 -0
  55. package/dist/src/evaluation/upstreamArtifacts/readJsonArtifact.js +53 -0
  56. package/dist/src/evaluation/upstreamArtifacts/readMyDevKitContextCapsuleV1.js +9 -0
  57. package/dist/src/evaluation/upstreamArtifacts/readMyDevKitRetrievalAuditRecordV1.js +9 -0
  58. package/dist/src/evaluation/upstreamArtifacts/readOrchestratorWorkflowInstructionPacketV1.js +9 -0
  59. package/dist/src/evaluation/upstreamArtifacts/readSupplementalContextTextFile.js +29 -0
  60. package/dist/src/evaluation/upstreamArtifacts/readTestContextPacketV1.js +9 -0
  61. package/dist/src/evaluation/upstreamArtifacts/readTestContextRetrievalReportV1.js +9 -0
  62. package/dist/src/evaluation/upstreamArtifacts/runtimeValidation.js +131 -0
  63. package/dist/src/evaluation/upstreamArtifacts/schemaVersion.js +32 -0
  64. package/dist/src/evaluation/upstreamArtifacts/supplementalContextTextParser.js +75 -0
  65. package/dist/src/evaluation/upstreamArtifacts/supplementalContextTypes.js +152 -0
  66. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitContextCapsuleV1.js +1208 -0
  67. package/dist/src/evaluation/upstreamArtifacts/validateMyDevKitRetrievalAuditRecordV1.js +112 -0
  68. package/dist/src/evaluation/upstreamArtifacts/validateOrchestratorWorkflowInstructionPacketV1.js +235 -0
  69. package/dist/src/evaluation/upstreamArtifacts/validateSupplementalContextDocumentV1.js +148 -0
  70. package/dist/src/experiments/plugins/contextStrategyComparison/executeV043StageContextStrategy.js +46 -0
  71. package/dist/src/experiments/plugins/contextStrategyComparison/index.js +9 -0
  72. package/dist/src/experiments/plugins/contextStrategyComparison/loadV043StrategyArtifacts.js +397 -0
  73. package/dist/src/experiments/plugins/contextStrategyComparison/plugin.js +39 -1
  74. package/dist/src/experiments/plugins/contextStrategyComparison/readV043FullWorkflowLibraryFixture.js +162 -0
  75. package/dist/src/experiments/plugins/contextStrategyComparison/resolveV043StrategyInputs.js +43 -0
  76. package/dist/src/experiments/plugins/contextStrategyComparison/resultMapping.js +3 -0
  77. package/dist/src/experiments/plugins/contextStrategyComparison/runV043StageContextStrategyWithAssurance.js +205 -0
  78. package/dist/src/experiments/plugins/contextStrategyComparison/v043FullWorkflowLibraryFixture.js +1 -0
  79. package/dist/src/experiments/plugins/contextStrategyComparison/v043RunAssuranceTypes.js +1 -0
  80. package/dist/src/experiments/plugins/contextStrategyComparison/v043StrategyExecutionTypes.js +1 -0
  81. package/dist/src/experiments/plugins/contextStrategyComparison/v043StrategyIds.js +13 -0
  82. package/dist/src/experiments/plugins/contextStrategyComparison/v043StrategyInputContracts.js +1 -0
  83. package/dist/src/experiments/plugins/contextStrategyComparison/validateV043RunAssuranceConfig.js +59 -0
  84. package/dist/src/experiments/plugins/contextStrategyComparison/validateV043StrategyInput.js +266 -0
  85. package/dist/src/report/experiments/buildContextStrategyComparisonV043Report.js +520 -0
  86. package/dist/src/report/experiments/buildPluginExperimentReport.js +21 -6
  87. package/dist/src/report/experiments/contextStrategyComparisonV043ReportModel.js +1 -0
  88. package/dist/src/report/experiments/index.js +4 -0
  89. package/dist/src/report/experiments/renderContextStrategyComparisonV043Html.js +296 -0
  90. package/dist/src/report/experiments/renderPluginExperimentReportHtml.js +3 -0
  91. package/dist/src/report/experiments/renderPluginExperimentReportText.js +292 -0
  92. package/dist/src/report/experiments/writePluginExperimentReports.js +3 -0
  93. package/dist/src/securityValidation/attackScenarios/scenarios/secretLeakageScenario.js +215 -9
  94. package/docs/METRICS.md +84 -10
  95. package/package.json +2 -2
  96. package/tests/fixtures/full-workflow-library/complete-v1.0.0.json +24 -0
  97. package/tests/fixtures/full-workflow-library/future-minor-v1.1.0-additive.json +25 -0
  98. package/tests/fixtures/stage-context-expectations/complete-v1.0.0.json +230 -0
  99. package/tests/fixtures/stage-context-expectations/future-minor-v1.1.0-additive.json +232 -0
  100. package/tests/fixtures/stage-context-expectations/invalid/malformed-json.txt +1 -0
  101. package/tests/fixtures/stage-context-expectations/invalid/non-object-root.json +1 -0
  102. package/tests/fixtures/stage-context-expectations/minimal-v1.0.0.json +18 -0
  103. package/tests/fixtures/upstream-artifacts/invalid/malformed-json.txt +1 -0
  104. package/tests/fixtures/upstream-artifacts/invalid/non-object-root.json +1 -0
  105. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/context-capsule/complete-v1.0.0.json +504 -0
  106. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/context-capsule/future-minor-v1.1.0-additive.json +955 -0
  107. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/retrieval-audit-record/complete-v1.0.0.json +190 -0
  108. package/tests/fixtures/upstream-artifacts/my-dev-kit/1.10.2/retrieval-audit-record/future-minor-v1.1.0-additive.json +327 -0
  109. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/PROVENANCE.txt +13 -0
  110. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/context-capsule.json +7874 -0
  111. package/tests/fixtures/upstream-artifacts/my-dev-kit-1.10.2-identity/retrieval-audit-record.json +1076 -0
  112. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.1/workflow-instruction-packet/complete-v1.0.0.json +160 -0
  113. package/tests/fixtures/upstream-artifacts/my-dev-kit-orchestrator/1.2.1/workflow-instruction-packet/future-minor-v1.1.0-additive.json +186 -0
@@ -0,0 +1,397 @@
1
+ import { readImplementationContextPacketV1, readImplementationContextRetrievalReportV1, readMyDevKitContextCapsuleV1, readMyDevKitRetrievalAuditRecordV1, readOrchestratorWorkflowInstructionPacketV1, readTestContextPacketV1, readTestContextRetrievalReportV1, validateOrchestratorContextReadinessResultV1 } from "../../../evaluation/upstreamArtifacts/index.js";
2
+ import { checkMyDevKitContextArtifactConsistency } from "../../../evaluation/stageContextSelectors/index.js";
3
+ import { readStageContextExpectationFixtureV1 } from "../../../evaluation/stageContextExpectations/index.js";
4
+ import { readV043FullWorkflowLibraryFixture } from "./readV043FullWorkflowLibraryFixture.js";
5
+ function buildFailureResult(input, issues) {
6
+ return { status: "failed", strategyId: input.strategyId, input, issues };
7
+ }
8
+ async function loadContextArtifactPair(role, capsulePath, auditPath, pairLabel, issues) {
9
+ const capsuleResult = await readMyDevKitContextCapsuleV1(capsulePath);
10
+ if (!capsuleResult.ok) {
11
+ issues.push({
12
+ code: "CONTEXT_CAPSULE_READ_FAILED",
13
+ fieldPath: `${pairLabel}.contextCapsule`,
14
+ message: `Failed to read ContextCapsule for "${pairLabel}": ${capsuleResult.message}`,
15
+ sourcePath: capsuleResult.sourcePath,
16
+ details: capsuleResult
17
+ });
18
+ }
19
+ let auditReadOk = false;
20
+ let auditSourcePath;
21
+ let auditArtifact;
22
+ if (auditPath !== undefined) {
23
+ const auditResult = await readMyDevKitRetrievalAuditRecordV1(auditPath);
24
+ if (!auditResult.ok) {
25
+ issues.push({
26
+ code: "RETRIEVAL_AUDIT_READ_FAILED",
27
+ fieldPath: `${pairLabel}.retrievalAuditRecord`,
28
+ message: `Failed to read RetrievalAuditRecord for "${pairLabel}": ${auditResult.message}`,
29
+ sourcePath: auditResult.sourcePath,
30
+ details: auditResult
31
+ });
32
+ }
33
+ else {
34
+ auditReadOk = true;
35
+ auditSourcePath = auditResult.sourcePath;
36
+ auditArtifact = auditResult.artifact;
37
+ }
38
+ }
39
+ if (!capsuleResult.ok)
40
+ return null;
41
+ const pair = {
42
+ role,
43
+ contextCapsuleSourcePath: capsuleResult.sourcePath,
44
+ contextCapsule: capsuleResult.artifact
45
+ };
46
+ if (auditReadOk) {
47
+ pair.retrievalAuditRecordSourcePath = auditSourcePath;
48
+ pair.retrievalAuditRecord = auditArtifact;
49
+ }
50
+ return pair;
51
+ }
52
+ function validateRole(pair, expectedRole, pairLabel, issues) {
53
+ if (pair.contextCapsule.request.role !== expectedRole) {
54
+ const fieldPath = `${pairLabel}.contextCapsule.request.role`;
55
+ issues.push({
56
+ code: "CONTEXT_ROLE_MISMATCH",
57
+ fieldPath,
58
+ message: `Expected context role "${expectedRole}" but found "${pair.contextCapsule.request.role}" at "${fieldPath}".`
59
+ });
60
+ }
61
+ if (pair.contextCapsule.roleContext.role !== expectedRole) {
62
+ const fieldPath = `${pairLabel}.contextCapsule.roleContext.role`;
63
+ issues.push({
64
+ code: "CONTEXT_ROLE_MISMATCH",
65
+ fieldPath,
66
+ message: `Expected context role "${expectedRole}" but found "${pair.contextCapsule.roleContext.role}" at "${fieldPath}".`
67
+ });
68
+ }
69
+ if (pair.retrievalAuditRecord) {
70
+ if (pair.retrievalAuditRecord.request.role !== expectedRole) {
71
+ const fieldPath = `${pairLabel}.retrievalAuditRecord.request.role`;
72
+ issues.push({
73
+ code: "CONTEXT_ROLE_MISMATCH",
74
+ fieldPath,
75
+ message: `Expected context role "${expectedRole}" but found "${pair.retrievalAuditRecord.request.role}" at "${fieldPath}".`
76
+ });
77
+ }
78
+ if (pair.retrievalAuditRecord.roleContext.role !== expectedRole) {
79
+ const fieldPath = `${pairLabel}.retrievalAuditRecord.roleContext.role`;
80
+ issues.push({
81
+ code: "CONTEXT_ROLE_MISMATCH",
82
+ fieldPath,
83
+ message: `Expected context role "${expectedRole}" but found "${pair.retrievalAuditRecord.roleContext.role}" at "${fieldPath}".`
84
+ });
85
+ }
86
+ }
87
+ }
88
+ function checkPairConsistency(pair, pairLabel, issues) {
89
+ if (!pair.retrievalAuditRecord)
90
+ return;
91
+ const consistency = checkMyDevKitContextArtifactConsistency(pair.contextCapsule, pair.retrievalAuditRecord);
92
+ pair.consistency = consistency;
93
+ if (!consistency.consistent) {
94
+ for (const consistencyIssue of consistency.issues) {
95
+ const prefixedFieldPath = `${pairLabel}.${consistencyIssue.fieldPath}`;
96
+ issues.push({
97
+ code: "CONTEXT_ARTIFACT_INCONSISTENT",
98
+ fieldPath: prefixedFieldPath,
99
+ message: `ContextCapsule and RetrievalAuditRecord are inconsistent at "${prefixedFieldPath}".`,
100
+ details: consistencyIssue
101
+ });
102
+ }
103
+ }
104
+ }
105
+ function validatePairsInOrder(entries, issues) {
106
+ for (const entry of entries) {
107
+ validateRole(entry.pair, entry.role, entry.label, issues);
108
+ checkPairConsistency(entry.pair, entry.label, issues);
109
+ }
110
+ }
111
+ export async function loadV043StrategyArtifacts(input) {
112
+ const issues = [];
113
+ const expectationsResult = await readStageContextExpectationFixtureV1(input.expectationsPath);
114
+ if (!expectationsResult.ok) {
115
+ issues.push({
116
+ code: "EXPECTATION_READ_FAILED",
117
+ fieldPath: "expectations",
118
+ message: `Failed to read stage-context expectation fixture: ${expectationsResult.message}`,
119
+ sourcePath: expectationsResult.sourcePath,
120
+ details: expectationsResult
121
+ });
122
+ }
123
+ switch (input.strategyId) {
124
+ case "architecture-context-only": {
125
+ const architecture = await loadContextArtifactPair("architecture", input.architectureContextCapsulePath, input.architectureRetrievalAuditRecordPath, "architecture", issues);
126
+ const entries = [];
127
+ if (architecture)
128
+ entries.push({ pair: architecture, role: "architecture", label: "architecture" });
129
+ validatePairsInOrder(entries, issues);
130
+ if (issues.length > 0 || !expectationsResult.ok || !architecture) {
131
+ return buildFailureResult(input, issues);
132
+ }
133
+ return {
134
+ status: "completed",
135
+ strategyId: input.strategyId,
136
+ input,
137
+ expectationsSourcePath: expectationsResult.sourcePath,
138
+ expectations: expectationsResult.fixture,
139
+ payload: { architecture },
140
+ warnings: []
141
+ };
142
+ }
143
+ case "architecture-plus-implementation-refresh": {
144
+ const architecture = await loadContextArtifactPair("architecture", input.architectureContextCapsulePath, input.architectureRetrievalAuditRecordPath, "architecture", issues);
145
+ const implementation = await loadContextArtifactPair("implementation", input.implementationContextCapsulePath, input.implementationRetrievalAuditRecordPath, "implementation", issues);
146
+ const entries = [];
147
+ if (architecture)
148
+ entries.push({ pair: architecture, role: "architecture", label: "architecture" });
149
+ if (implementation)
150
+ entries.push({ pair: implementation, role: "implementation", label: "implementation" });
151
+ validatePairsInOrder(entries, issues);
152
+ if (issues.length > 0 || !expectationsResult.ok || !architecture || !implementation) {
153
+ return buildFailureResult(input, issues);
154
+ }
155
+ return {
156
+ status: "completed",
157
+ strategyId: input.strategyId,
158
+ input,
159
+ expectationsSourcePath: expectationsResult.sourcePath,
160
+ expectations: expectationsResult.fixture,
161
+ payload: { architecture, implementation },
162
+ warnings: []
163
+ };
164
+ }
165
+ case "architecture-plus-implementation-and-test-refresh": {
166
+ const architecture = await loadContextArtifactPair("architecture", input.architectureContextCapsulePath, input.architectureRetrievalAuditRecordPath, "architecture", issues);
167
+ const implementation = await loadContextArtifactPair("implementation", input.implementationContextCapsulePath, input.implementationRetrievalAuditRecordPath, "implementation", issues);
168
+ const testImplementation = await loadContextArtifactPair("test-implementation", input.testImplementationContextCapsulePath, input.testImplementationRetrievalAuditRecordPath, "testImplementation", issues);
169
+ const entries = [];
170
+ if (architecture)
171
+ entries.push({ pair: architecture, role: "architecture", label: "architecture" });
172
+ if (implementation)
173
+ entries.push({ pair: implementation, role: "implementation", label: "implementation" });
174
+ if (testImplementation) {
175
+ entries.push({ pair: testImplementation, role: "test-implementation", label: "testImplementation" });
176
+ }
177
+ validatePairsInOrder(entries, issues);
178
+ if (issues.length > 0 || !expectationsResult.ok || !architecture || !implementation || !testImplementation) {
179
+ return buildFailureResult(input, issues);
180
+ }
181
+ return {
182
+ status: "completed",
183
+ strategyId: input.strategyId,
184
+ input,
185
+ expectationsSourcePath: expectationsResult.sourcePath,
186
+ expectations: expectationsResult.fixture,
187
+ payload: { architecture, implementation, testImplementation },
188
+ warnings: []
189
+ };
190
+ }
191
+ case "full-workflow-library": {
192
+ const libraryResult = await readV043FullWorkflowLibraryFixture(input.fullWorkflowLibraryFixturePath);
193
+ if (!libraryResult.ok) {
194
+ issues.push({
195
+ code: "FULL_WORKFLOW_LIBRARY_READ_FAILED",
196
+ fieldPath: "fullWorkflowLibrary",
197
+ message: `Failed to read full-workflow-library fixture: ${libraryResult.message}`,
198
+ sourcePath: libraryResult.sourcePath,
199
+ details: libraryResult
200
+ });
201
+ }
202
+ if (issues.length > 0 || !expectationsResult.ok || !libraryResult.ok) {
203
+ return buildFailureResult(input, issues);
204
+ }
205
+ return {
206
+ status: "completed",
207
+ strategyId: input.strategyId,
208
+ input,
209
+ expectationsSourcePath: expectationsResult.sourcePath,
210
+ expectations: expectationsResult.fixture,
211
+ payload: {
212
+ fullWorkflowLibrarySourcePath: libraryResult.sourcePath,
213
+ fullWorkflowLibrary: libraryResult.fixture
214
+ },
215
+ warnings: []
216
+ };
217
+ }
218
+ case "bounded-workflow-instruction-packet": {
219
+ const packetResult = await readOrchestratorWorkflowInstructionPacketV1(input.workflowInstructionPacketPath);
220
+ if (!packetResult.ok) {
221
+ issues.push({
222
+ code: "WORKFLOW_PACKET_READ_FAILED",
223
+ fieldPath: "workflowInstructionPacket",
224
+ message: `Failed to read WorkflowInstructionPacket: ${packetResult.message}`,
225
+ sourcePath: packetResult.sourcePath,
226
+ details: packetResult
227
+ });
228
+ }
229
+ if (issues.length > 0 || !expectationsResult.ok || !packetResult.ok) {
230
+ return buildFailureResult(input, issues);
231
+ }
232
+ return {
233
+ status: "completed",
234
+ strategyId: input.strategyId,
235
+ input,
236
+ expectationsSourcePath: expectationsResult.sourcePath,
237
+ expectations: expectationsResult.fixture,
238
+ payload: {
239
+ workflowInstructionPacketSourcePath: packetResult.sourcePath,
240
+ workflowInstructionPacket: packetResult.artifact
241
+ },
242
+ warnings: []
243
+ };
244
+ }
245
+ case "combined-bounded-stage-context": {
246
+ const pairs = [];
247
+ const entries = [];
248
+ for (let index = 0; index < input.contextArtifacts.length; index += 1) {
249
+ const contextArtifact = input.contextArtifacts[index];
250
+ const pairLabel = `contextArtifacts[${index}]`;
251
+ const pair = await loadContextArtifactPair(contextArtifact.role, contextArtifact.contextCapsulePath, contextArtifact.retrievalAuditRecordPath, pairLabel, issues);
252
+ if (pair) {
253
+ pairs.push(pair);
254
+ entries.push({ pair, role: contextArtifact.role, label: pairLabel });
255
+ }
256
+ }
257
+ validatePairsInOrder(entries, issues);
258
+ const packetResult = await readOrchestratorWorkflowInstructionPacketV1(input.workflowInstructionPacketPath);
259
+ if (!packetResult.ok) {
260
+ issues.push({
261
+ code: "WORKFLOW_PACKET_READ_FAILED",
262
+ fieldPath: "workflowInstructionPacket",
263
+ message: `Failed to read WorkflowInstructionPacket: ${packetResult.message}`,
264
+ sourcePath: packetResult.sourcePath,
265
+ details: packetResult
266
+ });
267
+ }
268
+ // v0.4.4 Batch 3: producer-readiness bridge inputs -- every one is optional (section
269
+ // 11.2). Only a supplied-but-unreadable source becomes a load failure; an absent
270
+ // source is simply left off the payload for the bridge evaluator to treat as
271
+ // unavailable/not-applicable.
272
+ let implementationContextPacketSourcePath;
273
+ let implementationContextPacket;
274
+ if (input.implementationContextPacketPath !== undefined) {
275
+ const result = await readImplementationContextPacketV1(input.implementationContextPacketPath);
276
+ if (!result.ok) {
277
+ issues.push({
278
+ code: "IMPLEMENTATION_CONTEXT_PACKET_READ_FAILED",
279
+ fieldPath: "implementationContextPacket",
280
+ message: `Failed to read implementation-context packet: ${result.message}`,
281
+ sourcePath: result.sourcePath,
282
+ details: result
283
+ });
284
+ }
285
+ else {
286
+ implementationContextPacketSourcePath = result.sourcePath;
287
+ implementationContextPacket = result.artifact;
288
+ }
289
+ }
290
+ let implementationContextRetrievalReportSourcePath;
291
+ let implementationContextRetrievalReport;
292
+ if (input.implementationContextRetrievalReportPath !== undefined) {
293
+ const result = await readImplementationContextRetrievalReportV1(input.implementationContextRetrievalReportPath);
294
+ if (!result.ok) {
295
+ issues.push({
296
+ code: "IMPLEMENTATION_CONTEXT_RETRIEVAL_REPORT_READ_FAILED",
297
+ fieldPath: "implementationContextRetrievalReport",
298
+ message: `Failed to read implementation-context retrieval report: ${result.message}`,
299
+ sourcePath: result.sourcePath,
300
+ details: result
301
+ });
302
+ }
303
+ else {
304
+ implementationContextRetrievalReportSourcePath = result.sourcePath;
305
+ implementationContextRetrievalReport = result.artifact;
306
+ }
307
+ }
308
+ let testContextPacketSourcePath;
309
+ let testContextPacket;
310
+ if (input.testContextPacketPath !== undefined) {
311
+ const result = await readTestContextPacketV1(input.testContextPacketPath);
312
+ if (!result.ok) {
313
+ issues.push({
314
+ code: "TEST_CONTEXT_PACKET_READ_FAILED",
315
+ fieldPath: "testContextPacket",
316
+ message: `Failed to read test-context packet: ${result.message}`,
317
+ sourcePath: result.sourcePath,
318
+ details: result
319
+ });
320
+ }
321
+ else {
322
+ testContextPacketSourcePath = result.sourcePath;
323
+ testContextPacket = result.artifact;
324
+ }
325
+ }
326
+ let testContextRetrievalReportSourcePath;
327
+ let testContextRetrievalReport;
328
+ if (input.testContextRetrievalReportPath !== undefined) {
329
+ const result = await readTestContextRetrievalReportV1(input.testContextRetrievalReportPath);
330
+ if (!result.ok) {
331
+ issues.push({
332
+ code: "TEST_CONTEXT_RETRIEVAL_REPORT_READ_FAILED",
333
+ fieldPath: "testContextRetrievalReport",
334
+ message: `Failed to read test-context retrieval report: ${result.message}`,
335
+ sourcePath: result.sourcePath,
336
+ details: result
337
+ });
338
+ }
339
+ else {
340
+ testContextRetrievalReportSourcePath = result.sourcePath;
341
+ testContextRetrievalReport = result.artifact;
342
+ }
343
+ }
344
+ let readiness;
345
+ if (input.readiness !== undefined) {
346
+ const readinessResult = validateOrchestratorContextReadinessResultV1(input.readiness, "programmatic-input:readiness");
347
+ if (!readinessResult.ok) {
348
+ issues.push({
349
+ code: "READINESS_INPUT_INVALID",
350
+ fieldPath: "readiness",
351
+ message: `Readiness programmatic input is invalid: ${readinessResult.message}`,
352
+ details: readinessResult
353
+ });
354
+ }
355
+ else {
356
+ readiness = readinessResult.artifact;
357
+ }
358
+ }
359
+ if (issues.length > 0 || !expectationsResult.ok || !packetResult.ok || pairs.length !== input.contextArtifacts.length) {
360
+ return buildFailureResult(input, issues);
361
+ }
362
+ const payload = {
363
+ contextArtifacts: pairs,
364
+ workflowInstructionPacketSourcePath: packetResult.sourcePath,
365
+ workflowInstructionPacket: packetResult.artifact
366
+ };
367
+ if (implementationContextPacket !== undefined) {
368
+ payload.implementationContextPacketSourcePath = implementationContextPacketSourcePath;
369
+ payload.implementationContextPacket = implementationContextPacket;
370
+ }
371
+ if (implementationContextRetrievalReport !== undefined) {
372
+ payload.implementationContextRetrievalReportSourcePath = implementationContextRetrievalReportSourcePath;
373
+ payload.implementationContextRetrievalReport = implementationContextRetrievalReport;
374
+ }
375
+ if (testContextPacket !== undefined) {
376
+ payload.testContextPacketSourcePath = testContextPacketSourcePath;
377
+ payload.testContextPacket = testContextPacket;
378
+ }
379
+ if (testContextRetrievalReport !== undefined) {
380
+ payload.testContextRetrievalReportSourcePath = testContextRetrievalReportSourcePath;
381
+ payload.testContextRetrievalReport = testContextRetrievalReport;
382
+ }
383
+ if (readiness !== undefined) {
384
+ payload.readiness = readiness;
385
+ }
386
+ return {
387
+ status: "completed",
388
+ strategyId: input.strategyId,
389
+ input,
390
+ expectationsSourcePath: expectationsResult.sourcePath,
391
+ expectations: expectationsResult.fixture,
392
+ payload,
393
+ warnings: []
394
+ };
395
+ }
396
+ }
397
+ }
@@ -3,6 +3,10 @@ import path from "node:path";
3
3
  import { runControlledExperiment } from "../../../evaluation/runControlledExperiment.js";
4
4
  import { defaultContextStrategyComparisonConfig, validateContextStrategyComparisonConfig, } from "./config.js";
5
5
  import { mapLegacyArtifactsToExperimentRun, } from "./resultMapping.js";
6
+ import { resolveV043StrategyInputs } from "./resolveV043StrategyInputs.js";
7
+ import { V043_STAGE_CONTEXT_STRATEGY_IDS } from "./v043StrategyIds.js";
8
+ import { validateV043RunAssuranceConfig } from "./validateV043RunAssuranceConfig.js";
9
+ import { runV043StageContextStrategyWithAssurance } from "./runV043StageContextStrategyWithAssurance.js";
6
10
  export const contextStrategyComparisonMetadata = {
7
11
  id: "context-strategy-comparison",
8
12
  name: "Context Strategy Comparison",
@@ -12,6 +16,9 @@ export const contextStrategyComparisonMetadata = {
12
16
  supportedTargets: ["self", "external-local"],
13
17
  supportedOutputs: ["json", "html", "plot", "screenshot", "artifact"],
14
18
  };
19
+ function isV043StrategyId(value) {
20
+ return V043_STAGE_CONTEXT_STRATEGY_IDS.includes(value);
21
+ }
15
22
  export const contextStrategyComparisonPlugin = {
16
23
  metadata: contextStrategyComparisonMetadata,
17
24
  defaultConfig: defaultContextStrategyComparisonConfig,
@@ -31,13 +38,41 @@ export const contextStrategyComparisonPlugin = {
31
38
  const projectProfiles = readInputArray(context.inputs, "projectProfiles");
32
39
  const env = readEnv(context.inputs);
33
40
  const startedAt = context.startedAt.toISOString();
41
+ const selectedStrategyIds = context.config.strategies ?? defaultContextStrategyComparisonConfig.strategies ?? [];
42
+ const providedV043Inputs = context.config.v043StrategyInputs ?? [];
43
+ const resolution = resolveV043StrategyInputs(selectedStrategyIds, providedV043Inputs);
44
+ if (!resolution.ok) {
45
+ const issuesText = resolution.issues.map((issue) => `${issue.code}:${issue.strategyId}`).join(", ");
46
+ throw new Error(`Invalid v0.4.3 strategy-input configuration: ${issuesText}`);
47
+ }
48
+ const runAssuranceValidation = validateV043RunAssuranceConfig(context.config.v043RunAssurance);
49
+ if (!runAssuranceValidation.ok) {
50
+ const issuesText = runAssuranceValidation.issues.map((issue) => `${issue.code}:${issue.fieldPath}`).join(", ");
51
+ throw new Error(`Invalid v0.4.3 run-assurance configuration: ${issuesText}`);
52
+ }
53
+ const runAssuranceConfig = runAssuranceValidation.config;
54
+ const legacyStrategyIds = selectedStrategyIds.filter((strategyId) => !isV043StrategyId(strategyId));
55
+ const legacyConfig = { ...context.config, strategies: legacyStrategyIds };
34
56
  const legacyArtifacts = await runControlledExperiment({
35
- config: context.config,
57
+ config: legacyConfig,
36
58
  cases,
37
59
  projectProfiles,
38
60
  repoRoot: context.target.targetRoot,
39
61
  env,
40
62
  });
63
+ const v043SelectedStrategyIds = selectedStrategyIds.filter(isV043StrategyId);
64
+ const v043StageContextExecutions = [];
65
+ const v043StageContextEvaluations = [];
66
+ const v043StageContextRunAssurance = [];
67
+ for (const strategyId of v043SelectedStrategyIds) {
68
+ const input = resolution.inputByStrategyId[strategyId];
69
+ if (!input)
70
+ continue;
71
+ const assurance = await runV043StageContextStrategyWithAssurance(input, runAssuranceConfig);
72
+ v043StageContextExecutions.push(assurance.primaryExecution);
73
+ v043StageContextEvaluations.push(assurance.primaryEvaluation);
74
+ v043StageContextRunAssurance.push(assurance);
75
+ }
41
76
  const completedAt = new Date().toISOString();
42
77
  const outDir = context.outputRoot ?? path.resolve(context.toolRoot, context.config.outDir);
43
78
  await mkdir(outDir, { recursive: true });
@@ -48,6 +83,9 @@ export const contextStrategyComparisonPlugin = {
48
83
  completedAt,
49
84
  target: context.target,
50
85
  legacyArtifacts,
86
+ v043StageContextExecutions,
87
+ v043StageContextEvaluations,
88
+ v043StageContextRunAssurance,
51
89
  pluginResultPath,
52
90
  });
53
91
  await writeFile(pluginResultPath, `${JSON.stringify(redactLegacyArtifacts(result), null, 2)}\n`, "utf8");
@@ -0,0 +1,162 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const SCHEMA_VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+$/;
4
+ const FIXTURE_ID_PATTERN = /^FULL-WORKFLOW-LIBRARY-[A-Z0-9]+(?:-[A-Z0-9]+)*-[0-9]{3}$/;
5
+ const REQUIRED_NONEMPTY_ID_ARRAY_FIELDS = [
6
+ "workflowIds",
7
+ "stageIds",
8
+ "commandIds",
9
+ "ruleIds",
10
+ "reportContractIds"
11
+ ];
12
+ const ALL_ID_ARRAY_FIELDS = [
13
+ ...REQUIRED_NONEMPTY_ID_ARRAY_FIELDS,
14
+ "provenanceEvidenceIds"
15
+ ];
16
+ function failure(sourcePath, code, message, extra) {
17
+ return { ok: false, sourcePath, code, message, ...extra };
18
+ }
19
+ function isStringArray(value) {
20
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
21
+ }
22
+ function hasDuplicates(values) {
23
+ return new Set(values).size !== values.length;
24
+ }
25
+ function validateFullWorkflowLibraryFixture(value, sourcePath) {
26
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
27
+ return failure(sourcePath, "NON_OBJECT_ROOT", "Full-workflow-library fixture must parse to a JSON object at the root.", {
28
+ expected: "object",
29
+ actual: value
30
+ });
31
+ }
32
+ const root = value;
33
+ if (root.schemaVersion === undefined) {
34
+ return failure(sourcePath, "MISSING_REQUIRED_FIELD", "schemaVersion is required.", { fieldPath: "schemaVersion" });
35
+ }
36
+ if (typeof root.schemaVersion !== "string") {
37
+ return failure(sourcePath, "INVALID_FIELD_TYPE", "schemaVersion must be a string.", { fieldPath: "schemaVersion" });
38
+ }
39
+ if (!SCHEMA_VERSION_PATTERN.test(root.schemaVersion)) {
40
+ return failure(sourcePath, "INVALID_SCHEMA_VERSION", `schemaVersion "${root.schemaVersion}" does not match x.y.z.`, {
41
+ fieldPath: "schemaVersion",
42
+ actual: root.schemaVersion
43
+ });
44
+ }
45
+ const schemaVersionValue = root.schemaVersion;
46
+ const schemaMajor = Number(schemaVersionValue.split(".")[0]);
47
+ if (schemaMajor !== 1) {
48
+ return failure(sourcePath, "UNSUPPORTED_SCHEMA_MAJOR", `schemaVersion major "${schemaMajor}" is not supported.`, {
49
+ fieldPath: "schemaVersion",
50
+ actual: schemaVersionValue
51
+ });
52
+ }
53
+ if (root.fixtureId === undefined) {
54
+ return failure(sourcePath, "MISSING_REQUIRED_FIELD", "fixtureId is required.", { fieldPath: "fixtureId" });
55
+ }
56
+ if (typeof root.fixtureId !== "string") {
57
+ return failure(sourcePath, "INVALID_FIELD_TYPE", "fixtureId must be a string.", { fieldPath: "fixtureId" });
58
+ }
59
+ if (!FIXTURE_ID_PATTERN.test(root.fixtureId)) {
60
+ return failure(sourcePath, "INVALID_FIXTURE_ID", `fixtureId "${root.fixtureId}" does not match the required pattern.`, {
61
+ fieldPath: "fixtureId",
62
+ actual: root.fixtureId
63
+ });
64
+ }
65
+ for (const field of ["title", "description"]) {
66
+ const fieldValue = root[field];
67
+ if (fieldValue === undefined) {
68
+ return failure(sourcePath, "MISSING_REQUIRED_FIELD", `${field} is required.`, { fieldPath: field });
69
+ }
70
+ if (typeof fieldValue !== "string") {
71
+ return failure(sourcePath, "INVALID_FIELD_TYPE", `${field} must be a string.`, { fieldPath: field });
72
+ }
73
+ if (fieldValue.trim().length === 0) {
74
+ return failure(sourcePath, "INVALID_FIELD_TYPE", `${field} must be a nonempty string.`, { fieldPath: field });
75
+ }
76
+ }
77
+ for (const field of ALL_ID_ARRAY_FIELDS) {
78
+ const fieldValue = root[field];
79
+ if (fieldValue === undefined) {
80
+ return failure(sourcePath, "MISSING_REQUIRED_FIELD", `${field} is required.`, { fieldPath: field });
81
+ }
82
+ if (!isStringArray(fieldValue)) {
83
+ return failure(sourcePath, "INVALID_FIELD_TYPE", `${field} must be an array of strings.`, { fieldPath: field });
84
+ }
85
+ if (fieldValue.some((entry) => entry.length === 0)) {
86
+ return failure(sourcePath, "INVALID_FIELD_TYPE", `${field} entries must be nonempty strings.`, { fieldPath: field });
87
+ }
88
+ }
89
+ for (const field of REQUIRED_NONEMPTY_ID_ARRAY_FIELDS) {
90
+ const fieldValue = root[field];
91
+ if (fieldValue.length === 0) {
92
+ return failure(sourcePath, "EMPTY_REQUIRED_ID_SET", `${field} must contain at least one entry.`, { fieldPath: field });
93
+ }
94
+ }
95
+ for (const field of ALL_ID_ARRAY_FIELDS) {
96
+ const fieldValue = root[field];
97
+ if (hasDuplicates(fieldValue)) {
98
+ return failure(sourcePath, "DUPLICATE_ID", `${field} contains duplicate entries.`, { fieldPath: field });
99
+ }
100
+ }
101
+ if (root.rawText === undefined) {
102
+ return failure(sourcePath, "MISSING_REQUIRED_FIELD", "rawText is required.", { fieldPath: "rawText" });
103
+ }
104
+ if (typeof root.rawText !== "string") {
105
+ return failure(sourcePath, "INVALID_FIELD_TYPE", "rawText must be a string.", { fieldPath: "rawText" });
106
+ }
107
+ if (root.rawText.trim().length === 0) {
108
+ return failure(sourcePath, "EMPTY_RAW_TEXT", "rawText must be a nonempty string.", { fieldPath: "rawText" });
109
+ }
110
+ if (root.warnings === undefined) {
111
+ return failure(sourcePath, "MISSING_REQUIRED_FIELD", "warnings is required.", { fieldPath: "warnings" });
112
+ }
113
+ if (!isStringArray(root.warnings)) {
114
+ return failure(sourcePath, "INVALID_FIELD_TYPE", "warnings must be an array of strings.", { fieldPath: "warnings" });
115
+ }
116
+ const fixture = value;
117
+ return {
118
+ ok: true,
119
+ sourcePath,
120
+ schemaVersion: schemaVersionValue,
121
+ schemaMajor: 1,
122
+ fixture,
123
+ rawFixture: fixture
124
+ };
125
+ }
126
+ export async function readV043FullWorkflowLibraryFixture(sourcePathInput) {
127
+ const sourcePath = path.resolve(sourcePathInput);
128
+ let raw;
129
+ try {
130
+ raw = await readFile(sourcePath, "utf8");
131
+ }
132
+ catch (error) {
133
+ const code = error.code;
134
+ if (code === "ENOENT") {
135
+ return {
136
+ ok: false,
137
+ sourcePath,
138
+ code: "FILE_NOT_FOUND",
139
+ message: `Full-workflow-library fixture was not found at "${sourcePath}".`
140
+ };
141
+ }
142
+ return {
143
+ ok: false,
144
+ sourcePath,
145
+ code: "UNREADABLE_FILE",
146
+ message: `Full-workflow-library fixture at "${sourcePath}" could not be read: ${error.message}`
147
+ };
148
+ }
149
+ let parsed;
150
+ try {
151
+ parsed = JSON.parse(raw);
152
+ }
153
+ catch (error) {
154
+ return {
155
+ ok: false,
156
+ sourcePath,
157
+ code: "MALFORMED_JSON",
158
+ message: `Full-workflow-library fixture at "${sourcePath}" is not valid JSON: ${error.message}`
159
+ };
160
+ }
161
+ return validateFullWorkflowLibraryFixture(parsed, sourcePath);
162
+ }
@@ -0,0 +1,43 @@
1
+ import { V043_STAGE_CONTEXT_STRATEGY_IDS } from "./v043StrategyIds.js";
2
+ function isV043StrategyId(value) {
3
+ return V043_STAGE_CONTEXT_STRATEGY_IDS.includes(value);
4
+ }
5
+ export function resolveV043StrategyInputs(selectedStrategyIds, providedInputs) {
6
+ const issues = [];
7
+ const inputByStrategyId = {};
8
+ const selectedV043Ids = selectedStrategyIds.filter(isV043StrategyId);
9
+ for (const strategyId of selectedV043Ids) {
10
+ const matches = providedInputs.filter((input) => input.strategyId === strategyId);
11
+ if (matches.length === 0) {
12
+ issues.push({
13
+ code: "MISSING_STRATEGY_INPUT",
14
+ strategyId,
15
+ message: `No strategy input was supplied for selected strategy "${strategyId}".`
16
+ });
17
+ }
18
+ else if (matches.length > 1) {
19
+ issues.push({
20
+ code: "DUPLICATE_STRATEGY_INPUT",
21
+ strategyId,
22
+ message: `More than one strategy input was supplied for selected strategy "${strategyId}".`
23
+ });
24
+ }
25
+ else {
26
+ inputByStrategyId[strategyId] = matches[0];
27
+ }
28
+ }
29
+ const selectedV043IdSet = new Set(selectedV043Ids);
30
+ for (const input of providedInputs) {
31
+ if (!selectedV043IdSet.has(input.strategyId)) {
32
+ issues.push({
33
+ code: "INPUT_STRATEGY_NOT_SELECTED",
34
+ strategyId: input.strategyId,
35
+ message: `A strategy input was supplied for "${input.strategyId}", which was not selected.`
36
+ });
37
+ }
38
+ }
39
+ if (issues.length > 0) {
40
+ return { ok: false, issues };
41
+ }
42
+ return { ok: true, inputByStrategyId };
43
+ }