@exaudeus/workrail 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/application/services/validation-engine.d.ts +15 -1
  2. package/dist/application/services/validation-engine.js +81 -51
  3. package/dist/application/services/workflow-compiler.d.ts +3 -0
  4. package/dist/application/services/workflow-compiler.js +26 -0
  5. package/dist/application/services/workflow-interpreter.d.ts +4 -1
  6. package/dist/application/services/workflow-interpreter.js +85 -24
  7. package/dist/application/services/workflow-service.js +19 -2
  8. package/dist/manifest.json +267 -83
  9. package/dist/mcp/handlers/shared/with-timeout.d.ts +1 -0
  10. package/dist/mcp/handlers/shared/with-timeout.js +9 -0
  11. package/dist/mcp/handlers/v2-advance-core.d.ts +45 -0
  12. package/dist/mcp/handlers/v2-advance-core.js +433 -0
  13. package/dist/mcp/handlers/v2-context-budget.d.ts +17 -0
  14. package/dist/mcp/handlers/v2-context-budget.js +169 -0
  15. package/dist/mcp/handlers/v2-error-mapping.d.ts +34 -0
  16. package/dist/mcp/handlers/v2-error-mapping.js +125 -0
  17. package/dist/mcp/handlers/v2-execution-helpers.js +4 -1
  18. package/dist/mcp/handlers/v2-execution.d.ts +19 -0
  19. package/dist/mcp/handlers/v2-execution.js +278 -765
  20. package/dist/mcp/handlers/v2-state-conversion.d.ts +40 -0
  21. package/dist/mcp/handlers/v2-state-conversion.js +132 -0
  22. package/dist/mcp/handlers/v2-token-ops.d.ts +33 -0
  23. package/dist/mcp/handlers/v2-token-ops.js +62 -0
  24. package/dist/mcp/handlers/v2-workflow.js +3 -8
  25. package/dist/mcp/handlers/workflow.js +4 -11
  26. package/dist/mcp/output-schemas.d.ts +272 -20
  27. package/dist/mcp/output-schemas.js +20 -1
  28. package/dist/mcp/server.js +2 -0
  29. package/dist/mcp/tool-descriptions.js +67 -51
  30. package/dist/mcp/types.d.ts +2 -0
  31. package/dist/mcp/v2/tools.d.ts +23 -2
  32. package/dist/mcp/v2/tools.js +35 -4
  33. package/dist/types/workflow-definition.d.ts +19 -0
  34. package/dist/v2/durable-core/constants.d.ts +2 -0
  35. package/dist/v2/durable-core/constants.js +3 -1
  36. package/dist/v2/durable-core/domain/ack-advance-append-plan.d.ts +1 -0
  37. package/dist/v2/durable-core/domain/ack-advance-append-plan.js +11 -1
  38. package/dist/v2/durable-core/domain/artifact-contract-validator.d.ts +31 -0
  39. package/dist/v2/durable-core/domain/artifact-contract-validator.js +98 -0
  40. package/dist/v2/durable-core/domain/blocked-node-builder.d.ts +20 -0
  41. package/dist/v2/durable-core/domain/blocked-node-builder.js +94 -0
  42. package/dist/v2/durable-core/domain/decision-trace-builder.d.ts +33 -0
  43. package/dist/v2/durable-core/domain/decision-trace-builder.js +92 -0
  44. package/dist/v2/durable-core/domain/function-definition-expander.js +1 -1
  45. package/dist/v2/durable-core/domain/loop-control-evaluator.d.ts +13 -0
  46. package/dist/v2/durable-core/domain/loop-control-evaluator.js +24 -0
  47. package/dist/v2/durable-core/domain/observation-builder.d.ts +16 -0
  48. package/dist/v2/durable-core/domain/observation-builder.js +42 -0
  49. package/dist/v2/durable-core/domain/outputs.js +2 -2
  50. package/dist/v2/durable-core/domain/prompt-renderer.js +37 -4
  51. package/dist/v2/durable-core/domain/reason-model.d.ts +3 -1
  52. package/dist/v2/durable-core/domain/reason-model.js +16 -3
  53. package/dist/v2/durable-core/domain/recommendation-warnings.d.ts +20 -0
  54. package/dist/v2/durable-core/domain/recommendation-warnings.js +35 -0
  55. package/dist/v2/durable-core/domain/risk-policy-guardrails.d.ts +15 -0
  56. package/dist/v2/durable-core/domain/risk-policy-guardrails.js +78 -0
  57. package/dist/v2/durable-core/domain/validation-criteria-validator.d.ts +8 -0
  58. package/dist/v2/durable-core/domain/validation-criteria-validator.js +30 -0
  59. package/dist/v2/durable-core/domain/validation-event-builder.d.ts +26 -0
  60. package/dist/v2/durable-core/domain/validation-event-builder.js +100 -0
  61. package/dist/v2/durable-core/domain/validation-loader.d.ts +11 -0
  62. package/dist/v2/durable-core/domain/validation-loader.js +21 -0
  63. package/dist/v2/durable-core/projections/snapshot-state.js +1 -1
  64. package/dist/v2/durable-core/schemas/artifacts/index.d.ts +4 -0
  65. package/dist/v2/durable-core/schemas/artifacts/index.js +18 -0
  66. package/dist/v2/durable-core/schemas/artifacts/loop-control.d.ts +66 -0
  67. package/dist/v2/durable-core/schemas/artifacts/loop-control.js +47 -0
  68. package/dist/v2/durable-core/schemas/execution-snapshot/blocked-snapshot.d.ts +598 -0
  69. package/dist/v2/durable-core/schemas/execution-snapshot/blocked-snapshot.js +89 -0
  70. package/dist/v2/durable-core/schemas/execution-snapshot/execution-snapshot.v1.d.ts +3801 -57
  71. package/dist/v2/durable-core/schemas/execution-snapshot/execution-snapshot.v1.js +12 -2
  72. package/dist/v2/durable-core/schemas/execution-snapshot/index.d.ts +2 -0
  73. package/dist/v2/durable-core/schemas/execution-snapshot/index.js +3 -1
  74. package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +4682 -758
  75. package/dist/v2/durable-core/schemas/session/events.d.ts +158 -45
  76. package/dist/v2/durable-core/schemas/session/events.js +8 -1
  77. package/dist/v2/durable-core/schemas/session/validation-event.d.ts +68 -0
  78. package/dist/v2/durable-core/schemas/session/validation-event.js +52 -0
  79. package/dist/v2/durable-core/tokens/payloads.d.ts +16 -16
  80. package/dist/v2/infra/local/workspace-anchor/index.d.ts +9 -0
  81. package/dist/v2/infra/local/workspace-anchor/index.js +44 -0
  82. package/dist/v2/ports/workspace-anchor.port.d.ts +18 -0
  83. package/dist/v2/ports/workspace-anchor.port.js +2 -0
  84. package/dist/v2/projections/artifacts.d.ts +22 -0
  85. package/dist/v2/projections/artifacts.js +53 -0
  86. package/dist/v2/projections/projection-timing.d.ts +13 -0
  87. package/dist/v2/projections/projection-timing.js +23 -0
  88. package/dist/v2/projections/run-dag.d.ts +1 -1
  89. package/dist/v2/projections/run-status-signals.js +3 -8
  90. package/package.json +1 -1
  91. package/spec/workflow.schema.json +60 -0
  92. package/spec/workflow.schema.v0.0.1.json +38 -0
  93. package/workflows/coding-task-workflow-agentic.json +11 -18
  94. package/workflows/test-artifact-loop-control.json +59 -0
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VALIDATION_CRITERIA_CONTRACT_REF = void 0;
4
4
  exports.getOutputRequirementStatusV1 = getOutputRequirementStatusV1;
