failproofai 1.0.2-beta.6 → 1.0.2-beta.8
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +6 -5
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__1qzqcio._.js → [externals]__1lt47k4._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +3 -3
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0mgrjnx._.js +10 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__128se8m._.js → [root-of-the-server]__1-wzs7f._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07gm3zl._.js → [root-of-the-server]__1n2ywfz._.js} +5 -22
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1tag8_-._.js → [root-of-the-server]__1wlvpe5._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_11fc-hb._.js → _0l7zv8b._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0no96tu._.js → _1h33neq._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +17 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me65._.js +3 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware.js +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
- package/.next/standalone/.next/static/chunks/{0931avh-06lj5.js → 0i3a6wf-f_yky.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1id7o44jjegf0.js → 0u2ojcw25c_np.js} +1 -1
- package/.next/standalone/.next/static/chunks/{276n-edifojbd.js → 11a_m8yksthtf.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0sdgnflvw8kta.js → 1ch5l9t2p16y4.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0h-3zffoy-_ji.js → 1n04wzsaes73g.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2pxr7nr1nyotn.js → 2iryw37qfqy5y.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2jfskwd2u8o5r.js → 34j7nmidlcuni.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3vu_7_eor1m-k.js → 3927pu4ss_l4k.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0p84npzxdgpc5.js → 3r0udrtpn78-e.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1mfzsja6ftim5.css → 40nr6ehj4p3cw.css} +1 -1
- package/.next/standalone/.next/static/chunks/{0z7au3njlak0j.js → 416zumre3fvfw.js} +1 -1
- package/.next/standalone/package.json +9 -9
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +831 -679
- package/dist/cli.mjs +9461 -7620
- package/dist/worker.mjs +6 -3
- package/package.json +9 -9
- package/scripts/build-policy-pack.mjs +28 -4
- package/src/audit/cli.ts +40 -39
- package/src/hooks/backfill-cli.ts +1 -1
- package/src/hooks/configure-wizard.ts +24 -10
- package/src/hooks/manager.ts +41 -6
- package/src/hooks/pack-cli.ts +827 -97
- package/src/hooks/pack-manifest.ts +34 -1
- package/src/hooks/pack-store.ts +208 -16
- package/src/hooks/tui.ts +194 -40
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15r6r7w._.js +0 -10
- /package/.next/standalone/.next/static/{mAYN9BOxWVFREnVp3yCHp → NgD5HvuyPxwgrpeIiafJL}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{mAYN9BOxWVFREnVp3yCHp → NgD5HvuyPxwgrpeIiafJL}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{mAYN9BOxWVFREnVp3yCHp → NgD5HvuyPxwgrpeIiafJL}/_ssgManifest.js +0 -0
package/src/hooks/tui.ts
CHANGED
|
@@ -108,6 +108,8 @@ const RADIO_OFF = "○";
|
|
|
108
108
|
export const CHECK_ON = "◼";
|
|
109
109
|
export const CHECK_OFF = "◻";
|
|
110
110
|
export const CARET = "❯";
|
|
111
|
+
/** The return key, as the multi-select hints already spell it. */
|
|
112
|
+
export const CARET_RETURN = "↵";
|
|
111
113
|
const MARK = "\u25AE\u25AE"; // ▮▮ — the brand mark, per the design system
|
|
112
114
|
|
|
113
115
|
// ── color ─────────────────────────────────────────────────────────────────
|
|
@@ -933,6 +935,24 @@ export function promptText(opts: PromptTextOptions): Promise<string | null> {
|
|
|
933
935
|
});
|
|
934
936
|
}
|
|
935
937
|
|
|
938
|
+
// A default nobody can see is a default nobody uses.
|
|
939
|
+
//
|
|
940
|
+
// `defaultValue` is applied on an empty submit and is otherwise INVISIBLE, so
|
|
941
|
+
// every prompt carrying one had to remember to spell it into its own hint —
|
|
942
|
+
// and the one where it mattered most, "Where should this publish?", spelled
|
|
943
|
+
// out the value while never saying that return was the key that took it.
|
|
944
|
+
// Somebody looking at a prefilled-looking placeholder types the whole thing
|
|
945
|
+
// out again. Owned here so a prompt cannot be added without it.
|
|
946
|
+
//
|
|
947
|
+
// Never for a masked prompt: those hold credentials, and the entire reason
|
|
948
|
+
// the characters are hidden is that the screen is being shared or recorded.
|
|
949
|
+
const hintText = [
|
|
950
|
+
opts.defaultValue && !opts.mask ? `${CARET_RETURN} ${opts.defaultValue}` : "",
|
|
951
|
+
opts.hint ?? "",
|
|
952
|
+
]
|
|
953
|
+
.filter(Boolean)
|
|
954
|
+
.join(" · ");
|
|
955
|
+
|
|
936
956
|
return new Promise((resolve) => {
|
|
937
957
|
let value = "";
|
|
938
958
|
const draw = (error?: string) => {
|
|
@@ -942,7 +962,7 @@ export function promptText(opts: PromptTextOptions): Promise<string | null> {
|
|
|
942
962
|
// steps aside as soon as there is a real answer to look at. Keeping both
|
|
943
963
|
// on one line put the example and the input side by side, which is the
|
|
944
964
|
// arrangement most likely to make somebody wonder which one is theirs.
|
|
945
|
-
const hint =
|
|
965
|
+
const hint = hintText && value.length === 0 ? ` ${c.dim(hintText)}` : "";
|
|
946
966
|
// Truncate to ONE physical row. `\r\x1b[2K` erases the row the cursor is
|
|
947
967
|
// on and nothing above it — so a line wider than the terminal wraps, the
|
|
948
968
|
// erase reaches only its last row, and every keystroke leaves the earlier
|
|
@@ -1254,9 +1274,14 @@ export function rule(label?: string, opts?: RenderOpts): string[] {
|
|
|
1254
1274
|
const { cols, c } = ctx(opts);
|
|
1255
1275
|
const width = Math.max(4, cols - INDENT.length * 2);
|
|
1256
1276
|
if (!label) return [`${INDENT}${c.dim("─".repeat(width))}`];
|
|
1257
|
-
const
|
|
1258
|
-
|
|
1259
|
-
|
|
1277
|
+
const tail = Math.max(3, width - `━━ ${label} `.length);
|
|
1278
|
+
// The one accent every sectioned surface carries: a pink lead into a bold
|
|
1279
|
+
// label. Decoration only — the glyphs and the spacing are identical without
|
|
1280
|
+
// colour, so a piped render and a painted one are the same width and say the
|
|
1281
|
+
// same thing. Changing it here moves `policies`, `harness`, `pack list`,
|
|
1282
|
+
// every `table` section and all twelve help screens together, which is the
|
|
1283
|
+
// reason they share this function instead of each drawing their own line.
|
|
1284
|
+
return [`${INDENT}${c.pink("━━")} ${c.bold(label)} ${c.dim("━".repeat(tail))}`];
|
|
1260
1285
|
}
|
|
1261
1286
|
|
|
1262
1287
|
export interface Row {
|
|
@@ -1524,52 +1549,181 @@ export interface HelpSpec {
|
|
|
1524
1549
|
usage: Array<[string, string?]>;
|
|
1525
1550
|
options?: Array<[string, string]>;
|
|
1526
1551
|
examples?: string[];
|
|
1527
|
-
/** Free lines
|
|
1552
|
+
/** Free lines above the first section. */
|
|
1528
1553
|
lead?: string[];
|
|
1529
1554
|
}
|
|
1530
1555
|
|
|
1531
1556
|
/**
|
|
1532
|
-
*
|
|
1557
|
+
* The description column for one block of entries, derived from its widest
|
|
1558
|
+
* described name and capped.
|
|
1533
1559
|
*
|
|
1534
|
-
*
|
|
1535
|
-
*
|
|
1536
|
-
*
|
|
1537
|
-
* column is computed here from the widest entry, capped so a long flag cannot
|
|
1538
|
-
* push every description off the right edge.
|
|
1560
|
+
* Its own step because the callers differ on the SCOPE they compute it over —
|
|
1561
|
+
* {@link helpBlock} across usage and options together, {@link helpScreen} per
|
|
1562
|
+
* section — and neither should be restating the cap or the floor.
|
|
1539
1563
|
*/
|
|
1540
|
-
export function
|
|
1564
|
+
export function helpColumn(entries: Array<[string, string?]>): number {
|
|
1565
|
+
// Only DESCRIBED entries set the column. A bare usage line — `failproofai
|
|
1566
|
+
// flush [--wait] [--timeout <secs>]`, which describes itself — is 44
|
|
1567
|
+
// characters and has nothing in the second column, so letting it vote pushed
|
|
1568
|
+
// every real description on the screen out to column 38.
|
|
1569
|
+
const named = entries.filter(([, d]) => d).map(([n]) => visibleWidth(n));
|
|
1570
|
+
return Math.min(34, Math.max(12, ...named));
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
/** `<name> <description>` at a column the caller fixed. */
|
|
1574
|
+
export function helpEntries(
|
|
1575
|
+
items: Array<[string, string?]>,
|
|
1576
|
+
nameWidth: number,
|
|
1577
|
+
opts?: RenderOpts,
|
|
1578
|
+
): string[] {
|
|
1541
1579
|
const { cols, c } = ctx(opts);
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
}
|
|
1562
|
-
continue;
|
|
1580
|
+
const out: string[] = [];
|
|
1581
|
+
for (const [raw, description] of items) {
|
|
1582
|
+
// Pink is what you TYPE, dim is what it means, bold is the section it sits
|
|
1583
|
+
// in. Three tones, the same three on every screen, so a flag looks like a
|
|
1584
|
+
// flag whether you found it on `publish --help` or on the index. Decoration
|
|
1585
|
+
// only: the column already separates the two halves, so the screen reads
|
|
1586
|
+
// the same piped to a file or under NO_COLOR.
|
|
1587
|
+
const name = c.pink(raw);
|
|
1588
|
+
if (!description) {
|
|
1589
|
+
out.push(`${INDENT}${name}`);
|
|
1590
|
+
continue;
|
|
1591
|
+
}
|
|
1592
|
+
const budget = Math.max(12, cols - INDENT.length * 2 - nameWidth - 2);
|
|
1593
|
+
const [first, ...rest] = wrap(description, budget);
|
|
1594
|
+
// A name wider than the column takes its own line rather than shoving the
|
|
1595
|
+
// description out — the top-level help has several of these today.
|
|
1596
|
+
if (visibleWidth(raw) > nameWidth) {
|
|
1597
|
+
out.push(`${INDENT}${name}`);
|
|
1598
|
+
for (const line of [first, ...rest]) {
|
|
1599
|
+
if (line !== undefined) out.push(`${INDENT}${" ".repeat(nameWidth)} ${c.dim(line)}`);
|
|
1563
1600
|
}
|
|
1564
|
-
|
|
1565
|
-
for (const line of rest) out.push(`${INDENT}${" ".repeat(nameWidth)} ${c.dim(line)}`);
|
|
1601
|
+
continue;
|
|
1566
1602
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1603
|
+
// Padded on the VISIBLE width, so a painted name still lands the column
|
|
1604
|
+
// where an unpainted one does.
|
|
1605
|
+
const gap = nameWidth - visibleWidth(raw);
|
|
1606
|
+
out.push(`${INDENT}${name}${" ".repeat(gap)} ${c.dim(first ?? "")}`);
|
|
1607
|
+
for (const line of rest) out.push(`${INDENT}${" ".repeat(nameWidth)} ${c.dim(line)}`);
|
|
1608
|
+
}
|
|
1609
|
+
return out;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
/**
|
|
1613
|
+
* A usage/options/examples block, on one column across all three.
|
|
1614
|
+
*
|
|
1615
|
+
* The plain shape, for a surface with nothing else to say. A screen with prose
|
|
1616
|
+
* sections, a heading, or a footer wants {@link helpScreen}, which is what the
|
|
1617
|
+
* twelve `--help` screens use.
|
|
1618
|
+
*/
|
|
1619
|
+
export function helpBlock(spec: HelpSpec, opts?: RenderOpts): string[] {
|
|
1620
|
+
const nameWidth = helpColumn([...spec.usage, ...(spec.options ?? [])]);
|
|
1621
|
+
const section = (label: string, body: string[]): string[] =>
|
|
1622
|
+
body.length === 0 ? [] : [...rule(label, opts), ...body];
|
|
1569
1623
|
return stack(
|
|
1570
1624
|
spec.lead ? spec.lead.map((l) => `${INDENT}${l}`) : null,
|
|
1571
|
-
section("
|
|
1572
|
-
section("
|
|
1573
|
-
section("
|
|
1625
|
+
section("usage", helpEntries(spec.usage, nameWidth, opts)),
|
|
1626
|
+
section("options", helpEntries(spec.options ?? [], nameWidth, opts)),
|
|
1627
|
+
section("examples", (spec.examples ?? []).map((e) => `${INDENT}${e}`)),
|
|
1574
1628
|
);
|
|
1575
1629
|
}
|
|
1630
|
+
|
|
1631
|
+
/**
|
|
1632
|
+
* Help is the one family of screens read at every width that belongs to no
|
|
1633
|
+
* terminal in particular. Capped at 80 so `publish --help` is the same shape in
|
|
1634
|
+
* a maximised window as in a tmux pane — and never wider than the terminal it
|
|
1635
|
+
* is actually in, so the cap can only ever narrow.
|
|
1636
|
+
*/
|
|
1637
|
+
export const HELP_COLS = 80;
|
|
1638
|
+
|
|
1639
|
+
/** {@link optsFor}, capped to {@link HELP_COLS}. Every help screen uses this. */
|
|
1640
|
+
export function helpOptsFor(stdout: TTYOut = process.stdout): Required<RenderOpts> {
|
|
1641
|
+
const base = optsFor(stdout);
|
|
1642
|
+
return { cols: Math.min(base.cols, HELP_COLS), color: base.color };
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
export interface HelpHeading {
|
|
1646
|
+
/** The command being documented. Omitted for the top-level index. */
|
|
1647
|
+
command?: string;
|
|
1648
|
+
version: string;
|
|
1649
|
+
/** One line: what this command is for. */
|
|
1650
|
+
tagline: string;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
/**
|
|
1654
|
+
* The two lines every help screen opens with.
|
|
1655
|
+
*
|
|
1656
|
+
* The wordmark carries the same pink on `il` that {@link renderBrandLogo} tints,
|
|
1657
|
+
* so a help screen and the wizard are visibly one product rather than two that
|
|
1658
|
+
* happen to ship together. The version sits right-aligned and dim because it is
|
|
1659
|
+
* the fact you want when a help screen and its binary disagree, and the fact you
|
|
1660
|
+
* never want in the way otherwise.
|
|
1661
|
+
*/
|
|
1662
|
+
export function helpHeading(spec: HelpHeading, opts?: RenderOpts): string[] {
|
|
1663
|
+
const { cols, c } = ctx(opts);
|
|
1664
|
+
const mark = `${c.bold("fa")}${c.pink("il")}${c.bold("proofai")}`;
|
|
1665
|
+
const left = `${INDENT}${mark}${spec.command ? ` ${c.bold(spec.command)}` : ""}`;
|
|
1666
|
+
const right = c.dim(`v${spec.version}`);
|
|
1667
|
+
const gap = cols - visibleWidth(left) - visibleWidth(right) - INDENT.length;
|
|
1668
|
+
// Too narrow for both: the version goes under rather than wrapping into the
|
|
1669
|
+
// middle of the name, where it reads as part of the command.
|
|
1670
|
+
const head = gap < 2 ? [left, `${INDENT}${right}`] : [left + " ".repeat(gap) + right];
|
|
1671
|
+
return [...head, ...note(spec.tagline, opts)];
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
/**
|
|
1675
|
+
* A section of a help screen: a table of names, a paragraph, or lines that are
|
|
1676
|
+
* already laid out. Every one of them gets the same `rule` heading, which is
|
|
1677
|
+
* what makes twelve screens one screen.
|
|
1678
|
+
*/
|
|
1679
|
+
export type HelpSection =
|
|
1680
|
+
/** A table of names. `after` is a paragraph under it, in the same section —
|
|
1681
|
+
* the alternative was a second heading over three lines of caveat, or an
|
|
1682
|
+
* unlabelled `rule` that read as the screen having lost its place. */
|
|
1683
|
+
| { label: string; entries: Array<[string, string?]>; after?: string[] }
|
|
1684
|
+
| { label: string; prose: string }
|
|
1685
|
+
| { label: string; lines: string[] };
|
|
1686
|
+
|
|
1687
|
+
export interface HelpScreenSpec extends HelpHeading {
|
|
1688
|
+
sections: HelpSection[];
|
|
1689
|
+
/** Dim closing lines — where to read more. */
|
|
1690
|
+
footer?: string[];
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
/**
|
|
1694
|
+
* A whole `--help`, assembled the same way twelve times.
|
|
1695
|
+
*
|
|
1696
|
+
* Before this, every screen was its own template literal: `USAGE` here and
|
|
1697
|
+
* `Usage:` there, a description column hand-counted per file, no version on the
|
|
1698
|
+
* page, and no colour on any of them while the index it was reached from had
|
|
1699
|
+
* all three. The screens still say exactly what their authors wrote — this owns
|
|
1700
|
+
* only the shape.
|
|
1701
|
+
*/
|
|
1702
|
+
export function helpScreen(spec: HelpScreenSpec, opts?: RenderOpts): string[] {
|
|
1703
|
+
const { cols, c } = ctx(opts);
|
|
1704
|
+
const width = Math.max(12, cols - INDENT.length * 2);
|
|
1705
|
+
const groups: Array<string[] | null> = [helpHeading(spec, opts)];
|
|
1706
|
+
for (const section of spec.sections) {
|
|
1707
|
+
// Per SECTION, not per screen. One column across the whole page is what a
|
|
1708
|
+
// screen of like-shaped entries wants, and it is exactly wrong on a screen
|
|
1709
|
+
// that has both: `failproofai policies show <owner>/<repo>` is 40 columns
|
|
1710
|
+
// and `--all` is 5, so a shared column left every flag description hanging
|
|
1711
|
+
// 34 columns out with nothing under it. What made two screens read as two
|
|
1712
|
+
// products was the INDENT and the heading, and those are shared here.
|
|
1713
|
+
const body =
|
|
1714
|
+
"entries" in section
|
|
1715
|
+
? [
|
|
1716
|
+
...helpEntries(section.entries, helpColumn(section.entries), opts),
|
|
1717
|
+
...(section.after?.length
|
|
1718
|
+
? ["", ...section.after.map((l) => (l.trim() === "" ? "" : `${INDENT}${l}`))]
|
|
1719
|
+
: []),
|
|
1720
|
+
]
|
|
1721
|
+
: "prose" in section
|
|
1722
|
+
? wrap(section.prose, width).map((l) => `${INDENT}${l}`)
|
|
1723
|
+
: section.lines.map((l) => (l.trim() === "" ? "" : `${INDENT}${l}`));
|
|
1724
|
+
if (body.length === 0) continue;
|
|
1725
|
+
groups.push([...rule(section.label, opts), ...body]);
|
|
1726
|
+
}
|
|
1727
|
+
if (spec.footer?.length) groups.push(spec.footer.map((l) => `${INDENT}${c.dim(l)}`));
|
|
1728
|
+
return stack(...groups);
|
|
1729
|
+
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
module.exports=[57764,(a,b,c)=>{b.exports=a.x("node:url",()=>require("node:url"))},92509,(a,b,c)=>{b.exports=a.x("url",()=>require("url"))},15638,a=>{"use strict";var b=a.i(50227),c=a.i(54799),d=a.i(2157),e=a.i(12714),f=a.i(57764),g=a.i(66680),h=a.i(10695),i=a.i(32352),j=a.i(84948);a.i(28120);var k=a.i(98378),l=a.i(69839);a.i(75818);let m="__FAILPROOFAI_LOADING_HOOKS__",n=/policies\.(js|mjs|ts)$/,o=0,p=new Map;async function q(a){let b,c,d=Number.isFinite(c=Number(process.env.FAILPROOFAI_POLICY_LOAD_TIMEOUT_MS))&&c>0?c:1e4;try{await Promise.race([import(a),new Promise((a,c)=>{b=setTimeout(()=>c(Error(`timed out loading module after ${d}ms`)),d),b.unref?.()})])}finally{b&&clearTimeout(b)}}async function r(a,d){let e=globalThis;e[m]=!0;let g=[];try{let b=await (0,j.findDistIndex)(),e=b?(0,f.pathToFileURL)(b).href:null,h=++o,k=`${j.TMP_SUFFIX}.${process.pid}.${h}.${(0,c.randomUUID)()}.mjs`;g=await (0,j.rewriteFileTree)(a,e,b,k,d?.verifyEntrySha);let l=await s(g,k),m=p.get(a);if(m?.fingerprint===l){for(let a of m.hooks)i.customPolicies.add({...a});return null}let n=a+k,r=(0,f.pathToFileURL)(n).href,t=(0,i.getCustomHooks)().length;return await q(r),p.size>=500&&p.clear(),p.set(a,{fingerprint:l,hooks:(0,i.getCustomHooks)().slice(t).map(a=>({...a}))}),null}catch(f){let c=f instanceof Error?f.message:String(f),e=/Cannot find module|MODULE_NOT_FOUND|ENOENT/i.test(c)?"module_not_found":/SyntaxError|Unexpected token/i.test(c)?"syntax_error":/timed out loading module/i.test(c)?"load_timeout":"runtime_error";if((0,k.trackHookEvent)((0,l.getInstanceId)(),"custom_hooks_load_error",{error_type:e,is_convention:!!d?.conventionScope,convention_scope:d?.conventionScope??null,file_basename:(0,b.basename)(a)}),d?.strict)throw Error(`Failed to load custom hooks from ${a}: ${c}`);return(0,h.hookLogError)(`failed to load custom hooks from ${a}: ${c}`),{type:e,reason:c}}finally{e[m]=!1,await (0,j.cleanupTmpFiles)(g)}}async function s(a,b){let c=(0,g.createHash)("sha256");for(let d of[...a].sort()){c.update(d.replaceAll(b,j.TMP_SUFFIX));let a=await (0,e.readFile)(d,"utf8");c.update(a.replaceAll(b,j.TMP_SUFFIX))}return c.digest("hex")}async function t(a,c){if(!a)return[];let e=(0,b.isAbsolute)(a)?a:(0,b.resolve)(c?.sessionCwd??process.cwd(),a);if(!(0,d.existsSync)(e)){if(c?.strict)throw Error(`Custom hooks file not found: ${e}`);return(0,h.hookLogWarn)(`customPoliciesPath not found: ${e}`),[]}return(0,i.clearCustomHooks)(),await r(e,c),(0,i.getCustomHooks)()}a.s(["conventionPolicyId",0,function(a,b,c){return`convention:${a}:${b}:${c}`},"customPolicyId",0,function(a,b){return`custom:${a}:${b}`},"discoverPolicyFiles",0,function(a){if(!(0,d.existsSync)(a))return[];try{return(0,d.readdirSync)(a,{withFileTypes:!0}).filter(a=>a.isFile()&&n.test(a.name)).sort((a,b)=>a.name.localeCompare(b.name)).map(c=>(0,b.resolve)(a,c.name))}catch{return[]}},"loadCustomHooks",0,t])},32352,84948,a=>{"use strict";let b="__failproofai_custom_hooks__";function c(){let a=globalThis;return Array.isArray(a[b])||(a[b]=[]),a[b]}a.s(["clearCustomHooks",0,function(){globalThis[b]=[]},"customPolicies",0,{add(a){c().push(a)}},"getCustomHooks",0,function(){return c()}],32352);var d=a.i(24868),e=a.i(46786),f=a.i(14747),g=a.i(92509),h=a.i(54799),i=a.i(75818),j=a.i(10695);let k=".__failproofai_tmp__.mjs",l=/(?:import\s+(?:[\s\S]*?\s+from\s+)?|export\s+(?:[\s\S]*?\s+from\s+))(['"])(\.\.?\/[^'"]+)\1/g,m=/require\s*\(\s*(['"])(\.\.?\/[^'"]+)\1\s*\)/g;async function n(a){try{return await (0,d.access)(a),!0}catch{return!1}}async function o(){let a=process.env.FAILPROOFAI_DIST_PATH;if(a){let b=(0,f.resolve)(a,"index.js");if(await n(b))return b}for(let a of[(0,f.resolve)((0,f.dirname)(process.execPath),"..","assets","dist","index.js"),(0,f.resolve)(process.cwd(),"dist","index.js"),(0,f.resolve)(process.cwd(),"node_modules","failproofai","dist","index.js")])if(await n(a))return a;return null}async function p(a,b){let c=(0,f.resolve)(a,b);for(let a of[c,`${c}.js`,`${c}.mjs`,`${c}.ts`,(0,f.resolve)(c,"index.js")])if(await n(a))return a;return null}async function q(a,b,c,e){let g=(0,f.join)(a,b);return await (0,d.writeFile)(g,c,{encoding:"utf-8",mode:384,...e?{flag:"wx"}:{}}),g}async function r(a,b,c=k){let f=`import _cjs from '${b}';
|
|
2
|
-
export const customPolicies = _cjs.customPolicies;
|
|
3
|
-
export const getCustomHooks = _cjs.getCustomHooks;
|
|
4
|
-
export const clearCustomHooks = _cjs.clearCustomHooks;
|
|
5
|
-
export const allow = _cjs.allow;
|
|
6
|
-
export const deny = _cjs.deny;
|
|
7
|
-
export const instruct = _cjs.instruct;
|
|
8
|
-
export default _cjs;`,h=`failproofai-dist${c}.shim.mjs`;try{let a=(0,i.shimsDir)();await (0,d.mkdir)(a,{recursive:!0,mode:448});let b=await (0,d.lstat)(a),c="function"==typeof process.getuid?process.getuid():null;if(!b.isDirectory()||b.isSymbolicLink()||null!==c&&b.uid!==c||63&b.mode)throw Error(`${a} is not a private directory owned by this user`);let e=await q(a,h,f,!1);return{shimPath:e,shimUrl:(0,g.pathToFileURL)(e).href}}catch(a){(0,j.hookLogWarn)(`policy shim directory unusable (${a instanceof Error?a.message:String(a)}); falling back to ${(0,e.tmpdir)()}`)}let l=await q((0,e.tmpdir)(),h,f,!0);return{shimPath:l,shimUrl:(0,g.pathToFileURL)(l).href}}async function s(a,b,c,e=k,g){let i=[a],j=new Set,n=[],o=null;if(c&&b){let a=await r(c,b,e);n.push(a.shimPath),o=a.shimUrl}for(;i.length>0;){let b,k=i.shift();if(j.has(k))continue;if(j.add(k),g&&k===a){let a=await (0,d.readFile)(k),c=(0,h.createHash)("sha256").update(a).digest("hex");if(c!==g)throw Error(`cloud-managed policy failed integrity re-verification at load: expected ${g}, got ${c}`);b=a.toString("utf-8")}else b=await (0,d.readFile)(k,"utf-8");o&&(b=b.replace(/from\s+(['"])(?:claudeye|failproofai)\1/g,`from '${o}'`)),c&&(b=b.replace(/require\s*\(\s*(['"])(?:claudeye|failproofai)\1\s*\)/g,`require('${c.replace(/\\/g,"\\\\")}')`));let q=(0,f.dirname)(k),r=new Map;for(let a of[l,m]){let c,d=new RegExp(a.source,a.flags);for(;null!==(c=d.exec(b));){let a=c[2];if(r.has(a))continue;let b=await p(q,a);if(!b)continue;j.has(b)||i.includes(b)||i.push(b);let d=(0,f.relative)(q,b+e).split("\\").join("/");d.startsWith(".")||(d="./"+d),r.set(a,d)}}for(let a of[...r.keys()].sort((a,b)=>b.length-a.length)){let c=r.get(a),d=a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");b=(b=b.replace(RegExp(`'${d}'`,"g"),`'${c}'`)).replace(RegExp(`"${d}"`,"g"),`"${c}"`)}let s=k+e;await (0,d.writeFile)(s,b,"utf-8"),n.push(s)}return n}async function t(a){for(let b of a)try{await (0,d.unlink)(b)}catch{}}a.s(["TMP_SUFFIX",0,k,"cleanupTmpFiles",0,t,"findDistIndex",0,o,"rewriteFileTree",0,s],84948)},28120,98378,a=>{"use strict";var b=a.i(2157),c=a.i(50227),d=a.i(60526),e=a.i(10695),f=a.i(75818);function g(a){if(!(0,b.existsSync)(a))return{};try{let c=(0,b.readFileSync)(a,"utf8");return JSON.parse(c)}catch(b){return(0,e.hookLogWarn)(`failed to parse config at ${a}: ${b instanceof Error?b.message:String(b)}`),{}}}function h(a){let e=(0,d.homedir)(),f=(0,c.resolve)(a);for(;f!==e;){let a=(0,c.resolve)(f,".failproofai");try{if((0,b.statSync)(a).isDirectory())return f}catch{}let d=(0,c.dirname)(f);if(d===f)break;f=d}return(0,c.resolve)(a)}function i(){return(0,f.globalPolicyConfigFile)()}function j(a,b){switch(a){case"user":return(0,f.globalPolicyConfigFile)();case"project":return(0,c.resolve)(h(b??process.cwd()),".failproofai","policies-config.json");case"local":return(0,c.resolve)(h(b??process.cwd()),".failproofai","policies-config.local.json")}}a.s(["configuredCustomPolicyPaths",0,function(a){return a.customPoliciesPaths??(a.customPoliciesPath?[a.customPoliciesPath]:[])},"findProjectConfigDir",0,h,"readHooksConfig",0,function(){let a=i();if(!(0,b.existsSync)(a))return{enabledPolicies:[]};try{let c=(0,b.readFileSync)(a,"utf8");return JSON.parse(c)}catch(b){return(0,e.hookLogWarn)(`failed to parse config at ${a}: ${b instanceof Error?b.message:String(b)}`),{enabledPolicies:[]}}},"readMergedHooksConfig",0,function(a){let b=h(a??process.cwd()),d=(0,c.resolve)(b,".failproofai","policies-config.json"),e=(0,c.resolve)(b,".failproofai","policies-config.local.json"),i=(0,f.globalPolicyConfigFile)(),j=g(d),k=g(e),l=g(i),m=new Set([...j.enabledPolicies??[],...k.enabledPolicies??[],...l.enabledPolicies??[]]),n={};for(let a of[j,k,l])if(a.policyParams)for(let[b,c]of Object.entries(a.policyParams))b in n||(n[b]=c);let o=[j,k,l].map(a=>void 0!==a.customPoliciesPaths?a.customPoliciesPaths:void 0!==a.customPoliciesPath?[a.customPoliciesPath]:void 0).find(a=>void 0!==a),p=new Set([...j.disabledCustomPolicies??[],...k.disabledCustomPolicies??[],...l.disabledCustomPolicies??[]]),q=j.customPoliciesEnabled??k.customPoliciesEnabled??l.customPoliciesEnabled,r=j.llm??k.llm??l.llm;return{enabledPolicies:[...m],...Object.keys(n).length>0?{policyParams:n}:{},...void 0!==o?{customPoliciesPaths:o}:{},...p.size?{disabledCustomPolicies:[...p]}:{},...void 0!==q?{customPoliciesEnabled:q}:{},...void 0!==r?{llm:r}:{}}},"readScopedHooksConfig",0,function(a,c){let d=j(a,c);if(!(0,b.existsSync)(d))return{enabledPolicies:[]};try{let a=(0,b.readFileSync)(d,"utf8");return JSON.parse(a)}catch(a){return(0,e.hookLogWarn)(`failed to parse config at ${d}: ${a instanceof Error?a.message:String(a)}`),{enabledPolicies:[]}}},"writeHooksConfig",0,function(a){let d=i(),e=(0,c.dirname)(d);(0,b.existsSync)(e)||(0,b.mkdirSync)(e,{recursive:!0}),(0,b.writeFileSync)(d,JSON.stringify(a,null,2)+"\n","utf8")},"writeScopedHooksConfig",0,function(a,d,e){let f=j(d,e),g=(0,c.dirname)(f);(0,b.existsSync)(g)||(0,b.mkdirSync)(g,{recursive:!0}),(0,b.writeFileSync)(f,JSON.stringify(a,null,2)+"\n","utf8")}],28120);var k=a.i(12072),l=a.i(79779),m=a.i(31920);let n=l.POSTHOG_API_KEY,o=new Set;async function p(a,b,c){let d=JSON.stringify({api_key:process.env.FAILPROOFAI_POSTHOG_KEY??n,event:b,distinct_id:a,properties:{...c,$lib:"failproofai-hooks",failproofai_version:k.version,product:l.POSTHOG_PRODUCT}});try{await fetch(process.env.FAILPROOFAI_POSTHOG_HOST?`${process.env.FAILPROOFAI_POSTHOG_HOST}/capture/`:"https://us.i.posthog.com/capture/",{method:"POST",headers:{"Content-Type":"application/json"},body:d,signal:AbortSignal.timeout(5e3)})}catch{}}async function q(a,b,c){if(!(0,m.isTelemetryEnabled)())return;let d=p(a,b,c);o.add(d),d.finally(()=>o.delete(d)),await d}a.s(["trackHookEvent",0,q],98378)}];
|
|
9
|
-
|
|
10
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__15r6r7w._.js.map
|
|
File without changes
|
|
File without changes
|
|
File without changes
|