@exaudeus/workrail 3.17.0 → 3.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +13 -0
  2. package/dist/application/services/validation-engine.js +7 -11
  3. package/dist/application/services/workflow-compiler.js +9 -11
  4. package/dist/console/assets/index-DMaX2-CW.js +28 -0
  5. package/dist/console/assets/index-ibLhWBmX.css +1 -0
  6. package/dist/console/index.html +2 -2
  7. package/dist/infrastructure/storage/workflow-resolution.js +6 -6
  8. package/dist/manifest.json +55 -55
  9. package/dist/mcp/handlers/v2-advance-core/assessment-consequences.d.ts +1 -1
  10. package/dist/mcp/handlers/v2-advance-core/assessment-consequences.js +14 -11
  11. package/dist/mcp/handlers/v2-advance-core/assessment-validation.d.ts +5 -3
  12. package/dist/mcp/handlers/v2-advance-core/assessment-validation.js +109 -87
  13. package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +0 -4
  14. package/dist/mcp/handlers/v2-advance-core/input-validation.js +1 -3
  15. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +8 -3
  16. package/dist/mcp/handlers/v2-advance-core/outcome-success.js +8 -3
  17. package/dist/mcp/handlers/v2-execution/replay.js +4 -4
  18. package/dist/mcp/output-schemas.d.ts +12 -12
  19. package/dist/mcp/output-schemas.js +10 -11
  20. package/dist/mcp-server.js +0 -0
  21. package/dist/types/workflow-source.js +1 -1
  22. package/dist/v2/durable-core/domain/observation-builder.d.ts +0 -3
  23. package/dist/v2/durable-core/domain/observation-builder.js +1 -3
  24. package/dist/v2/durable-core/domain/prompt-renderer.js +9 -1
  25. package/dist/v2/infra/local/session-summary-provider/index.js +1 -2
  26. package/dist/v2/projections/resume-ranking.d.ts +0 -1
  27. package/dist/v2/usecases/console-routes.js +65 -17
  28. package/dist/v2/usecases/console-service.js +4 -14
  29. package/dist/v2/usecases/console-types.d.ts +15 -1
  30. package/dist/v2/usecases/worktree-service.d.ts +1 -0
  31. package/dist/v2/usecases/worktree-service.js +143 -15
  32. package/package.json +3 -2
  33. package/spec/authoring-spec.json +3 -3
  34. package/spec/workflow.schema.json +1 -2
  35. package/workflows/coding-task-workflow-agentic.lean.v2.json +132 -1
  36. package/workflows/mr-review-workflow.agentic.v2.json +24 -10
  37. package/workflows/workflow-for-workflows.json +558 -448
  38. package/dist/console/assets/index-BZNM03t1.css +0 -1
  39. package/dist/console/assets/index-BwJelCXK.js +0 -28
@@ -38,39 +38,6 @@ function extractSubmittedRationale(value) {
38
38
  const trimmed = value.rationale?.trim();
39
39
  return trimmed && trimmed.length > 0 ? trimmed : undefined;
40
40
  }
41
- function buildDefinitionLookup(assessments, step) {
42
- const refs = step.assessmentRefs ?? [];
43
- if (refs.length === 0) {
44
- return {
45
- definition: undefined,
46
- issues: [],
47
- suggestions: [],
48
- };
49
- }
50
- if (!assessments || assessments.length === 0) {
51
- return {
52
- definition: undefined,
53
- issues: [`Step "${step.id}" expects assessment input, but the workflow declares no assessments.`],
54
- suggestions: ['Update the workflow definition to declare the assessments referenced by this step.'],
55
- };
56
- }
57
- if (refs.length > 1) {
58
- return {
59
- definition: undefined,
60
- issues: [`Step "${step.id}" declares multiple assessmentRefs. Assessment boundary validation currently supports exactly one assessment per step.`],
61
- suggestions: ['Reduce assessmentRefs to a single assessment for this step in v1.'],
62
- };
63
- }
64
- const definition = assessments.find((assessment) => assessment.id === refs[0]);
65
- if (!definition) {
66
- return {
67
- definition: undefined,
68
- issues: [`Step "${step.id}" references undeclared assessment "${refs[0]}".`],
69
- suggestions: [`Declare assessment "${refs[0]}" on the workflow or remove the step reference.`],
70
- };
71
- }
72
- return { definition, issues: [], suggestions: [] };
73
- }
74
41
  function validateDimension(dimension, artifact, issues, suggestions, warnings, recordedDimensions) {
75
42
  const submitted = artifact.dimensions[dimension.id];
76
43
  if (submitted === undefined) {
@@ -111,103 +78,158 @@ function validateDimension(dimension, artifact, issues, suggestions, warnings, r
111
78
  }
112
79
  }
113
80
  }
