prae-cli 0.9.2 → 0.10.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.
@@ -0,0 +1,1396 @@
1
+ import { n as cite, t as FRAMEWORKS } from "./frameworks-BgZHGKiH.js";
2
+
3
+ //#region ../tokens/src/fonts.ts
4
+ const FONT_FACES = "@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:300 700;font-display:swap;src:url(data:font/woff2;base64,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) format('woff2')}@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(data:font/woff2;base64,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) format('woff2')}@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(data:font/woff2;base64,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) format('woff2')}";
5
+
6
+ //#endregion
7
+ //#region ../tokens/src/mark.ts
8
+ /**
9
+ * The mark — Guardians — as code.
10
+ *
11
+ * Four corner brackets around a core that none of them touch: the Guardians
12
+ * PRAE assembles around an agent, and the agent, green because what is
13
+ * inside has been verified. The console, the site and the CLI draw it from
14
+ * here, so there is one geometry and no copies to drift. `brand/` holds the
15
+ * same shapes as files, for places that need a file.
16
+ *
17
+ * Grid 32u. Arms 11u long, 5u thick. Core 8u, centred, 5u clear. Radius 0.
18
+ */
19
+ const MARK = {
20
+ viewBox: "0 0 32 32",
21
+ brackets: "M2 2H13V7H7V13H2ZM19 2H30V13H25V7H19ZM2 19H7V25H13V30H2ZM25 19H30V30H19V25H25Z",
22
+ corners: [
23
+ {
24
+ d: "M2 2H13V7H7V13H2Z",
25
+ dx: -14,
26
+ dy: -14
27
+ },
28
+ {
29
+ d: "M19 2H30V13H25V7H19Z",
30
+ dx: 14,
31
+ dy: -14
32
+ },
33
+ {
34
+ d: "M25 19H30V30H19V25H25Z",
35
+ dx: 14,
36
+ dy: 14
37
+ },
38
+ {
39
+ d: "M2 19H7V25H13V30H2Z",
40
+ dx: -14,
41
+ dy: 14
42
+ }
43
+ ],
44
+ core: {
45
+ x: 12,
46
+ y: 12,
47
+ width: 8,
48
+ height: 8
49
+ },
50
+ colour: {
51
+ graphite: "#0E1114",
52
+ ink: "#FFFFFF",
53
+ signal: "#98ED49",
54
+ signalOnLight: "#0C6800"
55
+ }
56
+ };
57
+ /** The inner drawing: brackets and, unless absent, the core. */
58
+ function markShapes({ surface = "graphite", core = "verified", mono = false } = {}) {
59
+ const ink = surface === "graphite" ? MARK.colour.ink : MARK.colour.graphite;
60
+ const green = surface === "graphite" ? MARK.colour.signal : MARK.colour.signalOnLight;
61
+ const coreFill = mono || core === "unverified" ? ink : green;
62
+ const { x, y, width, height } = MARK.core;
63
+ const rect = core === "absent" ? "" : `<rect class="prae-core" x="${x}" y="${y}" width="${width}" height="${height}" fill="${coreFill}"/>`;
64
+ return `${MARK.corners.map((c, i) => `<path class="prae-corner" style="--i:${i};--dx:${c.dx};--dy:${c.dy}" d="${c.d}" fill="${ink}"/>`).join("")}${rect}`;
65
+ }
66
+ /** A complete SVG document of the mark. */
67
+ function markSvg(options = {}) {
68
+ const size = options.size ?? 32;
69
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${MARK.viewBox}" width="${size}" height="${size}">${markShapes(options)}</svg>`;
70
+ }
71
+ /** The mark as a data URI, for an `<img>` that must not fetch anything. */
72
+ function markDataUri(options = {}) {
73
+ return `data:image/svg+xml;utf8,${encodeURIComponent(markSvg(options))}`;
74
+ }
75
+
76
+ //#endregion
77
+ //#region ../tokens/src/palette.ts
78
+ /**
79
+ * The two grounds, as declaration blocks.
80
+ *
81
+ * The console renders twice from one design: `prae console --out` inlines its
82
+ * stylesheet into standalone documents, and the web app links a real one. Both
83
+ * need these values, so they are defined here once and the test in this
84
+ * package asserts the stylesheet agrees — the same guard the rest of the
85
+ * tokens already have, for the same reason.
86
+ *
87
+ * Names are unprefixed because these are consumed as a surface's own palette
88
+ * rather than alongside another product's. `tokens.css` carries the prefixed
89
+ * `--prae-*` set for anyone embedding PRAE inside their own page.
90
+ */
91
+ /** §06 — Surface B, the ledger, on paper. Printable and high-contrast. */
92
+ const PAPER = ` --signal: oklch(0.45 0.16 140);
93
+ --signal-bright: oklch(0.5 0.16 140);
94
+ --signal-edge: oklch(0.5 0.13 140);
95
+ --signal-text: oklch(0.42 0.14 140);
96
+ --signal-on: oklch(0.985 0.003 100);
97
+ --hold: oklch(0.55 0.15 55);
98
+ --veto: oklch(0.52 0.19 25);
99
+ --veto-text: oklch(0.5 0.19 25);
100
+ --veto-edge: oklch(0.62 0.17 25);
101
+
102
+ --ground: oklch(0.975 0.003 100);
103
+ --raised: oklch(0.99 0.002 100);
104
+ --sunk: oklch(0.955 0.004 100);
105
+ --active: oklch(0.955 0.006 130);
106
+ --line: oklch(0.88 0.004 100);
107
+ --line-soft: oklch(0.92 0.004 100);
108
+ --line-faint: oklch(0.93 0.004 100);
109
+ --line-card: oklch(0.86 0.005 100);
110
+ --line-strong: oklch(0.8 0.006 100);
111
+ --edge: oklch(0.32 0.01 255);
112
+ --ink: oklch(0.22 0.01 255);
113
+ --ink-row: oklch(0.24 0.01 255);
114
+ --secondary: oklch(0.4 0.01 255);
115
+ --muted: oklch(0.5 0.01 255);
116
+ --muted-soft: oklch(0.55 0.01 255);
117
+ --dim: oklch(0.45 0.01 255);
118
+ --seal: oklch(0.6 0.01 255);
119
+
120
+ --mark: none;`;
121
+ /** §02 — the graphite ramp and the neon signal it is drawn for. */
122
+ const FENCE = ` --signal: oklch(0.86 0.21 133);
123
+ --signal-bright: oklch(0.95 0.15 133);
124
+ --signal-edge: oklch(0.4 0.06 133);
125
+ --signal-text: oklch(0.86 0.21 133);
126
+ --signal-on: oklch(0.155 0.008 255);
127
+ --hold: oklch(0.83 0.16 78);
128
+ --veto: oklch(0.66 0.2 25);
129
+ --veto-text: oklch(0.75 0.16 25);
130
+ --veto-edge: oklch(0.45 0.12 25);
131
+
132
+ --ground: oklch(0.155 0.008 255);
133
+ --raised: oklch(0.185 0.009 255);
134
+ --sunk: oklch(0.135 0.008 255);
135
+ --active: oklch(0.215 0.022 133);
136
+ --line: oklch(0.28 0.01 255);
137
+ --line-soft: oklch(0.26 0.01 255);
138
+ --line-faint: oklch(0.235 0.01 255);
139
+ --line-card: oklch(0.3 0.01 255);
140
+ --line-strong: oklch(0.32 0.01 255);
141
+ --edge: oklch(0.72 0.01 255);
142
+ --ink: oklch(0.96 0.004 255);
143
+ --ink-row: oklch(0.9 0.006 255);
144
+ --secondary: oklch(0.72 0.01 255);
145
+ --muted: oklch(0.6 0.012 255);
146
+ /* Lands where paper's does, at AA on its own ground: 0.55 measures 4.03
147
+ against graphite, and this token labels pending and absent states that
148
+ still have to be read. */
149
+ --muted-soft: oklch(0.575 0.012 255);
150
+ --dim: oklch(0.62 0.012 255);
151
+ --seal: oklch(0.58 0.012 255);
152
+
153
+ /* The mark is a solid black glyph, so it disappears on the graphite ground.
154
+ Inverting it yields the white it would have been drawn as. */
155
+ --mark: invert(1);`;
156
+
157
+ //#endregion
158
+ //#region ../tokens/src/views.ts
159
+ /**
160
+ * The console's view styles, as one definition.
161
+ *
162
+ * Header, stat band, ledger grid, rule and mapping tables, the awaiting-human
163
+ * panel, and the limits block — everything that makes a PRAE view look like a
164
+ * PRAE view rather than a generic table.
165
+ *
166
+ * Both renderers need these. `prae console --out` inlines them into standalone
167
+ * documents; the web app injects them into a global style tag. Exported as a
168
+ * string rather than a stylesheet so there is exactly one copy: a `.css` file
169
+ * plus a mirrored constant would be two, and two copies of a stylesheet drift
170
+ * the same way two copies of a palette do.
171
+ *
172
+ * What is *not* here is layout — the rail, the scroll containment, the routing.
173
+ * The app has a persistent frame and the exporter produces separate documents,
174
+ * and that is the one thing the two are genuinely allowed to disagree about.
175
+ */
176
+ const VIEWS_CSS = `/* ── header ───────────────────────────────────────────────────────────── */
177
+ .head {
178
+ display: flex; align-items: flex-end; justify-content: space-between;
179
+ gap: 24px; padding: 26px 30px 22px; border-bottom: 1px solid var(--line);
180
+ }
181
+ .head h1 { font-size: 30px; font-weight: 700; letter-spacing: -0.03em; margin: 0; }
182
+ .head .meta {
183
+ font-family: var(--proof); font-size: 11.5px; color: var(--muted); margin-top: 6px;
184
+ }
185
+ .actions { display: flex; align-items: center; gap: 10px; }
186
+ .chain {
187
+ display: flex; align-items: center; gap: 8px; padding: 7px 12px;
188
+ border: 1px solid var(--signal-edge); border-radius: 999px;
189
+ font-family: var(--proof); font-size: 10.5px; letter-spacing: 0.12em;
190
+ color: var(--signal-text); white-space: nowrap;
191
+ }
192
+ .chain i { width: 6px; height: 6px; background: var(--signal-bright); border-radius: 999px; }
193
+ .chain.broken { border-color: var(--veto-edge); color: var(--veto-text); }
194
+ .chain.broken i { background: var(--veto); }
195
+ .btn {
196
+ padding: 9px 16px; border: 1px solid var(--line-strong); font-size: 13.5px;
197
+ border-radius: 2px; background: none; color: inherit; font-family: inherit;
198
+ white-space: nowrap;
199
+ }
200
+
201
+ /* ── stat band ────────────────────────────────────────────────────────── */
202
+ .stats { display: grid; grid-template-columns: repeat(4, 1fr); border-bottom: 1px solid var(--line); }
203
+ .stat { padding: 20px 24px; border-right: 1px solid var(--line-soft); }
204
+ .stat:first-child { padding-left: 30px; }
205
+ .stat:last-child { border-right: none; }
206
+ .stat .v {
207
+ font-size: 28px; font-weight: 700; letter-spacing: -0.03em;
208
+ font-variant-numeric: tabular-nums;
209
+ }
210
+ .stat .v.veto { color: var(--veto); }
211
+ .stat .v.hold { color: var(--hold); }
212
+ .stat .k {
213
+ font-family: var(--proof); font-size: 10px; letter-spacing: 0.14em;
214
+ color: var(--muted); margin-top: 4px;
215
+ }
216
+
217
+ /* ── ledger table ─────────────────────────────────────────────────────── */
218
+ .grid {
219
+ display: grid;
220
+ grid-template-columns: 96px 1fr 150px 130px 104px 120px;
221
+ gap: 16px;
222
+ }
223
+ .thead {
224
+ padding: 12px 30px; font-family: var(--proof); font-size: 10px;
225
+ letter-spacing: 0.14em; color: var(--muted); border-bottom: 1px solid var(--line);
226
+ }
227
+ .row {
228
+ padding: 14px 30px; font-family: var(--proof); font-size: 12px;
229
+ border-bottom: 1px solid var(--line-faint); align-items: center;
230
+ }
231
+ .row .seq { color: var(--muted-soft); font-variant-numeric: tabular-nums; }
232
+ .row .call { color: var(--ink-row); overflow-wrap: anywhere; }
233
+ .row .actor, .row .clause { color: var(--dim); }
234
+ .row .seal { color: var(--seal); }
235
+ .row .verdict { letter-spacing: 0.1em; }
236
+ .v-allow { color: var(--signal-text); }
237
+ .v-deny { color: var(--veto-text); }
238
+ .v-ask { color: var(--hold); }
239
+ .v-correct { color: var(--muted); }
240
+ .empty { padding: 30px; font-family: var(--proof); font-size: 12px; color: var(--muted); }
241
+
242
+ /* ── awaiting-human panel ─────────────────────────────────────────────── */
243
+ .await { padding: 26px 30px 30px; background: var(--sunk); border-top: 1px solid var(--line); }
244
+ .await .k {
245
+ font-family: var(--proof); font-size: 10px; letter-spacing: 0.16em;
246
+ color: var(--muted); margin-bottom: 16px;
247
+ }
248
+ .card {
249
+ display: flex; gap: 24px; align-items: flex-start; background: var(--raised);
250
+ border: 1px solid var(--line-card); padding: 22px 24px;
251
+ }
252
+ .card h2 { font-size: 20px; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 8px; }
253
+ .card .detail { font-family: var(--proof); font-size: 12px; color: var(--muted); line-height: 1.8; }
254
+ .decide { display: flex; flex-direction: column; gap: 8px; width: 200px; flex: none; }
255
+ .approve {
256
+ padding: 11px 18px; background: var(--signal); color: var(--signal-on);
257
+ font-weight: 600; font-size: 13.5px; text-align: center; border-radius: 2px;
258
+ border: none; font-family: inherit;
259
+ }
260
+ .deny {
261
+ padding: 11px 18px; border: 1px solid var(--veto-edge); color: var(--veto-text);
262
+ font-weight: 600; font-size: 13.5px; text-align: center; border-radius: 2px;
263
+ background: none; font-family: inherit;
264
+ }
265
+ /*
266
+ * A control that cannot act must not look like one that can. These render so
267
+ * the reader knows where the decision lives, and read as inert so they never
268
+ * reach for it — the harness settles approvals, and a button that looks live
269
+ * here would be an invitation to a second audit trail.
270
+ *
271
+ * The fill is dropped rather than faded. Fading a filled button works against
272
+ * paper and fails against graphite, where a dimmed green block still reads as
273
+ * a live primary action; an outline reads the same on either ground.
274
+ */
275
+ .approve[disabled], .deny[disabled] {
276
+ background: none; border: 1px solid var(--line-strong);
277
+ color: var(--muted-soft); font-weight: 500; cursor: not-allowed;
278
+ }
279
+ .recorded {
280
+ font-family: var(--proof); font-size: 10px; color: var(--muted-soft);
281
+ text-align: center; letter-spacing: 0.08em;
282
+ }
283
+
284
+ /* ── limits ───────────────────────────────────────────────────────────── */
285
+ .limits { padding: 22px 30px 28px; border-top: 1px solid var(--line); }
286
+ .limits .k {
287
+ font-family: var(--proof); font-size: 10px; letter-spacing: 0.16em;
288
+ color: var(--muted); margin-bottom: 10px;
289
+ }
290
+ .limits ul { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.7; color: var(--secondary); }
291
+ .limits code { font-family: var(--proof); font-size: 12px; }
292
+
293
+ /* ── rule / mapping tables, shared by the packs and compliance views ──── */
294
+ .rules { display: grid; grid-template-columns: 110px 1fr 96px; gap: 16px; }
295
+ .map { display: grid; grid-template-columns: 210px 1fr 96px; gap: 16px; }
296
+ .sect { padding: 22px 30px 8px; }
297
+ .sect h2 {
298
+ font-size: 20px; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 4px;
299
+ }
300
+ .sect p {
301
+ margin: 0 0 4px; font-size: 14px; line-height: 1.6; color: var(--secondary);
302
+ max-width: 76ch;
303
+ }
304
+ .caps { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 30px 22px; }
305
+ .cap {
306
+ font-family: var(--proof); font-size: 12px; padding: 6px 10px;
307
+ border: 1px solid var(--signal-edge); color: var(--signal-text);
308
+ border-radius: 2px;
309
+ }
310
+ .cap.off {
311
+ border-color: var(--line-strong); color: var(--muted-soft);
312
+ text-decoration: line-through;
313
+ }
314
+ .effect { letter-spacing: 0.1em; font-size: 11px; }
315
+ .e-deny { color: var(--veto-text); }
316
+ .e-ask { color: var(--hold); }
317
+ .e-warn { color: var(--muted); }
318
+ .e-correct { color: var(--signal-text); }
319
+ .covered { color: var(--signal-text); }
320
+ .partial { color: var(--hold); }
321
+ .absent { color: var(--muted-soft); }
322
+
323
+ button { cursor: pointer; }
324
+ a:focus-visible, button:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
325
+ `;
326
+
327
+ //#endregion
328
+ //#region ../tokens/src/index.ts
329
+ /**
330
+ * Verdict chip labels. Uppercase, mono, and never rendered without a clause
331
+ * reference within 8px — §04 is explicit that a chip alone is not allowed.
332
+ */
333
+ const VERDICT_LABEL = {
334
+ allow: "ALLOWED",
335
+ ask: "HELD",
336
+ deny: "DENIED",
337
+ correct: "CORRECTED"
338
+ };
339
+
340
+ //#endregion
341
+ //#region src/console/logo.ts
342
+ const LOGO = markDataUri({ size: 26 });
343
+
344
+ //#endregion
345
+ //#region src/console/shell.ts
346
+ function esc(value) {
347
+ return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
348
+ }
349
+ /** The stylesheet both console views share. Tokens first, then the surface. */
350
+ /** The stylesheet both console views share. Tokens first, then the surface. */
351
+ const SHEET = `
352
+ :root {
353
+ ${PAPER}
354
+ --claim: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif;
355
+ --proof: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
356
+ --ease: cubic-bezier(0.2, 0, 0, 1);
357
+ --surface-motion: 180ms;
358
+ }
359
+
360
+ /* An explicit choice, remembered. */
361
+ :root[data-theme='dark'] {
362
+ ${FENCE}
363
+ }
364
+
365
+ /* No choice made: follow the machine, unless the reader has said light. */
366
+ @media (prefers-color-scheme: dark) {
367
+ :root:not([data-theme='light']) {
368
+ ${FENCE}
369
+ }
370
+ }
371
+
372
+ /*
373
+ * The ground moves at the surface budget, and only while it is moving.
374
+ *
375
+ * Arming this permanently would put a 180ms fade on every hover and every
376
+ * verdict that renders, so the class goes on for one toggle and comes off.
377
+ * §01's 0ms rule is about a decision animating in; nothing is deciding here,
378
+ * the page is repainting, and a verdict that snapped while the page behind it
379
+ * faded would read as a glitch.
380
+ */
381
+ html.theming, html.theming * {
382
+ transition:
383
+ background-color var(--surface-motion) var(--ease),
384
+ border-color var(--surface-motion) var(--ease),
385
+ color var(--surface-motion) var(--ease),
386
+ fill var(--surface-motion) var(--ease) !important;
387
+ }
388
+
389
+ * { box-sizing: border-box; }
390
+
391
+ /*
392
+ * An application, not a document: the shell fills the viewport and only the
393
+ * content column scrolls, so the rail and the header stay where a reader left
394
+ * them. Print undoes all of it further down — the same page still has to
395
+ * flatten into evidence.
396
+ */
397
+ html, body { height: 100%; }
398
+ body {
399
+ margin: 0;
400
+ background: var(--ground);
401
+ color: var(--ink);
402
+ font-family: var(--claim);
403
+ -webkit-font-smoothing: antialiased;
404
+ overflow: hidden;
405
+ }
406
+
407
+ .wrap { height: 100%; }
408
+ .scroll { height: 100%; }
409
+
410
+ .console {
411
+ background: var(--ground);
412
+ display: grid;
413
+ grid-template-columns: 232px 1fr;
414
+ height: 100%;
415
+ min-height: 0;
416
+ }
417
+
418
+ /* The one column that moves. */
419
+ .console > main {
420
+ overflow-y: auto;
421
+ overflow-x: auto;
422
+ min-height: 0;
423
+ scroll-behavior: smooth;
424
+ }
425
+
426
+ /* ── rail ─────────────────────────────────────────────────────────────── */
427
+ .rail {
428
+ border-right: 1px solid var(--line); padding: 22px 0;
429
+ overflow-y: auto; min-height: 0;
430
+ display: flex; flex-direction: column;
431
+ }
432
+ .rail .compliance { margin-top: auto; }
433
+
434
+ /*
435
+ * Two positions, named, rather than a switch with a state you have to infer.
436
+ * Hidden until the head script has run: without scripting it would be a
437
+ * control that does nothing.
438
+ */
439
+ .ground { display: none; margin: auto 20px 14px; }
440
+ html.js .ground { display: grid; grid-template-columns: 1fr 1fr; }
441
+ html.js .rail .compliance { margin-top: 0; }
442
+ .ground button {
443
+ font-family: var(--proof); font-size: 10px; letter-spacing: 0.14em;
444
+ padding: 6px 0; background: none; color: var(--muted);
445
+ border: 1px solid var(--line); border-radius: 0;
446
+ transition: color 120ms var(--ease), border-color 120ms var(--ease);
447
+ }
448
+ .ground button:first-child { border-radius: 2px 0 0 2px; border-right: none; }
449
+ .ground button:last-child { border-radius: 0 2px 2px 0; }
450
+ .ground button:hover { color: var(--secondary); }
451
+ :root:not([data-theme='dark']) .ground [data-ground='paper'],
452
+ :root[data-theme='dark'] .ground [data-ground='fence'] {
453
+ color: var(--ink); border-color: var(--line-strong); background: var(--active);
454
+ }
455
+ .brand { display: flex; align-items: center; gap: 10px; padding: 0 20px 22px; }
456
+ /* The canvas sizes the mark at 26px; the glyph is square and needs no frame. */
457
+ .mark { width: 26px; height: 26px; display: block; filter: var(--mark); }
458
+ .brand b {
459
+ font-weight: 700; font-size: 16px; letter-spacing: 0.04em;
460
+ }
461
+ .eyebrow {
462
+ font-family: var(--proof); font-size: 10px; letter-spacing: 0.16em;
463
+ color: var(--muted-soft); padding: 0 20px 10px;
464
+ }
465
+ .nav { display: grid; }
466
+ .nav a, .nav span {
467
+ padding: 10px 20px; font-size: 14.5px; color: var(--secondary);
468
+ text-decoration: none; display: flex; justify-content: space-between;
469
+ align-items: center;
470
+ }
471
+ .nav a { transition: background var(--t-state, 120ms) var(--ease, cubic-bezier(.2,0,0,1)),
472
+ color var(--t-state, 120ms) var(--ease, cubic-bezier(.2,0,0,1)); }
473
+ .nav a:hover { background: var(--sunk); }
474
+
475
+ /*
476
+ * The surface transition, spent where the language says to spend it. Verdicts
477
+ * are deliberately excluded: a decision appears, it never animates in.
478
+ */
479
+ main > * { animation: surface 180ms cubic-bezier(0.2, 0, 0, 1) both; }
480
+ @keyframes surface {
481
+ from { opacity: 0; transform: translateY(4px); }
482
+ to { opacity: 1; transform: none; }
483
+ }
484
+ main.leaving { opacity: 0; transition: opacity 120ms cubic-bezier(0.2, 0, 0, 1); }
485
+ @media (prefers-reduced-motion: reduce) {
486
+ main > *, main.leaving { animation: none; transition: none; }
487
+ .console > main { scroll-behavior: auto; }
488
+ :root { --surface-motion: 0ms; }
489
+ }
490
+ .nav .pending { color: var(--muted-soft); }
491
+ .nav .badge.soon {
492
+ font-size: 9px; letter-spacing: 0.14em; color: var(--muted-soft);
493
+ border: 1px solid var(--line); border-radius: 999px; padding: 1px 6px;
494
+ }
495
+ .nav a.on {
496
+ font-weight: 600; color: var(--ink);
497
+ border-left: 2px solid var(--signal-bright);
498
+ background: var(--active); margin-left: -1px;
499
+ }
500
+ .nav .badge { font-family: var(--proof); font-size: 11px; color: var(--hold); }
501
+ .compliance {
502
+ margin: 22px 20px 0; padding-top: 18px; border-top: 1px solid var(--line-soft);
503
+ font-family: var(--proof); font-size: 10.5px; line-height: 1.9; color: var(--muted);
504
+ }
505
+
506
+ ${VIEWS_CSS}
507
+
508
+ /* Print is a first-class state, not an afterthought. */
509
+ @media print {
510
+ @page { margin: 12mm; }
511
+ /* Evidence prints on paper. The fence has no printed form. */
512
+ :root, :root[data-theme='dark'] {
513
+ ${PAPER}
514
+ }
515
+ html.theming, html.theming * { transition: none !important; }
516
+ html, body { height: auto; overflow: visible; }
517
+ body { padding: 0; background: #fff; }
518
+ .wrap, .scroll { height: auto; }
519
+ .console > main { overflow: visible; height: auto; }
520
+ main > * { animation: none; }
521
+ .console {
522
+ border: none; grid-template-columns: 1fr; min-width: 0;
523
+ height: auto; display: block;
524
+ }
525
+ .rail, .actions, .decide, .ground { display: none; }
526
+ .thead { display: grid; }
527
+ thead { display: table-header-group; }
528
+ .row { break-inside: avoid; }
529
+ /* A chip is colour; a printed page may not be. Keep the word. */
530
+ .chain { border-color: currentColor !important; }
531
+ .stats { break-inside: avoid; }
532
+ }
533
+ `;
534
+ /**
535
+ * Resolve the ground before the first paint.
536
+ *
537
+ * This runs in `<head>`, synchronously, on purpose: read the choice after the
538
+ * body has painted and the reader watches the page flash the wrong palette on
539
+ * every navigation. It also marks the document as scripted, which is what
540
+ * reveals the toggle — a control that cannot work should not be offered.
541
+ */
542
+ const GROUND_SCRIPT = `
543
+ (() => {
544
+ const root = document.documentElement;
545
+ root.classList.add('js');
546
+ let choice = null;
547
+ try { choice = localStorage.getItem('prae-ground'); } catch (e) {}
548
+ if (choice !== 'dark' && choice !== 'light') {
549
+ choice = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
550
+ }
551
+ root.dataset.theme = choice;
552
+ })();
553
+ `;
554
+ /**
555
+ * Client-side navigation, as progressive enhancement.
556
+ *
557
+ * Every view is still a complete document that opens, prints and mails on its
558
+ * own — that requirement has not moved. This only intercepts a click when the
559
+ * page is being served, swaps the main column, and leaves the rail alone, so
560
+ * the frame stays put and the surface transition the language budgets actually
561
+ * has somewhere to happen. With scripting off, the links are ordinary links.
562
+ */
563
+ const NAV_SCRIPT = `
564
+ (() => {
565
+ const main = () => document.querySelector('main');
566
+ const rail = () => document.querySelector('.rail');
567
+ if (!main() || !window.fetch) return;
568
+
569
+ const swap = async (href, push) => {
570
+ const target = main();
571
+ target.classList.add('leaving');
572
+ try {
573
+ const res = await fetch(href, { headers: { accept: 'text/html' } });
574
+ if (!res.ok) throw new Error(String(res.status));
575
+ const doc = new DOMParser().parseFromString(await res.text(), 'text/html');
576
+ const next = doc.querySelector('main');
577
+ const nextRail = doc.querySelector('.rail');
578
+ if (!next) throw new Error('no main');
579
+
580
+ // Collect the view's scripts BEFORE moving it: replaceWith detaches the
581
+ // element from the parsed document, so querying that document afterwards
582
+ // finds nothing and the view arrives inert. A parser-created script never
583
+ // executes on insertion either, which is why each is re-created below.
584
+ const scripts = [...next.querySelectorAll('script')].map((s) => s.textContent);
585
+ for (const s of next.querySelectorAll('script')) s.remove();
586
+
587
+ target.replaceWith(next);
588
+ // Only the rail's active marker changes; the element itself stays, so
589
+ // nothing in it flickers or loses scroll position.
590
+ if (nextRail) rail().innerHTML = nextRail.innerHTML;
591
+ if (doc.title) document.title = doc.title;
592
+ if (push) history.pushState({}, '', href);
593
+ next.scrollTop = 0;
594
+ wire();
595
+ for (const code of scripts) {
596
+ const el = document.createElement('script');
597
+ el.textContent = code;
598
+ document.body.appendChild(el);
599
+ }
600
+ } catch {
601
+ // A failed swap falls back to a real navigation rather than stranding
602
+ // the reader on a half-updated page.
603
+ location.href = href;
604
+ }
605
+ };
606
+
607
+ const wire = () => {
608
+ for (const a of document.querySelectorAll('.nav a[href$=".html"]')) {
609
+ a.addEventListener('click', (e) => {
610
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return;
611
+ e.preventDefault();
612
+ swap(a.getAttribute('href'), true);
613
+ });
614
+ }
615
+ };
616
+
617
+ // Delegated, because a client-side swap replaces the rail's markup and a
618
+ // handler bound to the old buttons would go with it.
619
+ let settle;
620
+ document.addEventListener('click', (e) => {
621
+ const button = e.target.closest('[data-ground]');
622
+ if (!button) return;
623
+ const next = button.dataset.ground === 'fence' ? 'dark' : 'light';
624
+ const root = document.documentElement;
625
+ if (root.dataset.theme === next) return;
626
+
627
+ // Arm the transition, let the current palette paint once, then move. Doing
628
+ // both in one frame gives the browser no 'from' state and it jumps.
629
+ root.classList.add('theming');
630
+ void root.offsetHeight;
631
+ root.dataset.theme = next;
632
+ try { localStorage.setItem('prae-ground', next); } catch (err) {}
633
+ clearTimeout(settle);
634
+ settle = setTimeout(() => root.classList.remove('theming'), 240);
635
+ });
636
+
637
+ addEventListener('popstate', () => swap(location.pathname, false));
638
+ wire();
639
+ })();
640
+ `;
641
+ /** Wrap a view in the console shell: rail, then the view's own header and body. */
642
+ function renderShell(page) {
643
+ return `<!doctype html>
644
+ <html lang="en" data-prae="ledger"><head>
645
+ <meta charset="utf-8">
646
+ <meta name="viewport" content="width=device-width, initial-scale=1">
647
+ <title>${esc(page.title)}</title>
648
+ <script>${GROUND_SCRIPT}<\/script>
649
+ <style>${FONT_FACES}</style>
650
+ <style>${SHEET}</style>
651
+ </head><body>
652
+ <div class="wrap"><div class="scroll">
653
+ <div class="console">
654
+ <nav class="rail">
655
+ <div class="brand"><img class="mark" src="${LOGO}" alt=""><b>PRAE</b></div>
656
+ <div class="eyebrow">CONTROL PLANE</div>
657
+ ${page.nav}
658
+ <div class="ground" role="group" aria-label="Ground">
659
+ <button type="button" data-ground="paper">PAPER</button>
660
+ <button type="button" data-ground="fence">FENCE</button>
661
+ </div>
662
+ <div class="compliance">EU AI ACT art. 12<br>NIST AI 600-1<br>SOC 2 CC7.2</div>
663
+ </nav>
664
+ <main>
665
+ ${page.head}
666
+ ${page.body}
667
+ </main>
668
+ </div>
669
+ </div></div>
670
+ <script>${NAV_SCRIPT}<\/script>
671
+ </body></html>
672
+ `;
673
+ }
674
+ function renderNav(items, active) {
675
+ return `<div class="nav">\n${items.map((item) => {
676
+ const classes = [item.label === active ? "on" : "", item.pending === true ? "pending" : ""].filter(Boolean).join(" ");
677
+ const attr = classes === "" ? "" : ` class="${classes}"`;
678
+ const badge = item.pending === true ? "<span class=\"badge soon\">SOON</span>" : item.badge === void 0 || item.badge === 0 ? "" : `<span class="badge">${item.badge}</span>`;
679
+ const href = item.pending === true ? "" : ` href="${esc(item.href ?? "#")}"`;
680
+ const tag = item.pending === true ? "span" : "a";
681
+ return ` <${tag}${href}${attr}>${esc(item.label)}${badge}</${tag}>`;
682
+ }).join("\n")}\n </div>`;
683
+ }
684
+
685
+ //#endregion
686
+ //#region ../controls/src/index.ts
687
+ const EU_AI_ACT = {
688
+ id: "eu-ai-act-2024",
689
+ name: "EU AI Act — Regulation (EU) 2024/1689"
690
+ };
691
+ const NIST_600_1 = {
692
+ id: "nist-ai-600-1-2024",
693
+ name: "NIST AI 600-1 (2024) — Generative AI profile"
694
+ };
695
+ const SOC_2 = {
696
+ id: "soc2-tsc-2017",
697
+ name: "SOC 2 — Trust Services Criteria (2017)"
698
+ };
699
+ /**
700
+ * What each control asks for, and what this profile actually produces.
701
+ *
702
+ * Framed as evidence toward a control, never as compliance with it. Nothing
703
+ * here certifies anything: an auditor decides whether the evidence satisfies
704
+ * the obligation, and a tool that told them the answer would be selling the
705
+ * one thing it cannot supply.
706
+ */
707
+ const isEvent = (e) => e.tool.startsWith("prae:") || e.tool === "system-prompt";
708
+ const decisionsOf = (data) => data.entries.filter((e) => !isEvent(e));
709
+ const allRules = (data) => (data.pack?.rules ?? []).map((r) => r.id);
710
+ /** Rows under the given rules. */
711
+ const under = (data, rules) => {
712
+ const ids = new Set(rules);
713
+ return {
714
+ rules,
715
+ rows: data.entries.filter((e) => e.rule !== void 0 && ids.has(e.rule))
716
+ };
717
+ };
718
+ /** Refusals and holds, with the rules that produced them. */
719
+ function heldAndRefused(data) {
720
+ const rows = decisionsOf(data).filter((e) => e.verdict === "deny" || e.verdict === "ask");
721
+ return {
722
+ rules: [...new Set(rows.flatMap((e) => e.rule ? [e.rule] : []))],
723
+ rows
724
+ };
725
+ }
726
+ const OBLIGATIONS = [
727
+ {
728
+ id: "EU AI Act art. 12",
729
+ code: "Art. 12",
730
+ name: "Record-keeping",
731
+ standard: EU_AI_ACT,
732
+ trace: (data) => ({
733
+ rules: [],
734
+ rows: data.entries
735
+ }),
736
+ asks: "Automatic recording of events over the lifetime of the system, to a degree that enables tracing.",
737
+ evidence: (data) => ({
738
+ state: data.entries.length > 0 ? "covered" : "partial",
739
+ note: data.entries.length > 0 ? `${data.entries.length} decisions recorded, each with the clause that produced it and a hash linking it to the one before.` : "Recording is configured but nothing has been logged yet."
740
+ })
741
+ },
742
+ {
743
+ id: "NIST AI 600-1 · GV-1.2",
744
+ name: "Trustworthy AI in policy",
745
+ standard: NIST_600_1,
746
+ trace: (data) => ({
747
+ rules: allRules(data),
748
+ rows: []
749
+ }),
750
+ asks: "Characteristics of trustworthy AI are integrated into organisational policies.",
751
+ evidence: (data) => ({
752
+ state: data.pack === void 0 ? "absent" : "covered",
753
+ note: data.pack === void 0 ? "No pack supplied to this view." : `${data.pack.rules.length} rules are declared as data and applied to every tool call, rather than living in a runbook.`
754
+ })
755
+ },
756
+ {
757
+ id: "NIST AI 600-1 · MS-2.6",
758
+ name: "Regular safety evaluation",
759
+ standard: NIST_600_1,
760
+ asks: "AI system is evaluated regularly for safety risks, with results documented.",
761
+ evidence: () => ({
762
+ state: "partial",
763
+ note: "Decisions are documented per call. Periodic evaluation of the policy itself is an operator process this tool does not perform."
764
+ })
765
+ },
766
+ {
767
+ id: "SOC 2 · CC7.2",
768
+ name: "Monitoring for anomalies",
769
+ standard: SOC_2,
770
+ trace: (data) => heldAndRefused(data),
771
+ asks: "The entity monitors system components for anomalies indicative of malicious acts.",
772
+ evidence: (data) => ({
773
+ state: data.entries.some((e) => e.verdict === "deny") ? "covered" : "partial",
774
+ note: `Refusals and held calls are recorded with their clause. ${data.entries.some((e) => e.verdict === "deny") ? "This record contains refusals." : "This record contains none yet, so the monitoring is unproven in practice."}`
775
+ })
776
+ },
777
+ {
778
+ id: "SOC 2 · CC6.1",
779
+ name: "Logical access restriction",
780
+ standard: SOC_2,
781
+ trace: (data) => ({
782
+ rules: allRules(data),
783
+ rows: []
784
+ }),
785
+ asks: "Logical access to protected information assets is restricted to authorised users.",
786
+ evidence: () => ({
787
+ state: "partial",
788
+ note: "Capabilities are restricted per agent. Authorisation of the human is not: approvals record what was decided, never who decided it."
789
+ })
790
+ }
791
+ ];
792
+ const OWASP = "owasp-llm-top-10-2026";
793
+ const AGENTIC = "owasp-agentic-top-10-2026";
794
+ /** Rules in the pack that cite one control of one framework. */
795
+ function citing(pack, framework, control) {
796
+ return (pack?.rules ?? []).filter((rule) => (rule.frameworks?.[framework] ?? []).includes(control));
797
+ }
798
+ /**
799
+ * Why a runtime execution gate is not the control for a risk no rule cites.
800
+ *
801
+ * Said per risk rather than as one generic line, because "out of scope" with
802
+ * no reason reads as an excuse. Each of these is a boundary a reader can
803
+ * check: the risk lives somewhere a tool-call gate does not stand.
804
+ */
805
+ const NOT_THIS_BOUNDARY = {
806
+ LLM04: "Where a model or dependency came from is settled before an agent runs; the gate sees the call, not the provenance.",
807
+ LLM05: "Training and fine-tuning data sit outside the execution boundary this gate stands on.",
808
+ LLM07: "Whether an answer is true is not a property of a tool call.",
809
+ LLM08: "The assembled system prompt is sealed into the ledger as evidence of what the model was told; nothing here stops the model repeating it.",
810
+ LLM09: "Retrieval stores are upstream of the call the gate judges.",
811
+ LLM10: "What downstream code does with model output is that code's boundary, not this one's.",
812
+ ASI04: "Where a tool, skill or plugin came from is settled before the agent runs. A rule on the skill tool (integrity, source) is how a pack refuses to trust one at load time; none in this pack does.",
813
+ ASI06: "Memory and retrieval stores are upstream of the call the gate judges. What the gate can do is seal what the agent was told (PRAE-ASM, PRAE-CTX) so a poisoned context is evidenced, never silent; this record holds no such seal.",
814
+ ASI07: "A message between agents is not a tool call; when it becomes one, it is judged like any other agent's call. The channel itself is outside this boundary.",
815
+ ASI09: "Whether a person was misled is not a property of a tool call. An ask verdict puts a human in the path and seals the outcome; nothing here judges the persuasion."
816
+ };
817
+ /**
818
+ * A risk this gate answers by *not* answering it: nothing here detects an
819
+ * injected instruction or a hijacked goal, and saying otherwise would be the
820
+ * claim a red team disproves first. What the gate does is bound what the
821
+ * subverted agent can execute — the cited controls of another risk doing
822
+ * their job. Said in those words, every time.
823
+ */
824
+ const BOUNDED_BY = {
825
+ LLM01: {
826
+ framework: OWASP,
827
+ control: "LLM03"
828
+ },
829
+ ASI01: {
830
+ framework: AGENTIC,
831
+ control: "ASI02"
832
+ }
833
+ };
834
+ function bounded(data, risk, by) {
835
+ const bounding = citing(data.pack, by.framework, by.control);
836
+ const what = risk === "ASI01" ? "a hijacked goal" : "injected instructions";
837
+ const who = risk === "ASI01" ? "a hijacked agent" : "an injected instruction";
838
+ return {
839
+ state: "partial",
840
+ note: bounding.length === 0 ? `Not mitigated: this gate does not detect ${what}, and no ${by.control} control in this pack bounds what ${who} can execute.` : `Not mitigated: this gate does not detect ${what}. Bounded: ${bounding.length} ${by.control} control${bounding.length === 1 ? "" : "s"} (${bounding.map((r) => r.id).join(", ")}) decide what ${who} can execute.`
841
+ };
842
+ }
843
+ /**
844
+ * Risks whose evidence is in the record rather than in a citing rule.
845
+ *
846
+ * ASI06: a poisoned context cannot be prevented here, but every change to what
847
+ * the agent was told is sealed, so it is evidenced. ASI10: a drifting agent's
848
+ * actions are judged like any other's; what the record shows is whether the
849
+ * gate refused any of them.
850
+ */
851
+ const FROM_THE_RECORD = {
852
+ ASI06: (data) => {
853
+ const seals = data.entries.filter((e) => e.rule === "PRAE-ASM" || e.rule === "PRAE-CTX");
854
+ return seals.length === 0 ? void 0 : {
855
+ state: "partial",
856
+ note: `Evidenced, not prevented: ${seals.length} seal${seals.length === 1 ? "" : "s"} of what the agent was told (PRAE-ASM / PRAE-CTX) in this record; a poisoned context changes the hash and is answerable afterwards.`
857
+ };
858
+ },
859
+ ASI10: (data) => {
860
+ const refused = data.entries.filter((e) => e.verdict === "deny").length;
861
+ const armed = [
862
+ "ASI02",
863
+ "ASI03",
864
+ "ASI08"
865
+ ].flatMap((c) => citing(data.pack, AGENTIC, c));
866
+ if (armed.length === 0) return void 0;
867
+ return {
868
+ state: refused > 0 ? "covered" : "partial",
869
+ note: refused > 0 ? `A drifting agent's actions are judged like any other's: ${armed.length} controls under ASI02/03/08 apply to every call, and ${refused} refusal${refused === 1 ? "" : "s"} in this record show them holding.` : `A drifting agent's actions are judged like any other's: ${armed.length} controls under ASI02/03/08 apply to every call; none has refused one in this record yet. Detecting drift itself is derived from the record, not a rule.`
870
+ };
871
+ }
872
+ };
873
+ function frameworkRow(frameworkId, control) {
874
+ const framework = FRAMEWORKS[frameworkId];
875
+ const risk = framework?.controls[control];
876
+ const name = risk?.name ?? control;
877
+ return {
878
+ id: `${framework?.short ?? frameworkId} · ${control}`,
879
+ asks: `${name}. ${risk?.summary ?? ""}`.trim(),
880
+ trace: (data) => {
881
+ const by = BOUNDED_BY[control];
882
+ if (by !== void 0) return under(data, citing(data.pack, by.framework, by.control).map((r) => r.id));
883
+ const rules = citing(data.pack, frameworkId, control).map((r) => r.id);
884
+ if (rules.length > 0) return under(data, rules);
885
+ if (control === "ASI06") return {
886
+ rules: [],
887
+ rows: data.entries.filter((e) => e.rule === "PRAE-ASM" || e.rule === "PRAE-CTX")
888
+ };
889
+ if (control === "ASI10") return {
890
+ rules: [
891
+ "ASI02",
892
+ "ASI03",
893
+ "ASI08"
894
+ ].flatMap((c) => citing(data.pack, AGENTIC, c)).map((r) => r.id),
895
+ rows: decisionsOf(data).filter((e) => e.verdict === "deny")
896
+ };
897
+ return {
898
+ rules: [],
899
+ rows: []
900
+ };
901
+ },
902
+ evidence: (data) => {
903
+ if (data.pack === void 0) return {
904
+ state: "absent",
905
+ note: "No pack supplied to this view."
906
+ };
907
+ const by = BOUNDED_BY[control];
908
+ if (by !== void 0) return bounded(data, control, by);
909
+ const rules = citing(data.pack, frameworkId, control);
910
+ if (rules.length === 0) {
911
+ const derived = FROM_THE_RECORD[control]?.(data);
912
+ if (derived !== void 0) return derived;
913
+ return {
914
+ state: "absent",
915
+ note: NOT_THIS_BOUNDARY[control] ?? "No rule in this pack cites this risk."
916
+ };
917
+ }
918
+ const ids = new Set(rules.map((rule) => rule.id));
919
+ const decisions = data.entries.filter((entry) => entry.rule !== void 0 && ids.has(entry.rule));
920
+ const listed = rules.map((rule) => rule.id).join(", ");
921
+ return decisions.length > 0 ? {
922
+ state: "covered",
923
+ note: `${rules.length} control${rules.length === 1 ? "" : "s"} mapped (${listed}) · ${decisions.length} sealed decision${decisions.length === 1 ? "" : "s"} under them in this record.`
924
+ } : {
925
+ state: "partial",
926
+ note: `${rules.length} control${rules.length === 1 ? "" : "s"} mapped (${listed}); none has decided a call in this record yet, so the mapping is declared, not exercised.`
927
+ };
928
+ }
929
+ };
930
+ }
931
+ const rowsOf = (frameworkId) => Object.keys(FRAMEWORKS[frameworkId]?.controls ?? {}).map((control) => frameworkRow(frameworkId, control));
932
+ const ISO_42001 = {
933
+ id: "iso-iec-42001-2023",
934
+ name: "ISO/IEC 42001:2023 — AI management system, Annex A"
935
+ };
936
+ const ISO_27001 = {
937
+ id: "iso-iec-27001-2022",
938
+ name: "ISO/IEC 27001:2022 — Annex A"
939
+ };
940
+ /** Rules in the pack whose `when` names a capability matching `test`. */
941
+ function rulesOn(pack, test) {
942
+ return (pack?.rules ?? []).filter((rule) => {
943
+ const cap = rule.when.capability;
944
+ return (cap === void 0 ? [] : typeof cap === "string" ? [cap] : cap).some(test);
945
+ });
946
+ }
947
+ /** The record itself: recorded, chained, and how much of it is signed. */
948
+ function recorded(data) {
949
+ const n = data.entries.length;
950
+ if (n === 0) return {
951
+ state: "partial",
952
+ note: "Recording is configured but nothing has been logged yet."
953
+ };
954
+ const signed = data.entries.filter((e) => e.sig !== void 0).length;
955
+ if (!data.verification.ok) return {
956
+ state: "partial",
957
+ note: `${n} rows recorded, but the chain does not verify: the log is present and its integrity is not.`
958
+ };
959
+ return {
960
+ state: "covered",
961
+ note: `${n} rows recorded, each hash-linked to the one before, chain intact${signed > 0 ? `, ${signed} of ${n} signed` : ", unsigned"} — an edited, removed or reordered row breaks it.`
962
+ };
963
+ }
964
+ /** Refusals and holds, recorded with their clause. */
965
+ function monitored(data) {
966
+ const refused = decisionsOf(data).filter((e) => e.verdict === "deny").length;
967
+ const held = decisionsOf(data).filter((e) => e.verdict === "ask").length;
968
+ return refused + held > 0 ? {
969
+ state: "covered",
970
+ note: `Every call is judged as it happens; this record holds ${refused} refusal${refused === 1 ? "" : "s"} and ${held} hold${held === 1 ? "" : "s"} for a human, each with the clause that produced it.`
971
+ } : {
972
+ state: "partial",
973
+ note: "Every call is judged as it happens, but this record contains no refusal or hold yet, so the monitoring is unproven in practice."
974
+ };
975
+ }
976
+ const ISO_CONTROLS = [
977
+ {
978
+ id: "ISO/IEC 42001 · A.2.2",
979
+ name: "AI policy",
980
+ standard: ISO_42001,
981
+ trace: (data) => ({
982
+ rules: allRules(data),
983
+ rows: []
984
+ }),
985
+ asks: "The organisation has a documented policy for developing or using AI systems.",
986
+ evidence: (data) => data.pack === void 0 ? {
987
+ state: "absent",
988
+ note: "No pack supplied to this view."
989
+ } : {
990
+ state: "partial",
991
+ note: `The executable part of an AI policy: ${data.pack.rules.length} rules declared as data and applied to every tool call. The policy document and its approval are the organisation's.`
992
+ }
993
+ },
994
+ {
995
+ id: "ISO/IEC 42001 · A.6.2.6",
996
+ name: "AI system operation and monitoring",
997
+ standard: ISO_42001,
998
+ trace: heldAndRefused,
999
+ asks: "The AI system is monitored while it operates, and what is found is acted on.",
1000
+ evidence: monitored
1001
+ },
1002
+ {
1003
+ id: "ISO/IEC 42001 · A.6.2.8",
1004
+ name: "Recording of event logs",
1005
+ standard: ISO_42001,
1006
+ trace: (data) => ({
1007
+ rules: [],
1008
+ rows: data.entries
1009
+ }),
1010
+ asks: "Event logs are kept while the AI system is in use.",
1011
+ evidence: recorded
1012
+ },
1013
+ {
1014
+ id: "ISO/IEC 42001 · A.9.4",
1015
+ name: "Intended use of the AI system",
1016
+ standard: ISO_42001,
1017
+ trace: (data) => {
1018
+ const rows = decisionsOf(data).filter((e) => e.verdict === "deny");
1019
+ return {
1020
+ rules: [...new Set(rows.flatMap((e) => e.rule ? [e.rule] : []))],
1021
+ rows
1022
+ };
1023
+ },
1024
+ asks: "The AI system is used only for its intended uses.",
1025
+ evidence: (data) => {
1026
+ if (data.pack === void 0) return {
1027
+ state: "absent",
1028
+ note: "No pack supplied to this view."
1029
+ };
1030
+ const refused = decisionsOf(data).filter((e) => e.verdict === "deny").length;
1031
+ return refused > 0 ? {
1032
+ state: "covered",
1033
+ note: `Intended use is enforced as scope: ${refused} action${refused === 1 ? "" : "s"} outside it refused before execution in this record.`
1034
+ } : {
1035
+ state: "partial",
1036
+ note: "Intended use is enforced as scope by the pack; nothing outside it has been attempted in this record yet."
1037
+ };
1038
+ }
1039
+ },
1040
+ {
1041
+ id: "ISO/IEC 27001 · A.8.3",
1042
+ name: "Information access restriction",
1043
+ standard: ISO_27001,
1044
+ trace: (data) => ({
1045
+ rules: rulesOn(data.pack, (c) => c.startsWith("fs:")).map((r) => r.id),
1046
+ rows: decisionsOf(data).filter((e) => e.verdict === "deny" && e.capability?.startsWith("fs:"))
1047
+ }),
1048
+ asks: "Access to information is restricted according to the access-control policy.",
1049
+ evidence: (data) => {
1050
+ const rules = rulesOn(data.pack, (c) => c.startsWith("fs:"));
1051
+ if (rules.length === 0) return {
1052
+ state: "absent",
1053
+ note: "No rule in this pack restricts file access."
1054
+ };
1055
+ const refused = decisionsOf(data).filter((e) => e.verdict === "deny" && e.capability?.startsWith("fs:")).length;
1056
+ return refused > 0 ? {
1057
+ state: "covered",
1058
+ note: `${rules.length} file-access rules restrict what the agent may read and write; ${refused} access${refused === 1 ? "" : "es"} refused in this record. Restriction is per agent, not per human.`
1059
+ } : {
1060
+ state: "partial",
1061
+ note: `${rules.length} file-access rules restrict what the agent may read and write; none has refused an access in this record yet.`
1062
+ };
1063
+ }
1064
+ },
1065
+ {
1066
+ id: "ISO/IEC 27001 · A.8.12",
1067
+ name: "Data leakage prevention",
1068
+ standard: ISO_27001,
1069
+ trace: (data) => ({
1070
+ rules: [...new Set([...rulesOn(data.pack, (c) => c === "net:fetch").map((r) => r.id), ...(data.pack?.rules ?? []).filter((r) => r.when.secrets !== void 0).map((r) => r.id)])],
1071
+ rows: decisionsOf(data).filter((e) => e.verdict === "deny" && (e.capability === "net:fetch" || e.secrets !== void 0 || e.phase === "output"))
1072
+ }),
1073
+ asks: "Leakage of sensitive information is prevented where it is processed or sent.",
1074
+ evidence: (data) => {
1075
+ const rules = [...rulesOn(data.pack, (c) => c === "net:fetch"), ...(data.pack?.rules ?? []).filter((r) => r.when.secrets !== void 0)];
1076
+ if (rules.length === 0) return {
1077
+ state: "absent",
1078
+ note: "No rule in this pack governs egress or credentials."
1079
+ };
1080
+ const stopped = decisionsOf(data).filter((e) => e.verdict === "deny" && (e.capability === "net:fetch" || e.secrets !== void 0 || e.phase === "output")).length;
1081
+ return stopped > 0 ? {
1082
+ state: "covered",
1083
+ note: `${new Set(rules.map((r) => r.id)).size} egress and credential rules; ${stopped} send${stopped === 1 ? "" : "s"} or credential read${stopped === 1 ? "" : "s"} stopped in this record before the data left.`
1084
+ } : {
1085
+ state: "partial",
1086
+ note: `${new Set(rules.map((r) => r.id)).size} egress and credential rules in force; none has stopped anything in this record yet.`
1087
+ };
1088
+ }
1089
+ },
1090
+ {
1091
+ id: "ISO/IEC 27001 · A.8.15",
1092
+ name: "Logging",
1093
+ standard: ISO_27001,
1094
+ trace: (data) => ({
1095
+ rules: [],
1096
+ rows: data.entries
1097
+ }),
1098
+ asks: "Activities, exceptions and other relevant events are logged, and the logs are protected.",
1099
+ evidence: recorded
1100
+ },
1101
+ {
1102
+ id: "ISO/IEC 27001 · A.8.16",
1103
+ name: "Monitoring activities",
1104
+ standard: ISO_27001,
1105
+ trace: heldAndRefused,
1106
+ asks: "Systems are monitored for anomalous behaviour, and potential incidents are evaluated.",
1107
+ evidence: monitored
1108
+ }
1109
+ ];
1110
+ /**
1111
+ * The obligations first, then the risks framework by framework. Two kinds of
1112
+ * row in one table on purpose: an auditor reads down one list and finds the
1113
+ * audit obligations the ledger evidences and the application risks the pack's
1114
+ * rules address, each stated in its framework's own words.
1115
+ */
1116
+ const CONTROLS = [
1117
+ ...OBLIGATIONS,
1118
+ ...rowsOf(OWASP),
1119
+ ...rowsOf(AGENTIC),
1120
+ ...ISO_CONTROLS
1121
+ ];
1122
+
1123
+ //#endregion
1124
+ //#region src/console/views.ts
1125
+ /** One rail for every view, so the shape of the product stays consistent. */
1126
+ function navFor(data) {
1127
+ return [
1128
+ {
1129
+ label: "Overview",
1130
+ href: "overview.html"
1131
+ },
1132
+ {
1133
+ label: "Policy packs",
1134
+ href: "packs.html"
1135
+ },
1136
+ {
1137
+ label: "Instructions",
1138
+ href: "instructions.html"
1139
+ },
1140
+ {
1141
+ label: "Playground",
1142
+ href: "playground.html"
1143
+ },
1144
+ {
1145
+ label: "Approvals",
1146
+ href: "approvals.html",
1147
+ badge: data.entries.filter((e) => e.verdict === "ask" && e.shadow !== true).length
1148
+ },
1149
+ {
1150
+ label: "Audit ledger",
1151
+ href: "ledger.html"
1152
+ },
1153
+ {
1154
+ label: "Fleet",
1155
+ pending: true
1156
+ },
1157
+ {
1158
+ label: "Compliance map",
1159
+ href: "compliance.html"
1160
+ }
1161
+ ];
1162
+ }
1163
+ function chainPill(ok) {
1164
+ return `<div class="chain${ok ? "" : " broken"}"><i></i>${ok ? "CHAIN INTACT" : "CHAIN BROKEN"}</div>`;
1165
+ }
1166
+ function header(title, meta, ok) {
1167
+ return ` <header class="head">
1168
+ <div><h1>${esc(title)}</h1><div class="meta">${esc(meta)}</div></div>
1169
+ <div class="actions">${chainPill(ok)}
1170
+ <button type="button" class="btn" onclick="window.print()">Export evidence</button>
1171
+ </div>
1172
+ </header>`;
1173
+ }
1174
+ function renderOverview(data) {
1175
+ const counts = {};
1176
+ const shadow = {
1177
+ refused: 0,
1178
+ held: 0
1179
+ };
1180
+ for (const entry of data.entries) if (entry.shadow !== true) counts[entry.verdict] = (counts[entry.verdict] ?? 0) + 1;
1181
+ else if (entry.verdict === "deny") shadow.refused += 1;
1182
+ else if (entry.verdict === "ask") shadow.held += 1;
1183
+ const held = counts.ask ?? 0;
1184
+ const pack = data.pack;
1185
+ const enforcing = pack?.rules.some((r) => r.effect.kind === "deny") ?? false;
1186
+ const body = `${` <section class="stats">
1187
+ <div class="stat"><div class="v">${data.entries.length}</div><div class="k">DECISIONS</div></div>
1188
+ <div class="stat"><div class="v veto">${counts.deny ?? 0}</div><div class="k">VETOED</div></div>
1189
+ <div class="stat"><div class="v hold">${held}</div><div class="k">AWAITING HUMAN</div></div>
1190
+ <div class="stat"><div class="v">${pack === void 0 ? "—" : esc(pack.rules.length)}</div><div class="k">RULES IN FORCE</div></div>
1191
+ </section>`}
1192
+ <section class="sect">
1193
+ <h2>Posture</h2>
1194
+ <p>${pack === void 0 ? "No pack was supplied to this view, so nothing here describes a policy in force." : enforcing ? `<strong>${esc(pack.pack)} ${esc(pack.version)}</strong> is enforcing: some calls are refused outright.` : `<strong>${esc(pack.pack)} ${esc(pack.version)}</strong> is observing: it records what an enforcing pack would refuse, and denies nothing.`}${shadow.refused + shadow.held === 0 ? "" : ` In shadow mode, ${shadow.refused} call${shadow.refused === 1 ? "" : "s"} would have been refused and ${shadow.held} held; each ran, and none is counted as vetoed.`}</p>
1195
+ <p>${data.verification.ok ? "The decision chain verifies: no row has been removed, edited, or reordered since it was written." : "The decision chain does <strong>not</strong> verify. This record is not continuous, and the Audit ledger names where it breaks."}</p>
1196
+ </section>
1197
+ <section class="sect" style="padding-bottom:26px">
1198
+ <h2>What is not covered</h2>
1199
+ <p>This gate decides tool calls. It does not sandbox plugin code — a
1200
+ plugin's <code>apply()</code> runs with full privileges before any tool
1201
+ call exists — and it does not secure the harness itself. Approvals record
1202
+ what was decided, never who decided it.</p>
1203
+ </section>`;
1204
+ return renderShell({
1205
+ title: `Overview — ${pack?.pack ?? "PRAE"}`,
1206
+ nav: renderNav(navFor(data), "Overview"),
1207
+ head: header("Overview", `${data.entries.length} decisions · ${pack === void 0 ? "no pack" : `${pack.pack} ${pack.version}`}`, data.verification.ok),
1208
+ body
1209
+ });
1210
+ }
1211
+ function matcherOf(rule) {
1212
+ const when = rule.when;
1213
+ const parts = [];
1214
+ const list = (v) => v === void 0 ? void 0 : Array.isArray(v) ? v.join(", ") : String(v);
1215
+ const cap = list(when.capability);
1216
+ if (cap !== void 0) parts.push(`capability ${cap}`);
1217
+ const tool = list(when.tool);
1218
+ if (tool !== void 0) parts.push(`tool ${tool}`);
1219
+ const plugin = list(when.plugin);
1220
+ if (plugin !== void 0) parts.push(`plugin ${plugin}`);
1221
+ if (when.path?.outside !== void 0) parts.push(`path outside ${when.path.outside.join(", ")}`);
1222
+ if (when.path?.inside !== void 0) parts.push(`path inside ${when.path.inside.join(", ")}`);
1223
+ if (when.host?.notIn !== void 0) parts.push(`host not in ${when.host.notIn.join(", ")}`);
1224
+ if (when.host?.in !== void 0) parts.push(`host in ${when.host.in.join(", ")}`);
1225
+ if (when.count !== void 0) parts.push(`more than ${when.count.above}`);
1226
+ for (const arg of when.arg ?? []) {
1227
+ const bits = [
1228
+ arg.above === void 0 ? "" : `above ${arg.above}`,
1229
+ arg.below === void 0 ? "" : `below ${arg.below}`,
1230
+ arg.equals === void 0 ? "" : `= ${String(arg.equals)}`
1231
+ ].filter(Boolean);
1232
+ parts.push(`${arg.name} ${bits.join(" ")}`.trim());
1233
+ }
1234
+ return parts.length === 0 ? "every call" : parts.join(" · ");
1235
+ }
1236
+ function renderPacks(data) {
1237
+ const pack = data.pack;
1238
+ if (pack === void 0) return renderShell({
1239
+ title: "Policy packs",
1240
+ nav: renderNav(navFor(data), "Policy packs"),
1241
+ head: header("Policy packs", "no pack supplied", data.verification.ok),
1242
+ body: " <div class=\"empty\">Pass --pack to render the policy in force.</div>"
1243
+ });
1244
+ const baseline = pack.baseline?.capabilities;
1245
+ const caps = baseline === void 0 ? `<p style="padding:0 30px 22px;font-size:14px;color:var(--secondary);max-width:76ch">This pack sets no capability ceiling. It governs through its rules alone, and withholds nothing an author declares.</p>` : `<div class="caps">${baseline.map((c) => `<span class="cap">${esc(c)}</span>`).join("")}</div>`;
1246
+ const cited = /* @__PURE__ */ new Map();
1247
+ for (const rule of pack.rules) for (const c of cite(rule)) cited.set(c.framework, c.frameworkName);
1248
+ const frameworks = cited.size === 0 ? "" : `<div class="caps">${[...cited.values()].map((name) => `<span class="cap">${esc(name)}</span>`).join("")}</div>`;
1249
+ const rows = pack.rules.map((rule) => {
1250
+ const tags = cite(rule).map((c) => `<br><span style="color:var(--secondary)">${esc(c.frameworkShort)} · ${esc(c.control)} ${esc(c.controlName)}</span>`).join("");
1251
+ return ` <div class="grid rules row">
1252
+ <div class="seq">${esc(rule.id)}</div>
1253
+ <div class="call">${esc(rule.title ?? rule.effect.because)}<br><span style="color:var(--muted)">${esc(matcherOf(rule))}</span>${tags}</div>
1254
+ <div class="effect e-${esc(rule.effect.kind)}">${esc(rule.effect.kind.toUpperCase())}</div>
1255
+ </div>`;
1256
+ }).join("\n");
1257
+ const body = ` <section class="sect">
1258
+ <h2>${esc(pack.pack)} <span style="font-family:var(--proof);font-size:14px;color:var(--muted)">${esc(pack.version)}</span></h2>
1259
+ <p>The operator baseline is intersected with whatever a plugin's own
1260
+ manifest declares, and the operator can only ever narrow. A pack cannot
1261
+ grant a capability an author never asked for.</p>
1262
+ </section>
1263
+ ${caps}
1264
+ ${frameworks}
1265
+ <div class="grid rules thead">
1266
+ <div>CLAUSE</div><div>RULE</div><div>EFFECT</div>
1267
+ </div>
1268
+ ${rows}
1269
+ <section class="sect" style="padding-bottom:26px">
1270
+ <h2>Ordering</h2>
1271
+ <p>When several rules match one call the strongest effect wins —
1272
+ deny over ask over correct over warn — and every match stays in the
1273
+ trace. That is what makes a pack safe to extend: appending a rule can
1274
+ raise a decision's strength and never lower it.</p>
1275
+ </section>`;
1276
+ return renderShell({
1277
+ title: `Policy packs — ${pack.pack}`,
1278
+ nav: renderNav(navFor(data), "Policy packs"),
1279
+ head: header("Policy packs", `${pack.pack} ${pack.version} · ${pack.rules.length} rules`, data.verification.ok),
1280
+ body
1281
+ });
1282
+ }
1283
+ function renderCompliance(data) {
1284
+ const body = ` <section class="sect">
1285
+ <h2>Evidence, not compliance</h2>
1286
+ <p>Each row states what a control asks for and what this profile actually
1287
+ produces. Nothing here certifies anything — whether the evidence satisfies
1288
+ the obligation is an auditor's judgement, and a tool that answered it for
1289
+ them would be selling the one thing it cannot supply.</p>
1290
+ </section>
1291
+ <div class="grid map thead">
1292
+ <div>CONTROL</div><div>ASKS FOR · WHAT THIS PROFILE PRODUCES</div><div>STATE</div>
1293
+ </div>
1294
+ ${CONTROLS.map((control) => {
1295
+ const found = control.evidence(data);
1296
+ const label = found.state === "covered" ? "EVIDENCE" : found.state === "partial" ? "PARTIAL" : "NONE";
1297
+ return ` <div class="grid map row">
1298
+ <div class="call">${esc(control.id)}</div>
1299
+ <div class="actor">${esc(control.asks)}<br><span style="color:var(--ink-row)">${esc(found.note)}</span></div>
1300
+ <div class="effect ${esc(found.state)}">${label}</div>
1301
+ </div>`;
1302
+ }).join("\n")}
1303
+ <section class="sect" style="padding-bottom:26px">
1304
+ <h2>Reading the states</h2>
1305
+ <p>For the audit obligations, several rows stop at <em>partial</em> for
1306
+ one reason: the harness records what was decided and never who decided
1307
+ it. Attributable approval needs an identity anchor outside this machine,
1308
+ which is a control-plane concern this build does not claim.</p>
1309
+ <p>For the OWASP risks, <em>evidence</em> means rules in this pack cite
1310
+ the risk and have decided calls in this record; <em>partial</em> means
1311
+ they cite it and have not yet, or — for prompt injection — that the gate
1312
+ bounds the risk without claiming to detect it; <em>none</em> means no
1313
+ rule cites it, with the reason a tool-call gate is not where that risk
1314
+ is controlled.</p>
1315
+ </section>`;
1316
+ return renderShell({
1317
+ title: "Compliance map",
1318
+ nav: renderNav(navFor(data), "Compliance map"),
1319
+ head: header("Compliance map", `${CONTROLS.length} controls · evidence from this profile`, data.verification.ok),
1320
+ body
1321
+ });
1322
+ }
1323
+ /**
1324
+ * Every call the policy held, and what became of it.
1325
+ *
1326
+ * This is a queue you read, not one you act on. The gate returns `ask` into the
1327
+ * harness's own approval seam and the harness settles it there; a second set of
1328
+ * buttons here would mean two places to approve from and two audit trails to
1329
+ * reconcile. So the view shows what is waiting and what was decided, and says
1330
+ * plainly where the decision happens.
1331
+ */
1332
+ function renderApprovals(data) {
1333
+ const held = data.entries.filter((e) => e.verdict === "ask" && e.shadow !== true);
1334
+ const settled = data.entries.filter((e) => e.rule === "approval");
1335
+ const now = Date.parse(data.generatedAt);
1336
+ const waited = (iso) => {
1337
+ const s = Math.max(0, Math.round((now - Date.parse(iso)) / 1e3));
1338
+ if (!Number.isFinite(s)) return "";
1339
+ const h = Math.floor(s / 3600);
1340
+ const m = Math.floor(s % 3600 / 60);
1341
+ return h > 0 ? `${h}h ${m}m` : `${m}m`;
1342
+ };
1343
+ const queue = held.length === 0 ? " <div class=\"empty\">Nothing is waiting on a human.</div>" : held.map((e) => ` <section class="await" style="border-top:none">
1344
+ <div class="card">
1345
+ <div style="flex:1">
1346
+ <h2>${esc(e.tool)}${e.subject === void 0 ? "" : ` on ${esc(e.subject)}`}</h2>
1347
+ <div class="detail">
1348
+ ${esc(e.rule ?? "held")} · ${esc(e.session ?? "local session")} · waiting ${esc(waited(e.at))}<br>
1349
+ ${esc(e.reason ?? "")}
1350
+ </div>
1351
+ </div>
1352
+ <div class="decide">
1353
+ <button type="button" class="approve" disabled title="The harness settles approvals; a second prompt would mean two audit trails">Approve</button>
1354
+ <button type="button" class="deny" disabled title="The harness settles approvals; a second prompt would mean two audit trails">Deny</button>
1355
+ <div class="recorded">SETTLED IN THE HARNESS</div>
1356
+ </div>
1357
+ </div>
1358
+ </section>`).join("\n");
1359
+ const history = settled.length === 0 ? "" : ` <div class="grid map thead">
1360
+ <div>WHEN</div><div>CALL · WHY</div><div>OUTCOME</div>
1361
+ </div>
1362
+ ${settled.map((e) => ` <div class="grid map row">
1363
+ <div class="seq">${esc(e.at.replace("T", " ").replace(/\.\d+Z$/, "Z"))}</div>
1364
+ <div class="call">${esc(e.tool)}${e.subject === void 0 ? "" : ` ${esc(e.subject)}`}<br><span style="color:var(--muted)">${esc(e.reason ?? "")}${e.actor === void 0 ? "" : ` · ${esc(e.actor)}`}</span></div>
1365
+ <div class="effect ${e.verdict === "allow" ? "covered" : "absent"}">${e.verdict === "allow" ? "APPROVED" : "REFUSED"}</div>
1366
+ </div>`).join("\n")}`;
1367
+ const body = ` <section class="stats">
1368
+ <div class="stat"><div class="v hold">${held.length}</div><div class="k">AWAITING HUMAN</div></div>
1369
+ <div class="stat"><div class="v">${settled.length}</div><div class="k">SETTLED</div></div>
1370
+ <div class="stat"><div class="v">${settled.filter((e) => e.actor !== void 0).length}</div><div class="k">WITH AN ACTOR</div></div>
1371
+ <div class="stat"><div class="v">${data.entries.length}</div><div class="k">DECISIONS</div></div>
1372
+ </section>
1373
+ <section class="sect">
1374
+ <h2>Waiting</h2>
1375
+ <p>A held call is one a clause would not decide alone. The harness owns
1376
+ the prompt and settles it; this is the queue, not a second place to
1377
+ approve from.</p>
1378
+ </section>
1379
+ ${queue}
1380
+ <section class="sect">
1381
+ <h2>Settled</h2>
1382
+ <p>Where an entry names an actor, that name is asserted by configuration.
1383
+ The harness records what was decided and never who decided it, so an
1384
+ attributable approval needs an identity anchor this build does not have.</p>
1385
+ </section>
1386
+ ${history}`;
1387
+ return renderShell({
1388
+ title: "Approvals",
1389
+ nav: renderNav(navFor(data), "Approvals"),
1390
+ head: header("Approvals", `${held.length} waiting · ${settled.length} settled`, data.verification.ok),
1391
+ body
1392
+ });
1393
+ }
1394
+
1395
+ //#endregion
1396
+ export { renderPacks as a, renderNav as c, renderOverview as i, renderShell as l, renderApprovals as n, CONTROLS as o, renderCompliance as r, esc as s, navFor as t, VERDICT_LABEL as u };