@cleocode/contracts 2026.4.69 → 2026.4.72

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 (71) hide show
  1. package/dist/__tests__/acceptance-gate.test.d.ts +14 -0
  2. package/dist/__tests__/acceptance-gate.test.d.ts.map +1 -0
  3. package/dist/__tests__/acceptance-gate.test.js +642 -0
  4. package/dist/__tests__/acceptance-gate.test.js.map +1 -0
  5. package/dist/__tests__/attachment.test.d.ts +17 -0
  6. package/dist/__tests__/attachment.test.d.ts.map +1 -0
  7. package/dist/__tests__/attachment.test.js +505 -0
  8. package/dist/__tests__/attachment.test.js.map +1 -0
  9. package/dist/__tests__/evidence-record.test.d.ts +14 -0
  10. package/dist/__tests__/evidence-record.test.d.ts.map +1 -0
  11. package/dist/__tests__/evidence-record.test.js +362 -0
  12. package/dist/__tests__/evidence-record.test.js.map +1 -0
  13. package/dist/__tests__/invariants.test.d.ts +19 -0
  14. package/dist/__tests__/invariants.test.d.ts.map +1 -0
  15. package/dist/__tests__/invariants.test.js +351 -0
  16. package/dist/__tests__/invariants.test.js.map +1 -0
  17. package/dist/acceptance-gate-schema.d.ts +701 -0
  18. package/dist/acceptance-gate-schema.d.ts.map +1 -0
  19. package/dist/acceptance-gate-schema.js +303 -0
  20. package/dist/acceptance-gate-schema.js.map +1 -0
  21. package/dist/acceptance-gate.d.ts +350 -0
  22. package/dist/acceptance-gate.d.ts.map +1 -0
  23. package/dist/acceptance-gate.js +22 -0
  24. package/dist/acceptance-gate.js.map +1 -0
  25. package/dist/attachment-schema.d.ts +243 -0
  26. package/dist/attachment-schema.d.ts.map +1 -0
  27. package/dist/attachment-schema.js +200 -0
  28. package/dist/attachment-schema.js.map +1 -0
  29. package/dist/attachment.d.ts +224 -0
  30. package/dist/attachment.d.ts.map +1 -0
  31. package/dist/attachment.js +21 -0
  32. package/dist/attachment.js.map +1 -0
  33. package/dist/evidence-record-schema.d.ts +202 -0
  34. package/dist/evidence-record-schema.d.ts.map +1 -0
  35. package/dist/evidence-record-schema.js +130 -0
  36. package/dist/evidence-record-schema.js.map +1 -0
  37. package/dist/evidence-record.d.ts +167 -0
  38. package/dist/evidence-record.d.ts.map +1 -0
  39. package/dist/evidence-record.js +21 -0
  40. package/dist/evidence-record.js.map +1 -0
  41. package/dist/index.d.ts +12 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +6 -0
  44. package/dist/index.js.map +1 -1
  45. package/dist/task-evidence.d.ts +251 -0
  46. package/dist/task-evidence.d.ts.map +1 -0
  47. package/dist/task-evidence.js +89 -0
  48. package/dist/task-evidence.js.map +1 -0
  49. package/dist/task.d.ts +23 -4
  50. package/dist/task.d.ts.map +1 -1
  51. package/package.json +8 -2
  52. package/schemas/acceptance-gate.schema.json +9 -0
  53. package/schemas/attachment.schema.json +9 -0
  54. package/schemas/gate-result-details.schema.json +9 -0
  55. package/schemas/gate-result.schema.json +9 -0
  56. package/schemas/manifest-v1.json +176 -0
  57. package/schemas/task-evidence.schema.json +9 -0
  58. package/schemas/task.schema.json +9 -0
  59. package/src/__tests__/acceptance-gate.test.ts +736 -0
  60. package/src/__tests__/attachment.test.ts +601 -0
  61. package/src/__tests__/evidence-record.test.ts +412 -0
  62. package/src/__tests__/invariants.test.ts +445 -0
  63. package/src/acceptance-gate-schema.ts +347 -0
  64. package/src/acceptance-gate.ts +370 -0
  65. package/src/attachment-schema.ts +223 -0
  66. package/src/attachment.ts +245 -0
  67. package/src/evidence-record-schema.ts +158 -0
  68. package/src/evidence-record.ts +182 -0
  69. package/src/index.ts +114 -1
  70. package/src/task-evidence.ts +239 -0
  71. package/src/task.ts +24 -4
