geneseed 3.1.2 → 3.2.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 +125 -0
- package/README.md +2 -2
- package/SHIPPED.md +3 -3
- package/bin/build-driver.mjs +127 -79
- package/bin/geneseed-cli.mjs +42 -84
- package/bin/geneseed-hook.mjs +5 -2
- package/docs/web/exclusions.md +1 -1
- package/docs/web/footprint.md +1 -1
- package/docs/web/foreman-mode.md +2 -2
- package/docs/web/themes-author.md +1 -1
- package/docs/web-ui.md +41 -29
- package/harness.config.json +1 -1
- package/js/README.md +1 -10
- package/js/build/emit-claude.mjs +4 -5
- package/js/build/emit-common.mjs +63 -114
- package/js/build/emit-opencode.mjs +74 -66
- package/js/build/generate.mjs +4 -6
- package/js/build/render.mjs +13 -13
- package/js/build/source.mjs +7 -6
- package/js/build/stubs.mjs +25 -33
- package/js/build/themes.mjs +1 -1
- package/js/build/version.mjs +1 -3
- package/js/hosts/hooks.mjs +3 -3
- package/js/hosts/hosts.mjs +2 -4
- package/js/hosts/installs.mjs +35 -28
- package/js/hosts/link.mjs +1 -1
- package/js/hosts/native.mjs +37 -19
- package/js/hosts/opencode.mjs +39 -28
- package/js/hosts/settings.mjs +33 -110
- package/js/inspect/checks-authoring.mjs +5 -4
- package/js/inspect/checks-build.mjs +1 -1
- package/js/inspect/diff.mjs +1 -3
- package/js/inspect/doctor.mjs +59 -44
- package/js/inspect/excludes.mjs +4 -10
- package/js/inspect/inventory.mjs +37 -55
- package/js/inspect/registry.mjs +4 -7
- package/js/inspect/scan.mjs +8 -15
- package/js/inspect/status.mjs +1 -1
- package/js/lib/fs.mjs +34 -0
- package/js/lib/json.mjs +28 -1
- package/js/lib/paths.mjs +0 -10
- package/js/lib/udiff.mjs +11 -16
- package/js/maintain/memory.mjs +2 -4
- package/js/maintain/migrate.mjs +3 -3
- package/js/maintain/uninstall.mjs +90 -78
- package/js/maintain/update.mjs +2 -2
- package/js/ui/anim.mjs +1 -1
- package/js/ui/menu.mjs +1 -1
- package/js/ui/tui.mjs +3 -20
- package/js/web/actions.mjs +230 -217
- package/js/web/activity.mjs +71 -89
- package/js/web/api.mjs +210 -220
- package/js/web/daemon.mjs +92 -110
- package/js/web/docs.mjs +66 -111
- package/js/web/graph.mjs +0 -0
- package/js/web/handler.mjs +78 -97
- package/js/web/jobs.mjs +124 -165
- package/js/web/routes.mjs +79 -136
- package/js/web/server.mjs +47 -82
- package/package.json +1 -1
- package/src/agents/explorer.md +2 -1
- package/src/doctrines/process.md +4 -2
- package/src/laws/universal.md +55 -43
- package/src/skills/clarify.md +1 -1
- package/src/skills/forge-mcp.md +2 -1
- package/src/skills/fresh-eyes.md +1 -1
- package/src/skills/ingest.md +2 -1
- package/src/skills/parallel-agents.md +1 -1
- package/src/skills/ponytail.md +2 -2
- package/src/skills/research.md +4 -2
- package/themes/_TEMPLATE.json +2 -0
- package/themes/biker.json +2 -0
- package/themes/commentator.json +2 -0
- package/themes/cyberpunk.json +2 -0
- package/themes/gamer.json +2 -0
- package/themes/imperial.json +2 -0
- package/themes/joker.json +2 -0
- package/themes/marvin.json +2 -0
- package/themes/mean.json +2 -0
- package/themes/military.json +2 -0
- package/themes/neutral.json +2 -0
- package/themes/pirate.json +2 -0
- package/themes/sports.json +2 -0
- package/themes/verstappen.json +2 -0
- package/themes/wizard.json +2 -0
- package/web/dist/assets/{Activity-z0uXdS7J.js → Activity-BTCG2gMl.js} +1 -1
- package/web/dist/assets/{ActivityDetail-CEj5IJpF.js → ActivityDetail-julsmPDB.js} +1 -1
- package/web/dist/assets/CatalogRow-DqS4e5XM.js +1 -0
- package/web/dist/assets/Diff-CIrGbiqm.js +5 -0
- package/web/dist/assets/Doctor-CpI53oHY.js +1 -0
- package/web/dist/assets/{Graph-BV6a6t2l.js → Graph-CS4tA7YS.js} +1 -1
- package/web/dist/assets/Harness-vRYs11kX.js +1 -0
- package/web/dist/assets/Laws-BjbHJrJt.js +3 -0
- package/web/dist/assets/Library-CjC7BAWN.js +1 -0
- package/web/dist/assets/{marked.esm-JKvyS0Pp.js → Markdown-kgpg9EQM.js} +15 -15
- package/web/dist/assets/Profile-CHr-PPf6.js +1 -0
- package/web/dist/assets/{Rules-DobVPd80.js → Rules-CsC6hfqk.js} +1 -1
- package/web/dist/assets/Skills-BvatJGfe.js +1 -0
- package/web/dist/assets/{StatusBadge-BhJ3HhdI.js → StatusBadge-gRrak0nO.js} +1 -1
- package/web/dist/assets/{activity-D9mfv7pY.js → activity-B0-FXZCj.js} +1 -1
- package/web/dist/assets/index-BnRWQbZb.js +12 -0
- package/web/dist/assets/index-Bx3I7cRW.js +2 -0
- package/web/dist/assets/index-D0f9tJlA.css +1 -0
- package/web/dist/assets/index-DJOhOwwR.js +1 -0
- package/web/dist/index.html +2 -2
- package/web/src/pages/Laws.jsx +46 -89
- package/web/dist/assets/About-CPvIFZGh.js +0 -1
- package/web/dist/assets/Diff-BMR8fPuG.js +0 -5
- package/web/dist/assets/Doctor-Bz5qE4r9.js +0 -1
- package/web/dist/assets/Harnesses-C5Ag5PaQ.js +0 -1
- package/web/dist/assets/Laws-BK07NKw9.js +0 -3
- package/web/dist/assets/Library-CiXN9sC3.js +0 -1
- package/web/dist/assets/Markdown-DG6FjUz-.js +0 -1
- package/web/dist/assets/Profile-B2oSvdxH.js +0 -1
- package/web/dist/assets/Skills-DQPsvsn9.js +0 -1
- package/web/dist/assets/Themes-BP38FBU9.js +0 -2
- package/web/dist/assets/index-BE226Gv6.css +0 -1
- package/web/dist/assets/index-BZ7cPLMI.js +0 -1
- package/web/dist/assets/index-BgIs5eIa.js +0 -12
- package/web/dist/assets/index-DGM5j2hB.js +0 -2
package/bin/geneseed-cli.mjs
CHANGED
|
@@ -56,6 +56,7 @@ import { cmdExclude } from '../js/inspect/excludes.mjs';
|
|
|
56
56
|
import { cmdBuild, cmdPrompt, cmdRebuildAll, cmdTheme } from '../js/build/generate.mjs';
|
|
57
57
|
import { cmdMigrate } from '../js/maintain/migrate.mjs';
|
|
58
58
|
import { parseIntStrict } from '../js/lib/text.mjs';
|
|
59
|
+
import { printErr } from '../js/lib/fs.mjs';
|
|
59
60
|
import { cmdLink, cmdUnlink } from '../js/hosts/link.mjs';
|
|
60
61
|
import { cmdMcp } from '../js/hosts/mcp.mjs';
|
|
61
62
|
import { cmdMemory } from '../js/maintain/memory.mjs';
|
|
@@ -83,56 +84,31 @@ import { cmdWeb } from '../js/web/server.mjs';
|
|
|
83
84
|
* `tests/test_hook_cli_parity.py` scrapes `const VERBS = {` for its three matrix gates, and
|
|
84
85
|
* `main`'s refusal lists `Object.keys(VERBS)` IN THIS ORDER, which `harness_golden` cells
|
|
85
86
|
* assert verbatim — the order is the old table's and is not alphabetical.
|
|
87
|
+
*
|
|
88
|
+
* FLATTENED TO `verb: fn` since Task 5: every row was a single-field `{ fn: cmdX }` object,
|
|
89
|
+
* the one field this table has left after `positionals`/`options`/`flags`/etc moved to
|
|
90
|
+
* `js/cli-table.json` above. `main` reads `VERBS[verb]` directly rather than
|
|
91
|
+
* `VERBS[verb].fn` now; the scraping regexes in `tests/unit/{cli_table,hook_cli,docs}.test.mjs`
|
|
92
|
+
* match on the KEY and the colon only; the literal string `const VERBS = {` and the key
|
|
93
|
+
* order neither changed.
|
|
86
94
|
*/
|
|
87
95
|
const VERBS = {
|
|
88
|
-
exclude:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
fn: cmdTheme,
|
|
105
|
-
},
|
|
106
|
-
diff: {
|
|
107
|
-
fn: cmdDiff,
|
|
108
|
-
},
|
|
109
|
-
'rebuild-all': {
|
|
110
|
-
fn: cmdRebuildAll,
|
|
111
|
-
},
|
|
112
|
-
migrate: {
|
|
113
|
-
fn: cmdMigrate,
|
|
114
|
-
},
|
|
115
|
-
doctor: {
|
|
116
|
-
fn: cmdDoctor,
|
|
117
|
-
},
|
|
118
|
-
uninstall: {
|
|
119
|
-
fn: cmdUninstall,
|
|
120
|
-
},
|
|
121
|
-
link: {
|
|
122
|
-
fn: cmdLink,
|
|
123
|
-
},
|
|
124
|
-
unlink: {
|
|
125
|
-
fn: cmdUnlink,
|
|
126
|
-
},
|
|
127
|
-
setup: {
|
|
128
|
-
fn: cmdSetup,
|
|
129
|
-
},
|
|
130
|
-
web: {
|
|
131
|
-
fn: cmdWeb,
|
|
132
|
-
},
|
|
133
|
-
upgrade: {
|
|
134
|
-
fn: cmdUpgrade,
|
|
135
|
-
},
|
|
96
|
+
exclude: cmdExclude,
|
|
97
|
+
status: cmdStatus,
|
|
98
|
+
version: cmdVersion,
|
|
99
|
+
build: cmdBuild,
|
|
100
|
+
prompt: cmdPrompt,
|
|
101
|
+
theme: cmdTheme,
|
|
102
|
+
diff: cmdDiff,
|
|
103
|
+
'rebuild-all': cmdRebuildAll,
|
|
104
|
+
migrate: cmdMigrate,
|
|
105
|
+
doctor: cmdDoctor,
|
|
106
|
+
uninstall: cmdUninstall,
|
|
107
|
+
link: cmdLink,
|
|
108
|
+
unlink: cmdUnlink,
|
|
109
|
+
setup: cmdSetup,
|
|
110
|
+
web: cmdWeb,
|
|
111
|
+
upgrade: cmdUpgrade,
|
|
136
112
|
// `up.add_parser(..., aliases=["update"])`, reproduced in P8c as a ROW OF ITS OWN rather than
|
|
137
113
|
// as an `aliases` field on the row above — because a field would be a DECLARATION and the
|
|
138
114
|
// three matrix gates read this table as the DISPATCH (rule 7, and M23 is where it was
|
|
@@ -144,28 +120,18 @@ const VERBS = {
|
|
|
144
120
|
//
|
|
145
121
|
// It is NOT what the web console's `update` ACTION needs: that row's argv names `upgrade`,
|
|
146
122
|
// the subparser, and always did. The two were coupled only in a handoff's note.
|
|
147
|
-
update:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// and `sync-self v1.2.3` differently. See `js/maintain/update.mjs`'s `syncSelf` for both halves.
|
|
155
|
-
fn: cmdSyncSelf,
|
|
156
|
-
},
|
|
157
|
-
bootstrap: {
|
|
158
|
-
fn: cmdBootstrap,
|
|
159
|
-
},
|
|
123
|
+
update: cmdUpgrade,
|
|
124
|
+
// Points at `cmdSyncSelf` rather than at `cmdUpgrade`, and that is not tidiness:
|
|
125
|
+
// `sync-self` DROPS its `ref` before `upgrade` ever sees it, where `upgrade` both WARNS
|
|
126
|
+
// about one and re-reads it as a theme — so the two verbs answer `sync-self cyberpunk`
|
|
127
|
+
// and `sync-self v1.2.3` differently. See `js/maintain/update.mjs`'s `syncSelf` for both halves.
|
|
128
|
+
'sync-self': cmdSyncSelf,
|
|
129
|
+
bootstrap: cmdBootstrap,
|
|
160
130
|
// P7a. Both are DISPATCHERS whose off-TTY arm is the whole of what a cell can reach, and
|
|
161
131
|
// `menu`'s on-TTY arm falls back rather than opening a panel — `js/ui/menu.mjs`'s header
|
|
162
132
|
// argues both.
|
|
163
|
-
menu:
|
|
164
|
-
|
|
165
|
-
},
|
|
166
|
-
home: {
|
|
167
|
-
fn: cmdHome,
|
|
168
|
-
},
|
|
133
|
+
menu: cmdMenu,
|
|
134
|
+
home: cmdHome,
|
|
169
135
|
// P7b, and it is the twenty-fifth and last. `cmd_tui`'s FIRST arm is `if not sys.stdin.
|
|
170
136
|
// isatty()`, so off a TTY — which is every cell there is — the verb is one line and an
|
|
171
137
|
// exit code, and that arm crosses byte for byte. The panel behind it is P7c's;
|
|
@@ -173,9 +139,7 @@ const VERBS = {
|
|
|
173
139
|
// panel-unavailable line rather than inventing a second full-screen UI, and
|
|
174
140
|
// `tests/test_tui_boundary.py` asserts that the arm it declares is genuinely unreachable
|
|
175
141
|
// here rather than merely untested.
|
|
176
|
-
tui:
|
|
177
|
-
fn: cmdTui,
|
|
178
|
-
},
|
|
142
|
+
tui: cmdTui,
|
|
179
143
|
// THE THREE THAT NEVER HAD A PYTHON ORIGINAL, and they are last for that reason rather
|
|
180
144
|
// than by alphabet: every row above is the twin of a subparser, and these three are not.
|
|
181
145
|
// The information behind them existed only behind the web console — the catalog endpoint,
|
|
@@ -190,21 +154,15 @@ const VERBS = {
|
|
|
190
154
|
// ABSOLUTE — `tests/snapshot/cli_help.test.mjs` splits the two populations by name and refuses a
|
|
191
155
|
// verb that falls into neither, and each has its own unit gate stating what it does rather
|
|
192
156
|
// than that it agrees.
|
|
193
|
-
catalog:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
mcp: {
|
|
197
|
-
fn: cmdMcp,
|
|
198
|
-
},
|
|
199
|
-
memory: {
|
|
200
|
-
fn: cmdMemory,
|
|
201
|
-
},
|
|
157
|
+
catalog: cmdCatalog,
|
|
158
|
+
mcp: cmdMcp,
|
|
159
|
+
memory: cmdMemory,
|
|
202
160
|
};
|
|
203
161
|
|
|
204
162
|
function die(code, msg) {
|
|
205
163
|
// CRLF on Windows, for the same reason `js/hosts/hooks.mjs`'s funnels translate: argparse writes
|
|
206
|
-
// this line through `sys.stderr`, which does.
|
|
207
|
-
|
|
164
|
+
// this line through `sys.stderr`, which does. `printErr` owns the `\n`-to-`os.linesep` rule.
|
|
165
|
+
printErr(`geneseed: error: ${msg}\n`);
|
|
208
166
|
return code;
|
|
209
167
|
}
|
|
210
168
|
|
|
@@ -358,8 +316,8 @@ async function main(argv) {
|
|
|
358
316
|
throw e;
|
|
359
317
|
}
|
|
360
318
|
}
|
|
361
|
-
const
|
|
362
|
-
if (!
|
|
319
|
+
const fn = VERBS[verb];
|
|
320
|
+
if (!fn) {
|
|
363
321
|
// "and every other harness subcommand is still Python — run the interpreter against the
|
|
364
322
|
// old harness script" is GONE, and its removal is not cosmetic: with the four hook verbs
|
|
365
323
|
// named, the two entry points now cover every subcommand there is, so the clause was not
|
|
@@ -395,7 +353,7 @@ async function main(argv) {
|
|
|
395
353
|
// it `process.exitCode` would be assigned a PENDING PROMISE, which Node coerces to 0
|
|
396
354
|
// and prints nothing about. `web status` would then report "not running" and exit 0.
|
|
397
355
|
// Awaiting a number is a no-op for the ten synchronous verbs.
|
|
398
|
-
return await
|
|
356
|
+
return await fn(parsed.args);
|
|
399
357
|
} catch (e) {
|
|
400
358
|
// `e.exitCode` is the generator's existing marker for a DELIBERATE refusal that has
|
|
401
359
|
// already explained itself on stderr — `js/build/emit-claude.mjs` reads the same flag, and it is
|
package/bin/geneseed-hook.mjs
CHANGED
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
*/
|
|
40
40
|
import { cmdContext, cmdGitGate, cmdRuleGate, cmdLearn } from '../js/hosts/hooks.mjs';
|
|
41
41
|
import { printHelp } from '../js/ui/cli.mjs';
|
|
42
|
+
// Not a new module on the hot path: `js/hosts/hooks.mjs` above already imports
|
|
43
|
+
// `js/lib/fs.mjs`, so this edge names a file the process has already loaded.
|
|
44
|
+
import { printErr } from '../js/lib/fs.mjs';
|
|
42
45
|
|
|
43
46
|
const VERBS = {
|
|
44
47
|
context: { fn: cmdContext, flags: { '--root': 'root' } },
|
|
@@ -54,8 +57,8 @@ const VERBS = {
|
|
|
54
57
|
|
|
55
58
|
function die(code, msg) {
|
|
56
59
|
// CRLF on Windows, for the same reason `js/hosts/hooks.mjs`'s funnels translate: argparse
|
|
57
|
-
// writes this line through `sys.stderr`, which does.
|
|
58
|
-
|
|
60
|
+
// writes this line through `sys.stderr`, which does. `printErr` owns the `\n`-to-`os.linesep` rule.
|
|
61
|
+
printErr(`geneseed-hook: error: ${msg}\n`);
|
|
59
62
|
return code;
|
|
60
63
|
}
|
|
61
64
|
|
package/docs/web/exclusions.md
CHANGED
|
@@ -3,7 +3,7 @@ group: concepts
|
|
|
3
3
|
order: 9
|
|
4
4
|
title: "Sovereign repos (exclusions)"
|
|
5
5
|
kind: "concept"
|
|
6
|
-
link: {"hash": "#/
|
|
6
|
+
link: {"hash": "#/harness", "label": "Manage in Harness →"}
|
|
7
7
|
---
|
|
8
8
|
A **sovereign repo** is a folder where every GLOBAL harness install goes fully dormant: hooks stay silent and the global preamble (`AGENT.md`/`CLAUDE.md`) is never loaded there. A repo that ships its own agent config you don't want a global harness layered onto is the usual case.
|
|
9
9
|
|
package/docs/web/footprint.md
CHANGED
|
@@ -29,7 +29,7 @@ Neither setting hides text from the agent; they hide it from *every turn*.
|
|
|
29
29
|
It's set-and-forget — stored in the `.geneseed-footprint` marker, preserved across every rebuild, identical on every host (OpenCode, Claude Code, Bob, Copilot). Changing it re-emits the install.
|
|
30
30
|
|
|
31
31
|
- **Settings** — the **Footprint** toggle flips the current install (full ⇄ lean) and rebuilds it in place.
|
|
32
|
-
- **
|
|
32
|
+
- **Harness tab** — on an active install, a per-harness dropdown sets it for that install independently, then **Apply**. On a host that is not installed yet, it is step 2 of **Install…**.
|
|
33
33
|
- **Setup / re-theme wizard** — asks for footprint alongside voice, posture, mode, and doctrine packs.
|
|
34
34
|
- **CLI** — `geneseed-build --footprint lean` (with any `--emit`).
|
|
35
35
|
|
package/docs/web/foreman-mode.md
CHANGED
|
@@ -3,7 +3,7 @@ group: concepts
|
|
|
3
3
|
order: 12
|
|
4
4
|
title: "Foreman mode"
|
|
5
5
|
kind: "concept"
|
|
6
|
-
link: {"hash": "#/
|
|
6
|
+
link: {"hash": "#/harness", "label": "Set the mode in Harness →"}
|
|
7
7
|
---
|
|
8
8
|
**Mode** is the session's *operating* register — how work gets executed — one of four build-time dials, beside posture (the *relationship* register), [doctrine packs](#/docs/setup-choices) (which practice rules bind) and footprint (how much of the constitution loads inline). Two modes ship, set at build time so the choice holds steady instead of drifting mid-session, and preserved across every rebuild and re-theme.
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ Because the crew runs apart from the conversation, the session stays responsive
|
|
|
24
24
|
|
|
25
25
|
Set-and-forget, stored beside the install and preserved across rebuilds and re-themes:
|
|
26
26
|
|
|
27
|
-
- **
|
|
27
|
+
- **Harness tab** — on an active install, the per-install **Mode** dropdown (beside Voice, Footprint, and Posture), then **Apply**. On a host that is not installed yet, the same four choices are steps inside **Install…**.
|
|
28
28
|
- **Setup / re-theme wizard** — asks for mode alongside voice, posture, doctrine packs, and footprint.
|
|
29
29
|
- **CLI** — `geneseed-build --mode foreman`; switch back with `--mode direct`.
|
|
30
30
|
|
|
@@ -3,7 +3,7 @@ group: extend
|
|
|
3
3
|
order: 1
|
|
4
4
|
title: "Write a new theme"
|
|
5
5
|
kind: "concept"
|
|
6
|
-
link: {"hash": "#/
|
|
6
|
+
link: {"hash": "#/harness", "label": "Open the voice gallery →"}
|
|
7
7
|
---
|
|
8
8
|
A theme is one JSON file under `themes/` declaring voice tokens only: `BANNER`, `TAGLINE`, `LOADED_SIGIL`, `VOICE`, the core nouns (`ONTOLOGY`/`LAW(S)`/`DOCTRINE(S)`/`AGENT(S)`/`SKILL(S)`/`MEMORY`/`NOTEBOOK`/`WIKI`), the section intros `INTRO_*`, the epigraphs `EPI_*`, the `BENEDICTION`, the `ROAST_PERSONA`, and `DESC_*` blurbs. Copy `themes/neutral.json` and edit. `geneseed build --theme yours` renders it; `doctor` checks for missing tokens.
|
|
9
9
|
|
package/docs/web-ui.md
CHANGED
|
@@ -50,12 +50,17 @@ The left rail mirrors the harness's own shape:
|
|
|
50
50
|
|
|
51
51
|
| Group | Views |
|
|
52
52
|
| --- | --- |
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
53
|
+
| *(ungrouped)* | Dashboard |
|
|
54
|
+
| **📖 Codex** | Constitution · Rules · Profile · Skills · Agents · Library · Docs · Graph |
|
|
55
|
+
| **🩺 Care** | Activity · Changes · Doctor |
|
|
56
|
+
| **🎨 Setup** | Harness · Settings |
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Above the index sits a **vitals** card — the germination ring, drift, the doctor's verdict
|
|
59
|
+
and how long ago the harness was built — so those four facts are on screen from every page.
|
|
60
|
+
It is hidden where the rail collapses to icons (≤960px) and returns with the phone drawer.
|
|
61
|
+
|
|
62
|
+
A global **Spotlight** search lives in the topbar — press <kbd>/</kbd> to focus it (or
|
|
63
|
+
<kbd>Ctrl</kbd>/<kbd>⌘</kbd>+<kbd>K</kbd>, which also works from inside a text field), type
|
|
59
64
|
to jump to any agent, skill, doc, spec, MCP server, or constitutional rule — the `laws`
|
|
60
65
|
catalog it indexes is the whole constitution, so an ontology section, an invariant and a
|
|
61
66
|
doctrine rule are all reachable by name; <kbd>↑</kbd>/<kbd>↓</kbd> to
|
|
@@ -129,32 +134,39 @@ streams the output of background jobs and keeps their history across reloads.
|
|
|
129
134
|
theme, parity, links, authoring gates, drift), grouping any problems per check. Re-run
|
|
130
135
|
on demand.
|
|
131
136
|
|
|
132
|
-
### 🎨
|
|
133
|
-
|
|
134
|
-
- **
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
137
|
+
### 🎨 Setup
|
|
138
|
+
|
|
139
|
+
- **Harness** (`#/harness`) — this machine's own install first (path, voice, footprint,
|
|
140
|
+
and when it was built), then the **Voice** reference, then every detected install.
|
|
141
|
+
`#/harnesses` and `#/themes` both still resolve here, so old links and bookmarks keep
|
|
142
|
+
working.
|
|
143
|
+
- The **Voice** card is the former Themes tab, kept as a REFERENCE rather than a second
|
|
144
|
+
control: a collapsed row that opens to every shipped voice with its tagline, the
|
|
145
|
+
deployed one pinned first and marked. It is the one place you can read what a voice
|
|
146
|
+
sounds like — the per-install picker below is a list of bare names. Applying happens
|
|
147
|
+
there, per install, beside that install's own footprint, posture and mode; a gallery at
|
|
148
|
+
the top of the page could only ever act on one of them.
|
|
149
|
+
- **Every install** lists each detected install (host × scope), one row each. An
|
|
150
|
+
ACTIVE row carries per-row **Voice**, **Footprint**, **Posture** and **Mode**
|
|
151
|
+
pickers plus **Apply**, an on/off switch, and remove; a host that is NOT installed
|
|
152
|
+
yet shows a single **Install…** that discloses the same four choices as steps.
|
|
153
|
+
**Posture** is the relationship register (peer/mentor/expert/assistant/artisan —
|
|
154
|
+
default **peer**); **Mode** is the operating register (direct/foreman — default
|
|
155
|
+
**direct**; foreman triages tasks into isolated pipelines instead of working every
|
|
156
|
+
one itself). Both are orthogonal to voice and to each other, picked here or via the
|
|
157
|
+
setup wizard, and preserved across every rebuild.
|
|
158
|
+
- "Deploy to folder…" and "Rebuild all" apply to the whole set. An **Excluded folders**
|
|
159
|
+
card (shown once a global install exists) manages sovereign repos — folders where every
|
|
160
|
+
global harness goes dormant (hooks stay silent, the global preamble never loads);
|
|
161
|
+
add or remove one here, the web mirror of `harness exclude add|remove|list`.
|
|
148
162
|
- **Settings** (`#/settings`) — a **Console direction** picker (the visual flavour of the
|
|
149
163
|
console) with a **Dashboard layout** control (Auto follows each theme's designed Status
|
|
150
|
-
lens; Cultivar / Greenhouse / Operator force one regardless of skin), the
|
|
151
|
-
(deployed/target/theme/version/memory store), a Maintenance card (PATH
|
|
152
|
-
uninstall), an offline package download,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
- **About** (`#/about`) — project + creator credits and the source link.
|
|
164
|
+
lens; Cultivar / Greenhouse / Operator / Journal force one regardless of skin), the
|
|
165
|
+
install snapshot (deployed/target/theme/version/memory store), a Maintenance card (PATH
|
|
166
|
+
link/unlink, uninstall), an offline package download, server controls (Stop), and the
|
|
167
|
+
**About** colophon — project + creator credits and the source link, folded in from the
|
|
168
|
+
retired `#/about` tab (which still resolves here). Build, update, and MCP wiring live in
|
|
169
|
+
the Harness tab.
|
|
158
170
|
|
|
159
171
|
## Rebuilding the UI
|
|
160
172
|
|
package/harness.config.json
CHANGED
|
@@ -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": "3.
|
|
5
|
+
"version": "3.2.0"
|
|
6
6
|
}
|
package/js/README.md
CHANGED
|
@@ -172,7 +172,7 @@ the deployed harness as JSON.
|
|
|
172
172
|
| `activity.mjs` | The `activity/` session files: pid-liveness prune, list, detail, and the on/off flag |
|
|
173
173
|
|
|
174
174
|
**Before editing:** `makeHandler(state, jm, token, dist, holder)`'s arity is load-bearing — three
|
|
175
|
-
test call sites construct one directly and drive it without a socket.
|
|
175
|
+
test call sites construct one directly and drive it without a socket. Five of `routes.mjs`'s
|
|
176
176
|
exported sets are deliberately EMPTY and must stay declared: each is half of a partition test.
|
|
177
177
|
`graph.mjs` contains a literal NUL byte, so `grep`/`ripgrep` treat it as binary and skip it.
|
|
178
178
|
|
|
@@ -192,12 +192,3 @@ exported sets are deliberately EMPTY and must stay declared: each is half of a p
|
|
|
192
192
|
| a console doc page | `docs/web/<id>.md` — the stem is the id | `docs/extending.md` §4c. Only `kind: "concept"` gets `{N_*}` substitution |
|
|
193
193
|
| an OpenCode plugin | `adapters/opencode/plugins/geneseed-<name>.js` | `docs/extending.md` §4a — the `geneseed-` prefix is mechanically load-bearing |
|
|
194
194
|
| to change a `js/lib/` primitive | `tests/fixtures/pure_probe.mjs` **first** | the docblock says which Node default it deliberately departs from — change that sentence too, or the next reader restores the default |
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Known debris
|
|
199
|
-
|
|
200
|
-
* **`js/hosts/settings.mjs` carries a private second copy of Python's whitespace class**, duplicating
|
|
201
|
-
`WHITESPACE` in `js/lib/text.mjs`. `text.mjs` is the owner.
|
|
202
|
-
* **`web/src/pages/Skills.jsx`'s `SKILL_CATS` is a fourth, ungated copy of the skill taxonomy** —
|
|
203
|
-
nothing compares it to `SKILL_CLASS`, and an unknown category renders as Build with no warning.
|
package/js/build/emit-claude.mjs
CHANGED
|
@@ -54,8 +54,7 @@ export function emitClaudeRender(cfg, job) {
|
|
|
54
54
|
|
|
55
55
|
// `os.path.relpath(cfg, claude_md.parent)` — note the reversed argument order, and
|
|
56
56
|
// that Python answers '.' for an identical pair where `path.relative` answers ''.
|
|
57
|
-
const relCfg =
|
|
58
|
-
|| '.';
|
|
57
|
+
const relCfg = relPosix(path.dirname(claudeMd), cfgDir) || '.';
|
|
59
58
|
const lawsPrefix = relCfg === '.' ? '' : `${relCfg}/`;
|
|
60
59
|
const { theme, items } = renderAll(cfg, themeName, { footprint, lawsPrefix, nativeCatalog });
|
|
61
60
|
assertSourceComplete(cfg, `claude-${scope}`);
|
|
@@ -98,7 +97,7 @@ export function emitClaudeRender(cfg, job) {
|
|
|
98
97
|
const rulesMd = path.join(cfgDir, 'rules', 'geneseed.md');
|
|
99
98
|
mkdirSync(path.dirname(rulesMd), { recursive: true });
|
|
100
99
|
writeText(rulesMd, scope === 'project' ? BOB_RULES_STUB
|
|
101
|
-
: stripCapabilityLinks(
|
|
100
|
+
: stripCapabilityLinks(prefixedAgentText('../') || agentText));
|
|
102
101
|
owned.push('rules/geneseed.md');
|
|
103
102
|
}
|
|
104
103
|
|
|
@@ -146,7 +145,7 @@ export function emitClaudeRender(cfg, job) {
|
|
|
146
145
|
// consumes and no more.
|
|
147
146
|
let claudeMdText = null;
|
|
148
147
|
if (agentText !== null && !(isBob && scope === 'global')) {
|
|
149
|
-
claudeMdText = stripCapabilityLinks(
|
|
148
|
+
claudeMdText = stripCapabilityLinks(prefixedAgentText(lawsPrefix) || agentText);
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
// WIRE — see `claudeWire` below. One child per emit, so the two halves are two
|
|
@@ -212,7 +211,7 @@ function claudeWire(job, claudeMdText, hasAgentText, doctrines = null, excludeRu
|
|
|
212
211
|
// above — unreachable here (CLAUDE.md is a file, cfgDir a directory, so the pair is
|
|
213
212
|
// never identical) and spelled anyway, because the two call sites are 400 lines apart
|
|
214
213
|
// and only one of them is obviously safe.
|
|
215
|
-
const rel =
|
|
214
|
+
const rel = relPosix(cfgDir, claudeMd) || '.';
|
|
216
215
|
managed.claude_md = { rel };
|
|
217
216
|
} else if (isBob && scope === 'global' && isTruthy(get(old, 'claude_md'))) {
|
|
218
217
|
const oldCm = isDict(get(old, 'claude_md')) ? get(old, 'claude_md') : {};
|