geneseed 3.9.0 → 3.11.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 +89 -1
- package/DESIGN.md +1 -1
- package/README.md +52 -71
- package/SHIPPED.md +3 -3
- package/adapters/bob/README.md +18 -2
- package/adapters/claude-code/README.md +17 -12
- package/adapters/openclaude/README.md +2 -2
- package/adapters/opencode/README.md +4 -4
- package/adapters/opencode/plugins/geneseed-context.js +78 -8
- package/bin/build-driver.mjs +2 -0
- package/bin/geneseed-cli.mjs +17 -0
- package/bin/geneseed-hook.mjs +3 -1
- package/docs/README.md +42 -0
- package/docs/_groups.json +18 -0
- package/docs/candidate-hosts.md +12 -5
- package/docs/concepts/agents.md +44 -0
- package/docs/concepts/collaboration.md +62 -0
- package/docs/concepts/exclusions.md +55 -0
- package/docs/concepts/footprint.md +52 -0
- package/docs/concepts/foreman-mode.md +69 -0
- package/docs/concepts/hooks.md +101 -0
- package/docs/concepts/hosts.md +55 -0
- package/docs/concepts/lsp.md +50 -0
- package/docs/{web → concepts}/memory.md +2 -2
- package/docs/{web → concepts}/notebook.md +2 -2
- package/docs/concepts/rules.md +52 -0
- package/docs/concepts/skills.md +49 -0
- package/docs/concepts/themes.md +50 -0
- package/docs/extending.md +27 -21
- package/docs/guides/autostart.md +70 -0
- package/docs/guides/choose-your-setup.md +120 -0
- package/docs/guides/headless.md +22 -0
- package/docs/guides/install.md +161 -0
- package/docs/guides/mcp.md +195 -0
- package/docs/guides/migrate.md +41 -0
- package/docs/guides/project-context.md +87 -0
- package/docs/guides/run-anywhere.md +45 -0
- package/docs/guides/uninstall.md +51 -0
- package/docs/guides/upgrade.md +65 -0
- package/docs/guides/verify.md +65 -0
- package/docs/guides/wiki.md +69 -0
- package/docs/guides/worktree.md +47 -0
- package/docs/reference/about.md +7 -0
- package/docs/reference/cli.md +7 -0
- package/docs/reference/environment.md +99 -0
- package/docs/reference/glossary.md +33 -0
- package/docs/reference/opencode-plugins.md +131 -0
- package/docs/reference/troubleshooting.md +350 -0
- package/docs/token-footprint.md +26 -21
- package/docs/understand/a-day.md +77 -0
- package/docs/understand/enforced-vs-asked.md +64 -0
- package/docs/understand/harness.md +36 -0
- package/docs/understand/on-your-machine.md +76 -0
- package/docs/web-ui.md +2 -2
- package/harness.config.json +1 -1
- package/js/README.md +7 -6
- package/js/build/driver.mjs +26 -95
- package/js/build/emit-claude.mjs +76 -81
- package/js/build/generate.mjs +12 -2
- package/js/build/render.mjs +4 -0
- package/js/build/source.mjs +6 -0
- package/js/build/stubs.mjs +18 -2
- package/js/cli-table.json +6 -6
- package/js/hosts/hooks.mjs +86 -54
- package/js/hosts/hosts.mjs +5 -21
- package/js/hosts/installs.mjs +4 -6
- package/js/hosts/mcp.mjs +4 -14
- package/js/hosts/native.mjs +27 -50
- package/js/hosts/opencode.mjs +1 -1
- package/js/hosts/settings.mjs +17 -79
- package/js/inspect/checks-authoring.mjs +9 -4
- package/js/inspect/checks-repo.mjs +45 -1
- package/js/inspect/diff.mjs +11 -3
- package/js/inspect/doctor.mjs +4 -4
- package/js/inspect/excludes.mjs +0 -4
- package/js/inspect/inventory.mjs +1 -1
- package/js/inspect/registry.mjs +20 -3
- package/js/inspect/status.mjs +11 -6
- package/js/lib/node-floor.mjs +30 -0
- package/js/maintain/migrate.mjs +5 -5
- package/js/maintain/setup.mjs +112 -26
- package/js/maintain/uninstall.mjs +8 -42
- package/js/maintain/update.mjs +4 -15
- package/js/ui/cli.mjs +2 -2
- package/js/web/actions.mjs +4 -5
- package/js/web/api.mjs +7 -4
- package/js/web/daemon.mjs +52 -0
- package/js/web/docs.mjs +149 -65
- package/js/web/server.mjs +5 -2
- package/package.json +6 -5
- package/registry.json +7 -0
- package/src/AGENT.md.tmpl +73 -52
- package/src/laws/universal.md +3 -0
- package/src/ontology/universal.md +1 -1
- package/src/postures/mentor.md +1 -0
- package/src/skills/daydream/SKILL.md +10 -3
- package/src/skills/daydream/VENDOR.md +10 -2
- package/src/skills/daydream/instructions.md +2 -2
- package/src/skills/explain-changes/SKILL.md +1 -1
- package/src/skills/explain-changes/VENDOR.md +1 -1
- package/src/skills/geneseed.md +1 -1
- package/src/skills/learn-mode.md +89 -0
- package/src/skills/pipeline.md +2 -2
- package/src/skills/quiz.md +2 -1
- package/src/skills/react-view-transitions/SKILL.md +1 -1
- package/src/skills/react-view-transitions/VENDOR.md +7 -2
- package/src/skills/teach.md +2 -1
- package/src/skills/token-report/SKILL.md +2 -3
- package/src/skills/token-report/VENDOR.md +2 -3
- package/src/skills/token-report/scripts/token_report.mjs +7 -121
- package/src/skills/workflow.md +1 -1
- package/themes/_TEMPLATE.json +1 -0
- package/themes/biker.json +1 -0
- package/themes/commentator.json +1 -0
- package/themes/cyberpunk.json +1 -0
- package/themes/gamer.json +1 -0
- package/themes/imperial.json +1 -0
- package/themes/joker.json +1 -0
- package/themes/marvin.json +1 -0
- package/themes/mean.json +1 -0
- package/themes/military.json +1 -0
- package/themes/neutral.json +1 -0
- package/themes/pirate.json +1 -0
- package/themes/sports.json +1 -0
- package/themes/verstappen.json +1 -0
- package/themes/wizard.json +1 -0
- package/web/dist/assets/Activity-C52LEb-2.js +1 -0
- package/web/dist/assets/ActivityDetail-CjNLRvXg.js +1 -0
- package/web/dist/assets/Dashboard-B6_sSCHi.js +2 -0
- package/web/dist/assets/Docs-Dj7BmCSA.js +5 -0
- package/web/dist/assets/{GreenhouseView-Bq1QmaGO.js → GreenhouseView-BALwjQsA.js} +1 -1
- package/web/dist/assets/Installs-BbffDQm3.js +2 -0
- package/web/dist/assets/JournalView-JpAQ8Hqe.js +1 -0
- package/web/dist/assets/Laws-DK7eCWSm.js +3 -0
- package/web/dist/assets/Library-CoamHelE.js +1 -0
- package/web/dist/assets/{Markdown-CkFyfgNf.js → Markdown-qjM2_ofS.js} +5 -5
- package/web/dist/assets/{OperatorHudView-B-HVBqfY.js → OperatorHudView-DVx1HlBx.js} +1 -1
- package/web/dist/assets/Personal-eaXb1zcj.js +1 -0
- package/web/dist/assets/{Tabs-_pjUFIEI.js → Tabs-BmGtt8E2.js} +1 -1
- package/web/dist/assets/api-Dc8f3ca-.js +1 -0
- package/web/dist/assets/drawable-Du_PZrQj.js +1 -0
- package/web/dist/assets/index-Bz_KMRDH.css +1 -0
- package/web/dist/assets/index-CNFH7o55.js +2 -0
- package/web/dist/index.html +3 -2
- package/QUICKSTART.md +0 -50
- package/SETUP.md +0 -1183
- package/adapters/copilot/README.md +0 -105
- package/docs/web/_groups.json +0 -45
- package/docs/web/about.md +0 -6
- package/docs/web/adapters-claude-code.md +0 -8
- package/docs/web/adapters-opencode-loads.md +0 -8
- package/docs/web/adapters-opencode-spec.md +0 -8
- package/docs/web/adapters-opencode.md +0 -8
- package/docs/web/agents.md +0 -8
- package/docs/web/authoring.md +0 -11
- package/docs/web/autostart.md +0 -9
- package/docs/web/claude-hooks.md +0 -37
- package/docs/web/cli.md +0 -6
- package/docs/web/collaboration.md +0 -27
- package/docs/web/configure-wiki.md +0 -9
- package/docs/web/design.md +0 -7
- package/docs/web/env-knobs.md +0 -9
- package/docs/web/exclusions.md +0 -27
- package/docs/web/first-session.md +0 -28
- package/docs/web/footprint.md +0 -38
- package/docs/web/foreman-mode.md +0 -33
- package/docs/web/glossary.md +0 -6
- package/docs/web/harnesses.md +0 -30
- package/docs/web/headless.md +0 -9
- package/docs/web/ingest-docs.md +0 -9
- package/docs/web/install-paths.md +0 -9
- package/docs/web/install-quick.md +0 -35
- package/docs/web/lsp-overview.md +0 -37
- package/docs/web/mcp-claude-code.md +0 -10
- package/docs/web/mcp-filesystem.md +0 -9
- package/docs/web/mcp-gitlab.md +0 -9
- package/docs/web/mcp-markitdown.md +0 -9
- package/docs/web/mcp-overview.md +0 -34
- package/docs/web/mcp-trouble.md +0 -9
- package/docs/web/mcp-verify.md +0 -9
- package/docs/web/migrate.md +0 -39
- package/docs/web/model.md +0 -20
- package/docs/web/pipelines.md +0 -24
- package/docs/web/plugin-activity.md +0 -23
- package/docs/web/plugin-context.md +0 -26
- package/docs/web/plugin-guard.md +0 -24
- package/docs/web/plugin-learn.md +0 -27
- package/docs/web/plugin-notify.md +0 -24
- package/docs/web/plugin-ponytail.md +0 -23
- package/docs/web/plugin-setup.md +0 -7
- package/docs/web/plugin-workflow.md +0 -25
- package/docs/web/plugins.md +0 -17
- package/docs/web/project-context.md +0 -9
- package/docs/web/rules.md +0 -30
- package/docs/web/run-anywhere.md +0 -9
- package/docs/web/self-improve.md +0 -8
- package/docs/web/setup-choices.md +0 -64
- package/docs/web/skills.md +0 -8
- package/docs/web/themes-author.md +0 -20
- package/docs/web/themes.md +0 -9
- package/docs/web/token-footprint.md +0 -7
- package/docs/web/trouble.md +0 -38
- package/docs/web/upgrade.md +0 -9
- package/docs/web/verify.md +0 -30
- package/docs/web/wiki.md +0 -7
- package/docs/web/worktree.md +0 -10
- package/docs/wiki.md +0 -43
- package/web/dist/assets/Activity-DAzV-qQj.js +0 -1
- package/web/dist/assets/ActivityDetail-CwEwMtKl.js +0 -1
- package/web/dist/assets/Dashboard-C2ELBW-X.js +0 -2
- package/web/dist/assets/Docs-iZrvQP8J.js +0 -2
- package/web/dist/assets/Installs-BiqR8xdO.js +0 -2
- package/web/dist/assets/JournalView-6wilG5Zd.js +0 -1
- package/web/dist/assets/Laws-D8YXD_XE.js +0 -3
- package/web/dist/assets/Library-DwuTZ2-L.js +0 -1
- package/web/dist/assets/Personal-BbUTmZQR.js +0 -1
- package/web/dist/assets/drawable-CoIulEH2.js +0 -1
- package/web/dist/assets/index-BMwSp8BP.js +0 -2
- package/web/dist/assets/index-CDPDk2vj.css +0 -1
|
@@ -56,6 +56,7 @@ import { promises as fs } from "node:fs"
|
|
|
56
56
|
import * as path from "node:path"
|
|
57
57
|
import { fileURLToPath } from "node:url"
|
|
58
58
|
import { homedir } from "node:os"
|
|
59
|
+
import { createHash } from "node:crypto"
|
|
59
60
|
|
|
60
61
|
const MARKER = "<!-- geneseed-context:v2 -->"
|
|
61
62
|
const PLUGIN_DIR = path.dirname(fileURLToPath(import.meta.url))
|
|
@@ -156,6 +157,49 @@ const EXCLUDE_DIRS = new Set([
|
|
|
156
157
|
async function isFile(p) { try { return (await fs.stat(p)).isFile() } catch { return false } }
|
|
157
158
|
async function isDir(p) { try { return (await fs.stat(p)).isDirectory() } catch { return false } }
|
|
158
159
|
|
|
160
|
+
// ---- session files (the harness's own) --------------------------------------
|
|
161
|
+
// The files AGENT.md names for session start, relative to the HARNESS dir — the dir that
|
|
162
|
+
// holds the installed AGENT.md: the repo root for a project install, the config dir for a
|
|
163
|
+
// global one. Same list and seed hashes as SESSION_FILES/SEED_SHA256 in js/hosts/hooks.mjs;
|
|
164
|
+
// tests/unit/claude.test.mjs gates both copies against SESSION_SEEDS in js/build/stubs.mjs.
|
|
165
|
+
// context.json is not here: it is a manifest, honoured by resolveSource. wiki.jsonc is not
|
|
166
|
+
// here either: the MACHINE WIKI block below already renders it in full.
|
|
167
|
+
const SESSION_FILES = ["user-rules.md", "PROFILE.md", "memory/MEMORY.md", "anamnesis/MEMORY.md",
|
|
168
|
+
"notebook/NOTEBOOK.md"]
|
|
169
|
+
const SEED_SHA256 = new Set([
|
|
170
|
+
"5c2e92fb1acde041e02d9ebf158460d8ff7a07cbc2b447859631604610130721", // user-rules.md
|
|
171
|
+
"29e012c3c4349ea62a9082cbd04bb25599a0ec280d62c33f6e10742809471816", // PROFILE.md
|
|
172
|
+
"cccc917c34e6b990e821620bdb4739090151885ab71b6e85046f30a3b71fa5e8", // wiki.jsonc
|
|
173
|
+
"99c786049c260f6baf7aec68a5c0f59907861afe9b867da009440613bdddb907", // MEMORY.md
|
|
174
|
+
"9acb5c9d9cb5dac572104480f05b48cc144e676869bd60e86d8a15b1f6308184", // NOTEBOOK.md
|
|
175
|
+
])
|
|
176
|
+
|
|
177
|
+
// $GENESEED_HARNESS when set, else the first of <plugin dir>/.. (global: the config dir) and
|
|
178
|
+
// <plugin dir>/../.. (project: .opencode/plugins -> the repo root) that holds AGENT.md.
|
|
179
|
+
async function harnessDir() {
|
|
180
|
+
if (process.env.GENESEED_HARNESS && (await isDir(process.env.GENESEED_HARNESS))) {
|
|
181
|
+
return process.env.GENESEED_HARNESS
|
|
182
|
+
}
|
|
183
|
+
for (const d of [path.resolve(PLUGIN_DIR, ".."), path.resolve(PLUGIN_DIR, "..", "..")]) {
|
|
184
|
+
if (await isFile(path.join(d, "AGENT.md"))) return d
|
|
185
|
+
}
|
|
186
|
+
return null
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Session files present under the harness dir and changed from their seed: [{ rel, abs, text }].
|
|
190
|
+
async function sessionFiles(dir) {
|
|
191
|
+
const found = []
|
|
192
|
+
if (!dir) return found
|
|
193
|
+
for (const rel of SESSION_FILES) {
|
|
194
|
+
const abs = path.join(dir, rel)
|
|
195
|
+
let text
|
|
196
|
+
try { text = (await fs.readFile(abs, "utf8")).replace(/\r\n/g, "\n") } catch { continue }
|
|
197
|
+
if (SEED_SHA256.has(createHash("sha256").update(text).digest("hex"))) continue
|
|
198
|
+
found.push({ rel, abs, text: text.replace(/\n+$/, "") })
|
|
199
|
+
}
|
|
200
|
+
return found
|
|
201
|
+
}
|
|
202
|
+
|
|
159
203
|
async function readJson(p) {
|
|
160
204
|
try { return JSON.parse(await fs.readFile(p, "utf8")) } catch { return null }
|
|
161
205
|
}
|
|
@@ -474,11 +518,13 @@ async function fromManifest(manifestFile, root) {
|
|
|
474
518
|
return { eager: eager.sort(byRel), lazy: lazy.sort(byRel) }
|
|
475
519
|
}
|
|
476
520
|
|
|
477
|
-
async function resolveSource(root) {
|
|
521
|
+
async function resolveSource(root, harness = null) {
|
|
478
522
|
const explicit = process.env.GENESEED_CONTEXT
|
|
479
523
|
if (explicit && (await isFile(explicit))) return { mode: "manifest", file: explicit }
|
|
480
|
-
|
|
481
|
-
|
|
524
|
+
// The harness dir last: a repo's own manifest outranks the one seeded beside the install.
|
|
525
|
+
const cands = [path.join(root, ".harness", "context.json"), path.join(root, "context.json")]
|
|
526
|
+
if (harness) cands.push(path.join(harness, "context.json"))
|
|
527
|
+
for (const p of cands) {
|
|
482
528
|
if (await isFile(p)) return { mode: "manifest", file: p }
|
|
483
529
|
}
|
|
484
530
|
return { mode: "discover" }
|
|
@@ -494,8 +540,12 @@ async function resolveSource(root) {
|
|
|
494
540
|
async function resolveWikiFile() {
|
|
495
541
|
const explicit = process.env.GENESEED_WIKI
|
|
496
542
|
if (explicit && (await isFile(explicit))) return explicit
|
|
543
|
+
// The harness dir (which honours $GENESEED_HARNESS) first: on a PROJECT install the plugin
|
|
544
|
+
// sits in .opencode/plugins, so <plugin dir>/.. is .opencode, not the dir the seed landed in.
|
|
545
|
+
// <plugin dir>/.. stays as the fallback for an install without an AGENT.md.
|
|
497
546
|
const bases = []
|
|
498
|
-
|
|
547
|
+
const harness = await harnessDir()
|
|
548
|
+
if (harness) bases.push(harness)
|
|
499
549
|
bases.push(path.resolve(PLUGIN_DIR, ".."))
|
|
500
550
|
for (const base of bases) {
|
|
501
551
|
// wiki.json is the legacy name from earlier seeds — still honoured.
|
|
@@ -652,9 +702,27 @@ async function renderSet(out, { eager, lazy }, state) {
|
|
|
652
702
|
state.lazy += lazyLines.length
|
|
653
703
|
}
|
|
654
704
|
|
|
655
|
-
async function buildBlock(sets, wikis = [], commands = []) {
|
|
705
|
+
async function buildBlock(sets, wikis = [], commands = [], session = []) {
|
|
656
706
|
const state = { spent: 0, injected: 0, lazy: 0, headingsRead: 0 }
|
|
657
707
|
|
|
708
|
+
// A session file discovery also found (user-rules.md at the root of a project install,
|
|
709
|
+
// whose harness dir IS the repo root) is injected once, in the session block.
|
|
710
|
+
const seen = new Set(session.map((s) => path.resolve(s.abs)))
|
|
711
|
+
const fresh = (x) => !seen.has(path.resolve(x.abs))
|
|
712
|
+
sets = { eager: sets.eager.filter(fresh), lazy: sets.lazy.filter(fresh) }
|
|
713
|
+
const ses = []
|
|
714
|
+
for (const s of session) {
|
|
715
|
+
const size = Buffer.byteLength(s.text, "utf8")
|
|
716
|
+
ses.push(`----- ${s.rel} -----`)
|
|
717
|
+
if (size > EAGER_FILE_KB * 1024) {
|
|
718
|
+
ses.push(`[demoted: ${s.rel} exceeded ${EAGER_FILE_KB} KB — read ${s.abs} on demand]`, "")
|
|
719
|
+
continue
|
|
720
|
+
}
|
|
721
|
+
ses.push(s.text, "")
|
|
722
|
+
state.spent += size
|
|
723
|
+
state.injected++
|
|
724
|
+
}
|
|
725
|
+
|
|
658
726
|
const proj = []
|
|
659
727
|
await renderSet(proj, sets, state)
|
|
660
728
|
|
|
@@ -675,8 +743,9 @@ async function buildBlock(sets, wikis = [], commands = []) {
|
|
|
675
743
|
if (w.truncated) wik.push(` [+${w.truncated} more notes in this wiki — explore its folders on demand]`, "")
|
|
676
744
|
}
|
|
677
745
|
|
|
678
|
-
if (!proj.length && !wik.length) return null
|
|
746
|
+
if (!ses.length && !proj.length && !wik.length) return null
|
|
679
747
|
const out = [MARKER]
|
|
748
|
+
if (ses.length) out.push("=== SESSION FILES — your harness files, injected at session start (untouched seeds skipped) ===", "", ...ses)
|
|
680
749
|
if (proj.length) out.push("=== PROJECT CONTEXT — binding for this repo ===", "", ...proj)
|
|
681
750
|
if (wik.length) out.push("=== MACHINE WIKI — the user's knowledge base, binding per AGENT.md §8 ===", "", ...wik)
|
|
682
751
|
return { text: out.join("\n"), injected: state.injected, lazy: state.lazy, kb: kb(state.spent) }
|
|
@@ -686,13 +755,14 @@ async function buildBlock(sets, wikis = [], commands = []) {
|
|
|
686
755
|
// and render the injection block — shared by the session.created injection and the
|
|
687
756
|
// compaction hook (the transform path reuses it via cachedBlockText).
|
|
688
757
|
async function resolveBlock(root) {
|
|
689
|
-
const
|
|
758
|
+
const harness = await harnessDir()
|
|
759
|
+
const src = await resolveSource(root, harness)
|
|
690
760
|
const sets = src.mode === "manifest"
|
|
691
761
|
? await fromManifest(src.file, root)
|
|
692
762
|
: await discover(root)
|
|
693
763
|
const wikis = await wikiSets()
|
|
694
764
|
const commands = await discoverCommands(root)
|
|
695
|
-
return { block: await buildBlock(sets, wikis, commands), src }
|
|
765
|
+
return { block: await buildBlock(sets, wikis, commands, await sessionFiles(harness)), src }
|
|
696
766
|
}
|
|
697
767
|
|
|
698
768
|
// Per-process cache of the rendered block text for the transform path (root is fixed
|
package/bin/build-driver.mjs
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* which the CLI verbs import too; this file only hands it argv. Keeping the entry this thin is
|
|
5
5
|
* what lets a `js/` module import the driver without running it on the importer's argv.
|
|
6
6
|
*/
|
|
7
|
+
// FIRST, before anything it could fail to run: an old Node gets one sentence, not a stack trace.
|
|
8
|
+
import '../js/lib/node-floor.mjs';
|
|
7
9
|
import { main } from '../js/build/driver.mjs';
|
|
8
10
|
|
|
9
11
|
process.exitCode = main(process.argv.slice(2));
|
package/bin/geneseed-cli.mjs
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
// table below now holds one LOADER per row (`() => import(…).then(m => m.cmdX)`), so a verb
|
|
55
55
|
// loads its slice of the tree and no other verb's. The spawn allow-list gate still sees the
|
|
56
56
|
// whole graph: `tests/unit/hook_cli.test.mjs`'s `importClosure` follows both import spellings.
|
|
57
|
+
// FIRST, before anything it could fail to run: an old Node gets one sentence, not a stack trace.
|
|
58
|
+
import '../js/lib/node-floor.mjs';
|
|
57
59
|
import { cliSpec, printHelp, printVerbList } from '../js/ui/cli.mjs';
|
|
58
60
|
import { parseIntStrict } from '../js/lib/text.mjs';
|
|
59
61
|
import { printErr } from '../js/lib/fs.mjs';
|
|
@@ -289,6 +291,21 @@ async function main(argv) {
|
|
|
289
291
|
validate: "check the source tree without emitting (the generator's --validate-only)",
|
|
290
292
|
});
|
|
291
293
|
}
|
|
294
|
+
// A DEAD HOOK SHIM, SAID ON EVERY RUN. The shim is machine-wide, so one stale write turns off
|
|
295
|
+
// every hook of every Claude-shaped install, and the hooks fail into a channel nobody reads —
|
|
296
|
+
// `doctor` was the only thing that looked. stderr, so no verb's stdout moves; skipped for help
|
|
297
|
+
// and for scripted callers that opt out. Not in `bin/geneseed-hook.mjs`: a dead shim means
|
|
298
|
+
// that binary is never reached, and its import graph is paid on every tool call.
|
|
299
|
+
if (process.env.GENESEED_NO_SHIM_CHECK !== '1' && verb !== 'help'
|
|
300
|
+
&& !argv.some((t) => t === '-h' || t === '--help')) {
|
|
301
|
+
const { shimDead } = await import('../js/hosts/settings.mjs');
|
|
302
|
+
const dead = shimDead();
|
|
303
|
+
if (dead.length) {
|
|
304
|
+
printErr(`[geneseed] ⚠ hooks are off on this machine: the hook shim points at `
|
|
305
|
+
+ `${dead.join(', ')}, which no longer exists. Fix: geneseed rebuild-all
|
|
306
|
+
`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
292
309
|
// `validate` — the generator's `--validate-only`, and the one verb this entry answers that is NOT
|
|
293
310
|
// in the table above. It is dispatched here, before the lookup, for a reason that is a
|
|
294
311
|
// property of the gates rather than a preference:
|
package/bin/geneseed-hook.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* The hook entry point — a Node twin of `rituals/harness.py` for the verbs the emitted
|
|
4
|
-
* `settings.json` actually invokes (four from the reference, plus `tool-gate` for
|
|
4
|
+
* `settings.json` actually invokes (four from the reference, plus `tool-gate` for Bob).
|
|
5
5
|
*
|
|
6
6
|
* WHY IT IS A SECOND BINARY AND NOT A SUBCOMMAND OF `bin/build-driver.mjs`. Three reasons,
|
|
7
7
|
* and each alone would be enough:
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
* every Geneseed hook returns 0 and signals through stdout — so "did nothing" and "worked"
|
|
38
38
|
* are the same observation.
|
|
39
39
|
*/
|
|
40
|
+
// FIRST, before anything it could fail to run: an old Node gets one sentence, not a stack trace.
|
|
41
|
+
import '../js/lib/node-floor.mjs';
|
|
40
42
|
import { cmdContext, cmdGitGate, cmdRuleGate, cmdToolGate, cmdLearn } from '../js/hosts/hooks.mjs';
|
|
41
43
|
// Not a new module on the hot path: `js/hosts/hooks.mjs` above already imports
|
|
42
44
|
// `js/lib/fs.mjs`, so this edge names a file the process has already loaded.
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Geneseed documentation
|
|
2
|
+
|
|
3
|
+
[← Back to README](../README.md)
|
|
4
|
+
|
|
5
|
+
**New to agent harnesses?** Read **Understand** first — four short pages, about ten minutes, and every other page assumes them. The same pages open the **Docs** tab of the web console (`geneseed web`), which adds an interactive map of your own install and filters host-specific passages to the tool you use.
|
|
6
|
+
|
|
7
|
+
## 1 · Understand
|
|
8
|
+
|
|
9
|
+
1. **[What a harness is](understand/harness.md)** — git hooks + CI + a runbook, but for your AI agent.
|
|
10
|
+
2. **[What lands on your machine](understand/on-your-machine.md)** — every file and hook an install writes, what it does for you, what it costs, how to turn it off.
|
|
11
|
+
3. **[A day with the harness](understand/a-day.md)** — the moments you will actually meet: a push that asks first, a skill, a delegation, a memory.
|
|
12
|
+
4. **[Enforced vs. asked](understand/enforced-vs-asked.md)** — what is guaranteed by code, and what the model is only asked to do.
|
|
13
|
+
|
|
14
|
+
## 2 · Guides
|
|
15
|
+
|
|
16
|
+
| Guide | When |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| [Install](guides/install.md) | First time — npx, a clone, or a specific host |
|
|
19
|
+
| [Choose your setup](guides/choose-your-setup.md) | Theme, doctrine packs, one rule at a time, footprint, posture, mode |
|
|
20
|
+
| [Verify it works](guides/verify.md) | Right after installing, or when something feels off |
|
|
21
|
+
| [Upgrade](guides/upgrade.md) | Getting a new version onto every install |
|
|
22
|
+
| [Uninstall](guides/uninstall.md) | Removing an install — and what stays behind |
|
|
23
|
+
| [Project context](guides/project-context.md) | Choosing which of a repo's docs the agent loads |
|
|
24
|
+
| [Connect your wiki](guides/wiki.md) | Giving the agent your own notes, machine-wide |
|
|
25
|
+
| [MCP servers](guides/mcp.md) | MarkItDown, GitLab, Filesystem — and reading non-markdown docs |
|
|
26
|
+
| [Run geneseed from anywhere](guides/run-anywhere.md) | Putting the CLI on your PATH from a clone |
|
|
27
|
+
| [Start the web console at login](guides/autostart.md) | Keeping the console running |
|
|
28
|
+
| [Run in CI / headless](guides/headless.md) | OpenCode without a terminal |
|
|
29
|
+
| [Add git-worktree isolation](guides/worktree.md) | OpenCode, optional third-party add-on |
|
|
30
|
+
| [Migrate from a clone to npm](guides/migrate.md) | Moving an old clone install to the npm package |
|
|
31
|
+
|
|
32
|
+
## 3 · Concepts
|
|
33
|
+
|
|
34
|
+
[Hosts](concepts/hosts.md) · [Rules](concepts/rules.md) · [Agents](concepts/agents.md) · [Skills](concepts/skills.md) · [Hooks](concepts/hooks.md) · [Memory](concepts/memory.md) · [Notebook](concepts/notebook.md) · [Footprint](concepts/footprint.md) · [Collaboration](concepts/collaboration.md) · [Foreman mode](concepts/foreman-mode.md) · [Exclusions](concepts/exclusions.md) · [Themes](concepts/themes.md) · [Code intelligence (LSP)](concepts/lsp.md)
|
|
35
|
+
|
|
36
|
+
## 4 · Reference
|
|
37
|
+
|
|
38
|
+
[CLI](reference/cli.md) · [Environment variables](reference/environment.md) · [Glossary](reference/glossary.md) · [Troubleshooting](reference/troubleshooting.md) (by symptom) · [OpenCode plugins](reference/opencode-plugins.md) · [About](reference/about.md)
|
|
39
|
+
|
|
40
|
+
## For contributors
|
|
41
|
+
|
|
42
|
+
[Extending Geneseed](extending.md) — what each kind of addition costs · [DESIGN.md](../DESIGN.md) · [Design history](design-history.md) · [Token footprint](token-footprint.md) · [Web console internals](web-ui.md) · [OpenCode plugin wiring](opencode-plugin-setup.md) · [Candidate hosts](candidate-hosts.md) · adapters: [OpenCode](../adapters/opencode/README.md), [Claude Code](../adapters/claude-code/README.md), [Bob](../adapters/bob/README.md), [OpenClaude](../adapters/openclaude/README.md)
|
package/docs/candidate-hosts.md
CHANGED
|
@@ -38,8 +38,7 @@ current host gets. Skills are the largest surface by file count and they cost no
|
|
|
38
38
|
Claude's, and `permissionDecision: "ask"` exists. The Claude engine with `host: "codex"`
|
|
39
39
|
covers instructions (`AGENTS.md`), skills (`.agents/skills`) and the hook verbs
|
|
40
40
|
unchanged; the only new code is the carrier writer (a `hooks.json` merge or a TOML
|
|
41
|
-
table) and the config-dir resolver (`~/.codex`, `$CODEX_HOME`).
|
|
42
|
-
port minus the dialect work.
|
|
41
|
+
table) and the config-dir resolver (`~/.codex`, `$CODEX_HOME`).
|
|
43
42
|
|
|
44
43
|
- **Gemini CLI — Claude's groups, Gemini's names.** The hook groups are Claude's
|
|
45
44
|
`event → [{matcher, hooks}]` and the payload fields are Claude's, but the events are
|
|
@@ -54,7 +53,7 @@ current host gets. Skills are the largest surface by file count and they cost no
|
|
|
54
53
|
- **Cursor — a third verdict dialect.** `AGENTS.md` and `.agents/skills` are free; hooks
|
|
55
54
|
are `hooks.json` with a `{command}` list per event and a `permission: allow|deny`
|
|
56
55
|
verdict, `additional_context` in snake_case for `sessionStart`. Same block-or-warn stance
|
|
57
|
-
as
|
|
56
|
+
as Bob, one more output spelling in `js/hosts/hooks.mjs`, one more carrier writer.
|
|
58
57
|
Cursor also reads `.claude/skills/`, so a Claude project install already gives a Cursor
|
|
59
58
|
user the skills.
|
|
60
59
|
|
|
@@ -64,8 +63,16 @@ If a fifth host is wanted, Codex first: it reuses the most and it is the only ca
|
|
|
64
63
|
where the gates can *ask* rather than block. Before any of them, a `--emit agents` for
|
|
65
64
|
the shared `.agents/skills/` folder would give Codex, Cursor and Gemini users the whole
|
|
66
65
|
skill catalogue for the price of one directory name, with no host-specific code at all.
|
|
67
|
-
A Gemini host would be the
|
|
68
|
-
ask
|
|
66
|
+
A Gemini host would be the third verdict spelling in `js/hosts/hooks.mjs` (after Claude's
|
|
67
|
+
ask and Bob's exit code 2), plus a resolver and a carrier.
|
|
68
|
+
|
|
69
|
+
## Evaluated, dropped
|
|
70
|
+
|
|
71
|
+
- **GitHub Copilot** — shipped as a host through 3.9.0, removed in 3.10.0. Dropped for lack
|
|
72
|
+
of support: its hooks were never verified live, its `postToolUse` output does not reach
|
|
73
|
+
the model, and it shared no cross-tool surface with the other hosts (camelCase payloads,
|
|
74
|
+
matcherless hook entries, its own agent dialect and carrier), so every feature needed a
|
|
75
|
+
Copilot-only decision.
|
|
69
76
|
|
|
70
77
|
## Not verified
|
|
71
78
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
group: concepts
|
|
3
|
+
order: 3
|
|
4
|
+
title: "Agents"
|
|
5
|
+
kind: "concept"
|
|
6
|
+
link: {"hash": "#/section/agents", "label": "Browse the catalog →"}
|
|
7
|
+
---
|
|
8
|
+
An **agent** is a specialist the main session can hand a piece of work to. Each one is a markdown file with its own instructions, installed where your host looks for subagents (`agents/` in the install). It runs in its own context and returns a result, so its reading and searching does not fill your conversation.
|
|
9
|
+
|
|
10
|
+
> **You already know this:** handing a ticket to a colleague. You do not explain how to review code to the reviewer — you say what to review, and they come back with findings.
|
|
11
|
+
|
|
12
|
+
{N_AGENTS} agents ship, in two groups.
|
|
13
|
+
|
|
14
|
+
### The specialists
|
|
15
|
+
|
|
16
|
+
| Agent | What it does |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `explorer` | reads and searches widely in a throwaway context, returns only distilled findings |
|
|
19
|
+
| `researcher` | searches the open web, cross-checks every claim against two sources, returns sourced findings |
|
|
20
|
+
| `architect` | produces a design or implementation plan before code is written |
|
|
21
|
+
| `developer` | implements a scoped change in an isolated worktree, self-checked, ready for the tester |
|
|
22
|
+
| `tester` | writes, runs and diagnoses tests |
|
|
23
|
+
| `reviewer` | reviews a change for correctness and quality before it merges |
|
|
24
|
+
| `security` | audits changes that touch the security surface |
|
|
25
|
+
| `docs` | writes and updates user-facing documentation after code lands |
|
|
26
|
+
|
|
27
|
+
### The council
|
|
28
|
+
|
|
29
|
+
Ten read-only debaters — `advocate`, `skeptic`, `pragmatist`, `steward`, `operator`, `visionary`, `framer`, `empiricist`, `historian`, `user-advocate` — each arguing one fixed stance. You do not call them one by one: the **council** [skill](skills.md) seats the ones that actually disagree on your question, runs bounded rounds of debate, and hands you a verdict with the strongest dissent kept verbatim. The council advises; it writes no code.
|
|
30
|
+
|
|
31
|
+
### Specialists, not folder owners
|
|
32
|
+
|
|
33
|
+
An agent is picked by **what the work needs**, not by **where the file lives**. There is no "agent for `src/api/`": a change to any folder goes to the `developer`, and its review to the `reviewer`. You can name one ("have the reviewer look at this"), or let the main session route the request to the right specialist itself.
|
|
34
|
+
|
|
35
|
+
In [foreman mode](foreman-mode.md) the session chains several of them into a pipeline — explorer, developer and tester, plus whatever specialists the task needs.
|
|
36
|
+
|
|
37
|
+
### Agents learn too
|
|
38
|
+
|
|
39
|
+
When a subagent finishes, the learn step can record a lesson for that agent alone, in `memory/agents/<name>.md` — one bullet per lesson, capped so it never grows unbounded. The next time that agent runs, it starts with what it learned. See [Memory](memory.md). (Not on Bob, which has no subagent-finished event.)
|
|
40
|
+
|
|
41
|
+
<!--harness:opencode-->
|
|
42
|
+
*(OpenCode only)*
|
|
43
|
+
OpenCode also has a **primary agent** — the one your session talks to directly. Geneseed installs it alongside the specialists; the specialists are subagents it delegates to.
|
|
44
|
+
<!--/harness-->
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
group: concepts
|
|
3
|
+
order: 9
|
|
4
|
+
title: "Collaboration"
|
|
5
|
+
kind: "concept"
|
|
6
|
+
---
|
|
7
|
+
Beside the [rules](rules.md), a few pieces shape *how* the agent works with you: the register it speaks in, the contract between you, how firmly a memory binds, and who you are. All of them are plain text in the install, so they reach every host unchanged.
|
|
8
|
+
|
|
9
|
+
> **You already know this:** a team's working agreement. The coding standards say what the code must look like; the working agreement says how people treat each other's reviews, questions and decisions.
|
|
10
|
+
|
|
11
|
+
### Posture — the relationship
|
|
12
|
+
|
|
13
|
+
A **posture** is the register the agent works in. You choose it at setup and it is fixed at build time, so it does not drift back toward plain execution halfway through a session.
|
|
14
|
+
|
|
15
|
+
| Posture | For |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **peer** (default) | a candid equal — dense, challenges you, no flattery |
|
|
18
|
+
| **mentor** | leaves you more capable — explains the why, checks understanding |
|
|
19
|
+
| **expert** | maximum density for a fluent user — terse, no basics |
|
|
20
|
+
| **assistant** | precise execution, low initiative — you steer |
|
|
21
|
+
| **artisan** | a peer with toolsmith reflexes — terminal-first, automates repetition |
|
|
22
|
+
|
|
23
|
+
Posture is separate from the [theme](themes.md): the theme is the *voice*, the posture is the *relationship*. Every posture obeys the same rules; what shifts is how firmly and how loudly the agent voices disagreement. Change it with `geneseed setup`, the web console's Harness page, or:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
geneseed build --emit claude-global --posture mentor
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
How the agent *executes* work — itself, or through a crew — is the separate **mode** setting: see [Foreman mode](foreman-mode.md).
|
|
30
|
+
|
|
31
|
+
### The Pact — a two-way contract
|
|
32
|
+
|
|
33
|
+
The **Pact** is stated in the first section of the Ethos, the layer that is always on, so it holds in every task and every repository. It ranks three duties for the agent, each yielding only to the one above:
|
|
34
|
+
|
|
35
|
+
1. protect you — and the future maintainer of your code;
|
|
36
|
+
2. serve your intent;
|
|
37
|
+
3. keep its own honesty.
|
|
38
|
+
|
|
39
|
+
Unusually, it also says what *you* owe back:
|
|
40
|
+
|
|
41
|
+
- **Don't punish candour.** When the agent contradicts you with evidence, flags a risk or admits a doubt, that is the Pact working. Penalising it teaches the agent to flatter.
|
|
42
|
+
- **Give the context up front.** The agent cannot weigh what it was not told.
|
|
43
|
+
- **Decide when shown a fork.** An unmade decision stalls work as surely as a wrong one.
|
|
44
|
+
|
|
45
|
+
Your half is not enforced against you. The agent's half binds it.
|
|
46
|
+
|
|
47
|
+
### Memory force — how firmly a memory binds
|
|
48
|
+
|
|
49
|
+
A [memory](memory.md) can carry an optional `force`:
|
|
50
|
+
|
|
51
|
+
| Force | Meaning |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| **constraint** | imposed; not the agent's to relax |
|
|
54
|
+
| **choice** | revisable, with your consent |
|
|
55
|
+
| **conviction** | revisable on evidence |
|
|
56
|
+
| **tempered** | a constraint that was relaxed |
|
|
57
|
+
|
|
58
|
+
When new evidence contradicts a memory with a force, the agent must revise it in the open rather than quietly drop it.
|
|
59
|
+
|
|
60
|
+
### Profile — who you are
|
|
61
|
+
|
|
62
|
+
`PROFILE.md` sits beside the instructions file, is seeded once and is never overwritten. It holds your role, habits and how you like answers pitched. It colours how the agent works but never binds — it is last in [precedence](rules.md). Edit the file directly, use the Profile tab in the web console, or let the `profile` [skill](skills.md) interview you and draft it; it writes only with your consent, and routes anything that is really a standing rule to `user-rules.md`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
group: concepts
|
|
3
|
+
order: 11
|
|
4
|
+
title: "Exclusions"
|
|
5
|
+
kind: "concept"
|
|
6
|
+
link: {"hash": "#/harness", "label": "Manage in Harness →"}
|
|
7
|
+
---
|
|
8
|
+
Geneseed has two different ways to switch something off, and they work at different scales:
|
|
9
|
+
|
|
10
|
+
| | Sovereign repo | Per-rule exclusion |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| **Switches off** | the whole global install, inside one folder | one doctrine rule, everywhere the install applies |
|
|
13
|
+
| **Scope** | a folder and everything under it | the install |
|
|
14
|
+
| **Applies to** | **global** installs only | any install |
|
|
15
|
+
| **Set with** | `geneseed exclude add <path>` | `--exclude-rules` at build time |
|
|
16
|
+
| **Takes effect** | on the next tool call, no rebuild | on rebuild |
|
|
17
|
+
|
|
18
|
+
> **You already know this:** `.gitignore` versus disabling one lint rule. One makes a tool ignore a whole folder; the other keeps the tool running everywhere with one check turned off.
|
|
19
|
+
|
|
20
|
+
### Sovereign repos — whole-repo dormancy
|
|
21
|
+
|
|
22
|
+
A **sovereign repo** is a folder where every *global* Geneseed install goes fully dormant. The usual case is a repo that ships its own complete agent setup — its own rules, hooks and memory — where a global harness layered on top would bring conflicting instructions and wasted tokens.
|
|
23
|
+
|
|
24
|
+
It is all-or-nothing. It does not trim which rules apply or which skills load; the global harness simply never engages inside that folder. A **per-repo** Geneseed install in the same folder is unaffected — exclusions only ever silence global installs.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
geneseed exclude add ~/code/my-vault
|
|
28
|
+
geneseed exclude list
|
|
29
|
+
geneseed exclude remove ~/code/my-vault
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
One command updates every global install on the machine. Each keeps the list in its own `excludes.json`, and every hook and plugin reads it on each call, so a change takes effect at once.
|
|
33
|
+
|
|
34
|
+
What "dormant" means per host:
|
|
35
|
+
|
|
36
|
+
- **Claude Code** — every hook exits silently, and the global `CLAUDE.md` is suppressed natively through `claudeMdExcludes` in the repo's `.claude/settings.local.json`.
|
|
37
|
+
- **OpenClaude** — the same, in the repo's `.openclaude/settings.local.json`.
|
|
38
|
+
- **Bob** — every hook exits silently, and a stub `.bob/rules/geneseed.md` in the repo shadows the global rules file. A hand-written stub already there is never overwritten.
|
|
39
|
+
- **OpenCode** — Geneseed's plugins stand down.
|
|
40
|
+
|
|
41
|
+
`geneseed exclude remove` undoes all of it.
|
|
42
|
+
|
|
43
|
+
**Limits.** Globally installed skills and agents stay *listed* by the host — no host offers a per-repo switch for them. And a global install created *after* you added exclusions starts with an empty list: run `geneseed exclude add` again (`geneseed exclude list` flags installs whose lists differ).
|
|
44
|
+
|
|
45
|
+
The web console has the same controls in the **Excluded folders** card on the Harness page, shown once a global install exists.
|
|
46
|
+
|
|
47
|
+
### Per-rule exclusion — one rule off
|
|
48
|
+
|
|
49
|
+
The finer switch removes a single doctrine rule from an install while keeping the rest of its pack:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
geneseed build --emit claude-global --exclude-rules "process 7"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The install records it (`Excluded rules: process 7` beside its pack list) and every rebuild and upgrade keeps it. The always-on Rules and the Ethos cannot be excluded. Picking packs and rules is covered in [Choose your setup](../guides/choose-your-setup.md); what the layers are is in [Rules](rules.md).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
group: concepts
|
|
3
|
+
order: 8
|
|
4
|
+
title: "Footprint (lean vs full)"
|
|
5
|
+
kind: "concept"
|
|
6
|
+
link: {"hash": "#/settings", "label": "Toggle it in Settings →"}
|
|
7
|
+
---
|
|
8
|
+
**Footprint** decides how much of the [constitution](rules.md) the agent carries *inline* in its instructions file on every turn. It has two settings, **lean** (the default) and **full**, chosen per install. It is a token-cost dial, not a rules dial: every rule the install adopted is in force at either setting.
|
|
9
|
+
|
|
10
|
+
> **You already know this:** eager versus lazy loading. Full ships everything in the first payload; lean ships the index and fetches the rest when it is needed.
|
|
11
|
+
|
|
12
|
+
### The difference
|
|
13
|
+
|
|
14
|
+
- **Full** — the instructions file carries the Ethos, every Rule and every rule of the active doctrine packs at complete length, reasoning included, every turn.
|
|
15
|
+
- **Lean** — each Rule and each doctrine rule is carried as its heading plus a short form written by hand (the rule and how it works, not the first sentence cut off). Each layer ends with a pointer to its complete text on disk, and the agent reads the reasoning when a rule's application is unclear. The Ethos gets one hand-written short form for the whole layer, because it is flowing prose rather than numbered rules.
|
|
16
|
+
|
|
17
|
+
Neither setting hides text from the agent. They decide what is in front of it on *every* turn.
|
|
18
|
+
|
|
19
|
+
### What is on disk either way
|
|
20
|
+
|
|
21
|
+
- **Lean** writes the full `laws/`, `ontology/` and `doctrines/` text beside the instructions file, because the inline copy is shorter than what the agent may need.
|
|
22
|
+
- **Full** writes `doctrines/` too: it inlines only the packs this install built in, so the others must be on disk for a citation into them to resolve, and for you to read before turning one on.
|
|
23
|
+
|
|
24
|
+
Everything else is identical at both settings — the same agents, skills, plugins or hooks, commands, memory and notebook.
|
|
25
|
+
|
|
26
|
+
### Which to choose
|
|
27
|
+
|
|
28
|
+
- **Lean** (default) for long sessions, large repos or cost-sensitive work. It is safe: the full text ships, and the instructions tell the agent to read it before acting on secrets, deletion, git history, scope or untrusted content.
|
|
29
|
+
- **Full** when token cost does not matter, or with a smaller or cheaper model — with the reasoning always in context, a model applies a rule's edge cases more reliably.
|
|
30
|
+
|
|
31
|
+
For measured numbers per host, see [docs/token-footprint.md](../token-footprint.md).
|
|
32
|
+
|
|
33
|
+
### How to set it
|
|
34
|
+
|
|
35
|
+
Footprint is stored in a `.geneseed-footprint` marker in the install and kept across every rebuild and upgrade, on every host.
|
|
36
|
+
|
|
37
|
+
- **Setup wizard** — asks for it alongside voice, posture, mode and doctrine packs:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
geneseed setup
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- **Web console** — the **Footprint** toggle in Settings flips the current install and rebuilds it; on the Harness page, each install has its own dropdown.
|
|
44
|
+
- **Command line** — with the emit target of the install you are changing:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
geneseed build --emit claude-global --footprint full
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
On the command line, a flag you leave out takes the generator's default, not the install's current value. `geneseed status --json` shows what an install currently has.
|
|
51
|
+
|
|
52
|
+
The walkthrough for all build-time choices is [Choose your setup](../guides/choose-your-setup.md).
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
group: concepts
|
|
3
|
+
order: 10
|
|
4
|
+
title: "Foreman mode"
|
|
5
|
+
kind: "concept"
|
|
6
|
+
link: {"hash": "#/harness", "label": "Set the mode in Harness →"}
|
|
7
|
+
---
|
|
8
|
+
**Mode** decides how work gets executed in a session. Two modes ship: **direct**, the default, where the agent does every task itself, and **foreman**, where the session hands substantial tasks to a crew of [agents](agents.md) and keeps talking to you while they work.
|
|
9
|
+
|
|
10
|
+
> **You already know this:** a tech lead with a team. Quick questions get answered on the spot; a real feature becomes a ticket that someone builds on a branch, and the lead reviews the result before it is merged.
|
|
11
|
+
|
|
12
|
+
Mode is chosen at build time, so it does not drift mid-session, and kept across every rebuild and re-theme. It is separate from [posture](collaboration.md) (the relationship register), the doctrine packs ([Rules](rules.md)) and [footprint](footprint.md).
|
|
13
|
+
|
|
14
|
+
### direct — the default
|
|
15
|
+
|
|
16
|
+
The agent works every task itself, turn by turn. Nothing is spawned; you talk to one agent from start to finish. Keep it unless you want the session to manage work for you.
|
|
17
|
+
|
|
18
|
+
### foreman — a session that triages
|
|
19
|
+
|
|
20
|
+
The session sorts every request:
|
|
21
|
+
|
|
22
|
+
- **Trivial** — a quick answer, a one-file tweak, a question: done directly, as in direct mode.
|
|
23
|
+
- **Substantial** — handed to a **pipeline** running in the background. The session tells you it is running and stays free to answer you.
|
|
24
|
+
|
|
25
|
+
Expect a substantial task to cost more (a crew runs instead of one agent) in exchange for a session that never blocks on a long job.
|
|
26
|
+
|
|
27
|
+
### What a pipeline is
|
|
28
|
+
|
|
29
|
+
A **pipeline** is a small crew of agents working one task in isolation. The minimum crew depends on the task:
|
|
30
|
+
|
|
31
|
+
| Task | Minimum crew |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| development | `explorer` (analyses the request) → `developer` → `tester`, plus a lint check |
|
|
34
|
+
| documentation | `explorer` → `docs` |
|
|
35
|
+
| research | `explorer`; add `researcher` when the question leaves the repository |
|
|
36
|
+
| review or audit | `reviewer` + `skeptic` |
|
|
37
|
+
|
|
38
|
+
The session adds specialists on top when the task needs them — `security`, `architect`, `reviewer` and so on — never fewer than the minimum.
|
|
39
|
+
|
|
40
|
+
The crew works in its own git worktree and branch. When worktrees are unavailable it falls back to the main tree, one pipeline at a time, and says so. Two pipelines whose sets of files overlap do not run at once.
|
|
41
|
+
|
|
42
|
+
Inside the crew, the developer implements and the tester runs the tests and lint. Failures go back to the developer, at most five rounds; after that the crew stops and reports the failure, leaving the branch for you to inspect.
|
|
43
|
+
|
|
44
|
+
### A pipeline never commits or merges
|
|
45
|
+
|
|
46
|
+
When the crew is done, it hands back its worktree **uncommitted**, with the raw test and lint output and the list of files it changed. Then the session:
|
|
47
|
+
|
|
48
|
+
1. re-runs the tests and lint itself — the crew's log is the crew's account, not proof;
|
|
49
|
+
2. shows you the diff and the green output;
|
|
50
|
+
3. commits and merges **only once you accept**.
|
|
51
|
+
|
|
52
|
+
Commit, push and merge belong to the session alone, under *Consent Before Push* ([Rules](rules.md)). A crew that cannot get to green reports back instead of landing broken work.
|
|
53
|
+
|
|
54
|
+
You can also start a pipeline without foreman mode: ask the agent to "run a pipeline" for a task, and the `pipeline` [skill](skills.md) takes it from there.
|
|
55
|
+
|
|
56
|
+
### How to set it
|
|
57
|
+
|
|
58
|
+
- **Setup wizard** — asks for mode alongside voice, posture, doctrine packs and footprint:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
geneseed setup
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- **Web console** — the per-install **Mode** dropdown on the Harness page, then **Apply**.
|
|
65
|
+
- **Command line** — with the emit target of the install you are changing; switch back with `--mode direct`:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
geneseed build --emit claude-global --mode foreman
|
|
69
|
+
```
|