@miller-tech/uap 1.141.0 → 1.143.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/bin/cli.js +2 -0
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/browser/web-browser.d.ts +4 -0
  5. package/dist/browser/web-browser.d.ts.map +1 -1
  6. package/dist/browser/web-browser.js +20 -0
  7. package/dist/browser/web-browser.js.map +1 -1
  8. package/dist/cli/deliver.d.ts.map +1 -1
  9. package/dist/cli/deliver.js +45 -1
  10. package/dist/cli/deliver.js.map +1 -1
  11. package/dist/cli/guided-setup.d.ts.map +1 -1
  12. package/dist/cli/guided-setup.js +49 -0
  13. package/dist/cli/guided-setup.js.map +1 -1
  14. package/dist/cli/policy-select.d.ts +46 -0
  15. package/dist/cli/policy-select.d.ts.map +1 -0
  16. package/dist/cli/policy-select.js +135 -0
  17. package/dist/cli/policy-select.js.map +1 -0
  18. package/dist/cli/policy.d.ts +15 -0
  19. package/dist/cli/policy.d.ts.map +1 -1
  20. package/dist/cli/policy.js +77 -2
  21. package/dist/cli/policy.js.map +1 -1
  22. package/dist/cli/verify.d.ts +3 -0
  23. package/dist/cli/verify.d.ts.map +1 -1
  24. package/dist/cli/verify.js +7 -0
  25. package/dist/cli/verify.js.map +1 -1
  26. package/dist/cli/wizard-config.d.ts +4 -0
  27. package/dist/cli/wizard-config.d.ts.map +1 -1
  28. package/dist/cli/wizard-config.js +1 -1
  29. package/dist/cli/wizard-config.js.map +1 -1
  30. package/dist/config/settings-registry.d.ts.map +1 -1
  31. package/dist/config/settings-registry.js +10 -0
  32. package/dist/config/settings-registry.js.map +1 -1
  33. package/dist/delivery/acceptance-judge.d.ts.map +1 -1
  34. package/dist/delivery/acceptance-judge.js +16 -0
  35. package/dist/delivery/acceptance-judge.js.map +1 -1
  36. package/dist/delivery/user-paths.d.ts +85 -0
  37. package/dist/delivery/user-paths.d.ts.map +1 -0
  38. package/dist/delivery/user-paths.js +179 -0
  39. package/dist/delivery/user-paths.js.map +1 -0
  40. package/dist/delivery/user-validation.d.ts +89 -0
  41. package/dist/delivery/user-validation.d.ts.map +1 -0
  42. package/dist/delivery/user-validation.js +516 -0
  43. package/dist/delivery/user-validation.js.map +1 -0
  44. package/dist/delivery/verifier-ladder.d.ts +7 -1
  45. package/dist/delivery/verifier-ladder.d.ts.map +1 -1
  46. package/dist/delivery/verifier-ladder.js +9 -2
  47. package/dist/delivery/verifier-ladder.js.map +1 -1
  48. package/dist/types/config.d.ts +8 -0
  49. package/dist/types/config.d.ts.map +1 -1
  50. package/dist/types/config.js +6 -0
  51. package/dist/types/config.js.map +1 -1
  52. package/package.json +1 -1
  53. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  54. package/src/policies/enforcers/enforcement_self_protect.py +1 -0
  55. package/templates/hooks/pre-tool-use-bash.sh +30 -0
  56. package/templates/hooks/uap-policy-gate.sh +1 -1
  57. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