package/src/index.ts CHANGED
@@ -6,6 +6,45 @@
6
6
  * Implementation packages (@cleocode/core, @cleocode/cleo) import from here.
7
7
  */
8
8
 
9
+ // === Acceptance Gate Types (machine-verifiable criteria) ===
10
+ export type {
11
+ AcceptanceGate,
12
+ AcceptanceGateKind,
13
+ AcceptanceGateResult,
14
+ CommandGate,
15
+ FileAssertion,
16
+ FileGate,
17
+ GateBase,
18
+ GateResultDetails,
19
+ HttpGate,
20
+ LintGate,
21
+ ManualGate,
22
+ TestGate,
23
+ } from './acceptance-gate.js';
24
+ export type {
25
+ AcceptanceArrayInput,
26
+ AcceptanceGateResultInput,
27
+ AcceptanceGateSchemaInput,
28
+ AcceptanceItemInput,
29
+ FileAssertionInput,
30
+ GateResultDetailsInput,
31
+ } from './acceptance-gate-schema.js';
32
+ // === Acceptance Gate Zod Schemas (runtime validation) ===
33
+ export {
34
+ acceptanceArraySchema,
35
+ acceptanceGateResultSchema,
36
+ acceptanceGateSchema,
37
+ acceptanceItemSchema,
38
+ commandGateSchema,
39
+ fileAssertionSchema,
40
+ fileGateSchema,
41
+ gateBaseSchema,
42
+ gateResultDetailsSchema,
43
+ httpGateSchema,
44
+ lintGateSchema,
45
+ manualGateSchema,
46
+ testGateSchema,
47
+ } from './acceptance-gate-schema.js';
9
48
  // === Provider Adapter Contracts ===
10
49
  export type { AdapterHealthStatus, CLEOProviderAdapter } from './adapter.js';
11
50
  // === Agent Registry (credential management) ===
@@ -34,6 +73,34 @@ export type {
34
73
  CycleTimeDistribution,
35
74
  CycleTimePercentiles,
36
75
  } from './archive.js';
76
+ // === Attachment Types ===
77
+ export type {
78
+ Attachment,
79
+ AttachmentKind,
80
+ AttachmentMetadata,
81
+ AttachmentRef,
82
+ BlobAttachment,
83
+ LlmsTxtAttachment,
84
+ LlmtxtDocAttachment,
85
+ LocalFileAttachment,
86
+ UrlAttachment,
87
+ } from './attachment.js';
88
+ // === Attachment Zod Schemas (runtime validation) ===
89
+ export type {
90
+ AttachmentMetadataSchemaInput,
91
+ AttachmentRefSchemaInput,
92
+ AttachmentSchemaInput,
93
+ } from './attachment-schema.js';
94
+ export {
95
+ attachmentMetadataSchema,
96
+ attachmentRefSchema,
97
+ attachmentSchema,
98
+ blobAttachmentSchema,
99
+ llmsTxtAttachmentSchema,
100
+ llmtxtDocAttachmentSchema,
101
+ localFileAttachmentSchema,
102
+ urlAttachmentSchema,
103
+ } from './attachment-schema.js';
37
104
  // === Backup Manifest Types ===
