@gate-forge/core 0.7.1 → 0.9.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.
- package/dist/classifier/bind.d.ts +2 -0
- package/dist/classifier/bind.d.ts.map +1 -1
- package/dist/classifier/bind.js +8 -0
- package/dist/classifier/bind.js.map +1 -1
- package/dist/classifier/classify.d.ts +2 -0
- package/dist/classifier/classify.d.ts.map +1 -1
- package/dist/classifier/classify.js +127 -2
- package/dist/classifier/classify.js.map +1 -1
- package/dist/classifier/index.d.ts +2 -2
- package/dist/classifier/index.d.ts.map +1 -1
- package/dist/classifier/index.js +1 -1
- package/dist/classifier/index.js.map +1 -1
- package/dist/classifier/schema.d.ts +54 -0
- package/dist/classifier/schema.d.ts.map +1 -1
- package/dist/classifier/schema.js +17 -0
- package/dist/classifier/schema.js.map +1 -1
- package/dist/config/index.d.ts +186 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +327 -1
- package/dist/config/index.js.map +1 -1
- package/dist/graph/schema.d.ts +34 -0
- package/dist/graph/schema.d.ts.map +1 -1
- package/dist/index.d.ts +80 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -6
- package/dist/index.js.map +1 -1
- package/dist/mapping/resolve.d.ts +32 -1
- package/dist/mapping/resolve.d.ts.map +1 -1
- package/dist/mapping/resolve.js +297 -65
- package/dist/mapping/resolve.js.map +1 -1
- package/dist/policy/evaluate.d.ts +30 -0
- package/dist/policy/evaluate.d.ts.map +1 -1
- package/dist/policy/evaluate.js +22 -12
- package/dist/policy/evaluate.js.map +1 -1
- package/dist/quarantine/index.d.ts +82 -0
- package/dist/quarantine/index.d.ts.map +1 -0
- package/dist/quarantine/index.js +194 -0
- package/dist/quarantine/index.js.map +1 -0
- package/dist/receipt/index.d.ts +65 -1
- package/dist/receipt/index.d.ts.map +1 -1
- package/dist/receipt/index.js +115 -1
- package/dist/receipt/index.js.map +1 -1
- package/dist/report/human-message.d.ts +33 -0
- package/dist/report/human-message.d.ts.map +1 -0
- package/dist/report/human-message.js +33 -0
- package/dist/report/human-message.js.map +1 -0
- package/dist/report/index.d.ts +183 -9
- package/dist/report/index.d.ts.map +1 -1
- package/dist/report/index.js +317 -23
- package/dist/report/index.js.map +1 -1
- package/dist/schemas/adoption.d.ts +2 -0
- package/dist/schemas/adoption.d.ts.map +1 -1
- package/dist/schemas/adoption.js +6 -0
- package/dist/schemas/adoption.js.map +1 -1
- package/dist/schemas/behavior-catalog.d.ts +12 -0
- package/dist/schemas/behavior-catalog.d.ts.map +1 -1
- package/dist/schemas/behavior-evidence.d.ts +40 -0
- package/dist/schemas/behavior-evidence.d.ts.map +1 -1
- package/dist/schemas/behavior-evidence.js +9 -0
- package/dist/schemas/behavior-evidence.js.map +1 -1
- package/dist/schemas/behavior-policy.d.ts +26 -0
- package/dist/schemas/behavior-policy.d.ts.map +1 -1
- package/dist/schemas/behavior-policy.js +37 -1
- package/dist/schemas/behavior-policy.js.map +1 -1
- package/dist/schemas/execution-result.d.ts +17 -5
- package/dist/schemas/execution-result.d.ts.map +1 -1
- package/dist/schemas/execution-result.js +57 -2
- package/dist/schemas/execution-result.js.map +1 -1
- package/dist/schemas/gate-receipt.d.ts +25 -2
- package/dist/schemas/gate-receipt.d.ts.map +1 -1
- package/dist/schemas/gate-receipt.js +181 -2
- package/dist/schemas/gate-receipt.js.map +1 -1
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/policy.d.ts +19 -0
- package/dist/schemas/policy.d.ts.map +1 -1
- package/dist/schemas/policy.js +36 -0
- package/dist/schemas/policy.js.map +1 -1
- package/dist/schemas/quarantine.d.ts +25 -0
- package/dist/schemas/quarantine.d.ts.map +1 -0
- package/dist/schemas/quarantine.js +34 -0
- package/dist/schemas/quarantine.js.map +1 -0
- package/dist/schemas/queue-observer.d.ts +195 -0
- package/dist/schemas/queue-observer.d.ts.map +1 -0
- package/dist/schemas/queue-observer.js +190 -0
- package/dist/schemas/queue-observer.js.map +1 -0
- package/dist/schemas/run-record.d.ts +57 -0
- package/dist/schemas/run-record.d.ts.map +1 -0
- package/dist/schemas/run-record.js +108 -0
- package/dist/schemas/run-record.js.map +1 -0
- package/dist/schemas/runtime-config.d.ts +67 -0
- package/dist/schemas/runtime-config.d.ts.map +1 -1
- package/dist/schemas/runtime-config.js +75 -1
- package/dist/schemas/runtime-config.js.map +1 -1
- package/dist/schemas/signature-profile.d.ts +99 -0
- package/dist/schemas/signature-profile.d.ts.map +1 -0
- package/dist/schemas/signature-profile.js +197 -0
- package/dist/schemas/signature-profile.js.map +1 -0
- package/dist/schemas/test-map.d.ts +4 -0
- package/dist/schemas/test-map.d.ts.map +1 -1
- package/dist/schemas/test-map.js +12 -0
- package/dist/schemas/test-map.js.map +1 -1
- package/dist/schemas/verdict.d.ts +19 -4
- package/dist/schemas/verdict.d.ts.map +1 -1
- package/dist/schemas/verdict.js +42 -5
- package/dist/schemas/verdict.js.map +1 -1
- package/dist/strictness.d.ts +102 -0
- package/dist/strictness.d.ts.map +1 -0
- package/dist/strictness.js +92 -0
- package/dist/strictness.js.map +1 -0
- package/dist/supervision/index.js +6 -6
- package/dist/supervision/index.js.map +1 -1
- package/dist/twin-paths.d.ts +125 -0
- package/dist/twin-paths.d.ts.map +1 -0
- package/dist/twin-paths.js +233 -0
- package/dist/twin-paths.js.map +1 -0
- package/dist/verdict/behavior.d.ts.map +1 -1
- package/dist/verdict/behavior.js +284 -10
- package/dist/verdict/behavior.js.map +1 -1
- package/dist/verdict/cause.d.ts.map +1 -1
- package/dist/verdict/cause.js +18 -0
- package/dist/verdict/cause.js.map +1 -1
- package/dist/verdict/evaluate.d.ts +62 -0
- package/dist/verdict/evaluate.d.ts.map +1 -1
- package/dist/verdict/evaluate.js +300 -13
- package/dist/verdict/evaluate.js.map +1 -1
- package/dist/verdict/index.d.ts +3 -3
- package/dist/verdict/index.d.ts.map +1 -1
- package/dist/verdict/index.js +3 -3
- package/dist/verdict/index.js.map +1 -1
- package/dist/verdict/pack-verifiers.d.ts +17 -3
- package/dist/verdict/pack-verifiers.d.ts.map +1 -1
- package/dist/verdict/pack-verifiers.js +47 -8
- package/dist/verdict/pack-verifiers.js.map +1 -1
- package/dist/verdict/registry.d.ts +19 -0
- package/dist/verdict/registry.d.ts.map +1 -1
- package/dist/verdict/registry.js +21 -0
- package/dist/verdict/registry.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queue-observer schemas: the OWNER
|
|
3
|
+
* declaration that binds a task resource to the queue the engine
|
|
4
|
+
* reads, plus the SEALED observation vocabulary the engine's own
|
|
5
|
+
* bounded reads are graded against. One schema, parsed by the CLI at
|
|
6
|
+
* config time AND by the witness when it opens the channel from its
|
|
7
|
+
* own environment, so a typo is a config error (never a silent
|
|
8
|
+
* default) and the two sides can never disagree about what was
|
|
9
|
+
* declared.
|
|
10
|
+
*
|
|
11
|
+
* Connection material never carries a secret inline: the URL form names
|
|
12
|
+
* an environment variable the witness process resolves privately, and
|
|
13
|
+
* the value is never sealed into a record, a report, or argv.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
/**
|
|
17
|
+
* The SEALED observation vocabulary. The witness reads the queue and
|
|
18
|
+
* seals what it read; the grader re-derives every task verdict from
|
|
19
|
+
* these fields alone. A suite-submitted "the job succeeded" cannot
|
|
20
|
+
* produce this shape — only the engine's own bounded reads can.
|
|
21
|
+
*
|
|
22
|
+
* Normalized states are library-independent on purpose: every
|
|
23
|
+
* implementation maps its backend's own vocabulary onto these seven,
|
|
24
|
+
* and an unrecognized backend state is a hard failure (fail closed),
|
|
25
|
+
* never a silent mapping.
|
|
26
|
+
*/
|
|
27
|
+
/** Normalized job states an observer may report. */
|
|
28
|
+
export declare const QUEUE_JOB_STATES: readonly ["waiting", "delayed", "prioritized", "active", "completed", "failed", "paused"];
|
|
29
|
+
/** Inferred normalized job state. */
|
|
30
|
+
export type QueueJobState = (typeof QUEUE_JOB_STATES)[number];
|
|
31
|
+
/** States a delivery may never leave while the engine waits. */
|
|
32
|
+
export declare const TERMINAL_QUEUE_JOB_STATES: ReadonlySet<QueueJobState>;
|
|
33
|
+
/** Hard bound on one observed field value (over it, fail closed). */
|
|
34
|
+
export declare const MAX_QUEUE_FIELD_CHARS = 512;
|
|
35
|
+
/** Default bound for one bounded list read. */
|
|
36
|
+
export declare const DEFAULT_QUEUE_LIST_LIMIT = 200;
|
|
37
|
+
/** Hard bound for one bounded list read (over it, fail closed). */
|
|
38
|
+
export declare const MAX_QUEUE_LIST_LIMIT = 1000;
|
|
39
|
+
/**
|
|
40
|
+
* Hard bound on the sealed observations of one delivery. One sample per
|
|
41
|
+
* polling tick, so a default 200 ms sampling interval and a 30 s settle
|
|
42
|
+
* bound sit well inside it; a longer wait fails closed rather than
|
|
43
|
+
* truncating the timeline a stall claim reads.
|
|
44
|
+
*/
|
|
45
|
+
export declare const MAX_QUEUE_SAMPLES = 2048;
|
|
46
|
+
/** One engine-read job observation (bounded fields only). */
|
|
47
|
+
export declare const QueueJobObservationSchema: z.ZodObject<{
|
|
48
|
+
jobId: z.ZodString;
|
|
49
|
+
deliveryId: z.ZodNullable<z.ZodString>;
|
|
50
|
+
idempotencyKey: z.ZodNullable<z.ZodString>;
|
|
51
|
+
state: z.ZodEnum<{
|
|
52
|
+
active: "active";
|
|
53
|
+
failed: "failed";
|
|
54
|
+
waiting: "waiting";
|
|
55
|
+
delayed: "delayed";
|
|
56
|
+
prioritized: "prioritized";
|
|
57
|
+
completed: "completed";
|
|
58
|
+
paused: "paused";
|
|
59
|
+
}>;
|
|
60
|
+
attemptsMade: z.ZodNumber;
|
|
61
|
+
maxAttempts: z.ZodNullable<z.ZodNumber>;
|
|
62
|
+
failedReason: z.ZodNullable<z.ZodString>;
|
|
63
|
+
processedAt: z.ZodNullable<z.ZodNumber>;
|
|
64
|
+
}, z.core.$strict>;
|
|
65
|
+
/** Inferred job-observation shape. */
|
|
66
|
+
export type QueueJobObservation = z.infer<typeof QueueJobObservationSchema>;
|
|
67
|
+
/**
|
|
68
|
+
* One sampled observation of a job with the engine's own elapsed time.
|
|
69
|
+
* Samples are NOT deduplicated: a queue that hands the same job out a
|
|
70
|
+
* second time (a lost-worker reclaim) is exactly the transition a
|
|
71
|
+
* "changed only" filter would hide. The record stays bounded by
|
|
72
|
+
* {@link MAX_QUEUE_SAMPLES}, over which the engine fails closed.
|
|
73
|
+
*/
|
|
74
|
+
export declare const QueueJobSampleSchema: z.ZodObject<{
|
|
75
|
+
jobId: z.ZodString;
|
|
76
|
+
state: z.ZodEnum<{
|
|
77
|
+
active: "active";
|
|
78
|
+
failed: "failed";
|
|
79
|
+
waiting: "waiting";
|
|
80
|
+
delayed: "delayed";
|
|
81
|
+
prioritized: "prioritized";
|
|
82
|
+
completed: "completed";
|
|
83
|
+
paused: "paused";
|
|
84
|
+
}>;
|
|
85
|
+
attemptsMade: z.ZodNumber;
|
|
86
|
+
failedReason: z.ZodNullable<z.ZodString>;
|
|
87
|
+
atMs: z.ZodNumber;
|
|
88
|
+
}, z.core.$strict>;
|
|
89
|
+
/** Inferred job-sample shape. */
|
|
90
|
+
export type QueueJobSample = z.infer<typeof QueueJobSampleSchema>;
|
|
91
|
+
/**
|
|
92
|
+
* The engine's sealed read of one delivery's jobs. `complete:false`
|
|
93
|
+
* means the engine stopped waiting before every job settled: that can
|
|
94
|
+
* never satisfy a task rule, and it is sealed as a diagnostic rather
|
|
95
|
+
* than a partial proof.
|
|
96
|
+
*/
|
|
97
|
+
export declare const QueueObservationSchema: z.ZodObject<{
|
|
98
|
+
kind: z.ZodString;
|
|
99
|
+
queue: z.ZodString;
|
|
100
|
+
deliveryIds: z.ZodArray<z.ZodString>;
|
|
101
|
+
jobs: z.ZodArray<z.ZodObject<{
|
|
102
|
+
jobId: z.ZodString;
|
|
103
|
+
deliveryId: z.ZodNullable<z.ZodString>;
|
|
104
|
+
idempotencyKey: z.ZodNullable<z.ZodString>;
|
|
105
|
+
state: z.ZodEnum<{
|
|
106
|
+
active: "active";
|
|
107
|
+
failed: "failed";
|
|
108
|
+
waiting: "waiting";
|
|
109
|
+
delayed: "delayed";
|
|
110
|
+
prioritized: "prioritized";
|
|
111
|
+
completed: "completed";
|
|
112
|
+
paused: "paused";
|
|
113
|
+
}>;
|
|
114
|
+
attemptsMade: z.ZodNumber;
|
|
115
|
+
maxAttempts: z.ZodNullable<z.ZodNumber>;
|
|
116
|
+
failedReason: z.ZodNullable<z.ZodString>;
|
|
117
|
+
processedAt: z.ZodNullable<z.ZodNumber>;
|
|
118
|
+
}, z.core.$strict>>;
|
|
119
|
+
samples: z.ZodArray<z.ZodObject<{
|
|
120
|
+
jobId: z.ZodString;
|
|
121
|
+
state: z.ZodEnum<{
|
|
122
|
+
active: "active";
|
|
123
|
+
failed: "failed";
|
|
124
|
+
waiting: "waiting";
|
|
125
|
+
delayed: "delayed";
|
|
126
|
+
prioritized: "prioritized";
|
|
127
|
+
completed: "completed";
|
|
128
|
+
paused: "paused";
|
|
129
|
+
}>;
|
|
130
|
+
attemptsMade: z.ZodNumber;
|
|
131
|
+
failedReason: z.ZodNullable<z.ZodString>;
|
|
132
|
+
atMs: z.ZodNumber;
|
|
133
|
+
}, z.core.$strict>>;
|
|
134
|
+
complete: z.ZodBoolean;
|
|
135
|
+
waitedMs: z.ZodNumber;
|
|
136
|
+
}, z.core.$strict>;
|
|
137
|
+
/** Inferred queue-observation shape. */
|
|
138
|
+
export type QueueObservation = z.infer<typeof QueueObservationSchema>;
|
|
139
|
+
/** One approved queue binding: task resource id → queue name. */
|
|
140
|
+
export declare const QueueBindingSchema: z.ZodObject<{
|
|
141
|
+
name: z.ZodString;
|
|
142
|
+
taskResourceId: z.ZodString;
|
|
143
|
+
}, z.core.$strict>;
|
|
144
|
+
/** Inferred queue-binding shape. */
|
|
145
|
+
export type QueueBinding = z.infer<typeof QueueBindingSchema>;
|
|
146
|
+
/** Redis connection material: host/port, or an env var holding the URL. */
|
|
147
|
+
export declare const QueueConnectionSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
148
|
+
host: z.ZodString;
|
|
149
|
+
port: z.ZodNumber;
|
|
150
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
151
|
+
urlEnv: z.ZodString;
|
|
152
|
+
}, z.core.$strict>]>;
|
|
153
|
+
/** Inferred queue-connection shape. */
|
|
154
|
+
export type QueueConnection = z.infer<typeof QueueConnectionSchema>;
|
|
155
|
+
/** The `.gateforge.yml` `queueObserver` block (also the witness env JSON). */
|
|
156
|
+
export declare const QueueObserverConfigSchema: z.ZodObject<{
|
|
157
|
+
kind: z.ZodString;
|
|
158
|
+
connection: z.ZodUnion<readonly [z.ZodObject<{
|
|
159
|
+
host: z.ZodString;
|
|
160
|
+
port: z.ZodNumber;
|
|
161
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
162
|
+
urlEnv: z.ZodString;
|
|
163
|
+
}, z.core.$strict>]>;
|
|
164
|
+
queues: z.ZodArray<z.ZodObject<{
|
|
165
|
+
name: z.ZodString;
|
|
166
|
+
taskResourceId: z.ZodString;
|
|
167
|
+
}, z.core.$strict>>;
|
|
168
|
+
pollIntervalMs: z.ZodOptional<z.ZodNumber>;
|
|
169
|
+
terminalTimeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
170
|
+
}, z.core.$strict>;
|
|
171
|
+
/** Inferred queue-observer configuration. */
|
|
172
|
+
export type QueueObserverConfig = z.infer<typeof QueueObserverConfigSchema>;
|
|
173
|
+
/** Environment variable naming the queue observer (built-in or module). */
|
|
174
|
+
export declare const QUEUE_OBSERVER_ENV = "GATEFORGE_QUEUE_OBSERVER";
|
|
175
|
+
/** Environment variable carrying the JSON queue-observer configuration. */
|
|
176
|
+
export declare const QUEUE_OBSERVER_CONFIG_ENV = "GATEFORGE_QUEUE_OBSERVER_CONFIG";
|
|
177
|
+
/** Default observer poll interval (transition sampling). */
|
|
178
|
+
export declare const DEFAULT_QUEUE_POLL_INTERVAL_MS = 200;
|
|
179
|
+
/** Default bound on waiting for every job of a delivery to settle. */
|
|
180
|
+
export declare const DEFAULT_QUEUE_TERMINAL_TIMEOUT_MS = 30000;
|
|
181
|
+
/**
|
|
182
|
+
* Parses a queue-observer configuration, failing closed with a message
|
|
183
|
+
* naming every illegal field.
|
|
184
|
+
*
|
|
185
|
+
* Args:
|
|
186
|
+
* raw: the JSON text (witness env form).
|
|
187
|
+
*
|
|
188
|
+
* Returns:
|
|
189
|
+
* QueueObserverConfig: the validated configuration.
|
|
190
|
+
*
|
|
191
|
+
* Throws:
|
|
192
|
+
* Error: malformed JSON or an illegal field (fail closed).
|
|
193
|
+
*/
|
|
194
|
+
export declare function parseQueueObserverConfigJson(raw: string): QueueObserverConfig;
|
|
195
|
+
//# sourceMappingURL=queue-observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-observer.d.ts","sourceRoot":"","sources":["../../src/schemas/queue-observer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AAEH,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,2FAQnB,CAAC;AAEX,qCAAqC;AACrC,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,aAAa,CAAoC,CAAC;AAEtG,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,+CAA+C;AAC/C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,mEAAmE;AACnE,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,6DAA6D;AAC7D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;kBAmB3B,CAAC;AAEZ,sCAAsC;AACtC,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;kBAatB,CAAC;AAEZ,iCAAiC;AACjC,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiBxB,CAAC;AAEZ,wCAAwC;AACxC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,iEAAiE;AACjE,eAAO,MAAM,kBAAkB;;;kBAOpB,CAAC;AAEZ,oCAAoC;AACpC,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB;;;;;oBAKhC,CAAC;AAEH,uCAAuC;AACvC,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;kBAgB3B,CAAC;AAEZ,6CAA6C;AAC7C,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAE7D,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,oCAAoC,CAAC;AAE3E,4DAA4D;AAC5D,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD,sEAAsE;AACtE,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAe7E"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queue-observer schemas: the OWNER
|
|
3
|
+
* declaration that binds a task resource to the queue the engine
|
|
4
|
+
* reads, plus the SEALED observation vocabulary the engine's own
|
|
5
|
+
* bounded reads are graded against. One schema, parsed by the CLI at
|
|
6
|
+
* config time AND by the witness when it opens the channel from its
|
|
7
|
+
* own environment, so a typo is a config error (never a silent
|
|
8
|
+
* default) and the two sides can never disagree about what was
|
|
9
|
+
* declared.
|
|
10
|
+
*
|
|
11
|
+
* Connection material never carries a secret inline: the URL form names
|
|
12
|
+
* an environment variable the witness process resolves privately, and
|
|
13
|
+
* the value is never sealed into a record, a report, or argv.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
/**
|
|
17
|
+
* The SEALED observation vocabulary. The witness reads the queue and
|
|
18
|
+
* seals what it read; the grader re-derives every task verdict from
|
|
19
|
+
* these fields alone. A suite-submitted "the job succeeded" cannot
|
|
20
|
+
* produce this shape — only the engine's own bounded reads can.
|
|
21
|
+
*
|
|
22
|
+
* Normalized states are library-independent on purpose: every
|
|
23
|
+
* implementation maps its backend's own vocabulary onto these seven,
|
|
24
|
+
* and an unrecognized backend state is a hard failure (fail closed),
|
|
25
|
+
* never a silent mapping.
|
|
26
|
+
*/
|
|
27
|
+
/** Normalized job states an observer may report. */
|
|
28
|
+
export const QUEUE_JOB_STATES = [
|
|
29
|
+
'waiting',
|
|
30
|
+
'delayed',
|
|
31
|
+
'prioritized',
|
|
32
|
+
'active',
|
|
33
|
+
'completed',
|
|
34
|
+
'failed',
|
|
35
|
+
'paused',
|
|
36
|
+
];
|
|
37
|
+
/** States a delivery may never leave while the engine waits. */
|
|
38
|
+
export const TERMINAL_QUEUE_JOB_STATES = new Set(['completed', 'failed']);
|
|
39
|
+
/** Hard bound on one observed field value (over it, fail closed). */
|
|
40
|
+
export const MAX_QUEUE_FIELD_CHARS = 512;
|
|
41
|
+
/** Default bound for one bounded list read. */
|
|
42
|
+
export const DEFAULT_QUEUE_LIST_LIMIT = 200;
|
|
43
|
+
/** Hard bound for one bounded list read (over it, fail closed). */
|
|
44
|
+
export const MAX_QUEUE_LIST_LIMIT = 1000;
|
|
45
|
+
/**
|
|
46
|
+
* Hard bound on the sealed observations of one delivery. One sample per
|
|
47
|
+
* polling tick, so a default 200 ms sampling interval and a 30 s settle
|
|
48
|
+
* bound sit well inside it; a longer wait fails closed rather than
|
|
49
|
+
* truncating the timeline a stall claim reads.
|
|
50
|
+
*/
|
|
51
|
+
export const MAX_QUEUE_SAMPLES = 2048;
|
|
52
|
+
/** One engine-read job observation (bounded fields only). */
|
|
53
|
+
export const QueueJobObservationSchema = z
|
|
54
|
+
.object({
|
|
55
|
+
/** Queue-native job id. */
|
|
56
|
+
jobId: z.string().min(1),
|
|
57
|
+
/** Delivery identity the engine stamped, or null when the job carries none. */
|
|
58
|
+
deliveryId: z.string().min(1).nullable(),
|
|
59
|
+
/** Idempotency key the engine stamped, or null when the job carries none. */
|
|
60
|
+
idempotencyKey: z.string().min(1).nullable(),
|
|
61
|
+
/** Normalized state. */
|
|
62
|
+
state: z.enum(QUEUE_JOB_STATES),
|
|
63
|
+
/** Attempts the queue has made for this job. */
|
|
64
|
+
attemptsMade: z.number().int().min(0),
|
|
65
|
+
/** Declared attempt bound, or null when the queue declares none. */
|
|
66
|
+
maxAttempts: z.number().int().min(1).nullable(),
|
|
67
|
+
/** Bounded failure reason (never a raw stack). */
|
|
68
|
+
failedReason: z.string().min(1).nullable(),
|
|
69
|
+
/** Engine-observed processing timestamp (ms) or null. */
|
|
70
|
+
processedAt: z.number().int().min(0).nullable(),
|
|
71
|
+
})
|
|
72
|
+
.strict();
|
|
73
|
+
/**
|
|
74
|
+
* One sampled observation of a job with the engine's own elapsed time.
|
|
75
|
+
* Samples are NOT deduplicated: a queue that hands the same job out a
|
|
76
|
+
* second time (a lost-worker reclaim) is exactly the transition a
|
|
77
|
+
* "changed only" filter would hide. The record stays bounded by
|
|
78
|
+
* {@link MAX_QUEUE_SAMPLES}, over which the engine fails closed.
|
|
79
|
+
*/
|
|
80
|
+
export const QueueJobSampleSchema = z
|
|
81
|
+
.object({
|
|
82
|
+
/** Queue-native job id. */
|
|
83
|
+
jobId: z.string().min(1),
|
|
84
|
+
/** Normalized state at sampling time. */
|
|
85
|
+
state: z.enum(QUEUE_JOB_STATES),
|
|
86
|
+
/** Attempts made at sampling time. */
|
|
87
|
+
attemptsMade: z.number().int().min(0),
|
|
88
|
+
/** Bounded failure reason at sampling time (null when unset). */
|
|
89
|
+
failedReason: z.string().min(1).nullable(),
|
|
90
|
+
/** Engine-side elapsed milliseconds since the delivery was produced. */
|
|
91
|
+
atMs: z.number().int().min(0),
|
|
92
|
+
})
|
|
93
|
+
.strict();
|
|
94
|
+
/**
|
|
95
|
+
* The engine's sealed read of one delivery's jobs. `complete:false`
|
|
96
|
+
* means the engine stopped waiting before every job settled: that can
|
|
97
|
+
* never satisfy a task rule, and it is sealed as a diagnostic rather
|
|
98
|
+
* than a partial proof.
|
|
99
|
+
*/
|
|
100
|
+
export const QueueObservationSchema = z
|
|
101
|
+
.object({
|
|
102
|
+
/** Observer implementation kind (`bullmq` or a declared module). */
|
|
103
|
+
kind: z.string().min(1),
|
|
104
|
+
/** The queue the engine read. */
|
|
105
|
+
queue: z.string().min(1),
|
|
106
|
+
/** Engine-stamped delivery identities, in production order. */
|
|
107
|
+
deliveryIds: z.array(z.string().min(1)).min(1),
|
|
108
|
+
/** Final engine read of every produced job. */
|
|
109
|
+
jobs: z.array(QueueJobObservationSchema).min(1),
|
|
110
|
+
/** Every distinct transition the engine sampled, in order. */
|
|
111
|
+
samples: z.array(QueueJobSampleSchema),
|
|
112
|
+
/** True when every job reached a terminal state before the bound. */
|
|
113
|
+
complete: z.boolean(),
|
|
114
|
+
/** Engine-side elapsed milliseconds spent waiting for settlement. */
|
|
115
|
+
waitedMs: z.number().int().min(0),
|
|
116
|
+
})
|
|
117
|
+
.strict();
|
|
118
|
+
/** One approved queue binding: task resource id → queue name. */
|
|
119
|
+
export const QueueBindingSchema = z
|
|
120
|
+
.object({
|
|
121
|
+
/** Queue name as the backend knows it. */
|
|
122
|
+
name: z.string().min(1),
|
|
123
|
+
/** Task resource id the owner maps this queue to. */
|
|
124
|
+
taskResourceId: z.string().min(1),
|
|
125
|
+
})
|
|
126
|
+
.strict();
|
|
127
|
+
/** Redis connection material: host/port, or an env var holding the URL. */
|
|
128
|
+
export const QueueConnectionSchema = z.union([
|
|
129
|
+
z
|
|
130
|
+
.object({ host: z.string().min(1), port: z.number().int().min(1).max(65_535) })
|
|
131
|
+
.strict(),
|
|
132
|
+
z.object({ urlEnv: z.string().min(1) }).strict(),
|
|
133
|
+
]);
|
|
134
|
+
/** The `.gateforge.yml` `queueObserver` block (also the witness env JSON). */
|
|
135
|
+
export const QueueObserverConfigSchema = z
|
|
136
|
+
.object({
|
|
137
|
+
/**
|
|
138
|
+
* `bullmq` (the built-in implementation) or a module path whose
|
|
139
|
+
* default export is a `(spec) => QueueChannel` factory.
|
|
140
|
+
*/
|
|
141
|
+
kind: z.string().min(1),
|
|
142
|
+
/** Connection material (no inline secret). */
|
|
143
|
+
connection: QueueConnectionSchema,
|
|
144
|
+
/** Approved queue bindings; an unknown task resource id fails closed. */
|
|
145
|
+
queues: z.array(QueueBindingSchema).min(1),
|
|
146
|
+
/** Transition-sampling interval in ms (default 200). */
|
|
147
|
+
pollIntervalMs: z.number().int().min(10).max(10_000).optional(),
|
|
148
|
+
/** Bound on waiting for every job of a delivery to settle. */
|
|
149
|
+
terminalTimeoutMs: z.number().int().min(1_000).max(600_000).optional(),
|
|
150
|
+
})
|
|
151
|
+
.strict();
|
|
152
|
+
/** Environment variable naming the queue observer (built-in or module). */
|
|
153
|
+
export const QUEUE_OBSERVER_ENV = 'GATEFORGE_QUEUE_OBSERVER';
|
|
154
|
+
/** Environment variable carrying the JSON queue-observer configuration. */
|
|
155
|
+
export const QUEUE_OBSERVER_CONFIG_ENV = 'GATEFORGE_QUEUE_OBSERVER_CONFIG';
|
|
156
|
+
/** Default observer poll interval (transition sampling). */
|
|
157
|
+
export const DEFAULT_QUEUE_POLL_INTERVAL_MS = 200;
|
|
158
|
+
/** Default bound on waiting for every job of a delivery to settle. */
|
|
159
|
+
export const DEFAULT_QUEUE_TERMINAL_TIMEOUT_MS = 30_000;
|
|
160
|
+
/**
|
|
161
|
+
* Parses a queue-observer configuration, failing closed with a message
|
|
162
|
+
* naming every illegal field.
|
|
163
|
+
*
|
|
164
|
+
* Args:
|
|
165
|
+
* raw: the JSON text (witness env form).
|
|
166
|
+
*
|
|
167
|
+
* Returns:
|
|
168
|
+
* QueueObserverConfig: the validated configuration.
|
|
169
|
+
*
|
|
170
|
+
* Throws:
|
|
171
|
+
* Error: malformed JSON or an illegal field (fail closed).
|
|
172
|
+
*/
|
|
173
|
+
export function parseQueueObserverConfigJson(raw) {
|
|
174
|
+
let parsed;
|
|
175
|
+
try {
|
|
176
|
+
parsed = JSON.parse(raw);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
throw new Error(`${QUEUE_OBSERVER_CONFIG_ENV} is not valid JSON (fail closed)`);
|
|
180
|
+
}
|
|
181
|
+
const result = QueueObserverConfigSchema.safeParse(parsed);
|
|
182
|
+
if (!result.success) {
|
|
183
|
+
const detail = result.error.issues
|
|
184
|
+
.map((issue) => `${issue.path.join('.') || '<root>'}: ${issue.message}`)
|
|
185
|
+
.join('; ');
|
|
186
|
+
throw new Error(`${QUEUE_OBSERVER_CONFIG_ENV} is not a valid queue-observer configuration: ${detail} (fail closed)`);
|
|
187
|
+
}
|
|
188
|
+
return result.data;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=queue-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-observer.js","sourceRoot":"","sources":["../../src/schemas/queue-observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run record schema (plan 2026-09-29, re-seal design rule 1): what a
|
|
3
|
+
* COMPLETE whole-suite supervised run leaves behind when it did NOT
|
|
4
|
+
* seal a gate receipt — the consumer's 563-tests-562-passed case.
|
|
5
|
+
*
|
|
6
|
+
* A gate receipt is a VERDICT: it is issued only for a clean run, and a
|
|
7
|
+
* run with one failing test issues none (it also clears the old one).
|
|
8
|
+
* Without a run record the exact case a test-only re-seal exists for
|
|
9
|
+
* could never re-seal. A run record binds exactly the material a
|
|
10
|
+
* receipt binds — execution result, evidence attestation, candidate
|
|
11
|
+
* tree, input snapshot, approved policy, engine bundle, execution
|
|
12
|
+
* boundary, catalog, per-test outcomes — and carries NO verdict at all.
|
|
13
|
+
*
|
|
14
|
+
* It is a DIFFERENT envelope, not a weaker receipt: its own domain tag
|
|
15
|
+
* (`gateforge.run-record.v1`), its own file (`run-record.json`), its own
|
|
16
|
+
* strict schema, and no field any receipt consumer reads. `check`,
|
|
17
|
+
* pre-commit and the broker therefore never see it: a run record alone
|
|
18
|
+
* leaves `check --require-e2e` exactly as blocked as it was. Only the
|
|
19
|
+
* test-only re-seal path reads it, and only as a PARENT to recompute
|
|
20
|
+
* from, never as proof on its own.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
/**
|
|
24
|
+
* The run record. Unsigned fields first, `mac` last; the signed body is
|
|
25
|
+
* exactly `{domain, ...everything except mac}`.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RunRecordSchema: z.ZodObject<{
|
|
28
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
29
|
+
recordVersion: z.ZodLiteral<1>;
|
|
30
|
+
recordId: z.ZodString;
|
|
31
|
+
verifierKeyId: z.ZodOptional<z.ZodString>;
|
|
32
|
+
runId: z.ZodString;
|
|
33
|
+
invocationId: z.ZodString;
|
|
34
|
+
inputDigest: z.ZodString;
|
|
35
|
+
gitSha: z.ZodNullable<z.ZodString>;
|
|
36
|
+
parentSha: z.ZodNullable<z.ZodString>;
|
|
37
|
+
trustedPolicyDigest: z.ZodString;
|
|
38
|
+
approvedPolicyDigest: z.ZodString;
|
|
39
|
+
invocation: z.ZodString;
|
|
40
|
+
selectionDigest: z.ZodString;
|
|
41
|
+
catalogDigest: z.ZodString;
|
|
42
|
+
executionResultDigest: z.ZodString;
|
|
43
|
+
testOutcomesDigest: z.ZodString;
|
|
44
|
+
plannedTests: z.ZodNumber;
|
|
45
|
+
passedTests: z.ZodNumber;
|
|
46
|
+
evidenceAttestationDigest: z.ZodNullable<z.ZodString>;
|
|
47
|
+
candidateTreeId: z.ZodNullable<z.ZodString>;
|
|
48
|
+
engineBundleDigest: z.ZodString;
|
|
49
|
+
executionBoundaryDigest: z.ZodString;
|
|
50
|
+
issuedAt: z.ZodString;
|
|
51
|
+
mac: z.ZodString;
|
|
52
|
+
}, z.core.$strict>;
|
|
53
|
+
/** Inferred run-record shape. */
|
|
54
|
+
export type RunRecord = z.infer<typeof RunRecordSchema>;
|
|
55
|
+
/** The unsigned run-record body (everything the MAC covers). */
|
|
56
|
+
export type RunRecordBody = Omit<RunRecord, 'mac'>;
|
|
57
|
+
//# sourceMappingURL=run-record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-record.d.ts","sourceRoot":"","sources":["../../src/schemas/run-record.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;kBA6ExB,CAAC;AAEL,iCAAiC;AACjC,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run record schema (plan 2026-09-29, re-seal design rule 1): what a
|
|
3
|
+
* COMPLETE whole-suite supervised run leaves behind when it did NOT
|
|
4
|
+
* seal a gate receipt — the consumer's 563-tests-562-passed case.
|
|
5
|
+
*
|
|
6
|
+
* A gate receipt is a VERDICT: it is issued only for a clean run, and a
|
|
7
|
+
* run with one failing test issues none (it also clears the old one).
|
|
8
|
+
* Without a run record the exact case a test-only re-seal exists for
|
|
9
|
+
* could never re-seal. A run record binds exactly the material a
|
|
10
|
+
* receipt binds — execution result, evidence attestation, candidate
|
|
11
|
+
* tree, input snapshot, approved policy, engine bundle, execution
|
|
12
|
+
* boundary, catalog, per-test outcomes — and carries NO verdict at all.
|
|
13
|
+
*
|
|
14
|
+
* It is a DIFFERENT envelope, not a weaker receipt: its own domain tag
|
|
15
|
+
* (`gateforge.run-record.v1`), its own file (`run-record.json`), its own
|
|
16
|
+
* strict schema, and no field any receipt consumer reads. `check`,
|
|
17
|
+
* pre-commit and the broker therefore never see it: a run record alone
|
|
18
|
+
* leaves `check --require-e2e` exactly as blocked as it was. Only the
|
|
19
|
+
* test-only re-seal path reads it, and only as a PARENT to recompute
|
|
20
|
+
* from, never as proof on its own.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
import { SchemaVersionField } from './common.js';
|
|
24
|
+
/** Hex pattern shared by every digest field. */
|
|
25
|
+
const HEX64 = /^[0-9a-f]{64}$/;
|
|
26
|
+
/**
|
|
27
|
+
* The run record. Unsigned fields first, `mac` last; the signed body is
|
|
28
|
+
* exactly `{domain, ...everything except mac}`.
|
|
29
|
+
*/
|
|
30
|
+
export const RunRecordSchema = z
|
|
31
|
+
.object({
|
|
32
|
+
schemaVersion: SchemaVersionField,
|
|
33
|
+
/** Envelope version; only `1` exists today. */
|
|
34
|
+
recordVersion: z.literal(1),
|
|
35
|
+
/** Record identity (UUID). */
|
|
36
|
+
recordId: z.string().uuid(),
|
|
37
|
+
/** Non-secret verifier-key id used for safe key-ring rotation. */
|
|
38
|
+
verifierKeyId: z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/).optional(),
|
|
39
|
+
/** Run manifest identity of the run that produced the record. */
|
|
40
|
+
runId: z.string().uuid(),
|
|
41
|
+
/** Fresh trusted invocation identity of that run. */
|
|
42
|
+
invocationId: z.string().uuid(),
|
|
43
|
+
/** 64-hex digest of the canonical input snapshot the run tested. */
|
|
44
|
+
inputDigest: z.string().regex(HEX64, 'inputDigest must be 64-char lowercase hex'),
|
|
45
|
+
/** Candidate HEAD sha, or null when unavailable (base identity). */
|
|
46
|
+
gitSha: z
|
|
47
|
+
.string()
|
|
48
|
+
.regex(/^[0-9a-f]{40}$/, 'gitSha must be a 40-char lowercase sha1 hex')
|
|
49
|
+
.nullable(),
|
|
50
|
+
/** Parent commit sha, or null when unavailable (parent identity). */
|
|
51
|
+
parentSha: z
|
|
52
|
+
.string()
|
|
53
|
+
.regex(/^[0-9a-f]{40}$/, 'parentSha must be a 40-char lowercase sha1 hex')
|
|
54
|
+
.nullable(),
|
|
55
|
+
/** 64-hex trusted policy/config revision digest (ADR 0005 D6). */
|
|
56
|
+
trustedPolicyDigest: z.string().regex(HEX64, 'trustedPolicyDigest must be 64-char lowercase hex'),
|
|
57
|
+
/** 64-hex owner-approved policy revision the run was pinned to. */
|
|
58
|
+
approvedPolicyDigest: z.string().regex(HEX64, 'approvedPolicyDigest must be 64-char lowercase hex'),
|
|
59
|
+
/** Normalized invocation that produced the record (e.g. `test-gates --changed`). */
|
|
60
|
+
invocation: z.string().min(1),
|
|
61
|
+
/** 64-hex selection digest (the expected test set, fixed pre-run). */
|
|
62
|
+
selectionDigest: z.string().regex(HEX64, 'selectionDigest must be 64-char lowercase hex'),
|
|
63
|
+
/** 64-hex digest of the catalog the selection was planned from. */
|
|
64
|
+
catalogDigest: z.string().regex(HEX64, 'catalogDigest must be 64-char lowercase hex'),
|
|
65
|
+
/** 64-hex digest of the supervision execution result (ADR 0005 D2). */
|
|
66
|
+
executionResultDigest: z.string().regex(HEX64, 'executionResultDigest must be 64-char lowercase hex'),
|
|
67
|
+
/**
|
|
68
|
+
* 64-hex digest over the run's per-test outcomes. It is recomputed
|
|
69
|
+
* from the execution result the record names, so the record can
|
|
70
|
+
* never claim a cleaner run than the one that happened.
|
|
71
|
+
*/
|
|
72
|
+
testOutcomesDigest: z.string().regex(HEX64, 'testOutcomesDigest must be 64-char lowercase hex'),
|
|
73
|
+
/** How many tests the whole-suite run planned. */
|
|
74
|
+
plannedTests: z.number().int().min(0),
|
|
75
|
+
/** How many of them the run reported as passed. */
|
|
76
|
+
passedTests: z.number().int().min(0),
|
|
77
|
+
/**
|
|
78
|
+
* 64-hex digest of the v2 evidence attestation envelope that run
|
|
79
|
+
* sealed, or null when it carried none. It binds no verdict: the
|
|
80
|
+
* attestation is evidence, and the gate grading is what the record
|
|
81
|
+
* deliberately omits.
|
|
82
|
+
*/
|
|
83
|
+
evidenceAttestationDigest: z.string().regex(HEX64, 'evidenceAttestationDigest must be 64-char lowercase hex').nullable(),
|
|
84
|
+
/** Immutable Git tree actually tested (40-char sha1, or null). */
|
|
85
|
+
candidateTreeId: z
|
|
86
|
+
.string()
|
|
87
|
+
.regex(/^[0-9a-f]{40}$/, 'candidateTreeId must be a 40-char lowercase sha1 hex')
|
|
88
|
+
.nullable(),
|
|
89
|
+
/** 64-hex digest binding the approved engine/policy bundle version. */
|
|
90
|
+
engineBundleDigest: z.string().regex(HEX64, 'engineBundleDigest must be 64-char lowercase hex'),
|
|
91
|
+
/** 64-hex digest binding the controller-issued execution-profile record. */
|
|
92
|
+
executionBoundaryDigest: z.string().regex(HEX64, 'executionBoundaryDigest must be 64-char lowercase hex'),
|
|
93
|
+
/** Issuance instant (ISO-8601). */
|
|
94
|
+
issuedAt: z.string().datetime(),
|
|
95
|
+
/** HMAC-SHA256 over the record body, domain `gateforge.run-record.v1`. */
|
|
96
|
+
mac: z.string().regex(HEX64, 'mac must be a 64-char lowercase hex HMAC'),
|
|
97
|
+
})
|
|
98
|
+
.strict()
|
|
99
|
+
.superRefine((record, ctx) => {
|
|
100
|
+
if (record.passedTests > record.plannedTests) {
|
|
101
|
+
ctx.addIssue({
|
|
102
|
+
code: 'custom',
|
|
103
|
+
path: ['passedTests'],
|
|
104
|
+
message: 'passedTests cannot exceed plannedTests',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=run-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-record.js","sourceRoot":"","sources":["../../src/schemas/run-record.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,27 @@ export declare const SERVICE_URL_PLACEHOLDER = "${service:<id>:url}";
|
|
|
30
30
|
export declare const DEFAULT_PREPARE_TIMEOUT_SECONDS = 600;
|
|
31
31
|
/** Default budget for one service readiness probe, in seconds. */
|
|
32
32
|
export declare const DEFAULT_READY_TIMEOUT_SECONDS = 60;
|
|
33
|
+
/**
|
|
34
|
+
* One managed-run recipe step (managed-run plan (2026-09-29), Part B): the app-owned
|
|
35
|
+
* lifecycle command Gateforge sequences for `gateforge run`. Commands
|
|
36
|
+
* are argv lists (never a shell string), each step carries its own
|
|
37
|
+
* timeout, and a step may be retried a bounded number of times.
|
|
38
|
+
*/
|
|
39
|
+
export declare const RecipeStepSchema: z.ZodObject<{
|
|
40
|
+
commands: z.ZodArray<z.ZodArray<z.ZodString>>;
|
|
41
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
42
|
+
retries: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
}, z.core.$strict>;
|
|
44
|
+
/** Inferred recipe step shape. */
|
|
45
|
+
export type RecipeStep = z.infer<typeof RecipeStepSchema>;
|
|
46
|
+
/** Default wall-clock budget for one managed-run recipe step, in seconds. */
|
|
47
|
+
export declare const DEFAULT_RECIPE_STEP_TIMEOUT_SECONDS = 600;
|
|
48
|
+
/**
|
|
49
|
+
* Environment file a recipe may load, as a PATH only. An entry carrying
|
|
50
|
+
* a value (`NAME=value`) is rejected: the recipe never holds secret
|
|
51
|
+
* material, and `gateforge run` never prints the values it loads.
|
|
52
|
+
*/
|
|
53
|
+
export declare const RecipeEnvFileSchema: z.ZodString;
|
|
33
54
|
/**
|
|
34
55
|
* One service readiness probe: a log line matching `log` (regex source
|
|
35
56
|
* over the captured stdout+stderr) OR an `http` GET returning 2xx.
|
|
@@ -79,9 +100,55 @@ export declare const RuntimeConfigSchema: z.ZodObject<{
|
|
|
79
100
|
schemaVersion: z.ZodLiteral<1>;
|
|
80
101
|
prepare: z.ZodOptional<z.ZodObject<{
|
|
81
102
|
command: z.ZodOptional<z.ZodString>;
|
|
103
|
+
commands: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString>>>;
|
|
104
|
+
runTimeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
runRetries: z.ZodOptional<z.ZodNumber>;
|
|
82
106
|
reuse: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
83
107
|
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
108
|
+
preflight: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
109
|
+
name: z.ZodString;
|
|
110
|
+
command: z.ZodString;
|
|
111
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
112
|
+
}, z.core.$strict>>>;
|
|
113
|
+
}, z.core.$strict>>;
|
|
114
|
+
health: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
115
|
+
name: z.ZodString;
|
|
116
|
+
tcp: z.ZodOptional<z.ZodString>;
|
|
117
|
+
http: z.ZodOptional<z.ZodString>;
|
|
118
|
+
command: z.ZodOptional<z.ZodString>;
|
|
119
|
+
logAbsent: z.ZodOptional<z.ZodObject<{
|
|
120
|
+
command: z.ZodString;
|
|
121
|
+
pattern: z.ZodString;
|
|
122
|
+
}, z.core.$strict>>;
|
|
123
|
+
tls: z.ZodOptional<z.ZodBoolean>;
|
|
124
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
125
|
+
}, z.core.$strict>>>;
|
|
126
|
+
services_up: z.ZodOptional<z.ZodObject<{
|
|
127
|
+
commands: z.ZodArray<z.ZodArray<z.ZodString>>;
|
|
128
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
129
|
+
retries: z.ZodOptional<z.ZodNumber>;
|
|
130
|
+
}, z.core.$strict>>;
|
|
131
|
+
services_down: z.ZodOptional<z.ZodObject<{
|
|
132
|
+
commands: z.ZodArray<z.ZodArray<z.ZodString>>;
|
|
133
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
134
|
+
retries: z.ZodOptional<z.ZodNumber>;
|
|
135
|
+
}, z.core.$strict>>;
|
|
136
|
+
reset: z.ZodOptional<z.ZodObject<{
|
|
137
|
+
commands: z.ZodArray<z.ZodArray<z.ZodString>>;
|
|
138
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
139
|
+
retries: z.ZodOptional<z.ZodNumber>;
|
|
140
|
+
}, z.core.$strict>>;
|
|
141
|
+
seed: z.ZodOptional<z.ZodObject<{
|
|
142
|
+
commands: z.ZodArray<z.ZodArray<z.ZodString>>;
|
|
143
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
144
|
+
retries: z.ZodOptional<z.ZodNumber>;
|
|
145
|
+
}, z.core.$strict>>;
|
|
146
|
+
healthcheck: z.ZodOptional<z.ZodObject<{
|
|
147
|
+
commands: z.ZodArray<z.ZodArray<z.ZodString>>;
|
|
148
|
+
timeoutSeconds: z.ZodOptional<z.ZodNumber>;
|
|
149
|
+
retries: z.ZodOptional<z.ZodNumber>;
|
|
84
150
|
}, z.core.$strict>>;
|
|
151
|
+
env_files: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
85
152
|
services: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
86
153
|
id: z.ZodString;
|
|
87
154
|
command: z.ZodString;
|