114
- function validateAssessmentForStep(args) {
115
- if (!args.step.assessmentRefs || args.step.assessmentRefs.length === 0)
116
- return undefined;
117
- const lookup = buildDefinitionLookup(args.assessments, args.step);
118
- if (!lookup.definition) {
81
+ function validateSingleAssessment(args) {
82
+ const assessmentArtifacts = args.artifacts
83
+ .map((artifact, index) => ({ artifact, index }))
84
+ .filter(({ artifact }) => typeof artifact === 'object' && artifact !== null && artifact.kind === 'wr.assessment');
85
+ if (assessmentArtifacts.length === 0) {
119
86
  return {
120
- contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
87
+ issues: [`This step requires an assessment submission for "${args.definition.id}".`],
88
+ suggestions: [
89
+ `Provide an artifact with kind "wr.assessment" for assessment "${args.definition.id}".`,
90
+ `Include dimension values for: ${args.definition.dimensions.map((dimension) => `${dimension.id} (${dimension.levels.join(' | ')})`).join(', ')}.`,
91
+ ],
92
+ warnings: [],
121
93
  acceptedArtifact: undefined,
122
94
  acceptedArtifactIndex: undefined,
123
95
  recordedAssessment: undefined,
124
- validation: {
125
- valid: false,
126
- issues: [...lookup.issues],
127
- suggestions: [...lookup.suggestions],
128
- },
129
96
  };
130
97
  }
131
- const assessmentArtifacts = args.artifacts
132
- .map((artifact, index) => ({ artifact, index }))
133
- .filter(({ artifact }) => typeof artifact === 'object' && artifact !== null && artifact.kind === 'wr.assessment');
134
- if (assessmentArtifacts.length === 0) {
98
+ const candidateEntry = args.isSingleRef
99
+ ? assessmentArtifacts[0]
100
+ : assessmentArtifacts.find(({ artifact }) => {
101
+ const parsed = (0, index_js_1.parseAssessmentArtifact)(artifact);
102
+ return parsed?.assessmentId === args.definition.id;
103
+ });
104
+ if (!candidateEntry) {
135
105
  return {
136
- contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
106
+ issues: [`Missing assessment artifact for "${args.definition.id}". Provide an artifact with kind "wr.assessment" and assessmentId "${args.definition.id}".`],
107
+ suggestions: [
108
+ `Include dimension values for: ${args.definition.dimensions.map((d) => `${d.id} (${d.levels.join(' | ')})`).join(', ')}.`,
109
+ ],
110
+ warnings: [],
137
111
  acceptedArtifact: undefined,
138
112
  acceptedArtifactIndex: undefined,
139
113
  recordedAssessment: undefined,
140
- validation: {
141
- valid: false,
142
- issues: [`This step requires an assessment submission for "${lookup.definition.id}".`],
143
- suggestions: [
144
- `Provide an artifact with kind "wr.assessment" for assessment "${lookup.definition.id}".`,
145
- `Include dimension values for: ${lookup.definition.dimensions.map((dimension) => `${dimension.id} (${dimension.levels.join(' | ')})`).join(', ')}.`,
146
- ],
147
- },
148
114
  };
149
115
  }
150
- const acceptedCandidate = assessmentArtifacts[0];
151
- const parsed = (0, index_js_1.parseAssessmentArtifact)(acceptedCandidate.artifact);
116
+ const parsed = (0, index_js_1.parseAssessmentArtifact)(candidateEntry.artifact);
152
117
  if (!parsed) {
153
118
  return {
154
- contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
119
+ issues: ['Assessment artifact is malformed or does not match the expected shape.'],
120
+ suggestions: [
121
+ `Use an artifact with kind "wr.assessment", a dimensions object, and canonical dimension values for assessment "${args.definition.id}".`,
122
+ ],
123
+ warnings: [],
155
124
  acceptedArtifact: undefined,
156
125
  acceptedArtifactIndex: undefined,
157
126
  recordedAssessment: undefined,
158
- validation: {
159
- valid: false,
160
- issues: ['Assessment artifact is malformed or does not match the expected shape.'],
161
- suggestions: [
162
- `Use an artifact with kind "wr.assessment", a dimensions object, and canonical dimension values for assessment "${lookup.definition.id}".`,
163
- ],
164
- },
165
127
  };
166
128
  }
167
- if (parsed.assessmentId && parsed.assessmentId !== lookup.definition.id) {
129
+ if (parsed.assessmentId && parsed.assessmentId !== args.definition.id) {
168
130
  return {
169
- contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
131
+ issues: [`Assessment artifact targets "${parsed.assessmentId}", but this step expects "${args.definition.id}".`],
132
+ suggestions: [`Set assessmentId to "${args.definition.id}" or omit it and provide the correct dimensions.`],
133
+ warnings: [],
170
134
  acceptedArtifact: undefined,
171
135
  acceptedArtifactIndex: undefined,
172
136
  recordedAssessment: undefined,
173
- validation: {
174
- valid: false,
175
- issues: [`Assessment artifact targets "${parsed.assessmentId}", but this step expects "${lookup.definition.id}".`],
176
- suggestions: [`Set assessmentId to "${lookup.definition.id}" or omit it and provide the correct dimensions.`],
177
- },
178
137
  };
179
138
  }
180
139
  const issues = [];
181
140
  const suggestions = [];
182
141
  const warnings = [];
183
142
  const recordedDimensions = [];
184
- for (const dimension of lookup.definition.dimensions) {
143
+ for (const dimension of args.definition.dimensions) {
185
144
  validateDimension(dimension, parsed, issues, suggestions, warnings, recordedDimensions);
186
145
  }
187
- const allowedDimensionIds = new Set(lookup.definition.dimensions.map((dimension) => dimension.id));
146
+ const allowedDimensionIds = new Set(args.definition.dimensions.map((d) => d.id));
188
147
  for (const submittedDimensionId of Object.keys(parsed.dimensions)) {
189
148
  if (!allowedDimensionIds.has(submittedDimensionId)) {
190
- issues.push(`Unknown assessment dimension "${submittedDimensionId}" for assessment "${lookup.definition.id}".`);
191
- suggestions.push(`Remove "${submittedDimensionId}" and use only: ${lookup.definition.dimensions.map((dimension) => dimension.id).join(', ')}.`);
149
+ issues.push(`Unknown assessment dimension "${submittedDimensionId}" for assessment "${args.definition.id}".`);
150
+ suggestions.push(`Remove "${submittedDimensionId}" and use only: ${args.definition.dimensions.map((d) => d.id).join(', ')}.`);
192
151
  }
193
152
  }
153
+ const valid = issues.length === 0;
194
154
  return {
195
- contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
196
- acceptedArtifact: issues.length === 0 ? parsed : undefined,
197
- acceptedArtifactIndex: issues.length === 0 ? acceptedCandidate.index : undefined,
198
- recordedAssessment: issues.length === 0
155
+ issues,
156
+ suggestions,
157
+ warnings,
158
+ acceptedArtifact: valid ? parsed : undefined,
159
+ acceptedArtifactIndex: valid ? candidateEntry.index : undefined,
160
+ recordedAssessment: valid
199
161
  ? {
200
- assessmentId: lookup.definition.id,
162
+ assessmentId: args.definition.id,
201
163
  summary: parsed.summary,
202
164
  dimensions: recordedDimensions,
203
165
  normalizationNotes: warnings,
204
166
  }
205
167
  : undefined,
168
+ };
169
+ }
170
+ function validateAssessmentForStep(args) {
171
+ if (!args.step.assessmentRefs || args.step.assessmentRefs.length === 0)
172
+ return undefined;
173
+ const refs = args.step.assessmentRefs;
174
+ if (!args.assessments || args.assessments.length === 0) {
175
+ return {
176
+ contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
177
+ recordedAssessments: [],
178
+ acceptedArtifacts: [],
179
+ validation: {
180
+ valid: false,
181
+ issues: refs.map((ref) => `Step expects assessment input for "${ref}", but the workflow declares no assessments.`),
182
+ suggestions: ['Update the workflow definition to declare the assessments referenced by this step.'],
183
+ },
184
+ };
185
+ }
186
+ const allIssues = [];
187
+ const allSuggestions = [];
188
+ const definitions = [];
189
+ for (const ref of refs) {
190
+ const definition = args.assessments.find((a) => a.id === ref);
191
+ if (!definition) {
192
+ allIssues.push(`Step references undeclared assessment "${ref}".`);
193
+ allSuggestions.push(`Declare assessment "${ref}" on the workflow or remove the step reference.`);
194
+ }
195
+ else {
196
+ definitions.push(definition);
197
+ }
198
+ }
199
+ if (allIssues.length > 0) {
200
+ return {
201
+ contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
202
+ recordedAssessments: [],
203
+ acceptedArtifacts: [],
204
+ validation: { valid: false, issues: allIssues, suggestions: allSuggestions },
205
+ };
206
+ }
207
+ const isSingleRef = refs.length === 1;
208
+ const perRefResults = definitions.map((definition) => validateSingleAssessment({ definition, artifacts: args.artifacts, isSingleRef }));
209
+ const combinedIssues = perRefResults.flatMap((r) => r.issues);
210
+ const combinedSuggestions = perRefResults.flatMap((r) => r.suggestions);
211
+ const combinedWarnings = perRefResults.flatMap((r) => r.warnings);
212
+ const allValid = combinedIssues.length === 0;
213
+ const recordedAssessments = [];
214
+ const acceptedArtifacts = [];
215
+ if (allValid) {
216
+ for (const result of perRefResults) {
217
+ if (result.recordedAssessment)
218
+ recordedAssessments.push(result.recordedAssessment);
219
+ if (result.acceptedArtifact !== undefined && result.acceptedArtifactIndex !== undefined) {
220
+ acceptedArtifacts.push({ artifact: result.acceptedArtifact, artifactIndex: result.acceptedArtifactIndex });
221
+ }
222
+ }
223
+ }
224
+ return {
225
+ contractRef: index_js_1.ASSESSMENT_CONTRACT_REF,
226
+ recordedAssessments,
227
+ acceptedArtifacts,
206
228
  validation: {
207
- valid: issues.length === 0,
208
- issues,
209
- suggestions,
210
- warnings: warnings.length > 0 ? warnings : undefined,
229
+ valid: allValid,
230
+ issues: combinedIssues,
231
+ suggestions: combinedSuggestions,
232
+ ...(combinedWarnings.length > 0 ? { warnings: combinedWarnings } : {}),
211
233
  },
212
234
  };
213
235
  }
@@ -5,8 +5,6 @@ import type { JsonValue, JsonObject } from '../../../v2/durable-core/canonical/j
5
5
  import type { V2ContinueWorkflowInput } from '../../v2/tools.js';
6
6
  import type { AssessmentDefinition, OutputContract } from '../../../types/workflow-definition.js';
7
7
  import type { ValidationCriteria } from '../../../types/validation.js';
8
- import type { AssessmentArtifactV1 } from '../../../v2/durable-core/schemas/artifacts/index.js';
9
- import type { RecordedAssessmentV1 } from '../../../v2/durable-core/domain/assessment-record.js';
10
8
  import type { TriggeredAssessmentConsequenceV1 } from './assessment-consequences.js';
11
9
  import type { InternalError } from '../v2-error-mapping.js';
12
10
  import type { SessionIndex } from '../../../v2/durable-core/session-index.js';
@@ -25,8 +23,6 @@ export interface ValidatedAdvanceInputs {
25
23
  readonly outputContract: OutputContract | undefined;
26
24
  readonly notesMarkdown: string | undefined;
27
25
  readonly artifacts: readonly unknown[];
28
- readonly assessmentArtifact: AssessmentArtifactV1 | undefined;
29
- readonly recordedAssessment: RecordedAssessmentV1 | undefined;
30
26
  readonly triggeredAssessmentConsequence: TriggeredAssessmentConsequenceV1 | undefined;
31
27
  readonly stepAssessments: readonly AssessmentDefinition[];
32
28
  readonly autonomy: 'guided' | 'full_auto_stop_on_user_deps' | 'full_auto_never_stop';
@@ -48,7 +48,7 @@ function validateAdvanceInputs(args) {
48
48
  : undefined;
49
49
  const triggeredAssessmentConsequence = (0, assessment_consequences_js_1.evaluateAssessmentConsequences)({
50
50
  step: typedStep,
51
- recordedAssessment: assessmentValidation?.recordedAssessment,
51
+ recordedAssessments: assessmentValidation?.recordedAssessments ?? [],
52
52
  });
53
53
  const notesOptional = outputContract !== undefined ||
54
54
  (step !== null && step !== undefined && 'notesOptional' in step && step.notesOptional === true);
@@ -92,8 +92,6 @@ function validateAdvanceInputs(args) {
92
92
  outputContract,
93
93
  notesMarkdown: inputOutput?.notesMarkdown,
94
94
  artifacts: inputOutput?.artifacts ?? [],
95
- assessmentArtifact: assessmentValidation?.acceptedArtifact,
96
- recordedAssessment: assessmentValidation?.recordedAssessment,
97
95
  triggeredAssessmentConsequence,
98
96
  stepAssessments,
99
97
  autonomy,
@@ -65,8 +65,13 @@ function buildBlockedOutcome(args) {
65
65
  ? outputAppendResult.value
66
66
  : [];
67
67
  const validated = args.v;
68
- if (validated?.recordedAssessment && validated.assessmentValidation?.acceptedArtifactIndex !== undefined) {
69
- const assessmentOutput = outputsToAppend[validated.assessmentValidation.acceptedArtifactIndex];
68
+ const acceptedArtifacts = validated?.assessmentValidation?.acceptedArtifacts ?? [];
69
+ for (let i = 0; i < acceptedArtifacts.length; i++) {
70
+ const { artifactIndex } = acceptedArtifacts[i];
71
+ const recordedAssessment = validated?.assessmentValidation?.recordedAssessments[i];
72
+ if (!recordedAssessment)
73
+ continue;
74
+ const assessmentOutput = outputsToAppend[artifactIndex];
70
75
  if (!assessmentOutput || assessmentOutput.outputChannel !== 'artifact') {
71
76
  return errAsync({ kind: 'invariant_violation', message: 'Accepted assessment artifact did not produce a matching artifact output on blocked path.' });
72
77
  }
@@ -75,7 +80,7 @@ function buildBlockedOutcome(args) {
75
80
  attemptId: String(attemptId),
76
81
  artifactOutputId: String(assessmentOutput.outputId),
77
82
  scope: { runId: String(runId), nodeId: String(currentNodeId) },
78
- assessment: validated.recordedAssessment,
83
+ assessment: recordedAssessment,
79
84
  minted: { eventId: idFactory.mintEventId() },
80
85
  });
81
86
  if (assessmentEventRes.isErr()) {
@@ -125,8 +125,13 @@ function buildSuccessOutcome(args) {
125
125
  if (artifactOutputsRes.isErr()) {
126
126
  return errAsync(artifactOutputsRes.error);
127
127
  }
128
- if (v.recordedAssessment && v.assessmentArtifact && v.assessmentValidation?.acceptedArtifactIndex !== undefined) {
129
- const assessmentOutput = artifactOutputsRes.value[v.assessmentValidation.acceptedArtifactIndex];
128
+ const acceptedArtifacts = v.assessmentValidation?.acceptedArtifacts ?? [];
129
+ for (let i = 0; i < acceptedArtifacts.length; i++) {
130
+ const { artifactIndex } = acceptedArtifacts[i];
131
+ const recordedAssessment = v.assessmentValidation?.recordedAssessments[i];
132
+ if (!recordedAssessment)
133
+ continue;
134
+ const assessmentOutput = artifactOutputsRes.value[artifactIndex];
130
135
  if (!assessmentOutput || assessmentOutput.outputChannel !== 'artifact') {
131
136
  return errAsync({
132
137
  kind: 'invariant_violation',
@@ -138,7 +143,7 @@ function buildSuccessOutcome(args) {
138
143
  attemptId: String(attemptId),
139
144
  artifactOutputId: String(assessmentOutput.outputId),
140
145
  scope: { runId: String(runId), nodeId: String(currentNodeId) },
141
- assessment: v.recordedAssessment,
146
+ assessment: recordedAssessment,
142
147
  minted: { eventId: idFactory.mintEventId() },
143
148
  });
144
149
  if (assessmentEventRes.isErr()) {
@@ -153,11 +153,11 @@ function buildStepContext(events, completedNodeId) {
153
153
  console.warn(`[workrail:replay] stepContext projection failed for node '${String(completedNodeId)}' — stepContext will be absent: ${projection.error.message}`);
154
154
  return undefined;
155
155
  }
156
- const recorded = (0, assessments_js_1.getLatestAssessmentForNode)(projection.value, String(completedNodeId));
157
- if (!recorded)
156
+ const allRecorded = projection.value.byNodeId[String(completedNodeId)];
157
+ if (!allRecorded || allRecorded.length === 0)
158
158
  return undefined;
159
159
  return {
160
- assessments: {
160
+ assessments: allRecorded.map((recorded) => ({
161
161
  assessmentId: recorded.assessmentId,
162
162
  dimensions: recorded.dimensions.map((d) => ({
163
163
  dimensionId: d.dimensionId,
@@ -165,7 +165,7 @@ function buildStepContext(events, completedNodeId) {
165
165
  ...(d.rationale !== undefined ? { rationale: d.rationale } : {}),
166
166
  })),
167
167
  normalizationNotes: recorded.normalizationNotes,
168
- },
168
+ })),
169
169
  };
170
170
  }
171
171
  function replayFromRecordedAdvance(args) {
@@ -1368,7 +1368,7 @@ export declare const V2BindingDriftWarningSchema: z.ZodObject<{
1368
1368
  currentValue: string;
1369
1369
  }>;
1370
1370
  export declare const V2StepContextSchema: z.ZodObject<{
1371
- assessments: z.ZodOptional<z.ZodObject<{
1371
+ assessments: z.ZodOptional<z.ZodArray<z.ZodObject<{
1372
1372
  assessmentId: z.ZodString;
1373
1373
  dimensions: z.ZodArray<z.ZodObject<{
1374
1374
  dimensionId: z.ZodString;
@@ -1400,7 +1400,7 @@ export declare const V2StepContextSchema: z.ZodObject<{
1400
1400
  rationale?: string | undefined;
1401
1401
  }[];
1402
1402
  normalizationNotes: readonly string[];
1403
- }>>;
1403
+ }>, "many">>;
1404
1404
  }, "strip", z.ZodTypeAny, {
1405
1405
  assessments?: {
1406
1406
  assessmentId: string;
@@ -1410,7 +1410,7 @@ export declare const V2StepContextSchema: z.ZodObject<{
1410
1410
  rationale?: string | undefined;
1411
1411
  }[];
1412
1412
  normalizationNotes: readonly string[];
1413
- } | undefined;
1413
+ }[] | undefined;
1414
1414
  }, {
1415
1415
  assessments?: {
1416
1416
  assessmentId: string;
@@ -1420,7 +1420,7 @@ export declare const V2StepContextSchema: z.ZodObject<{
1420
1420
  rationale?: string | undefined;
1421
1421
  }[];
1422
1422
  normalizationNotes: readonly string[];
1423
- } | undefined;
1423
+ }[] | undefined;
1424
1424
  }>;
1425
1425
  export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
1426
1426
  kind: z.ZodLiteral<"ok">;
@@ -1491,7 +1491,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1491
1491
  currentValue: string;
1492
1492
  }>, "many">>;
1493
1493
  stepContext: z.ZodOptional<z.ZodObject<{
1494
- assessments: z.ZodOptional<z.ZodObject<{
1494
+ assessments: z.ZodOptional<z.ZodArray<z.ZodObject<{
1495
1495
  assessmentId: z.ZodString;
1496
1496
  dimensions: z.ZodArray<z.ZodObject<{
1497
1497
  dimensionId: z.ZodString;
@@ -1523,7 +1523,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1523
1523
  rationale?: string | undefined;
1524
1524
  }[];
1525
1525
  normalizationNotes: readonly string[];
1526
- }>>;
1526
+ }>, "many">>;
1527
1527
  }, "strip", z.ZodTypeAny, {
1528
1528
  assessments?: {
1529
1529
  assessmentId: string;
@@ -1533,7 +1533,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1533
1533
  rationale?: string | undefined;
1534
1534
  }[];
1535
1535
  normalizationNotes: readonly string[];
1536
- } | undefined;
1536
+ }[] | undefined;
1537
1537
  }, {
1538
1538
  assessments?: {
1539
1539
  assessmentId: string;
@@ -1543,7 +1543,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1543
1543
  rationale?: string | undefined;
1544
1544
  }[];
1545
1545
  normalizationNotes: readonly string[];
1546
- } | undefined;
1546
+ }[] | undefined;
1547
1547
  }>>;
1548
1548
  }, "strip", z.ZodTypeAny, {
1549
1549
  kind: "ok";
@@ -1582,7 +1582,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1582
1582
  rationale?: string | undefined;
1583
1583
  }[];
1584
1584
  normalizationNotes: readonly string[];
1585
- } | undefined;
1585
+ }[] | undefined;
1586
1586
  } | undefined;
1587
1587
  }, {
1588
1588
  kind: "ok";
@@ -1621,7 +1621,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1621
1621
  rationale?: string | undefined;
1622
1622
  }[];
1623
1623
  normalizationNotes: readonly string[];
1624
- } | undefined;
1624
+ }[] | undefined;
1625
1625
  } | undefined;
1626
1626
  }>, z.ZodObject<{
1627
1627
  kind: z.ZodLiteral<"blocked">;
@@ -2058,7 +2058,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
2058
2058
  rationale?: string | undefined;
2059
2059
  }[];
2060
2060
  normalizationNotes: readonly string[];
2061
- } | undefined;
2061
+ }[] | undefined;
2062
2062
  } | undefined;