38
105
  export type {
39
106
  BackupDatabaseEntry,
@@ -134,6 +201,33 @@ export {
134
201
  isErrorType,
135
202
  normalizeError,
136
203
  } from './errors.js';
204
+ // === Evidence Record Types (IVTR typed proof artifacts) ===
205
+ export type {
206
+ CommandOutputRecord,
207
+ EvidenceRecord,
208
+ EvidenceRecordKind,
209
+ ImplDiffRecord,
210
+ LintReportRecord,
211
+ TestOutputRecord,
212
+ ValidateSpecCheckRecord,
213
+ } from './evidence-record.js';
214
+ export type {
215
+ CommandOutputRecordInput,
216
+ EvidenceRecordInput,
217
+ ImplDiffRecordInput,
218
+ LintReportRecordInput,
219
+ TestOutputRecordInput,
220
+ ValidateSpecCheckRecordInput,
221
+ } from './evidence-record-schema.js';
222
+ // === Evidence Record Zod Schemas (runtime validation) ===
223
+ export {
224
+ commandOutputRecordSchema,
225
+ evidenceRecordSchema,
226
+ implDiffRecordSchema,
227
+ lintReportRecordSchema,
228
+ testOutputRecordSchema,
229
+ validateSpecCheckRecordSchema,
230
+ } from './evidence-record-schema.js';
137
231
  // === Exit Codes ===
138
232
  export {
139
233
  ExitCode,
@@ -323,6 +417,7 @@ export {
323
417
  } from './status-registry.js';
324
418
  // === Task Types ===
325
419
  export type {
420
+ AcceptanceItem,
326
421
  CancelledTask,
327
422
  CompletedTask,
328
423
  EpicLifecycle,
@@ -348,6 +443,25 @@ export type {
348
443
  VerificationFailure,
349
444
  VerificationGate,
350
445
  } from './task.js';
446
+ // === Task Evidence Types (T801) ===
447
+ export type {
448
+ CommandOutputEvidence,
449
+ FileEvidence,
450
+ LogEvidence,
451
+ ScreenshotEvidence,
452
+ TaskEvidence,
453
+ TaskEvidenceInput,
454
+ TaskEvidenceKind,
455
+ TestOutputEvidence,
456
+ } from './task-evidence.js';
457
+ export {
458
+ commandOutputEvidenceSchema,
459
+ fileEvidenceSchema,
460
+ logEvidenceSchema,
461
+ screenshotEvidenceSchema,
462
+ taskEvidenceSchema,
463
+ testOutputEvidenceSchema,
464
+ } from './task-evidence.js';
351
465
  // === TaskRecord Types (string-widened for dispatch/LAFS) ===
352
466
  export type {
353
467
  MinimalTaskRecord,
@@ -396,5 +510,4 @@ export type {
396
510
  WarpLink,
397
511
  WarpStage,
398
512
  } from './warp-chain.js';
399
-
400
513
  // === WASM SDK (Rust crate bindings) ===
@@ -0,0 +1,239 @@
1
+ /**
2
+ * TaskEvidence discriminated union — typed evidence references for verification records.
3
+ *
4
+ * Replaces free-text evidence fields in verification records with structured,
5
+ * kind-specific evidence artifacts. Each variant carries a SHA-256 attachment
6
+ * reference, a timestamp, and optional description.
7
+ *
8
+ * Five evidence kinds are supported:
9
+ * - `file` — a file artifact (source file, output artifact, config)
10
+ * - `log` — a log stream captured from a process
11
+ * - `screenshot` — a visual capture (PNG/JPEG/WEBP)
12
+ * - `test-output` — structured test-runner output
13
+ * - `command-output` — raw stdout/stderr from a shell command
14
+ *
15
+ * @epic T760
16
+ * @task T801
17
+ * @see {@link AcceptanceGateResult} — `evidence` field
18
+ */
19
+
20
+ import { z } from 'zod';
21
+
22
+ // ─── Variant interfaces ───────────────────────────────────────────────────────
23
+
24
+ /**
25
+ * Evidence for a file artifact produced or inspected during verification.
26
+ *
27
+ * The `sha256` is the content hash of the file at capture time, used to
28
+ * look up the blob in the attachment store.
29
+ */
30
+ export interface FileEvidence {
31
+ kind: 'file';
32
+ /** SHA-256 hex digest of the file at capture time (attachment ref). */
33
+ sha256: string;
34
+ /** ISO 8601 timestamp when evidence was captured. */
35
+ timestamp: string;
36
+ /** Path to the file, relative to the project root. */
37
+ path: string;
38
+ /** IANA MIME type of the file (e.g. `"text/typescript"`, `"application/pdf"`). */
39
+ mime?: string;
40
+ /** Optional human-readable note about this evidence artifact. */
41
+ description?: string;
42
+ }
43
+
44
+ /**
45
+ * Evidence for a log stream captured from a running process.
46
+ *
47
+ * The `sha256` is the content hash of the captured log text.
48
+ */
49
+ export interface LogEvidence {
50
+ kind: 'log';
51
+ /** SHA-256 hex digest of the captured log content. */
52
+ sha256: string;
53
+ /** ISO 8601 timestamp when evidence was captured. */
54
+ timestamp: string;
55
+ /**
56
+ * Source process name or description (e.g. `"pnpm test"`, `"node server.js"`).
57
+ */
58
+ source: string;
59
+ /** Optional human-readable note about this log artifact. */
60
+ description?: string;
61
+ }
62
+
63
+ /**
64
+ * Evidence for a screenshot or visual capture taken during verification.
65
+ *
66
+ * Used for manual gates and UI smoke tests. The `sha256` references the
67
+ * image blob in the attachment store.
68
+ */
69
+ export interface ScreenshotEvidence {
70
+ kind: 'screenshot';
71
+ /** SHA-256 hex digest of the image file. */
72
+ sha256: string;
73
+ /** ISO 8601 timestamp when evidence was captured. */
74
+ timestamp: string;
75
+ /**
76
+ * MIME type of the image.
77
+ *
78
+ * @defaultValue "image/png"
79
+ */
80
+ mime?: 'image/png' | 'image/jpeg' | 'image/webp';
81
+ /** Optional human-readable note (e.g. `"dark mode toggle on macOS Chrome"`). */
82
+ description?: string;
83
+ }
84
+
85
+ /**
86
+ * Evidence for structured test-runner output.
87
+ *
88
+ * Carries the summary metrics from the test run alongside the SHA-256
89
+ * reference to the full output blob.
90
+ */
91
+ export interface TestOutputEvidence {
92
+ kind: 'test-output';
93
+ /** SHA-256 hex digest of the full test-runner output. */
94
+ sha256: string;
95
+ /** ISO 8601 timestamp when evidence was captured. */
96
+ timestamp: string;
97
+ /** Number of tests that passed. */
98
+ passed: number;
99
+ /** Number of tests that failed. */
100
+ failed: number;
101
+ /** Number of tests skipped or pending. */
102
+ skipped: number;
103
+ /** Exit code of the test process. */
104
+ exitCode: number;
105
+ /** Optional human-readable note about the test run. */
106
+ description?: string;
107
+ }
108
+
109
+ /**
110
+ * Evidence for raw stdout/stderr output from a shell command.
111
+ *
112
+ * The `sha256` references the full output blob in the attachment store.
113
+ */
114
+ export interface CommandOutputEvidence {
115
+ kind: 'command-output';
116
+ /** SHA-256 hex digest of the full command output. */
117
+ sha256: string;
118
+ /** ISO 8601 timestamp when evidence was captured. */
119
+ timestamp: string;
120
+ /** The command that was run (e.g. `"pnpm run build"`). */
121
+ cmd: string;
122
+ /** Exit code of the command process. */
123
+ exitCode: number;
124
+ /** Optional human-readable note about the command run. */
125
+ description?: string;
126
+ }
127
+
128
+ // ─── Discriminated union ──────────────────────────────────────────────────────
129
+
130
+ /**
131
+ * A typed evidence artifact attached to a verification record.
132
+ *
133
+ * Replaces the bare `evidence?: string` field on {@link AcceptanceGateResult}
134
+ * with structured, kind-specific references backed by the attachment store.
135
+ *
136
+ * The `kind` field is the discriminant. All variants carry `sha256` (the
137
+ * attachment store ref), `timestamp`, and optional `description`.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * const ev: TaskEvidence = {
142
+ * kind: 'test-output',
143
+ * sha256: 'a1b2c3...ff',
144
+ * timestamp: '2026-04-15T10:00:00.000Z',
145
+ * passed: 42,
146
+ * failed: 0,
147
+ * skipped: 2,
148
+ * exitCode: 0,
149
+ * };
150
+ * ```
151
+ */
152
+ export type TaskEvidence =
153
+ | FileEvidence
154
+ | LogEvidence
155
+ | ScreenshotEvidence
156
+ | TestOutputEvidence
157
+ | CommandOutputEvidence;
158
+
159
+ /** All valid `kind` discriminants for `TaskEvidence`. */
160
+ export type TaskEvidenceKind = TaskEvidence['kind'];
161
+
162
+ // ─── Zod schemas ─────────────────────────────────────────────────────────────
163
+
164
+ /** Zod schema for {@link FileEvidence}. */
165
+ export const fileEvidenceSchema = z.object({
166
+ kind: z.literal('file'),
167
+ sha256: z.string().length(64),
168
+ timestamp: z.string().datetime(),
169
+ path: z.string().min(1),
170
+ mime: z.string().optional(),
171
+ description: z.string().optional(),
172
+ });
173
+
174
+ /** Zod schema for {@link LogEvidence}. */
175
+ export const logEvidenceSchema = z.object({
176
+ kind: z.literal('log'),
177
+ sha256: z.string().length(64),
178
+ timestamp: z.string().datetime(),
179
+ source: z.string().min(1),
180
+ description: z.string().optional(),
181
+ });
182
+
183
+ /** Zod schema for {@link ScreenshotEvidence}. */
184
+ export const screenshotEvidenceSchema = z.object({
185
+ kind: z.literal('screenshot'),
186
+ sha256: z.string().length(64),
187
+ timestamp: z.string().datetime(),
188
+ mime: z.enum(['image/png', 'image/jpeg', 'image/webp']).optional(),
189
+ description: z.string().optional(),
190
+ });
191
+
192
+ /** Zod schema for {@link TestOutputEvidence}. */
193
+ export const testOutputEvidenceSchema = z.object({
194
+ kind: z.literal('test-output'),
195
+ sha256: z.string().length(64),
196
+ timestamp: z.string().datetime(),
197
+ passed: z.number().int().nonnegative(),
198
+ failed: z.number().int().nonnegative(),
199
+ skipped: z.number().int().nonnegative(),
200
+ exitCode: z.number().int(),
201
+ description: z.string().optional(),
202
+ });
203
+
204
+ /** Zod schema for {@link CommandOutputEvidence}. */
205
+ export const commandOutputEvidenceSchema = z.object({
206
+ kind: z.literal('command-output'),
207
+ sha256: z.string().length(64),
208
+ timestamp: z.string().datetime(),
209
+ cmd: z.string().min(1),
210
+ exitCode: z.number().int(),
211
+ description: z.string().optional(),
212
+ });
213
+
214
+ /**
215
+ * Zod discriminated-union schema for {@link TaskEvidence}.
216
+ *
217
+ * Uses `z.discriminatedUnion('kind', [...])` for O(1) variant lookup.
218
+ *
219
+ * @example
220
+ * ```ts
221
+ * const ev = taskEvidenceSchema.parse({
222
+ * kind: 'command-output',
223
+ * sha256: 'a'.repeat(64),
224
+ * timestamp: '2026-04-15T10:00:00.000Z',
225
+ * cmd: 'pnpm run build',
226
+ * exitCode: 0,
227
+ * });
228
+ * ```
229
+ */
230
+ export const taskEvidenceSchema = z.discriminatedUnion('kind', [
231
+ fileEvidenceSchema,
232
+ logEvidenceSchema,
233
+ screenshotEvidenceSchema,
234
+ testOutputEvidenceSchema,
235
+ commandOutputEvidenceSchema,
236
+ ]);
237
+
238
+ /** Inferred TypeScript type from {@link taskEvidenceSchema}. */
239
+ export type TaskEvidenceInput = z.input<typeof taskEvidenceSchema>;
package/src/task.ts CHANGED
@@ -21,10 +21,23 @@
21
21
  * @task T4456
22
22
  */
23
23
 
24
+ import type { AcceptanceGate } from './acceptance-gate.js';
24
25
  import type { TaskStatus } from './status-registry.js';
25
26
 
26
27
  export type { TaskStatus };
27
28
 
29
+ /**
30
+ * A single acceptance criterion — either a free-text string (legacy) or a
31
+ * structured {@link AcceptanceGate} (machine-verifiable).
32
+ *
33
+ * Mixed arrays of these are stored as JSON in the `acceptance_json` column.
34
+ *
35
+ * @epic T760
36
+ * @task T780
37
+ * @task T800
38
+ */
39
+ export type AcceptanceItem = string | AcceptanceGate;
40
+
28
41
  /** Task priority levels. */
29
42
  export type TaskPriority = 'critical' | 'high' | 'medium' | 'low';
30
43
 
@@ -169,8 +182,15 @@ export interface Task {
169
182
  /** File paths associated with this task. @defaultValue undefined */
170
183
  files?: string[];
171
184
 
172
- /** Acceptance criteria for completion. @defaultValue undefined */
173
- acceptance?: string[];
185
+ /**
186
+ * Mixed acceptance criteria — free-text strings (legacy) and/or structured
187
+ * {@link AcceptanceGate} objects (machine-verifiable).
188
+ *
189
+ * @epic T760
190
+ * @task T780
191
+ * @defaultValue undefined
192
+ */
193
+ acceptance?: AcceptanceItem[];
174
194
 
175
195
  /** IDs of tasks this task depends on. @defaultValue undefined */
176
196
  depends?: string[];
@@ -296,8 +316,8 @@ export interface TaskCreate {
296
316
  /** File paths associated with this task. @defaultValue undefined */
297
317
  files?: string[];
298
318
 
299
- /** Acceptance criteria. @defaultValue undefined */
300
- acceptance?: string[];
319
+ /** Acceptance criteria (string or AcceptanceGate objects). @defaultValue undefined */
320
+ acceptance?: AcceptanceItem[];
301
321
 
302
322
  /** IDs of tasks this task depends on. @defaultValue undefined */
303
323
  depends?: string[];