@@ -0,0 +1,516 @@
1
+ /**
2
+ * user-validation: exercise the delivered artifact through the SAME CLIENT a
3
+ * real user would use, and refuse DELIVERED until the critical paths pass.
4
+ *
5
+ * - browser paths: headless Chromium (cloakbrowser via WebBrowser) — real DOM
6
+ * interaction with console-error capture. `curl 200` does not count.
7
+ * - http paths: real HTTP requests against the actually-started server.
8
+ * - cli paths: the built artifact spawned with real argv.
9
+ *
10
+ * The runner interprets the declarative manifest (user-paths.ts); the model
11
+ * never supplies harness code. Results land in agents/data/validation/latest.json
12
+ * with a sha256 recorded in-process (getTrustedReportHash) so the acceptance
13
+ * judge's runtime note can refuse a report the runner did not itself write —
14
+ * the same anti-fabrication stance as the gate-integrity guard (integrity.ts).
15
+ *
16
+ * Availability follows the deploy-dev precedent: a missing browser marks
17
+ * browser paths skipped (rung non-blocking) rather than failing delivery on an
18
+ * environment gap — but the skip is loud in the report and the judge note.
19
+ */
20
+ import { spawn, spawnSync } from 'node:child_process';
21
+ import { createHash } from 'node:crypto';
22
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
23
+ import { join } from 'node:path';
24
+ import { startStaticServer } from './execution-gate.js';
25
+ import { loadUserPaths, USER_PATHS_FILE, } from './user-paths.js';
26
+ export const VALIDATION_REPORT_FILE = join('agents', 'data', 'validation', 'latest.json');
27
+ export const USER_VALIDATION_RUNG_ID = 'user-validation';
28
+ /* ------------------------------------------------------------------ trust */
29
+ let trustedReportHash = null;
30
+ export function sha256Text(text) {
31
+ return createHash('sha256').update(text, 'utf8').digest('hex');
32
+ }
33
+ /** Hash of the report THIS process last wrote via the runner. A report on
34
+ * disk whose hash differs was not produced by the sanctioned runner this run
35
+ * and must not be trusted for the "ALL PASSED" judge note. */
36
+ export function getTrustedReportHash() {
37
+ return trustedReportHash;
38
+ }
39
+ /** Test seam. */
40
+ export function resetTrustedReportHash() {
41
+ trustedReportHash = null;
42
+ }
43
+ /* ------------------------------------------------------- mode resolution */
44
+ /**
45
+ * delivery.userValidation resolution — ON BY DEFAULT ('block').
46
+ * Precedence: explicit config value > env downgrade > default.
47
+ * UAP_USER_VALIDATION=0 downgrades block→advisory (never to off): the
48
+ * operator out-of-band switch is the config file, and the env var is on the
49
+ * self-protect blocklist so the model cannot persist it.
50
+ */
51
+ export function resolveUserValidationMode(configValue, env = process.env) {
52
+ const cfg = typeof configValue === 'string' ? configValue.toLowerCase() : configValue;
53
+ let mode = cfg === 'off' || cfg === false ? 'off'
54
+ : cfg === 'advisory' ? 'advisory'
55
+ : 'block';
56
+ if (mode === 'block' && env.UAP_USER_VALIDATION === '0')
57
+ mode = 'advisory';
58
+ return mode;
59
+ }
60
+ async function loadBrowser() {
61
+ try {
62
+ const { WebBrowser } = await import('../browser/web-browser.js');
63
+ const b = new WebBrowser();
64
+ await b.launch({ headless: true });
65
+ return b;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ function stepLabel(step) {
72
+ const [k] = Object.keys(step);
73
+ const v = step[k];
74
+ return `${k}:${typeof v === 'object' ? JSON.stringify(v) : String(v)}`.slice(0, 160);
75
+ }
76
+ async function runBrowserPath(path, browser, ctx) {
77
+ const steps = [];
78
+ const screenshots = [];
79
+ browser.clearErrors();
80
+ let failed = false;
81
+ for (const [i, step] of path.steps.entries()) {
82
+ if (failed)
83
+ break;
84
+ const label = stepLabel(step);
85
+ try {
86
+ if (step.goto !== undefined) {
87
+ const target = /^https?:/.test(step.goto) ? step.goto : `${ctx.baseUrl}${step.goto.startsWith('/') ? '' : '/'}${step.goto}`;
88
+ const status = await browser.goto(target);
89
+ const ok = status.startsWith('2') || status.startsWith('3');
90
+ steps.push({ step: label, ok, observed: `HTTP ${status}` });
91
+ failed = !ok;
92
+ }
93
+ else if (step.click !== undefined) {
94
+ await browser.click(step.click);
95
+ steps.push({ step: label, ok: true, observed: 'clicked' });
96
+ }
97
+ else if (step.fill !== undefined) {
98
+ await browser.fill(step.fill.selector, step.fill.value);
99
+ steps.push({ step: label, ok: true, observed: 'filled' });
100
+ }
101
+ else if (step.press !== undefined) {
102
+ await browser.press(step.press);
103
+ steps.push({ step: label, ok: true, observed: 'pressed' });
104
+ }
105
+ else if (step.wait_ms !== undefined) {
106
+ await new Promise((r) => setTimeout(r, Math.min(step.wait_ms ?? 0, 15_000)));
107
+ steps.push({ step: label, ok: true, observed: 'waited' });
108
+ }
109
+ else if (step.expect_visible !== undefined) {
110
+ const vis = await browser.isVisible(step.expect_visible);
111
+ steps.push({ step: label, ok: vis, observed: vis ? 'visible' : 'NOT visible' });
112
+ failed = !vis;
113
+ }
114
+ else if (step.expect_text !== undefined) {
115
+ const text = await browser.getText(step.expect_text.selector);
116
+ let ok = true;
117
+ if (step.expect_text.contains !== undefined)
118
+ ok = text.includes(step.expect_text.contains);
119
+ if (ok && step.expect_text.not_empty)
120
+ ok = text.trim().length > 0;
121
+ steps.push({ step: label, ok, observed: `text="${text.slice(0, 120)}"` });
122
+ failed = !ok;
123
+ }
124
+ else if (step.expect_no_console_errors !== undefined) {
125
+ const errs = browser.getErrors().filter((e) => e.kind === 'pageerror' || e.kind === 'console');
126
+ const ok = errs.length === 0;
127
+ steps.push({ step: label, ok, observed: ok ? 'no errors' : errs.map((e) => e.message).join(' | ').slice(0, 300) });
128
+ failed = !ok;
129
+ }
130
+ else {
131
+ steps.push({ step: label, ok: false, observed: `step not valid for browser client` });
132
+ failed = true;
133
+ }
134
+ }
135
+ catch (e) {
136
+ steps.push({ step: label, ok: false, observed: `error: ${e instanceof Error ? e.message : String(e)}`.slice(0, 300) });
137
+ failed = true;
138
+ }
139
+ // Screenshot after each interaction step (evidence trail), best-effort.
140
+ try {
141
+ const shot = join(ctx.shotsDir, `${path.id}-${i}.png`);
142
+ await browser.screenshot(shot);
143
+ screenshots.push(shot);
144
+ }
145
+ catch { /* headless screenshot unavailable — evidence degrades */ }
146
+ }
147
+ return { id: path.id, rule: path.rule, client: 'browser', status: failed ? 'fail' : 'pass', steps, screenshots };
148
+ }
149
+ async function runHttpPath(path, ctx) {
150
+ const steps = [];
151
+ let failed = false;
152
+ let lastStatus = 0;
153
+ let lastBody = '';
154
+ for (const step of path.steps) {
155
+ if (failed)
156
+ break;
157
+ const label = stepLabel(step);
158
+ try {
159
+ if (step.request !== undefined) {
160
+ const url = `${ctx.baseUrl}${step.request.path.startsWith('/') ? '' : '/'}${step.request.path}`;
161
+ const controller = new AbortController();
162
+ const timer = setTimeout(() => controller.abort(), ctx.timeoutMs);
163
+ try {
164
+ const res = await fetch(url, {
165
+ method: step.request.method,
166
+ headers: { ...(step.request.json !== undefined ? { 'content-type': 'application/json' } : {}), ...step.request.headers },
167
+ body: step.request.json !== undefined ? JSON.stringify(step.request.json) : undefined,
168
+ signal: controller.signal,
169
+ });
170
+ lastStatus = res.status;
171
+ lastBody = await res.text();
172
+ }
173
+ finally {
174
+ clearTimeout(timer);
175
+ }
176
+ steps.push({ step: label, ok: true, observed: `HTTP ${lastStatus} ${lastBody.slice(0, 160)}` });
177
+ }
178
+ else if (step.expect_status !== undefined) {
179
+ const ok = lastStatus === step.expect_status;
180
+ steps.push({ step: label, ok, observed: `HTTP ${lastStatus}` });
181
+ failed = !ok;
182
+ }
183
+ else if (step.expect_json_contains !== undefined) {
184
+ let ok = false;
185
+ let observed = lastBody.slice(0, 160);
186
+ try {
187
+ const body = JSON.parse(lastBody);
188
+ ok = jsonContains(body, step.expect_json_contains);
189
+ }
190
+ catch {
191
+ observed = `non-JSON body: ${observed}`;
192
+ }
193
+ steps.push({ step: label, ok, observed });
194
+ failed = !ok;
195
+ }
196
+ else if (step.expect_body_matches !== undefined) {
197
+ const ok = new RegExp(step.expect_body_matches).test(lastBody);
198
+ steps.push({ step: label, ok, observed: lastBody.slice(0, 160) });
199
+ failed = !ok;
200
+ }
201
+ else {
202
+ steps.push({ step: label, ok: false, observed: 'step not valid for http client' });
203
+ failed = true;
204
+ }
205
+ }
206
+ catch (e) {
207
+ steps.push({ step: label, ok: false, observed: `error: ${e instanceof Error ? e.message : String(e)}`.slice(0, 300) });
208
+ failed = true;
209
+ }
210
+ }
211
+ return { id: path.id, rule: path.rule, client: 'http', status: failed ? 'fail' : 'pass', steps, screenshots: [] };
212
+ }
213
+ /** Deep subset match: every key/value in `expected` appears in `actual`
214
+ * (arrays: some element matches). */
215
+ export function jsonContains(actual, expected) {
216
+ if (expected === null || typeof expected !== 'object')
217
+ return actual === expected;
218
+ if (Array.isArray(expected)) {
219
+ return expected.every((e) => Array.isArray(actual) && actual.some((a) => jsonContains(a, e)));
220
+ }
221
+ if (Array.isArray(actual))
222
+ return actual.some((a) => jsonContains(a, expected));
223
+ if (typeof actual !== 'object' || actual === null)
224
+ return false;
225
+ return Object.entries(expected).every(([k, v]) => jsonContains(actual[k], v));
226
+ }
227
+ function runCliPath(path, ctx) {
228
+ const steps = [];
229
+ let failed = false;
230
+ let lastExit = null;
231
+ let lastStdout = '';
232
+ let lastStderr = '';
233
+ for (const step of path.steps) {
234
+ if (failed)
235
+ break;
236
+ const label = stepLabel(step);
237
+ try {
238
+ if (step.run !== undefined) {
239
+ const [cmd, ...rest] = step.run.argv;
240
+ const r = spawnSync(cmd, rest, {
241
+ cwd: ctx.projectRoot,
242
+ timeout: Math.min(step.run.timeoutMs ?? ctx.timeoutMs, 120_000),
243
+ input: step.run.stdin,
244
+ encoding: 'utf8',
245
+ shell: false,
246
+ });
247
+ lastExit = r.status;
248
+ lastStdout = r.stdout ?? '';
249
+ lastStderr = r.stderr ?? '';
250
+ steps.push({ step: label, ok: true, observed: `exit=${String(lastExit)} stdout=${lastStdout.slice(0, 120)}` });
251
+ }
252
+ else if (step.expect_exit !== undefined) {
253
+ const ok = lastExit === step.expect_exit;
254
+ steps.push({ step: label, ok, observed: `exit=${String(lastExit)}` });
255
+ failed = !ok;
256
+ }
257
+ else if (step.expect_stdout_matches !== undefined) {
258
+ const ok = new RegExp(step.expect_stdout_matches).test(lastStdout);
259
+ steps.push({ step: label, ok, observed: lastStdout.slice(0, 160) });
260
+ failed = !ok;
261
+ }
262
+ else if (step.expect_stderr_matches !== undefined) {
263
+ const ok = new RegExp(step.expect_stderr_matches).test(lastStderr);
264
+ steps.push({ step: label, ok, observed: lastStderr.slice(0, 160) });
265
+ failed = !ok;
266
+ }
267
+ else {
268
+ steps.push({ step: label, ok: false, observed: 'step not valid for cli client' });
269
+ failed = true;
270
+ }
271
+ }
272
+ catch (e) {
273
+ steps.push({ step: label, ok: false, observed: `error: ${e instanceof Error ? e.message : String(e)}`.slice(0, 300) });
274
+ failed = true;
275
+ }
276
+ }
277
+ return { id: path.id, rule: path.rule, client: 'cli', status: failed ? 'fail' : 'pass', steps, screenshots: [] };
278
+ }
279
+ async function startManifestServer(srv, projectRoot) {
280
+ const child = spawn(srv.command, srv.args ?? [], {
281
+ cwd: projectRoot,
282
+ env: { ...process.env, ...srv.env },
283
+ stdio: 'ignore',
284
+ detached: false,
285
+ });
286
+ const baseUrl = `http://127.0.0.1:${srv.port}`;
287
+ const deadline = Date.now() + (srv.readyTimeoutMs ?? 30_000);
288
+ const readyUrl = `${baseUrl}${srv.readyPath ?? '/'}`;
289
+ while (Date.now() < deadline) {
290
+ if (child.exitCode !== null)
291
+ return null; // died during bring-up
292
+ try {
293
+ await fetch(readyUrl, { signal: AbortSignal.timeout(1_000) });
294
+ return { baseUrl, close: () => { try {
295
+ child.kill();
296
+ }
297
+ catch { /* already gone */ } } };
298
+ }
299
+ catch {
300
+ await new Promise((r) => setTimeout(r, 500));
301
+ }
302
+ }
303
+ try {
304
+ child.kill();
305
+ }
306
+ catch { /* already gone */ }
307
+ return null;
308
+ }
309
+ export async function runUserValidation(projectRoot, opts = {}) {
310
+ const startedAt = new Date().toISOString();
311
+ const timeoutMs = opts.timeoutMs ?? 20_000;
312
+ const loaded = loadUserPaths(projectRoot);
313
+ const finish = (report) => {
314
+ const full = { ...report, startedAt, finishedAt: new Date().toISOString() };
315
+ try {
316
+ const file = join(projectRoot, VALIDATION_REPORT_FILE);
317
+ mkdirSync(join(projectRoot, 'agents', 'data', 'validation'), { recursive: true });
318
+ const text = JSON.stringify(full, null, 2) + '\n';
319
+ writeFileSync(file, text, 'utf8');
320
+ trustedReportHash = sha256Text(text);
321
+ }
322
+ catch {
323
+ trustedReportHash = null; // report unwritable — note stays untrusted
324
+ }
325
+ return full;
326
+ };
327
+ if (!loaded) {
328
+ return finish({
329
+ version: 1, manifestHash: null, results: [], verdict: 'na',
330
+ naReason: `no ${USER_PATHS_FILE} manifest`, browserAvailable: false,
331
+ });
332
+ }
333
+ if (!loaded.ok || !loaded.manifest) {
334
+ return finish({
335
+ version: 1, manifestHash: null,
336
+ results: [{
337
+ id: 'manifest', rule: 'manifest must be valid', client: 'cli', status: 'fail',
338
+ steps: loaded.errors.map((e) => ({ step: 'validate', ok: false, observed: e })), screenshots: [],
339
+ }],
340
+ verdict: 'fail', browserAvailable: false,
341
+ });
342
+ }
343
+ const manifest = loaded.manifest;
344
+ const manifestHash = sha256Text(JSON.stringify(manifest));
345
+ if (manifest.paths.length === 0) {
346
+ return finish({
347
+ version: 1, manifestHash, results: [], verdict: 'na',
348
+ naReason: 'manifest has no paths', browserAvailable: false,
349
+ });
350
+ }
351
+ const shotsDir = join(projectRoot, 'agents', 'data', 'validation', 'shots');
352
+ mkdirSync(shotsDir, { recursive: true });
353
+ const needsBrowser = manifest.paths.some((p) => p.client === 'browser');
354
+ const needsServer = manifest.paths.some((p) => p.client === 'http') || manifest.server !== undefined;
355
+ let managed = null;
356
+ let staticServer = null;
357
+ let browser = null;
358
+ const results = [];
359
+ try {
360
+ if (needsServer && manifest.server) {
361
+ managed = await startManifestServer(manifest.server, projectRoot);
362
+ }
363
+ if (needsBrowser) {
364
+ browser = await (opts.browserLoader ?? loadBrowser)();
365
+ if (!managed && !staticServer) {
366
+ try {
367
+ staticServer = await startStaticServer(projectRoot);
368
+ }
369
+ catch {
370
+ staticServer = null;
371
+ }
372
+ }
373
+ }
374
+ for (const path of manifest.paths) {
375
+ if (path.client === 'browser') {
376
+ if (!browser) {
377
+ results.push({
378
+ id: path.id, rule: path.rule, client: 'browser', status: 'skipped',
379
+ steps: [{ step: 'launch-browser', ok: false, observed: 'headless browser unavailable in this environment' }],
380
+ screenshots: [],
381
+ });
382
+ continue;
383
+ }
384
+ const base = managed?.baseUrl ?? staticServer?.url ?? null;
385
+ results.push(await runBrowserPath(path, browser, { projectRoot, baseUrl: base, shotsDir, timeoutMs }));
386
+ }
387
+ else if (path.client === 'http') {
388
+ if (!managed) {
389
+ results.push({
390
+ id: path.id, rule: path.rule, client: 'http', status: 'fail',
391
+ steps: [{ step: 'server', ok: false, observed: manifest.server ? 'server failed to become ready' : `http paths need a "server" entry in ${USER_PATHS_FILE}` }],
392
+ screenshots: [],
393
+ });
394
+ continue;
395
+ }
396
+ results.push(await runHttpPath(path, { projectRoot, baseUrl: managed.baseUrl, shotsDir, timeoutMs }));
397
+ }
398
+ else {
399
+ results.push(runCliPath(path, { projectRoot, baseUrl: null, shotsDir, timeoutMs }));
400
+ }
401
+ }
402
+ }
403
+ finally {
404
+ try {
405
+ await browser?.close();
406
+ }
407
+ catch { /* already closed */ }
408
+ managed?.close();
409
+ staticServer?.close();
410
+ }
411
+ const anyFail = results.some((r) => r.status === 'fail');
412
+ const allSkipped = results.length > 0 && results.every((r) => r.status === 'skipped');
413
+ return finish({
414
+ version: 1, manifestHash, results,
415
+ verdict: anyFail ? 'fail' : allSkipped ? 'na' : 'pass',
416
+ naReason: allSkipped ? 'all paths skipped (browser unavailable)' : undefined,
417
+ browserAvailable: browser !== null,
418
+ });
419
+ }
420
+ /* --------------------------------------------------------- ladder wiring */
421
+ /** Synthesize the terminal user-validation rung. `required` mirrors the
422
+ * resolved mode: block ⇒ required, advisory ⇒ optional. */
423
+ export function synthesizeUserValidationRung(mode) {
424
+ if (mode === 'off')
425
+ return null;
426
+ return {
427
+ id: USER_VALIDATION_RUNG_ID,
428
+ name: `User-path validation (real client${mode === 'advisory' ? ', advisory' : ''})`,
429
+ command: 'user-validation', // executed in-process by the injected runner
430
+ args: [],
431
+ required: mode === 'block',
432
+ timeoutMs: 300_000,
433
+ tier: 'final',
434
+ };
435
+ }
436
+ /**
437
+ * LadderRunFn for the 'final' tier: runs the validation in-process (never
438
+ * spawning model-writable code) and maps the report onto rung results.
439
+ * Skipped-not-failed when every path was environment-skipped, mirroring the
440
+ * deploy-dev docker-unavailable behavior.
441
+ */
442
+ export function createUserValidationRunner(runOpts = {}) {
443
+ return async (rungs, projectRoot) => {
444
+ const rung = rungs.find((r) => r.id === USER_VALIDATION_RUNG_ID) ?? rungs[0];
445
+ const started = Date.now();
446
+ const report = await runUserValidation(projectRoot, runOpts);
447
+ const failedPaths = report.results.filter((r) => r.status === 'fail');
448
+ const passed = report.verdict === 'pass' || report.verdict === 'na';
449
+ const skipped = report.verdict === 'na';
450
+ const detail = report.results
451
+ .map((r) => `${r.status.toUpperCase()} ${r.id}: ${r.rule}${r.status === 'fail' ? ` — ${r.steps.find((s) => !s.ok)?.step ?? ''} → ${r.steps.find((s) => !s.ok)?.observed ?? ''}` : ''}`)
452
+ .join('\n');
453
+ const result = {
454
+ id: rung.id,
455
+ name: rung.name,
456
+ // NA counts as passed (skipped-not-failed, the deploy-dev precedent):
457
+ // a required rung with no applicable paths must not fail the aggregate.
458
+ passed,
459
+ skipped,
460
+ exitCode: passed ? 0 : 1,
461
+ durationMs: Date.now() - started,
462
+ outputTail: (report.verdict === 'na' ? `NA: ${report.naReason ?? ''}\n` : '') +
463
+ detail +
464
+ (passed
465
+ ? ''
466
+ : `\nThe artifact does not work for a real user on these journeys. Fix the artifact so they pass; the manifest is ${USER_PATHS_FILE}.`),
467
+ };
468
+ return {
469
+ passed: passed || !rung.required,
470
+ score: passed ? 1 : Math.max(0, 1 - failedPaths.length / Math.max(1, report.results.length)),
471
+ results: [result],
472
+ feedback: passed
473
+ ? ''
474
+ : `User-path validation FAILED — the artifact does not work for a real user:\n${detail}\nFix the artifact so these journeys pass; the manifest is ${USER_PATHS_FILE}.`,
475
+ };
476
+ };
477
+ }
478
+ /**
479
+ * Build the acceptance-judge runtime note from the on-disk report, refusing
480
+ * to vouch for a report the in-process runner did not write (hash mismatch ⇒
481
+ * fabricated/stale ⇒ say so to the judge instead of staying silent).
482
+ */
483
+ export function buildUserPathsNote(projectRoot) {
484
+ const file = join(projectRoot, VALIDATION_REPORT_FILE);
485
+ if (!existsSync(file))
486
+ return null;
487
+ let text;
488
+ try {
489
+ text = readFileSync(file, 'utf8');
490
+ }
491
+ catch {
492
+ return null;
493
+ }
494
+ const trusted = trustedReportHash !== null && sha256Text(text) === trustedReportHash;
495
+ if (!trusted) {
496
+ return {
497
+ note: 'A user-validation report exists but was NOT produced by the sanctioned runner this run — treat it as unverified.',
498
+ trusted: false,
499
+ };
500
+ }
501
+ try {
502
+ const report = JSON.parse(text);
503
+ if (report.verdict === 'pass') {
504
+ return { note: `User-path validation ALL PASSED (${report.results.length} real-client journeys) — treat user-facing requirements covered by these paths as objectively verified.`, trusted: true };
505
+ }
506
+ if (report.verdict === 'fail') {
507
+ const failed = report.results.filter((r) => r.status === 'fail').map((r) => `${r.id} (${r.rule})`).join('; ');
508
+ return { note: `User-path validation FAILED: ${failed} — the artifact does not work for a real user on these journeys.`, trusted: true };
509
+ }
510
+ return { note: `User-path validation: not applicable (${report.naReason ?? 'no user-facing surface'}).`, trusted: true };
511
+ }
512
+ catch {
513
+ return null;
514
+ }
515
+ }
516
+ //# sourceMappingURL=user-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-validation.js","sourceRoot":"","sources":["../../src/delivery/user-validation.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@
17
17
  * `ci`/`deploy-staging`/`deploy-prod` bands are NEVER run locally — they are
18
18
  * consumed after commit via the CI watcher (see ci-watcher.ts).
19
19
  */
20
- export type GateTier = 'fast' | 'runtime' | 'integration' | 'deploy-dev' | 'ci' | 'deploy-staging' | 'deploy-prod';
20
+ export type GateTier = 'fast' | 'runtime' | 'integration' | 'deploy-dev' | 'final' | 'ci' | 'deploy-staging' | 'deploy-prod';
21
21
  /** Cheap → expensive promotion order. */
22
22
  export declare const TIER_ORDER: GateTier[];
23
23
  export interface GateRung {
@@ -211,6 +211,12 @@ export interface TieredLadderOptions extends LadderOptions {
211
211
  * which simply spawns the smoke command without managing a compose stack.
212
212
  */
213
213
  deployDevRunner?: LadderRunFn;
214
+ /**
215
+ * Specialized runner for the terminal `final` tier (user-path validation
216
+ * against the real client). When absent, `final` rungs fall back to
217
+ * {@link runner}, which would spawn their command verbatim.
218
+ */
219
+ userValidationRunner?: LadderRunFn;
214
220
  }
215
221
  /**
216
222
  * Cheap-first tiered ladder. Runs the cheapest tier first and only promotes to
@@ -1 +1 @@
1
- {"version":3,"file":"verifier-ladder.d.ts","sourceRoot":"","sources":["../../src/delivery/verifier-ladder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verifier-ladder.d.ts","sourceRoot":"","sources":["../../src/delivery/verifier-ladder.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@ export const TIER_ORDER = [
20
20
  'runtime',
21
21
  'integration',
22
22
  'deploy-dev',
23
+ 'final',
23
24
  'ci',
24
25
  'deploy-staging',
25
26
  'deploy-prod',
@@ -657,7 +658,11 @@ export async function runTieredLadder(rungs, projectRoot, options = {}) {
657
658
  const tierRungs = byTier.get(tier);
658
659
  if (!tierRungs || tierRungs.length === 0)
659
660
  continue;
660
- const eligible = TIER_ORDER.indexOf(tier) <= maxIdx;
661
+ // 'final' is an epilogue tier: always in scope when its rung was
662
+ // synthesized (config-gated upstream), regardless of the cost ceiling —
663
+ // it must not drag integration/deploy-dev into scope, and promotion
664
+ // still guarantees it only runs when every cheaper in-scope tier passed.
665
+ const eligible = tier === 'final' || TIER_ORDER.indexOf(tier) <= maxIdx;
661
666
  if (!eligible) {
662
667
  // Above maxTier — verified remotely, never run locally.
663
668
  for (const rung of tierRungs)
@@ -671,7 +676,9 @@ export async function runTieredLadder(rungs, projectRoot, options = {}) {
671
676
  results.push(skippedRung(rung));
672
677
  continue;
673
678
  }
674
- const useRunner = tier === 'deploy-dev' && options.deployDevRunner ? options.deployDevRunner : runner;
679
+ const useRunner = tier === 'deploy-dev' && options.deployDevRunner ? options.deployDevRunner
680
+ : tier === 'final' && options.userValidationRunner ? options.userValidationRunner
681
+ : runner;
675
682
  const tierResult = await useRunner(tierRungs, projectRoot, innerOptions);
676
683
  results.push(...tierResult.results);
677
684
  if (!tierResult.passed)