geneseed 3.7.0 → 3.8.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 CHANGED
@@ -10,6 +10,31 @@ label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
10
10
 
11
11
  _Nothing yet._
12
12
 
13
+ ## [3.8.0] — 2026-09-30
14
+
15
+ **Upgrading:** re-emit (or `geneseed rebuild-all`) after installing, so each install carries the
16
+ rewritten `geneseed` skill.
17
+
18
+ ### Added
19
+ - `geneseed status` lists every install with its theme, footprint, posture/mode, doctrine packs
20
+ and excluded rules; `geneseed status --json` prints the same payload plus, per install, the
21
+ `geneseed build` command that rebuilds it unchanged — a global install's command names its
22
+ config dir with `--config-dir`, so it rebuilds in place even from a shell without the env
23
+ override that located it.
24
+ - `geneseed build` forwards the generator's flags (`--emit`, `--footprint`, `--posture`, `--mode`,
25
+ `--doctrines`, `--exclude-rules`, `--out`, `--root`, `--config-dir`); the dry run is
26
+ `geneseed validate`.
27
+
28
+ ### Fixed
29
+ - `setup`'s non-interactive hint (`geneseed build --emit … --theme …`) was a usage error.
30
+ - The `geneseed` skill named `geneseed learn` and `geneseed context`, which are hook verbs the CLI
31
+ refuses; it now reads `status --json` and changes an install by one flag of its rebuild command.
32
+ - README and SETUP claimed `geneseed-build --validate-only` dry-runs a build; the generator refuses
33
+ that flag, and both now name `geneseed validate`.
34
+ - A `-global` emit ignored `--out` and always wrote the live config dir, so a global install could
35
+ not be previewed anywhere else; `--config-dir <dir>` now redirects it, and a per-repo emit
36
+ refuses the flag rather than ignoring it (#156).
37
+
13
38
  ## [3.7.0] — 2026-09-28
14
39
 
15
40
  **Upgrading:** re-emit (or `geneseed rebuild-all`) after installing. An install built before
package/README.md CHANGED
@@ -216,7 +216,7 @@ Lean is the default: the rationale is one read away and the context it frees is
216
216
 
217
217
  Either way the harness is otherwise identical — same files, Rules, capabilities, and guards; lean only relocates the *reasoning* to on-demand (and adds the standalone law, ontology and doctrine files to global/Claude/Bob installs). The one behavioural edge: with the rationale always in context, **full** applies a rule's nuance more reliably on subtle edge cases — or with a weaker model that may not reach for the pointer.
218
218
 
219
- Want to check a build before it touches anything real? `geneseed-build --validate-only --theme NAME --emit MODE --out TARGET` renders and validates into a throwaway sandbox — nothing under `--out`/`--root` is written — and exits non-zero on any problem. Details: [SETUP.md](SETUP.md#dry-run-a-build-validate).
219
+ Want to check a build before it touches anything real? `geneseed validate --theme NAME --emit MODE --out TARGET` renders and validates into a throwaway sandbox — nothing under `--out`/`--root` is written — and exits non-zero on any problem. Details: [SETUP.md](SETUP.md#dry-run-a-build-validate).
220
220
 
221
221
  ---
222
222
 
package/SETUP.md CHANGED
@@ -472,8 +472,8 @@ geneseed validate --theme imperial --emit opencode --out /path/to/repo/Harness
472
472
  ```
473
473
 
474
474
  (It is a verb on the CLI rather than a flag on the generator because it runs `doctor`, and
475
- the generator is deliberately unable to start a process. `geneseed-build --validate-only
476
- …` is the same tool with the same flags.)
475
+ the generator is deliberately unable to start a process — `geneseed-build` refuses
476
+ `--validate-only` outright.)
477
477
 
478
478
  Renders and emits the requested `--theme`/`--emit`/`--out`/`--root`/`--footprint`
479
479
  combination into a throwaway sandbox — nothing under the real `--out`/`--root` is
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: **3.7.0**.
23
+ > string. Current label: **3.8.0**.
24
24
 
25
25
  ## Capabilities
26
26
 
@@ -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.7.0"
5
+ "version": "3.8.0"
6
6
  }
@@ -166,7 +166,7 @@ const VALUED = {
166
166
  '--theme': 'theme', '--posture': 'posture', '--mode': 'mode',
167
167
  '--doctrines': 'doctrines', '--exclude-rules': 'excludeRules',
168
168
  '--out': 'out', '--target': 'out', '--emit': 'emit',
169
- '--footprint': 'footprint', '--root': 'root',
169
+ '--footprint': 'footprint', '--root': 'root', '--config-dir': 'cfgDir',
170
170
  };
171
171
  const FLAGS = {
172
172
  '--sync-themes': 'syncThemes', '--validate-only': 'validateOnly',
@@ -1032,10 +1032,10 @@ function writeMarkers(markerDir, emit, footprint) {
1032
1032
  * compares it file by file. The Python spells that `HOSTS[host]["emit_global"](theme,
1033
1033
  * out=..., cfg=<tmp>, footprint=...)`, where `cfg` overrides the target the emit would
1034
1034
  * otherwise resolve. This is that call, and the override is threaded as `args.cfgDir` through
1035
- * the four `emit*Global` bodies rather than added to `parseArgs`: `build.py` has no
1036
- * `--cfg-dir` flag, and a flag on one driver and not the other is a divergence
1037
- * `tests/golden.py` compares 259 times and could never see, because it drives both from the
1038
- * same argv.
1035
+ * the `emit*Global` bodies. The same key is also `--config-dir` on the command line: a global
1036
+ * emit never writes to `--out` (there `out` is the legacy bundle a memory store migrates FROM,
1037
+ * and `update` passes it for exactly that), so without the flag there was no way to preview a
1038
+ * global install anywhere but over the live one.
1039
1039
  *
1040
1040
  * WHICH SIDE OF THE BOUNDARY THIS SITS ON. P3c's rule was that a render CHILD must never
1041
1041
  * resolve a config dir, because a child that did would write 135 files into the developer's
@@ -1187,6 +1187,15 @@ function run(argv) {
1187
1187
  }
1188
1188
 
1189
1189
  const out = resolveOut(args.out);
1190
+ // Refused rather than ignored on a per-repo emit: an ignored target flag is how a preview
1191
+ // lands on a live install, which is the bug this flag exists to close.
1192
+ if (args.cfgDir !== undefined) {
1193
+ if (!args.emit.endsWith('-global')) {
1194
+ die(2, `argument --config-dir: only applies to a -global emit (got --emit ${args.emit}); `
1195
+ + 'a per-repo emit writes under --out/--root');
1196
+ }
1197
+ args.cfgDir = resolveOut(args.cfgDir);
1198
+ }
1190
1199
  const cfg = makeCfg(args);
1191
1200
 
1192
1201
  // The marker directory is the emit's TARGET, which for a global emit is the config dir it
@@ -80,12 +80,28 @@ function sysExit(msg) {
80
80
  * Calling the driver in-process keeps that: `resolveOut` resolves against `process.cwd()`
81
81
  * the same way. `build/the-bundle-follows-cwd-not-the-checkout` is the cell.
82
82
  *
83
- * Every other flag is the generator's own default, read from `harness.config.json` by the
84
- * driver — `harness build` forwards `--theme` and nothing else, and its own `--theme`
85
- * carries no `choices`, so an unknown one is refused by the generator rather than here.
83
+ * `geneseed build` used to forward `--theme` alone, which made `setup`'s own off-TTY hint
84
+ * (`geneseed build --emit … --theme …`) a usage error and left every other axis reachable
85
+ * only through the undocumented `geneseed-build`. Values are forwarded unchecked: the driver
86
+ * owns the choices, so the table does not repeat them.
87
+ *
88
+ * `--validate-only` is NOT one of these: it lives on `geneseed validate` only — that verb's
89
+ * source-tree half is the doctor, which starts a process, and this command's whole closure
90
+ * (`bin/geneseed-cli.mjs` → here → `driverMain`) is under the same transitive `child_process`
91
+ * ban as `bin/build-driver.mjs` itself. `driver.mjs`'s `run()` refuses the flag unconditionally
92
+ * for exactly that reason.
86
93
  */
94
+ const BUILD_FORWARD = [
95
+ ['theme', '--theme'], ['emit', '--emit'], ['footprint', '--footprint'],
96
+ ['posture', '--posture'], ['mode', '--mode'], ['doctrines', '--doctrines'],
97
+ ['excludeRules', '--exclude-rules'], ['out', '--out'], ['root', '--root'],
98
+ ['configDir', '--config-dir'],
99
+ ];
100
+
87
101
  export function cmdBuild(args) {
88
- return driverMain(args.theme ? ['--theme', args.theme] : []);
102
+ const argv = [];
103
+ for (const [key, flag] of BUILD_FORWARD) if (args[key] != null) argv.push(flag, args[key]);
104
+ return driverMain(argv);
89
105
  }
90
106
 
91
107
  // --------------------------------------------------------------------------------------
@@ -161,6 +177,66 @@ export const DEFAULT_EMIT = new Map([
161
177
  ['openclaude global', 'openclaude-global'], ['openclaude project', 'openclaude'],
162
178
  ]);
163
179
 
180
+ /**
181
+ * Everything `rebuild-all` reads back off one install, and the argv that re-emits it unchanged.
182
+ *
183
+ * EXTRACTED SO `status` SHOWS WHAT A REBUILD WOULD USE, not a second reading of the same
184
+ * markers that could drift from this one. An agent changing one setting takes `argv`, edits one
185
+ * flag and runs it; every flag it did not touch has to be the install's own, or the "one
186
+ * change" silently resets the rest — which is exactly the failure the seven read-backs below
187
+ * exist to prevent.
188
+ *
189
+ * THE MARKER IS TRUSTED ONLY FOR ITS OWN HOST. There is one `.geneseed-emit` per root and the
190
+ * last deploy wins, so in a dual-host repo (`.opencode/` and `.claude/` in one cwd) the other
191
+ * host's row would otherwise rebuild with the WRONG emit — turning a Claude install into an
192
+ * OpenCode one. `rebuild-all/a-dual-host-repo-rebuilds-each-row-in-its-own-emit` is the cell.
193
+ */
194
+ export function installProfile(host, scope, root) {
195
+ const raw = readMaybe(path.join(root, '.geneseed-emit'));
196
+ let marker = raw === null ? '' : raw.trim();
197
+ if (marker && (EMIT_HOST_SCOPE.get(marker) ?? ['', ''])[0] !== host) marker = '';
198
+ const emit = marker || DEFAULT_EMIT.get(`${host} ${scope}`) || 'opencode-global';
199
+ const theme = themeOfDir(root) || defaultTheme();
200
+ const footprint = footprintOfDir(root);
201
+ const posture = postureOfDir(root) || defaultPosture();
202
+ const mode = modeOfDir(root) || defaultMode();
203
+ // A rebuild that defaulted the pack selection would re-emit an install into a constitution
204
+ // its owner did not choose — and in one direction that is not merely surprising: dropping
205
+ // the process pack takes the commit/push consent RULES out of AGENT.md while
206
+ // `claudeHookGroups` keeps the gate wired, or the reverse. ⚠ AND THE FALLBACK IS NOT
207
+ // `harness.config.json`: a pre-migration carrier has no marker, and resolving that silence
208
+ // out of a machine-wide config narrows every such install on its first upgrade.
209
+ // `doctrinesForBuild` resolves unknown to ALL packs — see its docblock.
210
+ const doctrines = doctrinesForBuild(root);
211
+ // The per-rule axis is preserved for the same reason and with sharper teeth: an upgrade that
212
+ // dropped it would quietly hand back every rule its owner switched off, and `process 5` is
213
+ // one of them. `null` (no marker) stays `null` so the argv omits the flag, as it always did.
214
+ const excludeRules = excludedRulesOfDir(root);
215
+ const out = scope === 'global' ? null : root;
216
+ const argv = setupBuildArgs(theme, emit, out, out, footprint, posture, mode, doctrines,
217
+ PACK_ORDER, excludeRules);
218
+ // A GLOBAL ROW NAMES ITS OWN DIR. `root` came from the host's config-dir resolver, which
219
+ // honours env overrides (`OPENCODE_CONFIG_DIR`, `CLAUDE_CONFIG_DIR`…); without the flag the
220
+ // same argv run from a shell lacking that variable re-emits into the DEFAULT dir — a second
221
+ // install beside the one it was meant to rebuild. Appended, so the argv's head is unchanged.
222
+ if (scope === 'global') argv.push('--config-dir', root);
223
+ return {
224
+ host, scope, root, state: installState(root, host, scope),
225
+ emit, theme, footprint, posture, mode, doctrines, excludeRules, argv,
226
+ };
227
+ }
228
+
229
+ /**
230
+ * `argv` as one pasteable command, using the `geneseed build` launcher rather than the raw
231
+ * generator: `geneseed-build` is only on PATH for an npm global install, while a git-clone
232
+ * install has only the `geneseed` launcher, and `geneseed build` now forwards every flag
233
+ * `setupBuildArgs` produces. Only whitespace is quoted — a path holding shell metacharacters
234
+ * (`$`, `&`) would need quoting by hand.
235
+ */
236
+ export function rebuildCommand(argv) {
237
+ return ['geneseed', 'build', ...argv.map((a) => (/\s/.test(a) ? `"${a}"` : a))].join(' ');
238
+ }
239
+
164
240
  /**
165
241
  * `_harness_build.cmd_rebuild_all` — re-emit every ACTIVE install in place, best-effort.
166
242
  *
@@ -172,16 +248,12 @@ export const DEFAULT_EMIT = new Map([
172
248
  * `main` converts, and `rebuild-all/one-broken-install-does-not-stop-the-rest` is the cell
173
249
  * that fails if either half is undone.
174
250
  *
175
- * FIVE VALUES ARE READ BACK OFF EACH INSTALL, not defaulted. Theme and emit and footprint
176
- * come from markers; posture and mode are detected from the `**<Name>**` lead in the
177
- * deployed carrier's prose, because they were never markered. A rebuild that defaulted any
178
- * of them would silently re-emit an install into something its owner did not choose — which
179
- * is the same failure mode `_footprint_of_dir`'s WARN exists to prevent, at a larger scale.
180
- *
181
- * THE MARKER IS TRUSTED ONLY FOR ITS OWN HOST. There is one `.geneseed-emit` per root and the
182
- * last deploy wins, so in a dual-host repo (`.opencode/` and `.claude/` in one cwd) the other
183
- * host's row would otherwise rebuild with the WRONG emit — turning a Claude install into an
184
- * OpenCode one. `rebuild-all/a-dual-host-repo-rebuilds-each-row-in-its-own-emit` is the cell.
251
+ * SEVEN VALUES ARE READ BACK OFF EACH INSTALL, not defaulted — see `installProfile`. Theme and
252
+ * emit and footprint come from markers; posture and mode are detected from the `**<Name>**`
253
+ * lead in the deployed carrier's prose, because they were never markered. A rebuild that
254
+ * defaulted any of them would silently re-emit an install into something its owner did not
255
+ * choose — which is the same failure mode `_footprint_of_dir`'s WARN exists to prevent, at a
256
+ * larger scale.
185
257
  */
186
258
  export function cmdRebuildAll() {
187
259
  const targets = installTargets().filter(([h, s, r]) => installState(r, h, s) === 'active');
@@ -191,34 +263,11 @@ export function cmdRebuildAll() {
191
263
  }
192
264
  const failures = [];
193
265
  for (const [host, scope, root] of targets) {
194
- const raw = readMaybe(path.join(root, '.geneseed-emit'));
195
- let marker = raw === null ? '' : raw.trim();
196
- if (marker && (EMIT_HOST_SCOPE.get(marker) ?? ['', ''])[0] !== host) marker = '';
197
- const emit = marker || DEFAULT_EMIT.get(`${host} ${scope}`) || 'opencode-global';
198
- const theme = themeOfDir(root) || defaultTheme();
199
- const footprint = footprintOfDir(root);
200
- const posture = postureOfDir(root) || defaultPosture();
201
- const mode = modeOfDir(root) || defaultMode();
202
- const out = scope === 'global' ? null : root;
203
- // SIX values now, not five. A rebuild that defaulted the pack selection would re-emit an
204
- // install into a constitution its owner did not choose — and in one direction that is not
205
- // merely surprising: dropping the process pack takes the commit/push consent RULES out of
206
- // AGENT.md while `claudeHookGroups` keeps the gate wired, or the reverse. ⚠ AND THE
207
- // FALLBACK IS NOT `harness.config.json`: a pre-migration carrier has no marker, and
208
- // resolving that silence out of a machine-wide config narrows every such install on its
209
- // first upgrade. `doctrinesForBuild` resolves unknown to ALL packs — see its docblock.
210
- const doctrines = doctrinesForBuild(root);
211
- // SEVEN. The per-rule axis is preserved for the same reason and with sharper teeth: an
212
- // upgrade that dropped it would quietly hand back every rule its owner switched off, and
213
- // `process 5` is one of them — the consent gate would return to a harness that had been
214
- // built without it. No `doctrinesForBuild` rescue is needed here; see `apiInstallCmd`.
215
- const excludeRules = excludedRulesOfDir(root);
216
- const argv = setupBuildArgs(theme, emit, out, out, footprint, posture, mode, doctrines,
217
- PACK_ORDER, excludeRules);
266
+ const p = installProfile(host, scope, root);
218
267
  const label = `${host}:${scope} (${root})`;
219
- printOut(`[rebuild-all] ${label}: theme=${theme} emit=${emit} footprint=${footprint} `
220
- + `posture=${posture} mode=${mode}\n`);
221
- const rc = driverMain(argv);
268
+ printOut(`[rebuild-all] ${label}: theme=${p.theme} emit=${p.emit} footprint=${p.footprint} `
269
+ + `posture=${p.posture} mode=${p.mode}\n`);
270
+ const rc = driverMain(p.argv);
222
271
  if (rc !== 0) {
223
272
  failures.push(label);
224
273
  printErr(`[rebuild-all] FAILED ${label} (exit ${rc})\n`);
package/js/cli-table.json CHANGED
@@ -54,7 +54,7 @@
54
54
  },
55
55
  {
56
56
  "name": "build",
57
- "help": "render src/ -> Harness/",
57
+ "help": "render the harness (same flags as geneseed-build; an omitted flag takes the generator default, not the install's — see geneseed status --json for an install's own; dry run: geneseed validate)",
58
58
  "description": "",
59
59
  "positionals": [],
60
60
  "options": [
@@ -72,6 +72,141 @@
72
72
  "is_flag": false,
73
73
  "type": null,
74
74
  "hidden": false
75
+ },
76
+ {
77
+ "names": [
78
+ "--emit"
79
+ ],
80
+ "dest": "emit",
81
+ "metavar": null,
82
+ "help": "",
83
+ "choices": null,
84
+ "default": null,
85
+ "required": false,
86
+ "nargs": null,
87
+ "is_flag": false,
88
+ "type": null,
89
+ "hidden": false
90
+ },
91
+ {
92
+ "names": [
93
+ "--footprint"
94
+ ],
95
+ "dest": "footprint",
96
+ "metavar": null,
97
+ "help": "",
98
+ "choices": null,
99
+ "default": null,
100
+ "required": false,
101
+ "nargs": null,
102
+ "is_flag": false,
103
+ "type": null,
104
+ "hidden": false
105
+ },
106
+ {
107
+ "names": [
108
+ "--posture"
109
+ ],
110
+ "dest": "posture",
111
+ "metavar": null,
112
+ "help": "",
113
+ "choices": null,
114
+ "default": null,
115
+ "required": false,
116
+ "nargs": null,
117
+ "is_flag": false,
118
+ "type": null,
119
+ "hidden": false
120
+ },
121
+ {
122
+ "names": [
123
+ "--mode"
124
+ ],
125
+ "dest": "mode",
126
+ "metavar": null,
127
+ "help": "",
128
+ "choices": null,
129
+ "default": null,
130
+ "required": false,
131
+ "nargs": null,
132
+ "is_flag": false,
133
+ "type": null,
134
+ "hidden": false
135
+ },
136
+ {
137
+ "names": [
138
+ "--doctrines"
139
+ ],
140
+ "dest": "doctrines",
141
+ "metavar": null,
142
+ "help": "",
143
+ "choices": null,
144
+ "default": null,
145
+ "required": false,
146
+ "nargs": null,
147
+ "is_flag": false,
148
+ "type": null,
149
+ "hidden": false
150
+ },
151
+ {
152
+ "names": [
153
+ "--exclude-rules"
154
+ ],
155
+ "dest": "exclude_rules",
156
+ "metavar": null,
157
+ "help": "",
158
+ "choices": null,
159
+ "default": null,
160
+ "required": false,
161
+ "nargs": null,
162
+ "is_flag": false,
163
+ "type": null,
164
+ "hidden": false
165
+ },
166
+ {
167
+ "names": [
168
+ "--out"
169
+ ],
170
+ "dest": "out",
171
+ "metavar": null,
172
+ "help": "",
173
+ "choices": null,
174
+ "default": null,
175
+ "required": false,
176
+ "nargs": null,
177
+ "is_flag": false,
178
+ "type": null,
179
+ "hidden": false
180
+ },
181
+ {
182
+ "names": [
183
+ "--root"
184
+ ],
185
+ "dest": "root",
186
+ "metavar": null,
187
+ "help": "",
188
+ "choices": null,
189
+ "default": null,
190
+ "required": false,
191
+ "nargs": null,
192
+ "is_flag": false,
193
+ "type": null,
194
+ "hidden": false
195
+ },
196
+ {
197
+ "names": [
198
+ "--config-dir"
199
+ ],
200
+ "dest": "config_dir",
201
+ "metavar": null,
202
+ "help": "the config dir a -global emit writes to (default: the host's resolved one)",
203
+ "choices": null,
204
+ "default": null,
205
+ "required": false,
206
+ "nargs": null,
207
+ "is_flag": false,
208
+ "type": null,
209
+ "hidden": false
75
210
  }
76
211
  ],
77
212
  "mutex": []
@@ -681,7 +816,21 @@
681
816
  "help": "print the install dashboard as text (theme, mode, counts, memory, version)",
682
817
  "description": "",
683
818
  "positionals": [],
684
- "options": [],
819
+ "options": [
820
+ {
821
+ "names": ["--json"],
822
+ "dest": "json",
823
+ "metavar": null,
824
+ "help": "print the status payload as JSON — every install with its settings and the geneseed build command that rebuilds it",
825
+ "choices": null,
826
+ "default": false,
827
+ "required": false,
828
+ "nargs": "0",
829
+ "is_flag": true,
830
+ "type": null,
831
+ "hidden": false
832
+ }
833
+ ],
685
834
  "mutex": []
686
835
  },
687
836
  {
@@ -70,8 +70,9 @@ import {
70
70
  // re-exported below because `tests/fixtures/pure_probe.mjs` names this module for two of them
71
71
  // and a corpus that followed the code to its new file would stop testing the caller's view.
72
72
  import {
73
- defaultTheme, installedDefaults, manifestIsClaude, readJsonMaybe, readMaybe,
73
+ defaultTheme, installedDefaults, installTargets, manifestIsClaude, readJsonMaybe, readMaybe,
74
74
  } from '../hosts/installs.mjs';
75
+ import { installProfile, rebuildCommand } from '../build/generate.mjs';
75
76
  import { printOut } from '../lib/fs.mjs';
76
77
  import { codePointLength, padEndToWidth } from '../lib/text.mjs';
77
78
 
@@ -262,6 +263,20 @@ export function statusData() {
262
263
  agent_md: agentMd ? String(agentMd) : null,
263
264
  agent_md_present: Boolean(agentMd && existsSync(agentMd)),
264
265
  gates: gateSummary([...(cfgDir ? [cfgDir] : []), ...otherCfg]),
266
+ // EVERY install, not just the one `installedDefaults` settles on — and read through the
267
+ // same `installProfile` `rebuild-all` uses, so the settings shown are the ones a rebuild
268
+ // keeps. `rebuild` is the pasteable command an agent edits one flag of. A broken install
269
+ // must not sink the panel, so it is reported rather than thrown. `absent` slots are
270
+ // filtered out here: an absent slot has no settings, so a row of defaults for it reads as
271
+ // an install that does not exist — noise in the panel and misinformation in `--json`.
272
+ installs: installTargets().map(([host, scope, root]) => {
273
+ try {
274
+ const p = installProfile(host, scope, root);
275
+ return { ...p, rebuild: rebuildCommand(p.argv) };
276
+ } catch (e) {
277
+ return { host, scope, root, state: 'unreadable', error: String(e?.message ?? e) };
278
+ }
279
+ }).filter((p) => p.state !== 'absent'),
265
280
  };
266
281
  }
267
282
 
@@ -343,6 +358,18 @@ export function statusLines(d, color = false) {
343
358
  rows.push(['gates', `${armed} ${DOT} ${g.total} ask${g.total === 1 ? '' : 's'}`
344
359
  + (byRule ? ` (${byRule})` : '')]);
345
360
  }
361
+ // Conditional for the recording reason again: no recorded panel carries `installs`.
362
+ for (const p of d.installs ?? []) {
363
+ const where = p.scope === 'project' ? ` (${p.root})` : '';
364
+ if (p.state === 'unreadable') {
365
+ rows.push([`${p.host}:${p.scope}`, `unreadable: ${p.error}${where}`]);
366
+ continue;
367
+ }
368
+ const packs = p.doctrines.length ? p.doctrines.join(',') : 'no packs';
369
+ const excl = p.excludeRules?.length ? `excluding ${p.excludeRules.join(',')}` : 'no rules excluded';
370
+ rows.push([`${p.host}:${p.scope}`, [p.state, p.theme, p.footprint, `${p.posture}/${p.mode}`,
371
+ packs, excl].join(` ${DOT} `) + where]);
372
+ }
346
373
 
347
374
  const labelW = Math.max(...rows.map(([k]) => codePointLength(k)));
348
375
  const body = rows.map(([k, v]) => ` ${padEndToWidth(k, labelW)} ${v}`);
@@ -365,8 +392,17 @@ export function statusLines(d, color = false) {
365
392
  return lines;
366
393
  }
367
394
 
368
- /** `_harness_status.cmd_status`. */
369
- export function cmdStatus() {
370
- for (const line of statusLines(statusData(), colorEnabled())) printOut(`${line}\n`);
395
+ /**
396
+ * `_harness_status.cmd_status` — and `--json`, the machine face of the same payload. An agent
397
+ * reading the panel had to scrape box-drawing; the object below is what the panel is drawn
398
+ * FROM, so the two cannot disagree.
399
+ */
400
+ export function cmdStatus(args) {
401
+ const d = statusData();
402
+ if (args?.json) {
403
+ printOut(`${JSON.stringify(d, null, 2)}\n`);
404
+ return 0;
405
+ }
406
+ for (const line of statusLines(d, colorEnabled())) printOut(`${line}\n`);
371
407
  return 0;
372
408
  }
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": "3.7.0",
4
+ "version": "3.8.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",
@@ -2,17 +2,18 @@
2
2
 
3
3
  > {{DESC_GENESEED}}
4
4
 
5
- **Trigger:** the user mentions Geneseed, the harness, `AGENT.md`, or asks you to inspect, read from, or refresh the deployed bundle — or you need to know what {{LAWS}}, {{AGENTS}}, or {{SKILLS}} are available in the current install.
5
+ **Trigger:** the user mentions Geneseed, the harness, or `AGENT.md`; asks how the install is set up; asks to change its theme, footprint, posture, mode, doctrine packs or excluded rules — or you need to know what {{LAWS}}, {{AGENTS}}, or {{SKILLS}} this install carries.
6
6
 
7
7
  ## Procedure
8
- 1. Locate the deployment. Try in order: `command -v geneseed` (use the launcher if found); `$GENESEED_HARNESS`; `$OPENCODE_CONFIG_DIR`; `~/.config/opencode/AGENT.md`; `.opencode/AGENT.md` walking up from `pwd`; any `AGENT.md` at the repo root. Stop and say so if none resolves — do not run `setup`, `build`, or `upgrade` to "fix" this.
9
- 2. For state — install mode, theme, counts, version fingerprint, drift — prefer the CLI: `geneseed status`, `geneseed version`, `geneseed doctor`, `geneseed diff`. All read-only and cheap ({{DOCTRINE}} process 3).
10
- 3. To read a specific piece, read the file directly rather than re-deriving from prose ({{LAW}} III): `<harness>/agents/<name>.md`, `<harness>/skills/<name>/SKILL.md`, `<harness>/memory/<file>.md`, `<harness>/notebook/<file>.md`. The {{ONTOLOGY}}, the {{LAWS}} and the active {{DOCTRINES}} live as their own numbered `## N. …` sections inside `<harness>/AGENT.md`.
11
- 4. Side-effecting verbs need explicit assent ({{DOCTRINE}} process 5): `geneseed learn` (writes to {{MEMORY}}), `geneseed context` (refreshes the project's `context.json`), `geneseed web start|stop` (the local browser UI on `127.0.0.1`). `geneseed web status` is read-only.
12
- 5. Never run `setup`, `build`, `upgrade`, `bootstrap`, `update`, `sync-self`, `link`, `unlink`, or `uninstall` as a side effect — these are scope-changing and only run when the user explicitly asks ({{LAW}} II).
13
- 6. The bundle's directory and section names are theme-independent (plain English everywhere); only voice and prose change per theme. Don't pattern-match on flavour words to find files.
8
+ 1. **Locate.** Run `geneseed status --json` first: `installs` lists every install on this machine — host, scope, root, state, theme, footprint, posture, mode, packs, excluded rules — and `rebuild`, the command that reproduces each one exactly. `geneseed` not on PATH → ask the user before using `npx geneseed` (it downloads the package), and prefix every command below the same way. Still nothing → look for a host root file: `~/.config/opencode/AGENT.md` or `.opencode/AGENT.md` (OpenCode), `~/.claude/CLAUDE.md` or `.claude/` (Claude Code), `.openclaude/` (OpenClaude), `AGENTS.md` beside `.bob/` or `.github/` (Bob, Copilot). None → say so; never install to "fix" it.
9
+ 2. **Read state** with the read-only verbs, cheapest first ({{DOCTRINE}} process 3): `geneseed status --json`, `geneseed version`, `geneseed catalog` (optionally `agents|skills|laws|ontology|doctrines`), `geneseed doctor`, `geneseed diff`, `geneseed mcp`, `geneseed memory list`, `geneseed exclude list`.
10
+ 3. **Read a piece** from disk, not from recall ({{LAW}} III): `<root>/agents/<name>.md`, `<root>/skills/<name>/SKILL.md`, `<root>/memory/`, `<root>/notebook/`. The {{ONTOLOGY}}, the {{LAWS}} and the active {{DOCTRINES}} are numbered `## N. …` sections of the install's root file.
11
+ 4. **Change an install only when the user asked for that change** ({{LAW}} II). Take that install's `rebuild` command from step 1, edit only the flag the user named (add it if the command omits it — `--posture` and `--mode` are left out at their defaults) — `--theme`, `--footprint lean|full`, `--posture`, `--mode direct|foreman`, `--doctrines craft,rigor|none`, `--exclude-rules "process 7"|none` — dry-run it first by running the same flags through `geneseed validate`, show the command, and run it once the user agrees. Never rebuild from a bare `geneseed build`: every omitted flag resets that setting to the generator default. Confirm with `geneseed status`.
12
+ 5. **Other writes also need the user's word:** `geneseed memory rm <name>`, `geneseed exclude add|remove <path>`, `geneseed web start|stop`, `geneseed uninstall --target <root> --yes`. Personal rules and the profile belong to their own {{SKILLS}}; do not edit `user-rules.md` or `PROFILE.md` from here.
13
+ 6. **Never on your own initiative:** `geneseed setup` (interactive only), `geneseed upgrade`, `geneseed update`, `geneseed bootstrap`, `geneseed sync-self`, `geneseed rebuild-all`, `geneseed migrate`, `geneseed link`, `geneseed unlink`. `learn`, `context` and the `*-gate` verbs are `geneseed-hook` verbs the host's hooks run — never run them by hand.
14
+ 7. Directory and section names are plain English in every theme; only prose changes. Do not search by flavour words.
14
15
 
15
16
  ## Done when
16
- - The user's question about the deployed harness is answered from the live install — file paths or CLI output — not from recall.
17
+ - The answer comes from the live install — CLI output or file paths, not recall — or the requested change was rebuilt with every other setting preserved and `geneseed status` shows it.
17
18
 
18
19
  <!-- INCLUDE: skills/_self-improvement.md -->
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "<one-line description: drive herdr from inside it — split panes, spawn agents, read panes>",
74
74
  "DESC_RULE": "<one-line description: ask whether the user wants a standing rule or a durable memory, then write the memory, or pressure-test the rule until it is generic and adopt it in user-rules.md>",
75
75
  "DESC_PROFILE": "<one-line description: interview the user and draft or refresh PROFILE.md — who they are, how they work, how they like answers pitched; identity only, rules go to user-rules.md>",
76
- "DESC_GENESEED": "<one-line description: interact with the deployed Geneseed harness — read files, status, doctor, diff>",
76
+ "DESC_GENESEED": "<one-line description: operate the deployed Geneseed harness — find installs and their settings, read files, status, doctor, diff, rebuild one setting on request>",
77
77
  "DESC_REVIEW_RESPONSE": "<one-line description: respond to review feedback — verify each point, apply or decline with reasons>",
78
78
  "LEX_I": "<themed title for Law I (Sealed Secrets)>",
79
79
  "LEX_II": "<themed title for Law II (One Intent, One Act)>",
package/themes/biker.json CHANGED
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing rule, or just something to remember? Then log the memory, or lean on the rule till it holds every corner before bolting it into user-rules.md.",
75
75
  "DESC_PROFILE": "Stamp the rider's plate into PROFILE.md — who they are, what they ride, how they like the road called; identity only, club rules bolt into user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the notes straight — weigh each call, then act on it or push back with reasons.",
78
78
  "LEX_I": "Keep It in the Saddlebag · Sealed Secrets",
79
79
  "LEX_II": "One Move per Corner · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing house rule, or just one for the notebook? Then log it, or run the rule through the replay from every angle before it goes on the board in user-rules.md.",
75
75
  "DESC_PROFILE": "Build the player profile in PROFILE.md — position, form, how they like the commentary pitched; identity only, the rulebook stays in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the scrutineer's notes straight — weigh each call, then act on it or push back with reasons.",
78
78
  "LEX_I": "Sealed Garage · Sealed Secrets",
79
79
  "LEX_II": "One Move per Corner · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing rule, or just something to keep on file? Then write the memory, or stress the rule till it holds in every sector before flashing it into user-rules.md.",
75
75
  "DESC_PROFILE": "Compile the user's ident into PROFILE.md — who they are, their rig, the bandwidth they want answers at; identity only, hard directives flash to user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Action the review clean — verify each flag, then patch it or push back with reasons.",
78
78
  "LEX_I": "Encrypt the Cache · Sealed Secrets",
79
79
  "LEX_II": "One Run, One Move · One Intent, One Act",
package/themes/gamer.json CHANGED
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing house rule, or just something to remember? Then save the memory, or test the rule against its worst case before binding it into user-rules.md.",
75
75
  "DESC_PROFILE": "Fill in the player card in PROFILE.md — main role, loadout, preferred difficulty; identity only, house rules go in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the review feedback like a coach's notes — verify each call, then apply it or push back with reasons.",
78
78
  "LEX_I": "No-Leak Run · Sealed Secrets",
79
79
  "LEX_II": "One Objective per Run · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — a standing edict, or a matter merely to be remembered? Then inscribe the memory, or try the edict against the case that would break it before it enters user-rules.md.",
75
75
  "DESC_PROFILE": "Inscribe the user's identity into PROFILE.md — grant audience, ask who they are and how they will to be served; identity only, edicts belong in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Answer the review with discipline — weigh each judgement, then heed it or refute it with cause.",
78
78
  "LEX_I": "Arcana Sigillata · Sealed Secrets",
79
79
  "LEX_II": "Unus Actus · One Intent, One Act",
package/themes/joker.json CHANGED
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing rule, or just something to remember? Then jot the memory, or make the rule survive its own worst night before it gets pinned into user-rules.md.",
75
75
  "DESC_PROFILE": "Sketch the user's bio for the playbill in PROFILE.md — who they are, how they work, how they like the act paced; identity only, house rules stay in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the notes straight — weigh each call, then act on it or push back with reasons.",
78
78
  "LEX_I": "Don't Leak the Punchline · Sealed Secrets",
79
79
  "LEX_II": "One Bit at a Time · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing rule, or merely something to remember? Then write the memory, or test the rule against the case that ruins it before adopting it in user-rules.md. Either way, entropy wins.",
75
75
  "DESC_PROFILE": "Record who the user is in PROFILE.md — role, habits, preferred register. They'll change their mind, but do ask. Identity only; rules go in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Answer the review with rigour — weigh each point, then heed it or refute it with reasons.",
78
78
  "LEX_I": "Keep It in the Memory Banks · Sealed Secrets",
79
79
  "LEX_II": "One Task, One Act · One Intent, One Act",
package/themes/mean.json CHANGED
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing rule, or just a fact to remember? Then write the memory, or break the rule against its worst case before it goes in user-rules.md. Not a dumping ground.",
75
75
  "DESC_PROFILE": "Get the user's profile down in PROFILE.md — who they are, how they work, how they want answers. Identity only; rules go in user-rules.md, obviously.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the review straight — weigh each point, then fix it or push back with reasons. Not feelings.",
78
78
  "LEX_I": "Keep Your Secrets Off the Floor · Sealed Secrets",
79
79
  "LEX_II": "One Job at a Time · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing order, or an entry for the log? Then file the memory, or test the order against the case that would break it before adopting it in user-rules.md.",
75
75
  "DESC_PROFILE": "File the commander's dossier in PROFILE.md — role, theatre, preferred briefing style; identity only, standing orders route to user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Action the review like an AAR — verify each point, then adopt it or push back with reasons.",
78
78
  "LEX_I": "Sealed Orders · Sealed Secrets",
79
79
  "LEX_II": "One Mission, One Move · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first whether the user wants a standing rule or a durable memory, then write the memory, or pressure-test the rule — reformulate it, break it against its worst case — before adopting it in user-rules.md.",
75
75
  "DESC_PROFILE": "Interview the user and draft or refresh PROFILE.md — who they are, how they work, how they like answers pitched; identity only, standing rules route to user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Respond to review feedback with rigour — verify each point, then apply it or decline it with reasons.",
78
78
  "LEX_I": "Sealed Secrets",
79
79
  "LEX_II": "One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — a standin' rule, or just summat to remember? Then log the memory, or run the rule aground on its worst case afore ye nail it into user-rules.md.",
75
75
  "DESC_PROFILE": "Chart yer captain in PROFILE.md — who they be, how they sail, how they like their bearings called; identity only, articles o' conduct go in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Answer the inspection straight — weigh each mark, then mend it or argue it with cause.",
78
78
  "LEX_I": "Sealed Orders · Sealed Secrets",
79
79
  "LEX_II": "One Course, One Tack · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing house rule, or just one for the notes? Then log the memory, or run the rule against the play that breaks it before it goes on the board in user-rules.md.",
75
75
  "DESC_PROFILE": "Write the scouting report in PROFILE.md — position, playing style, how they want the play called; identity only, team rules go on the board in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the review like game tape — verify each note, then adjust or push back with reasons.",
78
78
  "LEX_I": "Guard the Signs · Sealed Secrets",
79
79
  "LEX_II": "One Play at a Time · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — standing rule, or just something to remember? Then note it, or run the rule through the lap that breaks it before locking it into user-rules.md.",
75
75
  "DESC_PROFILE": "Set up the driver profile in PROFILE.md — seat, driving style, how they want the pit wall to talk; identity only, team orders go in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Take the notes straight — weigh each call, then act on it or push back with reasons.",
78
78
  "LEX_I": "Keep It in the Garage · Sealed Secrets",
79
79
  "LEX_II": "One Move per Corner · One Intent, One Act",
@@ -73,7 +73,7 @@
73
73
  "DESC_HERDR": "Drive herdr from inside it — split panes, spawn sibling agents, wait on output, read other panes.",
74
74
  "DESC_RULE": "Ask first — a standing rule, or a thing merely to be remembered? Then inscribe the memory, or prove the rule against the case that would unmake it before it enters user-rules.md.",
75
75
  "DESC_PROFILE": "Divine the user's nature into PROFILE.md — who they are, how they work, the register they favour; identity only, binding runes belong in user-rules.md.",
76
- "DESC_GENESEED": "Interact with the deployed Geneseed harness — locate the install, read its files, run status, doctor, and diff, and drive learn, context, and the local web UI.",
76
+ "DESC_GENESEED": "Operate the deployed Geneseed harness — find each install and its settings, read its files, run status, doctor and diff, and rebuild it with one setting changed when the user asks.",
77
77
  "DESC_REVIEW_RESPONSE": "Answer the scrying with rigour — weigh each finding, then heed it or refute it with cause.",
78
78
  "LEX_I": "Sealed Sigils · Sealed Secrets",
79
79
  "LEX_II": "One Intent, One Casting · One Intent, One Act",