5
+ exports.getOutputRequirementStatusWithArtifactsV1 = getOutputRequirementStatusWithArtifactsV1;
6
+ const artifact_contract_validator_js_1 = require("./artifact-contract-validator.js");
5
7
  exports.VALIDATION_CRITERIA_CONTRACT_REF = 'wr.validationCriteria';
6
8
  function getOutputRequirementStatusV1(args) {
7
9
  if (!args.validationCriteria)
@@ -14,3 +16,31 @@ function getOutputRequirementStatusV1(args) {
14
16
  }
15
17
  return { kind: 'not_required' };
16
18
  }
19
+ function getOutputRequirementStatusWithArtifactsV1(args) {
20
+ if (args.outputContract) {
21
+ const result = (0, artifact_contract_validator_js_1.validateArtifactContract)(args.artifacts, args.outputContract);
22
+ if (!result.valid) {
23
+ const error = result.error;
24
+ if (error.code === 'MISSING_REQUIRED_ARTIFACT') {
25
+ return { kind: 'missing', contractRef: error.contractRef };
26
+ }
27
+ if (error.code === 'INVALID_ARTIFACT_SCHEMA') {
28
+ const validationResult = {
29
+ valid: false,
30
+ issues: error.issues.map(issue => issue),
31
+ suggestions: ['Provide a valid artifact matching the contract schema'],
32
+ };
33
+ return { kind: 'invalid', contractRef: error.contractRef, validation: validationResult };
34
+ }
35
+ if (error.code === 'UNKNOWN_CONTRACT_REF') {
36
+ return { kind: 'missing', contractRef: error.contractRef };
37
+ }
38
+ }
39
+ return { kind: 'not_required' };
40
+ }
41
+ return getOutputRequirementStatusV1({
42
+ validationCriteria: args.validationCriteria,
43
+ notesMarkdown: args.notesMarkdown,
44
+ validation: args.validation,
45
+ });
46
+ }
@@ -0,0 +1,26 @@
1
+ import { type Result } from 'neverthrow';
2
+ import type { ValidationResult } from '../../../types/validation.js';
3
+ import type { DomainEventV1 } from '../schemas/session/index.js';
4
+ type EventToAppendV1 = Omit<DomainEventV1, 'eventIndex' | 'sessionId'>;
5
+ export type ValidationEventError = {
6
+ readonly code: 'VALIDATION_EVENT_INVARIANT_VIOLATION';
7
+ readonly message: string;
8
+ } | {
9
+ readonly code: 'VALIDATION_EVENT_TEXT_TOO_LARGE';
10
+ readonly message: string;
11
+ };
12
+ export declare function buildValidationPerformedEvent(args: {
13
+ readonly sessionId: string;
14
+ readonly validationId: string;
15
+ readonly attemptId: string;
16
+ readonly contractRef: string;
17
+ readonly result: ValidationResult;
18
+ readonly scope: {
19
+ readonly runId: string;
20
+ readonly nodeId: string;
21
+ };
22
+ readonly minted: {
23
+ readonly eventId: string;
24
+ };
25
+ }): Result<EventToAppendV1, ValidationEventError>;
26
+ export {};
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildValidationPerformedEvent = buildValidationPerformedEvent;
4
+ const neverthrow_1 = require("neverthrow");
5
+ const constants_js_1 = require("../constants.js");
6
+ function utf8ByteLength(s) {
7
+ return new TextEncoder().encode(s).length;
8
+ }
9
+ function uniqueSorted(values) {
10
+ const sorted = [...values].filter((v) => v.length > 0).sort((a, b) => a.localeCompare(b, 'en-US'));
11
+ const out = [];
12
+ for (const v of sorted) {
13
+ if (out.length === 0 || out[out.length - 1] !== v)
14
+ out.push(v);
15
+ }
16
+ return out;
17
+ }
18
+ const VALIDATION_TRUNCATION_ITEM = '[TRUNCATED]';
19
+ function truncateListToUtf8ByteBudget(args) {
20
+ if (args.maxBytes <= 0) {
21
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'maxBytes must be positive' });
22
+ }
23
+ const markerBytes = args.includeTruncationMarker ? utf8ByteLength(VALIDATION_TRUNCATION_ITEM) : 0;
24
+ if (args.includeTruncationMarker && markerBytes > args.maxBytes) {
25
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_TEXT_TOO_LARGE', message: 'validation truncation marker does not fit budget' });
26
+ }
27
+ const values = uniqueSorted(args.values);
28
+ const out = [];
29
+ let used = 0;
30
+ for (const v of values) {
31
+ const bytes = utf8ByteLength(v);
32
+ if (bytes > args.maxBytes) {
33
+ return (0, neverthrow_1.err)({
34
+ code: 'VALIDATION_EVENT_TEXT_TOO_LARGE',
35
+ message: 'validation item exceeds max bytes budget',
36
+ });
37
+ }
38
+ const remainingBudget = args.maxBytes - used;
39
+ const reserve = args.includeTruncationMarker ? markerBytes : 0;
40
+ const canFitWithReserve = bytes <= remainingBudget - reserve;
41
+ if (!canFitWithReserve) {
42
+ if (args.includeTruncationMarker) {
43
+ if (used + markerBytes <= args.maxBytes)
44
+ out.push(VALIDATION_TRUNCATION_ITEM);
45
+ }
46
+ return (0, neverthrow_1.ok)(out);
47
+ }
48
+ out.push(v);
49
+ used += bytes;
50
+ }
51
+ return (0, neverthrow_1.ok)(out);
52
+ }
53
+ function buildValidationPerformedEvent(args) {
54
+ if (!args.sessionId)
55
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'sessionId is required' });
56
+ if (!args.validationId)
57
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'validationId is required' });
58
+ if (!args.attemptId)
59
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'attemptId is required' });
60
+ if (!args.contractRef)
61
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'contractRef is required' });
62
+ if (!args.scope.runId || !args.scope.nodeId) {
63
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'scope.runId and scope.nodeId are required' });
64
+ }
65
+ if (!args.minted.eventId)
66
+ return (0, neverthrow_1.err)({ code: 'VALIDATION_EVENT_INVARIANT_VIOLATION', message: 'minted.eventId is required' });
67
+ const issuesRes = truncateListToUtf8ByteBudget({
68
+ values: args.result.issues ?? [],
69
+ maxBytes: constants_js_1.MAX_VALIDATION_ISSUES_BYTES,
70
+ includeTruncationMarker: true,
71
+ });
72
+ if (issuesRes.isErr())
73
+ return (0, neverthrow_1.err)(issuesRes.error);
74
+ const suggestionsRes = truncateListToUtf8ByteBudget({
75
+ values: args.result.suggestions ?? [],
76
+ maxBytes: constants_js_1.MAX_VALIDATION_SUGGESTIONS_BYTES,
77
+ includeTruncationMarker: true,
78
+ });
79
+ if (suggestionsRes.isErr())
80
+ return (0, neverthrow_1.err)(suggestionsRes.error);
81
+ const dedupeKey = `validation_performed:${args.sessionId}:${args.attemptId}`;
82
+ const event = {
83
+ v: 1,
84
+ eventId: args.minted.eventId,
85
+ kind: 'validation_performed',
86
+ dedupeKey: dedupeKey,
87
+ scope: { runId: args.scope.runId, nodeId: args.scope.nodeId },
88
+ data: {
89
+ validationId: args.validationId,
90
+ attemptId: args.attemptId,
91
+ contractRef: args.contractRef,
92
+ result: {
93
+ valid: args.result.valid,
94
+ issues: issuesRes.value,
95
+ suggestions: suggestionsRes.value,
96
+ },
97
+ },
98
+ };
99
+ return (0, neverthrow_1.ok)(event);
100
+ }
@@ -0,0 +1,11 @@
1
+ import { type Result } from 'neverthrow';
2
+ import type { DomainEventV1 } from '../schemas/session/index.js';
3
+ export type ValidationLoadError = {
4
+ readonly code: 'VALIDATION_LOAD_INVARIANT_VIOLATION';
5
+ readonly message: string;
6
+ };
7
+ export type LoadedValidationV1 = {
8
+ readonly issues: readonly string[];
9
+ readonly suggestions: readonly string[];
10
+ };
11
+ export declare function loadValidationResultV1(events: readonly DomainEventV1[], validationId: string): Result<LoadedValidationV1 | null, ValidationLoadError>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadValidationResultV1 = loadValidationResultV1;
4
+ const neverthrow_1 = require("neverthrow");
5
+ function loadValidationResultV1(events, validationId) {
6
+ if (!validationId) {
7
+ return (0, neverthrow_1.ok)(null);
8
+ }
9
+ let latest = null;
10
+ for (const e of events) {
11
+ if (e.kind !== 'validation_performed')
12
+ continue;
13
+ if (e.data.validationId !== validationId)
14
+ continue;
15
+ if (!latest || e.eventIndex > latest.eventIndex)
16
+ latest = e;
17
+ }
18
+ if (!latest)
19
+ return (0, neverthrow_1.ok)(null);
20
+ return (0, neverthrow_1.ok)({ issues: latest.data.result.issues, suggestions: latest.data.result.suggestions });
21
+ }
@@ -6,7 +6,7 @@ function deriveIsComplete(state) {
6
6
  return state.kind === 'complete';
7
7
  }
