geneseed 4.17.2 → 4.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +1 -1
  3. package/SHIPPED.md +1 -1
  4. package/docs/concepts/footprint.md +1 -1
  5. package/docs/guides/upgrade.md +2 -2
  6. package/docs/web-ui.md +11 -4
  7. package/harness.config.json +1 -1
  8. package/js/inspect/diff.mjs +42 -9
  9. package/js/web/actions.mjs +14 -5
  10. package/js/web/api.mjs +3 -1
  11. package/js/web/catalog.mjs +14 -2
  12. package/js/web/docs.mjs +31 -11
  13. package/package.json +1 -1
  14. package/web/dist/assets/Activity-CrBz-58G.js +1 -0
  15. package/web/dist/assets/ActivityDetail-ZgsHrwvj.js +1 -0
  16. package/web/dist/assets/Dashboard-Ds7_blrK.js +3 -0
  17. package/web/dist/assets/Docs-f2YJDQah.js +4 -0
  18. package/web/dist/assets/GreenhouseView-De8W1BvM.js +1 -0
  19. package/web/dist/assets/Installs-BFsJIIti.js +3 -0
  20. package/web/dist/assets/JournalView-DZHR1l1P.js +1 -0
  21. package/web/dist/assets/KitApply-BYyktcdw.js +1 -0
  22. package/web/dist/assets/Kits-Dfch112m.js +1 -0
  23. package/web/dist/assets/Laws-BztN3C8x.js +3 -0
  24. package/web/dist/assets/Library-CrZGLGWE.js +1 -0
  25. package/web/dist/assets/Loops-BsbkBFl-.js +2 -0
  26. package/web/dist/assets/Markdown-OReRRoEV.js +65 -0
  27. package/web/dist/assets/OperatorHudView-BB8BH5PL.js +1 -0
  28. package/web/dist/assets/Personal-LRrDvMje.js +1 -0
  29. package/web/dist/assets/RailCats-D5RVYEjy.js +1 -0
  30. package/web/dist/assets/{Tabs-CFVpjPm7.js → Tabs-b-L-ra4k.js} +1 -1
  31. package/web/dist/assets/drawable-CuQpH-f5.js +1 -0
  32. package/web/dist/assets/index--3760QWr.js +2 -0
  33. package/web/dist/assets/index-FWb-1Qgz.css +1 -0
  34. package/web/dist/index.html +2 -2
  35. package/web/src/pages/Laws.jsx +56 -24
  36. package/web/dist/assets/Activity-BvbzB-H1.js +0 -1
  37. package/web/dist/assets/ActivityDetail-CSwA3UmY.js +0 -1
  38. package/web/dist/assets/Dashboard-DAN3juLM.js +0 -2
  39. package/web/dist/assets/Docs-BQ2pEV8F.js +0 -5
  40. package/web/dist/assets/FilterInput-CZREvrjX.js +0 -1
  41. package/web/dist/assets/GreenhouseView-BoJyzeuf.js +0 -2
  42. package/web/dist/assets/Installs-3fAay1NE.js +0 -3
  43. package/web/dist/assets/JournalView-Ck5c_3Md.js +0 -1
  44. package/web/dist/assets/KitApply-CsnEjQi6.js +0 -1
  45. package/web/dist/assets/Kits-Bos4VAWe.js +0 -1
  46. package/web/dist/assets/Laws-r1vX_zU5.js +0 -3
  47. package/web/dist/assets/Library-DmFLcNYl.js +0 -1
  48. package/web/dist/assets/Loops-DhRt563u.js +0 -2
  49. package/web/dist/assets/Markdown-unTJNwOC.js +0 -65
  50. package/web/dist/assets/OperatorHudView-DIhkL4qf.js +0 -2
  51. package/web/dist/assets/Personal-BxtZyYl_.js +0 -1
  52. package/web/dist/assets/drawable-D2dpNTE8.js +0 -1
  53. package/web/dist/assets/index-D-cBvfU2.js +0 -2
  54. package/web/dist/assets/index-jYlWihN-.css +0 -1
  55. package/web/dist/assets/jobBuckets-Dbq8ZlWW.js +0 -1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,29 @@ label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [4.18.1] — 2026-10-24
12
+
13
+ Patch: the web console's light mode meets WCAG AA, and console installs default to lean.
14
+
15
+ ### Fixed
16
+ - **Light mode meets WCAG AA in every flavour, mode and accent.** Accent and status text use darker text companions (`--accent-text`, `--good-text`, `--warn-text`, `--bad-text`), measured against each flavour's real surfaces; button text is chosen by contrast, so a light cyan, amber or green button now carries dark text; every control shows a 2 px focus ring; the light topbar is solid and light cards keep their flavour; the page behind the console and the browser's theme colour follow the active mode. A warning next to an amber accent turns orange, so it no longer looks like the accent. `contrast.test.js` checks all of it against the real stylesheet.
17
+
18
+ ### Changed
19
+ - **New installs from the web console default to the lean footprint**, like the CLI: a deploy, an install on an absent row and a first-run build. An explicit `full` still works, and an existing install keeps its footprint on rebuild.
20
+
21
+ ## [4.18.0] — 2026-10-24
22
+
23
+ Minor: the web console's numbers tell the truth (stale vs edited drift, lenses, Constitution, Docs) and it keeps your work (error boundary, draft guard, shared staging).
24
+
25
+ ### Fixed
26
+ - **Drift numbers tell the truth.** A file that differs from the source only because the install is behind (unmodified since its build) is now `stale`, not `edited`; `.geneseed-version` is always a build stamp. The Overview counts only real hand edits and shows stale files as "N files behind"; Local edits lists them apart under **Behind source** with a rebuild banner; `diff --out` and the upgrade export include only real local changes. "Never fired" counts each skill once across the fleet. A failed fleet read says so and keeps the last good table; a zero ceiling prints "no ceiling"; the ceiling marker sits on the root file's own lane.
27
+ - **The four Overview lenses agree with the Ledger.** They show the newest runs first, carry the fleet verdict badge, and read runs as `verb · scope · result · duration`. The Greenhouse ring is full at 100%, the Lineage badge no longer hard-codes "in sync", a failed doctor says so instead of drawing a false "1 checks", the HUD KPIs sit on one row, and the Journal map keeps its height.
28
+ - **Constitution ranks tiers by the real precedence** (Dictates, your rules, Credo, Doctrines) and renders rule bodies as Markdown. Rule texts are cached and a failed read offers Retry; a partly-on pack reads as mixed; a disarmed gate is marked off; tier names follow the voice.
29
+ - **Docs pages render their tokens.** The Memory and Notebook pages no longer show raw `{{…}}` build tokens. Heading ids come from one pass, so every outline link lands; wide tables scroll; Back no longer bounces off a hidden page; blocked storage no longer crashes the page; the Docs page no longer scrolls past the shell.
30
+ - **The console survives a page crash.** A page error or a missing chunk after an upgrade shows the error with Retry (or Restart) while the sidebar, topbar and console stay. A malformed `#/item/…` link no longer blanks the app; Skip to content works; each page change sets the title, scrolls to the top and moves focus to the page.
31
+ - **Unsaved work is kept.** Profile and Rules keep a draft through a 409 conflict and ask before an in-app navigation discards it; a draft whose rule was removed reopens as a new rule. Staged kit and doctrine switches are held for the whole console, survive leaving the page, and are kept after a failed rebuild; a row shows "Rebuilding…" while its job runs.
32
+ - **Slow answers no longer overwrite newer ones** in the console's data hook, and a failed first read shows an error instead of "Loading…" forever (Library entry, Activity session).
33
+
11
34
  ## [4.17.2] — 2026-10-24
12
35
 
13
36
  Patch: the web console closes its security and data-loss holes from the 2026-10-24 audit.
package/README.md CHANGED
@@ -334,7 +334,7 @@ geneseed rebuild-all # re-render every registered install in its own theme + m
334
334
  ./geneseed upgrade # just the content refresh (remembers theme + emit mode)
335
335
  ```
336
336
 
337
- **Local edits survive.** The self-improvement loops write to notes under `notebook/`, which no rebuild touches. If you or the agent edited deployed agent/skill files in place anyway, an upgrade exports that drift to an `improvements/` file inside the install before overwriting. Details: [Upgrade](docs/guides/upgrade.md).
337
+ **Local edits survive.** The self-improvement loops write to notes under `notebook/`, which no rebuild touches. If you or the agent edited deployed agent/skill files in place anyway, an upgrade exports those edits to an `improvements/` file inside the install; the rebuild then keeps each edited file instead of overwriting it. Details: [Upgrade](docs/guides/upgrade.md).
338
338
 
339
339
  ## 📚 Documentation
340
340
 
package/SHIPPED.md CHANGED
@@ -20,7 +20,7 @@ historical references, not files distributed with the repo.
20
20
  > **On version numbers.** [`harness.config.json`](harness.config.json)'s `version` is a
21
21
  > human-readable label only. The canonical identity of an installed harness is the
22
22
  > **source fingerprint** stamped in `.geneseed-version` (see `geneseed version`), not the
23
- > string. Current label: **4.17.2**.
23
+ > string. Current label: **4.18.1**.
24
24
 
25
25
  ## Capabilities
26
26
 
@@ -42,7 +42,7 @@ Footprint is stored in a `.geneseed-footprint` marker in the install and kept ac
42
42
  geneseed setup
43
43
  ```
44
44
 
45
- - **Web console** — the **Footprint** toggle in Settings flips the current install and rebuilds it; on the Harness page, each install has its own dropdown.
45
+ - **Web console** — the **Footprint** toggle in Settings flips the current install and rebuilds it; on the Harness page, each install has its own dropdown. A new install or deploy from the console starts lean, as from the command line.
46
46
  - **Command line** — with the emit target of the install you are changing:
47
47
 
48
48
  ```bash
@@ -64,7 +64,7 @@ A rebuild only replaces files the install's manifest says Geneseed owns. It leav
64
64
 
65
65
  ## Local edits, and the improvements file
66
66
 
67
- The agent records what it learns about a skill or agent in notes under `notebook/skill-notes/` and `notebook/agent-notes/`, which rebuilds never touch. Edits made to the deployed agent and skill files themselves, by you or by an older harness, are another matter: a rebuild would overwrite those, so **setup, re-theme and upgrade export them first**. When the files they are about to overwrite differ from a fresh render, the differences are written to a markdown **improvements file** in `improvements/`, inside the install's own folder (for the OpenCode global install, `~/.config/opencode/improvements/`). The manifest does not list that folder, so rebuilds never overwrite it and uninstall never removes it.
67
+ The agent records what it learns about a skill or agent in notes under `notebook/skill-notes/` and `notebook/agent-notes/`, which rebuilds never touch. Edits made to the deployed agent and skill files themselves, by you or by an older harness, are another matter: a rebuild would overwrite those, so **setup, re-theme and upgrade export them first**. When deployed files carry local edits (files only behind the source are not edits and are not exported), the differences are written to a markdown **improvements file** in `improvements/`, inside the install's own folder (for the OpenCode global install, `~/.config/opencode/improvements/`). The manifest does not list that folder, so rebuilds never overwrite it and uninstall never removes it.
68
68
 
69
69
  A rebuild also refuses to overwrite a file you edited. The manifest records a fingerprint of every file Geneseed wrote; when a file no longer matches it, the rebuild leaves it alone and prints `kept your edited <file> — delete it to get Geneseed's copy back`. From then on the file is yours and later rebuilds skip it. A file the new version no longer ships is kept the same way, with `(no longer shipped)`. Line-ending changes from a git checkout do not count as edits. Installs made before fingerprints existed are overwritten as before.
70
70
 
@@ -76,7 +76,7 @@ geneseed diff --full # with line-level diffs
76
76
  geneseed diff --out improvements.md # write the improvements file
77
77
  ```
78
78
 
79
- `diff` compares the global OpenCode install by default. Pass `--target <config dir>` to compare another install. A file you replaced with a link to your own copy (a skill folder junctioned or symlinked elsewhere, say) is listed as `linked`: Geneseed never writes through a link, so it is yours and not drift, and it stays out of the improvements file. `diff` also lists every non-empty self-improvement note, and `--out` copies them into the improvements file; the upgrade export does not fire on notes alone, since a rebuild cannot lose them. The improvements file is self-contained. To make the changes permanent, hand it to an agent in a Geneseed clone and ask it to fold them back into `src/`. Then they survive every future build. The web console's **Changes** page exports the same file.
79
+ `diff` compares the global OpenCode install by default. Pass `--target <config dir>` to compare another install. A file you replaced with a link to your own copy (a skill folder junctioned or symlinked elsewhere, say) is listed as `linked`: Geneseed never writes through a link, so it is yours and not drift, and it stays out of the improvements file. A file unmodified since its build that differs only because the source moved on is listed as behind source; a rebuild updates it, and it stays out of the improvements file too. `diff` also lists every non-empty self-improvement note, and `--out` copies them into the improvements file; the upgrade export does not fire on notes alone, since a rebuild cannot lose them. The improvements file is self-contained. To make the changes permanent, hand it to an agent in a Geneseed clone and ask it to fold them back into `src/`. Then they survive every future build. The web console's **Changes** page exports the same file.
80
80
 
81
81
  ## Moving from a clone to npm
82
82
 
package/docs/web-ui.md CHANGED
@@ -83,8 +83,11 @@ streams the output of background jobs and keeps their history across reloads.
83
83
  - **Dashboard** (`#/`) — a live readout of what's deployed. Three lenses: **Status**
84
84
  (readiness ring, a KPI band, a genome grid, recent activity), **Lineage** (the
85
85
  source → render → deployed timeline and the genome-by-volume strand chart), and
