geneseed 4.19.0 → 4.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/SHIPPED.md +1 -1
  3. package/docs/guides/upgrade.md +1 -1
  4. package/docs/web-ui.md +11 -10
  5. package/harness.config.json +1 -1
  6. package/js/README.md +1 -1
  7. package/js/web/actions.mjs +39 -0
  8. package/js/web/api.mjs +24 -2
  9. package/js/web/handler.mjs +20 -1
  10. package/js/web/jobs.mjs +6 -6
  11. package/js/web/usage-api.mjs +24 -3
  12. package/package.json +1 -1
  13. package/src/skills/rule.md +3 -3
  14. package/web/dist/assets/Activity-DsKkFGhT.js +1 -0
  15. package/web/dist/assets/ActivityDetail-BWY-vaiK.js +1 -0
  16. package/web/dist/assets/Dashboard-BZmw2a7d.js +2 -0
  17. package/web/dist/assets/Docs-CNuRuMin.js +4 -0
  18. package/web/dist/assets/EmptyState-1sPNleqv.js +1 -0
  19. package/web/dist/assets/GreenhouseView-BCiZP9f9.js +1 -0
  20. package/web/dist/assets/Installs-xkBX6OjK.js +3 -0
  21. package/web/dist/assets/JournalView-BSR51TKR.js +1 -0
  22. package/web/dist/assets/{KitApply-BAF0gtXb.js → KitApply-BR8AcZ62.js} +1 -1
  23. package/web/dist/assets/Kits-e0DCj9sT.js +1 -0
  24. package/web/dist/assets/Laws-BuG2_HFE.js +3 -0
  25. package/web/dist/assets/Library-BYfB4mhf.js +2 -0
  26. package/web/dist/assets/Loops-r6L7a1g1.js +2 -0
  27. package/web/dist/assets/OperatorHudView-BLXm0zzn.js +1 -0
  28. package/web/dist/assets/Personal-kEfKCxlh.js +1 -0
  29. package/web/dist/assets/RailCats-DNlJKicm.js +1 -0
  30. package/web/dist/assets/StackBar-Y_gkoC3t.js +1 -0
  31. package/web/dist/assets/Tabs-2uMB511T.js +1 -0
  32. package/web/dist/assets/activity-BEWV9er4.js +1 -0
  33. package/web/dist/assets/drawable-ixCquffB.js +1 -0
  34. package/web/dist/assets/index-CDSHv_7s.css +1 -0
  35. package/web/dist/assets/index-Dwo3Gxek.js +2 -0
  36. package/web/dist/assets/jobBuckets-Dpjvbfm1.js +2 -0
  37. package/web/dist/index.html +2 -2
  38. package/web/dist/assets/Activity-2fa9G39h.js +0 -1
  39. package/web/dist/assets/ActivityDetail-DIT7ITJw.js +0 -1
  40. package/web/dist/assets/Dashboard-Ddz0KQF3.js +0 -3
  41. package/web/dist/assets/Docs-j5cPrsOs.js +0 -4
  42. package/web/dist/assets/GreenhouseView-BhI_tF4c.js +0 -1
  43. package/web/dist/assets/Installs-kkE0H4Q2.js +0 -3
  44. package/web/dist/assets/JournalView-w5adl4Sm.js +0 -1
  45. package/web/dist/assets/Kits-BteVDSKD.js +0 -1
  46. package/web/dist/assets/Laws-DNTpf31b.js +0 -3
  47. package/web/dist/assets/Library-CgX1dJTr.js +0 -1
  48. package/web/dist/assets/Loops-MhJU2d8B.js +0 -2
  49. package/web/dist/assets/OperatorHudView-BvLd1zig.js +0 -1
  50. package/web/dist/assets/Personal-BdN0jlmh.js +0 -1
  51. package/web/dist/assets/RailCats-D5RVYEjy.js +0 -1
  52. package/web/dist/assets/Tabs-BPs85vgk.js +0 -1
  53. package/web/dist/assets/activity-Jw8XcPiP.js +0 -1
  54. package/web/dist/assets/drawable-DjpisR6c.js +0 -1
  55. package/web/dist/assets/index-B9-bvRjd.js +0 -2
  56. package/web/dist/assets/index-DwzZK5uG.css +0 -1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,33 @@ label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [4.21.0] — 2026-10-25
12
+
13
+ Minor: Activity "Today", per-install rebuild, usage in the Library, sync with source in Hosts, a command palette, and `user` as an alias of `global`.
14
+
15
+ ### Added
16
+ - **Activity "Today".** Runs per day over 14 days, gate asks per rule over 30 days and "Waiting on you", above a feed that mixes runs and gate asks by day, with filters — so the page answers what your agents did even with live tracking off.
17
+ - **Rebuild one install.** Each Overview row rebuilds only its own install, and "Rebuild all behind (N)" rebuilds only the installs that need it; both ask first and show progress on the rows they touch. A per-install rebuild on a console running older code than the disk asks you to restart it first.
18
+ - **Usage in the Library.** Each skill and agent shows its call count across installs, the reader shows where and how often it ran over 30 days, and a "Not used yet" filter lists what has not fired since counting began.
19
+ - **Hosts shows each install's sync with source**, and the Server tab is a settings sheet: server pid and uptime, whether the code matches the disk, the request guards, and a danger zone.
20
+ - **Command palette.** "Search or run…" (Ctrl/⌘ K or `/`) finds pages, items and actions in one place; actions that write still ask first.
21
+
22
+ ### Changed
23
+ - **Rule scope `user` is an alias of `global`.** The rule skill documents `project` and `global`; the editor opens a `user` rule on `global` and writes `global` when you save it. Untouched rules keep what they say.
24
+
25
+ ### Fixed
26
+ - The Constitution page's Dictates and Doctrines cells no longer show a light browser-default button background that hid their names in dark mode.
27
+
28
+ ## [4.20.0] — 2026-10-24
29
+
30
+ Minor: every web console page uses the shared building blocks — one header and one primary action per page, named controls, consistent empty and error states.
31
+
32
+ ### Changed
33
+ - **Every console page uses the shared building blocks.** One page header per page with a single primary action ("Rebuild all (N behind)" on the Overview, "Apply and rebuild" only while Constitution changes are staged); repeated buttons carry distinct names for screen readers; empty and error states, tables, rings and bars come from the shared components. The four Overview lenses sit under that header with a working View switcher.
34
+ - **Installs:** uninstall goes through the danger dialog and names the memory and notebook paths when they will be deleted; notes carry a tone; Doctor shows when it last checked, failing groups first and clean ones folded; the diff names the install it compares and opens large diffs collapsed; host labels replace raw ids.
35
+ - **Activity, Docs and the shell:** one heading per page, timestamps on session timelines, Prev/Next as links, an outline on the CLI page; the appearance menu opens above the phone drawer; choosing a voice asks first; the breadcrumb is a list of links; lists move with the arrow keys, Home and End; the phone tab bar uses the sidebar's labels with a More button.
36
+ - **Library, Kits, Loops, Personal:** the reader titles an entry by its heading, empty kinds explain what to do, Loops explains what a loop and a brick are; the rule budget is one panel with one threshold, memory and notebook show real counts, a profile that is still the template says so, and the rule form has visible labels and keeps focus where you were.
37
+
11
38
  ## [4.19.0] — 2026-10-24
12
39
 
13
40
  Minor: shared console building blocks, rule summaries kept next to their rules, and `global` as a documented rule scope.
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.19.0**.
23
+ > string. Current label: **4.21.0**.
24
24
 
25
25
  ## Capabilities
26
26
 
@@ -50,7 +50,7 @@ The console asks npm for the latest release once a day. An Overview page that st
50
50
 
51
51
  The npm route never uses `sudo` and never retries. If npm refuses (no permission on the global folder, a proxy, a private registry), the job log shows npm's own output. Fix the cause, or run the two commands yourself.
52
52
 
53
- When the update is done, the console restarts and the page reloads. If you ran `git pull` yourself, the Overview shows a banner that the console runs old code. Click **Rebuild** on an install that is behind: the console restarts after the rebuild and reloads the page. If no install is behind, click **Restart** in the banner.
53
+ When the update is done, the console restarts and the page reloads. If you ran `git pull` yourself, the Overview shows a banner that the console runs old code. Click **Rebuild** on an install that is behind, or **Rebuild all behind** in the header. The console asks you to confirm, rebuilds only the installs it names, then restarts and reloads the page. If no install is behind, click **Restart** in the banner.
54
54
 
55
55
  ## What an upgrade keeps
56
56
 
package/docs/web-ui.md CHANGED
@@ -101,7 +101,7 @@ streams the output of background jobs and keeps their history across reloads.
101
101
 
102
102
  - **Rules** (`#/rules`) — your own standing rules, read from and written to the
103
103
  `user-rules.md` beside the deployed AGENT.md (the seed-once file no update ever
104
- touches). List with scope (project/user/global, or any other scope written by hand, which a
104
+ touches). List with scope (project/global — a hand-written `user` opens as global — or any other scope written by hand, which a
105
105
  save keeps as written) and trial chips, add/edit/retire forms (a body line starting
106
106
  `## ` is refused: the file would read it as a new rule heading), a
107
107
  **Graduate** action that adopts a trial rule for good, and a budget meter that turns
@@ -195,7 +195,9 @@ streams the output of background jobs and keeps their history across reloads.
195
195
  ### 🎨 Setup
196
196
 
197
197
  - **Harness** (`#/harness`) — this machine's own install first (path, voice, footprint,
198
- and when it was built), then the **Voice** reference, then every detected install.
198
+ and when it was built), then the **Voice** reference, then every detected install. A
199
+ **Sync with source** column says whether each install is behind the source (and by how many
200
+ files), in sync or not checked, shows hand edits apart from stale files, and links to Local edits.
199
201
  `#/harnesses` and `#/themes` both still resolve here, so old links and bookmarks keep
200
202
  working.
201
203
  - The **Voice** card is the former Themes tab, kept as a REFERENCE rather than a second
@@ -224,14 +226,13 @@ streams the output of background jobs and keeps their history across reloads.
224
226
  row's staging only when that install's kits changed. A failed rebuild keeps it and says so,
225
227
  and a reload asks first while anything is staged. Files you edited in a kit that is now off are kept,
226
228
  and the row lists them.
227
- - **Settings** (`#/settings`) — a **Console direction** picker (the visual flavour of the
228
- console: Cultivar, Operator, Matrix or Atlas) with a **Dashboard layout** control (Auto follows each theme's designed Status
229
- lens; Cultivar / Greenhouse / Operator / Journal force one regardless of skin), the
230
- install snapshot (deployed/target/theme/version/memory store), a Maintenance card (PATH
231
- link/unlink and Update; each install is uninstalled from its own panel in Hosts), an
232
- offline package download, server controls (Stop), and the **About** colophon — project + creator credits and the source link, folded in from the
233
- retired `#/about` tab (which still resolves here). Build, update, and MCP wiring live in
234
- the Harness tab.
229
+ - **Server** (`#/installs/server`; `#/settings` and `#/about` resolve here) — a settings sheet
230
+ with a section index. **Appearance**: accent, Overview view, console direction. **Machine**:
231
+ version + Update, Add to PATH, the viewed install's footprint. **Server**: running · port ·
232
+ pid · uptime, whether the code matches the disk (with Restart), start-at-login state (read
233
+ only), and the four request guards. **About**: version, changelog, credits, source, creator.
234
+ **Danger zone**: Stop server, Remove from PATH, and a pointer to each install's own
235
+ Uninstall in Hosts.
235
236
 
236
237
  ## Rebuilding the UI
237
238
 
@@ -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.19.0"
5
+ "version": "4.21.0"
6
6
  }
package/js/README.md CHANGED
@@ -241,7 +241,7 @@ the deployed harness as JSON.
241
241
  | `api.mjs` | The dashboard and settings reads: overview, recent, themes, setup, doctor, diff, installs, excludes, loops |
242
242
  | `update-check.mjs` | Is a newer release on npm? Answers from memory, refreshes in the background (a day when it got an answer, an hour when it did not), `null` on any failure, never asked under `node --test` |
243
243
  | `gates-api.mjs` | `GET /api/gates`: gate asks per rule per day over 30 days, read off every installed harness's `notebook/gates.jsonl` (the Overview's sparklines) |
244
- | `usage-api.mjs` | `GET /api/usage`: the 30-day skill and agent call counts across every installed harness, the never-fired list, and the 90-day prune of each `notebook/usage.jsonl` |
244
+ | `usage-api.mjs` | `GET /api/usage`: the 30-day skill and agent call counts across every installed harness, the never-fired list, a fleet-wide `names` list (per-name 30-day counts, installs, daily series, last day seen), and skips lines older than 90 days in each `notebook/usage.jsonl` |
245
245
  | `user-files.mjs` | The fingerprint-guarded editors for `user-rules.md` (incl. memory promotion) and `PROFILE.md`, read and write |
