geneseed 4.8.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/SHIPPED.md +1 -1
- package/adapters/claude-code/README.md +3 -1
- package/adapters/opencode/plugins/geneseed-context.js +17 -1
- package/adapters/opencode/plugins/geneseed-guard.js +17 -15
- package/bin/geneseed-hook.mjs +9 -4
- package/docs/concepts/enforcement-table.md +2 -2
- package/docs/concepts/exclusions.md +18 -1
- package/docs/concepts/hooks.md +2 -2
- package/docs/reference/plugin-context.md +1 -1
- package/docs/reference/plugin-guard.md +1 -1
- package/docs/reference/troubleshoot-doctor.md +2 -1
- package/docs/web-ui.md +7 -6
- package/harness.config.json +1 -1
- package/js/build/args.mjs +3 -0
- package/js/build/driver.mjs +14 -6
- package/js/build/emit-claude.mjs +3 -3
- package/js/build/generate.mjs +16 -12
- package/js/build/render.mjs +7 -5
- package/js/build/source.mjs +19 -1
- package/js/cli-table.json +75 -0
- package/js/hosts/hooks-done.mjs +4 -0
- package/js/hosts/hooks-learn.mjs +3 -1
- package/js/hosts/hooks.mjs +3 -1
- package/js/hosts/installs.mjs +20 -11
- package/js/hosts/settings.mjs +17 -8
- package/js/inspect/diff.mjs +4 -4
- package/js/inspect/status.mjs +4 -3
- package/js/inspect/validate.mjs +9 -4
- package/js/maintain/uninstall.mjs +7 -5
- package/js/maintain/update.mjs +1 -1
- package/js/web/actions.mjs +20 -16
- package/js/web/api.mjs +4 -3
- package/package.json +1 -1
- package/src/AGENT.md.tmpl +1 -1
- package/web/dist/assets/{Activity-B-XbKlzu.js → Activity-DZ3O_DsJ.js} +1 -1
- package/web/dist/assets/{ActivityDetail-8oq0fycD.js → ActivityDetail-BQSWwoJ-.js} +1 -1
- package/web/dist/assets/Dashboard-COLskkOJ.js +2 -0
- package/web/dist/assets/Docs-DUxizutI.js +5 -0
- package/web/dist/assets/FilterInput-zLFXoSt6.js +1 -0
- package/web/dist/assets/GreenhouseView-BSzVX_l7.js +2 -0
- package/web/dist/assets/{Installs-DrqPaLDM.js → Installs-Ck4YyEzs.js} +2 -2
- package/web/dist/assets/JournalView-BbbACsYK.js +1 -0
- package/web/dist/assets/Laws-BZ_M86r3.js +3 -0
- package/web/dist/assets/{Library-BCaqPf61.js → Library-D_4LbUg2.js} +1 -1
- package/web/dist/assets/{Loops-Bx3HnlUA.js → Loops-Bzb2Y96W.js} +2 -2
- package/web/dist/assets/{Markdown-BK38dn4x.js → Markdown-iHvBrpRN.js} +1 -1
- package/web/dist/assets/{OperatorHudView-ChQPM8JE.js → OperatorHudView-D-nzB6_r.js} +1 -1
- package/web/dist/assets/{Personal-DELm61DF.js → Personal-C66284wd.js} +1 -1
- package/web/dist/assets/Tabs-DkPfjG3H.js +1 -0
- package/web/dist/assets/{activity-D4w9t8fE.js → activity-DvPxoS4Y.js} +1 -1
- package/web/dist/assets/drawable-DlrXDOJ7.js +1 -0
- package/web/dist/assets/{index-CHpydQJg.css → index-BCJz4_8C.css} +1 -1
- package/web/dist/assets/{index-r2jRgf6l.js → index-DJorAjeH.js} +2 -2
- package/web/dist/assets/{react-Ci4wQD4a.js → react-BOF6yL40.js} +1 -1
- package/web/dist/assets/{sections-GalMS0Zv.js → sections-BET3c1WT.js} +1 -1
- package/web/dist/assets/{usePoll-BcywUo55.js → usePoll-NSTzLOF4.js} +1 -1
- package/web/dist/index.html +4 -4
- package/web/src/pages/Laws.jsx +52 -25
- package/web/dist/assets/Dashboard-C4EMz5mf.js +0 -2
- package/web/dist/assets/Docs-mq4XDQK_.js +0 -5
- package/web/dist/assets/FilterInput-Ikvi-pS9.js +0 -1
- package/web/dist/assets/GreenhouseView-D1WOtq3n.js +0 -2
- package/web/dist/assets/JournalView-BYpASU-L.js +0 -1
- package/web/dist/assets/Laws-A3PFwiPD.js +0 -3
- package/web/dist/assets/Tabs-DcMq5IvC.js +0 -1
- package/web/dist/assets/drawable-BI2_tF3o.js +0 -1
package/js/cli-table.json
CHANGED
|
@@ -238,6 +238,36 @@
|
|
|
238
238
|
"type": null,
|
|
239
239
|
"hidden": false
|
|
240
240
|
},
|
|
241
|
+
{
|
|
242
|
+
"names": [
|
|
243
|
+
"--no-secrets-gate"
|
|
244
|
+
],
|
|
245
|
+
"dest": "no_secrets_gate",
|
|
246
|
+
"metavar": null,
|
|
247
|
+
"help": "switch Law I's secret scan off for this install: a credential-shaped write stops being refused (Sealed Secrets' text still binds); written to the carrier as 'Secrets gate: off' and replayed by rebuilds",
|
|
248
|
+
"choices": null,
|
|
249
|
+
"default": false,
|
|
250
|
+
"required": false,
|
|
251
|
+
"nargs": "0",
|
|
252
|
+
"is_flag": true,
|
|
253
|
+
"type": null,
|
|
254
|
+
"hidden": false
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"names": [
|
|
258
|
+
"--no-done-gate"
|
|
259
|
+
],
|
|
260
|
+
"dest": "no_done_gate",
|
|
261
|
+
"metavar": null,
|
|
262
|
+
"help": "switch Law III's done gate off for this install: a turn may end with the project's declared checks unproven (Verify Before Asserting's text still binds); written to the carrier as 'Done gate: off' and replayed by rebuilds",
|
|
263
|
+
"choices": null,
|
|
264
|
+
"default": false,
|
|
265
|
+
"required": false,
|
|
266
|
+
"nargs": "0",
|
|
267
|
+
"is_flag": true,
|
|
268
|
+
"type": null,
|
|
269
|
+
"hidden": false
|
|
270
|
+
},
|
|
241
271
|
{
|
|
242
272
|
"names": [
|
|
243
273
|
"--no-deletion-gate"
|
|
@@ -672,6 +702,21 @@
|
|
|
672
702
|
"is_flag": true,
|
|
673
703
|
"type": null,
|
|
674
704
|
"hidden": false
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
"names": [
|
|
708
|
+
"--no-done-gate"
|
|
709
|
+
],
|
|
710
|
+
"dest": "no_done_gate",
|
|
711
|
+
"metavar": null,
|
|
712
|
+
"help": "skip the done gate on Stop (set by the emit when the install was built --no-done-gate); learning still runs",
|
|
713
|
+
"choices": null,
|
|
714
|
+
"default": false,
|
|
715
|
+
"required": false,
|
|
716
|
+
"nargs": "0",
|
|
717
|
+
"is_flag": true,
|
|
718
|
+
"type": null,
|
|
719
|
+
"hidden": false
|
|
675
720
|
}
|
|
676
721
|
],
|
|
677
722
|
"mutex": []
|
|
@@ -1150,6 +1195,21 @@
|
|
|
1150
1195
|
"is_flag": false,
|
|
1151
1196
|
"type": null,
|
|
1152
1197
|
"hidden": false
|
|
1198
|
+
},
|
|
1199
|
+
{
|
|
1200
|
+
"names": [
|
|
1201
|
+
"--no-secrets-gate"
|
|
1202
|
+
],
|
|
1203
|
+
"dest": "no_secrets_gate",
|
|
1204
|
+
"metavar": null,
|
|
1205
|
+
"help": "skip the Sealed Secrets credential scan (set by the emit when the install was built --no-secrets-gate); the protected checks and the persist check still run",
|
|
1206
|
+
"choices": null,
|
|
1207
|
+
"default": false,
|
|
1208
|
+
"required": false,
|
|
1209
|
+
"nargs": "0",
|
|
1210
|
+
"is_flag": true,
|
|
1211
|
+
"type": null,
|
|
1212
|
+
"hidden": false
|
|
1153
1213
|
}
|
|
1154
1214
|
],
|
|
1155
1215
|
"mutex": []
|
|
@@ -1427,6 +1487,21 @@
|
|
|
1427
1487
|
"is_flag": true,
|
|
1428
1488
|
"type": null,
|
|
1429
1489
|
"hidden": false
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
"names": [
|
|
1493
|
+
"--no-secrets-gate"
|
|
1494
|
+
],
|
|
1495
|
+
"dest": "no_secrets_gate",
|
|
1496
|
+
"metavar": null,
|
|
1497
|
+
"help": "skip the Sealed Secrets credential scan (set by the emit when the install was built --no-secrets-gate); the deletion, root-scan and protected checks still refuse",
|
|
1498
|
+
"choices": null,
|
|
1499
|
+
"default": false,
|
|
1500
|
+
"required": false,
|
|
1501
|
+
"nargs": "0",
|
|
1502
|
+
"is_flag": true,
|
|
1503
|
+
"type": null,
|
|
1504
|
+
"hidden": false
|
|
1430
1505
|
}
|
|
1431
1506
|
],
|
|
1432
1507
|
"mutex": []
|
package/js/hosts/hooks-done.mjs
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* last-writer-wins: an older `geneseed-hook` would refuse a new verb or flag, and the Stop
|
|
11
11
|
* command's `|| exit 0` would then skip learning too, silently. Arming on a project FILE keeps
|
|
12
12
|
* every emitted settings file byte-identical, so a stale shim only means "no done gate".
|
|
13
|
+
* The ONE flag is the off switch, `--no-done-gate` (user decision 2026-10-18): it is emitted
|
|
14
|
+
* only on an install built with the gate off, so armed settings stay byte-identical — but on
|
|
15
|
+
* such an install a stale shim refuses the flag and that install loses LEARNING too, not just a
|
|
16
|
+
* gate it already switched off. Hence "run rebuild-all before switching it off" (exclusions.md).
|
|
13
17
|
*
|
|
14
18
|
* WHY STDOUT JSON AND NOT EXIT 2. The emitted Stop command ends in `|| exit 0`, which swallows
|
|
15
19
|
* a 2. `{"decision":"block"}` on exit 0 is the one signal that survives the existing wiring.
|
package/js/hosts/hooks-learn.mjs
CHANGED
|
@@ -312,7 +312,9 @@ export function cmdLearn(args) {
|
|
|
312
312
|
|
|
313
313
|
// The done gate (#289) judges the turn BEFORE anything here spawns, and only on Stop. A block
|
|
314
314
|
// means the turn goes on, so there is nothing to distil yet: the next Stop will.
|
|
315
|
-
|
|
315
|
+
// `--no-done-gate` (the install switched Law III's gate off) skips the check, never the
|
|
316
|
+
// distillation below.
|
|
317
|
+
if (hookEvent === 'Stop' && !args.file && !args.noDoneGate && doneGate(meta, args, install)) return 0;
|
|
316
318
|
|
|
317
319
|
// I2 (Bob): its Stop payload never carries `transcript_path`, so there is never a transcript
|
|
318
320
|
// to distil — and the bare envelope itself is not notes text (that would waste a model call
|
package/js/hosts/hooks.mjs
CHANGED
|
@@ -569,7 +569,9 @@ function ruleDecide(args, payload) {
|
|
|
569
569
|
const edits = Array.isArray(ti.edits) ? ti.edits.map((e) => e && e.new_string) : [];
|
|
570
570
|
const body = [ti.content, ti.new_string, ti.new_source, diffReplaced(ti.diff), ti.replace, ...edits]
|
|
571
571
|
.filter((v) => typeof v === 'string').join('\n');
|
|
572
|
-
|
|
572
|
+
// `--no-secrets-gate`: the install switched Law I's scan off (user decision 2026-10-18). Only
|
|
573
|
+
// this check stands down; the protected checks and process 1 below still run.
|
|
574
|
+
if (!args.noSecretsGate && body && !DOTENV_RE.test(p) && SECRET_RE.test(body)) {
|
|
573
575
|
return ask(args, 'rule-gate', 'law-1', `Geneseed (Sealed Secrets) — ${p} would carry a `
|
|
574
576
|
+ 'credential-shaped string. Secrets live in .env or a secret manager, never in a '
|
|
575
577
|
+ 'tracked file.');
|
package/js/hosts/installs.mjs
CHANGED
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
import { existsSync, readdirSync } from 'node:fs';
|
|
36
36
|
import path from 'node:path';
|
|
37
37
|
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
CONFIG, GATE_SWITCHES, PACK_ORDER, THEMES, discoverNames, resolveSkillNames,
|
|
40
|
+
} from '../build/source.mjs';
|
|
39
41
|
import {
|
|
40
42
|
CLAUDE_STYLE, DISABLED_STASH, GLOBAL_MANIFEST, HOSTS, isHostGlobalDir, liveRecordedHooks,
|
|
41
43
|
resolvePath,
|
|
@@ -583,26 +585,33 @@ export function excludedSkillsOfDir(d, host = null, notify = null) {
|
|
|
583
585
|
}, [], host);
|
|
584
586
|
}
|
|
585
587
|
|
|
586
|
-
/** `Deletion gate: off` — written only when Law IV's gate was switched off. */
|
|
587
|
-
const DELETION_GATE_RE = /^Deletion gate:[ \t]*(.+?)[ \t]*$/m;
|
|
588
|
-
|
|
589
588
|
/**
|
|
590
|
-
* Whether a DEPLOYED install keeps
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
589
|
+
* Whether a DEPLOYED install keeps one law's hook gate armed — `true` (armed) or `false` (its
|
|
590
|
+
* `<marker>: off` line, written by a build with that gate's `--no-*-gate` flag; `GATE_SWITCHES`).
|
|
591
|
+
* Read back so `upgrade`, `rebuild-all`, `diff` and the console re-render the same switch.
|
|
592
|
+
* FAILS CLOSED: a missing line, a missing carrier, or any value but exactly `off` reads as
|
|
593
|
+
* armed, because the line is only ever written when the gate is off and a gate is the thing a
|
|
594
|
+
* misread must never take away.
|
|
595
595
|
*/
|
|
596
|
-
|
|
596
|
+
function gateOfDir(d, marker, host = null) {
|
|
597
|
+
const re = new RegExp(`^${marker}:[ \\t]*(.+?)[ \\t]*$`, 'm');
|
|
597
598
|
return firstCarrier(d, (carrierPath) => {
|
|
598
599
|
const text = readMaybe(carrierPath);
|
|
599
600
|
if (text === null) return undefined;
|
|
600
|
-
const m =
|
|
601
|
+
const m = re.exec(text);
|
|
601
602
|
if (!m) return undefined;
|
|
602
603
|
return m[1] !== 'off';
|
|
603
604
|
}, true, host);
|
|
604
605
|
}
|
|
605
606
|
|
|
607
|
+
/** Every switchable gate of a deployed install, keyed as `makeCfg` and `installProfile` key them. */
|
|
608
|
+
export function gatesOfDir(d, host = null) {
|
|
609
|
+
return Object.fromEntries(GATE_SWITCHES.map((g) => [g.key, gateOfDir(d, g.marker, host)]));
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/** Law IV's switch alone (#319's reader, kept for its callers). */
|
|
613
|
+
export const deletionGateOfDir = (d, host = null) => gateOfDir(d, 'Deletion gate', host);
|
|
614
|
+
|
|
606
615
|
// ---- what host a deployed dir belongs to (`_harness_mcp`) ---------------------------------
|
|
607
616
|
|
|
608
617
|
/** `_harness_mcp._claude_read_manifest`. */
|
package/js/hosts/settings.mjs
CHANGED
|
@@ -726,7 +726,7 @@ export function mergeOpencodeJson(p, agentPath, doctrines = null, excluded = [],
|
|
|
726
726
|
* remove. `default` here means unknown, and unknown keeps the gate (see `processPackOn`).
|
|
727
727
|
*/
|
|
728
728
|
export function claudeHookGroups(cfg, hookOpts, doctrines = null, excluded = [], host = 'claude',
|
|
729
|
-
deletionGate = true) {
|
|
729
|
+
deletionGate = true, { secretsGate = true, doneGate = true } = {}) {
|
|
730
730
|
const run = hookPrefix(hookOpts);
|
|
731
731
|
const mem = `--memory "${path.join(cfg, 'memory')}"`;
|
|
732
732
|
// --root carries the install's own dir so a GLOBAL hook can stand down when a live, wired
|
|
@@ -760,20 +760,25 @@ export function claudeHookGroups(cfg, hookOpts, doctrines = null, excluded = [],
|
|
|
760
760
|
// `--no-deletion-gate` only when the install switched Law IV's gate off, so an armed
|
|
761
761
|
// install's command stays byte-identical (and an older shim never sees the flag).
|
|
762
762
|
const dg = deletionGate === false ? ' --no-deletion-gate' : '';
|
|
763
|
+
// Law I's secret scan and Law III's done gate, under the same contract (user decision
|
|
764
|
+
// 2026-10-18): each flag only when that gate is off.
|
|
765
|
+
const sg = secretsGate === false ? ' --no-secrets-gate' : '';
|
|
766
|
+
const dn = doneGate === false ? ' --no-done-gate' : '';
|
|
763
767
|
return {
|
|
764
768
|
SessionStart: [{ hooks: [{ type: 'command', command: `${run} context --root "${cfg}"${b} || exit 0` }] }],
|
|
765
769
|
// One group, both gates: process 5's consent is a stderr line here (Bob has no ask
|
|
766
770
|
// tier), so the pack toggle that drops Claude's git-gate group has nothing to drop —
|
|
767
|
-
// `tool-gate` only ever EXITS 2 for Laws I and IV (
|
|
771
|
+
// `tool-gate` only ever EXITS 2 for Laws I and IV (unless built `--no-secrets-gate` /
|
|
772
|
+
// `--no-deletion-gate`), and for a
|
|
768
773
|
// write under a project's own `.geneseed/protected-checks.txt` — the project opted in —
|
|
769
774
|
// and for a recursive scan rooted at a whole filesystem (ops 2, the root-scan check).
|
|
770
|
-
PreToolUse: [{ hooks: [{ type: 'command', command: `${run} tool-gate --root "${cfg}"${b}${dg}` }] }],
|
|
775
|
+
PreToolUse: [{ hooks: [{ type: 'command', command: `${run} tool-gate --root "${cfg}"${b}${sg}${dg}` }] }],
|
|
771
776
|
// Bob's Stop payload never carries `transcript_path` (I2) — `learn` reads `--host bob`
|
|
772
777
|
// and returns immediately rather than wasting a model call on the bare envelope. KEPT
|
|
773
778
|
// rather than DROPPED: the stand-down costs nothing (no transcript read, no spawn), and
|
|
774
779
|
// if Bob ever starts sending one, learning on Bob starts working with no emit change —
|
|
775
780
|
// dropping the group would need a second one re-added later for the same reason.
|
|
776
|
-
Stop: [{ hooks: [{ type: 'command', command: `${run} learn ${mem}${b} || exit 0` }] }],
|
|
781
|
+
Stop: [{ hooks: [{ type: 'command', command: `${run} learn ${mem}${b}${dn} || exit 0` }] }],
|
|
777
782
|
};
|
|
778
783
|
}
|
|
779
784
|
// OpenClaude takes Claude's whole group set and verdicts unchanged. `context` needs the host
|
|
@@ -786,8 +791,11 @@ export function claudeHookGroups(cfg, hookOpts, doctrines = null, excluded = [],
|
|
|
786
791
|
const context = `${run} context --root "${cfg}"${h} || exit 0`;
|
|
787
792
|
const gate = `${run} git-gate --root "${cfg}"${h}${consentRuleOn(doctrines, excluded) ? '' : ' --no-consent'}`
|
|
788
793
|
+ (deletionGate === false ? ' --no-deletion-gate' : '');
|
|
789
|
-
|
|
790
|
-
|
|
794
|
+
// `--no-secrets-gate` skips only rule-gate's credential scan (rigor 5 and process 1 still
|
|
795
|
+
// run); `--no-done-gate` only learn's done check, never the distillation. One `learn` string
|
|
796
|
+
// feeds Stop, SubagentStop and PreCompact, and the flag sits before `|| exit 0`.
|
|
797
|
+
const ruleGate = `${run} rule-gate --root "${cfg}"${secretsGate === false ? ' --no-secrets-gate' : ''}`;
|
|
798
|
+
const learn = `${run} learn ${mem}${h}${doneGate === false ? ' --no-done-gate' : ''} || exit 0`;
|
|
791
799
|
// Claude Code only (hooks.md, v2.1.295+; Task 1): a `command` hook that can't start, times
|
|
792
800
|
// out, or exits anything but 0 or 2 — even one whose stdout happens to be valid JSON — now
|
|
793
801
|
// BLOCKS the tool call instead of sliding through as the non-blocking default. Only safe to
|
|
@@ -924,14 +932,15 @@ function readSettingsForMerge(p, consequence) {
|
|
|
924
932
|
* global that never stood down for a project install.
|
|
925
933
|
*/
|
|
926
934
|
export function mergeClaudeSettings(p, priorHooks = null, hookOpts = {},
|
|
927
|
-
doctrines = null, excluded = [], host = 'claude', cfgDir = path.dirname(p), deletionGate = true
|
|
935
|
+
doctrines = null, excluded = [], host = 'claude', cfgDir = path.dirname(p), deletionGate = true,
|
|
936
|
+
gates = {}) {
|
|
928
937
|
const prior = (priorHooks || []).filter(isDict);
|
|
929
938
|
const loaded = readSettingsForMerge(p, 'Hooks were not wired.');
|
|
930
939
|
if (!loaded) return [p, prior];
|
|
931
940
|
const [config, hadComments] = loaded;
|
|
932
941
|
let hooks = get(config, 'hooks');
|
|
933
942
|
if (!isDict(hooks)) hooks = {};
|
|
934
|
-
const canonical = claudeHookGroups(cfgDir, hookOpts, doctrines, excluded, host, deletionGate);
|
|
943
|
+
const canonical = claudeHookGroups(cfgDir, hookOpts, doctrines, excluded, host, deletionGate, gates);
|
|
935
944
|
const canonFlat = [];
|
|
936
945
|
for (const [event, groups] of Object.entries(canonical)) {
|
|
937
946
|
for (const g of groups) canonFlat.push({ event, group: g });
|
package/js/inspect/diff.mjs
CHANGED
|
@@ -44,8 +44,8 @@ import {
|
|
|
44
44
|
GLOBAL_MANIFEST, VERSION_MARKER, expanduser, opencodeConfigDir, resolvePath,
|
|
45
45
|
} from '../hosts/hosts.mjs';
|
|
46
46
|
import {
|
|
47
|
-
EMIT_HOST_SCOPE, defaultTheme,
|
|
48
|
-
excludedSkillsOfDir,
|
|
47
|
+
EMIT_HOST_SCOPE, defaultTheme, doctrinesForBuild, excludedRulesOfDir,
|
|
48
|
+
excludedSkillsOfDir, gatesOfDir,
|
|
49
49
|
footprintOfDir, modeOfDir, postureOfDir,
|
|
50
50
|
trustOfDir,
|
|
51
51
|
readJsonMaybe, readMaybe, themeOfDir,
|
|
@@ -184,8 +184,8 @@ export function diffCollect({ target = null, theme = null, emit = null, footprin
|
|
|
184
184
|
excludeRules: excludedRulesOfDir(dir),
|
|
185
185
|
// The excluded skills, or every skill the install left out reads as deleted.
|
|
186
186
|
excludeSkills: excludedSkillsOfDir(dir),
|
|
187
|
-
//
|
|
188
|
-
|
|
187
|
+
// The gate switches, or a disarmed install reads its `<gate>: off` line as drift.
|
|
188
|
+
...gatesOfDir(dir),
|
|
189
189
|
}));
|
|
190
190
|
// The one place a render depends on WHERE it is installed: a global Bob emit writes each
|
|
191
191
|
// folder skill's absolute directory into its SKILL.md (see `writeNativeLayer`), so the
|
package/js/inspect/status.mjs
CHANGED
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
59
59
|
import path from 'node:path';
|
|
60
60
|
|
|
61
|
-
import { THEMES, ROOT, makeCfg } from '../build/source.mjs';
|
|
61
|
+
import { GATE_SWITCHES, THEMES, ROOT, makeCfg } from '../build/source.mjs';
|
|
62
62
|
import { tuiInventory } from './inventory.mjs';
|
|
63
63
|
import { readVersion, sourceFingerprint } from '../build/version.mjs';
|
|
64
64
|
import {
|
|
@@ -422,8 +422,9 @@ export function statusLines(d, color = false) {
|
|
|
422
422
|
const excl = p.excludeRules?.length ? `excluding ${p.excludeRules.join(',')}` : 'no rules excluded';
|
|
423
423
|
rows.push([`${p.host}:${p.scope}`, [p.state, p.theme, p.footprint, `${p.posture}/${p.mode}/${p.trust}`,
|
|
424
424
|
packs, excl, ...(p.excludeSkills?.length ? [`skills off: ${p.excludeSkills.join(',')}`] : []),
|
|
425
|
-
//
|
|
426
|
-
...(p.
|
|
425
|
+
// Each elided when armed. The law's text still binds; only its tool-boundary gate is off.
|
|
426
|
+
...GATE_SWITCHES.filter((g) => p[g.key] === false)
|
|
427
|
+
.map((g) => `${g.marker.toLowerCase()}: off (Law ${g.law} text still binds)`)]
|
|
427
428
|
.join(` ${DOT} `) + where]);
|
|
428
429
|
}
|
|
429
430
|
|
package/js/inspect/validate.mjs
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { buildInto, emitGlobalInto, emitProjectInto } from '../build/driver.mjs';
|
|
11
|
+
import { GATE_SWITCHES } from '../build/source.mjs';
|
|
11
12
|
import { resolvePath } from '../hosts/hosts.mjs';
|
|
12
13
|
import {
|
|
13
|
-
|
|
14
|
+
doctrinesOfDir, excludedRulesOfDir, gatesOfDir, modeOfDir, postureOfDir,
|
|
14
15
|
} from '../hosts/installs.mjs';
|
|
15
16
|
import { validateIsVendored } from '../hosts/native.mjs';
|
|
16
17
|
import { printOut, printErr } from '../lib/fs.mjs';
|
|
@@ -33,7 +34,8 @@ export const VALIDATE_USAGE = [
|
|
|
33
34
|
'usage: geneseed validate [-h] [--theme THEME] [--emit EMIT] [--out OUT] [--root ROOT]',
|
|
34
35
|
' [--footprint {lean,full}] [--posture POSTURE] [--mode MODE]',
|
|
35
36
|
' [--trust TRUST] [--doctrines DOCTRINES] [--exclude-rules RULES]',
|
|
36
|
-
' [--exclude-skills SKILLS] [--no-
|
|
37
|
+
' [--exclude-skills SKILLS] [--no-secrets-gate] [--no-done-gate]',
|
|
38
|
+
' [--no-deletion-gate] [-v]',
|
|
37
39
|
'',
|
|
38
40
|
"Render and emit into a throwaway sandbox, run the doctor's checks, and write nothing real.",
|
|
39
41
|
"Takes the generator's render flags (see geneseed-build --help) except --sync-themes and",
|
|
@@ -129,6 +131,7 @@ export function cmdValidate(args) {
|
|
|
129
131
|
theme: args.theme, footprint: args.footprint, posture: args.posture, mode: args.mode,
|
|
130
132
|
trust: args.trust, doctrines: args.doctrines, excludeRules: args.excludeRules,
|
|
131
133
|
excludeSkills: args.excludeSkills, deletionGate: args.noDeletionGate ? false : null,
|
|
134
|
+
secretsGate: args.noSecretsGate ? false : null, doneGate: args.noDoneGate ? false : null,
|
|
132
135
|
};
|
|
133
136
|
let scanDirs;
|
|
134
137
|
try {
|
|
@@ -170,11 +173,13 @@ export function cmdValidate(args) {
|
|
|
170
173
|
const at = scanDirs[0];
|
|
171
174
|
const packs = doctrinesOfDir(at);
|
|
172
175
|
const excluded = excludedRulesOfDir(at);
|
|
176
|
+
const gates = gatesOfDir(at);
|
|
173
177
|
printOut(`[validate-only] rendered at posture=${postureOfDir(at) ?? '?'} `
|
|
174
178
|
+ `mode=${modeOfDir(at) ?? '?'} packs=${packs ? packs.join(',') || 'none' : '?'} `
|
|
175
179
|
+ `excluded=${excluded.map((id) => id.replace('.', ' ')).join(', ') || 'none'}`
|
|
176
|
-
//
|
|
177
|
-
+ `${
|
|
180
|
+
// Each elided when armed, so an armed dry run prints the line it always did.
|
|
181
|
+
+ `${GATE_SWITCHES.filter((g) => gates[g.key] === false)
|
|
182
|
+
.map((g) => ` ${g.marker.toLowerCase().replace(' ', '-')}=off`).join('')}\n`);
|
|
178
183
|
printOut(`[validate-only] would write ${written.length} file(s) under ${args.out}`
|
|
179
184
|
+ (args.root ? ` (root ${args.root})` : '')
|
|
180
185
|
+ ' — nothing was actually written (sandboxed).\n');
|
|
@@ -51,7 +51,7 @@ import { hookRunnerEntry } from '../hosts/shim.mjs';
|
|
|
51
51
|
import { confirm } from '../lib/prompt.mjs';
|
|
52
52
|
import {
|
|
53
53
|
claudeCfg, claudeReadManifest, doctrinesOfDir, EMIT_HOST_SCOPE, emitHostScopeOf,
|
|
54
|
-
|
|
54
|
+
excludedRulesOfDir, gatesOfDir, installKind, installState,
|
|
55
55
|
registeredTargets,
|
|
56
56
|
} from '../hosts/installs.mjs';
|
|
57
57
|
import {
|
|
@@ -1173,11 +1173,13 @@ function remergeClaudeHooks(cfg, root = cfg, host = 'claude') {
|
|
|
1173
1173
|
const excluded = excludedRulesOfDir(root, host).length ? excludedRulesOfDir(root, host)
|
|
1174
1174
|
: excludedRulesOfDir(cfg, host);
|
|
1175
1175
|
// `host` reaches the group builder: a Bob reactivate must re-wire Gemini-named groups.
|
|
1176
|
-
//
|
|
1177
|
-
// reactivate never disarms an install that did not ask for it.
|
|
1178
|
-
const
|
|
1176
|
+
// The gate switches, the same two-carrier read: a gate is off only when a carrier says so,
|
|
1177
|
+
// so a reactivate never disarms an install that did not ask for it.
|
|
1178
|
+
const [atRoot, atCfg] = [gatesOfDir(root, host), gatesOfDir(cfg, host)];
|
|
1179
|
+
const gates = Object.fromEntries(Object.keys(atRoot).map((k) => [k, atRoot[k] && atCfg[k]]));
|
|
1179
1180
|
const [, claims] = mergeClaudeSettings(settingsFile(cfg, managed),
|
|
1180
|
-
managed.settings_hooks ?? null, hookRunnerEntry(), doctrines, excluded, host, cfg,
|
|
1181
|
+
managed.settings_hooks ?? null, hookRunnerEntry(), doctrines, excluded, host, cfg,
|
|
1182
|
+
gates.deletionGate, gates);
|
|
1181
1183
|
// `and data` — a manifest that did not parse is not one to write back.
|
|
1182
1184
|
if (!deepEquals(claims, managed.settings_hooks ?? null) && Object.keys(data).length > 0) {
|
|
1183
1185
|
managed.settings_hooks = claims;
|
package/js/maintain/update.mjs
CHANGED
|
@@ -632,7 +632,7 @@ export async function installAxes(dir, { installProfile, setupBuildArgs }, notif
|
|
|
632
632
|
if (legacyProcessCarrierOfDir(String(dir), 'opencode')) return null;
|
|
633
633
|
const p = installProfile('opencode', 'global', String(dir), notify);
|
|
634
634
|
return setupBuildArgs('', 'files', null, null, p.footprint, p.posture, p.mode, p.doctrines,
|
|
635
|
-
undefined, p.excludeRules, p.trust, p.excludeSkills, p.deletionGate).slice(4);
|
|
635
|
+
undefined, p.excludeRules, p.trust, p.excludeSkills, p.deletionGate, p).slice(4);
|
|
636
636
|
}
|
|
637
637
|
|
|
638
638
|
/**
|
package/js/web/actions.mjs
CHANGED
|
@@ -46,8 +46,8 @@ import {
|
|
|
46
46
|
opencodeConfigDir, resolvePath,
|
|
47
47
|
} from '../hosts/hosts.mjs';
|
|
48
48
|
import {
|
|
49
|
-
EMIT_HOST_SCOPE,
|
|
50
|
-
footprintOfDir,
|
|
49
|
+
EMIT_HOST_SCOPE, doctrinesForBuild, excludedRulesOfDir, excludedSkillsOfDir,
|
|
50
|
+
footprintOfDir, gatesOfDir,
|
|
51
51
|
installState, installTargets, legacyProcessCarrierOfDir, modeOfDir, postureOfDir, trustOfDir,
|
|
52
52
|
} from '../hosts/installs.mjs';
|
|
53
53
|
import {
|
|
@@ -131,13 +131,17 @@ function bodyExcludeRules(body) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
|
-
*
|
|
135
|
-
* else — a string `"false"`, a number,
|
|
136
|
-
* own answer, so a malformed
|
|
134
|
+
* The gate switches across the trust boundary (`deletionGate`, `secretsGate`, `doneGate`), each
|
|
135
|
+
* on its own: only a real JSON boolean counts. Anything else — a string `"false"`, a number,
|
|
136
|
+
* absence — falls back to the install's own answer for THAT gate, so a malformed or partial body
|
|
137
|
+
* can never disarm (or re-arm) a gate it did not name.
|
|
137
138
|
*/
|
|
138
|
-
function
|
|
139
|
-
const
|
|
140
|
-
return
|
|
139
|
+
function bodyGates(body, root, host) {
|
|
140
|
+
const own = gatesOfDir(root, host);
|
|
141
|
+
return Object.fromEntries(Object.entries(own).map(([k, v]) => {
|
|
142
|
+
const said = bget(body, k);
|
|
143
|
+
return [k, typeof said === 'boolean' ? said : v];
|
|
144
|
+
}));
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
/**
|
|
@@ -501,8 +505,8 @@ export function apiRestore(state, files) {
|
|
|
501
505
|
// re-states a rule whose hook gate the install deliberately left unwired.
|
|
502
506
|
excludeRules: excludedRulesOfDir(target),
|
|
503
507
|
excludeSkills: excludedSkillsOfDir(target),
|
|
504
|
-
//
|
|
505
|
-
|
|
508
|
+
// The gate switches: a restored AGENT.md must keep the install's `<gate>: off` lines.
|
|
509
|
+
...gatesOfDir(target),
|
|
506
510
|
}));
|
|
507
511
|
for (const raw of (isTruthy(files) ? files : [])) {
|
|
508
512
|
const rel = stripWhitespace(formatValue(raw).replace(/\\/g, '/')).replace(/^\/+/, '');
|
|
@@ -585,12 +589,12 @@ export function apiInstallCmd(state, body) {
|
|
|
585
589
|
// the silence a pre-2.3 carrier gives on packs. Unspecified therefore keeps the install's
|
|
586
590
|
// own answer, and a pre-marker install answers the empty list — which is what it has.
|
|
587
591
|
const excludeRules = bodyExcludeRules(body) ?? excludedRulesOfDir(root, host);
|
|
588
|
-
//
|
|
589
|
-
// the install's own answer — so a pack Apply
|
|
590
|
-
const
|
|
592
|
+
// The gate switches (the Constitution page's toggles): a strict boolean per gate in the body,
|
|
593
|
+
// else the install's own answer — so a pack Apply keeps every switch as it is.
|
|
594
|
+
const gates = bodyGates(body, root, host);
|
|
591
595
|
const out = scope === 'global' ? null : String(root);
|
|
592
596
|
const argv = setupBuildArgs(theme || 'neutral', emit, out, out, fp, pos, mode, doctrines,
|
|
593
|
-
PACK_ORDER, excludeRules, trust, excludedSkillsOfDir(root, host), deletionGate);
|
|
597
|
+
PACK_ORDER, excludeRules, trust, excludedSkillsOfDir(root, host), gates.deletionGate, gates);
|
|
594
598
|
return { cmd: [process.execPath, path.join(ROOT, 'bin', 'build-driver.mjs'), ...argv] };
|
|
595
599
|
}
|
|
596
600
|
|
|
@@ -689,9 +693,9 @@ export function apiDeployCmd(state, body) {
|
|
|
689
693
|
// and `PreToolUse::Bash` went with them. `doctrinesForBuild` resolves unknown to ALL packs.
|
|
690
694
|
const doctrines = bodyDoctrines(body) ?? doctrinesForBuild(root, host);
|
|
691
695
|
const excludeRules = bodyExcludeRules(body) ?? excludedRulesOfDir(root, host);
|
|
692
|
-
const
|
|
696
|
+
const gates = bodyGates(body, root, host);
|
|
693
697
|
// project-scope emit name == host name (opencode / claude / bob / openclaude)
|
|
694
698
|
const argv = setupBuildArgs(theme || 'neutral', host, root, root, fp, pos, mode, doctrines,
|
|
695
|
-
PACK_ORDER, excludeRules, trust, excludedSkillsOfDir(root, host), deletionGate);
|
|
699
|
+
PACK_ORDER, excludeRules, trust, excludedSkillsOfDir(root, host), gates.deletionGate, gates);
|
|
696
700
|
return { cmd: [process.execPath, path.join(ROOT, 'bin', 'build-driver.mjs'), ...argv] };
|
|
697
701
|
}
|
package/js/web/api.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import { doctorCollect } from '../inspect/doctor.mjs';
|
|
|
20
20
|
import { excludesSnapshot } from '../inspect/excludes.mjs';
|
|
21
21
|
import { CLAUDE_STYLE, HOSTS, VERSION_MARKER, resolvePath } from '../hosts/hosts.mjs';
|
|
22
22
|
import {
|
|
23
|
-
|
|
23
|
+
footprintOfDir, gatesOfDir, installState, installTargets, modeOfDir, trustOfDir,
|
|
24
24
|
postureOfDir, readJsonMaybe, themeOfDir,
|
|
25
25
|
} from '../hosts/installs.mjs';
|
|
26
26
|
import { PRESETS } from '../loop/score.mjs';
|
|
@@ -247,9 +247,10 @@ export function apiOverview(state) {
|
|
|
247
247
|
for (const [host, scope, root] of installTargets()) {
|
|
248
248
|
try {
|
|
249
249
|
if (samePath(viewCfg(host, scope, root), state.target)) {
|
|
250
|
-
// `deletionGate`:
|
|
250
|
+
// `deletionGate`/`secretsGate`/`doneGate`: the gate switches, for the Constitution
|
|
251
|
+
// page's toggles on rows IV, I and III.
|
|
251
252
|
install = { host, scope, path: root, footprint: footprintOfDir(root),
|
|
252
|
-
|
|
253
|
+
...gatesOfDir(root, host) };
|
|
253
254
|
break;
|
|
254
255
|
}
|
|
255
256
|
} catch { /* an unreadable candidate just isn't a match */ }
|
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.
|
|
4
|
+
"version": "4.9.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",
|
package/src/AGENT.md.tmpl
CHANGED
|
@@ -144,7 +144,7 @@ Inactive packs still ship under `{{DIR_DOCTRINES}}/`, so a citation into one res
|
|
|
144
144
|
|
|
145
145
|
{{DOCTRINES_BODY}}
|
|
146
146
|
|
|
147
|
-
Active packs: {{DOCTRINES_LIST}}{{EXCLUDED_RULES_LINE}}{{
|
|
147
|
+
Active packs: {{DOCTRINES_LIST}}{{EXCLUDED_RULES_LINE}}{{GATE_LINES}}
|
|
148
148
|
|
|
149
149
|
---
|
|
150
150
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{s as e}from"./sections-
|
|
1
|
+
import{s as e}from"./sections-BET3c1WT.js";import{i as t,t as n}from"./react-BOF6yL40.js";import{t as r}from"./api-Bp5eW_6m.js";import{A as i,F as a,Y as o,b as s,v as c}from"./index-DJorAjeH.js";import{a as l,i as u,n as d,o as f,r as p,t as m}from"./activity-DvPxoS4Y.js";import{t as h}from"./usePoll-NSTzLOF4.js";var g=e(t(),1),_=n();function v({s:e}){let t=p[e.status]||p.idle,n=e.files,r=e.todos,o=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)(i,{name:`chevron`,className:`glyph act-chev`})]})]}),e.phase&&(0,_.jsxs)(`div`,{className:`row gap-8`,style:{marginTop:10,fontSize:14},children:[(0,_.jsx)(i,{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]})]})]}),o&&(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 `,a(e.updated_at),` ago`]})]})}function y(){let[e,t]=(0,g.useState)(null),[n,i]=(0,g.useState)(``);h(e=>r.activity().then(n=>{e()&&(t(n),i(``))},t=>{e()&&i(t.message)}),2e3,[]);let a=!e||e.enabled!==!1,l=e?.activity||[],u=o(),d=async()=>{let e=!a;try{let n=await r.activityToggle(e);t(e=>({...e||{},enabled:n.enabled,activity:n.enabled&&e?.activity||[]})),i(``)}catch(e){i(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:a?`tracking on`:`tracking off`}),(0,_.jsx)(`div`,{className:`sw-toggle${a?` on`:``}`,role:`switch`,"aria-checked":a,"aria-label":`Toggle activity tracking`,tabIndex:0,onClick:d,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.key===` `&&e.preventDefault(),d())}})]})]}),(0,_.jsx)(c,{error:n,style:{marginBottom:12}}),e?a?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)(s,{label:`Reading live sessions…`})]})}export{y as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{s as e}from"./sections-
|
|
1
|
+
import{s as e}from"./sections-BET3c1WT.js";import{i as t,t as n}from"./react-BOF6yL40.js";import{t as r}from"./api-Bp5eW_6m.js";import{A as i,F as a,b as o}from"./index-DJorAjeH.js";import{a as s,n as c,o as l,r as u,t as d}from"./activity-DvPxoS4Y.js";import{t as f}from"./usePoll-NSTzLOF4.js";var p=e(t(),1),m=n();function h(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 g({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,m.jsxs)(`div`,{className:`row gap-10`,style:{alignItems:`baseline`},children:[(0,m.jsx)(`span`,{className:`badge ${t?``:`acc`}`,style:{flexShrink:0,minWidth:52,justifyContent:`center`},children:t?`you`:`agent`}),(0,m.jsxs)(`div`,{style:{minWidth:0,flex:1,fontSize:13},children:[!t&&(0,m.jsx)(`span`,{className:`feed-dot ${h(e)||`acc`}`,style:{display:`inline-block`,marginRight:8,verticalAlign:`middle`}}),e.kind===`thinking`&&(0,m.jsx)(`span`,{className:`dim`,children:`thinking: `}),r?(0,m.jsx)(`span`,{className:`dim`,children:i}):t?i:(0,m.jsx)(`b`,{children:i}),e.error&&(0,m.jsxs)(`span`,{className:`dim`,children:[`: `,e.error]})]}),n.length>0&&(0,m.jsx)(`span`,{className:`dim mono`,style:{flexShrink:0,fontSize:12},children:n.join(` · `)})]})}function _({turns:e}){return!e||e.length===0?(0,m.jsx)(`div`,{className:`dim`,style:{fontSize:13},children:`No conversation captured yet.`}):(0,m.jsx)(`div`,{className:`stack gap-12`,children:e.map((e,t)=>{let n=e.role===`user`;return(0,m.jsxs)(`div`,{className:`row gap-10`,style:{alignItems:`baseline`},children:[(0,m.jsx)(`span`,{className:`badge ${n?``:`acc`}`,style:{flexShrink:0,minWidth:52,justifyContent:`center`},children:n?`you`:`agent`}),(0,m.jsx)(`div`,{style:{minWidth:0,fontSize:13,color:n?`inherit`:`var(--text-2)`},children:e.text})]},t)})})}function v({sid:e}){let[t,n]=(0,p.useState)(null),[h,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(!1),[x,S]=(0,p.useState)(!1);f(t=>r.activityDetail(e).then(e=>{t()&&(n(e),v(``),b(!1))},e=>{t()&&(e.status===404?b(!0):v(e.message))}),2e3,[e]);let C=(0,m.jsxs)(`a`,{className:`btn ghost sm`,href:`#/activity`,style:{marginBottom:12,display:`inline-flex`,gap:6},children:[(0,m.jsx)(i,{name:`arrow`,style:{transform:`rotate(180deg)`}}),` Activity`]});if(y)return(0,m.jsxs)(`div`,{className:`narrow`,children:[C,(0,m.jsxs)(`div`,{className:`empty`,children:[(0,m.jsx)(`div`,{className:`big`,children:`Session ended`}),`It's no longer live. `,(0,m.jsx)(`a`,{href:`#/activity`,children:`Back to Activity`}),`.`]})]});if(!t)return(0,m.jsxs)(`div`,{className:`narrow`,children:[C,(0,m.jsx)(o,{label:`Loading session…`})]});let w=t.session,T=u[w.status]||u.idle,E=w.files,D=w.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,m.jsxs)(`div`,{className:`narrow`,children:[C,h&&(0,m.jsx)(`p`,{className:`badge bad`,style:{marginBottom:12},children:h}),(0,m.jsxs)(`div`,{className:`card pad-md`,children:[(0,m.jsxs)(`div`,{className:`row between wrap gap-12`,children:[(0,m.jsxs)(`div`,{style:{minWidth:0},children:[(0,m.jsx)(`h1`,{className:`h`,style:{margin:0},children:w.title||s(w.cwd)||w.session_id}),w.cwd&&(0,m.jsx)(`div`,{className:`dim mono`,style:{fontSize:12,...d},title:w.cwd,children:w.cwd})]}),(0,m.jsxs)(`div`,{className:`row gap-8`,style:{flexShrink:0},children:[w.model&&(0,m.jsx)(`span`,{className:`badge mono`,children:w.model}),w.agent&&(0,m.jsx)(`span`,{className:`badge`,children:w.agent}),(0,m.jsxs)(`span`,{className:`badge ${T.cls}`,children:[(0,m.jsx)(`span`,{className:`dot`}),T.label]})]})]}),w.phase&&(0,m.jsxs)(`div`,{className:`row gap-8`,style:{marginTop:10,fontSize:14},children:[(0,m.jsx)(i,{name:`activity`}),(0,m.jsx)(`span`,{style:d,children:w.phase})]}),(0,m.jsxs)(`div`,{className:`row wrap`,style:{gap:16,marginTop:12,fontSize:13,color:`var(--text-2)`},children:[w.tokens>0&&(0,m.jsxs)(`span`,{children:[l(w.tokens),` tok`]}),w.cost>0&&(0,m.jsxs)(`span`,{children:[`$`,w.cost.toFixed(2)]}),w.turn_started_at?(0,m.jsx)(`span`,{children:(0,m.jsx)(c,{startedAt:w.turn_started_at})}):null,(0,m.jsxs)(`span`,{className:`dim`,children:[`updated `,a(w.updated_at),` ago`]})]}),(w.error||w.blocked_on)&&(0,m.jsx)(`div`,{style:{marginTop:10},children:(0,m.jsx)(`span`,{className:`badge bad`,style:{maxWidth:`100%`,...d},children:w.error||w.blocked_on})})]}),(O||k)&&(0,m.jsxs)(`div`,{className:`grid gap-12`,style:{marginTop:12,gridTemplateColumns:O&&k?`minmax(0, 1fr) minmax(0, 1fr)`:`1fr`},children:[O&&(0,m.jsxs)(`div`,{className:`card pad-md`,children:[(0,m.jsx)(`div`,{className:`card-head`,children:(0,m.jsxs)(`h3`,{children:[`Files touched `,(0,m.jsxs)(`span`,{className:`dim`,children:[`(`,E.count,`)`]})]})}),(0,m.jsx)(`div`,{className:`stack`,style:{gap:6,marginTop:8},children:E.items.map(e=>(0,m.jsxs)(`div`,{className:`row between gap-12`,style:{fontSize:13},children:[(0,m.jsx)(`span`,{className:`mono`,style:{...d,minWidth:0,flex:1},title:e.file,children:e.file}),(0,m.jsxs)(`span`,{style:{flexShrink:0},children:[(0,m.jsxs)(`span`,{style:{color:`var(--good)`},children:[`+`,e.additions]}),` `,(0,m.jsxs)(`span`,{style:{color:`var(--bad)`},children:[`−`,e.deletions]})]})]},e.file))})]}),k&&(0,m.jsxs)(`div`,{className:`card pad-md`,children:[(0,m.jsx)(`div`,{className:`card-head`,children:(0,m.jsxs)(`h3`,{children:[`Plan`,` `,(0,m.jsxs)(`span`,{className:`dim`,children:[`(`,D.done,`/`,D.total,`)`]})]})}),(0,m.jsx)(`div`,{className:`stack`,style:{gap:6,marginTop:8},children:D.items.map((e,t)=>(0,m.jsxs)(`div`,{className:`row gap-8`,style:{fontSize:13},children:[(0,m.jsx)(`span`,{className:`feed-dot ${e.status===`completed`?`ok`:e.status===`in_progress`?`acc`:``}`}),(0,m.jsx)(`span`,{style:{textDecoration:e.status===`completed`?`line-through`:`none`,color:e.status===`completed`?`var(--text-3)`:`inherit`},children:e.content})]},t))})]})]}),(0,m.jsxs)(`div`,{className:`card pad-md`,style:{marginTop:12},children:[(0,m.jsxs)(`div`,{className:`card-head`,style:{justifyContent:`space-between`,marginBottom:12},children:[(0,m.jsx)(`h3`,{children:`Timeline`}),j.length>0&&(0,m.jsx)(`button`,{className:`btn ghost sm`,onClick:()=>S(e=>!e),children:x?`Show conversation`:`Show all ${j.length} steps`})]}),x?(0,m.jsx)(`div`,{className:`stack gap-12`,children:M.map((e,t)=>(0,m.jsx)(g,{rec:e},t))}):(0,m.jsx)(_,{turns:A})]})]})}export{v as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GreenhouseView-BSzVX_l7.js","assets/sections-BET3c1WT.js","assets/react-BOF6yL40.js","assets/drawable-DlrXDOJ7.js","assets/index-DJorAjeH.js","assets/api-Bp5eW_6m.js","assets/index-BCJz4_8C.css","assets/jobBuckets-Dbq8ZlWW.js","assets/OperatorHudView-D-nzB6_r.js","assets/JournalView-BbbACsYK.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{n as e,o as t,r as n,s as r}from"./sections-BET3c1WT.js";import{i,t as a}from"./react-BOF6yL40.js";import{t as o}from"./api-Bp5eW_6m.js";import{A as s,F as c,G as l,J as u,L as d,M as f,N as p,P as m,R as h,S as g,W as _,_ as v,b as y,t as b,v as x}from"./index-DJorAjeH.js";var S=r(i(),1),C={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.`},w=e=>e.deployed?C[e.theme]||`Loaded & ready`:`Not deployed`,T=a();function E({value:e,size:t=232}){let n=u(e,1100)??0,r=t/2-14,i=2*Math.PI*r,a=i*(1-n);return(0,T.jsxs)(`div`,{className:`ring-wrap`,style:{width:t,height:t},children:[(0,T.jsxs)(`svg`,{viewBox:`0 0 ${t} ${t}`,children:[(0,T.jsx)(`circle`,{cx:t/2,cy:t/2,r,fill:`none`,stroke:`var(--surface-3)`,strokeWidth:`10`}),(0,T.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,T.jsx)(`line`,{x1:c,y1:l,x2:u,y2:d,stroke:`var(--line-2)`,strokeWidth:`1`,opacity:i/48<n?.9:.25},i)})]}),(0,T.jsxs)(`div`,{className:`ring-center`,children:[(0,T.jsxs)(`div`,{className:`pct`,children:[Math.round(n*100),(0,T.jsx)(`span`,{style:{fontSize:20,color:`var(--text-3)`},children:`%`})]}),(0,T.jsx)(`div`,{className:`lbl`,children:`germination`})]})]})}function D({overview:e}){let t=f(e.diff),n=e.counts||{};return(0,T.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,T.jsxs)(`a`,{className:`kseg`,href:e.hash,title:`Open ${e.label}`,children:[(0,T.jsx)(`span`,{className:`kseg-n`+(t===0?` zero`:``),children:t==null?`—`:(0,T.jsx)(l,{value:t})}),(0,T.jsx)(`span`,{className:`kseg-l`,children:e.label})]},e.key)}),(0,T.jsx)(`div`,{className:`kseg-spacer`}),(0,T.jsxs)(`button`,{className:`kseg`+(t>0?` hot`:``),onClick:()=>_(`#/diff`),title:`Open changes`,children:[(0,T.jsx)(`span`,{className:`kseg-n`+(t===0?` zero`:``),children:(0,T.jsx)(l,{value:t})}),(0,T.jsx)(`span`,{className:`kseg-l`,children:`Local edits`}),t>0&&(0,T.jsx)(`span`,{className:`delta up`,children:`▲`})]})]})}function O({overview:t}){return(0,T.jsx)(`div`,{className:`genome`,children:n.map((n,r)=>{let i=e[n],a=t.counts?.[n];return(0,T.jsxs)(`div`,{className:`card gcell rise`,style:{"--i":r},onClick:()=>_(`#/section/`+n),children:[(0,T.jsxs)(`div`,{className:`gtop`,children:[(0,T.jsx)(`span`,{className:`gname`,children:i.label}),(0,T.jsx)(s,{name:i.icon,className:`gicon`})]}),(0,T.jsx)(`div`,{className:`gcount`+(a===0?` zero`:``),children:a==null?`—`:(0,T.jsx)(l,{value:a})}),(0,T.jsx)(`div`,{className:`gdesc`,children:i.desc})]},n)})})}function k({jobs:e}){if(!e||e.length===0)return(0,T.jsx)(`div`,{className:`feed`,children:(0,T.jsxs)(`div`,{className:`empty`,children:[(0,T.jsx)(`div`,{className:`big`,children:`No activity yet`}),`Actions you run appear here.`]})});let t={done:`ok`,running:`acc`,failed:`bad`},n=[...e].sort((e,t)=>t.started-e.started).slice(0,8);return(0,T.jsx)(`div`,{className:`feed`,children:n.map(e=>(0,T.jsxs)(`div`,{className:`feed-row`,children:[(0,T.jsx)(`span`,{className:`feed-dot ${t[e.status]||`ok`}`}),(0,T.jsx)(`span`,{className:`feed-txt`,children:(0,T.jsx)(`b`,{children:e.action})}),(0,T.jsxs)(`span`,{className:`feed-when`,children:[c(e.started),` ago`]})]},e.id))})}function A({overview:e,sigil:t,setup:r,jobs:i,onAction:a}){let o=w(e),c=m(e,r);return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`div`,{className:`card pad-lg rise mb-16`,children:(0,T.jsxs)(`div`,{className:`hero`,children:[(0,T.jsx)(E,{value:c}),(0,T.jsxs)(`div`,{className:`hero-facts`,children:[(0,T.jsx)(`div`,{className:`ttl`,children:o}),t&&(0,T.jsxs)(`div`,{className:`voice-readout`,children:[(0,T.jsx)(`span`,{className:`vr-cur`,children:`▕`}),(0,T.jsx)(`span`,{className:`vr-txt`,children:t})]},e.theme),(0,T.jsxs)(`p`,{className:`sub`,children:[`One source rendered into `,(0,T.jsx)(`code`,{children:e.target}),`. Every repo on this machine inherits it.`]}),(0,T.jsxs)(`div`,{className:`hero-chips`,children:[(0,T.jsxs)(`span`,{className:`chip`,children:[(0,T.jsx)(`span`,{className:`ck`,children:`voice`}),(0,T.jsx)(`span`,{className:`cv`,style:{textTransform:`capitalize`},children:e.theme})]}),(0,T.jsxs)(`span`,{className:`chip`,children:[(0,T.jsx)(`span`,{className:`ck`,children:`mode`}),(0,T.jsx)(`span`,{className:`cv`,children:e.emit})]}),(0,T.jsxs)(`span`,{className:`chip`,children:[(0,T.jsx)(`span`,{className:`ck`,children:`footprint`}),(0,T.jsx)(`span`,{className:`cv`,children:e.footprint})]}),(0,T.jsxs)(`span`,{className:`chip`,children:[(0,T.jsx)(`span`,{className:`ck`,children:`built`}),(0,T.jsx)(`span`,{className:`cv`,children:e.build_time||`unknown`})]}),(0,T.jsxs)(`span`,{className:`chip`,children:[(0,T.jsx)(`span`,{className:`ck`,children:`fp`}),(0,T.jsx)(`span`,{className:`cv`,children:r?.installed_fp||`—`})]})]}),(0,T.jsxs)(`div`,{className:`row wrap gap-10`,children:[(0,T.jsxs)(`button`,{className:`btn`,onClick:()=>a(`update`),children:[(0,T.jsx)(s,{name:`refresh`}),`Update`]}),(0,T.jsxs)(`button`,{className:`btn ghost`,onClick:()=>a(`build-all`),children:[(0,T.jsx)(s,{name:`build`}),`Rebuild`]}),(0,T.jsxs)(`button`,{className:`btn ghost`,onClick:()=>a(`doctor`),children:[(0,T.jsx)(s,{name:`doctor`}),`Run doctor`]})]})]})]})}),(0,T.jsx)(D,{overview:e}),(0,T.jsxs)(`div`,{className:`grid split-status`,children:[(0,T.jsxs)(`div`,{className:`card pad-lg`,children:[(0,T.jsxs)(`div`,{className:`card-head`,children:[(0,T.jsx)(`h3`,{children:`Capability genome`}),(0,T.jsx)(`div`,{className:`right`,children:(0,T.jsxs)(`span`,{className:`tick`,children:[n.length,` sections`]})})]}),(0,T.jsx)(O,{overview:e})]}),(0,T.jsxs)(`div`,{className:`card pad-lg`,children:[(0,T.jsxs)(`div`,{className:`card-head`,children:[(0,T.jsx)(`h3`,{children:`Recent activity`}),(0,T.jsx)(`div`,{className:`right`,children:(0,T.jsxs)(`span`,{className:`badge acc`,children:[(0,T.jsx)(`span`,{className:`dot`}),`live`]})})]}),(0,T.jsx)(k,{jobs:i})]})]})]})}function j({k:t,overview:n,max:r}){let i=e[t],a=n.counts?.[t]??0;return(0,T.jsxs)(`div`,{className:`strand`,children:[(0,T.jsxs)(`span`,{className:`strand-name`,children:[(0,T.jsx)(`span`,{className:`strand-dot`}),(0,T.jsx)(`a`,{href:`#/section/`+t,className:`strand-link stretch-link`,children:i.label})]}),(0,T.jsx)(`div`,{className:`hbar`,children:(0,T.jsx)(`i`,{style:{width:`${a/r*100}%`}})}),(0,T.jsx)(`span`,{className:`strand-val`,children:a})]})}function M({overview:e,sigil:t,setup:r,jobs:i}){let a=p(e.counts),o=r?.version_verdict||``,s=o.includes(`up to date`),c=f(e.diff),l=[[`Source`,`src/, the canonical genetic material`,r?.source_fp||`—`,!0],[`Render`,`geneseed build → ${e.emit}`,e.theme+` voice`,!0],[`Deployed`,e.target,`inherited by every repo`,!1]];return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`div`,{className:`mb-16`,children:(0,T.jsxs)(`div`,{className:`card pad-lg rise`,style:{position:`relative`,overflow:`hidden`},children:[(0,T.jsx)(`h2`,{className:`h`,style:{fontSize:22,margin:`0 0 18px`},children:`Gene-seed lineage`}),(0,T.jsxs)(`div`,{className:`lineage-track`,children:[(0,T.jsx)(`div`,{className:`spine`}),l.map(([e,t,n,r],i)=>(0,T.jsxs)(`div`,{className:`lineage-step`,children:[(0,T.jsx)(`span`,{className:`node ${r?`on`:``}`}),(0,T.jsx)(`div`,{className:`lt`,children:e}),(0,T.jsx)(`div`,{className:`ld`,children:t}),(0,T.jsx)(`div`,{className:`ltag`,children:n})]},i))]}),(0,T.jsx)(`hr`,{className:`hr`}),t&&(0,T.jsxs)(`div`,{className:`voice-readout`,style:{marginBottom:14},children:[(0,T.jsx)(`span`,{className:`vr-cur`,children:`▕`}),(0,T.jsx)(`span`,{className:`vr-txt`,children:t})]},e.theme),(0,T.jsxs)(`div`,{className:`row wrap gap-10`,children:[(0,T.jsxs)(`span`,{className:`badge ${s?`ok`:`warn`}`,children:[(0,T.jsx)(`span`,{className:`dot`}),`in sync · `,o]}),(0,T.jsxs)(`span`,{className:`badge`,children:[(0,T.jsx)(`span`,{className:`dot`}),c,` local edits`]})]})]})}),(0,T.jsxs)(`div`,{className:`grid split-even`,children:[(0,T.jsxs)(`div`,{className:`card pad-lg`,children:[(0,T.jsxs)(`div`,{className:`card-head`,children:[(0,T.jsx)(`h3`,{children:`Genome strand`}),(0,T.jsx)(`div`,{className:`right`,children:(0,T.jsx)(`span`,{className:`tick`,children:`by volume`})})]}),n.map(t=>(0,T.jsx)(j,{k:t,overview:e,max:a},t))]}),(0,T.jsxs)(`div`,{className:`card pad-lg`,children:[(0,T.jsx)(`div`,{className:`card-head`,children:(0,T.jsx)(`h3`,{children:`Recent activity`})}),(0,T.jsx)(k,{jobs:i})]})]})]})}function N({overview:t,setup:r,jobs:i}){let a=n.reduce((e,n)=>e+(t.counts?.[n]??0),0),o=p(t.counts),s=t.doctor?.ok,c=t.doctor?.problems?.length??0,l=f(t.diff);return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`div`,{className:`card pad-md rise mb-16`,children:(0,T.jsx)(`div`,{className:`row wrap between gap-16`,children:(0,T.jsxs)(`div`,{className:`row`,style:{gap:20,flexWrap:`wrap`},children:[(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`div`,{className:`tick`,children:`status`}),(0,T.jsx)(`div`,{className:`row`,style:{gap:8,marginTop:4},children:(0,T.jsxs)(`span`,{className:`badge ${t.deployed?`ok`:`warn`}`,children:[(0,T.jsx)(`span`,{className:`dot`}),t.deployed?`deployed`:`not deployed`]})})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`div`,{className:`tick`,children:`voice`}),(0,T.jsx)(`div`,{className:`metric`,style:{fontSize:18,marginTop:6,textTransform:`capitalize`},children:t.theme})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`div`,{className:`tick`,children:`mode`}),(0,T.jsx)(`div`,{className:`mono`,style:{fontSize:14,marginTop:6},children:t.emit})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`div`,{className:`tick`,children:`fingerprint`}),(0,T.jsx)(`div`,{className:`mono`,style:{fontSize:14,marginTop:6,color:`var(--accent)`},children:r?.installed_fp||`—`})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`div`,{className:`tick`,children:`doctor`}),(0,T.jsx)(`div`,{className:`row`,style:{gap:8,marginTop:4},children:s?(0,T.jsxs)(`span`,{className:`badge ok`,children:[(0,T.jsx)(`span`,{className:`dot`}),`clean`]}):(0,T.jsxs)(`span`,{className:`badge warn`,children:[(0,T.jsx)(`span`,{className:`dot`}),c,` issue`,c===1?``:`s`]})})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`div`,{className:`tick`,children:`edits`}),(0,T.jsx)(`div`,{className:`metric`,style:{fontSize:18,marginTop:6},children:l})]})]})})}),(0,T.jsxs)(`div`,{className:`grid split-operator`,children:[(0,T.jsxs)(`div`,{className:`card rise`,style:{"--i":1},children:[(0,T.jsxs)(`div`,{className:`card-head pad-lg`,style:{padding:`18px 20px 0`,marginBottom:14},children:[(0,T.jsx)(`h3`,{children:`Sections`}),(0,T.jsx)(`div`,{className:`right`,children:(0,T.jsxs)(`span`,{className:`tick`,children:[a,` entries total`]})})]}),(0,T.jsxs)(`table`,{className:`tbl`,children:[(0,T.jsx)(`thead`,{children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`th`,{children:`Section`}),(0,T.jsx)(`th`,{children:`Detail`}),(0,T.jsx)(`th`,{style:{width:130},children:`Share`}),(0,T.jsx)(`th`,{className:`num`,children:`Count`})]})}),(0,T.jsx)(`tbody`,{children:n.map(n=>{let r=e[n],i=t.counts?.[n]??0;return(0,T.jsxs)(`tr`,{className:`clickable`,children:[(0,T.jsx)(`td`,{className:`name`,children:(0,T.jsx)(`a`,{href:`#/section/`+n,className:`stretch-link`,children:r.label})}),(0,T.jsx)(`td`,{className:`muted`,children:r.desc}),(0,T.jsx)(`td`,{children:(0,T.jsx)(`div`,{className:`hbar`,children:(0,T.jsx)(`i`,{style:{width:`${i/o*100}%`}})})}),(0,T.jsx)(`td`,{className:`num`,children:i})]},n)})})]})]}),(0,T.jsxs)(`div`,{className:`card pad-lg rise`,style:{"--i":2},children:[(0,T.jsx)(`div`,{className:`card-head`,children:(0,T.jsx)(`h3`,{children:`Run log`})}),(0,T.jsx)(k,{jobs:i})]})]})]})}function P(){let[e,t]=(0,S.useState)(!1),[n,r]=(0,S.useState)(null);return(0,T.jsxs)(`div`,{className:`stale-banner`,role:`alert`,children:[(0,T.jsx)(`span`,{children:n||`This console is running code from before your last upgrade.`}),(0,T.jsx)(`button`,{className:`btn sm`,onClick:async()=>{t(!0),r(null);try{await h()}catch(e){r(e.message),t(!1)}},disabled:e,children:e?`Restarting…`:`Restart`})]})}var F=t({default:()=>z}),I=(0,S.lazy)(()=>b(()=>import(`./GreenhouseView-BSzVX_l7.js`),__vite__mapDeps([0,1,2,3,4,5,6,7]))),L=(0,S.lazy)(()=>b(()=>import(`./OperatorHudView-D-nzB6_r.js`),__vite__mapDeps([8,1,2,4,5,6,7]))),R=(0,S.lazy)(()=>b(()=>import(`./JournalView-BbbACsYK.js`),__vite__mapDeps([9,1,2,5,3,4,6])));function z({overview:e,overviewError:t,onRetry:n,themes:r,setup:i,runs:a,onAction:s,layout:c=`cultivar`,dataRev:l}){let u=c,[f,p]=(0,S.useState)(`status`),m=e&&r.find(t=>t.name===e.theme)?.sigil||``,{data:h}=d(()=>u===`greenhouse`||u===`operator`?o.doctor().catch(()=>null):Promise.resolve(null),[u,l]),{data:_}=d(()=>u===`journal`?o.recent().catch(()=>null):Promise.resolve(null),[u,l]);if(!e)return t?(0,T.jsxs)(`div`,{children:[(0,T.jsx)(x,{error:`Could not load the harness overview: ${t}`}),(0,T.jsx)(`button`,{className:`btn`,onClick:n,children:`Retry`})]}):(0,T.jsx)(y,{});let b=e.daemon_stale?(0,T.jsx)(P,{}):null;return e.deployed?f===`status`&&u===`journal`?(0,T.jsxs)(S.Suspense,{fallback:(0,T.jsx)(y,{}),children:[b,(0,T.jsx)(R,{overview:e,recent:_,onAction:s,onDirection:p,dataRev:l})]}):(0,T.jsxs)(T.Fragment,{children:[b,(0,T.jsx)(`div`,{className:`head-row`,children:(0,T.jsx)(g,{"aria-label":`Dashboard view`,children:[[`status`,`Status`],[`lineage`,`Lineage`],[`operator`,`Operator`]].map(([e,t])=>(0,T.jsx)(`button`,{className:f===e?`on`:``,onClick:()=>p(e),"aria-pressed":f===e,children:t},e))})}),(0,T.jsxs)(`div`,{className:`view-in`,children:[f===`status`&&u===`cultivar`&&(0,T.jsx)(A,{overview:e,sigil:m,setup:i,jobs:a,onAction:s}),f===`status`&&u===`greenhouse`&&(0,T.jsx)(S.Suspense,{fallback:(0,T.jsx)(y,{}),children:(0,T.jsx)(I,{overview:e,sigil:m,jobs:a,doctor:h,onAction:s})}),f===`status`&&u===`operator`&&(0,T.jsx)(S.Suspense,{fallback:(0,T.jsx)(y,{}),children:(0,T.jsx)(L,{overview:e,jobs:a,doctor:h,onAction:s})}),f===`lineage`&&(0,T.jsx)(M,{overview:e,sigil:m,setup:i,jobs:a}),f===`operator`&&(0,T.jsx)(N,{overview:e,setup:i,jobs:a})]},f)]}):(0,T.jsxs)(T.Fragment,{children:[b,(0,T.jsx)(v,{onAction:s})]})}export{z as default,w as n,F as t};
|