8
8
  function derivePendingStep(state) {
9
- if (state.kind !== 'running')
9
+ if (state.kind !== 'running' && state.kind !== 'blocked')
10
10
  return null;
11
11
  if (state.pending.kind !== 'some')
12
12
  return null;
@@ -0,0 +1,4 @@
1
+ export { LOOP_CONTROL_CONTRACT_REF, LoopControlDecisionSchema, LoopControlMetadataV1Schema, LoopControlArtifactV1Schema, isLoopControlArtifact, parseLoopControlArtifact, findLoopControlArtifact, type LoopControlDecision, type LoopControlMetadataV1, type LoopControlArtifactV1, } from './loop-control.js';
2
+ export declare const ARTIFACT_CONTRACT_REFS: readonly ["wr.contracts.loop_control"];
3
+ export type ArtifactContractRef = (typeof ARTIFACT_CONTRACT_REFS)[number];
4
+ export declare function isValidContractRef(ref: string): ref is ArtifactContractRef;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ARTIFACT_CONTRACT_REFS = exports.findLoopControlArtifact = exports.parseLoopControlArtifact = exports.isLoopControlArtifact = exports.LoopControlArtifactV1Schema = exports.LoopControlMetadataV1Schema = exports.LoopControlDecisionSchema = exports.LOOP_CONTROL_CONTRACT_REF = void 0;
4
+ exports.isValidContractRef = isValidContractRef;
5
+ var loop_control_js_1 = require("./loop-control.js");
6
+ Object.defineProperty(exports, "LOOP_CONTROL_CONTRACT_REF", { enumerable: true, get: function () { return loop_control_js_1.LOOP_CONTROL_CONTRACT_REF; } });
7
+ Object.defineProperty(exports, "LoopControlDecisionSchema", { enumerable: true, get: function () { return loop_control_js_1.LoopControlDecisionSchema; } });
8
+ Object.defineProperty(exports, "LoopControlMetadataV1Schema", { enumerable: true, get: function () { return loop_control_js_1.LoopControlMetadataV1Schema; } });
9
+ Object.defineProperty(exports, "LoopControlArtifactV1Schema", { enumerable: true, get: function () { return loop_control_js_1.LoopControlArtifactV1Schema; } });
10
+ Object.defineProperty(exports, "isLoopControlArtifact", { enumerable: true, get: function () { return loop_control_js_1.isLoopControlArtifact; } });
11
+ Object.defineProperty(exports, "parseLoopControlArtifact", { enumerable: true, get: function () { return loop_control_js_1.parseLoopControlArtifact; } });
12
+ Object.defineProperty(exports, "findLoopControlArtifact", { enumerable: true, get: function () { return loop_control_js_1.findLoopControlArtifact; } });
13
+ exports.ARTIFACT_CONTRACT_REFS = [
14
+ 'wr.contracts.loop_control',
15
+ ];
16
+ function isValidContractRef(ref) {
17
+ return exports.ARTIFACT_CONTRACT_REFS.includes(ref);
18
+ }
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ export declare const LOOP_CONTROL_CONTRACT_REF: "wr.contracts.loop_control";
3
+ export declare const LoopControlDecisionSchema: z.ZodEnum<["continue", "stop"]>;
4
+ export type LoopControlDecision = z.infer<typeof LoopControlDecisionSchema>;
5
+ export declare const LoopControlMetadataV1Schema: z.ZodOptional<z.ZodObject<{
6
+ reason: z.ZodOptional<z.ZodString>;
7
+ issuesFound: z.ZodOptional<z.ZodNumber>;
8
+ iterationIndex: z.ZodOptional<z.ZodNumber>;
9
+ confidence: z.ZodOptional<z.ZodNumber>;
10
+ }, "strict", z.ZodTypeAny, {
11
+ confidence?: number | undefined;
12
+ reason?: string | undefined;
13
+ issuesFound?: number | undefined;
14
+ iterationIndex?: number | undefined;
15
+ }, {
16
+ confidence?: number | undefined;
17
+ reason?: string | undefined;
18
+ issuesFound?: number | undefined;
19
+ iterationIndex?: number | undefined;
20
+ }>>;
21
+ export type LoopControlMetadataV1 = z.infer<typeof LoopControlMetadataV1Schema>;
22
+ export declare const LoopControlArtifactV1Schema: z.ZodObject<{
23
+ kind: z.ZodLiteral<"wr.loop_control">;
24
+ loopId: z.ZodString;
25
+ decision: z.ZodEnum<["continue", "stop"]>;
26
+ metadata: z.ZodOptional<z.ZodObject<{
27
+ reason: z.ZodOptional<z.ZodString>;
28
+ issuesFound: z.ZodOptional<z.ZodNumber>;
29
+ iterationIndex: z.ZodOptional<z.ZodNumber>;
30
+ confidence: z.ZodOptional<z.ZodNumber>;
31
+ }, "strict", z.ZodTypeAny, {
32
+ confidence?: number | undefined;
33
+ reason?: string | undefined;
34
+ issuesFound?: number | undefined;
35
+ iterationIndex?: number | undefined;
36
+ }, {
37
+ confidence?: number | undefined;
38
+ reason?: string | undefined;
39
+ issuesFound?: number | undefined;
40
+ iterationIndex?: number | undefined;
41
+ }>>;
42
+ }, "strict", z.ZodTypeAny, {
43
+ kind: "wr.loop_control";
44
+ loopId: string;
45
+ decision: "continue" | "stop";
46
+ metadata?: {
47
+ confidence?: number | undefined;
48
+ reason?: string | undefined;
49
+ issuesFound?: number | undefined;
50
+ iterationIndex?: number | undefined;
51
+ } | undefined;
52
+ }, {
53
+ kind: "wr.loop_control";
54
+ loopId: string;
55
+ decision: "continue" | "stop";
56
+ metadata?: {
57
+ confidence?: number | undefined;
58
+ reason?: string | undefined;
59
+ issuesFound?: number | undefined;
60
+ iterationIndex?: number | undefined;
61
+ } | undefined;
62
+ }>;
63
+ export type LoopControlArtifactV1 = z.infer<typeof LoopControlArtifactV1Schema>;
64
+ export declare function isLoopControlArtifact(artifact: unknown): artifact is LoopControlArtifactV1;
65
+ export declare function parseLoopControlArtifact(artifact: unknown): LoopControlArtifactV1 | null;
66
+ export declare function findLoopControlArtifact(artifacts: readonly unknown[], loopId: string): LoopControlArtifactV1 | null;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoopControlArtifactV1Schema = exports.LoopControlMetadataV1Schema = exports.LoopControlDecisionSchema = exports.LOOP_CONTROL_CONTRACT_REF = void 0;
4
+ exports.isLoopControlArtifact = isLoopControlArtifact;
5
+ exports.parseLoopControlArtifact = parseLoopControlArtifact;
6
+ exports.findLoopControlArtifact = findLoopControlArtifact;
7
+ const zod_1 = require("zod");
8
+ const constants_js_1 = require("../../constants.js");
9
+ exports.LOOP_CONTROL_CONTRACT_REF = 'wr.contracts.loop_control';
10
+ exports.LoopControlDecisionSchema = zod_1.z.enum(['continue', 'stop']);
11
+ exports.LoopControlMetadataV1Schema = zod_1.z
12
+ .object({
13
+ reason: zod_1.z.string().max(1024).optional(),
14
+ issuesFound: zod_1.z.number().int().nonnegative().optional(),
15
+ iterationIndex: zod_1.z.number().int().nonnegative().optional(),
16
+ confidence: zod_1.z.number().int().min(0).max(100).optional(),
17
+ })
18
+ .strict()
19
+ .optional();
20
+ exports.LoopControlArtifactV1Schema = zod_1.z
21
+ .object({
22
+ kind: zod_1.z.literal('wr.loop_control'),
23
+ loopId: zod_1.z.string().min(1).max(64).regex(constants_js_1.DELIMITER_SAFE_ID_PATTERN, 'loopId must be delimiter-safe: [a-z0-9_-]+'),
24
+ decision: exports.LoopControlDecisionSchema,
25
+ metadata: exports.LoopControlMetadataV1Schema,
26
+ })
27
+ .strict();
28
+ function isLoopControlArtifact(artifact) {
29
+ if (typeof artifact !== 'object' || artifact === null)
30
+ return false;
31
+ return artifact.kind === 'wr.loop_control';
32
+ }
33
+ function parseLoopControlArtifact(artifact) {
34
+ const result = exports.LoopControlArtifactV1Schema.safeParse(artifact);
35
+ return result.success ? result.data : null;
36
+ }
37
+ function findLoopControlArtifact(artifacts, loopId) {
38
+ for (const artifact of artifacts) {
39
+ if (!isLoopControlArtifact(artifact))
40
+ continue;
41
+ const parsed = parseLoopControlArtifact(artifact);
42
+ if (parsed && parsed.loopId === loopId) {
43
+ return parsed;
44
+ }
45
+ }
46
+ return null;
47
+ }