246
246
  | `actions.mjs` | The other mutating endpoints — memory delete, MCP, excludes, installs, view, restore — plus install/deploy argv |
247
247
  | `daemon.mjs` | Detached web start/stop/status/restart, the `.geneseed-web.json` record, and `openUrl` |
@@ -715,6 +715,45 @@ export function apiInstallCmd(state, body) {
715
715
  return { cmd: [process.execPath, path.join(ROOT, 'bin', 'build-driver.mjs'), ...argv] };
716
716
  }
717
717
 
718
+ /**
719
+ * The job steps for the `rebuild` action: the Overview's per-row Rebuild and its "Rebuild all
720
+ * behind", which name the installs to rebuild rather than every one on the machine.
721
+ *
722
+ * Body `{ installs: [{host, path}, ...] }`. Each pair must be an ACTIVE detected install, matched
723
+ * on the same serialised key as `detectedInstall` against a fresh `installTargets()` — the client
724
+ * echoes the raw `path` `/api/fleet` gave it, so an exact match is the honest test. The argv is
725
+ * built from the REGISTRY's host/scope/root, never from body strings, and it is what `rebuildAll`
726
+ * replays (`installProfile`), so a console rebuild of one row equals the CLI's of all of them.
727
+ *
728
+ * ALL OR NOTHING: one unknown, inactive or legacy entry (or a malformed body) is `{ error }` and no
729
+ * job starts. `detectedInstall`'s `NotFound` would answer 404; a refusal here means the world
730
+ * changed under the client, so the dispatcher answers 409, as for `install`. The shape is checked
731
+ * before the registry is read, so a bad body never costs a detect.
732
+ */
733
+ export function rebuildCmds(body) {
734
+ const list = bget(body, 'installs');
735
+ if (!Array.isArray(list) || !list.length || !list.every(isDict)) {
736
+ return { error: 'installs must be a non-empty list of {host, path}' };
737
+ }
738
+ const active = installTargets().filter(([h, s, r]) => installState(r, h, s) === 'active');
739
+ const keys = [...new Set(list.map((e) => JSON.stringify([strOr(bget(e, 'host')),
740
+ strOr(bget(e, 'path'))])))];
741
+ if (keys.length > active.length) return { error: 'more installs named than are active' };
742
+ const steps = [];
743
+ for (const key of keys) {
744
+ const hit = active.findLast(([host, , root]) => JSON.stringify([host, String(root)]) === key);
745
+ if (hit === undefined) return { error: `not an active install: ${key}` };
746
+ const [host, scope, root] = hit;
747
+ // Asked BEFORE `installProfile`, as `rebuildAll` does: a legacy carrier must never be rebuilt.
748
+ if (legacyProcessCarrierOfDir(root, host)) {
749
+ return { error: `${host}:${scope} (${root}) predates the comms pack (its carrier names `
750
+ + "'process 8') — run `geneseed setup` for it before rebuilding from the console" };
751
+ }
752
+ steps.push(...actionCommands('build', { buildArgv: installProfile(host, scope, root).argv }));
753
+ }
754
+ return { cmds: steps };
755
+ }
756
+
718
757
  /**
719
758
  * Deactivate, reactivate, or REMOVE one install.
720
759
  *
package/js/web/api.mjs CHANGED
@@ -8,7 +8,7 @@
8
8
  * bind paths to these functions are `routes.mjs`. This file imports none of its route siblings,
9
9
  * which is what keeps the old `api ↔ actions` and `api ↔ activity` cycles from coming back.
10
10
  */
11
- import { readdirSync, statSync } from 'node:fs';
11
+ import { existsSync, readdirSync, statSync } from 'node:fs';
12
12
  import path from 'node:path';
13
13
 
14
14
  import { CONFIG, CREDIT_RE, ROOT, SRC, THEMES, discoverNames, loadKits, makeCfg, upstreamOf } from '../build/source.mjs';
@@ -19,6 +19,7 @@ import { installProfile } from '../build/generate.mjs';
19
19
  import { diffCollect, renderMemo } from '../inspect/diff.mjs';
20
20
  import { excludesSnapshot } from '../inspect/excludes.mjs';
21
21
  import { VERSION_MARKER, resolvePath } from '../hosts/hosts.mjs';
22
+ import { autostartPaths } from '../hosts/shim.mjs';
22
23
  import {
23
24
  footprintOfDir, gatesOfDir, installState, installTargets, legacyProcessCarrierOfDir, modeOfDir,
24
25
  trustOfDir,
@@ -236,7 +237,27 @@ export function apiFleet(state) {
236
237
  cost: alwaysOnCost({ host, root, dir, footprint: footprintOfDir(root) }),
237
238
  });
238
239
  }
239
- return { installs, source_fp: sourceFp, doctor: state.doctor };
240
+ // `version` is the source's release label, the "Behind 4.19.0" a behind row names; the same
241
+ // reader `/api/overview` uses, so the two never name different releases.
242
+ return { installs, source_fp: sourceFp, doctor: state.doctor, version: releaseLabel() };
243
+ }
244
+
245
+ /**
246
+ * What the Server tab says about the process answering it — built FIELD BY FIELD, never from the
247
+ * daemon record, which holds the write token: a GET is readable by anything that passes the Host
248
+ * check, and the token is the only guard on a POST. `started` is the process's own start (the
249
+ * server is the process), in epoch seconds. `autostart` is whether the hand-written login
250
+ * launcher the install guide describes (`autostartPaths`) is on disk for THIS platform; null
251
+ * where that guide names none.
252
+ */
253
+ function serverFacts() {
254
+ const [vbs, plist] = autostartPaths();
255
+ const launcher = { win32: vbs, darwin: plist }[process.platform];
256
+ return {
257
+ pid: process.pid,
258
+ started: Math.floor(Date.now() / 1000 - process.uptime()),
259
+ autostart: launcher ? existsSync(launcher) : null,
260
+ };
240
261
  }
241
262
 
242
263
  /** Source files of a kit member: `<dir>/<name>.md`, or every `.md` in a `<dir>/<name>/` folder. */