2063
2063
  } | {
2064
2064
  kind: "blocked";
@@ -2155,7 +2155,7 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
2155
2155
  rationale?: string | undefined;
2156
2156
  }[];
2157
2157
  normalizationNotes: readonly string[];
2158
- } | undefined;
2158
+ }[] | undefined;
2159
2159
  } | undefined;
2160
2160
  } | {
2161
2161
  kind: "blocked";
@@ -288,18 +288,17 @@ exports.V2BindingDriftWarningSchema = zod_1.z.object({
288
288
  pinnedValue: zod_1.z.string().min(1),
289
289
  currentValue: zod_1.z.string().min(1),
290
290
  });
291
+ const V2StepContextAssessmentSchema = zod_1.z.object({
292
+ assessmentId: zod_1.z.string().min(1),
293
+ dimensions: zod_1.z.array(zod_1.z.object({
294
+ dimensionId: zod_1.z.string().min(1),
295
+ level: zod_1.z.string().min(1),
296
+ rationale: zod_1.z.string().optional(),
297
+ })),
298
+ normalizationNotes: zod_1.z.array(zod_1.z.string()).readonly(),
299
+ });
291
300
  exports.V2StepContextSchema = zod_1.z.object({
292
- assessments: zod_1.z
293
- .object({
294
- assessmentId: zod_1.z.string().min(1),
295
- dimensions: zod_1.z.array(zod_1.z.object({
296
- dimensionId: zod_1.z.string().min(1),
297
- level: zod_1.z.string().min(1),
298
- rationale: zod_1.z.string().optional(),
299
- })),
300
- normalizationNotes: zod_1.z.array(zod_1.z.string()).readonly(),
301
- })
302
- .optional(),
301
+ assessments: zod_1.z.array(V2StepContextAssessmentSchema).optional(),
303
302
  });
304
303
  const V2ContinueWorkflowOkSchema = zod_1.z.object({
305
304
  kind: zod_1.z.literal('ok'),
File without changes
@@ -75,7 +75,7 @@ function assertNever(x) {
75
75
  function getSourceDisplayName(source) {
76
76
  switch (source.kind) {
77
77
  case 'bundled':
78
- return 'Built-in';
78
+ return 'WorkRail';
79
79
  case 'user':
80
80
  return 'User Library';
81
81
  case 'project':
@@ -10,9 +10,6 @@ export interface ObservationEventData {
10
10
  } | {
11
11
  readonly type: 'sha256';
12
12
  readonly value: string;
13
- } | {
14
- readonly type: 'path';
15
- readonly value: string;
16
13
  };
17
14
  readonly confidence: 'low' | 'med' | 'high';
18
15
  }
@@ -34,11 +34,9 @@ function anchorsToObservations(anchors) {
34
34
  });
35
35
  break;
36
36
  case 'repo_root':
37
- if (anchor.value.length > constants_js_1.MAX_OBSERVATION_PATH_LENGTH)
38
- break;
39
37
  observations.push({
40
38
  key: 'repo_root',
41
- value: { type: 'path', value: anchor.value },
39
+ value: { type: 'short_string', value: anchor.value },
42
40
  confidence: 'high',
43
41
  });
44
42
  break;
@@ -177,11 +177,19 @@ function formatOutputContractRequirements(outputContract) {
177
177
  function formatAssessmentRequirements(assessments) {
178
178
  if (assessments.length === 0)
179
179
  return [];
180
+ const multiRef = assessments.length > 1;
180
181
  const requirements = [];
181
182
  for (const assessment of assessments) {
182
183
  requirements.push('Provide an artifact with kind: "wr.assessment"');
184
+ if (multiRef) {
185
+ requirements.push(`Set assessmentId: "${assessment.id}" on the artifact so the engine can match it to the correct assessment.`);
186
+ }
183
187
  requirements.push(`Assessment target: "${assessment.id}"`);
184
- requirements.push(`Dimensions: ${assessment.dimensions.map((dimension) => `${dimension.id} (${dimension.levels.join(' | ')})`).join(', ')}`);
188
+ requirements.push(`Purpose: ${assessment.purpose}`);
189
+ requirements.push('Dimensions:');
190
+ for (const dimension of assessment.dimensions) {
191
+ requirements.push(` ${dimension.id} (${dimension.levels.join(' | ')}): ${dimension.purpose}`);
192
+ }
185
193
  requirements.push('Use only canonical dimension levels. If the engine rejects the artifact, correct the submitted levels instead of inventing new ones.');
186
194
  }
187
195
  return requirements;
@@ -18,7 +18,6 @@ const EMPTY_OBSERVATIONS = {
18
18
  gitHeadSha: null,
19
19
  gitBranch: null,
20
20
  repoRootHash: null,
21
- repoRoot: null,
22
21
  };
23
22
  const TITLE_CONTEXT_KEYS = ['goal', 'taskDescription', 'mrTitle', 'prTitle', 'ticketTitle', 'problem'];
24
23
  class LocalSessionSummaryProviderV2 {
@@ -137,7 +136,7 @@ function extractObservations(events) {
137
136
  case 'git_head_sha': return { ...acc, gitHeadSha: e.data.value.value };
138
137
  case 'git_branch': return { ...acc, gitBranch: e.data.value.value };
139
138
  case 'repo_root_hash': return { ...acc, repoRootHash: e.data.value.value };
140
- case 'repo_root': return { ...acc, repoRoot: e.data.value.value };
139
+ case 'repo_root': return acc;
141
140
  }
142
141
  }, EMPTY_OBSERVATIONS);
143
142
  }
@@ -8,7 +8,6 @@ export interface SessionObservations {
8
8
  readonly gitHeadSha: string | null;
9
9
  readonly gitBranch: string | null;
10
10
  readonly repoRootHash: string | null;
11
- readonly repoRoot: string | null;
12
11
  }
13
12
  export type WorkflowIdentity = {
14
13
  readonly kind: 'unknown';