@desplega.ai/agent-swarm 1.114.0 → 1.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{actions-bm8vdxys.js → actions-17ya5wde.js} +6 -6
- package/dist/{app-bhwdxmvp.js → app-4f718yk0.js} +4 -4
- package/dist/{assistant-15mp2apr.js → assistant-ah7csnjz.js} +9 -9
- package/dist/{boot-reembed-awr2179r.js → boot-reembed-4jpxhb25.js} +4 -4
- package/dist/{boot-reembed-b9sbk87z.js → boot-reembed-qata34xa.js} +3 -3
- package/dist/{boot-scrub-logs-c1zsaw9m.js → boot-scrub-logs-tv48nn3z.js} +2 -2
- package/dist/{claude-adapter-2k45y7p7.js → claude-adapter-3csn5bks.js} +2 -2
- package/dist/{cli-zmmp2r79.js → cli-12vb0xg6.js} +13 -2
- package/dist/{cli-jzwtn8rm.js → cli-15y7qhzp.js} +188 -18
- package/dist/{cli-w3nq88yc.js → cli-3samkyap.js} +2 -2
- package/dist/{cli-7rgh0w0k.js → cli-52fg7s7x.js} +10 -3
- package/dist/{cli-5afkmcfj.js → cli-65ekje01.js} +6 -6
- package/dist/{cli-113wmegp.js → cli-6aq8xhvm.js} +1 -1
- package/dist/{cli-byjcad11.js → cli-7xje5amz.js} +1 -1
- package/dist/{cli-0kgcv878.js → cli-86fdnerz.js} +63 -2
- package/dist/{cli-f5pzfvwb.js → cli-b23axgz4.js} +1 -1
- package/dist/{cli-a0t7vapf.js → cli-bc89my0z.js} +1 -1
- package/dist/{cli-q4e2x252.js → cli-beea4a3y.js} +73 -24
- package/dist/{cli-w4wk3kx6.js → cli-cchksf5q.js} +2 -2
- package/dist/{cli-f9n2jg31.js → cli-cmw9rzy5.js} +2 -2
- package/dist/{cli-hvg05qwm.js → cli-cnwssmsr.js} +1 -1
- package/dist/{cli-2t4e4ayk.js → cli-dcca6j8m.js} +46 -5
- package/dist/{cli-tkmm5nf9.js → cli-e61fs2hp.js} +59 -2
- package/dist/{cli-e2xbxmhd.js → cli-hrhye2rm.js} +90 -32
- package/dist/{cli-312v3c41.js → cli-k3y4z3h5.js} +1 -1
- package/dist/{cli-6xd0bvf8.js → cli-ma04faw5.js} +1 -1
- package/dist/{cli-ggy8c7tk.js → cli-mnbgv3w7.js} +1 -1
- package/dist/{cli-hq39e630.js → cli-pet3aev6.js} +95 -10
- package/dist/{cli-a6tzw6vq.js → cli-q1rx7g0d.js} +6 -6
- package/dist/{cli-pnfyyp6h.js → cli-r9f6ngrf.js} +6 -3
- package/dist/{cli-q1z5d5ss.js → cli-shvaxw27.js} +4 -4
- package/dist/{cli-49j095n9.js → cli-t0vqevnm.js} +1 -1
- package/dist/{cli-k6h2zkw3.js → cli-tece6zgm.js} +1 -1
- package/dist/{cli-5ktc9fd4.js → cli-tffvrh6j.js} +1 -1
- package/dist/cli-wh91zby6.js +187222 -0
- package/dist/{cli-r3mtrrzp.js → cli-zsrdty74.js} +12 -12
- package/dist/cli.js +10 -10
- package/dist/{codex-adapter-4z8m9mb5.js → codex-adapter-de3w0nch.js} +2 -2
- package/dist/{codex-session-runner-rbct46dg.js → codex-session-runner-bnw8cysk.js} +2 -2
- package/dist/{commands-zk4d6esf.js → commands-hch4e2k1.js} +2 -2
- package/dist/{db-stn16jp2.js → db-p3h2j06x.js} +12 -2
- package/dist/{handlers-gshprvpf.js → handlers-9er4zx9q.js} +9 -9
- package/dist/{hook-amzx9tap.js → hook-4axs756z.js} +1 -1
- package/dist/{http-6g0hfzax.js → http-809fvtz2.js} +182 -65
- package/dist/{index-ty42rxw9.js → index-47em3d2n.js} +10 -10
- package/dist/{index-jbm7qcqk.js → index-9fqaktjr.js} +8 -8
- package/dist/{index-f03rnnrs.js → index-9ht8gr56.js} +9 -9
- package/dist/{index-df8fmphk.js → index-rm85cfdx.js} +331 -30
- package/dist/{keepalive-pm6g2wpw.js → keepalive-3cps6e3e.js} +4 -4
- package/dist/{lead-h79fzpzw.js → lead-fkk95wgq.js} +24 -24
- package/dist/{maintenance-433zndy1.js → maintenance-fweqh0yj.js} +4 -4
- package/dist/{oauth-refresh-sweep-mjsbmsk2.js → oauth-refresh-sweep-sycqtbph.js} +3 -3
- package/dist/{onboard-vdr9hc3f.js → onboard-cy0rkgvx.js} +2 -2
- package/dist/{opencode-adapter-mqsxr170.js → opencode-adapter-p6bxnbm4.js} +2 -2
- package/dist/{otel-impl-yswd0fty.js → otel-impl-wbns8hf7.js} +1 -1
- package/dist/{pi-mono-adapter-vbrvg1p8.js → pi-mono-adapter-05sck1ds.js} +1 -1
- package/dist/{pricing-refresh-2kk2ap9b.js → pricing-refresh-0hvazmkf.js} +4 -4
- package/dist/{rbac-roles-xdc5208b.js → rbac-roles-kfesjy9y.js} +4 -4
- package/dist/{rbac-roles-2wgh9b5t.js → rbac-roles-mwcwhbxc.js} +11 -4
- package/dist/{seed-pricing-m9h69d2t.js → seed-pricing-h2kdq4cq.js} +3 -3
- package/dist/{setup-eynkvafa.js → setup-8506q97w.js} +2 -2
- package/dist/{worker-136q8dc2.js → worker-4r5c6zyb.js} +24 -24
- package/openapi.json +8 -4
- package/package.json +1 -1
- package/src/be/db.ts +253 -20
- package/src/be/migrations/113_task_routing_affinity.sql +9 -0
- package/src/be/migrations/114_backfill_gpt_5_6_pricing.sql +15 -0
- package/src/be/modelsdev-cache.json +135 -0
- package/src/be/rbac-audit.ts +19 -8
- package/src/be/rbac-roles.ts +8 -1
- package/src/be/script-connections.ts +4 -4
- package/src/be/scripts/typecheck.ts +11 -0
- package/src/be/seed-scripts/catalog/catalog-report.inline.ts +325 -24
- package/src/be/seed-scripts/catalog/catalog-report.ts +325 -24
- package/src/heartbeat/heartbeat.ts +143 -21
- package/src/http/favorites.ts +1 -5
- package/src/http/mcp-servers.ts +38 -0
- package/src/http/poll.ts +7 -2
- package/src/http/scripts.ts +6 -0
- package/src/http/skills.ts +11 -0
- package/src/http/tasks.ts +21 -9
- package/src/providers/codex-models.ts +100 -30
- package/src/providers/modelsdev-reasoning.json +51 -0
- package/src/providers/reasoning-effort.ts +11 -5
- package/src/rbac/admission.ts +26 -2
- package/src/rbac/index.ts +2 -2
- package/src/rbac/legacy-policy.ts +9 -0
- package/src/rbac/permissions.ts +36 -0
- package/src/scripts-runtime/api-client.ts +82 -6
- package/src/scripts-runtime/types/swarm-sdk.d.ts +11 -0
- package/src/server-user.ts +114 -59
- package/src/slack/responses.ts +91 -1
- package/src/slack/watcher.ts +9 -6
- package/src/tasks/worker-follow-up.ts +100 -3
- package/src/tests/codex-adapter.test.ts +46 -23
- package/src/tests/heartbeat.test.ts +48 -3
- package/src/tests/model-control.test.ts +8 -2
- package/src/tests/pool-affinity.test.ts +401 -0
- package/src/tests/rbac-admission-e2e.test.ts +152 -7
- package/src/tests/rbac-admission.test.ts +60 -1
- package/src/tests/rbac-engine.test.ts +9 -0
- package/src/tests/rbac-mcp-admission-e2e.test.ts +362 -0
- package/src/tests/rbac-roles.test.ts +2 -0
- package/src/tests/reasoning-effort.test.ts +15 -2
- package/src/tests/script-apis-mcp.test.ts +37 -13
- package/src/tests/script-connections.test.ts +27 -1
- package/src/tests/scripts-runtime.test.ts +187 -0
- package/src/tests/seed-scripts.test.ts +36 -0
- package/src/tests/slack-inline-output.test.ts +65 -0
- package/src/tests/user-token-rest-auth.test.ts +110 -0
- package/src/tools/script-apis.ts +62 -3
- package/src/tools/send-task.ts +15 -1
- package/src/tools/task-action.ts +34 -2
- package/src/tools/templates.ts +48 -0
- package/src/tools/utils.ts +2 -0
- package/src/types.ts +27 -5
- package/dist/cli-46b6kc7f.js +0 -1698
|
@@ -20,24 +20,24 @@ import {
|
|
|
20
20
|
stopWaitPoller,
|
|
21
21
|
subscribeWaitToBus,
|
|
22
22
|
validateTemplateVariables
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-q1rx7g0d.js";
|
|
24
24
|
import"./cli-f14fvzag.js";
|
|
25
|
-
import"./cli-
|
|
25
|
+
import"./cli-r9f6ngrf.js";
|
|
26
26
|
import"./cli-jkhwmmgg.js";
|
|
27
|
-
import"./cli-
|
|
28
|
-
import"./cli-
|
|
27
|
+
import"./cli-cmw9rzy5.js";
|
|
28
|
+
import"./cli-7xje5amz.js";
|
|
29
29
|
import"./cli-q25ejbyn.js";
|
|
30
|
-
import"./cli-
|
|
30
|
+
import"./cli-t0vqevnm.js";
|
|
31
31
|
import"./cli-0pygq9r1.js";
|
|
32
|
-
import"./cli-
|
|
32
|
+
import"./cli-k3y4z3h5.js";
|
|
33
33
|
import"./cli-dh55d5fg.js";
|
|
34
34
|
import {
|
|
35
35
|
interpolate
|
|
36
|
-
} from "./cli-
|
|
36
|
+
} from "./cli-15y7qhzp.js";
|
|
37
37
|
import"./cli-z2zcxes1.js";
|
|
38
38
|
import"./cli-bw80ck94.js";
|
|
39
39
|
import"./cli-xz9aq0rf.js";
|
|
40
|
-
import"./cli-
|
|
40
|
+
import"./cli-b23axgz4.js";
|
|
41
41
|
import"./cli-4j2mrzag.js";
|
|
42
42
|
import {
|
|
43
43
|
workflowEventBus
|
|
@@ -4,23 +4,23 @@ import {
|
|
|
4
4
|
runScheduleNow,
|
|
5
5
|
startScheduler,
|
|
6
6
|
stopScheduler
|
|
7
|
-
} from "./cli-
|
|
8
|
-
import"./cli-
|
|
7
|
+
} from "./cli-shvaxw27.js";
|
|
8
|
+
import"./cli-q1rx7g0d.js";
|
|
9
9
|
import"./cli-f14fvzag.js";
|
|
10
|
-
import"./cli-
|
|
10
|
+
import"./cli-r9f6ngrf.js";
|
|
11
11
|
import"./cli-jkhwmmgg.js";
|
|
12
|
-
import"./cli-
|
|
13
|
-
import"./cli-
|
|
12
|
+
import"./cli-cmw9rzy5.js";
|
|
13
|
+
import"./cli-7xje5amz.js";
|
|
14
14
|
import"./cli-q25ejbyn.js";
|
|
15
|
-
import"./cli-
|
|
15
|
+
import"./cli-t0vqevnm.js";
|
|
16
16
|
import"./cli-0pygq9r1.js";
|
|
17
|
-
import"./cli-
|
|
17
|
+
import"./cli-k3y4z3h5.js";
|
|
18
18
|
import"./cli-dh55d5fg.js";
|
|
19
|
-
import"./cli-
|
|
19
|
+
import"./cli-15y7qhzp.js";
|
|
20
20
|
import"./cli-z2zcxes1.js";
|
|
21
21
|
import"./cli-bw80ck94.js";
|
|
22
22
|
import"./cli-xz9aq0rf.js";
|
|
23
|
-
import"./cli-
|
|
23
|
+
import"./cli-b23axgz4.js";
|
|
24
24
|
import"./cli-4j2mrzag.js";
|
|
25
25
|
import"./cli-9aryf9tv.js";
|
|
26
26
|
import"./cli-p9swy5t3.js";
|
|
@@ -3,15 +3,15 @@ import {
|
|
|
3
3
|
extractArgsJsonSchema,
|
|
4
4
|
extractScriptSignature,
|
|
5
5
|
typecheckScript
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-12vb0xg6.js";
|
|
7
7
|
import {
|
|
8
8
|
getScript,
|
|
9
9
|
upsertScriptByName,
|
|
10
10
|
validateScriptImports
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-r9f6ngrf.js";
|
|
12
12
|
import"./cli-jkhwmmgg.js";
|
|
13
|
-
import"./cli-
|
|
14
|
-
import"./cli-
|
|
13
|
+
import"./cli-cmw9rzy5.js";
|
|
14
|
+
import"./cli-7xje5amz.js";
|
|
15
15
|
import"./cli-q25ejbyn.js";
|
|
16
16
|
import"./cli-0pygq9r1.js";
|
|
17
17
|
import {
|
|
@@ -21,11 +21,11 @@ import {
|
|
|
21
21
|
getSkillByName,
|
|
22
22
|
init_db,
|
|
23
23
|
updateSkill
|
|
24
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-15y7qhzp.js";
|
|
25
25
|
import"./cli-z2zcxes1.js";
|
|
26
26
|
import"./cli-bw80ck94.js";
|
|
27
27
|
import"./cli-xz9aq0rf.js";
|
|
28
|
-
import"./cli-
|
|
28
|
+
import"./cli-b23axgz4.js";
|
|
29
29
|
import"./cli-4j2mrzag.js";
|
|
30
30
|
import"./cli-p9swy5t3.js";
|
|
31
31
|
|
|
@@ -318,6 +318,7 @@ function catalogReportHumanLabel(value: string): string {
|
|
|
318
318
|
|
|
319
319
|
function catalogReportFormatMetric(value: unknown): string {
|
|
320
320
|
if (typeof value === "number") return new Intl.NumberFormat("en-US").format(value);
|
|
321
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
321
322
|
return catalogReportAsText(value);
|
|
322
323
|
}
|
|
323
324
|
|
|
@@ -328,6 +329,25 @@ function catalogReportSeverityTone(value?: string): string {
|
|
|
328
329
|
return "low";
|
|
329
330
|
}
|
|
330
331
|
|
|
332
|
+
function catalogReportIsScalar(value: unknown): boolean {
|
|
333
|
+
return value == null || ["string", "number", "boolean"].includes(typeof value);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function catalogReportIsRecord(value: unknown): value is Record<string, unknown> {
|
|
337
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function catalogReportValueClass(value: unknown): string {
|
|
341
|
+
if (typeof value === "number") return "numeric";
|
|
342
|
+
if (typeof value === "boolean") return value ? "positive" : "muted-value";
|
|
343
|
+
return "";
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function catalogReportClassAttr(value: unknown): string {
|
|
347
|
+
const className = catalogReportValueClass(value);
|
|
348
|
+
return className ? \` class="\${catalogReportHtmlEscape(className)}"\` : "";
|
|
349
|
+
}
|
|
350
|
+
|
|
331
351
|
function catalogReportRenderSampleValue(value: unknown): string {
|
|
332
352
|
if (Array.isArray(value)) {
|
|
333
353
|
return value
|
|
@@ -365,9 +385,116 @@ function catalogReportRenderSamples(samples?: unknown[]): string {
|
|
|
365
385
|
</div>\`;
|
|
366
386
|
}
|
|
367
387
|
|
|
388
|
+
function catalogReportTableRows(rows: Record<string, unknown>[], limit = 12): string {
|
|
389
|
+
if (rows.length === 0) return '<p class="empty">No rows.</p>';
|
|
390
|
+
const columns = Array.from(new Set(rows.flatMap((row) => Object.keys(row).slice(0, 8)))).slice(0, 8);
|
|
391
|
+
const visible = rows.slice(0, limit);
|
|
392
|
+
const hiddenCount = Math.max(0, rows.length - visible.length);
|
|
393
|
+
return \`<div class="data-table" role="region" aria-label="Data table">
|
|
394
|
+
<table>
|
|
395
|
+
<thead><tr>\${columns.map((column) => \`<th>\${catalogReportHtmlEscape(catalogReportHumanLabel(column))}</th>\`).join("")}</tr></thead>
|
|
396
|
+
<tbody>
|
|
397
|
+
\${visible
|
|
398
|
+
.map(
|
|
399
|
+
(row) =>
|
|
400
|
+
\`<tr>\${columns
|
|
401
|
+
.map((column) => {
|
|
402
|
+
const value = row[column];
|
|
403
|
+
return \`<td\${catalogReportClassAttr(value)}>\${catalogReportHtmlEscape(
|
|
404
|
+
catalogReportRenderSampleValue(value),
|
|
405
|
+
)}</td>\`;
|
|
406
|
+
})
|
|
407
|
+
.join("")}</tr>\`,
|
|
408
|
+
)
|
|
409
|
+
.join("")}
|
|
410
|
+
</tbody>
|
|
411
|
+
</table>
|
|
412
|
+
\${hiddenCount ? \`<p class="table-note">Showing \${visible.length} of \${rows.length} rows. Full payload remains in the appendix.</p>\` : ""}
|
|
413
|
+
</div>\`;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function catalogReportRenderDataValue(value: unknown): string {
|
|
417
|
+
if (catalogReportIsScalar(value)) {
|
|
418
|
+
return \`<strong\${catalogReportClassAttr(value)}>\${catalogReportHtmlEscape(
|
|
419
|
+
catalogReportFormatMetric(value),
|
|
420
|
+
)}</strong>\`;
|
|
421
|
+
}
|
|
422
|
+
if (Array.isArray(value)) {
|
|
423
|
+
if (value.every((item) => catalogReportIsRecord(item))) {
|
|
424
|
+
return catalogReportTableRows(value as Record<string, unknown>[]);
|
|
425
|
+
}
|
|
426
|
+
return \`<div class="value-list">\${value
|
|
427
|
+
.slice(0, 12)
|
|
428
|
+
.map((item) => \`<span>\${catalogReportHtmlEscape(catalogReportRenderSampleValue(item))}</span>\`)
|
|
429
|
+
.join("")}</div>\`;
|
|
430
|
+
}
|
|
431
|
+
if (catalogReportIsRecord(value)) {
|
|
432
|
+
const entries = Object.entries(value);
|
|
433
|
+
const scalarEntries = entries.filter(([, entryValue]) => catalogReportIsScalar(entryValue));
|
|
434
|
+
const complexEntries = entries.filter(([, entryValue]) => !catalogReportIsScalar(entryValue));
|
|
435
|
+
return \`<div class="data-object">
|
|
436
|
+
\${
|
|
437
|
+
scalarEntries.length
|
|
438
|
+
? \`<div class="object-stats">\${scalarEntries
|
|
439
|
+
.map(
|
|
440
|
+
([label, entryValue]) =>
|
|
441
|
+
\`<div><span>\${catalogReportHtmlEscape(catalogReportHumanLabel(label))}</span><strong\${catalogReportClassAttr(
|
|
442
|
+
entryValue,
|
|
443
|
+
)}>\${catalogReportHtmlEscape(catalogReportFormatMetric(entryValue))}</strong></div>\`,
|
|
444
|
+
)
|
|
445
|
+
.join("")}</div>\`
|
|
446
|
+
: ""
|
|
447
|
+
}
|
|
448
|
+
\${complexEntries
|
|
449
|
+
.map(
|
|
450
|
+
([label, entryValue]) => \`<section class="data-nested">
|
|
451
|
+
<h4>\${catalogReportHtmlEscape(catalogReportHumanLabel(label))}</h4>
|
|
452
|
+
\${catalogReportRenderDataValue(entryValue)}
|
|
453
|
+
</section>\`,
|
|
454
|
+
)
|
|
455
|
+
.join("")}
|
|
456
|
+
</div>\`;
|
|
457
|
+
}
|
|
458
|
+
return \`<pre>\${catalogReportHtmlEscape(JSON.stringify(value, null, 2))}</pre>\`;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function catalogReportRenderDataPanels(entries: Array<[string, unknown]>): string {
|
|
462
|
+
if (entries.length === 0) return "";
|
|
463
|
+
return \`<div class="data-panels">
|
|
464
|
+
\${entries
|
|
465
|
+
.map(
|
|
466
|
+
([label, value]) => \`<section class="data-panel">
|
|
467
|
+
<div class="data-panel-head">
|
|
468
|
+
<h3>\${catalogReportHtmlEscape(catalogReportHumanLabel(label))}</h3>
|
|
469
|
+
<span>\${catalogReportHtmlEscape(
|
|
470
|
+
Array.isArray(value)
|
|
471
|
+
? \`\${value.length} rows\`
|
|
472
|
+
: catalogReportIsRecord(value)
|
|
473
|
+
? \`\${Object.keys(value).length} fields\`
|
|
474
|
+
: "value",
|
|
475
|
+
)}</span>
|
|
476
|
+
</div>
|
|
477
|
+
\${catalogReportRenderDataValue(value)}
|
|
478
|
+
</section>\`,
|
|
479
|
+
)
|
|
480
|
+
.join("")}
|
|
481
|
+
</div>\`;
|
|
482
|
+
}
|
|
483
|
+
|
|
368
484
|
export function renderCatalogReportPage(report: CatalogReport): string {
|
|
485
|
+
const nav = report.sections
|
|
486
|
+
.map(
|
|
487
|
+
(section) =>
|
|
488
|
+
\`<a href="#\${catalogReportHtmlEscape(section.key)}"><span>\${catalogReportHtmlEscape(
|
|
489
|
+
section.label || catalogReportHumanLabel(section.key),
|
|
490
|
+
)}</span><strong>\${catalogReportHtmlEscape(catalogReportFormatMetric(section.findingCount ?? section.findings?.length ?? 0))}</strong></a>\`,
|
|
491
|
+
)
|
|
492
|
+
.join("");
|
|
369
493
|
const sections = report.sections
|
|
370
494
|
.map((section) => {
|
|
495
|
+
const checkEntries = Object.entries(section.checks || {});
|
|
496
|
+
const scalarChecks = checkEntries.filter(([, value]) => catalogReportIsScalar(value));
|
|
497
|
+
const dataChecks = checkEntries.filter(([, value]) => !catalogReportIsScalar(value));
|
|
371
498
|
const findings = (section.findings || [])
|
|
372
499
|
.map(
|
|
373
500
|
(finding) => \`<article class="finding \${catalogReportHtmlEscape(catalogReportSeverityTone(finding.severity))}">
|
|
@@ -385,25 +512,26 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
385
512
|
</article>\`,
|
|
386
513
|
)
|
|
387
514
|
.join("");
|
|
388
|
-
const checks =
|
|
515
|
+
const checks = scalarChecks
|
|
389
516
|
.map(
|
|
390
517
|
([label, value]) =>
|
|
391
|
-
\`<div class="check"><span>\${catalogReportHtmlEscape(catalogReportHumanLabel(label))}</span><strong
|
|
392
|
-
|
|
393
|
-
)}</strong></div>\`,
|
|
518
|
+
\`<div class="check"><span>\${catalogReportHtmlEscape(catalogReportHumanLabel(label))}</span><strong\${catalogReportClassAttr(
|
|
519
|
+
value,
|
|
520
|
+
)}>\${catalogReportHtmlEscape(catalogReportFormatMetric(value))}</strong></div>\`,
|
|
394
521
|
)
|
|
395
522
|
.join("");
|
|
396
|
-
return \`<section class="section">
|
|
523
|
+
return \`<section class="section" id="\${catalogReportHtmlEscape(section.key)}">
|
|
397
524
|
<div class="section-grid">
|
|
398
525
|
<aside class="checks">
|
|
399
526
|
<p class="section-kicker">\${catalogReportHtmlEscape(section.label || catalogReportHumanLabel(section.key))}</p>
|
|
400
|
-
<div class="check-list">\${checks}</div>
|
|
527
|
+
<div class="check-list">\${checks || '<p class="empty">No scalar checks.</p>'}</div>
|
|
401
528
|
</aside>
|
|
402
529
|
<div>
|
|
403
530
|
<div class="section-head">
|
|
404
531
|
<h2>\${catalogReportHtmlEscape(section.goal)}</h2>
|
|
405
532
|
<span>\${catalogReportHtmlEscape(catalogReportFormatMetric(section.findingCount ?? section.findings?.length ?? 0))} finding(s)</span>
|
|
406
533
|
</div>
|
|
534
|
+
\${catalogReportRenderDataPanels(dataChecks)}
|
|
407
535
|
<div class="findings">
|
|
408
536
|
\${findings || '<p class="empty">No actionable findings in this cluster.</p>'}
|
|
409
537
|
</div>
|
|
@@ -424,10 +552,14 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
424
552
|
color-scheme: light;
|
|
425
553
|
--bg: #f5f2ea;
|
|
426
554
|
--panel: #ffffff;
|
|
555
|
+
--panel-soft: #fbfaf6;
|
|
427
556
|
--ink: #18181b;
|
|
428
557
|
--muted: #5f6368;
|
|
558
|
+
--muted-strong: #3f3f46;
|
|
429
559
|
--line: #ded8cb;
|
|
560
|
+
--line-soft: #ebe5d7;
|
|
430
561
|
--accent: #255c99;
|
|
562
|
+
--accent-soft: #edf5ff;
|
|
431
563
|
--danger: #b42318;
|
|
432
564
|
--danger-bg: #fff1f0;
|
|
433
565
|
--warn: #b54708;
|
|
@@ -449,11 +581,19 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
449
581
|
line-height: 1.55;
|
|
450
582
|
}
|
|
451
583
|
main {
|
|
452
|
-
width: min(
|
|
584
|
+
width: min(1240px, calc(100% - 32px));
|
|
453
585
|
margin: 0 auto;
|
|
454
586
|
padding: 48px 0 72px;
|
|
455
587
|
}
|
|
456
|
-
header {
|
|
588
|
+
header {
|
|
589
|
+
display: grid;
|
|
590
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
591
|
+
gap: 24px;
|
|
592
|
+
align-items: end;
|
|
593
|
+
margin-bottom: 24px;
|
|
594
|
+
padding-bottom: 22px;
|
|
595
|
+
border-bottom: 1px solid var(--line);
|
|
596
|
+
}
|
|
457
597
|
.eyebrow {
|
|
458
598
|
margin: 0 0 8px;
|
|
459
599
|
color: var(--muted);
|
|
@@ -465,34 +605,48 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
465
605
|
h1 {
|
|
466
606
|
margin: 0;
|
|
467
607
|
max-width: 860px;
|
|
468
|
-
font-size: clamp(2rem,
|
|
608
|
+
font-size: clamp(2rem, 3.8vw, 3.25rem);
|
|
469
609
|
line-height: 1.05;
|
|
470
610
|
letter-spacing: 0;
|
|
471
611
|
}
|
|
472
612
|
.lede {
|
|
473
|
-
max-width:
|
|
613
|
+
max-width: 840px;
|
|
474
614
|
margin: 16px 0 0;
|
|
475
|
-
color: var(--muted);
|
|
615
|
+
color: var(--muted-strong);
|
|
476
616
|
font-size: 18px;
|
|
477
617
|
}
|
|
618
|
+
.description {
|
|
619
|
+
max-width: 340px;
|
|
620
|
+
margin: 0;
|
|
621
|
+
color: var(--muted);
|
|
622
|
+
font-size: 14px;
|
|
623
|
+
text-align: right;
|
|
624
|
+
}
|
|
478
625
|
.metrics {
|
|
479
626
|
display: grid;
|
|
480
|
-
grid-template-columns: repeat(
|
|
627
|
+
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
481
628
|
gap: 12px;
|
|
482
|
-
margin:
|
|
629
|
+
margin: 24px 0 16px;
|
|
483
630
|
}
|
|
484
|
-
.metric, .section, details {
|
|
631
|
+
.metric, .section, details, .report-nav {
|
|
485
632
|
background: var(--panel);
|
|
486
633
|
border: 1px solid var(--line);
|
|
487
634
|
border-radius: var(--radius);
|
|
488
635
|
box-shadow: var(--shadow);
|
|
489
636
|
}
|
|
490
|
-
.metric {
|
|
637
|
+
.metric {
|
|
638
|
+
min-height: 112px;
|
|
639
|
+
padding: 16px;
|
|
640
|
+
display: flex;
|
|
641
|
+
flex-direction: column;
|
|
642
|
+
justify-content: space-between;
|
|
643
|
+
}
|
|
491
644
|
.metric strong {
|
|
492
645
|
display: block;
|
|
493
|
-
font-size:
|
|
646
|
+
font-size: 30px;
|
|
494
647
|
line-height: 1;
|
|
495
648
|
font-variant-numeric: tabular-nums;
|
|
649
|
+
overflow-wrap: anywhere;
|
|
496
650
|
}
|
|
497
651
|
.metric span {
|
|
498
652
|
display: block;
|
|
@@ -501,14 +655,45 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
501
655
|
font-size: 13px;
|
|
502
656
|
font-weight: 650;
|
|
503
657
|
}
|
|
658
|
+
.report-nav {
|
|
659
|
+
display: grid;
|
|
660
|
+
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
661
|
+
gap: 1px;
|
|
662
|
+
overflow: hidden;
|
|
663
|
+
margin: 0 0 20px;
|
|
664
|
+
background: var(--line);
|
|
665
|
+
}
|
|
666
|
+
.report-nav a {
|
|
667
|
+
display: flex;
|
|
668
|
+
align-items: center;
|
|
669
|
+
justify-content: space-between;
|
|
670
|
+
gap: 10px;
|
|
671
|
+
min-height: 48px;
|
|
672
|
+
padding: 11px 13px;
|
|
673
|
+
background: var(--panel);
|
|
674
|
+
color: var(--muted-strong);
|
|
675
|
+
text-decoration: none;
|
|
676
|
+
font-size: 13px;
|
|
677
|
+
font-weight: 700;
|
|
678
|
+
}
|
|
679
|
+
.report-nav a:hover { background: var(--accent-soft); }
|
|
680
|
+
.report-nav strong {
|
|
681
|
+
color: var(--accent);
|
|
682
|
+
font-variant-numeric: tabular-nums;
|
|
683
|
+
}
|
|
504
684
|
.section {
|
|
505
|
-
margin-top:
|
|
506
|
-
padding:
|
|
685
|
+
margin-top: 16px;
|
|
686
|
+
padding: 22px;
|
|
507
687
|
}
|
|
508
688
|
.section-grid {
|
|
509
689
|
display: grid;
|
|
510
|
-
grid-template-columns:
|
|
511
|
-
gap:
|
|
690
|
+
grid-template-columns: 240px minmax(0, 1fr);
|
|
691
|
+
gap: 24px;
|
|
692
|
+
}
|
|
693
|
+
.checks {
|
|
694
|
+
position: sticky;
|
|
695
|
+
top: 18px;
|
|
696
|
+
align-self: start;
|
|
512
697
|
}
|
|
513
698
|
.section-kicker {
|
|
514
699
|
margin: 0 0 12px;
|
|
@@ -530,6 +715,7 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
530
715
|
padding: 10px 0;
|
|
531
716
|
border-bottom: 1px solid var(--line);
|
|
532
717
|
}
|
|
718
|
+
.check:last-child { border-bottom: 0; }
|
|
533
719
|
.check span {
|
|
534
720
|
color: var(--muted);
|
|
535
721
|
font-size: 13px;
|
|
@@ -537,6 +723,8 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
537
723
|
.check strong {
|
|
538
724
|
font-size: 18px;
|
|
539
725
|
font-variant-numeric: tabular-nums;
|
|
726
|
+
text-align: right;
|
|
727
|
+
overflow-wrap: anywhere;
|
|
540
728
|
}
|
|
541
729
|
.section-head {
|
|
542
730
|
display: flex;
|
|
@@ -554,11 +742,113 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
554
742
|
}
|
|
555
743
|
.section-head > span {
|
|
556
744
|
flex: 0 0 auto;
|
|
557
|
-
color: var(--
|
|
745
|
+
color: var(--accent);
|
|
746
|
+
background: var(--accent-soft);
|
|
747
|
+
border: 1px solid #cfe5ff;
|
|
748
|
+
border-radius: 999px;
|
|
749
|
+
padding: 5px 10px;
|
|
558
750
|
font-size: 13px;
|
|
559
751
|
font-weight: 700;
|
|
560
752
|
white-space: nowrap;
|
|
561
753
|
}
|
|
754
|
+
.data-panels {
|
|
755
|
+
display: grid;
|
|
756
|
+
gap: 12px;
|
|
757
|
+
margin: 0 0 16px;
|
|
758
|
+
}
|
|
759
|
+
.data-panel {
|
|
760
|
+
border: 1px solid var(--line-soft);
|
|
761
|
+
border-radius: var(--radius);
|
|
762
|
+
background: var(--panel-soft);
|
|
763
|
+
overflow: hidden;
|
|
764
|
+
}
|
|
765
|
+
.data-panel-head {
|
|
766
|
+
display: flex;
|
|
767
|
+
align-items: baseline;
|
|
768
|
+
justify-content: space-between;
|
|
769
|
+
gap: 16px;
|
|
770
|
+
padding: 12px 14px;
|
|
771
|
+
border-bottom: 1px solid var(--line-soft);
|
|
772
|
+
background: #fffdf8;
|
|
773
|
+
}
|
|
774
|
+
.data-panel-head h3,
|
|
775
|
+
.data-nested h4 {
|
|
776
|
+
margin: 0;
|
|
777
|
+
color: var(--muted-strong);
|
|
778
|
+
font-size: 14px;
|
|
779
|
+
line-height: 1.25;
|
|
780
|
+
letter-spacing: 0;
|
|
781
|
+
}
|
|
782
|
+
.data-panel-head span,
|
|
783
|
+
.table-note {
|
|
784
|
+
color: var(--muted);
|
|
785
|
+
font-size: 12px;
|
|
786
|
+
font-weight: 700;
|
|
787
|
+
}
|
|
788
|
+
.data-object {
|
|
789
|
+
display: grid;
|
|
790
|
+
gap: 12px;
|
|
791
|
+
padding: 14px;
|
|
792
|
+
}
|
|
793
|
+
.object-stats {
|
|
794
|
+
display: grid;
|
|
795
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
796
|
+
gap: 10px;
|
|
797
|
+
}
|
|
798
|
+
.object-stats > div {
|
|
799
|
+
min-height: 76px;
|
|
800
|
+
padding: 12px;
|
|
801
|
+
border: 1px solid var(--line-soft);
|
|
802
|
+
border-radius: var(--radius);
|
|
803
|
+
background: var(--panel);
|
|
804
|
+
}
|
|
805
|
+
.object-stats span,
|
|
806
|
+
.value-list span {
|
|
807
|
+
display: block;
|
|
808
|
+
color: var(--muted);
|
|
809
|
+
font-size: 12px;
|
|
810
|
+
font-weight: 700;
|
|
811
|
+
}
|
|
812
|
+
.object-stats strong {
|
|
813
|
+
display: block;
|
|
814
|
+
margin-top: 6px;
|
|
815
|
+
color: var(--ink);
|
|
816
|
+
font-size: 20px;
|
|
817
|
+
line-height: 1.1;
|
|
818
|
+
font-variant-numeric: tabular-nums;
|
|
819
|
+
overflow-wrap: anywhere;
|
|
820
|
+
}
|
|
821
|
+
.data-nested {
|
|
822
|
+
display: grid;
|
|
823
|
+
gap: 8px;
|
|
824
|
+
}
|
|
825
|
+
.data-table {
|
|
826
|
+
overflow-x: auto;
|
|
827
|
+
background: var(--panel);
|
|
828
|
+
}
|
|
829
|
+
.data-table .table-note {
|
|
830
|
+
margin: 0;
|
|
831
|
+
padding: 10px 12px;
|
|
832
|
+
border-top: 1px solid var(--line-soft);
|
|
833
|
+
background: var(--panel-soft);
|
|
834
|
+
}
|
|
835
|
+
.value-list {
|
|
836
|
+
display: flex;
|
|
837
|
+
flex-wrap: wrap;
|
|
838
|
+
gap: 8px;
|
|
839
|
+
padding: 14px;
|
|
840
|
+
}
|
|
841
|
+
.value-list span {
|
|
842
|
+
padding: 6px 9px;
|
|
843
|
+
border: 1px solid var(--line-soft);
|
|
844
|
+
border-radius: 999px;
|
|
845
|
+
background: var(--panel);
|
|
846
|
+
color: var(--muted-strong);
|
|
847
|
+
overflow-wrap: anywhere;
|
|
848
|
+
}
|
|
849
|
+
.numeric { font-variant-numeric: tabular-nums; }
|
|
850
|
+
.positive { color: var(--low); }
|
|
851
|
+
.muted-value { color: var(--muted); }
|
|
562
852
|
.findings {
|
|
563
853
|
display: grid;
|
|
564
854
|
gap: 12px;
|
|
@@ -667,26 +957,36 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
667
957
|
}
|
|
668
958
|
@media (max-width: 860px) {
|
|
669
959
|
main { width: min(100% - 24px, 1120px); padding-top: 32px; }
|
|
960
|
+
header { grid-template-columns: 1fr; }
|
|
961
|
+
.description { max-width: none; text-align: left; }
|
|
670
962
|
.metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
963
|
+
.report-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
671
964
|
.section-grid { grid-template-columns: 1fr; gap: 18px; }
|
|
965
|
+
.checks { position: static; }
|
|
672
966
|
.section { padding: 18px; }
|
|
673
967
|
.section-head { display: block; }
|
|
674
968
|
.section-head > span { display: block; margin-top: 8px; }
|
|
969
|
+
.object-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
675
970
|
}
|
|
676
971
|
@media (max-width: 520px) {
|
|
677
972
|
.metrics { grid-template-columns: 1fr; }
|
|
973
|
+
.report-nav { grid-template-columns: 1fr; }
|
|
678
974
|
.lede { font-size: 16px; }
|
|
679
975
|
.finding-head { display: block; }
|
|
680
976
|
.pill { margin-top: 10px; }
|
|
977
|
+
.object-stats { grid-template-columns: 1fr; }
|
|
681
978
|
}
|
|
682
979
|
</style>
|
|
683
980
|
</head>
|
|
684
981
|
<body>
|
|
685
982
|
<main>
|
|
686
983
|
<header>
|
|
687
|
-
<
|
|
688
|
-
|
|
689
|
-
|
|
984
|
+
<div>
|
|
985
|
+
<p class="eyebrow">Generated \${catalogReportHtmlEscape(report.generatedAt)}</p>
|
|
986
|
+
<h1>\${catalogReportHtmlEscape(report.title)}</h1>
|
|
987
|
+
<p class="lede">\${catalogReportHtmlEscape(report.lede)}</p>
|
|
988
|
+
</div>
|
|
989
|
+
<p class="description">\${catalogReportHtmlEscape(report.description)}</p>
|
|
690
990
|
</header>
|
|
691
991
|
<section class="metrics" aria-label="Audit summary">
|
|
692
992
|
\${report.metrics
|
|
@@ -698,6 +998,7 @@ export function renderCatalogReportPage(report: CatalogReport): string {
|
|
|
698
998
|
)
|
|
699
999
|
.join("")}
|
|
700
1000
|
</section>
|
|
1001
|
+
<nav class="report-nav" aria-label="Report sections">\${nav}</nav>
|
|
701
1002
|
\${sections}
|
|
702
1003
|
<details>
|
|
703
1004
|
<summary>Compressed JSON appendix</summary>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureTokenOrThrow
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-t0vqevnm.js";
|
|
4
4
|
import"./cli-0pygq9r1.js";
|
|
5
|
-
import"./cli-
|
|
5
|
+
import"./cli-15y7qhzp.js";
|
|
6
6
|
import"./cli-z2zcxes1.js";
|
|
7
7
|
import"./cli-bw80ck94.js";
|
|
8
8
|
import"./cli-xz9aq0rf.js";
|
|
9
|
-
import"./cli-
|
|
9
|
+
import"./cli-b23axgz4.js";
|
|
10
10
|
import"./cli-4j2mrzag.js";
|
|
11
11
|
import {
|
|
12
12
|
__require
|
|
@@ -55,7 +55,7 @@ async function notifySlack(text) {
|
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
57
|
try {
|
|
58
|
-
const { getSlackApp } = await import("./app-
|
|
58
|
+
const { getSlackApp } = await import("./app-4f718yk0.js");
|
|
59
59
|
const app = getSlackApp();
|
|
60
60
|
if (!app) {
|
|
61
61
|
console.warn("[OAuth Keepalive] Slack not available, cannot send notification");
|