86
- **Operator** (a searchable table of every deployed capability). Headlines reflect the
87
- active theme's voice.
86
+ **Operator** (a searchable table of every deployed capability). Every lens hero carries the
87
+ fleet verdict badge (the Ledger's `fleetVerdict`). The headline speaks the theme's voice only
88
+ while that verdict is good or still loading; a warn, bad or unreachable fleet reads plain
89
+ *Deployed*. Recent-run previews read `verb · scope · result · duration`, and the raw command
90
+ is a tooltip only.
88
91
 
89
92
  The KPI band reads **Agents · Skills · Dictates · Local edits**. That third tile is
90
93
  labelled *Dictates* (the name AGENT.md gives the laws) and not *Constitution* on purpose: its value is the law count
@@ -178,7 +181,8 @@ streams the output of background jobs and keeps their history across reloads.
178
181
  - **Activity** (`#/activity`) — the agent sessions on this machine: each one's status,
179
182
  the files it touched and its todo progress; open one for its detail.
180
183
  - **Changes** (`#/diff`) — the diff between the deployed harness and the source: edited /
181
- added / missing files with per-file expansion and coloured unified-diff lines. Select
184
+ added / missing files, and files only behind the source (unedited; a rebuild updates them)
185
+ listed apart under **Behind source**, with per-file expansion and coloured unified-diff lines. Select
182
186
  files to **export an `improvements.md`** back-port, or **restore** them to source.
183
187
  Restore acts only on files the diff lists, and never on your own files (`user-rules.md`,
184
188
  `PROFILE.md`, `memory/`, `notebook/`). An added file is moved into
@@ -215,7 +219,10 @@ streams the output of background jobs and keeps their history across reloads.
215
219
  add or remove one here, the web mirror of `harness exclude add|remove|list`.
216
220
  - **Kits** (`#/installs/kits`) — every install (disabled ones read-only) as a panel with one switch per kit.
217
221
  Toggling only stages the set; **Apply** asks first, then rebuilds that install with
218
- exactly that set as a console job. Files you edited in a kit that is now off are kept,
222
+ exactly that set as a console job. Staged switches are held for the whole console: they
223
+ survive leaving the page, and the Kits page and Installs › Kits share them. A refetch drops a
224
+ row's staging only when that install's kits changed. A failed rebuild keeps it and says so,
225
+ and a reload asks first while anything is staged. Files you edited in a kit that is now off are kept,
219
226
  and the row lists them.
220
227
  - **Settings** (`#/settings`) — a **Console direction** picker (the visual flavour of the
221
228
  console: Cultivar, Operator, Matrix or Atlas) with a **Dashboard layout** control (Auto follows each theme's designed Status
@@ -2,5 +2,5 @@
2
2
  "_comment": "version is a human-readable release label only; the canonical identity of an installed harness is the source fingerprint stamped in .geneseed-version (see `harness version`), not this string.",
3
3
  "theme": "neutral",
4
4
  "product": "Geneseed",
5
- "version": "4.17.2"
5
+ "version": "4.18.1"
6
6
  }
@@ -54,7 +54,7 @@ import {
54
54
  trustOfDir,
55
55
  readJsonMaybe, readMaybe, themeOfDir,
56
56
  } from '../hosts/installs.mjs';
57
- import { safeLeaf } from '../hosts/owned.mjs';
57
+ import { hashesOf, ownedState, safeLeaf } from '../hosts/owned.mjs';
58
58
  import { unifiedDiff, splitLines } from '../lib/udiff.mjs';
59
59
  import { printOut, printErr, readText, writeText, isFile } from '../lib/fs.mjs';
60
60
  import { toPlatformPath } from '../lib/paths.mjs';
@@ -86,8 +86,7 @@ export function cmpKey(rel, text) {
86
86
  }
87
87
 
88
88
  /** `_harness_diff._owned_set` — the files a global install claims, per its manifest. */
89
- function ownedSet(d) {
90
- const data = readJsonMaybe(path.join(d, GLOBAL_MANIFEST));
89
+ function ownedSet(d, data = readJsonMaybe(path.join(d, GLOBAL_MANIFEST))) {
91
90
  if (data === null || typeof data !== 'object') return new Set();
92
91
  const owned = data.owned;
93
92
  return new Set(Array.isArray(owned) ? owned : []);
@@ -275,8 +274,17 @@ export function diffCollect({
275
274
  ? memoExpected(memo, host, axes, deployedDir, sourceFp)
276
275
  : renderExpected(host, axes, deployedDir);
277
276
 
277
+ // The deployed manifest, read once: its `owned` and its `hashes` both classify below.
278
+ const manifest = readJsonMaybe(path.join(dir, GLOBAL_MANIFEST));
279
+ const deployedOwned = ownedSet(dir, manifest);
280
+ const hashes = hashesOf(manifest);
281
+ // STALE IS NOT AN EDIT. A file whose bytes still match the hash its emit recorded was never
282
+ // touched: it differs only because the source moved on, and the next rebuild overwrites it.
283
+ // Reporting it as "edited" told every install behind its source that it was hand-edited.
284
+ // Only a manifest with hashes can tell the two apart; a legacy one keeps the old reading.
285
+ const hashed = Object.keys(hashes).length > 0;
278
286
  const files = [];
279
- const rels = [...new Set([...ownedSet(dir), ...exp.owned])].sort();
287
+ const rels = [...new Set([...deployedOwned, ...exp.owned])].sort();
280
288
  for (const rel of rels) {
281
289
  const a = path.join(dir, rel);
282
290
  const tb = exp.texts.get(posixRel(rel));
@@ -289,7 +297,11 @@ export function diffCollect({
289
297
  const diff = unifiedDiff(splitLines(tb), splitLines(ta), {
290
298
  fromfile: `source/${rel}`, tofile: `deployed/${rel}`, lineterm: '',
291
299
  });
292
- rec = { rel, status: 'edited', diff };
300
+ // `.geneseed-version` is a build stamp: a different fingerprint in it is the install
301
+ // being behind, never an edit, with or without hashes.
302
+ const stale = rel === VERSION_MARKER
303
+ || (hashed && ownedState(dir, rel, hashes) === 'unmodified');
304
+ rec = { rel, status: stale ? 'stale' : 'edited', diff };
293
305
  }
294
306
  } else if (isFile(a)) {
295
307
  const body = splitLines(readText(a));
@@ -298,6 +310,9 @@ export function diffCollect({
298
310
  status: 'added',
299
311
  diff: ['(only in deployed — your addition)', '', ...body.map((ln) => `+${ln}`)],
300
312
  };
313
+ } else if (hashed && !deployedOwned.has(rel)) {
314
+ // In source and never in this install's manifest: new since its emit, not deleted.
315
+ rec = { rel, status: 'stale', diff: ['(new in source, not yet deployed — a rebuild adds it)'] };
301
316
  } else {
302
317
  rec = { rel, status: 'missing', diff: ['(in source, not deployed — re-emit to add)'] };
303
318
  }
@@ -318,9 +333,20 @@ export function diffCollect({
318
333
  return { target: dir, theme: themeName, files };
319
334
  }
320
335
 
321
- /** The records that are drift: everything but a `linked` path, which is the user's own. */
336
+ /**
337
+ * The records that are drift: everything but a `linked` path, which is the user's own. A
338
+ * `stale` file stays in: `apiRestore` offers exactly this set, and restoring a stale file is
339
+ * the same as rebuilding it.
340
+ */
322
341
  export const drifted = (files) => files.filter((f) => f.status !== 'linked');
323
342
 
343
+ /**
344
+ * The records that are LOCAL CHANGES: drift minus `stale`. A stale file has nothing to
345
+ * back-port (a rebuild updates it), so the improvements report and the export `setup` and
346
+ * `update` fire read this set, not `drifted`.
347
+ */
348
+ export const localChanges = (files) => drifted(files).filter((f) => f.status !== 'stale');
349
+
324
350
  /** Where the self-improvement loops write, relative to an install's `notebook/`. */
325
351
  export const NOTES_DIRS = ['skill-notes', 'agent-notes'];
326
352
 
@@ -354,7 +380,8 @@ export function collectNotes(dir) {
354
380
  /** `_harness_diff._improvements_md` — pure; `when` is the caller's timestamp. */
355
381
  export function improvementsMd(target, theme, allFiles, when, notes = []) {
356
382
  // A linked path is never a back-port item: the file is the user's, not a local edit of ours.
357
- const files = drifted(allFiles);
383
+ // Nor is a stale one: the source already has what it lacks.
384
+ const files = localChanges(allFiles);
358
385
  const edited = files.filter((f) => f.status === 'edited');
359
386
  const added = files.filter((f) => f.status === 'added');
360
387
  const missing = files.filter((f) => f.status === 'missing');
@@ -458,7 +485,10 @@ export function exportImprovements(target = null, theme = null, outPath = null)
458
485
  // Python's `if not files` — null AND the empty list both return, which is why the caller
459
486
  // gets `files` back rather than a bare path and can tell the two apart itself.
460
487
  // A linked path alone is not drift, or every update would export an empty report.
461
- if (!collected.files || drifted(collected.files).length === 0) return [null, collected.files];
488
+ // Nor are stale files alone, or every update over an older install would export one.
489
+ if (!collected.files || localChanges(collected.files).length === 0) {
490
+ return [null, collected.files];
491
+ }
462
492
  return [writeImprovements(collected.target, collected.theme, collected.files, outPath),
463
493
  collected.files];
464
494
  }
@@ -515,20 +545,23 @@ export function cmdDiff(args) {
515
545
  const added = files.filter((f) => f.status === 'added');
516
546
  const missing = files.filter((f) => f.status === 'missing');
517
547
  const linked = files.filter((f) => f.status === 'linked');
548
+ const stale = files.filter((f) => f.status === 'stale');
518
549
  printOut(`[diff] deployed ${target} vs source (theme: ${theme})\n`);
519
550
  printOut(`[diff] ${edited.length} edited, ${added.length} added-in-deployed, `
520
551
  + `${missing.length} missing-from-deployed\n`);
521
552
  // Its own line, printed only when there is one, so the summary above is unchanged otherwise.
522
553
  if (linked.length) printOut(`[diff] ${linked.length} linked (yours, left alone)\n`);
554
+ if (stale.length) printOut(`[diff] ${stale.length} file(s) behind source — rebuild to update them\n`);
523
555
  const notes = collectNotes(target);
524
556
  if (notes.length) printOut(`[diff] ${notes.length} self-improvement note(s) to back-port\n`);
525
557
  for (const f of edited) printOut(` ~ ${f.rel} (edited in deployed — review to back-port)\n`);
526
558
  for (const f of added) printOut(` + ${f.rel} (only in deployed — your addition)\n`);
527
559
  for (const f of missing) printOut(` - ${f.rel} (in source, not deployed — re-emit to add)\n`);
528
560
  for (const f of linked) printOut(` = ${f.rel} (a link — yours, left alone)\n`);
561
+ for (const f of stale) printOut(` · ${f.rel} (behind source — a rebuild updates it)\n`);
529
562
  for (const n of notes) printOut(` * ${n.rel} (self-improvement note — review to back-port)\n`);
530
563
  if (args.out) {
531
- if (drifted(files).length || notes.length) {
564
+ if (localChanges(files).length || notes.length) {
532
565
  // Bare `--out` is argparse's `nargs="?"` const: True, meaning "the default timestamped
533
566
  // path". `parse()` gives a flag `true` and an option a string, so the two arrive
534
567
  // distinguishable here without a third kind of entry in the VERBS table.
@@ -466,7 +466,9 @@ export function buildOverride(state, body) {
466
466
  * deliberately carries none of this install's switches or exclusions — and keeps the defaults it
467
467
  * always had: footprint, posture
468
468
  * and mode off the viewed dir, and ALL packs when unknown — never `harness.config.json`, which
469
- * would drop the consent gate.
469
+ * would drop the consent gate. The one exception is the footprint with NOTHING deployed: the
470
+ * viewed dir then has no footprint of its own (`footprintOfDir`'s no-marker answer is `full`),
471
+ * so a first install takes the CLI's default, lean — see `apiDeployCmd`.
470
472
  */
471
473
  export function buildActionCmds(state, body) {
472
474
  const [theme, emit] = buildOverride(state, body);
@@ -486,7 +488,8 @@ export function buildActionCmds(state, body) {
486
488
  + 'not Build' };
487
489
  }
488
490
  return actionCommands('build', {
489
- theme, emit, footprint: state.footprint, posture: state.posture, mode: state.mode,
491
+ theme, emit, footprint: deployed(state) ? state.footprint : 'lean',
492
+ posture: state.posture, mode: state.mode,
490
493
  trust: state.trust,
491
494
  doctrines: doctrinesForBuild(state.target),
492
495
  });
@@ -673,8 +676,11 @@ export function apiInstallCmd(state, body) {
673
676
  // Every read-back below is narrowed to `host`'s OWN carrier (host-compat B1) — see the
674
677
  // comment at `installProfile` in `js/build/generate.mjs`.
675
678
  // The theme default is THIS install's own, not the viewed one's: the Kits tab acts on any row.
679
+ // An ABSENT row has no footprint of its own (`footprintOfDir` answers its no-marker `full`),
680
+ // so a new install takes the CLI's default, lean — see `apiDeployCmd` below.
676
681
  const { theme, footprint: fp, posture: pos, mode, trust } = bodyAxes(body, {
677
- theme: themeOfDir(root, host) || state.theme, footprint: footprintOfDir(root),
682
+ theme: themeOfDir(root, host) || state.theme,
683
+ footprint: installState(root, host, scope) === 'absent' ? 'lean' : footprintOfDir(root),
678
684
  posture: postureOfDir(root, host) || 'peer',
679
685
  mode: modeOfDir(root, host) || 'direct', trust: trustOfDir(root, host) || DEFAULT_PRESET });
680
686
  // Unspecified means "keep what this install already has", exactly as theme, footprint,
@@ -792,9 +798,12 @@ export function apiDeployCmd(state, body) {
792
798
  return { error: `${root} predates the comms pack (its carrier names 'process 8') — `
793
799
  + 'run `geneseed setup` for it before deploying over it' };
794
800
  }
795
- // A fresh deploy is full, at the default register, mode and trust.
801
+ // A fresh deploy is LEAN, at the default register, mode and trust: the same default as the
802
+ // CLI's `--footprint`, which the user chose (2026-10-24) over the console's old `full` — a
803
+ // console install and a CLI install of the same folder must not differ in always-on text for
804
+ // no reason the user picked. An explicit `full` in the body still wins.
796
805
  const { theme, footprint: fp, posture: pos, mode, trust } = bodyAxes(body, {
797
- theme: state.theme, footprint: 'full', posture: 'peer', mode: 'direct',
806
+ theme: state.theme, footprint: 'lean', posture: 'peer', mode: 'direct',
798
807
  trust: DEFAULT_PRESET });
799
808
  // Same resolution as `apiInstallCmd` above, and for the same reason: the console's Deploy
800
809
  // form sends host/path/theme/footprint/posture/mode and NO pack selection, and nothing stops
package/js/web/api.mjs CHANGED
@@ -144,13 +144,15 @@ const memoOf = (state) => (state.renderMemo ??= renderMemo());
144
144
 
145
145
  /**
146
146
  * The edited/added/missing tally of a `diffCollect` file list, and apart from it the `linked`
147
- * paths — the user's own links, which the console never adds into a drift total.
147
+ * paths — the user's own links, which the console never adds into a drift total — and the
148
+ * `stale` ones, unedited files a rebuild updates, which the console shows as "behind".
148
149
  */
149
150
  const driftCounts = (files) => ({
150
151
  edited: files.filter((f) => f.status === 'edited').length,
151
152
  added: files.filter((f) => f.status === 'added').length,
152
153
  missing: files.filter((f) => f.status === 'missing').length,
153
154
  linked: files.filter((f) => f.status === 'linked').length,
155
+ stale: files.filter((f) => f.status === 'stale').length,
154
156
  });
155
157
 
156
158
  /**
@@ -24,7 +24,8 @@ import { readText, withDiscardableStderr, isDir, isFile } from '../lib/fs.mjs';
24
24
  import { comparePaths, normcase, within } from '../lib/paths.mjs';
25
25
  import { stripWhitespace } from '../lib/text.mjs';
26
26
  import { readJsonc } from '../hosts/settings.mjs';
27
- import { loadKits } from '../build/source.mjs';
27
+ import { loadKits, makeCfg } from '../build/source.mjs';
28
+ import { loadTheme } from '../build/render.mjs';
28
29
 
29
30
  /** A requested catalog section or item that does not exist. */
30
31
  export class NotFound extends Error {}
@@ -482,6 +483,17 @@ function kitOwners() {
482
483
  return owner;
483
484
  }
484
485
 
486
+ /**
487
+ * The constitution's tier nouns in the install's own voice. Pack titles already arrive themed
488
+ * ("Observance"), so a page that hard-coded "Ethos" beside "Dictates" mixed two voices; the
489
+ * theme file is the one writer of these words. An unknown theme throws here exactly as it
490
+ * already throws in `tuiInventory` for the same `state.theme`, so this adds no failure mode.
491
+ */
492
+ function tierNouns(theme) {
493
+ const t = loadTheme(makeCfg(), theme);
494
+ return { ontology: t.ONTOLOGY, law: t.LAW, laws: t.LAWS, doctrines: t.DOCTRINES };
495
+ }
496
+
485
497
  export function apiCatalog(state, section) {
486
498
  if (!SECTIONS.includes(section)) throw new NotFound(section);
487
499
  const inv = state.inventory;
@@ -494,7 +506,7 @@ export function apiCatalog(state, section) {
494
506
  items = inv.skills.map((e) => ({ name: e.name, title: e.name, desc: e.desc,
495
507
  source: e.source ?? null, klass: e.klass ?? 'build', status: e.status ?? 'unknown', kit: owner.get(`skill:${e.name}`) ?? null }));
496
508
  } else if (section === 'laws') {
497
- items = constitutionItems(inv);
509
+ return { section, items: constitutionItems(inv), nouns: tierNouns(state.theme) };
498
510
  } else if (section === 'memory') {
499
511
  items = memoryItems(state);
500
512
  } else if (section === 'notebook') {
package/js/web/docs.mjs CHANGED
@@ -18,7 +18,8 @@
18
18
  import { readdirSync } from 'node:fs';
19
19
  import path from 'node:path';
20
20
 
21
- import { DOCS, DOC_FOLDERS, ROOT, THEMES } from '../build/source.mjs';
21
+ import { DOCS, DOC_FOLDERS, ROOT, THEMES, resolveRuleIds } from '../build/source.mjs';
22
+ import { STRUCTURE, substitute } from '../build/render.mjs';
22
23
  import { cliReference } from '../ui/cli.mjs';
23
24
  import { readJsonMaybe, readMaybe } from '../hosts/installs.mjs';
24
25
  import { resolvePath } from '../hosts/hosts.mjs';
@@ -222,7 +223,9 @@ const GITHUB_BLOB = 'https://github.com/Arylmera/Geneseed/blob/main/';
222
223
  * A target that is a docs page becomes `#/docs/<id>` (its `#anchor` dropped — the console
223
224
  * addresses pages, not headings); any other repo file — a maintainer doc, a README under
224
225
  * `src/` — opens on GitHub, since the console does not serve it. Absolute URLs, in-page
225
- * anchors and fenced examples are left alone.
226
+ * anchors and fenced examples are left alone. So is a target that is no file at all: the
227
+ * memory convention shows example links (`topics/<topic>.md`) in code spans, and a GitHub URL
228
+ * to a file that does not exist is a dead link where the relative one is merely inert.
226
229
  */
227
230
  export function rewriteDocLinks(body, fromRel, idByRel) {
228
231
  if (!body.includes('.md')) return body;
@@ -233,7 +236,8 @@ export function rewriteDocLinks(body, fromRel, idByRel) {
233
236
  return line.replace(MD_LINK_RE, (m, target, anchor) => {
234
237
  const resolved = path.posix.normalize(path.posix.join(path.posix.dirname(fromRel), target));
235
238
  const id = idByRel.get(resolved);
236
- return id ? `](#/docs/${id})` : `](${GITHUB_BLOB}${resolved}${anchor ?? ''})`;
239
+ if (id) return `](#/docs/${id})`;
240
+ return isFile(path.join(ROOT, resolved)) ? `](${GITHUB_BLOB}${resolved}${anchor ?? ''})` : m;
237
241
  });
238
242
  }).join('\n');
239
243
  }
@@ -458,14 +462,28 @@ function readDocSource(rel) {
458
462
  return readMaybe(target) ?? '';
459
463
  }
460
464
 
465
+ /** A theme's words, `{}` for a theme that is missing or malformed — never a throw. */
466
+ function themeWords(theme) {
467
+ const doc = readJsonMaybe(path.join(THEMES, `${theme}.json`));
468
+ return doc && typeof doc === 'object' && !Array.isArray(doc) ? doc : {};
469
+ }
470
+
471
+ /**
472
+ * A `src/` file as an install would render it: rule citations named, then the deployed theme's
473
+ * words (neutral underneath, for a key the theme lacks) and the fixed STRUCTURE substituted —
474
+ * the build's own functions, so the page cannot drift from what lands on disk. Only string
475
+ * words go in: `substitute` throws on any other value, and a theme's AGENT_COLORS is a dict.
476
+ */
477
+ function renderSource(text, theme) {
478
+ const words = Object.entries({ ...themeWords('neutral'), ...themeWords(theme) })
479
+ .filter(([, v]) => typeof v === 'string');
480
+ return substitute(resolveRuleIds(text), { ...Object.fromEntries(words), ...STRUCTURE });
481
+ }
482
+
461
483
  /** The deployed theme's words beside the neutral ones, from `docs/reference/glossary.md`. */
462
484
  function glossary(state, page) {
463
- const load = (theme) => {
464
- const doc = readJsonMaybe(path.join(THEMES, `${theme}.json`));
465
- return doc && typeof doc === 'object' && !Array.isArray(doc) ? doc : {};
466
- };
467
- const neutral = load('neutral');
468
- const themed = state.theme !== 'neutral' ? load(state.theme) : neutral;
485
+ const neutral = themeWords('neutral');
486
+ const themed = state.theme !== 'neutral' ? themeWords(state.theme) : neutral;
469
487
  const rows = [];
470
488
  for (const { label, key, desc, analogy } of parseGlossaryTable(page.body ?? '')) {
471
489
  if (key === null) {
@@ -554,9 +572,11 @@ export function apiDocsPage(state, pageId, harnessName = null) {
554
572
  * using it.
555
573
  */
556
574
  const KIND_ROUTES = {
575
+ // The body's own H1 goes: MarkdownPage prints the page title as the H1, and a page has one.
557
576
  markdown: (state, pageId, page, hn) => {
558
- const body = rewriteDocLinks(stripHarnessBlocks(readDocSource(page.source), hn),
559
- page.source, idsByRel());
577
+ const text = renderSource(stripHarnessBlocks(readDocSource(page.source), hn), state.theme)
578
+ .replace(/^# [^\n]*(?:\r?\n)+/, '');
579
+ const body = rewriteDocLinks(text, page.source, idsByRel());
560
580
  return { id: pageId, title: page.title, kind: 'markdown', body,
561
581
  source: page.source, links: resolveLinks(state, body) };
562
582
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "Every field here is argued and gated in tests/unit/package_manifest.test.mjs. `files`, `bin` and `engines` each have a test that fails when reality drifts from this file; `version` mirrors harness.config.json and is gated too. Read that docblock before editing this one.",
3
3
  "name": "geneseed",
4
- "version": "4.17.2",
4
+ "version": "4.18.1",
5
5
  "description": "A portable, theme-able harness you implant once and use everywhere to grow a disciplined AI coding agent.",
6
6
  "keywords": [
7
7
  "ai",
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t,t as n}from"./react-DlYQp10C.js";import{t as r}from"./api-BfpZmUMI.js";import{D as i,O as a,R as o,U as s,it as c}from"./index--3760QWr.js";import{a as l,i as u,n as d,o as f,r as p,t as m}from"./activity-Jw8XcPiP.js";import{t as h}from"./usePoll-bDFN-Hr6.js";var g=e(t(),1),_=n();function v({s:e}){let t=p[e.status]||p.idle,n=e.files,r=e.todos,i=r&&r.total>0||e.error||e.blocked_on;return(0,_.jsxs)(`a`,{className:`card pad-md act-card`,href:`#/activity/${encodeURIComponent(e.session_id)}`,children:[(0,_.jsxs)(`div`,{className:`row between wrap gap-12`,children:[(0,_.jsxs)(`div`,{className:`row gap-10`,style:{minWidth:0},children:[(0,_.jsx)(`span`,{className:`feed-dot ${t.cls||`acc`}`,style:{width:9,height:9}}),(0,_.jsxs)(`div`,{style:{minWidth:0},children:[(0,_.jsx)(`h3`,{style:{margin:0},children:e.title||l(e.cwd)||e.session_id}),e.cwd&&(0,_.jsx)(`div`,{className:`dim mono`,style:{fontSize:12,...m},title:e.cwd,children:e.cwd})]})]}),(0,_.jsxs)(`div`,{className:`row gap-8`,style:{flexShrink:0},children:[e.model&&(0,_.jsx)(`span`,{className:`badge mono`,title:`model`,children:e.model}),e.agent&&(0,_.jsx)(`span`,{className:`badge`,children:e.agent}),(0,_.jsxs)(`span`,{className:`badge ${t.cls}`,children:[(0,_.jsx)(`span`,{className:`dot`}),t.label]}),(0,_.jsx)(o,{name:`chevron`,className:`glyph act-chev`})]})]}),e.phase&&(0,_.jsxs)(`div`,{className:`row gap-8`,style:{marginTop:10,fontSize:14},children:[(0,_.jsx)(o,{name:`activity`}),(0,_.jsx)(`span`,{style:m,children:e.phase})]}),(e.tokens>0||e.cost>0||e.turn_started_at||n&&n.count>0)&&(0,_.jsxs)(`div`,{className:`row wrap`,style:{gap:16,marginTop:12,fontSize:13,color:`var(--text-2)`},children:[e.tokens>0&&(0,_.jsxs)(`span`,{children:[f(e.tokens),` tok`]}),e.cost>0&&(0,_.jsxs)(`span`,{children:[`$`,e.cost.toFixed(2)]}),e.turn_started_at?(0,_.jsx)(`span`,{children:(0,_.jsx)(d,{startedAt:e.turn_started_at})}):null,n&&n.count>0&&(0,_.jsxs)(`span`,{children:[n.count,` file`,n.count===1?``:`s`,` `,(0,_.jsxs)(`span`,{style:{color:`var(--good)`},children:[`+`,n.additions]}),` `,(0,_.jsxs)(`span`,{style:{color:`var(--bad)`},children:[`−`,n.deletions]})]})]}),i&&(0,_.jsxs)(`div`,{className:`row between wrap gap-12`,style:{marginTop:12,paddingTop:10,borderTop:`1px solid var(--line)`},children:[r&&r.total>0?(0,_.jsxs)(`span`,{className:`row gap-8 dim`,style:{fontSize:13},children:[(0,_.jsx)(u,{done:r.done,total:r.total}),`plan `,r.done,`/`,r.total]}):(0,_.jsx)(`span`,{}),e.error?(0,_.jsx)(`span`,{className:`badge bad`,title:e.error,style:{maxWidth:300,...m},children:e.error}):e.blocked_on?(0,_.jsx)(`span`,{className:`badge bad`,title:e.blocked_on,style:{maxWidth:300,...m},children:e.blocked_on}):null]}),(0,_.jsxs)(`div`,{className:`dim mono`,style:{fontSize:11,marginTop:8},children:[`updated `,s(e.updated_at),` ago`]})]})}function y(){let[e,t]=(0,g.useState)(null),[n,o]=(0,g.useState)(``);h(e=>r.activity().then(n=>{e()&&(t(n),o(``))},t=>{e()&&o(t.message)}),2e3,[]);let s=!e||e.enabled!==!1,l=e?.activity||[],u=c(),d=async()=>{let e=!s;try{let n=await r.activityToggle(e);t(e=>({...e||{},enabled:n.enabled,activity:n.enabled&&e?.activity||[]})),o(``)}catch(e){o(e.message)}};return(0,_.jsxs)(`div`,{className:`narrow`,children:[(0,_.jsxs)(`div`,{className:`head-row mb-16`,children:[(0,_.jsxs)(`div`,{children:[(0,_.jsx)(`h1`,{className:`h`,children:`Activity`}),(0,_.jsx)(`p`,{className:`sub`,children:`Live OpenCode sessions this harness is running: what each one is doing right now. Refreshes every couple of seconds; sessions drop off when their process exits.`})]}),(0,_.jsxs)(`div`,{className:`row gap-10`,style:{alignItems:`center`,flexShrink:0},children:[(0,_.jsx)(`span`,{className:`dim mono`,style:{fontSize:12},children:s?`tracking on`:`tracking off`}),(0,_.jsx)(`div`,{className:`sw-toggle${s?` on`:``}`,role:`switch`,"aria-checked":s,"aria-label":`Toggle activity tracking`,tabIndex:0,onClick:d,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.key===` `&&e.preventDefault(),d())}})]})]}),(0,_.jsx)(i,{error:n,style:{marginBottom:12}}),e?s?l.length===0?(0,_.jsxs)(`div`,{className:`empty`,children:[(0,_.jsx)(`div`,{className:`big`,children:`No active sessions`}),`Run `,(0,_.jsx)(`code`,{children:`opencode`}),` and the sessions it spins up appear here.`]}):(0,_.jsx)(`div`,{className:`stack gap-12`,ref:u,children:l.map(e=>(0,_.jsx)(`div`,{"data-flip":e.session_id,children:(0,_.jsx)(v,{s:e})},e.session_id))}):(0,_.jsxs)(`div`,{className:`empty`,children:[(0,_.jsx)(`div`,{className:`big`,children:`Activity tracking is off`}),`The plugin isn't recording sessions. Flip the switch to turn it back on.`]}):(0,_.jsx)(a,{label:`Reading live sessions…`})]})}export{y as default};
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t,t as n}from"./react-DlYQp10C.js";import{t as r}from"./api-BfpZmUMI.js";import{D as i,O as a,R as o,U as s}from"./index--3760QWr.js";import{a as c,n as l,o as u,r as d,t as f}from"./activity-Jw8XcPiP.js";import{t as p}from"./usePoll-bDFN-Hr6.js";var m=e(t(),1),h=n();function g(e){return e.kind===`tool`?e.status===`error`?`bad`:e.status===`completed`?`ok`:`acc`:{retry:`warn`,error:`bad`,subtask:`acc`,text:`acc`}[e.kind]||``}function _({rec:e}){let t=e.who===`you`,n=[];t||(e.kind===`tool`&&e.ms!=null&&n.push(`${(e.ms/1e3).toFixed(1)}s`),e.kind===`step`&&(e.tokens&&n.push(`${u(e.tokens)} tok`),e.cost&&n.push(`$${e.cost.toFixed(2)}`)),e.kind===`subtask`&&e.agent&&n.unshift(e.agent));let r=!t&&(e.kind===`text`||e.kind===`thinking`||e.kind===`step`),i=t?e.text:e.label||e.snippet||e.kind;return(0,h.jsxs)(`div`,{className:`row gap-10`,style:{alignItems:`baseline`},children:[(0,h.jsx)(`span`,{className:`badge ${t?``:`acc`}`,style:{flexShrink:0,minWidth:52,justifyContent:`center`},children:t?`you`:`agent`}),(0,h.jsxs)(`div`,{style:{minWidth:0,flex:1,fontSize:13},children:[!t&&(0,h.jsx)(`span`,{className:`feed-dot ${g(e)||`acc`}`,style:{display:`inline-block`,marginRight:8,verticalAlign:`middle`}}),e.kind===`thinking`&&(0,h.jsx)(`span`,{className:`dim`,children:`thinking: `}),r?(0,h.jsx)(`span`,{className:`dim`,children:i}):t?i:(0,h.jsx)(`b`,{children:i}),e.error&&(0,h.jsxs)(`span`,{className:`dim`,children:[`: `,e.error]})]}),n.length>0&&(0,h.jsx)(`span`,{className:`dim mono`,style:{flexShrink:0,fontSize:12},children:n.join(` · `)})]})}function v({turns:e}){return!e||e.length===0?(0,h.jsx)(`div`,{className:`dim`,style:{fontSize:13},children:`No conversation captured yet.`}):(0,h.jsx)(`div`,{className:`stack gap-12`,children:e.map((e,t)=>{let n=e.role===`user`;return(0,h.jsxs)(`div`,{className:`row gap-10`,style:{alignItems:`baseline`},children:[(0,h.jsx)(`span`,{className:`badge ${n?``:`acc`}`,style:{flexShrink:0,minWidth:52,justifyContent:`center`},children:n?`you`:`agent`}),(0,h.jsx)(`div`,{style:{minWidth:0,fontSize:13,color:n?`inherit`:`var(--text-2)`},children:e.text})]},t)})})}function y({sid:e}){let[t,n]=(0,m.useState)(null),[g,y]=(0,m.useState)(``),[b,x]=(0,m.useState)(!1),[S,C]=(0,m.useState)(!1);p(t=>r.activityDetail(e).then(e=>{t()&&(n(e),y(``),x(!1))},e=>{t()&&(e.status===404?x(!0):y(e.message))}),2e3,[e]);let w=(0,h.jsxs)(`a`,{className:`btn ghost sm`,href:`#/activity`,style:{marginBottom:12,display:`inline-flex`,gap:6},children:[(0,h.jsx)(o,{name:`arrow`,style:{transform:`rotate(180deg)`}}),` Activity`]});if(b)return(0,h.jsxs)(`div`,{className:`narrow`,children:[w,(0,h.jsxs)(`div`,{className:`empty`,children:[(0,h.jsx)(`div`,{className:`big`,children:`Session ended`}),`It's no longer live. `,(0,h.jsx)(`a`,{href:`#/activity`,children:`Back to Activity`}),`.`]})]});if(!t)return(0,h.jsxs)(`div`,{className:`narrow`,children:[w,g?(0,h.jsx)(i,{error:g}):(0,h.jsx)(a,{label:`Loading session…`})]});let T=t.session,E=d[T.status]||d.idle,D=T.files,O=T.todos,k=!!(D&&D.items&&D.items.length>0),A=!!(O&&O.items&&O.items.length>0),j=t.conversation||[],M=t.timeline||[],N=[...j.filter(e=>e.role===`user`).map(e=>({who:`you`,text:e.text,t:e.t||0})),...M.map(e=>({...e,who:`agent`}))].sort((e,t)=>(e.t||0)-(t.t||0));return(0,h.jsxs)(`div`,{className:`narrow`,children:[w,g&&(0,h.jsx)(`p`,{className:`badge bad`,style:{marginBottom:12},children:g}),(0,h.jsxs)(`div`,{className:`card pad-md`,children:[(0,h.jsxs)(`div`,{className:`row between wrap gap-12`,children:[(0,h.jsxs)(`div`,{style:{minWidth:0},children:[(0,h.jsx)(`h1`,{className:`h`,style:{margin:0},children:T.title||c(T.cwd)||T.session_id}),T.cwd&&(0,h.jsx)(`div`,{className:`dim mono`,style:{fontSize:12,...f},title:T.cwd,children:T.cwd})]}),(0,h.jsxs)(`div`,{className:`row gap-8`,style:{flexShrink:0},children:[T.model&&(0,h.jsx)(`span`,{className:`badge mono`,children:T.model}),T.agent&&(0,h.jsx)(`span`,{className:`badge`,children:T.agent}),(0,h.jsxs)(`span`,{className:`badge ${E.cls}`,children:[(0,h.jsx)(`span`,{className:`dot`}),E.label]})]})]}),T.phase&&(0,h.jsxs)(`div`,{className:`row gap-8`,style:{marginTop:10,fontSize:14},children:[(0,h.jsx)(o,{name:`activity`}),(0,h.jsx)(`span`,{style:f,children:T.phase})]}),(0,h.jsxs)(`div`,{className:`row wrap`,style:{gap:16,marginTop:12,fontSize:13,color:`var(--text-2)`},children:[T.tokens>0&&(0,h.jsxs)(`span`,{children:[u(T.tokens),` tok`]}),T.cost>0&&(0,h.jsxs)(`span`,{children:[`$`,T.cost.toFixed(2)]}),T.turn_started_at?(0,h.jsx)(`span`,{children:(0,h.jsx)(l,{startedAt:T.turn_started_at})}):null,(0,h.jsxs)(`span`,{className:`dim`,children:[`updated `,s(T.updated_at),` ago`]})]}),(T.error||T.blocked_on)&&(0,h.jsx)(`div`,{style:{marginTop:10},children:(0,h.jsx)(`span`,{className:`badge bad`,style:{maxWidth:`100%`,...f},children:T.error||T.blocked_on})})]}),(k||A)&&(0,h.jsxs)(`div`,{className:`grid gap-12`,style:{marginTop:12,gridTemplateColumns:k&&A?`minmax(0, 1fr) minmax(0, 1fr)`:`1fr`},children:[k&&(0,h.jsxs)(`div`,{className:`card pad-md`,children:[(0,h.jsx)(`div`,{className:`card-head`,children:(0,h.jsxs)(`h3`,{children:[`Files touched `,(0,h.jsxs)(`span`,{className:`dim`,children:[`(`,D.count,`)`]})]})}),(0,h.jsx)(`div`,{className:`stack`,style:{gap:6,marginTop:8},children:D.items.map(e=>(0,h.jsxs)(`div`,{className:`row between gap-12`,style:{fontSize:13},children:[(0,h.jsx)(`span`,{className:`mono`,style:{...f,minWidth:0,flex:1},title:e.file,children:e.file}),(0,h.jsxs)(`span`,{style:{flexShrink:0},children:[(0,h.jsxs)(`span`,{style:{color:`var(--good)`},children:[`+`,e.additions]}),` `,(0,h.jsxs)(`span`,{style:{color:`var(--bad)`},children:[`−`,e.deletions]})]})]},e.file))})]}),A&&(0,h.jsxs)(`div`,{className:`card pad-md`,children:[(0,h.jsx)(`div`,{className:`card-head`,children:(0,h.jsxs)(`h3`,{children:[`Plan`,` `,(0,h.jsxs)(`span`,{className:`dim`,children:[`(`,O.done,`/`,O.total,`)`]})]})}),(0,h.jsx)(`div`,{className:`stack`,style:{gap:6,marginTop:8},children:O.items.map((e,t)=>(0,h.jsxs)(`div`,{className:`row gap-8`,style:{fontSize:13},children:[(0,h.jsx)(`span`,{className:`feed-dot ${e.status===`completed`?`ok`:e.status===`in_progress`?`acc`:``}`}),(0,h.jsx)(`span`,{style:{textDecoration:e.status===`completed`?`line-through`:`none`,color:e.status===`completed`?`var(--text-3)`:`inherit`},children:e.content})]},t))})]})]}),(0,h.jsxs)(`div`,{className:`card pad-md`,style:{marginTop:12},children:[(0,h.jsxs)(`div`,{className:`card-head`,style:{justifyContent:`space-between`,marginBottom:12},children:[(0,h.jsx)(`h3`,{children:`Timeline`}),M.length>0&&(0,h.jsx)(`button`,{className:`btn ghost sm`,onClick:()=>C(e=>!e),children:S?`Show conversation`:`Show all ${M.length} steps`})]}),S?(0,h.jsx)(`div`,{className:`stack gap-12`,children:N.map((e,t)=>(0,h.jsx)(_,{rec:e},t))}):(0,h.jsx)(v,{turns:j})]})]})}export{y as default};
@@ -0,0 +1,3 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GreenhouseView-De8W1BvM.js","assets/rolldown-runtime-hePW80VL.js","assets/react-DlYQp10C.js","assets/drawable-CuQpH-f5.js","assets/index--3760QWr.js","assets/api-BfpZmUMI.js","assets/sections-ChwaobfW.js","assets/index-FWb-1Qgz.css","assets/OperatorHudView-BB8BH5PL.js","assets/JournalView-DZHR1l1P.js"])))=>i.map(i=>d[i]);
2
+ import{n as e,r as t}from"./rolldown-runtime-hePW80VL.js";import{i as n,t as r}from"./react-DlYQp10C.js";import{t as i}from"./api-BfpZmUMI.js";import{n as a,r as o}from"./sections-ChwaobfW.js";import{A as s,B as c,D as l,E as u,G as d,H as f,O as p,Q as m,R as h,S as g,U as _,V as v,c as y,et as b,rt as x,t as S}from"./index--3760QWr.js";var C=t(n(),1),w=r(),T=864e5;function E(e,t=10,n=`today`){let r=Array(t).fill(0).map((e,r)=>({t:r===t-1?n:`${t-1-r}d`,v:0})),i=Date.now();for(let n of e){let e=n.started||n.finished||n.created||n.ts;if(!e)continue;let a=typeof e==`string`?Date.parse(e):e*1e3;if(!Number.isFinite(a))continue;let o=Math.floor((i-a)/T);o<0||o>=t||(r[t-1-o].v+=1)}return r}var D=(e,t)=>[...e||[]].sort((e,t)=>(t.started||0)-(e.started||0)).slice(0,t),O=[`--emit`,`--theme`,`--scope`],k={done:`✓`,failed:`✗`};function A(e){let t=(e.output||``).split(`
3
+ `).find(e=>e.startsWith(`$ `))||``,n=t.split(/\s+/),r=[];return n.forEach((e,t)=>{let[i,a]=e.split(`=`),o=a||n[t+1];O.includes(i)&&o&&!o.startsWith(`--`)&&r.push(o)}),{verb:(e.action||`run`).split(/[\s(]/)[0],scope:r.join(` · `),result:k[e.status]||`…`,duration:e.duration?`${e.duration}s`:`—`,command:t}}var j={neutral:`Loaded & ready`,imperial:`The Codex in force`,military:`The unit stands ready`,cyberpunk:`Jacked in`,wizard:`Wards in place`,pirate:`The crew stands ready`,gamer:`Game loaded`,sports:`The squad takes the field`,biker:`The crew rolls out`,commentator:`Lights out, away we go`,verstappen:`Setup's in`,joker:`Mic check`,mean:`Rules are up`,marvin:`Online. Reluctantly.`},M=(e,t)=>e.deployed?t===void 0||t===`good`?j[e.theme]||`Loaded & ready`:`Deployed`:`Not deployed`,N={good:`ok`,warn:`warn`,bad:`bad`};function P({verdict:e}){return e?(0,w.jsxs)(`span`,{className:`badge ${N[e.tone]}`,role:`status`,style:{alignSelf:`flex-start`},children:[(0,w.jsx)(`span`,{className:`dot`}),e.head]}):null}function F({value:e,size:t=232}){let n=x(e,1100)??0,r=t/2-14,i=2*Math.PI*r,a=i*(1-n);return(0,w.jsxs)(`div`,{className:`ring-wrap`,style:{width:t,height:t},children:[(0,w.jsxs)(`svg`,{viewBox:`0 0 ${t} ${t}`,children:[(0,w.jsx)(`circle`,{cx:t/2,cy:t/2,r,fill:`none`,stroke:`var(--surface-3)`,strokeWidth:`10`}),(0,w.jsx)(`circle`,{cx:t/2,cy:t/2,r,fill:`none`,stroke:`var(--accent)`,strokeWidth:`10`,strokeLinecap:`round`,strokeDasharray:i,strokeDashoffset:a}),Array.from({length:48}).map((e,i)=>{let a=i/48*2*Math.PI,o=r-18,s=r-24,c=t/2+Math.cos(a)*o,l=t/2+Math.sin(a)*o,u=t/2+Math.cos(a)*s,d=t/2+Math.sin(a)*s;return(0,w.jsx)(`line`,{x1:c,y1:l,x2:u,y2:d,stroke:`var(--line-2)`,strokeWidth:`1`,opacity:i/48<n?.9:.25},i)})]}),(0,w.jsxs)(`div`,{className:`ring-center`,children:[(0,w.jsxs)(`div`,{className:`pct`,children:[Math.round(n*100),(0,w.jsx)(`span`,{style:{fontSize:20,color:`var(--text-3)`},children:`%`})]}),(0,w.jsx)(`div`,{className:`lbl`,children:`germination`})]})]})}function I({overview:e}){let t=c(e.diff),n=e.counts||{};return(0,w.jsxs)(`div`,{className:`card kpiband rise mb-16`,children:[[{key:`agents`,label:`Agents`,hash:`#/agents`},{key:`skills`,label:`Skills`,hash:`#/skills`},{key:`laws`,label:`Dictates`,hash:`#/laws`}].map(e=>{let t=n[e.key];return(0,w.jsxs)(`a`,{className:`kseg`,href:e.hash,title:`Open ${e.label}`,children:[(0,w.jsx)(`span`,{className:`kseg-n`+(t===0?` zero`:``),children:t==null?`—`:(0,w.jsx)(b,{value:t})}),(0,w.jsx)(`span`,{className:`kseg-l`,children:e.label})]},e.key)}),(0,w.jsx)(`div`,{className:`kseg-spacer`}),(0,w.jsxs)(`button`,{className:`kseg`+(t>0?` hot`:``),onClick:()=>m(`#/diff`),title:`Open changes`,children:[(0,w.jsx)(`span`,{className:`kseg-n`+(t===0?` zero`:``),children:(0,w.jsx)(b,{value:t})}),(0,w.jsx)(`span`,{className:`kseg-l`,children:`Local edits`}),t>0&&(0,w.jsx)(`span`,{className:`delta up`,children:`▲`})]})]})}function L({overview:e}){return(0,w.jsx)(`div`,{className:`genome`,children:o.map((t,n)=>{let r=a[t],i=e.counts?.[t];return(0,w.jsxs)(`div`,{className:`card gcell rise`,style:{"--i":n},onClick:()=>m(`#/section/`+t),children:[(0,w.jsxs)(`div`,{className:`gtop`,children:[(0,w.jsx)(`span`,{className:`gname`,children:r.label}),(0,w.jsx)(h,{name:r.icon,className:`gicon`})]}),(0,w.jsx)(`div`,{className:`gcount`+(i===0?` zero`:``),children:i==null?`—`:(0,w.jsx)(b,{value:i})}),(0,w.jsx)(`div`,{className:`gdesc`,children:r.desc})]},t)})})}function R({jobs:e}){if(!e||e.length===0)return(0,w.jsx)(`div`,{className:`feed`,children:(0,w.jsxs)(`div`,{className:`empty`,children:[(0,w.jsx)(`div`,{className:`big`,children:`No activity yet`}),`Actions you run appear here.`]})});let t={done:`ok`,running:`acc`,failed:`bad`},n=D(e,8);return(0,w.jsx)(`div`,{className:`feed`,children:n.map(e=>(0,w.jsxs)(`div`,{className:`feed-row`,children:[(0,w.jsx)(`span`,{className:`feed-dot ${t[e.status]||`ok`}`}),(0,w.jsx)(`span`,{className:`feed-txt`,children:(0,w.jsx)(`b`,{children:e.action})}),(0,w.jsxs)(`span`,{className:`feed-when`,children:[_(e.started),` ago`]})]},e.id))})}function z({overview:e,sigil:t,setup:n,jobs:r,lens:i,onAction:a}){let s=M(e,i?.tone),c=f(e,n);return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:`card pad-lg rise mb-16`,children:(0,w.jsxs)(`div`,{className:`hero`,children:[(0,w.jsx)(F,{value:c}),(0,w.jsxs)(`div`,{className:`hero-facts`,children:[(0,w.jsx)(`div`,{className:`ttl`,children:s}),(0,w.jsx)(P,{verdict:i?.verdict}),t&&(0,w.jsxs)(`div`,{className:`voice-readout`,children:[(0,w.jsx)(`span`,{className:`vr-cur`,children:`▕`}),(0,w.jsx)(`span`,{className:`vr-txt`,children:t})]},e.theme),(0,w.jsxs)(`p`,{className:`sub`,children:[`One source rendered into `,(0,w.jsx)(`code`,{children:e.target}),`. Every repo on this machine inherits it.`]}),(0,w.jsxs)(`div`,{className:`hero-chips`,children:[(0,w.jsxs)(`span`,{className:`chip`,children:[(0,w.jsx)(`span`,{className:`ck`,children:`voice`}),(0,w.jsx)(`span`,{className:`cv`,style:{textTransform:`capitalize`},children:e.theme})]}),(0,w.jsxs)(`span`,{className:`chip`,children:[(0,w.jsx)(`span`,{className:`ck`,children:`mode`}),(0,w.jsx)(`span`,{className:`cv`,children:e.emit})]}),(0,w.jsxs)(`span`,{className:`chip`,children:[(0,w.jsx)(`span`,{className:`ck`,children:`footprint`}),(0,w.jsx)(`span`,{className:`cv`,children:e.footprint})]}),(0,w.jsxs)(`span`,{className:`chip`,children:[(0,w.jsx)(`span`,{className:`ck`,children:`built`}),(0,w.jsx)(`span`,{className:`cv`,children:e.build_time||`unknown`})]}),(0,w.jsxs)(`span`,{className:`chip`,children:[(0,w.jsx)(`span`,{className:`ck`,children:`fp`}),(0,w.jsx)(`span`,{className:`cv`,children:n?.installed_fp||`—`})]})]}),(0,w.jsxs)(`div`,{className:`row wrap gap-10`,children:[(0,w.jsxs)(`button`,{className:`btn`,onClick:()=>a(`update`),children:[(0,w.jsx)(h,{name:`refresh`}),`Update`]}),(0,w.jsxs)(`button`,{className:`btn ghost`,onClick:()=>a(`build-all`),children:[(0,w.jsx)(h,{name:`build`}),`Rebuild`]}),(0,w.jsxs)(`button`,{className:`btn ghost`,onClick:()=>a(`doctor`),children:[(0,w.jsx)(h,{name:`doctor`}),`Run doctor`]})]})]})]})}),(0,w.jsx)(I,{overview:e}),(0,w.jsxs)(`div`,{className:`grid split-status`,children:[(0,w.jsxs)(`div`,{className:`card pad-lg`,children:[(0,w.jsxs)(`div`,{className:`card-head`,children:[(0,w.jsx)(`h3`,{children:`Capability genome`}),(0,w.jsx)(`div`,{className:`right`,children:(0,w.jsxs)(`span`,{className:`tick`,children:[o.length,` sections`]})})]}),(0,w.jsx)(L,{overview:e})]}),(0,w.jsxs)(`div`,{className:`card pad-lg`,children:[(0,w.jsxs)(`div`,{className:`card-head`,children:[(0,w.jsx)(`h3`,{children:`Recent activity`}),(0,w.jsx)(`div`,{className:`right`,children:(0,w.jsxs)(`span`,{className:`badge acc`,children:[(0,w.jsx)(`span`,{className:`dot`}),`live`]})})]}),(0,w.jsx)(R,{jobs:r})]})]})]})}function B({k:e,overview:t,max:n}){let r=a[e],i=t.counts?.[e]??0;return(0,w.jsxs)(`div`,{className:`strand`,children:[(0,w.jsxs)(`span`,{className:`strand-name`,children:[(0,w.jsx)(`span`,{className:`strand-dot`}),(0,w.jsx)(`a`,{href:`#/section/`+e,className:`strand-link stretch-link`,children:r.label})]}),(0,w.jsx)(`div`,{className:`hbar`,children:(0,w.jsx)(`i`,{style:{width:`${i/n*100}%`}})}),(0,w.jsx)(`span`,{className:`strand-val`,children:i})]})}function V(e){return e?e.includes(`up to date`)?{label:`in sync`,tone:`ok`}:e.includes(`no Geneseed install`)?{label:`not installed`,tone:``}:{label:`behind source`,tone:`warn`}:null}function H({overview:e,sigil:t,setup:n,jobs:r,lens:i}){let a=v(e.counts),s=n?.version_verdict||``,l=V(s),u=c(e.diff),d=[[`Source`,`src/, the canonical genetic material`,n?.source_fp||`—`,!0],[`Render`,`geneseed build → ${e.emit}`,e.theme+` voice`,!0],[`Deployed`,e.target,`inherited by every repo`,!1]];return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:`mb-16`,children:(0,w.jsxs)(`div`,{className:`card pad-lg rise`,style:{position:`relative`,overflow:`hidden`},children:[(0,w.jsx)(`h2`,{className:`h`,style:{fontSize:22,margin:`0 0 18px`},children:`Gene-seed lineage`}),(0,w.jsxs)(`div`,{className:`lineage-track`,children:[(0,w.jsx)(`div`,{className:`spine`}),d.map(([e,t,n,r],i)=>(0,w.jsxs)(`div`,{className:`lineage-step`,children:[(0,w.jsx)(`span`,{className:`node ${r?`on`:``}`}),(0,w.jsx)(`div`,{className:`lt`,children:e}),(0,w.jsx)(`div`,{className:`ld`,children:t}),(0,w.jsx)(`div`,{className:`ltag`,children:n})]},i))]}),(0,w.jsx)(`hr`,{className:`hr`}),t&&(0,w.jsxs)(`div`,{className:`voice-readout`,style:{marginBottom:14},children:[(0,w.jsx)(`span`,{className:`vr-cur`,children:`▕`}),(0,w.jsx)(`span`,{className:`vr-txt`,children:t})]},e.theme),(0,w.jsxs)(`div`,{className:`row wrap gap-10`,children:[(0,w.jsx)(P,{verdict:i?.verdict}),l&&(0,w.jsxs)(`span`,{className:`badge ${l.tone}`,title:s,children:[(0,w.jsx)(`span`,{className:`dot`}),l.label]}),(0,w.jsxs)(`span`,{className:`badge`,children:[(0,w.jsx)(`span`,{className:`dot`}),u,` local edits`]})]})]})}),(0,w.jsxs)(`div`,{className:`grid split-even`,children:[(0,w.jsxs)(`div`,{className:`card pad-lg`,children:[(0,w.jsxs)(`div`,{className:`card-head`,children:[(0,w.jsx)(`h3`,{children:`Genome strand`}),(0,w.jsx)(`div`,{className:`right`,children:(0,w.jsx)(`span`,{className:`tick`,children:`by volume`})})]}),o.map(t=>(0,w.jsx)(B,{k:t,overview:e,max:a},t))]}),(0,w.jsxs)(`div`,{className:`card pad-lg`,children:[(0,w.jsx)(`div`,{className:`card-head`,children:(0,w.jsx)(`h3`,{children:`Recent activity`})}),(0,w.jsx)(R,{jobs:r})]})]})]})}function U({overview:e,setup:t,jobs:n,lens:r}){let i=o.reduce((t,n)=>t+(e.counts?.[n]??0),0),s=v(e.counts),l=e.doctor?.ok,u=e.doctor?.problems?.length??0,d=c(e.diff);return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:`card pad-md rise mb-16`,children:(0,w.jsx)(`div`,{className:`row wrap between gap-16`,children:(0,w.jsxs)(`div`,{className:`row`,style:{gap:20,flexWrap:`wrap`},children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`tick`,children:`status`}),(0,w.jsxs)(`div`,{className:`row`,style:{gap:8,marginTop:4},children:[(0,w.jsxs)(`span`,{className:`badge ${e.deployed?`ok`:`warn`}`,children:[(0,w.jsx)(`span`,{className:`dot`}),e.deployed?`deployed`:`not deployed`]}),(0,w.jsx)(P,{verdict:r?.verdict})]})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`tick`,children:`voice`}),(0,w.jsx)(`div`,{className:`metric`,style:{fontSize:18,marginTop:6,textTransform:`capitalize`},children:e.theme})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`tick`,children:`mode`}),(0,w.jsx)(`div`,{className:`mono`,style:{fontSize:14,marginTop:6},children:e.emit})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`tick`,children:`fingerprint`}),(0,w.jsx)(`div`,{className:`mono`,style:{fontSize:14,marginTop:6,color:`var(--accent)`},children:t?.installed_fp||`—`})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`tick`,children:`doctor`}),(0,w.jsx)(`div`,{className:`row`,style:{gap:8,marginTop:4},children:l?(0,w.jsxs)(`span`,{className:`badge ok`,children:[(0,w.jsx)(`span`,{className:`dot`}),`clean`]}):(0,w.jsxs)(`span`,{className:`badge warn`,children:[(0,w.jsx)(`span`,{className:`dot`}),u,` issue`,u===1?``:`s`]})})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`tick`,children:`edits`}),(0,w.jsx)(`div`,{className:`metric`,style:{fontSize:18,marginTop:6},children:d})]})]})})}),(0,w.jsxs)(`div`,{className:`grid split-operator`,children:[(0,w.jsxs)(`div`,{className:`card rise`,style:{"--i":1},children:[(0,w.jsxs)(`div`,{className:`card-head pad-lg`,style:{padding:`18px 20px 0`,marginBottom:14},children:[(0,w.jsx)(`h3`,{children:`Sections`}),(0,w.jsx)(`div`,{className:`right`,children:(0,w.jsxs)(`span`,{className:`tick`,children:[i,` entries total`]})})]}),(0,w.jsxs)(`table`,{className:`tbl`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{children:[(0,w.jsx)(`th`,{children:`Section`}),(0,w.jsx)(`th`,{children:`Detail`}),(0,w.jsx)(`th`,{style:{width:130},children:`Share`}),(0,w.jsx)(`th`,{className:`num`,children:`Count`})]})}),(0,w.jsx)(`tbody`,{children:o.map(t=>{let n=a[t],r=e.counts?.[t]??0;return(0,w.jsxs)(`tr`,{className:`clickable`,children:[(0,w.jsx)(`td`,{className:`name`,children:(0,w.jsx)(`a`,{href:`#/section/`+t,className:`stretch-link`,children:n.label})}),(0,w.jsx)(`td`,{className:`muted`,children:n.desc}),(0,w.jsx)(`td`,{children:(0,w.jsx)(`div`,{className:`hbar`,children:(0,w.jsx)(`i`,{style:{width:`${r/s*100}%`}})})}),(0,w.jsx)(`td`,{className:`num`,children:r})]},t)})})]})]}),(0,w.jsxs)(`div`,{className:`card pad-lg rise`,style:{"--i":2},children:[(0,w.jsx)(`div`,{className:`card-head`,children:(0,w.jsx)(`h3`,{children:`Run log`})}),(0,w.jsx)(R,{jobs:n})]})]})]})}var W=Symbol(`failed`),G=e=>Promise.resolve().then(e).catch(()=>W);function K({dataRev:e,needDoctor:t}){let n=d(()=>G(()=>i.fleet()),[e]),r=d(()=>t?G(()=>i.doctor()):Promise.resolve(null),[t,e]),a=n.data,o=a==null?`loading`:a===W?`failed`:`ok`,s=o===`ok`?a:null,c=s?y(s):null,l=r.data,u=t?l==null?`loading`:l===W?`failed`:`ok`:`idle`;return{fleet:s,fleetState:o,verdict:c,tone:o===`failed`?`failed`:c?.tone,doctor:{state:u,data:u===`ok`?r.data:null}}}var q=e({default:()=>Z}),J=(0,C.lazy)(()=>S(()=>import(`./GreenhouseView-De8W1BvM.js`),__vite__mapDeps([0,1,2,3,4,5,6,7]))),Y=(0,C.lazy)(()=>S(()=>import(`./OperatorHudView-BB8BH5PL.js`),__vite__mapDeps([8,1,2,6,4,5,7]))),X=(0,C.lazy)(()=>S(()=>import(`./JournalView-DZHR1l1P.js`),__vite__mapDeps([9,1,2,5,3,4,6,7])));function Z({overview:e,overviewError:t,onRetry:n,themes:r,setup:a,runs:o,onAction:c,layout:f=`cultivar`,dataRev:m}){let h=f,[_,v]=(0,C.useState)(`status`),y=e&&r.find(t=>t.name===e.theme)?.sigil||``,b=K({dataRev:m,needDoctor:h===`greenhouse`||h===`operator`}),{data:x}=d(()=>h===`journal`?i.recent().catch(()=>null):Promise.resolve(null),[h,m]);if(!e)return t?(0,w.jsxs)(`div`,{children:[(0,w.jsx)(l,{error:`Could not load the harness overview: ${t}`}),(0,w.jsx)(`button`,{className:`btn`,onClick:n,children:`Retry`})]}):(0,w.jsx)(p,{});let S=e.daemon_stale?(0,w.jsx)(u,{}):null;return e.deployed?_===`status`&&h===`journal`?(0,w.jsxs)(C.Suspense,{fallback:(0,w.jsx)(p,{}),children:[S,(0,w.jsx)(X,{overview:e,recent:x,lens:b,onAction:c,onDirection:v,dataRev:m})]}):(0,w.jsxs)(w.Fragment,{children:[S,(0,w.jsx)(`div`,{className:`head-row`,children:(0,w.jsx)(s,{"aria-label":`Dashboard view`,children:[[`status`,`Status`],[`lineage`,`Lineage`],[`operator`,`Operator`]].map(([e,t])=>(0,w.jsx)(`button`,{className:_===e?`on`:``,onClick:()=>v(e),"aria-pressed":_===e,children:t},e))})}),(0,w.jsxs)(`div`,{className:`view-in`,children:[_===`status`&&h===`cultivar`&&(0,w.jsx)(z,{overview:e,sigil:y,setup:a,jobs:o,lens:b,onAction:c}),_===`status`&&h===`greenhouse`&&(0,w.jsx)(C.Suspense,{fallback:(0,w.jsx)(p,{}),children:(0,w.jsx)(J,{overview:e,sigil:y,jobs:o,lens:b,onAction:c})}),_===`status`&&h===`operator`&&(0,w.jsx)(C.Suspense,{fallback:(0,w.jsx)(p,{}),children:(0,w.jsx)(Y,{overview:e,jobs:o,lens:b,onAction:c})}),_===`lineage`&&(0,w.jsx)(H,{overview:e,sigil:y,setup:a,jobs:o,lens:b}),_===`operator`&&(0,w.jsx)(U,{overview:e,setup:a,jobs:o,lens:b})]},_)]}):(0,w.jsxs)(w.Fragment,{children:[S,(0,w.jsx)(g,{onAction:c})]})}export{A as a,Z as default,E as i,P as n,D as o,M as r,q as t};
@@ -0,0 +1,4 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t,t as n}from"./react-DlYQp10C.js";import{t as r}from"./api-BfpZmUMI.js";import{A as i,D as a,G as o,M as s,N as c,O as l,Q as u,R as d,a as f,i as p,j as m,n as h,o as g,r as _,s as v}from"./index--3760QWr.js";import{a as y,n as ee,o as te,r as b,t as x}from"./RailCats-D5RVYEjy.js";import{i as S,n as C,r as w}from"./Markdown-OReRRoEV.js";var T=e(t(),1);function E(e,t=0){let n=String(e).toLowerCase().trim().replace(/[^a-z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-+|-+$/g,``);return n&&/^[a-z]/.test(n)?n:`h-${t}-${n||`section`}`}function D(e){let t=[],n=[],r=`before`;for(let i of(e||``).split(`
2
+ `))r===`before`&&/^\|\s*piece\s*\|/i.test(i)?r=`map`:r===`map`&&!i.trimStart().startsWith(`|`)&&(r=`after`),r===`before`?t.push(i):r===`after`&&n.push(i);return[t.join(`
3
+ `),n.join(`
4
+ `)]}function O(e,t){let n=document.createElement(`template`);return n.innerHTML=e,n.content.querySelectorAll(`h1, h2, h3`).forEach(e=>{e.tagName!==`H1`&&(t.idx+=1);let n=e.id||E(e.textContent||``,t.idx),r=n;for(let e=2;t.ids.has(r);e++)r=`${n}-${e}`;t.ids.add(r),e.id=r,e.tagName!==`H1`&&t.toc.push({level:Number(e.tagName[1]),title:(e.textContent||``).trim(),id:r})}),n.content.querySelectorAll(`table`).forEach(e=>{let t=document.createElement(`div`);t.className=`table-scroll`,t.setAttribute(`tabindex`,`0`),t.setAttribute(`role`,`region`),t.setAttribute(`aria-label`,`Table`),e.replaceWith(t),t.appendChild(e)}),n.innerHTML}function k(e){let t={ids:new Set,idx:0,toc:[]},n=n=>O(C(n,e?.links),t);if(e?.rows){let[r,i]=D(e.body);return{before:n(r),after:n(i),toc:t.toc}}return{html:n(e?.body),toc:t.toc}}var A=n(),j={"opencode-global":[`install-opencode`,`Global (recommended)`],opencode:[`install-opencode`,`Per repo`],"claude-global":[`install-claude-code`],claude:[`install-claude-code`],"openclaude-global":[`install-openclaude`],openclaude:[`install-openclaude`],"bob-global":[`install-bob`],bob:[`install-bob`],files:[`install-agent-md`]},M=`you already know this`;function N({page:e,overview:t,onAction:n}){let r=(0,T.useRef)(null),i=(0,T.useMemo)(()=>k({body:e.body,links:e.links}).html,[e.body,e.links]);(0,T.useEffect)(()=>{let e=r.current;e&&e.querySelectorAll(`blockquote`).forEach(e=>{(e.querySelector(`strong`)?.textContent||``).toLowerCase().startsWith(M)&&e.classList.add(`analogy`)})},[i]),(0,T.useEffect)(()=>{let e=r.current;if(!e)return;let t=e=>{let t=e.target.closest(`a[href]`);if(!t)return;let n=t.getAttribute(`href`);n&&n.startsWith(`#/`)&&(e.preventDefault(),u(n))};return e.addEventListener(`click`,t),()=>e.removeEventListener(`click`,t)},[i]),(0,T.useEffect)(()=>{let n=r.current;if(!n)return;n.querySelectorAll(`.docs-here`).forEach(e=>e.classList.remove(`docs-here`));let[i,a]=j[t?.emit]||[];if(!i)return;let o=null;e.id===`install`?o=n.querySelector(`a[href="#/docs/${i}"]`)?.closest(`li`):e.id===i&&a&&(o=[...n.querySelectorAll(`h2`)].find(e=>E(e.textContent||``)===E(a))),o?.classList.add(`docs-here`)},[i,e.id,t?.emit]);let a=[];return e.id===`install`&&(a.push({label:`Run doctor`,action:`doctor`}),a.push({label:`Rebuild`,action:`build`})),e.id===`verify`&&a.push({label:`Run doctor`,action:`doctor`}),e.id===`upgrade`&&a.push({label:`Update`,action:`update`}),(0,A.jsxs)(`div`,{className:`detail-doc`,children:[(0,A.jsx)(`h1`,{style:{marginTop:0},children:e.title}),e.source&&(0,A.jsx)(`div`,{className:`doc-meta`,children:(0,A.jsxs)(`span`,{className:`badge`,children:[(0,A.jsx)(`span`,{className:`dot`}),e.source]})}),a.length>0&&(0,A.jsx)(`div`,{className:`row wrap gap-10`,style:{margin:`10px 0 14px`},children:a.map(e=>e.hash?(0,A.jsx)(`a`,{className:`btn ghost sm`,href:e.hash,children:e.label},e.label):(0,A.jsx)(`button`,{className:`btn ghost sm`,onClick:()=>n&&n(e.action),children:e.label},e.label))}),(0,A.jsx)(`div`,{className:`markdown`,ref:r,dangerouslySetInnerHTML:{__html:i}}),e.link&&(0,A.jsx)(`div`,{style:{marginTop:24},children:(0,A.jsx)(`a`,{className:`btn soft sm`,href:e.link.hash,children:e.link.label})})]})}var P=1200;function F({a:e,kind:t}){let n=t===`positional`?e.dest:e.names.join(`, `),r=[];return e.metavar&&r.push(e.metavar),e.choices&&r.push(`{${e.choices.join(`|`)}}`),e.default!==null&&e.default!==void 0&&e.default!==``&&!e.is_flag&&r.push(`default: ${e.default}`),e.required&&r.push(`required`),(0,A.jsxs)(`div`,{className:`cli-arg`,children:[(0,A.jsx)(`code`,{className:`cli-arg-name`,children:n}),r.length>0&&(0,A.jsxs)(`code`,{className:`cli-arg-meta`,children:[` `,r.join(` · `)]}),e.help&&(0,A.jsx)(`div`,{className:`cli-arg-help`,children:e.help})]})}function I({text:e}){let[t,n]=(0,T.useState)(!1);return(0,A.jsxs)(`button`,{className:`btn ghost sm`,onClick:async()=>{try{await navigator.clipboard.writeText(e),n(!0),setTimeout(()=>n(!1),P)}catch{}},title:`Copy command`,children:[(0,A.jsx)(d,{name:t?`spark`:`copy`}),t?`Copied`:`Copy`]})}function L({cmd:e,prog:t}){let n=[t,e.name];for(let t of e.positionals||[]){let e=(t.metavar||t.dest||``).toUpperCase();n.push(t.required?e:`[${e}]`)}(e.options||[]).length&&n.push(`[OPTIONS]`);let r=n.join(` `);return(0,A.jsxs)(`div`,{className:`card pad-md mb-12 cli-card`,children:[(0,A.jsxs)(`div`,{className:`row wrap between`,style:{alignItems:`flex-start`},children:[(0,A.jsxs)(`div`,{className:`stack`,style:{gap:4},children:[(0,A.jsx)(`h3`,{style:{margin:0},children:(0,A.jsx)(`code`,{children:e.name})}),e.help&&(0,A.jsx)(`p`,{className:`sub`,style:{margin:0},children:e.help})]}),(0,A.jsx)(I,{text:`${t} ${e.name}`})]}),(0,A.jsx)(`pre`,{className:`cli-syn`,children:r}),(e.positionals||[]).length>0&&(0,A.jsxs)(`div`,{className:`cli-block`,children:[(0,A.jsx)(`div`,{className:`cli-block-head`,children:`Arguments`}),e.positionals.map(e=>(0,A.jsx)(F,{a:e,kind:`positional`},e.dest))]}),(e.options||[]).length>0&&(0,A.jsxs)(`div`,{className:`cli-block`,children:[(0,A.jsx)(`div`,{className:`cli-block-head`,children:`Options`}),e.options.map(e=>(0,A.jsx)(F,{a:e,kind:`option`},e.names.join(`,`)))]})]})}function R({page:e}){let t=e.prog||`geneseed`,n=e.commands||[];return(0,A.jsxs)(`div`,{className:`detail-doc`,children:[(0,A.jsx)(`h1`,{style:{marginTop:0},children:e.title}),(0,A.jsxs)(`p`,{className:`sub`,style:{marginTop:4},children:[`Every subcommand of `,(0,A.jsx)(`code`,{children:t}),`. Generated from the parser at request time (the same one `,(0,A.jsx)(`code`,{children:`geneseed`}),` actually parses), so this page cannot drift.`]}),(0,A.jsx)(`div`,{style:{marginTop:18},children:n.map(e=>(0,A.jsx)(L,{cmd:e,prog:t},e.name))})]})}function z({page:e}){let t=e.rows||[],n=e.theme||`neutral`;return(0,A.jsxs)(`div`,{className:`detail-doc`,children:[(0,A.jsx)(`h1`,{style:{marginTop:0},children:e.title}),(0,A.jsxs)(`p`,{className:`sub`,style:{marginTop:4},children:[`Geneseed's invented vocabulary, decoded. Left: the neutral, plain-English term. Right: the word your `,(0,A.jsx)(`code`,{style:{textTransform:`capitalize`},children:n}),` theme actually uses in the agent's voice. Last: the developer idea it maps to.`]}),(0,A.jsx)(`div`,{className:`card pad-md`,style:{marginTop:18},children:(0,A.jsxs)(`table`,{className:`glossary-table`,children:[(0,A.jsx)(`thead`,{children:(0,A.jsxs)(`tr`,{children:[(0,A.jsx)(`th`,{children:`Concept`}),(0,A.jsx)(`th`,{children:`Neutral term`}),(0,A.jsxs)(`th`,{children:[`In `,n]}),(0,A.jsx)(`th`,{children:`Meaning`}),(0,A.jsx)(`th`,{children:`In dev terms`})]})}),(0,A.jsx)(`tbody`,{children:t.map(e=>(0,A.jsxs)(`tr`,{children:[(0,A.jsx)(`td`,{children:(0,A.jsx)(`strong`,{children:e.label})}),(0,A.jsx)(`td`,{children:(0,A.jsx)(`code`,{children:e.neutral||`—`})}),(0,A.jsx)(`td`,{children:(0,A.jsx)(`code`,{children:e.themed||e.neutral||`—`})}),(0,A.jsx)(`td`,{className:`dim`,children:e.desc}),(0,A.jsx)(`td`,{className:`dim`,children:e.analogy||`—`})]},e.label))})]})})]})}var B={enforced:`ok`,automatic:`ok`,asked:`warn`,"on demand":`warn`},V=({text:e})=>(0,A.jsx)(`span`,{dangerouslySetInnerHTML:{__html:w(S.parseInline(e||``))}}),H=({kind:e})=>(0,A.jsx)(`span`,{className:`tag ${B[e]||``}`,children:e});function U({page:e,overview:t,onAction:n}){let[r,i]=(0,T.useState)(0),{before:a,after:o}=(0,T.useMemo)(()=>k(e),[e]);if(!e.rows)return(0,A.jsx)(N,{page:e,overview:t,onAction:n});let s=e.rows[r]||e.rows[0];return(0,A.jsxs)(`div`,{className:`detail-doc`,children:[(0,A.jsx)(`h1`,{style:{marginTop:0},children:e.title}),(0,A.jsx)(`div`,{className:`markdown`,dangerouslySetInnerHTML:{__html:a}}),(0,A.jsxs)(`div`,{className:`docs-map`,children:[(0,A.jsx)(`ul`,{className:`map-tree`,"aria-label":`Pieces`,children:e.rows.map((e,t)=>(0,A.jsx)(`li`,{children:(0,A.jsxs)(`button`,{className:`map-node ${t===r?`on`:``}`,"aria-pressed":t===r,onClick:()=>i(t),children:[(0,A.jsx)(`span`,{className:`map-piece`,children:(0,A.jsx)(V,{text:e.piece})}),(0,A.jsx)(H,{kind:e.kind}),(0,A.jsx)(`span`,{className:`mono dim map-cost`,children:(0,A.jsx)(V,{text:e.cost})})]})},t))}),s&&(0,A.jsxs)(`div`,{className:`card pad-md map-detail`,"aria-live":`polite`,children:[(0,A.jsx)(`h3`,{style:{margin:`0 0 8px`},children:(0,A.jsx)(V,{text:s.piece})}),(0,A.jsx)(H,{kind:s.kind}),(0,A.jsxs)(`dl`,{children:[(0,A.jsx)(`dt`,{children:`Does`}),(0,A.jsx)(`dd`,{children:(0,A.jsx)(V,{text:s.does})}),(0,A.jsx)(`dt`,{children:`Costs`}),(0,A.jsx)(`dd`,{children:(0,A.jsx)(V,{text:s.cost})}),(0,A.jsx)(`dt`,{children:`Turn it off`}),(0,A.jsx)(`dd`,{children:(0,A.jsx)(V,{text:s.off})})]})]})]}),o.trim()&&(0,A.jsx)(`div`,{className:`markdown`,dangerouslySetInnerHTML:{__html:o}})]})}var W=5,G=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);function K(e,t){let n=e||``,r=[];for(let e of t||[])if([...new Set([e.themed,e.neutral,e.label].filter(Boolean))].some(e=>RegExp(`(?<![\\w-])${G(e)}s?(?![\\w-])`,`i`).test(n))&&r.push(e),r.length===W)break;return r}var q=e=>document.getElementById(e)?.scrollIntoView({behavior:`smooth`});function J({page:e,glossaryRows:t}){let n=e?.body,r=(0,T.useMemo)(()=>k(e).toc,[e]),i=(0,T.useMemo)(()=>K(n,t),[n,t]);return!r.length&&!i.length?null:(0,A.jsxs)(`aside`,{className:`docs-margin`,children:[r.length>0&&(0,A.jsxs)(`nav`,{className:`docs-toc`,"aria-label":`On this page`,children:[(0,A.jsx)(`div`,{className:`docs-toc-head`,children:`On this page`}),(0,A.jsx)(`ul`,{children:r.map(e=>(0,A.jsx)(`li`,{className:`lvl-${e.level}`,children:(0,A.jsx)(`a`,{href:`#${e.id}`,onClick:t=>{t.preventDefault(),q(e.id)},children:e.title})},e.id))})]}),i.length>0&&(0,A.jsxs)(`div`,{className:`docs-gloss`,children:[(0,A.jsx)(`div`,{className:`docs-toc-head`,children:`Terms on this page`}),i.map(e=>(0,A.jsxs)(`div`,{className:`docs-gloss-card`,children:[(0,A.jsx)(`b`,{children:e.themed||e.neutral||e.label}),(0,A.jsx)(`p`,{children:e.desc})]},e.label))]})]})}function Y({page:e}){let t=e.version||{},n=[[`Theme`,e.theme],[`Install mode`,e.emit],[`Deployed`,e.deployed?`yes`:`no`],[`Target`,(0,A.jsx)(`code`,{children:e.target},`t`)],[`Source root`,(0,A.jsx)(`code`,{children:e.root},`r`)],[`Installed build`,(0,A.jsx)(`code`,{children:t.installed_fp||`(none)`},`i`)],[`Source build`,(0,A.jsx)(`code`,{children:t.source_fp||`—`},`s`)],[`Match?`,t.verdict||`—`],[`License`,e.license]];return(0,A.jsxs)(`div`,{className:`detail-doc`,children:[(0,A.jsx)(`h1`,{style:{marginTop:0},children:e.title}),(0,A.jsx)(`p`,{className:`sub`,style:{marginTop:4},children:`Live snapshot of the install behind this UI, plus where to go next.`}),(0,A.jsx)(`div`,{className:`card pad-md`,style:{marginTop:18},children:n.map(([e,t])=>(0,A.jsxs)(`div`,{className:`kv`,children:[(0,A.jsx)(`span`,{className:`k`,children:e}),(0,A.jsx)(`span`,{className:`v`,children:t??`—`})]},e))}),(0,A.jsxs)(`div`,{className:`row wrap gap-10`,style:{marginTop:18},children:[(0,A.jsxs)(`a`,{className:`btn ghost`,href:e.repo,target:`_blank`,rel:`noreferrer`,children:[(0,A.jsx)(d,{name:`external`}),e.repo_is_github?`GitHub repo`:`Source repo`]}),e.repo_is_github&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsxs)(`a`,{className:`btn ghost`,href:`${e.repo}/issues`,target:`_blank`,rel:`noreferrer`,children:[(0,A.jsx)(d,{name:`external`}),`File an issue`]}),(0,A.jsxs)(`a`,{className:`btn ghost`,href:`${e.repo}/blob/main/LICENSE`,target:`_blank`,rel:`noreferrer`,children:[(0,A.jsx)(d,{name:`external`}),`License`]})]})]})]})}var X=encodeURIComponent,Z=e=>`#/docs/${X(e)}`;function Q(e){return e?.groups?.[0]?.pages?.[0]?.id||``}function ne({data:e,error:t,overview:n,onAction:r}){if(t)return(0,A.jsx)(a,{error:t,style:{margin:18}});if(!e)return(0,A.jsx)(l,{label:`Loading page…`});switch(e.kind){case`markdown`:case`concept`:return(0,A.jsx)(N,{page:e,overview:n,onAction:r});case`map`:return(0,A.jsx)(U,{page:e,overview:n,onAction:r});case`cli`:return(0,A.jsx)(R,{page:e});case`glossary`:return(0,A.jsx)(z,{page:e});case`about`:return(0,A.jsx)(Y,{page:e});default:return(0,A.jsxs)(`div`,{className:`empty`,children:[(0,A.jsx)(`div`,{className:`big`,children:`Unknown page kind`}),e.kind]})}}function $(e){return(e?.pages||[]).map(e=>({name:e.id,title:e.title,desc:e.description||``,group:e.section||`General`,groupC:`var(--accent)`}))}function re({page:e,overview:t,onAction:n}){let[u,d]=c(s(t?.emit)),{data:S,error:C}=o(()=>r.docs(u),[u]),w=e||Q(S),{data:E,error:D,loading:O}=o(()=>w?r.docsPage(w,u):Promise.resolve(null),[w,u]),{data:k}=o(()=>r.docsPage(`glossary`,u).catch(()=>null),[u],`docs:glossary`);(0,T.useEffect)(()=>{if(S&&w&&!S.groups.some(e=>e.pages.some(e=>e.id===w))){let e=Q(S);e&&e!==w&&window.location.replace(Z(e))}},[S,w]),(0,T.useEffect)(()=>{let e=document.scrollingElement||document.documentElement;for(let t of[document.getElementById(`main`),e])t&&(t.scrollTop=0)},[w]);let j=g(S,w),M=j.part||S?.groups?.[0]||null,N=M?.id===_;(0,T.useEffect)(()=>{N&&E?.id===w&&f(w)},[N,E,w]);let P=N?[...v(),w]:[],[F,I]=(0,T.useState)(``),[L,R]=(0,T.useState)(`all`),[z,B]=(0,T.useState)(M?.id);M?.id!==z&&(B(M?.id),I(``),R(`all`));let V=$(M),H=ee(V),U=L===`all`?V:V.filter(e=>e.group===L),W=te(U,F);return C?(0,A.jsx)(a,{error:C}):(0,A.jsx)(`div`,{className:`docs-wrap`,children:(0,A.jsxs)(`div`,{className:`library docs-lib`,children:[(0,A.jsxs)(`aside`,{className:`lib-kinds`,"aria-label":`Docs parts`,children:[(0,A.jsxs)(`div`,{className:`lib-title`,children:[(0,A.jsx)(`h1`,{className:`h`,children:`Docs`}),(0,A.jsx)(`span`,{className:`dim`,children:`How it works, and how to use it`})]}),(0,A.jsx)(i,{"aria-label":`Harness`,children:m.map(e=>(0,A.jsx)(`button`,{className:u===e.id?`on`:``,onClick:()=>d(e.id),"aria-pressed":u===e.id,children:e.label},e.id))}),(0,A.jsx)(`nav`,{className:`kind-list`,"aria-label":`Parts`,children:(S?.groups||[]).map(e=>(0,A.jsxs)(T.Fragment,{children:[(0,A.jsxs)(`a`,{href:e.pages[0]?Z(e.pages[0].id):`#/docs`,className:M?.id===e.id?`on`:``,"aria-current":M?.id===e.id?`page`:void 0,children:[e.label,(0,A.jsx)(`span`,{className:`mono dim`,children:e.pages.length})]}),M?.id===e.id&&(0,A.jsx)(x,{label:`Sections`,total:V.length,cats:H,cat:L,onChange:R})]},e.id))})]}),(0,A.jsx)(y,{label:M?.label||`Docs`,count:F.trim()?`${W.length} of ${U.length}`:U.length||``,extra:N&&(0,A.jsx)(p,{pages:M.pages,seen:P}),q:F,onQ:I,matched:W.length,inView:[M?.id,w],children:S?(0,A.jsx)(b,{rows:W,activeName:w,hrefOf:e=>Z(e.name),pills:N?e=>P.includes(e.name)&&e.name!==w?(0,A.jsx)(`span`,{className:`docs-read-mark`,role:`img`,"aria-label":`, read`,children:`✓`}):null:void 0}):(0,A.jsx)(l,{label:`Loading docs…`})}),(0,A.jsxs)(`article`,{className:`lib-reader docs-reader`,"aria-label":`Page`,children:[j.page&&(0,A.jsxs)(`nav`,{className:`docs-crumbs mono`,"aria-label":`Breadcrumb`,children:[(0,A.jsx)(`a`,{href:Z(j.part.pages[0].id),children:j.part.label}),(0,A.jsx)(`span`,{"aria-hidden":`true`,children:`›`}),(0,A.jsx)(`a`,{href:Z(j.part.pages.find(e=>(e.section||`General`)===j.section).id),children:j.section}),(0,A.jsx)(`span`,{"aria-hidden":`true`,children:`›`}),(0,A.jsx)(`span`,{"aria-current":`page`,children:j.page.title})]}),(0,A.jsxs)(`div`,{className:`docs-read`,children:[(0,A.jsxs)(`div`,{className:`docs-article`,children:[(0,A.jsx)(ne,{data:O?null:E,error:D,overview:t,onAction:n},`${w}|${u}`),!O&&(0,A.jsx)(h,{menu:S,pageId:w})]}),!O&&(0,A.jsx)(J,{page:E,glossaryRows:k?.rows})]})]})]})})}export{re as default,$ as docRows};
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t,t as n}from"./react-DlYQp10C.js";import{t as r}from"./drawable-CuQpH-f5.js";import{n as i,r as a}from"./sections-ChwaobfW.js";import{B as o,R as s,U as c,et as l,lt as u,nt as d,ot as f,tt as p}from"./index--3760QWr.js";import{a as m,i as h,n as g,o as _,r as v}from"./Dashboard-Ds7_blrK.js";var y=e(t(),1),b=n(),x=12,S=[`#2BB673`,`#16A6A6`,`#E8A23B`,`#E07A5F`,`#8E7DBE`,`#5BD08A`,`#79856E`],C=650;function w({segments:e,size:t=186,stroke:n=26,caption:i=`capabilities`}){let a=e.reduce((e,t)=>e+t.value,0),o=a||1,s=(0,y.useRef)(null),c=e.map(e=>e.value).join(`,`);(0,y.useLayoutEffect)(()=>{let t=s.current?.querySelectorAll(`path`);if(!t?.length||!p())return;let n=e.filter(e=>e.value>0).map(e=>e.value/o),i=n.map((e,t)=>n.slice(0,t).reduce((e,t)=>e+t,0)),a=r(t);f(a,{draw:`0 0`});let c=u(a,{draw:[`0 0`,`0 1`],duration:(e,t)=>Math.max(C*n[t],60),delay:(e,t)=>C*i[t],ease:`linear`});return d(c,C)},[c]);let m=t/2-n/2,h=t/2,g=t/2,_=[],v=0;for(let t of e)_.push(v),v+=t.value;return(0,b.jsxs)(`svg`,{width:t,height:t,viewBox:`0 0 ${t} ${t}`,children:[(0,b.jsx)(`circle`,{cx:h,cy:g,r:m,fill:`none`,stroke:`var(--surface-3)`,strokeWidth:n}),(0,b.jsx)(`g`,{ref:s,children:e.map((e,t)=>{let r=e.value/o;if(r<=0)return null;let i=_[t]/o*2*Math.PI-Math.PI/2,a=(_[t]+e.value)/o*2*Math.PI-Math.PI/2,s=h+m*Math.cos(i),c=g+m*Math.sin(i),l=h+m*Math.cos(a),u=g+m*Math.sin(a),d=+(a-i>Math.PI),f=r>=.9999?`M ${s} ${c} A ${m} ${m} 0 1 1 ${2*h-s} ${2*g-c} A ${m} ${m} 0 1 1 ${s} ${c}`:`M ${s} ${c} A ${m} ${m} 0 ${d} 1 ${l} ${u}`;return(0,b.jsx)(`path`,{d:f,fill:`none`,stroke:e.color,strokeWidth:n,strokeLinecap:`butt`,children:(0,b.jsxs)(`title`,{children:[e.label,`: `,e.value]})},t)})}),(0,b.jsx)(`text`,{x:h,y:g-4,textAnchor:`middle`,className:`donut-c-num`,children:(0,b.jsx)(l,{value:a,duration:C})}),(0,b.jsx)(`text`,{x:h,y:g+16,textAnchor:`middle`,className:`donut-c-cap`,children:i})]})}function T(e){if(e.length<2)return e.length?`M${e[0][0]},${e[0][1]}`:``;let t=`M${e[0][0]},${e[0][1]}`;for(let n=0;n<e.length-1;n++){let r=e[n-1]||e[n],i=e[n],a=e[n+1],o=e[n+2]||a,s=i[0]+(a[0]-r[0])/6,c=i[1]+(a[1]-r[1])/6,l=a[0]-(o[0]-i[0])/6,u=a[1]-(o[1]-i[1])/6;t+=` C${s},${c} ${l},${u} ${a[0]},${a[1]}`}return t}function E({data:e,height:t=156,accent:n}){if(!e.length)return null;let r=t,i=Math.max(...e.map(e=>e.v),1)+1,a=e.length>1?588/(e.length-1):588,o=e.map((e,t)=>[6+t*a,r-6-e.v/i*(r-14-6)]),s=T(o),c=o[o.length-1],l=o[0],u=`${s} L${c[0]},${r} L${l[0]},${r} Z`;return(0,b.jsxs)(`svg`,{viewBox:`0 0 600 ${r}`,preserveAspectRatio:`none`,style:{width:`100%`,height:t,display:`block`,overflow:`visible`},children:[(0,b.jsx)(`defs`,{children:(0,b.jsxs)(`linearGradient`,{id:`b-grad`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,b.jsx)(`stop`,{offset:`0`,stopColor:n,stopOpacity:`.28`}),(0,b.jsx)(`stop`,{offset:`1`,stopColor:n,stopOpacity:`0`})]})}),(0,b.jsx)(`path`,{d:u,fill:`url(#b-grad)`}),(0,b.jsx)(`path`,{d:s,fill:`none`,stroke:n,strokeWidth:`2`,strokeLinejoin:`round`,strokeLinecap:`round`,vectorEffect:`non-scaling-stroke`}),(0,b.jsx)(`circle`,{cx:c[0],cy:c[1],r:`3.5`,fill:n,vectorEffect:`non-scaling-stroke`})]})}function D({label:e,value:t,sub:n,color:r,icon:i}){return(0,b.jsxs)(`div`,{className:`b-tile`,children:[(0,b.jsx)(`span`,{className:`b-tile-ic`,style:{background:`color-mix(in srgb, ${r} 18%, transparent)`,color:r},children:(0,b.jsx)(s,{name:i})}),(0,b.jsxs)(`div`,{className:`b-tile-body`,children:[(0,b.jsx)(`div`,{className:`b-tile-val`+(t===0?` zero`:``),children:t}),(0,b.jsx)(`div`,{className:`b-tile-label`,children:e})]}),(0,b.jsx)(`div`,{className:`b-tile-sub`,children:n})]})}function O({overview:e,sigil:t,jobs:n,lens:r,onAction:u}){let d=e.counts||{},f=r?.doctor?.state||`loading`,p=r?.doctor?.data?.groups||[],y=f===`ok`,C=p.filter(e=>e.problems.length===0).length,T=p.length,O=v(e,r?.tone),k=_(n,x),A=o(e.diff),j=a.filter(e=>(d[e]||0)>0).map((e,t)=>({label:i[e].label,value:d[e]||0,color:S[t%S.length]})),M=j.reduce((e,t)=>e+t.value,0),N=h(n||[],10),P=N.reduce((e,t)=>e+t.v,0);return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`div`,{className:`b-greet`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(`div`,{className:`eyebrow`,children:`your harness`}),(0,b.jsx)(`h1`,{className:`h b-h`,children:O}),(0,b.jsx)(g,{verdict:r?.verdict}),(0,b.jsx)(`p`,{className:`sub`,children:t||`A friendly read of every layer growing in your harness.`})]}),(0,b.jsxs)(`div`,{className:`row gap-8`,children:[(0,b.jsxs)(`button`,{className:`btn`,onClick:()=>u(`update`),children:[(0,b.jsx)(s,{name:`refresh`}),`Update`]}),(0,b.jsxs)(`button`,{className:`btn ghost`,onClick:()=>u(`build-all`),children:[(0,b.jsx)(s,{name:`build`}),`Rebuild`]})]})]}),(0,b.jsxs)(`div`,{className:`grid b-hero-grid mb-16`,children:[(0,b.jsxs)(`div`,{className:`card b-hero`,children:[(0,b.jsx)(`div`,{className:`b-hero-ring`,children:(0,b.jsx)(w,{segments:[{label:`pass`,value:C,color:S[0]},{label:`attention`,value:Math.max(T-C,0),color:S[2]}],size:168,stroke:20,caption:`checks`})}),(0,b.jsxs)(`div`,{className:`b-hero-side`,children:[(0,b.jsx)(`h3`,{className:`b-hero-title`,children:y?`${C} of ${T} checks pass`:f===`failed`?`Doctor did not answer`:`Checking…`}),f===`failed`&&(0,b.jsxs)(`button`,{className:`btn ghost b-hero-retry`,onClick:()=>u(`doctor`),children:[(0,b.jsx)(s,{name:`doctor`}),`Run doctor`]}),(0,b.jsxs)(`p`,{className:`sub`,children:[`One source, rendered into `,(0,b.jsx)(`code`,{children:e.target}),` and inherited by every repo on this machine.`]}),y&&(0,b.jsx)(`ul`,{className:`b-hero-checks`,children:p.map(e=>{let t=e.problems.length===0;return(0,b.jsxs)(`li`,{className:`b-hcheck ${t?`ok`:`bad`}`,title:t?`clean`:e.problems.join(`; `),children:[(0,b.jsx)(`span`,{className:`b-hcheck-mark`,children:t?`✓`:`!`}),(0,b.jsx)(`span`,{className:`b-hcheck-label`,children:e.label})]},e.label)})}),(0,b.jsxs)(`div`,{className:`b-chips`,children:[(0,b.jsxs)(`span`,{className:`b-chip`,children:[(0,b.jsx)(`b`,{style:{textTransform:`capitalize`},children:e.theme}),` voice`]}),(0,b.jsx)(`span`,{className:`b-chip`,children:(0,b.jsx)(`b`,{children:e.emit})}),(0,b.jsxs)(`span`,{className:`b-chip`,children:[`built `,(0,b.jsx)(`b`,{children:e.build_time||`unknown`})]})]})]})]}),(0,b.jsxs)(`div`,{className:`b-tiles`,children:[(0,b.jsx)(D,{label:`Agents`,value:d.agents??`—`,sub:`specialists`,color:S[0],icon:`layers`}),(0,b.jsx)(D,{label:`Skills`,value:d.skills??`—`,sub:`workflows`,color:S[1],icon:`skill`}),(0,b.jsx)(D,{label:`Dictates`,value:d.laws??`—`,sub:d.doctrines?`${d.doctrines.active}/${d.doctrines.total} packs · ${d.doctrines.rules} rules`:`all upheld`,color:S[2],icon:`law`}),(0,b.jsx)(D,{label:`Edits`,value:A,sub:`to graft`,color:S[3],icon:`changes`})]})]}),(0,b.jsxs)(`div`,{className:`grid split-even mb-16`,children:[(0,b.jsxs)(`div`,{className:`card pad-lg b-mix-card`,children:[(0,b.jsxs)(`div`,{className:`card-head`,children:[(0,b.jsx)(`h3`,{children:`Capability mix`}),(0,b.jsx)(`div`,{className:`right`,children:(0,b.jsxs)(`span`,{className:`tick`,children:[M,` total`]})})]}),(0,b.jsxs)(`div`,{className:`b-mix`,children:[(0,b.jsx)(w,{segments:j,size:186,stroke:26}),(0,b.jsx)(`div`,{className:`b-legend`,children:j.map(e=>(0,b.jsxs)(`div`,{className:`b-leg-row`,children:[(0,b.jsx)(`span`,{className:`b-leg-dot`,style:{background:e.color}}),(0,b.jsx)(`span`,{className:`b-leg-name`,children:e.label}),(0,b.jsx)(`span`,{className:`b-leg-bar`,children:(0,b.jsx)(`i`,{style:{width:`${e.value/M*100}%`,background:e.color}})}),(0,b.jsx)(`span`,{className:`b-leg-val`,children:e.value})]},e.label))})]})]}),(0,b.jsxs)(`div`,{className:`card pad-lg`,children:[(0,b.jsxs)(`div`,{className:`card-head`,children:[(0,b.jsx)(`h3`,{children:`Recent runs`}),(0,b.jsx)(`div`,{className:`right`,children:(0,b.jsxs)(`span`,{className:`badge ok`,children:[(0,b.jsx)(`span`,{className:`dot`}),`job log`]})})]}),(0,b.jsxs)(`div`,{className:`b-stat-lead`,children:[(0,b.jsx)(`span`,{className:`b-stat-big`,children:(0,b.jsx)(l,{value:P})}),(0,b.jsxs)(`span`,{className:`b-stat-cap`,children:[`runs in the last 10 days`,y&&T>0&&` · ${C}/${T} checks pass now`]})]}),(0,b.jsx)(E,{data:N,accent:S[0],height:156})]})]}),(0,b.jsxs)(`div`,{className:`card pad-lg`,children:[(0,b.jsxs)(`div`,{className:`card-head`,children:[(0,b.jsx)(`h3`,{children:`Recent activity`}),(0,b.jsx)(`div`,{className:`right`,children:(0,b.jsxs)(`span`,{className:`tick`,children:[`last `,k.length,` runs`]})})]}),(0,b.jsxs)(`div`,{className:`b-timeline`,children:[k.map(e=>{let t=e.status===`done`,n=e.status===`failed`?`warn`:t?`ok`:`acc`,r=m(e);return(0,b.jsxs)(`div`,{className:`b-tl-row`,children:[(0,b.jsx)(`span`,{className:`b-tl-node ${n}`}),(0,b.jsxs)(`div`,{className:`b-tl-body`,title:r.command||void 0,children:[(0,b.jsx)(`b`,{children:r.verb}),[r.scope,r.result,r.duration].map(e=>e?` · ${e}`:``).join(``)]}),(0,b.jsx)(`span`,{className:`b-tl-when`,children:e.started?`${c(e.started)} ago`:`—`})]},e.id)}),(!n||n.length===0)&&(0,b.jsxs)(`div`,{className:`b-tl-row`,children:[(0,b.jsx)(`span`,{className:`b-tl-node`}),(0,b.jsx)(`div`,{className:`b-tl-body sub`,children:`No runs yet. Trigger an action to populate this.`}),(0,b.jsx)(`span`,{className:`b-tl-when`,children:`—`})]})]})]})]})}export{O as default};