From 2061faa35b078f68d0c7551131dc719ff75f74ec Mon Sep 17 00:00:00 2001 From: draw me an elephant <68925779+drawmeanelephant@users.noreply.github.com> Date: Sun, 13 Sep 2026 14:28:00 -0400 Subject: [PATCH 1/2] fix(cli): document the shipped commands and drop a stray backslash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The published CLI reference opened by claiming six core commands while the binary also ships `graph`, `proof verify`, and `init`. `proof verify` is the gate the Pages deploy runs, so the one page that documents the surface was the one page that omitted it. The three are added with their flags verified against src/cli.zig rather than taken from the contract prose. `--help` also printed a doubled backslash in its Modes list, because nothing read the help text at all. The usage string is now a named value with a test asserting it contains no backslash and lists every shipped command, so the typo cannot return unnoticed. ๐Ÿค– Generated with Codebuff Co-Authored-By: Codebuff --- content/reference/commands.md | 54 +++++++++++++++++-- docs/changelog.d/995-cli-reference-current.md | 10 ++++ src/cli.zig | 43 +++++++++++++-- 3 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 docs/changelog.d/995-cli-reference-current.md diff --git a/content/reference/commands.md b/content/reference/commands.md index d03a14bd..d8370538 100644 --- a/content/reference/commands.md +++ b/content/reference/commands.md @@ -18,9 +18,11 @@ This page is lookup. For which command to run first, see -The public CLI has six core commands plus the `standard-site` and `nostr` -families. With no command, Boris runs `build` and publishes an HTML site -under `dist/` โ€” the default target, not the only one. +The public CLI is a small command set plus the `standard-site` and `nostr` +families: `build`, `validate`, `watch`, `check`, `impact`, `plan`, +`recipe-scale`, `graph`, `proof verify`, and `init`. With no command, Boris +runs `build` and publishes an HTML site under `dist/` โ€” the default target, +not the only one. ## Commands at a glance @@ -37,6 +39,9 @@ under `dist/` โ€” the default target, not the only one. | `nostr sign` | Sign a plan artifact into a signed-event bundle (key once via stdin) | No; bundle JSON on stdout or `--out PATH` | | `nostr publish` | Send the exact signed events to the plan's relays over WebSocket | No; report JSON on stdout or `--out PATH` | | `recipe-scale --id PAGE --factor TEXT` | Print a derived Cooklang scale view | No; view JSON on stdout or `--out PATH` | +| `graph` | Render the frozen graph as Mermaid (default) or Graphviz DOT | No; render on stdout or `--out PATH` | +| `proof verify` | Apply the publication-check policy to a committed `checks.json` | No; verdict report on stderr | +| `init [DIR]` | Materialize a deterministic starter site and verify that it compiles | A starter tree into `DIR` (must be empty) | ## Basic usage @@ -209,6 +214,47 @@ for the normative contract. | `--report PATH` | Write the analysis report to PATH instead of stderr (check/impact) | | `--quiet` | Suppress normal progress and diagnostic text where supported | +## Graph renders + +```bash +./zig-out/bin/boris graph --input content --format mermaid +./zig-out/bin/boris graph --input content --format dot --out graph.dot +``` + +`graph` renders the frozen content graph read-only: Mermaid by default, or +Graphviz DOT with `--format dot`. It writes nothing unless `--out PATH` names a +single file, and it never mutates the graph. See +[`graph-formats.md`](https://github.com/drawmeanelephant/boris/blob/main/docs/contracts/graph-formats.md) +for the normative render contract. + +## Publication-check policy + +```bash +./zig-out/bin/boris proof verify --html-dir dist +./zig-out/bin/boris proof verify --html-dir dist --max-warnings 0 +``` + +`proof verify` applies the publication-check severity policy to the committed +`checks.json` of one target. It writes no artifacts โ€” the verdict goes to +stderr โ€” and findings beyond the configured caps exit `1`. `--max-errors N`, +`--max-warnings N`, and repeatable `--block-code CODE` select the policy. This +is the gate the GitHub Pages workflow runs before it deploys, so running it +locally predicts the deploy. + +## Starter site + +```bash +./zig-out/bin/boris init my-site +``` + +`init [DIR]` materializes a fixed starter tree โ€” three content pages that +exercise the graph, a closed-slot theme whose layout ships the rendered-search +client, and the two publication profiles โ€” and then compiles it through the +normal HTML pipeline into a probe directory that is removed again. `DIR` must +be empty or not exist, and the tree is byte-deterministic. Exit `0` means the +starter was both materialized and compiled; a probe failure removes the tree +and exits `1`, and a target outside the workspace skips the probe and says so. + ## Publication profiles ```bash @@ -244,7 +290,7 @@ workflow plus `plan --profile` for the normalized location. | Code | Meaning | |---:|---| | `0` | Command completed successfully | -| `1` | Content/graph error, or a failing `check` health finding | +| `1` | Content/graph error, a failing `check` health finding, or a `proof verify` policy failure | | `2` | Usage error, missing value, or conflicting flags | | `3` | I/O or other system failure | diff --git a/docs/changelog.d/995-cli-reference-current.md b/docs/changelog.d/995-cli-reference-current.md new file mode 100644 index 00000000..922a76a3 --- /dev/null +++ b/docs/changelog.d/995-cli-reference-current.md @@ -0,0 +1,10 @@ +### Fixed + +- `boris --help` no longer prints a stray backslash on the `recipe-scale` mode + line โ€” a doubled multiline marker that shipped because nothing read the help + text, which is now a named constant with a test over its shape โ€” and the + interactive CLI reference documents the three shipped commands it was missing + (`graph`, `proof verify`, and `init`) instead of describing a + six-command surface. Links: [the command + reference](/content/reference/commands.md), [the CLI + contract](/docs/contracts/cli.md). diff --git a/src/cli.zig b/src/cli.zig index 7d5f31c1..1f3785e3 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -2583,8 +2583,11 @@ fn takeValueAllowEmpty( return args[i.*]; } -pub fn printUsage() void { - std.debug.print( +/// The public CLI help text. It is a named const rather than an inline literal +/// inside the printer so a test can assert its shape: nothing read this text, +/// which is how a doubled multiline marker survived on one mode line and +/// printed a stray backslash in `boris --help`. +pub const usage_text = \\Boris โ€” Zig content compiler (HTML site + IR + optional RAG) \\ \\Usage: boris [options] @@ -2596,7 +2599,7 @@ pub fn printUsage() void { \\ check Read-only graph health report (findings do not fail by default) \\ impact Read-only transitive impact report for a page \\ plan Emit a normalized publication plan (no publication) - \\ \\ recipe-scale Print a derived Cooklang scale view (no rewrite) + \\ recipe-scale Print a derived Cooklang scale view (no rewrite) \\ graph Read-only graph render: Mermaid (default) or Graphviz DOT \\ proof verify Fail when committed publication-check findings exceed policy \\ standard-site publish One-shot Standard.site publish (stored session + reconcile; never implicit) @@ -2796,7 +2799,10 @@ pub fn printUsage() void { \\ values fail validation). A draft renders to its .html files but is \\ excluded from nav, search, sitemap, RSS, and publication projections. \\ - , .{}); +; + +pub fn printUsage() void { + std.debug.print("{s}", .{usage_text}); } /// Focused usage for the `standard-site` family. `boris standard-site` with @@ -3098,6 +3104,35 @@ const expectEqual = std.testing.expectEqual; const expectEqualStrings = std.testing.expectEqualStrings; const expectError = std.testing.expectError; +test "usage: the public help text is well-formed and lists the shipped commands" { + // Regression: a doubled multiline marker on the `recipe-scale` mode line + // printed a stray backslash into `boris --help`. Nothing read this text, so + // assert the two properties that would have caught it. + try std.testing.expect(std.mem.indexOfScalar(u8, usage_text, '\\') == null); + + // Every shipped command must be discoverable from the Modes list: this text + // and the reference page are the two places a user looks first. + const commands = [_][]const u8{ + "build", + "validate", + "watch", + "check", + "impact", + "plan", + "recipe-scale", + "graph", + "proof verify", + "init", + "standard-site publish", + "nostr plan", + }; + for (commands) |name| { + const line = try std.fmt.allocPrint(std.testing.allocator, " {s}", .{name}); + defer std.testing.allocator.free(line); + try std.testing.expect(std.mem.indexOf(u8, usage_text, line) != null); + } +} + test "parse: default is HTML mode" { var o = try parseOptions(std.testing.allocator, &.{"boris"}); defer o.deinit(std.testing.allocator); From 750ec1df93e01a920f6d56d0c5116ec0cce000fa Mon Sep 17 00:00:00 2001 From: draw me an elephant <68925779+drawmeanelephant@users.noreply.github.com> Date: Sun, 13 Sep 2026 14:32:21 -0400 Subject: [PATCH 2/2] style(cli): apply zig fmt to the usage text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extracting the usage string into a const moved its continuation lines one indent level out, and I did not re-run the formatter, so CI's Format check failed before it reached Build or Test. This commit is the formatter's own output and nothing else. The string's content is unchanged: `boris --help` output is byte-identical before and after (14329 bytes, verified by diffing the two builds), because Zig strips the whitespace preceding each `\\` marker. ๐Ÿค– Generated with Codebuff Co-Authored-By: Codebuff --- src/cli.zig | 422 ++++++++++++++++++++++++++-------------------------- 1 file changed, 211 insertions(+), 211 deletions(-) diff --git a/src/cli.zig b/src/cli.zig index 1f3785e3..ce00bada 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -2588,217 +2588,217 @@ fn takeValueAllowEmpty( /// which is how a doubled multiline marker survived on one mode line and /// printed a stray backslash in `boris --help`. pub const usage_text = - \\Boris โ€” Zig content compiler (HTML site + IR + optional RAG) - \\ - \\Usage: boris [options] - \\ - \\Modes: - \\ build Build the HTML site (default command) - \\ validate Validate selected HTML source/config without publication - \\ watch Build HTML, then watch and rebuild on changes - \\ check Read-only graph health report (findings do not fail by default) - \\ impact Read-only transitive impact report for a page - \\ plan Emit a normalized publication plan (no publication) - \\ recipe-scale Print a derived Cooklang scale view (no rewrite) - \\ graph Read-only graph render: Mermaid (default) or Graphviz DOT - \\ proof verify Fail when committed publication-check findings exceed policy - \\ standard-site publish One-shot Standard.site publish (stored session + reconcile; never implicit) - \\ standard-site plan Emit the deterministic Standard.site plan offline (no network) - \\ standard-site records Dump the full canonical record payloads offline (no network) - \\ standard-site verify Cross-check the built head links + well-known file offline (no network) - \\ standard-site login Authorize a DID or handle and persist the session - \\ standard-site sessions List persisted sessions (DID, flavor, PDS; no secrets) - \\ standard-site logout Remove a persisted session (secure erase; does not revoke) - \\ standard-site smoke Live interop smoke against a real PDS (manual, opt-in; never in CI) - \\ nostr plan Emit the offline Nostr NIP-23 publication plan (no signing, no relay) - \\ nostr sign Sign a plan artifact into a signed-event bundle (offline; key via stdin) - \\ nostr publish Send a signed-event bundle to the plan's relays; writes the report - \\ init [DIR] Write a starter site (content, theme, profile) into DIR (default: .) - \\ (no command) Same as build - \\ standard-site publish options: - \\ --profile PATH Standard.site publication profile (required) - \\ --plan PATH Committed standard-site plan to validate (fail closed on drift) - \\ --out PATH Evidence artifact path (default: stdout) - \\ --prune Explicit prune authority (ANDs with the profile prune flag) - \\ --source-commit C Source commit recorded in the evidence bindings - \\ standard-site plan options: - \\ --profile PATH Standard.site publication profile (required) - \\ --out PATH Plan artifact path (default: stdout) - \\ standard-site records options: - \\ --profile PATH Standard.site publication profile (required) - \\ --out PATH Records artifact path (default: stdout) - \\ standard-site verify options: - \\ --profile PATH Standard.site publication profile (required) - \\ --dist DIR Built output directory to check (default: dist) - \\ --out PATH Verify result artifact path (default: stdout) - \\ standard-site login/logout options: - \\ --did DID AT Protocol DID to authorize (login) or forget (logout) - \\ --handle HANDLE AT Protocol handle for login --app-password, logout, or smoke - \\ --app-password Opt-in app-password login (broad account write; never OAuth scope) - \\ standard-site smoke options: - \\ --did DID Test identity DID (or use --handle) - \\ --namespace NAME Unique rkey namespace prefix (default: clock-derived) - \\ --surface-url URL Served verification-surface origin to check (optional) - \\ --indexer URL Indexer/AppView origin observed non-normatively (optional) - \\ --out PATH Smoke result artifact path (default: stdout) - \\ standard-site options (all subcommands): - \\ --session-root PATH Override the persistent session store root - \\ --profile PATH Publication profile: emit Standard.site verification and/or Nostr naddr head links - \\ --html Explicit HTML site mode โ†’ --html-dir (default dist) - \\ --html-dir HTML site mode with output directory DIR - \\ --target NAME=DIR HTML multi-target mode (repeatable; order-independent); implies HTML - \\ --out IR mode โ†’ write JSON under DIR (default .boris when --no-rag) - \\ --no-rag Explicit IR mode (JSON under --out, default .boris) - \\ --rag RAG-only mode โ†’ working-context packs under --rag-dir (default rag) - \\ --rag-dir RAG-only mode with output directory DIR - \\ --complete Complete-corpus RAG export (with --rag): the entire validated corpus โ€” system + per-page + graph + catalog - \\ --context Context-only mode โ†’ bundle under --context-dir (default context) - \\ --context-dir DIR Context-only mode with output directory DIR - \\ --scope VALUE RAG/context entity id or collection prefix - \\ --split-size BYTES Working-RAG pack target (default 262144); context bundle byte cap - \\ --bundles-only Accepted for RAG compatibility; working packs are bundle-style by design - \\ --llms Deterministic llms.txt export โ†’ llms.txt - \\ --llms-path PATH llms.txt export path (implies --llms) - \\ --rss Deterministic RSS 2.0 export โ†’ rss.xml - \\ --rss-path PATH RSS output path (implies --rss) - \\ --sitemap Add deterministic sitemap.xml to the HTML target - \\ --sitemap-path PATH Target-root-relative sitemap path (implies --sitemap) - \\ --static-dir DIR Copy a directory of static files byte-identically into - \\ the HTML target root (robots.txt, .well-known/; #804) - \\ - \\Options: - \\ --input Content root (default: content) - \\ --textile Explicit .textile-only input adapter mode (no mixed trees) - \\ --cooklang Explicit .cook-only Cooklang recipe mode (no mixed trees) - \\ --out IR output directory (selects IR mode; default: .boris) - \\ --rag-dir RAG corpus directory (implies RAG-only; default: rag) - \\ --site-url URL Required HTTP(S) deployment URL for RSS or sitemap - \\ --pages-base-url U Normalized Pages public base URL - \\ --pages-origin U Normalized Pages public origin - \\ --pages-base-path P Normalized Pages path (empty for root/custom sites) - \\ --rss-title TITLE Required RSS channel title - \\ --rss-description T Required RSS channel description - \\ --rss-limit N RSS item limit (1โ€“500; default 20) - \\ --html-dir HTML output directory (implies HTML; default: dist) - \\ --html-layout PATH Global layout template (default: themes/boris/layouts/main.html) - \\ --theme ROOT Theme root sugar โ†’ ROOT/layouts/main.html (+ managed assets/) - \\ --target NAME=DIR Named HTML output root (repeatable; exclusive with --html-dir) - \\ --target-layout N=P Per-target layout (NAME=PATH; may precede or follow --target) - \\ --target-profile N=P Per-target Oliver serialization profile (NAME=html|xhtml; default html) - \\ --layout-rule T S P HTML layout rule: TARGET SELECTOR LAYOUT_PATH (repeatable; max 256/target) - \\ Selectors: id: | glob: | role:trunk|satellite - \\ --incremental Content-addressed incremental HTML rendering (HTML mode) - \\ --refresh-evidence Force full evidence re-derivation, skipping reuse of - \\ unchanged committed evidence (HTML mode, #728) - \\ --watch Compatibility flag; same as the watch command; with `validate` - \\ starts the zero-write validation daemon (validate --watch) - \\ --watch-json Emit one NDJSON event per build phase on stderr (watch only, - \\ including validate --watch); see docs/contracts/watch-mode.md ยง8 - \\ --serve Serve the built tree over loopback HTTP (watch only); - \\ auto-reload helper: http://127.0.0.1:PORT/__boris/ - \\ --port N Loopback port for --serve (default 8090; 0 = ephemeral); - \\ implies --serve - \\ --jobs N, -j N Bounded parallel HTML page workers (1โ€“64; HTML mode; default 1; smoke-validated) - \\ --timings Print a machine-readable phase timing/counter JSON report to stdout - \\ (opt-in; default output, diagnostics, and exit codes unchanged) - \\ --quiet Suppress progress + success stderr; errors always print - \\ (exit codes/artifacts unchanged) - \\ --format human|json Analysis output format for check/impact (default human) - \\ --format mermaid|dot Graph render format for `graph` (default mermaid) - \\ --out PATH Graph render output path (single file; default stdout) - \\ --report PATH Write the report to PATH (check/impact analysis; build/validate HTML diagnostics) - \\ --fail-on-unreferenced Make check fail when it reports unreferenced pages - \\ --profile PATH Selected publication profile for `plan` - \\ --id PAGE Recipe page entity id (`recipe-scale`; required) - \\ --factor TEXT Scale factor: 2, 1/2, 1.5, 1 1/2 (`recipe-scale`; exclusive with --servings) - \\ --servings N Target serving count (`recipe-scale`; exclusive with --factor) - \\ --out PATH Scaled-view JSON path (`recipe-scale`; default: stdout only) - \\ --plan PATH Plan artifact to sign (`nostr sign`) - \\ --key-stdin Read the hex/nsec secret key once from stdin (`nostr sign`) - \\ --out PATH Signed-event bundle output path (`nostr sign`; default: stdout) - \\ --prior PATH Prior signed bundle to reuse unchanged evidence from (`nostr sign`) - \\ --created-at N Explicit signing-time override, unix seconds (`nostr sign`; test/recovery) - \\ --bundle PATH Signed-event bundle to publish (`nostr publish`) - \\ --out PATH Publish report output path (`nostr publish`; default: stdout) - \\ -h, --help Show this help and exit 0 - \\ -V, --version Print the compiler version (`boris/`) and exit 0 - \\ - \\HTML artifacts (success; Oliver + layout splice): - \\ /**/*.html or /**/*.html - \\ /sitemap.xml (with --sitemap; path configurable) - \\ /** (with --static-dir; byte-identical passthrough files, - \\ declared in _boris/proof/artifacts.json) - \\ /.boris-cache/manifest.json (with --incremental / --watch) - \\ Staging: .boris-stage (ephemeral; committed only on full target success) - \\ - \\IR artifacts (success; --out or --no-rag): - \\ /manifest.json /graph.json /completion.json /build-report.json - \\ - \\RAG artifacts (success; same graph validation as IR): - \\ working-N.md model-facing working packs (site documents only) - \\ manifest.json sidecar manifest โ€” NOT normally uploaded (scope, counts, hashes) - \\ (with --complete) INDEX.md UPLOAD-GUIDE.md catalog.jsonl catalog_meta.json system/** - \\ content/pages/** graph/entity-catalog.md graph/relations.md - \\ - \\Context artifacts (success; same graph validation as IR/RAG): - \\ bundle.md manifest.json graph.json pages/.md - \\ parts/part-N.md (with --split-size) - \\ - \\Conflicts (exit 2): - \\ --rag with --no-rag - \\ --no-rag with --rag-dir - \\ --textile with --cooklang - \\ --complete without --rag / --rag-dir - \\ --complete with --scope, --split-size, or --bundles-only - \\ --context / --context-dir with --rag, --out, or HTML selectors - \\ --rss / --rss-path with HTML, IR, RAG, Context, llms.txt, validate, check, or impact - \\ --sitemap / --sitemap-path without --site-url, with non-HTML modes, - \\ or with multiple targets sharing one ambiguous public URL - \\ --site-url without --rss or --sitemap - \\ --out with nostr plan (stdout carries the plan document) - \\ session flags (--did, --handle, --app-password, --prune, - \\ --source-commit, --dist, --namespace, --surface-url, --indexer, - \\ --session-root) outside standard-site - \\ --static-dir with non-HTML modes or multiple targets - \\ explicit --out with --rag or --rag-dir - \\ --html / --html-dir / --html-layout / --theme / --target / --target-layout / - \\ --target-profile / --layout-rule with --rag, --rag-dir, --context, or explicit --out - \\ --target with --html-dir - \\ --theme with --html-layout (both select the one global layout) - \\ check / impact with any HTML selector (--html, --html-dir, - \\ --html-layout, --theme, --target, --target-layout, --target-profile, - \\ --layout-rule, --sitemap / --sitemap-path, --static-dir) or --profile - \\ --watch, --incremental, or --jobs with IR (--out / --no-rag) or RAG / context - \\ validate with --profile, non-HTML exports, --incremental, --refresh-evidence, --jobs, --format, or --out - \\ validate --watch with --html-dir, --target, --serve/--port, --incremental, --jobs, or --format - \\ Invalid target names, duplicate names, output collisions, workspace escape, - \\ content/layout overlap, unknown --target-layout / --layout-rule target, - \\ duplicate or invalid layout selectors, invalid layout paths (.. / absolute), - \\ mixed theme roots, >256 rules/target - \\ - \\Exit codes: 0 success, 1 content validation, 2 usage, 3 I/O/system - \\ - \\Note: Bare `boris` builds HTML under dist/ as target "default". Use --out for JSON IR. - \\ `boris validate` observes the selected HTML target configuration but writes no artifacts. - \\ `boris validate --watch` repeats that preflight on every change and exits 0 on signal; - \\ `--report PATH` is rewritten each cycle and `--watch-json` emits mode "validate" events. - \\ `boris plan --profile PATH` emits only the normalized declaration JSON on stdout. - \\ `boris recipe-scale --input DIR --id PAGE --factor TEXT` prints a derived - \\ scaled view on stdout; `--servings N` is the same view with - \\ factor = N / current (missing current is 1). Never rewrites .cook or graph.json. - \\ `boris standard-site` (no subcommand) prints the Standard.site family list. - \\ `boris nostr plan --profile PATH` emits the offline NIP-23 publication plan on stdout; - \\ it never signs, never contacts a relay, and never reads a key. - \\ `boris nostr sign --plan PLAN --key-stdin` reads the secret key once from stdin and - \\ writes the signed-event bundle to stdout (or --out PATH); it never contacts a relay. - \\ Secrets are never accepted from argv, profile, or environment. - \\ --html / --html-dir / bare CLI map to a single target named "default". - \\ Equivalent --target / --target-layout / --layout-rule permutations yield the - \\ same config (targets sorted by name; rules canonicalized). No layout frontmatter. - \\ Frontmatter `status:` is exactly draft, published, or archived (unknown - \\ values fail validation). A draft renders to its .html files but is - \\ excluded from nav, search, sitemap, RSS, and publication projections. - \\ + \\Boris โ€” Zig content compiler (HTML site + IR + optional RAG) + \\ + \\Usage: boris [options] + \\ + \\Modes: + \\ build Build the HTML site (default command) + \\ validate Validate selected HTML source/config without publication + \\ watch Build HTML, then watch and rebuild on changes + \\ check Read-only graph health report (findings do not fail by default) + \\ impact Read-only transitive impact report for a page + \\ plan Emit a normalized publication plan (no publication) + \\ recipe-scale Print a derived Cooklang scale view (no rewrite) + \\ graph Read-only graph render: Mermaid (default) or Graphviz DOT + \\ proof verify Fail when committed publication-check findings exceed policy + \\ standard-site publish One-shot Standard.site publish (stored session + reconcile; never implicit) + \\ standard-site plan Emit the deterministic Standard.site plan offline (no network) + \\ standard-site records Dump the full canonical record payloads offline (no network) + \\ standard-site verify Cross-check the built head links + well-known file offline (no network) + \\ standard-site login Authorize a DID or handle and persist the session + \\ standard-site sessions List persisted sessions (DID, flavor, PDS; no secrets) + \\ standard-site logout Remove a persisted session (secure erase; does not revoke) + \\ standard-site smoke Live interop smoke against a real PDS (manual, opt-in; never in CI) + \\ nostr plan Emit the offline Nostr NIP-23 publication plan (no signing, no relay) + \\ nostr sign Sign a plan artifact into a signed-event bundle (offline; key via stdin) + \\ nostr publish Send a signed-event bundle to the plan's relays; writes the report + \\ init [DIR] Write a starter site (content, theme, profile) into DIR (default: .) + \\ (no command) Same as build + \\ standard-site publish options: + \\ --profile PATH Standard.site publication profile (required) + \\ --plan PATH Committed standard-site plan to validate (fail closed on drift) + \\ --out PATH Evidence artifact path (default: stdout) + \\ --prune Explicit prune authority (ANDs with the profile prune flag) + \\ --source-commit C Source commit recorded in the evidence bindings + \\ standard-site plan options: + \\ --profile PATH Standard.site publication profile (required) + \\ --out PATH Plan artifact path (default: stdout) + \\ standard-site records options: + \\ --profile PATH Standard.site publication profile (required) + \\ --out PATH Records artifact path (default: stdout) + \\ standard-site verify options: + \\ --profile PATH Standard.site publication profile (required) + \\ --dist DIR Built output directory to check (default: dist) + \\ --out PATH Verify result artifact path (default: stdout) + \\ standard-site login/logout options: + \\ --did DID AT Protocol DID to authorize (login) or forget (logout) + \\ --handle HANDLE AT Protocol handle for login --app-password, logout, or smoke + \\ --app-password Opt-in app-password login (broad account write; never OAuth scope) + \\ standard-site smoke options: + \\ --did DID Test identity DID (or use --handle) + \\ --namespace NAME Unique rkey namespace prefix (default: clock-derived) + \\ --surface-url URL Served verification-surface origin to check (optional) + \\ --indexer URL Indexer/AppView origin observed non-normatively (optional) + \\ --out PATH Smoke result artifact path (default: stdout) + \\ standard-site options (all subcommands): + \\ --session-root PATH Override the persistent session store root + \\ --profile PATH Publication profile: emit Standard.site verification and/or Nostr naddr head links + \\ --html Explicit HTML site mode โ†’ --html-dir (default dist) + \\ --html-dir HTML site mode with output directory DIR + \\ --target NAME=DIR HTML multi-target mode (repeatable; order-independent); implies HTML + \\ --out IR mode โ†’ write JSON under DIR (default .boris when --no-rag) + \\ --no-rag Explicit IR mode (JSON under --out, default .boris) + \\ --rag RAG-only mode โ†’ working-context packs under --rag-dir (default rag) + \\ --rag-dir RAG-only mode with output directory DIR + \\ --complete Complete-corpus RAG export (with --rag): the entire validated corpus โ€” system + per-page + graph + catalog + \\ --context Context-only mode โ†’ bundle under --context-dir (default context) + \\ --context-dir DIR Context-only mode with output directory DIR + \\ --scope VALUE RAG/context entity id or collection prefix + \\ --split-size BYTES Working-RAG pack target (default 262144); context bundle byte cap + \\ --bundles-only Accepted for RAG compatibility; working packs are bundle-style by design + \\ --llms Deterministic llms.txt export โ†’ llms.txt + \\ --llms-path PATH llms.txt export path (implies --llms) + \\ --rss Deterministic RSS 2.0 export โ†’ rss.xml + \\ --rss-path PATH RSS output path (implies --rss) + \\ --sitemap Add deterministic sitemap.xml to the HTML target + \\ --sitemap-path PATH Target-root-relative sitemap path (implies --sitemap) + \\ --static-dir DIR Copy a directory of static files byte-identically into + \\ the HTML target root (robots.txt, .well-known/; #804) + \\ + \\Options: + \\ --input Content root (default: content) + \\ --textile Explicit .textile-only input adapter mode (no mixed trees) + \\ --cooklang Explicit .cook-only Cooklang recipe mode (no mixed trees) + \\ --out IR output directory (selects IR mode; default: .boris) + \\ --rag-dir RAG corpus directory (implies RAG-only; default: rag) + \\ --site-url URL Required HTTP(S) deployment URL for RSS or sitemap + \\ --pages-base-url U Normalized Pages public base URL + \\ --pages-origin U Normalized Pages public origin + \\ --pages-base-path P Normalized Pages path (empty for root/custom sites) + \\ --rss-title TITLE Required RSS channel title + \\ --rss-description T Required RSS channel description + \\ --rss-limit N RSS item limit (1โ€“500; default 20) + \\ --html-dir HTML output directory (implies HTML; default: dist) + \\ --html-layout PATH Global layout template (default: themes/boris/layouts/main.html) + \\ --theme ROOT Theme root sugar โ†’ ROOT/layouts/main.html (+ managed assets/) + \\ --target NAME=DIR Named HTML output root (repeatable; exclusive with --html-dir) + \\ --target-layout N=P Per-target layout (NAME=PATH; may precede or follow --target) + \\ --target-profile N=P Per-target Oliver serialization profile (NAME=html|xhtml; default html) + \\ --layout-rule T S P HTML layout rule: TARGET SELECTOR LAYOUT_PATH (repeatable; max 256/target) + \\ Selectors: id: | glob: | role:trunk|satellite + \\ --incremental Content-addressed incremental HTML rendering (HTML mode) + \\ --refresh-evidence Force full evidence re-derivation, skipping reuse of + \\ unchanged committed evidence (HTML mode, #728) + \\ --watch Compatibility flag; same as the watch command; with `validate` + \\ starts the zero-write validation daemon (validate --watch) + \\ --watch-json Emit one NDJSON event per build phase on stderr (watch only, + \\ including validate --watch); see docs/contracts/watch-mode.md ยง8 + \\ --serve Serve the built tree over loopback HTTP (watch only); + \\ auto-reload helper: http://127.0.0.1:PORT/__boris/ + \\ --port N Loopback port for --serve (default 8090; 0 = ephemeral); + \\ implies --serve + \\ --jobs N, -j N Bounded parallel HTML page workers (1โ€“64; HTML mode; default 1; smoke-validated) + \\ --timings Print a machine-readable phase timing/counter JSON report to stdout + \\ (opt-in; default output, diagnostics, and exit codes unchanged) + \\ --quiet Suppress progress + success stderr; errors always print + \\ (exit codes/artifacts unchanged) + \\ --format human|json Analysis output format for check/impact (default human) + \\ --format mermaid|dot Graph render format for `graph` (default mermaid) + \\ --out PATH Graph render output path (single file; default stdout) + \\ --report PATH Write the report to PATH (check/impact analysis; build/validate HTML diagnostics) + \\ --fail-on-unreferenced Make check fail when it reports unreferenced pages + \\ --profile PATH Selected publication profile for `plan` + \\ --id PAGE Recipe page entity id (`recipe-scale`; required) + \\ --factor TEXT Scale factor: 2, 1/2, 1.5, 1 1/2 (`recipe-scale`; exclusive with --servings) + \\ --servings N Target serving count (`recipe-scale`; exclusive with --factor) + \\ --out PATH Scaled-view JSON path (`recipe-scale`; default: stdout only) + \\ --plan PATH Plan artifact to sign (`nostr sign`) + \\ --key-stdin Read the hex/nsec secret key once from stdin (`nostr sign`) + \\ --out PATH Signed-event bundle output path (`nostr sign`; default: stdout) + \\ --prior PATH Prior signed bundle to reuse unchanged evidence from (`nostr sign`) + \\ --created-at N Explicit signing-time override, unix seconds (`nostr sign`; test/recovery) + \\ --bundle PATH Signed-event bundle to publish (`nostr publish`) + \\ --out PATH Publish report output path (`nostr publish`; default: stdout) + \\ -h, --help Show this help and exit 0 + \\ -V, --version Print the compiler version (`boris/`) and exit 0 + \\ + \\HTML artifacts (success; Oliver + layout splice): + \\ /**/*.html or /**/*.html + \\ /sitemap.xml (with --sitemap; path configurable) + \\ /** (with --static-dir; byte-identical passthrough files, + \\ declared in _boris/proof/artifacts.json) + \\ /.boris-cache/manifest.json (with --incremental / --watch) + \\ Staging: .boris-stage (ephemeral; committed only on full target success) + \\ + \\IR artifacts (success; --out or --no-rag): + \\ /manifest.json /graph.json /completion.json /build-report.json + \\ + \\RAG artifacts (success; same graph validation as IR): + \\ working-N.md model-facing working packs (site documents only) + \\ manifest.json sidecar manifest โ€” NOT normally uploaded (scope, counts, hashes) + \\ (with --complete) INDEX.md UPLOAD-GUIDE.md catalog.jsonl catalog_meta.json system/** + \\ content/pages/** graph/entity-catalog.md graph/relations.md + \\ + \\Context artifacts (success; same graph validation as IR/RAG): + \\ bundle.md manifest.json graph.json pages/.md + \\ parts/part-N.md (with --split-size) + \\ + \\Conflicts (exit 2): + \\ --rag with --no-rag + \\ --no-rag with --rag-dir + \\ --textile with --cooklang + \\ --complete without --rag / --rag-dir + \\ --complete with --scope, --split-size, or --bundles-only + \\ --context / --context-dir with --rag, --out, or HTML selectors + \\ --rss / --rss-path with HTML, IR, RAG, Context, llms.txt, validate, check, or impact + \\ --sitemap / --sitemap-path without --site-url, with non-HTML modes, + \\ or with multiple targets sharing one ambiguous public URL + \\ --site-url without --rss or --sitemap + \\ --out with nostr plan (stdout carries the plan document) + \\ session flags (--did, --handle, --app-password, --prune, + \\ --source-commit, --dist, --namespace, --surface-url, --indexer, + \\ --session-root) outside standard-site + \\ --static-dir with non-HTML modes or multiple targets + \\ explicit --out with --rag or --rag-dir + \\ --html / --html-dir / --html-layout / --theme / --target / --target-layout / + \\ --target-profile / --layout-rule with --rag, --rag-dir, --context, or explicit --out + \\ --target with --html-dir + \\ --theme with --html-layout (both select the one global layout) + \\ check / impact with any HTML selector (--html, --html-dir, + \\ --html-layout, --theme, --target, --target-layout, --target-profile, + \\ --layout-rule, --sitemap / --sitemap-path, --static-dir) or --profile + \\ --watch, --incremental, or --jobs with IR (--out / --no-rag) or RAG / context + \\ validate with --profile, non-HTML exports, --incremental, --refresh-evidence, --jobs, --format, or --out + \\ validate --watch with --html-dir, --target, --serve/--port, --incremental, --jobs, or --format + \\ Invalid target names, duplicate names, output collisions, workspace escape, + \\ content/layout overlap, unknown --target-layout / --layout-rule target, + \\ duplicate or invalid layout selectors, invalid layout paths (.. / absolute), + \\ mixed theme roots, >256 rules/target + \\ + \\Exit codes: 0 success, 1 content validation, 2 usage, 3 I/O/system + \\ + \\Note: Bare `boris` builds HTML under dist/ as target "default". Use --out for JSON IR. + \\ `boris validate` observes the selected HTML target configuration but writes no artifacts. + \\ `boris validate --watch` repeats that preflight on every change and exits 0 on signal; + \\ `--report PATH` is rewritten each cycle and `--watch-json` emits mode "validate" events. + \\ `boris plan --profile PATH` emits only the normalized declaration JSON on stdout. + \\ `boris recipe-scale --input DIR --id PAGE --factor TEXT` prints a derived + \\ scaled view on stdout; `--servings N` is the same view with + \\ factor = N / current (missing current is 1). Never rewrites .cook or graph.json. + \\ `boris standard-site` (no subcommand) prints the Standard.site family list. + \\ `boris nostr plan --profile PATH` emits the offline NIP-23 publication plan on stdout; + \\ it never signs, never contacts a relay, and never reads a key. + \\ `boris nostr sign --plan PLAN --key-stdin` reads the secret key once from stdin and + \\ writes the signed-event bundle to stdout (or --out PATH); it never contacts a relay. + \\ Secrets are never accepted from argv, profile, or environment. + \\ --html / --html-dir / bare CLI map to a single target named "default". + \\ Equivalent --target / --target-layout / --layout-rule permutations yield the + \\ same config (targets sorted by name; rules canonicalized). No layout frontmatter. + \\ Frontmatter `status:` is exactly draft, published, or archived (unknown + \\ values fail validation). A draft renders to its .html files but is + \\ excluded from nav, search, sitemap, RSS, and publication projections. + \\ ; pub fn printUsage() void {