@@ -357,6 +378,7 @@ export function apiOverview(state) {
357
378
  // True when the files on disk changed under this server since it started (an upgrade).
358
379
  // `serve` installs the comparison; a state built without a server has none and is false.
359
380
  daemon_stale: Boolean(state.daemonStale?.()),
381
+ server: serverFacts(),
360
382
  counts: {
361
383
  agents: inv.agents.length,
362
384
  skills: inv.skills.length,
@@ -14,7 +14,9 @@
14
14
  import { resolvePath } from '../hosts/hosts.mjs';
15
15
  import { isTruthy, jsonDumpsCompact } from '../lib/json.mjs';
16
16
  import { parseIntStrict, percentDecode } from '../lib/text.mjs';
17
- import { apiDeployCmd, apiInstallCmd, apiPickFolder, apiRestore, buildActionCmds, mcpTargetPaths } from './actions.mjs';
17
+ import {
18
+ apiDeployCmd, apiInstallCmd, apiPickFolder, apiRestore, buildActionCmds, mcpTargetPaths, rebuildCmds,
19
+ } from './actions.mjs';
18
20
  import { BadRequest, NotFound } from './catalog.mjs';
19
21
  import { openUrl, requestRestart } from './daemon.mjs';
20
22
  import { apiDocs, apiDocsPage } from './docs.mjs';
@@ -312,6 +314,11 @@ export function makeHandler(state, jm, token, dist, holder = null) {
312
314
  * means the world changed under the client) and 400 for deploy (its path came from the body,
313
315
  * so a refusal means the body was wrong). Unifying the two would be wrong for one of them.
314
316
  *
317
+ * `rebuild` follows them: the named installs' argv (`rebuildCmds`), 409 on a refusal for the
318
+ * install reason, and the build-all restart on a stale server. Its job is several steps, and
319
+ * `_run` stops at the first failed one where `rebuild-all` is best-effort: a click names the
320
+ * installs it wants, so a failure should stop and be read rather than be stepped past.
321
+ *
315
322
  * `update` COMES NEXT AND IS INLINE: it is gated on a LOCAL-ONLY preflight before a job is
316
323
  * ever started, so a dirty tree or a zip-download install gets a friendly 422 the UI renders
317
324
  * as an info popup instead of a job that spawns and then fails. Its finish handler is its own
@@ -336,6 +343,18 @@ export function makeHandler(state, jm, token, dist, holder = null) {
336
343
  if (Object.hasOwn(plan, 'error')) return sendJson(res, plan, 400, ae);
337
344
  return startJob(res, 'deploy', [plan.cmd], ae);
338
345
  }
346
+ if (action === 'rebuild') {
347
+ const plan = rebuildCmds(body);
348
+ if (Object.hasOwn(plan, 'error')) return sendJson(res, plan, 409, ae);
349
+ // A STALE server is refused, not restarted afterwards as build-all is: `rebuildCmds` built
350
+ // each argv with THIS (old) process's `installProfile`, while the build-driver it spawns is
351
+ // the new code on disk, so an axis or marker the pull added would be dropped. build-all
352
+ // spawns the new CLI, which builds every profile with the new code; this path cannot.
353
+ if (state.daemonStale?.()) {
354
+ return sendJson(res, { error: 'the console is running older code than the disk — restart it first (Installs › Server › Restart), then rebuild' }, 422, ae);
355
+ }
356
+ return startJob(res, 'rebuild', plan.cmds, ae);
357
+ }
339
358
  if (action === 'update') {
340
359
  // The route follows the install (`updatePlan`); a refusal is the same friendly 422.
341
360
  // The daily background `git fetch` still running would hold `.git` locks the update's own
package/js/web/jobs.mjs CHANGED
@@ -45,7 +45,7 @@
45
45
  *
46
46
  * ---------------------------------------------------------------------------------------
47
47
  * THE ACTION SURFACE — `doctor`, `build`, `build-all`, `export`, `update`, `link` and
48
- * `unlink` each name a verb `bin/geneseed-cli.mjs` runs, plus the three `INLINE_ACTIONS` the
48
+ * `unlink` each name a verb `bin/geneseed-cli.mjs` runs, plus the four `INLINE_ACTIONS` the
49
49
  * dispatcher answers without the table. `tests/unit/web_jobs.test.mjs` holds the union against
50
50
  * a written-out list, so an eighth action cannot appear unchecked.
51
51
  *
@@ -413,12 +413,12 @@ const CLI = () => path.join(ROOT, 'bin', 'geneseed-cli.mjs');
413
413
  const GEN = () => path.join(ROOT, 'bin', 'build-driver.mjs');
414
414
 
415
415
  /**
416
- * The three actions the dispatcher answers INLINE, without consulting the table above:
417
- * `restore` is synchronous and returns a result rather than a job id, and `install`/`deploy`
418
- * resolve their argv from the request body first. Declared so the surface check covers every
419
- * action the dispatcher answers, not only the table's keys.
416
+ * The four actions the dispatcher answers INLINE, without consulting the table above:
417
+ * `restore` is synchronous and returns a result rather than a job id, and `install`/`deploy`/
418
+ * `rebuild` resolve their argv from the request body first. Declared so the surface check
419
+ * covers every action the dispatcher answers, not only the table's keys.
420
420
  */
421
- export const INLINE_ACTIONS = ['restore', 'install', 'deploy'];
421
+ export const INLINE_ACTIONS = ['restore', 'install', 'deploy', 'rebuild'];
422
422
 
423
423
  /**
424
424
  * ⚠ `doctrines` DEFAULTS TO THE FULL SET, and it is the one axis here whose default is not the
@@ -3,7 +3,15 @@
3
3
  * `notebook/usage.jsonl` (the writer is js/hosts/usage.mjs, and the OpenCode guard plugin's copy).
4
4
  *
5
5
  * `{ enabled, since, days_counted, per_day[30], rows[{install, kind, name, n}],
6
- * never[{install, kind, name}] }`, the window being the last 30 days including today.
6
+ * never[{install, kind, name}], names[{kind, name, n, installs, per_day[30], last}] }`, the
7
+ * window being the last 30 days including today.
8
+ *
9
+ * `names` is the Library's view, fleet-wide: one entry per distinct kind+name, summed over every
10
+ * install, because a skill fired daily on claude and never on opencode IS used — reading
11
+ * `never` (per install) for that was the OV-2 bug. `installs` names those with a call in the
12
+ * window; `last` is the latest day across installs, day-granular and bounded by the 90-day read,
13
+ * so a name whose only lines are older than the window still appears, with n 0 and its `last`.
14
+ * Bounded: distinct names × 30.
7
15
  *
8
16
  * `since` is the oldest day any ledger holds and `days_counted` how many of the 30 it covers:
9
17
  * the console keeps the never-fired claim back until a full 30 are counted, so a fresh install
@@ -53,6 +61,7 @@ export function usageSummary({ now = Date.now(), targets = installTargets() } =
53
61
  const first = days[0];
54
62
  const perDay = new Array(WINDOW).fill(0);
55
63
  const counts = new Map();
64
+ const names = new Map();
56
65
  const never = [];
57
66
  let since = null;
58
67
  let enabled = !process.env.GENESEED_NO_USAGE;
@@ -63,9 +72,18 @@ export function usageSummary({ now = Date.now(), targets = installTargets() } =
63
72
  const fired = new Set();
64
73
  for (const e of entries) {
65
74
  if (since === null || e.ts < since) since = e.ts;
75
+ const nk = `${e.kind}\u0000${e.name}`;
76
+ let it = names.get(nk);
77
+ if (!it) names.set(nk, it = { kind: e.kind, name: e.name, n: 0, installs: [], per_day: new Array(WINDOW).fill(0), last: e.ts });
78
+ if (e.ts > it.last) it.last = e.ts;
66
79
  if (e.ts < first) continue;
67
80
  const i = days.indexOf(e.ts);
68
- if (i >= 0) perDay[i] += 1;
81
+ if (i >= 0) {
82
+ perDay[i] += 1;
83
+ it.per_day[i] += 1;
84
+ it.n += 1;
85
+ if (!it.installs.includes(install)) it.installs.push(install);
86
+ }
69
87
  const key = `${install}\u0000${e.kind}\u0000${e.name}`;
70
88
  counts.set(key, (counts.get(key) || 0) + 1);
71
89
  fired.add(`${e.kind}\u0000${e.name}`);
@@ -86,7 +104,10 @@ export function usageSummary({ now = Date.now(), targets = installTargets() } =
86
104
  }).sort((a, b) => b.n - a.n || a.name.localeCompare(b.name));
87
105
  const daysCounted = since === null ? 0
88
106
  : Math.min(WINDOW, Math.floor((Date.parse(day(now)) - Date.parse(since)) / DAY_MS) + 1);
89
- return { enabled, since, days_counted: daysCounted, per_day: perDay, rows, never };
107
+ return {
108
+ enabled, since, days_counted: daysCounted, per_day: perDay, rows, never,
109
+ names: [...names.values()].sort((a, b) => b.n - a.n || a.name.localeCompare(b.name)),
110
+ };
90
111
  }
91
112
 
92
113
  export const apiUsage = () => usageSummary();
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.19.0",
4
+ "version": "4.21.0",
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",
@@ -72,13 +72,13 @@ re-derived. Then take exactly one branch.
72
72
  5. **Destination.** Scope decides the file: a rule that holds across all the user's
73
73
  work goes to the *global* install's `user-rules.md`, a rule bound to this
74
74
  codebase to the project's. Tag it to match: `scope: project` — this repo, committable,
75
- binds the team; `scope: global` — every repository on the machine; `scope: user` —
76
- a personal preference, kept in the global file too, never the team's. Read the target first ({{LAW:verify-before-asserting}} — the real current
75
+ binds the team; `scope: global` — every repository on the machine. `user` is still read
76
+ as `global`. Read the target first ({{LAW:verify-before-asserting}} — the real current
77
77
  rules, not a remembered copy). The build seeds it once and never overwrites it;
78
78
  if it is genuinely absent, create it with a `# User rules` header and note that a
79
79
  rebuild would have seeded it.
80
80
  6. **Draft in the file's own format**: the next free `## R<n> — Title` heading, an
81
- optional `(scope: project|global|user | source: …)` metadata line, then the rule in one
81
+ optional `(scope: project|global | source: …)` metadata line, then the rule in one
82
82
  short paragraph, plain and testable. For a rule the user stated, `source:` keeps
83
83
  their own words and the day they said them — `source: user 2026-10-16 "never push
84
84
  red"` — one sentence at most: it is what later tells a stale rule from a changed
@@ -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{A as i,J as a,K as o,T as s,V as c,k as l,st as u,u as d}from"./index-Dwo3Gxek.js";import{n as f}from"./jobBuckets-Dpjvbfm1.js";import{c as p,d as m,i as h,l as g,n as _,o as v,r as y,s as b,t as x,u as S}from"./activity-BEWV9er4.js";import{t as C}from"./EmptyState-1sPNleqv.js";import{t as w}from"./usePoll-bDFN-Hr6.js";var T=e(t(),1),E=n(),D=e=>e.catch(()=>null);function O({s:e}){let t=(0,T.useId)(),n=e.todos,r=b(e);return(0,E.jsxs)(`a`,{className:`card pad-md act-card`,href:`#/activity/${encodeURIComponent(e.session_id)}`,"aria-labelledby":`${t}-t ${t}-st`,"aria-describedby":r?`${t}-c`:void 0,children:[(0,E.jsx)(x,{s:e,id:t,heading:e.title||h(e.cwd)||e.session_id,children:(0,E.jsx)(c,{name:`chevron`,className:`glyph act-chev`})}),n&&n.total>0&&(0,E.jsx)(`div`,{className:`act-foot`,children:(0,E.jsxs)(`span`,{className:`row gap-8 dim act-sm`,children:[(0,E.jsx)(y,{done:n.done,total:n.total}),`plan `,n.done,`/`,n.total]})}),(0,E.jsxs)(`div`,{className:`dim mono act-updated`,children:[`updated `,o(e.updated_at),` ago`]})]})}var k=[[`all`,`All`],[`needs`,`Needs you`],[`runs`,`Runs`],[`gates`,`Gate asks`]];function A(){let e=new URLSearchParams(window.location.hash.split(`?`)[1]||``),t=e.get(`f`);return{f:k.some(([e])=>e===t)?t:`all`,host:e.get(`host`)||``,project:e.get(`project`)||``}}function j(e){let t=new URLSearchParams;e.f!==`all`&&t.set(`f`,e.f),e.host&&t.set(`host`,e.host),e.project&&t.set(`project`,e.project);let n=t.toString();window.history.replaceState(null,``,`#/activity${n?`?${n}`:``}`)}function M({enabled:e,onToggle:t}){return(0,E.jsxs)(`section`,{className:`card pad-md act-track`,"aria-labelledby":`act-track-h`,children:[(0,E.jsx)(c,{name:`activity`,className:`glyph act-fixed`}),(0,E.jsxs)(`div`,{className:`act-grow`,children:[(0,E.jsx)(`h2`,{id:`act-track-h`,className:`act-track-title`,children:e?`Live sessions are on`:`Live sessions are off`}),!e&&(0,E.jsx)(`p`,{className:`dim act-sm act-track-p`,children:`Runs and gate asks below come from the job log and the gate ledger. Turn tracking on to see what each session is doing now.`})]}),(0,E.jsxs)(`div`,{className:`row gap-10 act-fixed act-sm`,children:[(0,E.jsx)(`span`,{id:`act-track-l`,children:`Track live sessions`}),(0,E.jsx)(`div`,{className:`sw-toggle${e?` on`:``}`,role:`switch`,"aria-checked":e,"aria-labelledby":`act-track-l`,tabIndex:0,onClick:t,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.key===` `&&e.preventDefault(),t())}})]})]})}function N({jobs:e,loading:t}){let n=typeof e?.cap==`number`?e.cap:void 0,r=g(e?.jobs,{days:14,cap:n}),i=m(r.map(e=>e.nodata?`-`:e.n).join(`,`),`scaleY`),a=Math.max(1,...r.map(e=>e.n)),o=r.reduce((e,t)=>e+t.n,0),s=r.find(e=>!e.nodata),c=r.some(e=>e.nodata),l=`Runs per day: ${r.filter(e=>e.n).map(e=>`${e.n} on ${S(e.key)}`).join(`, `)||`none`}.`+(c?s?` Days before ${S(s.key)} are older than the runs the log keeps.`:` No run is in the log yet.`:``);return(0,E.jsxs)(`section`,{className:`card pad-md act-stat`,"aria-labelledby":`act-runs-h`,children:[(0,E.jsxs)(`div`,{className:`act-stat-head`,children:[(0,E.jsx)(`h2`,{id:`act-runs-h`,className:`act-lbl`,children:`Runs per day · 14 days`}),e&&(0,E.jsx)(`span`,{className:`act-big`,children:o})]}),t?(0,E.jsx)(`p`,{className:`dim act-sm`,children:`Reading the job log…`}):e?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`div`,{className:`act-runs`,role:`img`,"aria-label":l,ref:i,children:r.map(e=>e.nodata?(0,E.jsx)(`i`,{className:`nodata`},e.key):e.n?(0,E.jsx)(`i`,{"data-sweep":!0,style:{height:`${e.n/a*100}%`},title:`${S(e.key)}: ${e.n}`},e.key):(0,E.jsx)(`i`,{className:`zero`},e.key))}),(0,E.jsxs)(`div`,{className:`mono act-axis`,"aria-hidden":`true`,children:[(0,E.jsx)(`span`,{children:S(r[0].key)}),(0,E.jsx)(`span`,{children:S(r[7].key)}),(0,E.jsx)(`span`,{children:`today`})]}),c&&(0,E.jsxs)(`span`,{className:`dim act-xs`,children:[`Hatched: older than the runs the log keeps`,n?` (last ${n})`:``,`.`]})]}):(0,E.jsx)(`p`,{className:`dim act-sm`,children:`The job log could not be read.`})]})}function ee({rows:e,gates:t,loading:n}){let r=e.reduce((e,t)=>e+t.n,0);return(0,E.jsxs)(`section`,{className:`card pad-md act-stat`,"aria-labelledby":`act-gates-h`,children:[(0,E.jsxs)(`div`,{className:`act-stat-head`,children:[(0,E.jsx)(`h2`,{id:`act-gates-h`,className:`act-lbl`,children:`Gate asks by rule · 30 days`}),t&&(0,E.jsx)(`span`,{className:`act-big`,children:r})]}),n?(0,E.jsx)(`p`,{className:`dim act-sm`,children:`Reading the gate ledger…`}):e.length?(0,E.jsx)(`ul`,{className:`gate-rows`,children:e.slice(0,6).map((e,t)=>(0,E.jsxs)(`li`,{children:[(0,E.jsxs)(`span`,{className:`act-ell`,children:[e.name,` `,(0,E.jsx)(`span`,{className:`mono dim act-xs`,children:e.rule})]}),(0,E.jsx)(_,{vals:e.per_day,i:t,sweep:!0}),(0,E.jsx)(`span`,{className:`mono`,children:e.n})]},e.rule))}):(0,E.jsx)(`p`,{className:`dim act-sm`,children:t?`No gate asked in 30 days.`:`The gate ledger could not be read.`})]})}var P={done:[`ok`,`done`],failed:[`bad`,`failed`],running:[``,`running`]};function F({job:e,longest:t}){let n=f(e),r=e.duration?Math.round(e.duration*10)/10:0,[i,a]=P[e.status]||[``,e.status||`…`],o=e.status===`running`?`Still running`:r?`Took ${r} second${r===1?``:`s`}`:`No duration`,s=e.started?new Date(e.started*1e3).toLocaleTimeString(`en-GB`,{hour:`2-digit`,minute:`2-digit`}):`—`;return(0,E.jsxs)(`li`,{className:`act-row`,children:[(0,E.jsx)(`span`,{className:`mono dim act-xs`,children:s}),(0,E.jsx)(c,{name:`play`,className:`glyph act-glyph`}),(0,E.jsxs)(`span`,{className:`act-what`,children:[(0,E.jsx)(`span`,{className:`act-row-title`,children:n.verb}),n.scope&&(0,E.jsx)(`span`,{className:`dim act-xs act-ell`,title:n.command,children:n.scope})]}),(0,E.jsx)(`span`,{className:`act-dur`,role:`img`,"aria-label":o,children:(0,E.jsx)(`span`,{"data-sweep":!0,style:{width:t>0?`${(e.duration||0)/t*100}%`:`0%`}})}),(0,E.jsx)(`span`,{className:`badge ${i}`,children:a})]})}function I({gate:e}){return(0,E.jsxs)(`li`,{className:`act-row gate`,children:[(0,E.jsx)(`span`,{className:`mono dim act-xs`,children:`—`}),(0,E.jsx)(c,{name:`rule`,className:`glyph act-glyph t-warn`}),(0,E.jsxs)(`span`,{className:`act-what`,children:[(0,E.jsx)(`span`,{className:`act-row-title`,children:e.title}),(0,E.jsx)(`span`,{className:`dim act-xs`,children:`Gate ledger`})]}),(0,E.jsx)(`span`,{className:`act-dur-none`,"aria-hidden":`true`}),(0,E.jsx)(`span`,{className:`badge warn`,children:`asked`})]})}var L=(e,t)=>[...new Set([...e.filter(Boolean),t].filter(Boolean))];function R(){let[e,t]=(0,T.useState)(null),[n,o]=(0,T.useState)(``),[c,f]=(0,T.useState)(A),g=e=>{let t={...c,...e};f(t),j(t)};w(e=>r.activity().then(n=>{e()&&(t(n),o(``))},t=>{e()&&o(t.message)}),2e3,[]);let _=a(()=>D(r.jobs()),[]),y=a(()=>D(r.gates()),[]),b=a(()=>D(r.catalog(`laws`)),[]),x=!e||e.enabled!==!1,S=[...e?.activity||[]].sort((e,t)=>e.session_id<t.session_id?-1:+(e.session_id>t.session_id)),P=u(),R=x&&e?S.filter(p).length:null,z=L(S.map(e=>e.host),c.host),B=L(S.map(e=>h(e.cwd)),c.project),V=c.host&&c.project?`host or project`:c.host?`host`:c.project?`project`:``,H=e=>(!c.host||e.host===c.host)&&(!c.project||h(e.cwd)===c.project),U=S.filter(e=>H(e)&&(c.f!==`needs`||p(e))),W=c.f===`all`||c.f===`needs`,G=!V&&(c.f===`all`||c.f===`runs`),K=!V&&(c.f===`all`||c.f===`gates`),q=_.data?.jobs||[],J=d(y.data,b.data),Y=v(q,J,y.data?.days).map(e=>({...e,runs:G?e.runs:[],gate:K?e.gate:null})).filter(e=>e.runs.length||e.gate),X=Math.max(0,...q.map(e=>e.duration||0)),Z=m(Y.flatMap(e=>e.runs.map(e=>`${e.id}:${e.duration}`)).join(`,`),`scaleX`),Q=async()=>{let e=!x;try{let n=await r.activityToggle(e);if(n.ok===!1){o(n.error||`Could not change tracking`);return}t(e=>({...e||{},enabled:n.enabled,activity:n.enabled&&e?.activity||[]})),o(``)}catch(e){o(e.message)}},$=(e,t,n)=>(0,E.jsxs)(`span`,{className:`row gap-8 act-sm`,children:[(0,E.jsx)(`label`,{htmlFor:`act-f-${e}`,children:t}),(0,E.jsxs)(`select`,{id:`act-f-${e}`,className:`sel`,value:c[e],disabled:n.length===0,title:n.length===0?`No source carries a ${e} yet`:void 0,onChange:t=>g({[e]:t.target.value}),children:[(0,E.jsxs)(`option`,{value:``,children:[`All `,e===`host`?`hosts`:`projects`]}),n.map(e=>(0,E.jsx)(`option`,{value:e,children:e},e))]})]});return(0,E.jsxs)(`div`,{className:`narrow`,children:[(0,E.jsx)(s,{title:`Activity`,sub:`What your agents ran, what the gates asked, and which sessions are waiting on you.`}),n&&(0,E.jsx)(`div`,{className:`act-gap`,children:(0,E.jsx)(l,{error:n})}),e&&(0,E.jsx)(M,{enabled:x,onToggle:Q}),(0,E.jsxs)(`div`,{className:`act-today`,children:[(0,E.jsx)(N,{jobs:_.data,loading:_.loading}),(0,E.jsx)(ee,{rows:J,gates:y.data,loading:y.loading}),(0,E.jsxs)(`section`,{className:`card pad-md act-stat`,"aria-labelledby":`act-wait-h`,children:[(0,E.jsx)(`h2`,{id:`act-wait-h`,className:`act-lbl`,children:`Waiting on you`}),(0,E.jsxs)(`span`,{className:`act-big act-wait`,children:[R??`—`,` `,(0,E.jsx)(`span`,{className:`dim act-sm`,children:`sessions`})]}),(0,E.jsx)(`p`,{className:`dim act-sm`,children:x?`A session that waits on an approval or on your answer counts here.`:`Turn tracking on to count the sessions that wait on you.`})]})]}),(0,E.jsxs)(`div`,{className:`row wrap gap-8 act-filters`,children:[(0,E.jsx)(`div`,{role:`group`,"aria-label":`Filter`,className:`row wrap gap-8`,children:k.map(([e,t])=>(0,E.jsxs)(`button`,{type:`button`,className:c.f===e?`chip-f on`:`chip-f`,"aria-pressed":c.f===e,onClick:()=>g({f:e}),children:[t,e===`needs`&&R>0?(0,E.jsxs)(`span`,{className:`mono`,children:[` `,R]}):null]},e))}),$(`host`,`Host`,z),$(`project`,`Project`,B)]}),V&&c.f!==`needs`&&(0,E.jsxs)(`p`,{className:`dim act-sm`,children:[`Runs and gate asks carry no `,V,`; showing sessions only.`]}),W&&(e?!x&&c.f!==`needs`?null:U.length===0?c.f===`needs`?(0,E.jsx)(C,{title:`Nothing waits on you`}):(0,E.jsxs)(C,{title:`No active sessions`,children:[`Run `,(0,E.jsx)(`code`,{children:`opencode`}),` and the sessions it spins up appear here.`]}):(0,E.jsx)(`div`,{className:`stack gap-12 act-live`,ref:P,children:U.map(e=>(0,E.jsx)(`div`,{"data-flip":e.session_id,children:(0,E.jsx)(O,{s:e})},e.session_id))}):(0,E.jsx)(i,{label:`Reading live sessions…`})),c.f!==`needs`&&(0,E.jsx)(`section`,{"aria-label":`Feed`,className:`stack gap-16 act-feed`,ref:Z,children:Y.map(e=>(0,E.jsxs)(`section`,{className:`card act-day`,children:[(0,E.jsxs)(`h3`,{className:`act-day-h`,children:[(0,E.jsx)(`span`,{children:e.title}),(0,E.jsx)(`span`,{className:`mono dim`,children:e.sum})]}),(0,E.jsxs)(`ul`,{className:`act-rows`,children:[e.runs.map(e=>(0,E.jsx)(F,{job:e,longest:X},e.id)),e.gate&&(0,E.jsx)(I,{gate:e.gate})]})]},e.key))})]})}export{R 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{A as i,K as a,T as o,V as s,k as c}from"./index-Dwo3Gxek.js";import{a as l,i as u,t as d}from"./activity-BEWV9er4.js";import{t as f}from"./EmptyState-1sPNleqv.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(`${l(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 act-line`,children:[(0,h.jsx)(`span`,{className:`badge act-who ${t?``:`acc`}`,children:t?`you`:`agent`}),(0,h.jsxs)(`div`,{className:`act-grow act-sm`,children:[!t&&(0,h.jsx)(`span`,{className:`feed-dot act-inline-dot ${g(e)||`acc`}`}),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 act-xs act-fixed`,children:n.join(` · `)}),e.t?(0,h.jsx)(`time`,{className:`mono dim act-xs act-fixed`,dateTime:new Date(e.t).toISOString(),title:`${a(e.t/1e3)} ago`,children:new Date(e.t).toTimeString().slice(0,8)}):null]})}function v({turns:e}){return!e||e.length===0?(0,h.jsx)(`div`,{className:`dim act-sm`,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 act-line`,children:[(0,h.jsx)(`span`,{className:`badge act-who ${n?``:`acc`}`,children:n?`you`:`agent`}),(0,h.jsx)(`div`,{className:`act-min act-sm${n?``:` muted`}`,children:e.text})]},t)})})}function y({sid:e}){let[t,n]=(0,m.useState)(null),[l,g]=(0,m.useState)(``),[y,b]=(0,m.useState)(!1),[x,S]=(0,m.useState)(!1),C=(0,m.useId)();p(t=>y?void 0:r.activityDetail(e).then(e=>{t()&&(n(e),g(``),b(!1))},e=>{t()&&(e.status===404?b(!0):g(e.message))}),2e3,[e,y]);let w=(0,h.jsxs)(`a`,{className:`btn ghost sm act-back`,href:`#/activity`,children:[(0,h.jsx)(s,{name:`arrow`}),` Activity`]});if(y)return(0,h.jsxs)(`div`,{className:`narrow`,children:[w,(0,h.jsx)(f,{title:`Session ended`,action:(0,h.jsx)(`a`,{href:`#/activity`,children:`Back to Activity`}),children:`It's no longer live.`})]});if(!t)return(0,h.jsxs)(`div`,{className:`narrow`,children:[w,l?(0,h.jsx)(c,{error:l}):(0,h.jsx)(i,{label:`Loading session…`})]});let T=t.session,E=T.files,D=T.todos,O=!!(E&&E.items&&E.items.length>0),k=!!(D&&D.items&&D.items.length>0),A=t.conversation||[],j=t.timeline||[],M=[...A.filter(e=>e.role===`user`).map(e=>({who:`you`,text:e.text,t:e.t||0})),...j.map(e=>({...e,who:`agent`}))].sort((e,t)=>(e.t||0)-(t.t||0));return(0,h.jsxs)(`div`,{className:`narrow`,children:[w,(0,h.jsx)(o,{title:T.title||u(T.cwd)||T.session_id,sub:T.cwd?(0,h.jsx)(`span`,{className:`mono act-cwd`,title:T.cwd,children:T.cwd}):null}),l&&(0,h.jsx)(`div`,{className:`act-gap`,children:(0,h.jsx)(c,{error:l})}),(0,h.jsxs)(`div`,{className:`card pad-md`,children:[(0,h.jsx)(d,{s:T}),(0,h.jsxs)(`div`,{className:`dim act-updated`,children:[`updated `,a(T.updated_at),` ago`]})]}),(O||k)&&(0,h.jsxs)(`div`,{className:`grid gap-12 act-panels${O&&k?` two`:``}`,children:[O&&(0,h.jsxs)(`div`,{className:`card pad-md`,children:[(0,h.jsx)(`div`,{className:`card-head`,children:(0,h.jsxs)(`h2`,{children:[`Files touched `,(0,h.jsxs)(`span`,{className:`dim`,children:[`(`,E.count,`)`]})]})}),(0,h.jsx)(`div`,{className:`stack act-list`,children:E.items.map(e=>(0,h.jsxs)(`div`,{className:`row between gap-12 act-sm`,children:[(0,h.jsx)(`span`,{className:`mono act-ell act-grow`,title:e.file,children:e.file}),(0,h.jsxs)(`span`,{className:`act-fixed`,children:[(0,h.jsxs)(`span`,{className:`t-good`,children:[`+`,e.additions]}),` `,(0,h.jsxs)(`span`,{className:`t-bad`,children:[`−`,e.deletions]})]})]},e.file))})]}),k&&(0,h.jsxs)(`div`,{className:`card pad-md`,children:[(0,h.jsx)(`div`,{className:`card-head`,children:(0,h.jsxs)(`h2`,{children:[`Plan`,` `,(0,h.jsxs)(`span`,{className:`dim`,children:[`(`,D.done,`/`,D.total,`)`]})]})}),(0,h.jsx)(`div`,{className:`stack act-list`,children:D.items.map((e,t)=>(0,h.jsxs)(`div`,{className:`row gap-8 act-sm`,children:[(0,h.jsx)(`span`,{className:`feed-dot ${e.status===`completed`?`ok`:e.status===`in_progress`?`acc`:``}`}),(0,h.jsx)(`span`,{className:e.status===`completed`?`act-done`:void 0,children:e.content})]},t))})]})]}),(0,h.jsxs)(`div`,{className:`card pad-md act-mt`,children:[(0,h.jsxs)(`div`,{className:`card-head act-tl-head`,children:[(0,h.jsx)(`h2`,{children:`Timeline`}),j.length>0&&(0,h.jsx)(`button`,{className:`btn ghost sm`,"aria-expanded":x,"aria-controls":C,onClick:()=>S(e=>!e),children:x?`Show conversation`:`Show full stream (${M.length})`})]}),(0,h.jsx)(`div`,{id:C,children:x?(0,h.jsx)(`div`,{className:`stack gap-12`,children:M.map((e,t)=>(0,h.jsx)(_,{rec:e},t))}):(0,h.jsx)(v,{turns:A})})]})]})}export{y as default};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GreenhouseView-BCiZP9f9.js","assets/rolldown-runtime-hePW80VL.js","assets/react-DlYQp10C.js","assets/sections-ChwaobfW.js","assets/index-Dwo3Gxek.js","assets/api-BfpZmUMI.js","assets/index-CDSHv_7s.css","assets/jobBuckets-Dpjvbfm1.js","assets/OperatorHudView-BLXm0zzn.js","assets/JournalView-BSR51TKR.js","assets/drawable-ixCquffB.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{t as a}from"./drawable-ixCquffB.js";import{n as o,r as s}from"./sections-ChwaobfW.js";import{A as c,G as l,J as u,K as d,M as f,O as p,U as m,V as h,W as g,at as _,ft as v,it as y,k as b,l as x,lt as S,ot as C,rt as w,t as T,tt as E,w as D}from"./index-Dwo3Gxek.js";import{r as O}from"./jobBuckets-Dpjvbfm1.js";var k=t(n(),1),A=r();function j({segments:e,value:t,max:n,size:r=120,stroke:i=12,label:o,sweepMs:s=650}){let c=n>0?n:0,l=e||[{key:`v`,label:o,n:Math.min(Math.max(t||0,0),c),tone:`accent`}],u=e?l.reduce((e,t)=>e+t.n,0):c,d=e?l.map(e=>`${e.label}: ${e.n} of ${u}`).join(`, `):`${l[0].n} of ${u}`,f=r/2-i/2,p=r/2,m=e=>[p+f*Math.cos(e),p+f*Math.sin(e)],h=[],g=0;for(let e of l)h.push(g),g+=e.n;let b=(0,k.useRef)(null),x=l.map(e=>e.n).join(`,`);return(0,k.useLayoutEffect)(()=>{let e=b.current?.querySelectorAll(`path.ring-arc`);if(!s||!e?.length||!y())return;let t=l.map(e=>e.n/u).filter(e=>e>0),n=t.map((e,n)=>t.slice(0,n).reduce((e,t)=>e+t,0)),r=a(e);S(r,{draw:`0 0`});let i=v(r,{draw:[`0 0`,`0 1`],duration:(e,n)=>Math.max(s*t[n],60),delay:(e,t)=>s*n[t],ease:`linear`});return _(i,s)},[x,s]),(0,A.jsxs)(`svg`,{className:`ring`,width:r,height:r,viewBox:`0 0 ${r} ${r}`,role:`img`,"aria-label":o?`${o}: ${d}`:d,children:[(0,A.jsx)(`circle`,{className:`ring-track`,cx:p,cy:p,r:f,fill:`none`,strokeWidth:i}),(0,A.jsx)(`g`,{ref:b,children:u>0?l.map((e,t)=>{let n=e.n/u;if(!(n>0))return null;let r=h[t]/u*2*Math.PI-Math.PI/2,a=r+n*2*Math.PI,[o,s]=m(r),[c,l]=m(a),d=n>=.9999?`M ${o} ${s} A ${f} ${f} 0 1 1 ${2*p-o} ${2*p-s} A ${f} ${f} 0 1 1 ${o} ${s}`:`M ${o} ${s} A ${f} ${f} 0 ${+(n>.5)} 1 ${c} ${l}`;return(0,A.jsx)(`path`,{className:`ring-arc tone-${e.tone||`muted`}`,d,fill:`none`,strokeWidth:i,children:(0,A.jsxs)(`title`,{children:[e.label,`: `,e.n]})},e.key)}):null})]})}var M={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.`},N=(e,t)=>e.deployed?t===void 0||t===`good`?M[e.theme]||`Loaded & ready`:`Deployed`:`Not deployed`,P={good:`ok`,warn:`warn`,bad:`bad`};function F({verdict:e}){return e?(0,A.jsxs)(`span`,{className:`badge ${P[e.tone]}`,role:`status`,style:{alignSelf:`flex-start`},children:[(0,A.jsx)(`span`,{className:`dot`}),e.head]}):null}function I({overview:e,dataRev:t}){let{data:n}=u(()=>Promise.resolve().then(()=>i.catalog(`laws`)),[t],`catalog:laws`),r=m(e.diff),a=e.counts||{},o=[{key:`agents`,label:`Agents`,hash:`#/agents`},{key:`skills`,label:`Skills`,hash:`#/skills`},{key:`laws`,label:n?.nouns?.laws||`Dictates`,hash:`#/laws`}];return(0,A.jsxs)(`div`,{className:`card kpiband rise mb-16`,children:[o.map(e=>{let t=a[e.key];return(0,A.jsxs)(`a`,{className:`kseg`,href:e.hash,title:`Open ${e.label}`,children:[(0,A.jsx)(`span`,{className:`kseg-n`+(t===0?` zero`:``),children:t==null?`—`:(0,A.jsx)(w,{value:t})}),(0,A.jsx)(`span`,{className:`kseg-l`,children:e.label})]},e.key)}),(0,A.jsx)(`div`,{className:`kseg-spacer`}),(0,A.jsxs)(`button`,{className:`kseg`+(r>0?` hot`:``),onClick:()=>E(`#/diff`),title:`Open changes`,children:[(0,A.jsx)(`span`,{className:`kseg-n`+(r===0?` zero`:``),children:(0,A.jsx)(w,{value:r})}),(0,A.jsx)(`span`,{className:`kseg-l`,children:`Local edits`}),r>0&&(0,A.jsx)(`span`,{className:`delta up`,children:`▲`})]})]})}function L({overview:e}){return(0,A.jsx)(`div`,{className:`genome`,children:s.map((t,n)=>{let r=o[t],i=e.counts?.[t];return(0,A.jsxs)(`div`,{className:`card gcell rise`,style:{"--i":n},onClick:()=>E(`#/section/`+t),children:[(0,A.jsxs)(`div`,{className:`gtop`,children:[(0,A.jsx)(`span`,{className:`gname`,children:r.label}),(0,A.jsx)(h,{name:r.icon,className:`gicon`})]}),(0,A.jsx)(`div`,{className:`gcount`+(i===0?` zero`:``),children:i==null?`—`:(0,A.jsx)(w,{value:i})}),(0,A.jsx)(`div`,{className:`gdesc`,children:r.desc})]},t)})})}function R({jobs:e}){if(!e||e.length===0)return(0,A.jsx)(`div`,{className:`feed`,children:(0,A.jsxs)(`div`,{className:`empty`,children:[(0,A.jsx)(`div`,{className:`big`,children:`No activity yet`}),`Actions you run appear here.`]})});let t={done:`ok`,running:`acc`,failed:`bad`},n=O(e,8);return(0,A.jsx)(`div`,{className:`feed`,children:n.map(e=>(0,A.jsxs)(`div`,{className:`feed-row`,children:[(0,A.jsx)(`span`,{className:`feed-dot ${t[e.status]||`ok`}`}),(0,A.jsx)(`span`,{className:`feed-txt`,children:(0,A.jsx)(`b`,{children:e.action})}),(0,A.jsxs)(`span`,{className:`feed-when`,children:[d(e.started),` ago`]})]},e.id))})}function z({value:e}){let t=C(e,1100)??0,n=Math.round(t*100);return(0,A.jsxs)(`div`,{className:`ring-box`,children:[(0,A.jsx)(j,{value:n,max:100,label:`germination`,size:232,stroke:10,sweepMs:0}),(0,A.jsxs)(`div`,{className:`ring-center`,children:[(0,A.jsxs)(`div`,{className:`pct`,children:[n,(0,A.jsx)(`span`,{className:`pct-unit`,children:`%`})]}),(0,A.jsx)(`div`,{className:`lbl`,children:`germination`})]})]})}function B({overview:e,sigil:t,setup:n,jobs:r,lens:i,dataRev:a}){let o=N(e,i?.tone),c=l(e,n,i?.tone);return(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`div`,{className:`card pad-lg rise mb-16`,children:(0,A.jsxs)(`div`,{className:`hero`,children:[(0,A.jsx)(z,{value:c}),(0,A.jsxs)(`div`,{className:`hero-facts`,children:[(0,A.jsx)(`div`,{className:`ttl`,children:o}),(0,A.jsx)(F,{verdict:i?.verdict}),t&&(0,A.jsxs)(`div`,{className:`voice-readout`,children:[(0,A.jsx)(`span`,{className:`vr-cur`,children:`▕`}),(0,A.jsx)(`span`,{className:`vr-txt`,children:t})]},e.theme),(0,A.jsxs)(`p`,{className:`sub`,children:[`One source rendered into `,(0,A.jsx)(`code`,{children:e.target}),`. Every repo on this machine inherits it.`]}),(0,A.jsxs)(`div`,{className:`hero-chips`,children:[(0,A.jsxs)(`span`,{className:`chip`,children:[(0,A.jsx)(`span`,{className:`ck`,children:`voice`}),(0,A.jsx)(`span`,{className:`cv t-cap`,children:e.theme})]}),(0,A.jsxs)(`span`,{className:`chip`,children:[(0,A.jsx)(`span`,{className:`ck`,children:`mode`}),(0,A.jsx)(`span`,{className:`cv`,children:e.emit})]}),(0,A.jsxs)(`span`,{className:`chip`,children:[(0,A.jsx)(`span`,{className:`ck`,children:`footprint`}),(0,A.jsx)(`span`,{className:`cv`,children:e.footprint})]}),(0,A.jsxs)(`span`,{className:`chip`,children:[(0,A.jsx)(`span`,{className:`ck`,children:`built`}),(0,A.jsx)(`span`,{className:`cv`,children:e.build_time||`unknown`})]}),(0,A.jsxs)(`span`,{className:`chip`,children:[(0,A.jsx)(`span`,{className:`ck`,children:`fp`}),(0,A.jsx)(`span`,{className:`cv`,children:n?.installed_fp||`—`})]})]})]})]})}),(0,A.jsx)(I,{overview:e,dataRev:a}),(0,A.jsxs)(`div`,{className:`grid split-status`,children:[(0,A.jsxs)(`div`,{className:`card pad-lg`,children:[(0,A.jsxs)(`div`,{className:`card-head`,children:[(0,A.jsx)(`h3`,{children:`Capability genome`}),(0,A.jsx)(`div`,{className:`right`,children:(0,A.jsxs)(`span`,{className:`tick`,children:[s.length,` sections`]})})]}),(0,A.jsx)(L,{overview:e})]}),(0,A.jsxs)(`div`,{className:`card pad-lg`,children:[(0,A.jsxs)(`div`,{className:`card-head`,children:[(0,A.jsx)(`h3`,{children:`Recent activity`}),(0,A.jsx)(`div`,{className:`right`,children:(0,A.jsxs)(`span`,{className:`badge acc`,children:[(0,A.jsx)(`span`,{className:`dot`}),`live`]})})]}),(0,A.jsx)(R,{jobs:r})]})]})]})}function V({k:e,overview:t,max:n}){let r=o[e],i=t.counts?.[e]??0;return(0,A.jsxs)(`div`,{className:`strand`,children:[(0,A.jsxs)(`span`,{className:`strand-name`,children:[(0,A.jsx)(`span`,{className:`strand-dot`}),(0,A.jsx)(`a`,{href:`#/section/`+e,className:`strand-link stretch-link`,children:r.label})]}),(0,A.jsx)(`div`,{className:`hbar`,children:(0,A.jsx)(`i`,{style:{width:`${i/n*100}%`}})}),(0,A.jsx)(`span`,{className:`strand-val`,children:i})]})}function H(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 U({overview:e,sigil:t,setup:n,jobs:r,lens:i}){let a=g(e.counts),o=n?.version_verdict||``,c=H(o),l=m(e.diff),u=[[`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,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`div`,{className:`mb-16`,children:(0,A.jsxs)(`div`,{className:`card pad-lg rise`,style:{position:`relative`,overflow:`hidden`},children:[(0,A.jsx)(`h2`,{className:`h`,style:{fontSize:22,margin:`0 0 18px`},children:`Gene-seed lineage`}),(0,A.jsxs)(`div`,{className:`lineage-track`,children:[(0,A.jsx)(`div`,{className:`spine`}),u.map(([e,t,n,r],i)=>(0,A.jsxs)(`div`,{className:`lineage-step`,children:[(0,A.jsx)(`span`,{className:`node ${r?`on`:``}`}),(0,A.jsx)(`div`,{className:`lt`,children:e}),(0,A.jsx)(`div`,{className:`ld`,children:t}),(0,A.jsx)(`div`,{className:`ltag`,children:n})]},i))]}),(0,A.jsx)(`hr`,{className:`hr`}),t&&(0,A.jsxs)(`div`,{className:`voice-readout`,style:{marginBottom:14},children:[(0,A.jsx)(`span`,{className:`vr-cur`,children:`▕`}),(0,A.jsx)(`span`,{className:`vr-txt`,children:t})]},e.theme),(0,A.jsxs)(`div`,{className:`row wrap gap-10`,children:[(0,A.jsx)(F,{verdict:i?.verdict}),c&&(0,A.jsxs)(`span`,{className:`badge ${c.tone}`,title:o,children:[(0,A.jsx)(`span`,{className:`dot`}),c.label]}),(0,A.jsxs)(`span`,{className:`badge`,children:[(0,A.jsx)(`span`,{className:`dot`}),l,` local edits`]})]})]})}),(0,A.jsxs)(`div`,{className:`grid split-even`,children:[(0,A.jsxs)(`div`,{className:`card pad-lg`,children:[(0,A.jsxs)(`div`,{className:`card-head`,children:[(0,A.jsx)(`h3`,{children:`Genome strand`}),(0,A.jsx)(`div`,{className:`right`,children:(0,A.jsx)(`span`,{className:`tick`,children:`by volume`})})]}),s.map(t=>(0,A.jsx)(V,{k:t,overview:e,max:a},t))]}),(0,A.jsxs)(`div`,{className:`card pad-lg`,children:[(0,A.jsx)(`div`,{className:`card-head`,children:(0,A.jsx)(`h3`,{children:`Recent activity`})}),(0,A.jsx)(R,{jobs:r})]})]})]})}function W({overview:e,setup:t,jobs:n,lens:r}){let i=s.reduce((t,n)=>t+(e.counts?.[n]??0),0),a=g(e.counts),c=e.doctor?.ok,l=e.doctor?.problems?.length??0,u=m(e.diff);return(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`div`,{className:`card pad-md rise mb-16`,children:(0,A.jsx)(`div`,{className:`row wrap between gap-16`,children:(0,A.jsxs)(`div`,{className:`row`,style:{gap:20,flexWrap:`wrap`},children:[(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`div`,{className:`tick`,children:`status`}),(0,A.jsxs)(`div`,{className:`row`,style:{gap:8,marginTop:4},children:[(0,A.jsxs)(`span`,{className:`badge ${e.deployed?`ok`:`warn`}`,children:[(0,A.jsx)(`span`,{className:`dot`}),e.deployed?`deployed`:`not deployed`]}),(0,A.jsx)(F,{verdict:r?.verdict})]})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`div`,{className:`tick`,children:`voice`}),(0,A.jsx)(`div`,{className:`metric`,style:{fontSize:18,marginTop:6,textTransform:`capitalize`},children:e.theme})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`div`,{className:`tick`,children:`mode`}),(0,A.jsx)(`div`,{className:`mono`,style:{fontSize:14,marginTop:6},children:e.emit})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`div`,{className:`tick`,children:`fingerprint`}),(0,A.jsx)(`div`,{className:`mono`,style:{fontSize:14,marginTop:6,color:`var(--accent)`},children:t?.installed_fp||`—`})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`div`,{className:`tick`,children:`doctor`}),(0,A.jsx)(`div`,{className:`row`,style:{gap:8,marginTop:4},children:c?(0,A.jsxs)(`span`,{className:`badge ok`,children:[(0,A.jsx)(`span`,{className:`dot`}),`clean`]}):(0,A.jsxs)(`span`,{className:`badge warn`,children:[(0,A.jsx)(`span`,{className:`dot`}),l,` issue`,l===1?``:`s`]})})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`div`,{className:`tick`,children:`edits`}),(0,A.jsx)(`div`,{className:`metric`,style:{fontSize:18,marginTop:6},children:u})]})]})})}),(0,A.jsxs)(`div`,{className:`grid split-operator`,children:[(0,A.jsxs)(`div`,{className:`card rise`,style:{"--i":1},children:[(0,A.jsxs)(`div`,{className:`card-head pad-lg`,style:{padding:`18px 20px 0`,marginBottom:14},children:[(0,A.jsx)(`h3`,{children:`Sections`}),(0,A.jsx)(`div`,{className:`right`,children:(0,A.jsxs)(`span`,{className:`tick`,children:[i,` entries total`]})})]}),(0,A.jsxs)(`table`,{className:`tbl`,children:[(0,A.jsx)(`thead`,{children:(0,A.jsxs)(`tr`,{children:[(0,A.jsx)(`th`,{children:`Section`}),(0,A.jsx)(`th`,{children:`Detail`}),(0,A.jsx)(`th`,{style:{width:130},children:`Share`}),(0,A.jsx)(`th`,{className:`num`,children:`Count`})]})}),(0,A.jsx)(`tbody`,{children:s.map(t=>{let n=o[t],r=e.counts?.[t]??0;return(0,A.jsxs)(`tr`,{className:`clickable`,children:[(0,A.jsx)(`td`,{className:`name`,children:(0,A.jsx)(`a`,{href:`#/section/`+t,className:`stretch-link`,children:n.label})}),(0,A.jsx)(`td`,{className:`muted`,children:n.desc}),(0,A.jsx)(`td`,{children:(0,A.jsx)(`div`,{className:`hbar`,children:(0,A.jsx)(`i`,{style:{width:`${r/a*100}%`}})})}),(0,A.jsx)(`td`,{className:`num`,children:r})]},t)})})]})]}),(0,A.jsxs)(`div`,{className:`card pad-lg rise`,style:{"--i":2},children:[(0,A.jsx)(`div`,{className:`card-head`,children:(0,A.jsx)(`h3`,{children:`Run log`})}),(0,A.jsx)(R,{jobs:n})]})]})]})}var G=Symbol(`failed`),K=e=>Promise.resolve().then(e).catch(()=>G);function q({dataRev:e,needDoctor:t}){let n=u(()=>K(()=>i.fleet()),[e]),r=u(()=>t?K(()=>i.doctor()):Promise.resolve(null),[t,e]),a=n.data,o=a==null?`loading`:a===G?`failed`:`ok`,s=o===`ok`?a:null,c=s?x(s):null,l=r.data,d=t?l==null?`loading`:l===G?`failed`:`ok`:`idle`;return{fleet:s,fleetState:o,verdict:c,tone:o===`failed`?`failed`:c?.tone,doctor:{state:d,data:d===`ok`?r.data:null}}}var J=e({default:()=>Q}),Y=(0,k.lazy)(()=>T(()=>import(`./GreenhouseView-BCiZP9f9.js`),__vite__mapDeps([0,1,2,3,4,5,6,7]))),X=(0,k.lazy)(()=>T(()=>import(`./OperatorHudView-BLXm0zzn.js`),__vite__mapDeps([8,1,2,3,4,5,6,7]))),Z=(0,k.lazy)(()=>T(()=>import(`./JournalView-BSR51TKR.js`),__vite__mapDeps([9,1,2,5,10,4,3,6])));function Q({overview:e,overviewError:t,onRetry:n,themes:r,setup:a,runs:o,onAction:s,layout:l=`cultivar`,dataRev:d}){let m=l,[h,g]=(0,k.useState)(`status`),_=e&&r.find(t=>t.name===e.theme)?.sigil||``,v=q({dataRev:d,needDoctor:m===`greenhouse`||m===`operator`}),{data:y}=u(()=>m===`journal`?i.recent().catch(()=>null):Promise.resolve(null),[m,d]);if(!e)return t?(0,A.jsx)(b,{error:`Could not load the harness overview: ${t}`,onRetry:n}):(0,A.jsx)(c,{});let x=e.daemon_stale?(0,A.jsx)(p,{}):null;return e.deployed?h===`status`&&m===`journal`?(0,A.jsxs)(k.Suspense,{fallback:(0,A.jsx)(c,{}),children:[x,(0,A.jsx)(Z,{overview:e,recent:y,lens:v,onDirection:g,dataRev:d})]}):(0,A.jsxs)(A.Fragment,{children:[x,(0,A.jsx)(`div`,{className:`head-row`,children:(0,A.jsx)(f,{"aria-label":`Dashboard view`,children:[[`status`,`Status`],[`lineage`,`Lineage`],[`operator`,`Operator`,`Operator data`]].map(([e,t,n])=>(0,A.jsx)(`button`,{className:h===e?`on`:``,onClick:()=>g(e),"aria-pressed":h===e,"aria-label":n,children:t},e))})}),(0,A.jsxs)(`div`,{className:`view-in`,children:[h===`status`&&m===`cultivar`&&(0,A.jsx)(B,{overview:e,sigil:_,setup:a,jobs:o,lens:v,dataRev:d}),h===`status`&&m===`greenhouse`&&(0,A.jsx)(k.Suspense,{fallback:(0,A.jsx)(c,{}),children:(0,A.jsx)(Y,{overview:e,sigil:_,jobs:o,lens:v,onAction:s})}),h===`status`&&m===`operator`&&(0,A.jsx)(k.Suspense,{fallback:(0,A.jsx)(c,{}),children:(0,A.jsx)(X,{overview:e,jobs:o,lens:v})}),h===`lineage`&&(0,A.jsx)(U,{overview:e,sigil:_,setup:a,jobs:o,lens:v}),h===`operator`&&(0,A.jsx)(W,{overview:e,setup:a,jobs:o,lens:v})]},h)]}):(0,A.jsxs)(A.Fragment,{children:[x,(0,A.jsx)(D,{onAction:s})]})}export{Q as default,j as i,F as n,N as r,J 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,F as a,I as o,J as s,M as c,P as l,T as u,V as d,a as f,c as p,i as m,k as h,n as g,o as _,r as v,s as ee,tt as y}from"./index-Dwo3Gxek.js";import{t as b}from"./EmptyState-1sPNleqv.js";import{a as te,n as ne,o as x,r as S,t as C}from"./RailCats-DNlJKicm.js";import{i as w,n as T,r as E}from"./Markdown-OReRRoEV.js";var D=e(t(),1);function O(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 k(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 A(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||O(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 j(e){let t={ids:new Set,idx:0,toc:[]},n=n=>A(T(n,e?.links),t);if(e?.rows){let[r,i]=k(e.body);return{before:n(r),after:n(i),toc:t.toc}}return{html:n(e?.body),toc:t.toc}}var M=n(),N={"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`]},P=`you already know this`;function F({page:e,overview:t,onAction:n}){let r=(0,D.useRef)(null),i=(0,D.useMemo)(()=>j({body:e.body,links:e.links}).html,[e.body,e.links]);(0,D.useEffect)(()=>{let e=r.current;e&&e.querySelectorAll(`blockquote`).forEach(e=>{(e.querySelector(`strong`)?.textContent||``).toLowerCase().startsWith(P)&&e.classList.add(`analogy`)})},[i]),(0,D.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(),y(n))};return e.addEventListener(`click`,t),()=>e.removeEventListener(`click`,t)},[i]),(0,D.useEffect)(()=>{let n=r.current;if(!n)return;n.querySelectorAll(`.docs-here`).forEach(e=>e.classList.remove(`docs-here`));let[i,a]=N[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=>O(e.textContent||``)===O(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,M.jsxs)(`div`,{className:`detail-doc`,children:[(0,M.jsx)(u,{title:e.title,actions:a.length>0&&a.map(e=>e.hash?(0,M.jsx)(`a`,{className:`btn ghost sm`,href:e.hash,children:e.label},e.label):(0,M.jsx)(`button`,{className:`btn ghost sm`,onClick:()=>n&&n(e.action),children:e.label},e.label))}),e.source&&(0,M.jsx)(`div`,{className:`doc-meta`,children:(0,M.jsxs)(`span`,{className:`badge`,children:[(0,M.jsx)(`span`,{className:`dot`}),e.source]})}),(0,M.jsx)(`div`,{className:`markdown`,ref:r,dangerouslySetInnerHTML:{__html:i}}),e.link&&(0,M.jsx)(`div`,{className:`doc-link`,children:(0,M.jsx)(`a`,{className:`btn soft sm`,href:e.link.hash,children:e.link.label})})]})}var I=e=>`cmd-`+String(e).replace(/[^\w-]+/g,`-`),L=1200;function R({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,M.jsxs)(`div`,{className:`cli-arg`,children:[(0,M.jsx)(`code`,{className:`cli-arg-name`,children:n}),r.length>0&&(0,M.jsxs)(`code`,{className:`cli-arg-meta`,children:[` `,r.join(` · `)]}),e.help&&(0,M.jsx)(`div`,{className:`cli-arg-help`,children:e.help})]})}function z({text:e}){let[t,n]=(0,D.useState)(!1);return(0,M.jsxs)(`button`,{className:`btn ghost sm`,onClick:async()=>{try{await navigator.clipboard.writeText(e),n(!0),setTimeout(()=>n(!1),L)}catch{}},title:`Copy command`,children:[(0,M.jsx)(d,{name:t?`spark`:`copy`}),t?`Copied`:`Copy`]})}function B({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,M.jsxs)(`div`,{className:`card pad-md mb-12 cli-card`,children:[(0,M.jsxs)(`div`,{className:`row wrap between cli-head`,children:[(0,M.jsxs)(`div`,{className:`stack gap-4`,children:[(0,M.jsx)(`h2`,{id:I(e.name),children:(0,M.jsx)(`code`,{children:e.name})}),e.help&&(0,M.jsx)(`p`,{className:`sub`,children:e.help})]}),(0,M.jsx)(z,{text:`${t} ${e.name}`})]}),(0,M.jsx)(`pre`,{className:`cli-syn`,children:r}),(e.positionals||[]).length>0&&(0,M.jsxs)(`div`,{className:`cli-block`,children:[(0,M.jsx)(`div`,{className:`cli-block-head`,children:`Arguments`}),e.positionals.map(e=>(0,M.jsx)(R,{a:e,kind:`positional`},e.dest))]}),(e.options||[]).length>0&&(0,M.jsxs)(`div`,{className:`cli-block`,children:[(0,M.jsx)(`div`,{className:`cli-block-head`,children:`Options`}),e.options.map(e=>(0,M.jsx)(R,{a:e,kind:`option`},e.names.join(`,`)))]})]})}function V({page:e}){let t=e.prog||`geneseed`,n=e.commands||[];return(0,M.jsxs)(`div`,{className:`detail-doc`,children:[(0,M.jsx)(u,{title:e.title,sub:(0,M.jsxs)(M.Fragment,{children:[`Every subcommand of `,(0,M.jsx)(`code`,{children:t}),`. Generated from the parser at request time (the same one `,(0,M.jsx)(`code`,{children:`geneseed`}),` actually parses), so this page cannot drift.`]})}),(0,M.jsx)(`div`,{children:n.map(e=>(0,M.jsx)(B,{cmd:e,prog:t},e.name))})]})}function H({page:e}){let t=e.rows||[],n=e.theme||`neutral`;return(0,M.jsxs)(`div`,{className:`detail-doc`,children:[(0,M.jsx)(u,{title:e.title,sub:(0,M.jsxs)(M.Fragment,{children:[`Geneseed's invented vocabulary, decoded. Left: the neutral, plain-English term. Right: the word your `,(0,M.jsx)(`code`,{className:`cap`,children:n}),` theme actually uses in the agent's voice. Last: the developer idea it maps to.`]})}),(0,M.jsx)(`div`,{className:`card pad-md`,children:(0,M.jsxs)(`table`,{className:`glossary-table`,children:[(0,M.jsx)(`thead`,{children:(0,M.jsxs)(`tr`,{children:[(0,M.jsx)(`th`,{children:`Concept`}),(0,M.jsx)(`th`,{children:`Neutral term`}),(0,M.jsxs)(`th`,{children:[`In `,n]}),(0,M.jsx)(`th`,{children:`Meaning`}),(0,M.jsx)(`th`,{children:`In dev terms`})]})}),(0,M.jsx)(`tbody`,{children:t.map(e=>(0,M.jsxs)(`tr`,{children:[(0,M.jsx)(`td`,{children:(0,M.jsx)(`strong`,{children:e.label})}),(0,M.jsx)(`td`,{children:(0,M.jsx)(`code`,{children:e.neutral||`—`})}),(0,M.jsx)(`td`,{children:(0,M.jsx)(`code`,{children:e.themed||e.neutral||`—`})}),(0,M.jsx)(`td`,{className:`dim`,children:e.desc}),(0,M.jsx)(`td`,{className:`dim`,children:e.analogy||`—`})]},e.label))})]})})]})}var U={enforced:`ok`,automatic:`ok`,asked:`warn`,"on demand":`warn`},W=({text:e})=>(0,M.jsx)(`span`,{dangerouslySetInnerHTML:{__html:E(w.parseInline(e||``))}}),G=({kind:e})=>(0,M.jsx)(`span`,{className:`tag ${U[e]||``}`,children:e});function K({page:e,overview:t,onAction:n}){let[r,i]=(0,D.useState)(0),{before:a,after:o}=(0,D.useMemo)(()=>j(e),[e]);if(!e.rows)return(0,M.jsx)(F,{page:e,overview:t,onAction:n});let s=e.rows[r]||e.rows[0];return(0,M.jsxs)(`div`,{className:`detail-doc`,children:[(0,M.jsx)(u,{title:e.title}),(0,M.jsx)(`div`,{className:`markdown`,dangerouslySetInnerHTML:{__html:a}}),(0,M.jsxs)(`div`,{className:`docs-map`,children:[(0,M.jsx)(`ul`,{className:`map-tree`,"aria-label":`Pieces`,children:e.rows.map((e,t)=>(0,M.jsx)(`li`,{children:(0,M.jsxs)(`button`,{className:`map-node ${t===r?`on`:``}`,"aria-pressed":t===r,onClick:()=>i(t),children:[(0,M.jsx)(`span`,{className:`map-piece`,children:(0,M.jsx)(W,{text:e.piece})}),(0,M.jsx)(G,{kind:e.kind}),(0,M.jsx)(`span`,{className:`mono dim map-cost`,children:(0,M.jsx)(W,{text:e.cost})})]})},t))}),s&&(0,M.jsxs)(`div`,{className:`card pad-md map-detail`,"aria-live":`polite`,children:[(0,M.jsx)(`h2`,{children:(0,M.jsx)(W,{text:s.piece})}),(0,M.jsx)(G,{kind:s.kind}),(0,M.jsxs)(`dl`,{children:[(0,M.jsx)(`dt`,{children:`Does`}),(0,M.jsx)(`dd`,{children:(0,M.jsx)(W,{text:s.does})}),(0,M.jsx)(`dt`,{children:`Costs`}),(0,M.jsx)(`dd`,{children:(0,M.jsx)(W,{text:s.cost})}),(0,M.jsx)(`dt`,{children:`Turn it off`}),(0,M.jsx)(`dd`,{children:(0,M.jsx)(W,{text:s.off})})]})]})]}),o.trim()&&(0,M.jsx)(`div`,{className:`markdown`,dangerouslySetInnerHTML:{__html:o}})]})}var q=5,J=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);function Y(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-])${J(e)}s?(?![\\w-])`,`i`).test(n))&&r.push(e),r.length===q)break;return r}var X=e=>document.getElementById(e)?.scrollIntoView({behavior:`smooth`});function Z({page:e,glossaryRows:t}){let n=e?.body,r=(0,D.useMemo)(()=>e?.kind===`cli`?(e.commands||[]).map(e=>({id:I(e.name),title:e.name,level:2})):j(e).toc,[e]),i=(0,D.useMemo)(()=>Y(n,t),[n,t]);return!r.length&&!i.length?null:(0,M.jsxs)(`aside`,{className:`docs-margin`,children:[r.length>0&&(0,M.jsxs)(`nav`,{className:`docs-toc`,"aria-label":`On this page`,children:[(0,M.jsx)(`div`,{className:`docs-toc-head`,children:`On this page`}),(0,M.jsx)(`ul`,{children:r.map(e=>(0,M.jsx)(`li`,{className:`lvl-${e.level}`,children:(0,M.jsx)(`a`,{href:`#${e.id}`,onClick:t=>{t.preventDefault(),X(e.id)},children:e.title})},e.id))})]}),i.length>0&&(0,M.jsxs)(`div`,{className:`docs-gloss`,children:[(0,M.jsx)(`div`,{className:`docs-toc-head`,children:`Terms on this page`}),i.map(e=>(0,M.jsxs)(`div`,{className:`docs-gloss-card`,children:[(0,M.jsx)(`b`,{children:e.themed||e.neutral||e.label}),(0,M.jsx)(`p`,{children:e.desc})]},e.label))]})]})}function re({page:e}){let t=e.version||{},n=[[`Theme`,e.theme],[`Install mode`,e.emit],[`Deployed`,e.deployed?`yes`:`no`],[`Target`,(0,M.jsx)(`code`,{children:e.target},`t`)],[`Source root`,(0,M.jsx)(`code`,{children:e.root},`r`)],[`Installed build`,(0,M.jsx)(`code`,{children:t.installed_fp||`(none)`},`i`)],[`Source build`,(0,M.jsx)(`code`,{children:t.source_fp||`—`},`s`)],[`Match?`,t.verdict||`—`],[`License`,e.license]];return(0,M.jsxs)(`div`,{className:`detail-doc`,children:[(0,M.jsx)(u,{title:e.title,sub:`Live snapshot of the install behind this UI, plus where to go next.`}),(0,M.jsx)(`div`,{className:`card pad-md mb-18`,children:n.map(([e,t])=>(0,M.jsxs)(`div`,{className:`kv`,children:[(0,M.jsx)(`span`,{className:`k`,children:e}),(0,M.jsx)(`span`,{className:`v`,children:t??`—`})]},e))}),(0,M.jsxs)(`div`,{className:`row wrap gap-10`,children:[(0,M.jsxs)(`a`,{className:`btn ghost`,href:e.repo,target:`_blank`,rel:`noreferrer`,children:[(0,M.jsx)(d,{name:`external`}),e.repo_is_github?`GitHub repo`:`Source repo`]}),e.repo_is_github&&(0,M.jsxs)(M.Fragment,{children:[(0,M.jsxs)(`a`,{className:`btn ghost`,href:`${e.repo}/issues`,target:`_blank`,rel:`noreferrer`,children:[(0,M.jsx)(d,{name:`external`}),`File an issue`]}),(0,M.jsxs)(`a`,{className:`btn ghost`,href:`${e.repo}/blob/main/LICENSE`,target:`_blank`,rel:`noreferrer`,children:[(0,M.jsx)(d,{name:`external`}),`License`]})]})]})]})}function Q(e){return e?.groups?.[0]?.pages?.[0]?.id||``}function ie({data:e,error:t,overview:n,onAction:r}){if(t)return(0,M.jsx)(h,{error:t,style:{margin:18}});if(!e)return(0,M.jsx)(i,{label:`Loading page…`});switch(e.kind){case`markdown`:case`concept`:return(0,M.jsx)(F,{page:e,overview:n,onAction:r});case`map`:return(0,M.jsx)(K,{page:e,overview:n,onAction:r});case`cli`:return(0,M.jsx)(V,{page:e});case`glossary`:return(0,M.jsx)(H,{page:e});case`about`:return(0,M.jsx)(re,{page:e});default:return(0,M.jsx)(b,{title:`Unknown page kind`,children: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 ae({page:e,overview:t,onAction:n}){let[u,d]=o(a(t?.emit)),{data:y,error:b}=s(()=>r.docs(u),[u]),w=e||Q(y),{data:T,error:E,loading:O}=s(()=>w?r.docsPage(w,u):Promise.resolve(null),[w,u]),{data:k}=s(()=>r.docsPage(`glossary`,u).catch(()=>null),[u],`docs:glossary`);(0,D.useEffect)(()=>{if(y&&w&&!y.groups.some(e=>e.pages.some(e=>e.id===w))){let e=Q(y);e&&e!==w&&window.location.replace(f(e))}},[y,w]),(0,D.useEffect)(()=>{let e=document.scrollingElement||document.documentElement;for(let t of[document.getElementById(`main`),e])t&&(t.scrollTop=0)},[w]);let A=ee(y,w),j=A.part||y?.groups?.[0]||null,N=j?.id===v;(0,D.useEffect)(()=>{N&&T?.id===w&&_(w)},[N,T,w]);let P=N?[...p(),w]:[],[F,I]=(0,D.useState)(``),[L,R]=(0,D.useState)(`all`),[z,B]=(0,D.useState)(j?.id);j?.id!==z&&(B(j?.id),I(``),R(`all`));let V=$(j),H=ne(V),U=L===`all`?V:V.filter(e=>e.group===L),W=x(U,F);return b?(0,M.jsx)(h,{error:b}):(0,M.jsx)(`div`,{className:`docs-wrap`,children:(0,M.jsxs)(`div`,{className:`library docs-lib`,children:[(0,M.jsxs)(`aside`,{className:`lib-kinds`,"aria-label":`Docs parts`,children:[(0,M.jsxs)(`div`,{className:`lib-title`,children:[(0,M.jsx)(`p`,{className:`h`,children:`Docs`}),(0,M.jsx)(`span`,{className:`dim`,children:`How it works, and how to use it`})]}),(0,M.jsx)(c,{"aria-label":`Harness`,children:l.map(e=>(0,M.jsx)(`button`,{className:u===e.id?`on`:``,onClick:()=>d(e.id),"aria-pressed":u===e.id,children:e.label},e.id))}),(0,M.jsx)(`nav`,{className:`kind-list`,"aria-label":`Parts`,children:(y?.groups||[]).map(e=>(0,M.jsxs)(D.Fragment,{children:[(0,M.jsxs)(`a`,{href:e.pages[0]?f(e.pages[0].id):`#/docs`,className:j?.id===e.id?`on`:``,"aria-current":j?.id===e.id?`page`:void 0,children:[e.label,(0,M.jsx)(`span`,{className:`mono dim`,children:e.pages.length})]}),j?.id===e.id&&(0,M.jsx)(C,{label:`Sections`,total:V.length,cats:H,cat:L,onChange:R})]},e.id))})]}),(0,M.jsx)(te,{label:j?.label||`Docs`,count:F.trim()?`${W.length} of ${U.length}`:U.length||``,extra:N&&(0,M.jsx)(m,{pages:j.pages,seen:P}),q:F,onQ:I,matched:W.length,inView:[j?.id,w],children:y?(0,M.jsx)(S,{rows:W,activeName:w,hrefOf:e=>f(e.name),pills:N?e=>P.includes(e.name)&&e.name!==w?(0,M.jsx)(`span`,{className:`docs-read-mark`,role:`img`,"aria-label":`, read`,children:`✓`}):null:void 0}):(0,M.jsx)(i,{label:`Loading docs…`})}),(0,M.jsxs)(`article`,{className:`lib-reader docs-reader`,"aria-label":`Page`,children:[A.page&&(0,M.jsxs)(`nav`,{className:`docs-crumbs mono`,"aria-label":`Breadcrumb`,children:[(0,M.jsx)(`a`,{href:f(A.part.pages[0].id),children:A.part.label}),(0,M.jsx)(`span`,{"aria-hidden":`true`,children:`›`}),(0,M.jsx)(`a`,{href:f(A.part.pages.find(e=>(e.section||`General`)===A.section).id),children:A.section}),(0,M.jsx)(`span`,{"aria-hidden":`true`,children:`›`}),(0,M.jsx)(`span`,{"aria-current":`page`,children:A.page.title})]}),(0,M.jsxs)(`div`,{className:`docs-read`,children:[(0,M.jsxs)(`div`,{className:`docs-article`,children:[(0,M.jsx)(ie,{data:O?null:T,error:E,overview:t,onAction:n},`${w}|${u}`),!O&&(0,M.jsx)(g,{menu:y,pageId:w})]}),!O&&(0,M.jsx)(Z,{page:T,glossaryRows:k?.rows})]})]})]})})}export{ae as default,$ as docRows};
@@ -0,0 +1 @@
1
+ import"./rolldown-runtime-hePW80VL.js";import{i as e,t}from"./react-DlYQp10C.js";e();var n=t();function r({title:e,children:t,action:r,docs:i}){return(0,n.jsxs)(`div`,{className:`empty`,children:[e?(0,n.jsx)(`div`,{className:`big`,children:e}):null,t?(0,n.jsx)(`div`,{children:t}):null,r||i?(0,n.jsxs)(`div`,{className:`empty-actions`,children:[r,i?(0,n.jsx)(`a`,{href:i.href,children:i.label}):null]}):null]})}export{r as t};
@@ -0,0 +1 @@
1
+ import"./rolldown-runtime-hePW80VL.js";import{i as e,t}from"./react-DlYQp10C.js";import{n,r}from"./sections-ChwaobfW.js";import{K as i,U as a,V as o,rt as s}from"./index-Dwo3Gxek.js";import{n as c,r as l,t as u}from"./jobBuckets-Dpjvbfm1.js";import{i as d,n as f,r as p}from"./Dashboard-BZmw2a7d.js";e();var m=t(),h=12,g=[`#2BB673`,`#16A6A6`,`#E8A23B`,`#E07A5F`,`#8E7DBE`,`#5BD08A`,`#79856E`],_=650;function v({segments:e,size:t=186,stroke:n=26,caption:r=`capabilities`}){let i=e.reduce((e,t)=>e+t.n,0);return(0,m.jsxs)(`div`,{className:`ring-box`,children:[(0,m.jsx)(d,{segments:e,size:t,stroke:n,label:r,sweepMs:_}),(0,m.jsxs)(`div`,{className:`ring-center`,children:[(0,m.jsx)(`div`,{className:`donut-c-num`,children:(0,m.jsx)(s,{value:i,duration:_})}),(0,m.jsx)(`div`,{className:`donut-c-cap`,children:r})]})]})}function y(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 b({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=y(o),c=o[o.length-1],l=o[0],u=`${s} L${c[0]},${r} L${l[0]},${r} Z`;return(0,m.jsxs)(`svg`,{viewBox:`0 0 600 ${r}`,preserveAspectRatio:`none`,style:{width:`100%`,height:t,display:`block`,overflow:`visible`},children:[(0,m.jsx)(`defs`,{children:(0,m.jsxs)(`linearGradient`,{id:`b-grad`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,m.jsx)(`stop`,{offset:`0`,stopColor:n,stopOpacity:`.28`}),(0,m.jsx)(`stop`,{offset:`1`,stopColor:n,stopOpacity:`0`})]})}),(0,m.jsx)(`path`,{d:u,fill:`url(#b-grad)`}),(0,m.jsx)(`path`,{d:s,fill:`none`,stroke:n,strokeWidth:`2`,strokeLinejoin:`round`,strokeLinecap:`round`,vectorEffect:`non-scaling-stroke`}),(0,m.jsx)(`circle`,{cx:c[0],cy:c[1],r:`3.5`,fill:n,vectorEffect:`non-scaling-stroke`})]})}function x({label:e,value:t,sub:n,color:r,icon:i}){return(0,m.jsxs)(`div`,{className:`b-tile`,children:[(0,m.jsx)(`span`,{className:`b-tile-ic`,style:{background:`color-mix(in srgb, ${r} 18%, transparent)`,color:r},children:(0,m.jsx)(o,{name:i})}),(0,m.jsxs)(`div`,{className:`b-tile-body`,children:[(0,m.jsx)(`div`,{className:`b-tile-val`+(t===0?` zero`:``),children:t}),(0,m.jsx)(`div`,{className:`b-tile-label`,children:e})]}),(0,m.jsx)(`div`,{className:`b-tile-sub`,children:n})]})}function S({overview:e,sigil:t,jobs:d,lens:_,onAction:y}){let S=e.counts||{},C=_?.doctor?.state||`loading`,w=_?.doctor?.data?.groups||[],T=C===`ok`,E=w.filter(e=>e.problems.length===0).length,D=w.length,O=p(e,_?.tone),k=l(d,h),A=a(e.diff),j=r.filter(e=>(S[e]||0)>0).map((e,t)=>({key:e,label:n[e].label,n:S[e]||0,tone:`cat`+t%g.length,color:g[t%g.length]})),M=j.reduce((e,t)=>e+t.n,0),N=u(d||[],10),P=N.reduce((e,t)=>e+t.v,0);return(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`div`,{className:`b-greet`,children:(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`div`,{className:`eyebrow`,children:`your harness`}),(0,m.jsx)(`h2`,{className:`h b-h`,children:O}),(0,m.jsx)(f,{verdict:_?.verdict}),(0,m.jsx)(`p`,{className:`sub`,children:t||`A friendly read of every layer growing in your harness.`})]})}),(0,m.jsxs)(`div`,{className:`grid b-hero-grid mb-16`,children:[(0,m.jsxs)(`div`,{className:`card b-hero`,children:[(0,m.jsx)(`div`,{className:`b-hero-ring`,children:(0,m.jsx)(v,{segments:[{key:`pass`,label:`pass`,n:E,tone:`good`},{key:`attention`,label:`attention`,n:Math.max(D-E,0),tone:`warn`}],size:168,stroke:20,caption:`checks`})}),(0,m.jsxs)(`div`,{className:`b-hero-side`,children:[(0,m.jsx)(`h3`,{className:`b-hero-title`,children:T?`${E} of ${D} checks pass`:C===`failed`?`Doctor did not answer`:`Checking…`}),C===`failed`&&(0,m.jsxs)(`button`,{className:`btn ghost b-hero-retry`,"aria-label":`Run doctor again`,onClick:()=>y(`doctor`),children:[(0,m.jsx)(o,{name:`doctor`}),`Run doctor`]}),(0,m.jsxs)(`p`,{className:`sub`,children:[`One source, rendered into `,(0,m.jsx)(`code`,{children:e.target}),` and inherited by every repo on this machine.`]}),T&&(0,m.jsx)(`ul`,{className:`b-hero-checks`,children:w.map(e=>{let t=e.problems.length===0;return(0,m.jsxs)(`li`,{className:`b-hcheck ${t?`ok`:`bad`}`,title:t?`clean`:e.problems.join(`; `),children:[(0,m.jsx)(`span`,{className:`b-hcheck-mark`,children:t?`✓`:`!`}),(0,m.jsx)(`span`,{className:`b-hcheck-label`,children:e.label})]},e.label)})}),(0,m.jsxs)(`div`,{className:`b-chips`,children:[(0,m.jsxs)(`span`,{className:`b-chip`,children:[(0,m.jsx)(`b`,{className:`t-cap`,children:e.theme}),` voice`]}),(0,m.jsx)(`span`,{className:`b-chip`,children:(0,m.jsx)(`b`,{children:e.emit})}),(0,m.jsxs)(`span`,{className:`b-chip`,children:[`built `,(0,m.jsx)(`b`,{children:e.build_time||`unknown`})]})]})]})]}),(0,m.jsxs)(`div`,{className:`b-tiles`,children:[(0,m.jsx)(x,{label:`Agents`,value:S.agents??`—`,sub:`specialists`,color:g[0],icon:`layers`}),(0,m.jsx)(x,{label:`Skills`,value:S.skills??`—`,sub:`workflows`,color:g[1],icon:`skill`}),(0,m.jsx)(x,{label:`Dictates`,value:S.laws??`—`,sub:S.doctrines?`${S.doctrines.active}/${S.doctrines.total} packs · ${S.doctrines.rules} rules`:`all upheld`,color:g[2],icon:`law`}),(0,m.jsx)(x,{label:`Edits`,value:A,sub:`to graft`,color:g[3],icon:`changes`})]})]}),(0,m.jsxs)(`div`,{className:`grid split-even mb-16`,children:[(0,m.jsxs)(`div`,{className:`card pad-lg b-mix-card`,children:[(0,m.jsxs)(`div`,{className:`card-head`,children:[(0,m.jsx)(`h3`,{children:`Capability mix`}),(0,m.jsx)(`div`,{className:`right`,children:(0,m.jsxs)(`span`,{className:`tick`,children:[M,` total`]})})]}),(0,m.jsxs)(`div`,{className:`b-mix`,children:[(0,m.jsx)(v,{segments:j,size:186,stroke:26}),(0,m.jsx)(`div`,{className:`b-legend`,children:j.map(e=>(0,m.jsxs)(`div`,{className:`b-leg-row`,children:[(0,m.jsx)(`span`,{className:`b-leg-dot`,style:{background:e.color}}),(0,m.jsx)(`span`,{className:`b-leg-name`,children:e.label}),(0,m.jsx)(`span`,{className:`b-leg-bar`,children:(0,m.jsx)(`i`,{style:{width:`${e.n/M*100}%`,background:e.color}})}),(0,m.jsx)(`span`,{className:`b-leg-val`,children:e.n})]},e.label))})]})]}),(0,m.jsxs)(`div`,{className:`card pad-lg`,children:[(0,m.jsxs)(`div`,{className:`card-head`,children:[(0,m.jsx)(`h3`,{children:`Recent runs`}),(0,m.jsx)(`div`,{className:`right`,children:(0,m.jsxs)(`span`,{className:`badge ok`,children:[(0,m.jsx)(`span`,{className:`dot`}),`job log`]})})]}),(0,m.jsxs)(`div`,{className:`b-stat-lead`,children:[(0,m.jsx)(`span`,{className:`b-stat-big`,children:(0,m.jsx)(s,{value:P})}),(0,m.jsxs)(`span`,{className:`b-stat-cap`,children:[`runs in the last 10 days`,T&&D>0&&` · ${E}/${D} checks pass now`]})]}),(0,m.jsx)(b,{data:N,accent:g[0],height:156})]})]}),(0,m.jsxs)(`div`,{className:`card pad-lg`,children:[(0,m.jsxs)(`div`,{className:`card-head`,children:[(0,m.jsx)(`h3`,{children:`Recent activity`}),(0,m.jsx)(`div`,{className:`right`,children:(0,m.jsxs)(`span`,{className:`tick`,children:[`last `,k.length,` runs`]})})]}),(0,m.jsxs)(`div`,{className:`b-timeline`,children:[k.map(e=>{let t=e.status===`done`,n=e.status===`failed`?`warn`:t?`ok`:`acc`,r=c(e);return(0,m.jsxs)(`div`,{className:`b-tl-row`,children:[(0,m.jsx)(`span`,{className:`b-tl-node ${n}`}),(0,m.jsxs)(`div`,{className:`b-tl-body`,title:r.command||void 0,children:[(0,m.jsx)(`b`,{children:r.verb}),[r.scope,r.result,r.duration].map(e=>e?` · ${e}`:``).join(``)]}),(0,m.jsx)(`span`,{className:`b-tl-when`,children:e.started?`${i(e.started)} ago`:`—`})]},e.id)}),(!d||d.length===0)&&(0,m.jsxs)(`div`,{className:`b-tl-row`,children:[(0,m.jsx)(`span`,{className:`b-tl-node`}),(0,m.jsx)(`div`,{className:`b-tl-body sub`,children:`No runs yet. Trigger an action to populate this.`}),(0,m.jsx)(`span`,{className:`b-tl-when`,children:`—`})]})]})]})]})}export{S as default};