@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance-gate-schema.d.ts","sourceRoot":"","sources":["../src/acceptance-gate-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;iBASzB,CAAC;AAIH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;2BAe9B,CAAC;AAEH,iEAAiE;AACjE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAIrE;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;iBAQzB,CAAC;AAEH,uCAAuC;AACvC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAazB,CAAC;AAEH,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;iBAS5B,CAAC;AAEH,uCAAuC;AACvC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;iBAMzB,CAAC;AAEH,uCAAuC;AACvC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;iBASzB,CAAC;AAEH,yCAAyC;AACzC,eAAO,MAAM,gBAAgB;;;;;;;;;;;;iBAI3B,CAAC;AAIH;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAO/B,CAAC;AAEH,kEAAkE;AAClE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAI7E;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAqClC,CAAC;AAEH,qEAAqE;AACrE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAI7E;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAarC,CAAC;AAEH,wEAAwE;AACxE,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAInF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAU/B,CAAC;AAEH,kEAAkE;AAClE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAwB/B,CAAC;AAEJ,mEAAmE;AACnE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Zod validation schemas for {@link AcceptanceGate} and related types.
3
+ *
4
+ * Kept in a separate file from the plain TypeScript types so that consumers
5
+ * that do not need runtime validation (e.g. type-only imports) pay zero cost.
6
+ *
7
+ * All schemas are named `*Schema` and derive their inferred types from the
8
+ * canonical TypeScript interfaces in `./acceptance-gate.ts`.
9
+ *
10
+ * @epic T760
11
+ * @task T763
12
+ * @task T779
13
+ */
14
+ import { z } from 'zod';
15
+ // ─── Base schema ──────────────────────────────────────────────────────────────
16
+ /**
17
+ * Zod schema for {@link GateBase} — fields every gate variant carries.
18
+ *
19
+ * Not exported as a standalone validator because it is always composed into a
20
+ * full gate schema via `z.discriminatedUnion`. Exported so downstream packages
21
+ * can extend it (e.g. for migration or testing).
22
+ */
23
+ export const gateBaseSchema = z.object({
24
+ /** Optional GSD-style REQ-ID, e.g. `"TIMER-03"`. */
25
+ req: z.string().optional(),
26
+ /** Human-readable description of what the gate checks. Required. */
27
+ description: z.string().min(1),
28
+ /** When true, failure is recorded as a warning rather than a block. */
29
+ advisory: z.boolean().optional(),
30
+ /** Per-gate timeout override in milliseconds. */
31
+ timeoutMs: z.number().int().positive().optional(),
32
+ });
33
+ // ─── File assertion schemas ───────────────────────────────────────────────────
34
+ /**
35
+ * Zod schema for {@link FileAssertion}.
36
+ *
37
+ * Each variant carries a `type` literal that drives the discriminated union.
38
+ */
39
+ export const fileAssertionSchema = z.discriminatedUnion('type', [
40
+ z.object({ type: z.literal('exists') }),
41
+ z.object({ type: z.literal('absent') }),
42
+ z.object({ type: z.literal('nonEmpty') }),
43
+ z.object({ type: z.literal('maxBytes'), value: z.number().int().nonnegative() }),
44
+ z.object({ type: z.literal('minBytes'), value: z.number().int().nonnegative() }),
45
+ z.object({ type: z.literal('contains'), value: z.string() }),
46
+ z.object({
47
+ type: z.literal('matches'),
48
+ /** Serialized `RegExp` source string. */
49
+ regex: z.string().min(1),
50
+ /** Optional `RegExp` flags, e.g. `"gim"`. */
51
+ flags: z.string().optional(),
52
+ }),
53
+ z.object({ type: z.literal('sha256'), value: z.string().length(64) }),
54
+ ]);
55
+ // ─── Individual gate schemas ──────────────────────────────────────────────────
56
+ /**
57
+ * Zod schema for {@link TestGate}.
58
+ *
59
+ * Validates that `command` is present and `expect` is one of the two allowed
60
+ * literal values.
61
+ */
62
+ export const testGateSchema = gateBaseSchema.extend({
63
+ kind: z.literal('test'),
64
+ command: z.string().min(1),
65
+ args: z.array(z.string()).optional(),
66
+ expect: z.enum(['pass', 'exit0']),
67
+ minCount: z.number().int().nonnegative().optional(),
68
+ cwd: z.string().optional(),
69
+ env: z.record(z.string(), z.string()).optional(),
70
+ });
71
+ /** Zod schema for {@link FileGate}. */
72
+ export const fileGateSchema = gateBaseSchema.extend({
73
+ kind: z.literal('file'),
74
+ /** Absolute or project-root-relative file path. Mutually exclusive with `attachmentSha256`. */
75
+ path: z.string().min(1).optional(),
76
+ /**
77
+ * SHA-256 hex of an attachment blob. Gate runner resolves the on-disk path
78
+ * via AttachmentStore. Mutually exclusive with `path`.
79
+ */
80
+ attachmentSha256: z
81
+ .string()
82
+ .regex(/^[0-9a-f]{64}$/i, 'attachmentSha256 must be a 64-char hex string')
83
+ .optional(),
84
+ assertions: z.array(fileAssertionSchema).min(1),
85
+ });
86
+ /** Zod schema for {@link CommandGate}. */
87
+ export const commandGateSchema = gateBaseSchema.extend({
88
+ kind: z.literal('command'),
89
+ cmd: z.string().min(1),
90
+ args: z.array(z.string()).optional(),
91
+ exitCode: z.number().int().optional(),
92
+ stdoutMatches: z.string().optional(),
93
+ stderrMatches: z.string().optional(),
94
+ cwd: z.string().optional(),
95
+ env: z.record(z.string(), z.string()).optional(),
96
+ });
97
+ /** Zod schema for {@link LintGate}. */
98
+ export const lintGateSchema = gateBaseSchema.extend({
99
+ kind: z.literal('lint'),
100
+ tool: z.enum(['biome', 'eslint', 'tsc', 'prettier', 'rustc', 'clippy']),
101
+ args: z.array(z.string()).optional(),
102
+ expect: z.enum(['clean', 'noErrors']),
103
+ cwd: z.string().optional(),
104
+ });
105
+ /** Zod schema for {@link HttpGate}. */
106
+ export const httpGateSchema = gateBaseSchema.extend({
107
+ kind: z.literal('http'),
108
+ url: z.string().url(),
109
+ method: z.enum(['GET', 'HEAD', 'POST', 'PUT', 'DELETE']).optional(),
110
+ status: z.number().int().min(100).max(599),
111
+ bodyMatches: z.string().optional(),
112
+ headers: z.record(z.string(), z.string()).optional(),
113
+ startCommand: z.string().optional(),
114
+ startupDelayMs: z.number().int().nonnegative().optional(),
115
+ });
116
+ /** Zod schema for {@link ManualGate}. */
117
+ export const manualGateSchema = gateBaseSchema.extend({
118
+ kind: z.literal('manual'),
119
+ prompt: z.string().min(1),
120
+ verdicts: z.array(z.enum(['pass', 'fail', 'warn'])).optional(),
121
+ });
122
+ // ─── Discriminated union ──────────────────────────────────────────────────────
123
+ /**
124
+ * Zod discriminated-union schema for {@link AcceptanceGate}.
125
+ *
126
+ * Uses `z.discriminatedUnion('kind', [...])` for O(1) variant lookup.
127
+ * Parse with `acceptanceGateSchema.parse(input)` or
128
+ * `acceptanceGateSchema.safeParse(input)`.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * const gate = acceptanceGateSchema.parse({
133
+ * kind: 'test',
134
+ * command: 'pnpm test',
135
+ * expect: 'pass',
136
+ * description: 'Test suite must pass',
137
+ * });
138
+ * ```
139
+ */
140
+ export const acceptanceGateSchema = z.discriminatedUnion('kind', [
141
+ testGateSchema,
142
+ fileGateSchema,
143
+ commandGateSchema,
144
+ lintGateSchema,
145
+ httpGateSchema,
146
+ manualGateSchema,
147
+ ]);
148
+ // ─── GateResultDetails schema (T802) ─────────────────────────────────────────
149
+ /**
150
+ * Zod discriminated-union schema for {@link GateResultDetails}.
151
+ *
152
+ * Each variant mirrors the corresponding {@link AcceptanceGate} kind so
153
+ * callers can narrow `details` using the `kind` discriminant.
154
+ *
155
+ * @epic T760
156
+ * @task T802
157
+ */
158
+ export const gateResultDetailsSchema = z.discriminatedUnion('kind', [
159
+ z.object({
160
+ kind: z.literal('test'),
161
+ exitCode: z.number().int(),
162
+ stdout: z.string(),
163
+ stderr: z.string(),
164
+ duration: z.number().nonnegative(),
165
+ }),
166
+ z.object({
167
+ kind: z.literal('file'),
168
+ path: z.string().min(1),
169
+ passedAssertions: z.array(z.string()),
170
+ failedAssertions: z.array(z.string()),
171
+ }),
172
+ z.object({
173
+ kind: z.literal('command'),
174
+ cmd: z.string().min(1),
175
+ exitCode: z.number().int(),
176
+ stdout: z.string(),
177
+ }),
178
+ z.object({
179
+ kind: z.literal('lint'),
180
+ tool: z.string().min(1),
181
+ warnings: z.number().int().nonnegative(),
182
+ errors: z.number().int().nonnegative(),
183
+ }),
184
+ z.object({
185
+ kind: z.literal('http'),
186
+ url: z.string(),
187
+ status: z.number().int().min(100).max(599),
188
+ body: z.string(),
189
+ }),
190
+ z.object({
191
+ kind: z.literal('manual'),
192
+ prompt: z.string().min(1),
193
+ accepted: z.boolean(),
194
+ }),
195
+ ]);
196
+ // ─── Result schema ────────────────────────────────────────────────────────────
197
+ /**
198
+ * Zod schema for {@link AcceptanceGateResult}.
199
+ *
200
+ * Validates the shape produced by the gate runner and stored in
201
+ * `lifecycle_gate_results`.
202
+ */
203
+ export const acceptanceGateResultSchema = z.object({
204
+ index: z.number().int().nonnegative(),
205
+ req: z.string().optional(),
206
+ kind: z.enum(['test', 'file', 'command', 'lint', 'http', 'manual']),
207
+ result: z.enum(['pass', 'fail', 'warn', 'skipped', 'error']),
208
+ durationMs: z.number().nonnegative(),
209
+ /** Typed kind-specific detail payload (T802). */
210
+ details: gateResultDetailsSchema.optional(),
211
+ evidence: z.string().optional(),
212
+ errorMessage: z.string().optional(),
213
+ /** ISO 8601 timestamp. */
214
+ checkedAt: z.string().datetime(),
215
+ checkedBy: z.string().min(1),
216
+ });
217
+ // ─── Mixed acceptance item schema (T780 + T800) ───────────────────────────────
218
+ /**
219
+ * Zod schema for a single acceptance criterion — either a non-empty string
220
+ * (legacy) or a structured {@link AcceptanceGate} (machine-verifiable).
221
+ *
222
+ * **Tightened (T800)**: Rejects empty strings, whitespace-only strings, and
223
+ * any non-gate objects. Clear error messages guide callers toward valid input.
224
+ *
225
+ * Strings are validated with `z.string().trim().min(1)` to eliminate empty
226
+ * and whitespace-only criteria. The gate branch uses the existing discriminated-union
227
+ * schema so all six gate kinds (`test`, `file`, `command`, `lint`, `http`, `manual`)
228
+ * are accepted.
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * acceptanceItemSchema.parse('must render in <100ms'); // => 'must render in <100ms'
233
+ * acceptanceItemSchema.parse({ kind: 'test', command: 'pnpm test', expect: 'pass', description: '...' }); // => TestGate
234
+ * acceptanceItemSchema.parse(''); // ERROR: string must be non-empty
235
+ * acceptanceItemSchema.parse({ foo: 'bar' }); // ERROR: invalid gate object
236
+ * ```
237
+ *
238
+ * @epic T760
239
+ * @task T780
240
+ * @task T800
241
+ */
242
+ export const acceptanceItemSchema = z.union([
243
+ z
244
+ .string()
245
+ .trim()
246
+ .min(1, {
247
+ message: 'Acceptance string criterion must be non-empty. Provide a non-blank description or a valid AcceptanceGate object.',
248
+ })
249
+ .describe('Free-text legacy acceptance criterion (non-empty string)'),
250
+ acceptanceGateSchema.describe('Structured machine-verifiable acceptance gate'),
251
+ ]);
252
+ /**
253
+ * Zod schema for a mixed acceptance array — `(string | AcceptanceGate)[]`.
254
+ *
255
+ * **Tightened (T800)**:
256
+ * - Requires at least 1 item (matching CLEO's anti-hallucination policy).
257
+ * - Rejects duplicate `req:` GSD-style REQ-IDs within the same array.
258
+ *
259
+ * Use this to validate the full `Task.acceptance` field after widening (T780).
260
+ *
261
+ * @example
262
+ * ```ts
263
+ * // Valid: mixed types with unique req IDs
264
+ * acceptanceArraySchema.parse([
265
+ * 'must render in <100ms',
266
+ * { kind: 'test', command: 'pnpm test', expect: 'pass', description: 'Tests pass', req: 'TEST-01' }
267
+ * ]);
268
+ *
269
+ * // ERROR: empty array
270
+ * acceptanceArraySchema.parse([]);
271
+ *
272
+ * // ERROR: duplicate req:'TEST-01' across two gates
273
+ * acceptanceArraySchema.parse([
274
+ * { kind: 'test', command: 'pnpm test', expect: 'pass', description: 'Tests pass', req: 'TEST-01' },
275
+ * { kind: 'file', path: 'README.md', assertions: [{ type: 'exists' }], description: 'README exists', req: 'TEST-01' }
276
+ * ]);
277
+ * ```
278
+ *
279
+ * @epic T760
280
+ * @task T780
281
+ * @task T800
282
+ */
283
+ export const acceptanceArraySchema = z
284
+ .array(acceptanceItemSchema)
285
+ .min(1, {
286
+ message: 'Task must have at least one acceptance criterion. Provide a non-empty string or a valid AcceptanceGate object.',
287
+ })
288
+ .refine((items) => {
289
+ // Extract all req: values from gates (skip plain strings)
290
+ const reqIds = new Set();
291
+ for (const item of items) {
292
+ if (typeof item === 'object' && item !== null && 'req' in item && item.req) {
293
+ if (reqIds.has(item.req)) {
294
+ return false; // Duplicate found
295
+ }
296
+ reqIds.add(item.req);
297
+ }
298
+ }
299
+ return true; // No duplicates
300
+ }, {
301
+ message: 'Duplicate req: (REQ-ID) values within the same acceptance array. Each GSD-style requirement ID must be unique. Check for repeated req fields and ensure each gate has a distinct identifier.',
302
+ });
303
+ //# sourceMappingURL=acceptance-gate-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance-gate-schema.js","sourceRoot":"","sources":["../src/acceptance-gate-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Acceptance gate discriminated union and result types.
3
+ *
4
+ * A machine-verifiable acceptance gate. Gates coexist with free-text criteria
5
+ * in `Task.acceptance`; the runtime executes only gates and records results in
6
+ * `task.verification.gateResults` and in the `lifecycle_gate_results` DB table.
7
+ *
8
+ * Six gate kinds are supported:
9
+ * - `test` — run a command and assert exit code / test-count
10
+ * - `file` — assert properties of a file on disk
11
+ * - `command` — run any CLI command and assert exit code / stdout
12
+ * - `lint` — run a static-analysis tool and require a clean result
13
+ * - `http` — hit a URL and assert status + optional body
14
+ * - `manual` — explicit escape hatch requiring human/agent verdict
15
+ *
16
+ * @epic T760
17
+ * @task T763
18
+ * @task T779
19
+ * @see {@link https://github.com/kryptobaseddev/cleo} T760 RCASD hardening
20
+ */
21
+ /** Fields every gate variant carries. */
22
+ export interface GateBase {
23
+ /**
24
+ * Optional REQ-ID (GSD-style: `TIMER-03`, `A11Y-04`). When present the
25
+ * gate is addressable via `cleo req show <taskId> --id TIMER-03` and its
26
+ * result is indexed in `lifecycle_gate_results.gate_name`.
27
+ */
28
+ req?: string;
29
+ /**
30
+ * Free-text description of what this gate is checking. Shown in
31
+ * `cleo show` output and in failure messages. Required so agents and
32
+ * humans can read the gate without executing it.
33
+ */
34
+ description: string;
35
+ /**
36
+ * When `true` a failure of this gate does not block completion — it is
37
+ * recorded as `result: 'warn'` in `lifecycle_gate_results`.
38
+ *
39
+ * @defaultValue false
40
+ */
41
+ advisory?: boolean;
42
+ /**
43
+ * Gate timeout in milliseconds.
44
+ *
45
+ * @defaultValue 120_000
46
+ */
47
+ timeoutMs?: number;
48
+ }
49
+ /**
50
+ * Run a command; pass when exit code is 0 and when at least `minCount`
51
+ * tests have run. Designed for test suites:
52
+ * `{ kind: 'test', command: 'pnpm test', expect: 'pass' }`.
53
+ */
54
+ export interface TestGate extends GateBase {
55
+ kind: 'test';
56
+ /** Shell command. Executed via `child_process.spawn`, no `shell: true`. */
57
+ command: string;
58
+ /** Arguments split explicitly (avoids shell-injection). */
59
+ args?: string[];
60
+ /**
61
+ * - `"pass"`: exit code 0 AND stdout contains no `FAIL|failing|Error:` pattern.
62
+ * - `"exit0"`: exit code 0 only (permissive mode).
63
+ */
64
+ expect: 'pass' | 'exit0';
65
+ /** Minimum number of tests that must have run. */
66
+ minCount?: number;
67
+ /** Working directory relative to project root. Default `.`. */
68
+ cwd?: string;
69
+ /** Environment variable overrides. Keys must match `/^[A-Z_][A-Z0-9_]*$/`. */
70
+ env?: Record<string, string>;
71
+ }
72
+ /**
73
+ * Assert properties of a file on disk. Multiple assertions are AND-ed:
74
+ * all must hold for the gate to pass.
75
+ *
76
+ * Either `path` or `attachmentSha256` must be provided (not both).
77
+ * When `attachmentSha256` is set, the gate runner resolves the on-disk path
78
+ * via `AttachmentStore.get(sha256)` before running assertions.
79
+ */
80
+ export interface FileGate extends GateBase {
81
+ kind: 'file';
82
+ /**
83
+ * Absolute or project-root-relative path. Globs are not supported here
84
+ * — use one gate per path.
85
+ *
86
+ * Exactly one of `path` or `attachmentSha256` must be set.
87
+ */
88
+ path?: string;
89
+ /**
90
+ * SHA-256 hex digest of an attachment stored in the CLEO attachment store.
91
+ *
92
+ * When set, the gate runner resolves the attachment's on-disk blob path
93
+ * via `AttachmentStore.get(sha256)` and uses that path for all assertions.
94
+ * Mutually exclusive with `path`.
95
+ *
96
+ * @example
97
+ * ```json
98
+ * { "kind": "file", "attachmentSha256": "a1b2c3...", "assertions": [{ "type": "nonEmpty" }] }
99
+ * ```
100
+ */
101
+ attachmentSha256?: string;
102
+ assertions: FileAssertion[];
103
+ }
104
+ /**
105
+ * A single assertion about a file on disk.
106
+ *
107
+ * All assertion variants in a `FileGate` must pass for the gate to pass.
108
+ */
109
+ export type FileAssertion = {
110
+ type: 'exists';
111
+ } | {
112
+ type: 'absent';
113
+ } | {
114
+ type: 'nonEmpty';
115
+ } | {
116
+ type: 'maxBytes';
117
+ value: number;
118
+ } | {
119
+ type: 'minBytes';
120
+ value: number;
121
+ } | {
122
+ type: 'contains';
123
+ value: string;
124
+ } | {
125
+ type: 'matches';
126
+ /** Serialized `RegExp` source string. */
127
+ regex: string;
128
+ /** Optional `RegExp` flags, e.g. `"gim"`. */
129
+ flags?: string;
130
+ } | {
131
+ type: 'sha256';
132
+ value: string;
133
+ };
134
+ /**
135
+ * Run any CLI command and assert exit code and optional stdout match.
136
+ * Escape hatch for anything `TestGate`/`LintGate`/`HttpGate` do not cover.
137
+ */
138
+ export interface CommandGate extends GateBase {
139
+ kind: 'command';
140
+ cmd: string;
141
+ args?: string[];
142
+ /**
143
+ * Expected exit code.
144
+ *
145
+ * @defaultValue 0
146
+ */
147
+ exitCode?: number;
148
+ /** stdout must match this regex source. */
149
+ stdoutMatches?: string;
150
+ /** stderr must match this regex source. */
151
+ stderrMatches?: string;
152
+ /** Working directory relative to project root. */
153
+ cwd?: string;
154
+ /** Environment variable overrides. */
155
+ env?: Record<string, string>;
156
+ }
157
+ /**
158
+ * Run a static-analysis tool and require a clean result.
159
+ * Wraps common cases with known exit codes so agents do not re-invent them.
160
+ */
161
+ export interface LintGate extends GateBase {
162
+ kind: 'lint';
163
+ /** Linting tool to invoke. */
164
+ tool: 'biome' | 'eslint' | 'tsc' | 'prettier' | 'rustc' | 'clippy';
165
+ /**
166
+ * Tool arguments. Defaults: biome→`['check', '.']`, eslint→`['.']`,
167
+ * tsc→`['--noEmit']`.
168
+ */
169
+ args?: string[];
170
+ /**
171
+ * - `"clean"`: zero findings.
172
+ * - `"noErrors"`: tolerates warnings but not errors.
173
+ */
174
+ expect: 'clean' | 'noErrors';
175
+ /** Working directory relative to project root. */
176
+ cwd?: string;
177
+ }
178
+ /**
179
+ * Hit a URL and assert HTTP status and optional body match. For tasks that
180
+ * ship a webapp or API. The runner starts a server only if `startCommand`
181
+ * is set and tears it down after the probe.
182
+ */
183
+ export interface HttpGate extends GateBase {
184
+ kind: 'http';
185
+ url: string;
186
+ /** HTTP method for the probe request. Default `"GET"`. */
187
+ method?: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE';
188
+ /** Expected HTTP status code. */
189
+ status: number;
190
+ /** Response body must match this regex source. */
191
+ bodyMatches?: string;
192
+ /** Request headers to include. */
193
+ headers?: Record<string, string>;
194
+ /** Pre-probe command to start a server. Runs in background; killed after probe. */
195
+ startCommand?: string;
196
+ /**
197
+ * Milliseconds to wait after starting before probing.
198
+ *
199
+ * @defaultValue 2000
200
+ */
201
+ startupDelayMs?: number;
202
+ }
203
+ /**
204
+ * Explicit escape hatch: a gate the runtime CANNOT verify automatically.
205
+ * Requires a human or a different agent to record a verdict before
206
+ * `cleo complete` will accept it.
207
+ *
208
+ * This is the ONLY gate variant that preserves today's free-text behaviour.
209
+ * Use for subjective criteria: "copy reads well", "visual design matches mockup".
210
+ */
211
+ export interface ManualGate extends GateBase {
212
+ kind: 'manual';
213
+ /** Question or prompt shown to the human or agent performing verification. */
214
+ prompt: string;
215
+ /**
216
+ * Valid verdicts the reviewer may record.
217
+ *
218
+ * @defaultValue ['pass', 'fail']
219
+ */
220
+ verdicts?: ('pass' | 'fail' | 'warn')[];
221
+ }
222
+ /**
223
+ * A machine-verifiable acceptance gate attached to a task.
224
+ *
225
+ * All variants share the {@link GateBase} fields (`req`, `description`,
226
+ * `advisory`, `timeoutMs`). The `kind` discriminant selects the variant.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * const gate: AcceptanceGate = {
231
+ * kind: 'test',
232
+ * command: 'pnpm test',
233
+ * expect: 'pass',
234
+ * minCount: 3,
235
+ * description: '≥3 tests must pass',
236
+ * };
237
+ * ```
238
+ */
239
+ export type AcceptanceGate = TestGate | FileGate | CommandGate | LintGate | HttpGate | ManualGate;
240
+ /** All valid `kind` discriminants for `AcceptanceGate`. */
241
+ export type AcceptanceGateKind = AcceptanceGate['kind'];
242
+ /**
243
+ * Kind-specific detail payload for {@link AcceptanceGateResult}.
244
+ *
245
+ * Each variant is keyed by `kind` — the same discriminant used on
246
+ * {@link AcceptanceGate} — so callers can narrow `details` with a simple
247
+ * `if (result.details?.kind === 'test') { ... }` guard.
248
+ *
249
+ * @epic T760
250
+ * @task T802
251
+ */
252
+ export type GateResultDetails = {
253
+ kind: 'test';
254
+ /** Exit code of the test process. */
255
+ exitCode: number;
256
+ /** Captured standard output (may be truncated). */
257
+ stdout: string;
258
+ /** Captured standard error (may be truncated). */
259
+ stderr: string;
260
+ /** Wall-clock duration in milliseconds. */
261
+ duration: number;
262
+ } | {
263
+ kind: 'file';
264
+ /** The file path that was evaluated. */
265
+ path: string;
266
+ /** Assertions that passed. */
267
+ passedAssertions: string[];
268
+ /** Assertions that failed (empty on pass). */
269
+ failedAssertions: string[];
270
+ } | {
271
+ kind: 'command';
272
+ /** The command that was run. */
273
+ cmd: string;
274
+ /** Exit code of the command process. */
275
+ exitCode: number;
276
+ /** Captured standard output (may be truncated). */
277
+ stdout: string;
278
+ } | {
279
+ kind: 'lint';
280
+ /** Linting tool name (e.g. `"biome"`, `"tsc"`). */
281
+ tool: string;
282
+ /** Number of diagnostic warnings emitted. */
283
+ warnings: number;
284
+ /** Number of diagnostic errors emitted. */
285
+ errors: number;
286
+ } | {
287
+ kind: 'http';
288
+ /** The URL that was probed. */
289
+ url: string;
290
+ /** HTTP status code returned by the server. */
291
+ status: number;
292
+ /** Response body (may be truncated). */
293
+ body: string;
294
+ } | {
295
+ kind: 'manual';
296
+ /** The prompt shown to the reviewer. */
297
+ prompt: string;
298
+ /** Whether the reviewer accepted (`true`) or rejected (`false`) the gate. */
299
+ accepted: boolean;
300
+ };
301
+ /**
302
+ * Result of running one acceptance gate.
303
+ *
304
+ * Persisted to `lifecycle_gate_results` and summarised in
305
+ * `task.verification.gateResults`.
306
+ *
307
+ * NOTE: Named `AcceptanceGateResult` (not `GateResult`) to avoid collision
308
+ * with the existing {@link GateResult} from `./warp-chain.js` which describes
309
+ * WarpChain LOOM-gate evaluation outcomes.
310
+ */
311
+ export interface AcceptanceGateResult {
312
+ /** Zero-based index in the task's acceptance array. */
313
+ index: number;
314
+ /** REQ-ID if the gate had one, else `undefined`. */
315
+ req?: string;
316
+ /** Gate variant. */
317
+ kind: AcceptanceGateKind;
318
+ /** Outcome of the gate execution. */
319
+ result: 'pass' | 'fail' | 'warn' | 'skipped' | 'error';
320
+ /** Wall-clock duration of the gate execution in milliseconds. */
321
+ durationMs: number;
322
+ /**
323
+ * Typed kind-specific detail payload.
324
+ *
325
+ * Replaces the untyped `evidence?: string` pattern. The `kind` discriminant
326
+ * matches the gate's `kind` so callers can narrow safely:
327
+ *
328
+ * ```ts
329
+ * if (r.details?.kind === 'test') {
330
+ * console.log(r.details.exitCode, r.details.stdout);
331
+ * }
332
+ * ```
333
+ */
334
+ details?: GateResultDetails;
335
+ /**
336
+ * Short plain-text evidence snippet shown in failure messages.
337
+ *
338
+ * Kept for backward compatibility with existing persisted records and
339
+ * display code that reads this field as a truncated summary.
340
+ * New code should prefer {@link details}.
341
+ */
342
+ evidence?: string;
343
+ /** Error message when `result` is `"error"` (the gate runner itself crashed). */
344
+ errorMessage?: string;
345
+ /** ISO 8601 timestamp at which the gate ran. */
346
+ checkedAt: string;
347
+ /** Agent identifier or `"human"` that ran or attested the gate. */
348
+ checkedBy: string;
349
+ }
350
+ //# sourceMappingURL=acceptance-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance-gate.d.ts","sourceRoot":"","sources":["../src/acceptance-gate.ts"],"names":[],"mappings":"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"}