geneseed 3.1.0 → 3.1.2
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 +110 -0
- package/DESIGN.md +31 -20
- package/README.md +2 -2
- package/SETUP.md +30 -3
- package/SHIPPED.md +1 -1
- package/bin/{geneseed.mjs → build-driver.mjs} +88 -42
- package/bin/geneseed-cli.mjs +33 -32
- package/bin/geneseed-hook.mjs +7 -7
- package/docs/design-history.md +40 -40
- package/docs/extending.md +113 -85
- package/docs/web/rules.md +2 -0
- package/docs/web/setup-choices.md +13 -1
- package/harness.config.json +1 -1
- package/js/README.md +203 -0
- package/js/build/bundle.mjs +231 -0
- package/js/{catalog.mjs → build/catalog.mjs} +7 -7
- package/js/build/emit-claude.mjs +287 -0
- package/js/build/emit-common.mjs +255 -0
- package/js/build/emit-opencode.mjs +214 -0
- package/js/{generate.mjs → build/generate.mjs} +45 -31
- package/js/{render.mjs → build/render.mjs} +72 -11
- package/js/{checkout.mjs → build/source.mjs} +52 -11
- package/js/build/stubs.mjs +256 -0
- package/js/{themes.mjs → build/themes.mjs} +24 -24
- package/js/build/version.mjs +155 -0
- package/js/{hooks.mjs → hosts/hooks.mjs} +47 -44
- package/js/{hosts.mjs → hosts/hosts.mjs} +30 -28
- package/js/{installs.mjs → hosts/installs.mjs} +68 -16
- package/js/{link.mjs → hosts/link.mjs} +29 -28
- package/js/{mcp.mjs → hosts/mcp.mjs} +10 -9
- package/js/{native.mjs → hosts/native.mjs} +24 -22
- package/js/{opencode.mjs → hosts/opencode.mjs} +12 -7
- package/js/{settings.mjs → hosts/settings.mjs} +94 -69
- package/js/inspect/checks-authoring.mjs +761 -0
- package/js/inspect/checks-build.mjs +231 -0
- package/js/inspect/checks-repo.mjs +308 -0
- package/js/{diff.mjs → inspect/diff.mjs} +34 -31
- package/js/inspect/doctor.mjs +286 -0
- package/js/{excludes.mjs → inspect/excludes.mjs} +30 -33
- package/js/{inventory.mjs → inspect/inventory.mjs} +34 -20
- package/js/{registry.mjs → inspect/registry.mjs} +12 -10
- package/js/inspect/scan.mjs +125 -0
- package/js/{status.mjs → inspect/status.mjs} +27 -25
- package/js/inspect/validate.mjs +199 -0
- package/js/lib/fs.mjs +37 -759
- package/js/lib/json.mjs +344 -0
- package/js/lib/paths.mjs +242 -0
- package/js/lib/proc.mjs +3 -3
- package/js/lib/text.mjs +181 -0
- package/js/lib/udiff.mjs +1 -1
- package/js/{memory.mjs → maintain/memory.mjs} +10 -10
- package/js/{migrate.mjs → maintain/migrate.mjs} +28 -26
- package/js/{setup.mjs → maintain/setup.mjs} +49 -37
- package/js/{uninstall.mjs → maintain/uninstall.mjs} +62 -58
- package/js/{update.mjs → maintain/update.mjs} +51 -51
- package/js/{anim.mjs → ui/anim.mjs} +30 -28
- package/js/{cli.mjs → ui/cli.mjs} +10 -10
- package/js/{menu.mjs → ui/menu.mjs} +10 -9
- package/js/{tui.mjs → ui/tui.mjs} +36 -34
- package/js/web/actions.mjs +124 -89
- package/js/web/activity.mjs +22 -21
- package/js/web/api.mjs +88 -58
- package/js/web/daemon.mjs +319 -0
- package/js/web/docs.mjs +24 -21
- package/js/web/graph.mjs +0 -0
- package/js/web/handler.mjs +442 -0
- package/js/web/jobs.mjs +29 -21
- package/js/web/routes.mjs +223 -0
- package/js/web/server.mjs +56 -987
- package/package.json +11 -3
- package/src/AGENT.md.tmpl +1 -1
- package/src/doctrines/README.md +1 -1
- package/themes/opencode/README.md +1 -1
- package/web/dist/assets/{About-_MnJcwb_.js → About-CPvIFZGh.js} +1 -1
- package/web/dist/assets/{Activity-DpjqO-FR.js → Activity-z0uXdS7J.js} +1 -1
- package/web/dist/assets/{ActivityDetail-Bvrjv8oW.js → ActivityDetail-CEj5IJpF.js} +1 -1
- package/web/dist/assets/{Diff-DZ0IehBV.js → Diff-BMR8fPuG.js} +1 -1
- package/web/dist/assets/{Doctor-cu4krooO.js → Doctor-Bz5qE4r9.js} +1 -1
- package/web/dist/assets/{Graph-DUOPY65j.js → Graph-BV6a6t2l.js} +1 -1
- package/web/dist/assets/{Harnesses-B5Osg-BF.js → Harnesses-C5Ag5PaQ.js} +1 -1
- package/web/dist/assets/Laws-BK07NKw9.js +3 -0
- package/web/dist/assets/{Library-8y69I3_z.js → Library-CiXN9sC3.js} +1 -1
- package/web/dist/assets/{Markdown-Ds5GS1OD.js → Markdown-DG6FjUz-.js} +1 -1
- package/web/dist/assets/{Profile-7Jxa7ZUX.js → Profile-B2oSvdxH.js} +1 -1
- package/web/dist/assets/{Rules-UZ0jWkjg.js → Rules-DobVPd80.js} +1 -1
- package/web/dist/assets/{Skills-Bgkl0xLd.js → Skills-DQPsvsn9.js} +1 -1
- package/web/dist/assets/{StatusBadge-Cx4caF_2.js → StatusBadge-BhJ3HhdI.js} +1 -1
- package/web/dist/assets/{Themes-De8az7Sv.js → Themes-BP38FBU9.js} +1 -1
- package/web/dist/assets/{activity-VDAdVQ3q.js → activity-D9mfv7pY.js} +1 -1
- package/web/dist/assets/index-BE226Gv6.css +1 -0
- package/web/dist/assets/{index-BKrjBRV4.js → index-BZ7cPLMI.js} +1 -1
- package/web/dist/assets/index-BgIs5eIa.js +12 -0
- package/web/dist/assets/{index-wNiNzFFQ.js → index-DGM5j2hB.js} +1 -1
- package/web/dist/index.html +2 -2
- package/web/src/pages/Laws.jsx +135 -69
- package/docs/declined.md +0 -200
- package/docs/limits.md +0 -329
- package/js/doctor.mjs +0 -1712
- package/js/emit.mjs +0 -1410
- package/web/dist/assets/Laws-D8DJgTBp.js +0 -3
- package/web/dist/assets/index-1pPSz7Kl.css +0 -1
- package/web/dist/assets/index-C-gb-q-r.js +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,116 @@ labels in `harness.config.json`. The canonical identity of an *installed* harnes
|
|
|
6
6
|
is the source fingerprint in `.geneseed-version` (see `geneseed version`), not this
|
|
7
7
|
label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
|
|
8
8
|
|
|
9
|
+
## [3.1.2] — 2026-08-24
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
- **`js/` is now domain folders, not a flat drawer.** The tree splits into `build/`, `hosts/`,
|
|
15
|
+
`inspect/`, and `main/`, and the four largest modules split with it: `server.mjs` into
|
|
16
|
+
routes / handler / daemon / server, `emit.mjs` into common / stubs / version / bundle,
|
|
17
|
+
`doctor.mjs` into scan plus three check groups, and `fs.mjs` into fs / json / paths / text.
|
|
18
|
+
The Node generator driver is renamed to `bin/build-driver.mjs`; the `geneseed-build` bin name
|
|
19
|
+
is unchanged, so nothing on an installed harness has to move.
|
|
20
|
+
|
|
21
|
+
**No emitted byte moves.** The 261-cell corpus replays identical across all 14 themes, which
|
|
22
|
+
is the whole warrant for a reorganization this size — 151 files, 8502 insertions, 6481
|
|
23
|
+
deletions, and zero observable difference for anyone who installed 3.1.1.
|
|
24
|
+
|
|
25
|
+
- **Docs point at the code that exists.** A module map and front door in `js/README.md`, with a
|
|
26
|
+
doctor arm that keeps them honest; 201 stale paths repointed in prose, the 35 split-module
|
|
27
|
+
pointers resolved, and 69 docblock claims corrected where the code had stopped supporting
|
|
28
|
+
what the comment promised. The vestigial `emit.mjs` is deleted.
|
|
29
|
+
|
|
30
|
+
- **The Python-era `py` identifier prefix is retired**, and `js/ bin/ tests/ adapters/` are now
|
|
31
|
+
linted — the half of the tree that never was.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
- **Two of "the four things that are genuinely hard" are resolved rather than rewritten.**
|
|
35
|
+
`docs/extending.md` §5.2 — seven theme keys pinned byte-for-byte, so restyling a tagline was a
|
|
36
|
+
red gate — and §5.4 — *a snapshot red is a finding, not a step*. Theme text is free to edit,
|
|
37
|
+
and a red test is a step again. Editing a CLI verb's help text or flags is an ordinary edit.
|
|
38
|
+
|
|
39
|
+
- **The standing rule is now "expected values are written out, not recorded"**: change the
|
|
40
|
+
expectation and the sentence that explains it in the same commit, and say why in the message.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
- **A gate on how a runtime dependency may enter**: vendored under `js/vendor/<name>/` as tracked
|
|
46
|
+
source behind a relative import, never installed. Fixtures run from the OS temp root and cannot
|
|
47
|
+
resolve a bare specifier, and neither can a fresh `git clone`; devDependencies are unaffected.
|
|
48
|
+
|
|
49
|
+
### Removed
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
- **The recorded corpora, and the notion of a corpus with them.** `tests/__snapshots__/` held
|
|
53
|
+
2.6 MB of transcripts taken from the CPython reference before it was deleted, replayed by
|
|
54
|
+
`tests/snapshot/`. With no recorder left they could never be re-blessed, so a red run could
|
|
55
|
+
only ever mean *you changed something*, never *you broke something* — and every deliberate
|
|
56
|
+
change to emitted text arrived as a red gate. The 1381-cell retirement of 2026-08-17 had
|
|
57
|
+
already made the argument; this finishes it.
|
|
58
|
+
|
|
59
|
+
**What they owned is now written out.** `wrapText`, `dwidth` and `formatHelp` had zero unit
|
|
60
|
+
coverage — the recordings were their only gate — so `tests/unit/text_layout.test.mjs` states
|
|
61
|
+
their rules explicitly and renders all 29 verbs. The JSONC, Windows-PATH and token-report
|
|
62
|
+
tables moved inline; `sync_themes` became an owned fixture with plain-text expectations. The
|
|
63
|
+
"corpus contains what it is named for" gates went with them: when the apostrophe is visible in
|
|
64
|
+
the file, nothing has to assert it is there.
|
|
65
|
+
|
|
66
|
+
Recoverable at tag `corpus-reference-v3.1.2`. Nothing can regenerate them.
|
|
67
|
+
|
|
68
|
+
- **Three migration statistics.** "N of the M subcommands run from Node", "0 commands have no
|
|
69
|
+
Node twin", and a native-verb list duplicated across two files purely so each could police the
|
|
70
|
+
other. A migration percentage is not a fact about a finished tool. The durable property under
|
|
71
|
+
the first two — every declared verb is dispatched by an entry point — is now asserted directly.
|
|
72
|
+
|
|
73
|
+
- **`golden.mjs --against`**, which could not have worked since the emit corpus was retired, and
|
|
74
|
+
`orphanCheck`, `narrowingReason` and `tests/helpers/snapshot_io.mjs` with it. The three
|
|
75
|
+
surviving modes are all self-comparisons.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## [3.1.1] — 2026-08-21
|
|
79
|
+
|
|
80
|
+
### Added
|
|
81
|
+
|
|
82
|
+
- **Doctrines toggle per RULE, not per pack.** A second build-time axis,
|
|
83
|
+
`geneseed-build --exclude-rules "process 7"`, drops individual rules from the packs that
|
|
84
|
+
survive `--doctrines`. Either spelling of an address is accepted — `process 7` as the
|
|
85
|
+
constitution writes it, `process.7` as the console addresses it — and `none` is the explicit
|
|
86
|
+
empty selection.
|
|
87
|
+
|
|
88
|
+
**This supersedes the pack-level switch 3.1.0 shipped one day earlier.** That control could
|
|
89
|
+
only say *all of Observance or none of it*; the case it could not express — *keep the pack,
|
|
90
|
+
drop one rule* — is the one people actually have. The console's switches are now one per rule,
|
|
91
|
+
still staged locally and still applied in a single rebuild, and there is no pack switch at all:
|
|
92
|
+
the pack axis is DERIVED at Apply time from whichever rules survive. A pack whose every rule is
|
|
93
|
+
off leaves `--doctrines` entirely, so `AGENT.md` never renders a pack header with nothing under
|
|
94
|
+
it.
|
|
95
|
+
|
|
96
|
+
An install records its exclusions in a second marker line, `Excluded rules: process 7`,
|
|
97
|
+
**written only when something is excluded**. That asymmetry is load-bearing rather than tidy: a
|
|
98
|
+
default build is byte-identical to one from before this axis existed — 261 golden cells, nine
|
|
99
|
+
emit modes, both footprints, all unmoved, nothing re-blessed — and the line's absence is a
|
|
100
|
+
complete answer, so `excludedRulesOfDir` reads a missing line as `[]` where `doctrinesOfDir`
|
|
101
|
+
must read one as `null`. Every rebuild path (`upgrade`, `rebuild-all`, the console's Build and
|
|
102
|
+
Deploy) reads the line back and preserves it, or an upgrade would silently hand back every rule
|
|
103
|
+
its owner switched off.
|
|
104
|
+
|
|
105
|
+
⚠ **The consent gate is re-keyed from the pack to the rule.** `process 5` carries commit/push
|
|
106
|
+
consent, and the `git-gate` hook plus the `git commit*` / `git push*` permission are now wired
|
|
107
|
+
on that rule rather than on its pack — so excluding it alone unwires them, and excluding
|
|
108
|
+
`process 7` beside it does not. Prompt and boundary are never allowed to disagree; `doctor`
|
|
109
|
+
gained a gate that fails if `js/settings.mjs`'s hardcoded `process.5` ever stops naming the
|
|
110
|
+
consent rule. `rm -rf` and force-push refusals remain Rule IV's territory and ride no axis.
|
|
111
|
+
|
|
112
|
+
### Fixed
|
|
113
|
+
|
|
114
|
+
- **Independent doctrine controls.** Each Constitution doctrine row now keeps its detail
|
|
115
|
+
disclosure separate from the right-aligned switch. Toggling a staged rule no longer opens or
|
|
116
|
+
closes its detail, and the existing bottom **Apply** action remains the sole point at which a
|
|
117
|
+
selection changes the deployed harness.
|
|
118
|
+
|
|
9
119
|
## [3.1.0] — 2026-08-20
|
|
10
120
|
|
|
11
121
|
### Added
|
package/DESIGN.md
CHANGED
|
@@ -35,7 +35,7 @@ vault or a specific tool's hooks.
|
|
|
35
35
|
names (`ONT_TELOS`, `ONT_EVIDENCE`, `ONT_DECISIONS`, `ONT_CONDUCT`), a few rare
|
|
36
36
|
technical nouns (`Context`, `Scripts`, `Charter`), and the folder names (`laws/`,
|
|
37
37
|
`ontology/`, `doctrines/`, `agents/`, `skills/`, `memory/`, `notebook/` via `DIR_*`).
|
|
38
|
-
These live in the `STRUCTURE` map in `js/render.mjs` and are laid on top of every
|
|
38
|
+
These live in the `STRUCTURE` map in `js/build/render.mjs` and are laid on top of every
|
|
39
39
|
render, so a theme can never move a path, a link, or a heading number. No theme file
|
|
40
40
|
defines a `DIR_*` or an `ONT_*` key, and none may: an ontology citation spells the
|
|
41
41
|
section on both sides (`{{ONTOLOGY}}: {{ONT_TELOS}}`), so heading and reference move
|
|
@@ -102,22 +102,33 @@ vault or a specific tool's hooks.
|
|
|
102
102
|
Rules, `I`..`IX`, headed `### {{LAW}} <roman> — {{LEX_<roman>}}`.
|
|
103
103
|
- **Doctrines** (`src/doctrines/{craft,rigor,ops,process}.md`) — *how work is done
|
|
104
104
|
here*. Practice rules addressed by pack and number, cited as `Doctrine process 5`.
|
|
105
|
-
`PACK_ORDER` (`js/
|
|
105
|
+
`PACK_ORDER` (`js/build/source.mjs`) fixes the order craft → rigor → ops → process, which
|
|
106
106
|
is narrative and deliberately not alphabetical.
|
|
107
107
|
|
|
108
108
|
**The Ontology and the Invariants are never toggleable** — every build carries both,
|
|
109
|
-
whole. The Doctrine
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
whole. The Doctrine tier is the only one a repository may narrow, and it narrows on
|
|
110
|
+
**two axes**, both chosen once at build time and both defaulting to everything on:
|
|
111
|
+
`--doctrines craft,rigor` (or `none`, or the wizard) selects PACKS, and
|
|
112
|
+
`--exclude-rules "process 7"` drops individual RULES from the packs that survive. They
|
|
113
|
+
compose in one direction only — a pack whose every rule is excluded leaves the active
|
|
114
|
+
set, so no pack header is ever rendered empty. There is no runtime toggle for either.
|
|
115
|
+
Every pack file ships on disk at both footprints whether or not it was built in, which
|
|
116
|
+
is what lets a citation into an inactive pack still resolve.
|
|
117
|
+
|
|
118
|
+
Each axis leaves its own marker line in the carrier for later readers (`upgrade`,
|
|
119
|
+
`rebuild-all`, the console) to parse back: `Active packs:` always, and
|
|
120
|
+
`Excluded rules:` **only when something is excluded**. That asymmetry is deliberate and
|
|
121
|
+
load-bearing — the second line's absence is a complete answer ("nothing"), so a default
|
|
122
|
+
build is byte-identical to one from before the axis existed and no recording had to be
|
|
123
|
+
re-blessed; `excludedRulesOfDir` accordingly reads a missing line as `[]` where
|
|
124
|
+
`doctrinesOfDir` must read one as `null`.
|
|
114
125
|
|
|
115
126
|
**Conflict order, exactly:** Ontology + Invariants → the user's own `user-rules.md` →
|
|
116
127
|
the active Doctrines → `PROFILE.md`. A doctrine rule may *tighten* an invariant, never
|
|
117
128
|
repeal one; a user rule outranks a doctrine rule outright; nothing outranks an
|
|
118
129
|
invariant. And an always-on tier may never cite a toggleable one — a `--doctrines craft`
|
|
119
130
|
build would otherwise ship an invariant pointing at text its `AGENT.md` does not
|
|
120
|
-
contain — so `constitutionProblems` (`js/
|
|
131
|
+
contain — so `constitutionProblems` (`js/inspect/checks-authoring.mjs`) refuses a `{{DOCTRINE}}` token
|
|
121
132
|
anywhere under `src/ontology/` or `src/laws/`.
|
|
122
133
|
|
|
123
134
|
The bar for a **new invariant** is the highest in the tree: universal (it binds *every*
|
|
@@ -135,9 +146,9 @@ vault or a specific tool's hooks.
|
|
|
135
146
|
|---|---|---|---|
|
|
136
147
|
| body | append to `src/laws/universal.md` — never insert; nothing resolves a cross-reference against the canon | append to `src/doctrines/<pack>.md`, `### {{DOCTRINE}} <pack> <n> — {{DOC_<PACK>_<n>}}`; ids must run contiguously from 1 | a new `src/doctrines/<pack>.md` with its `**Name** — lead line` |
|
|
137
148
|
| themed title | `LEX_<roman>` in all 15 theme files | `DOC_<PACK>_<n>` in all 15 theme files | `PACK_<NAME>` in all 15, plus each rule's `DOC_*` |
|
|
138
|
-
| class | `LAW_CLASS` in `js/inventory.mjs`, one of the six in `LAW_CLASSES` | **none** — a doctrine rule's class *is* its pack, and there is no second taxonomy over it | — |
|
|
149
|
+
| class | `LAW_CLASS` in `js/inspect/inventory.mjs`, one of the six in `LAW_CLASSES` | **none** — a doctrine rule's class *is* its pack, and there is no second taxonomy over it | — |
|
|
139
150
|
| console copy | a `LAW_META` row in `web/src/pages/Laws.jsx` (keyed by arabic number) | a `DOCTRINE_META` row in the same file (keyed `<pack>.<n>`) | one `DOCTRINE_META` row per rule |
|
|
140
|
-
| registration | the numeral is the registration | the number is the registration | the pack name in `PACK_ORDER`, `js/
|
|
151
|
+
| registration | the numeral is the registration | the number is the registration | the pack name in `PACK_ORDER`, `js/build/source.mjs` |
|
|
141
152
|
| renumber risk | high — appending is the only safe move | none — packs are numbered independently | none |
|
|
142
153
|
| counts | README badge + the `N universal laws` prose, `SHIPPED.md`'s triple, the web onboarding copy | **none** — the console spends the `N_PACKS` / `N_PACKS_ACTIVE` / `N_DOCTRINE_RULES` count tokens, all computed at request time | none, same reason |
|
|
143
154
|
| changelog | `CHANGELOG.md` | `CHANGELOG.md` | `CHANGELOG.md` |
|
|
@@ -149,7 +160,7 @@ vault or a specific tool's hooks.
|
|
|
149
160
|
synonym. `--sync-themes` writes the template's placeholder and only *prints* which keys
|
|
150
161
|
to restyle; a shipped placeholder passes every gate.
|
|
151
162
|
|
|
152
|
-
Almost all of it is gated, across six named checks in `js/
|
|
163
|
+
Almost all of it is gated, across six named checks in `js/inspect/checks-build.mjs` —
|
|
153
164
|
`themeParityProblems` (key parity across the voices), `lawMetaProblems` and
|
|
154
165
|
`doctrineMetaProblems` (the console's Principle column, in both directions),
|
|
155
166
|
`constitutionProblems` (pack numbering and filing, `LEX_I..LEX_IX` as an *equality*, the
|
|
@@ -184,11 +195,11 @@ theme file defines a `DIR_*` key, so `laws/` is `laws/` in all fourteen voices.
|
|
|
184
195
|
| Notebook | `src/notebook/` | `notebook/` | the agent's sovereign space — any medium, seed-once charter the agent may rewrite; only `.gitignore` re-asserted |
|
|
185
196
|
| Posture | `src/postures/` | inlined into `AGENT.md` | how much ceremony the agent brings to a task |
|
|
186
197
|
| Mode | `src/modes/` | inlined into `AGENT.md` | the working axis (solo, foreman, …) — orthogonal to posture |
|
|
187
|
-
| Context | `js/
|
|
198
|
+
| Context | `js/build/stubs.mjs` | `context.json` | empty per-repo manifest, written once and never overwritten; git-ignore it |
|
|
188
199
|
| Themes | `themes/*.json` | — | token → label maps; `themes/opencode/` is a separate colour system |
|
|
189
200
|
| Release label | `harness.config.json` | `.geneseed-version` | the theme and the human-readable version the driver reads; the canonical identity is the source fingerprint, not this string |
|
|
190
201
|
| Lifecycle | `registry.json` | — | maintainer-side status/version/owner per agent and skill; never rendered into a bundle |
|
|
191
|
-
| Generator | `bin/
|
|
202
|
+
| Generator | `bin/build-driver.mjs` (`geneseed-build`) | — | substitution + `<!-- INCLUDE: -->` inlining, and the nine `--emit` targets |
|
|
192
203
|
| CLI, as data | `js/cli-table.json` | — | the owned document the entry point parses its own argv from |
|
|
193
204
|
| Automation | `bin/geneseed-cli.mjs` (`geneseed`) | — | 25 verbs — `build` / `doctor` / `status` / `prompt` / `diff` / `setup` / `web` / `upgrade` / … |
|
|
194
205
|
| Hooks | `bin/geneseed-hook.mjs` (`geneseed-hook`) | — | the four verbs an emitted `settings.json` invokes: `context` / `git-gate` / `rule-gate` / `learn` |
|
|
@@ -201,28 +212,28 @@ theme file defines a `DIR_*` key, so `laws/` is `laws/` in all fourteen voices.
|
|
|
201
212
|
- Unknown tokens are left visible (debugging aid); `doctor` flags them.
|
|
202
213
|
- Node built-ins only; no third-party dependencies, ever. (`package.json` carries neither a
|
|
203
214
|
`dependencies` nor a `devDependencies` key, and a test asserts it.)
|
|
204
|
-
- **`js/settings.mjs` is the half of the emit that edits files you co-own** — the
|
|
215
|
+
- **`js/hosts/settings.mjs` is the half of the emit that edits files you co-own** — the
|
|
205
216
|
`settings.json` / `opencode.json` merges, JSONC parsing, the hook shim and the managed
|
|
206
217
|
CLAUDE.md block. It is a separate module because every function in it reconciles
|
|
207
218
|
Geneseed's claim with content Geneseed did not write, and because eleven of its names are
|
|
208
|
-
driven by the *runtime* as well as by an emit (`js/mcp.mjs` uses ten of them
|
|
219
|
+
driven by the *runtime* as well as by an emit (`js/hosts/mcp.mjs` uses ten of them
|
|
209
220
|
for deactivate, remerge, reactivate and uninstall; `exclude` and `doctor` use the rest).
|
|
210
|
-
Its dependency closure points one way only: nothing in it calls into `js/render.mjs` or
|
|
211
|
-
`js/
|
|
221
|
+
Its dependency closure points one way only: nothing in it calls into `js/build/render.mjs` or
|
|
222
|
+
`js/build/bundle.mjs`. Keep it that way — that closure is what makes it a unit.
|
|
212
223
|
- **Every emit runs five stages in one order: `RENDER* → WIRE* → PRUNE → MANIFEST →
|
|
213
|
-
VERIFY`.** RENDER writes files Geneseed owns wholesale; WIRE is `js/settings.mjs`
|
|
224
|
+
VERIFY`.** RENDER writes files Geneseed owns wholesale; WIRE is `js/hosts/settings.mjs`
|
|
214
225
|
reconciling files you co-own; PRUNE removes what the previous manifest owned and this
|
|
215
226
|
emit no longer produces; MANIFEST records both; VERIFY re-reads the merge to confirm it
|
|
216
227
|
stuck. WIRE must precede MANIFEST because wiring is what fills the `managed` record the
|
|
217
228
|
manifest stores, and no RENDER may follow a WIRE because a render writes wholesale a file
|
|
218
229
|
a wire has just reconciled. `tests/unit/emit_phase_order.test.mjs` fails the build if any of
|
|
219
230
|
the nine emits drifts out of that order, or if a new file-mutating routine in
|
|
220
|
-
`js/settings.mjs` is called from an emit without being classified. RENDER and WIRE now run
|
|
231
|
+
`js/hosts/settings.mjs` is called from an emit without being classified. RENDER and WIRE now run
|
|
221
232
|
in the *same process* — the seam that once spawned a second runtime per emit is gone — so
|
|
222
233
|
the render and wire dispatchers stay two separate functions and two separate statements on
|
|
223
234
|
purpose: that shape is the only thing left for the walker to check, and a gate refuses an
|
|
224
235
|
emit whose sequence has lost its WIRE.
|
|
225
|
-
`bin/
|
|
236
|
+
`bin/build-driver.mjs`'s `main()` is classified too, as the one stage no per-emit gate can see: it
|
|
226
237
|
writes the `.geneseed-emit` / `-footprint` / `-theme` markers and the install-registry
|
|
227
238
|
record *after* every emit returns, and nothing that reconciles a file you co-own may run
|
|
228
239
|
there, because there is no manifest to record the claim and no teardown able to undo it.
|
package/README.md
CHANGED
|
@@ -93,7 +93,7 @@ Both launchers are thin shims over the Node CLI: they need `node` (22.3+) on `PA
|
|
|
93
93
|
|
|
94
94
|
Node ≥ 22.3 is the entire dependency list. Every subcommand, all four hooks, every web-console endpoint and both generators run from it, and every commit runs the whole unit suite plus `doctor --all` across every theme × host × footprint, on Linux and Windows both. So an install needs no second interpreter — not for the harness, and not for anything it ships. (Until 2026-08-17 the generator's output was also replayed byte for byte against recordings taken from the Python implementation. Those were retired — see [`docs/limits.md`](docs/limits.md) for the measurement that licensed it and the coverage it cost.)
|
|
95
95
|
|
|
96
|
-
- **
|
|
96
|
+
- **One runtime, no second one to install**: every command and all four hook verbs answer from the Node entry points. `catalog`, `mcp` and `memory` are console-facing verbs the CLI table declares alongside them. There is no full-screen browse panel — `geneseed tui` and `geneseed menu` are verbs that refuse it by name and print the command list instead, off a terminal as well as on one.
|
|
97
97
|
- **Nothing you install needs an interpreter.** The `token-report` skill is a script rather than prose, and it ships as `scripts/token_report.mjs`, run with `node`; `daydream` and `herdr` hand their inline code to `node -e`. So **every bundle carries** nothing that needs one: no Python file, and no skill that shells out to an interpreter, on any host, theme or footprint. Three tests freeze that — one scans every tracked file for inline code handed to an interpreter, one globs the bundle source, and one replays the report script over seeded transcripts for all four hosts and compares the bytes.
|
|
98
98
|
- **`upgrade` / `update` / `sync-self` / `bootstrap` are for a git checkout.** They `git pull` the install's own origin. From an npm install they stop before touching anything and name `npm install -g geneseed@latest` as the update instead.
|
|
99
99
|
|
|
@@ -154,7 +154,7 @@ The harness ships as a small set of layers, and the web console's rail is the sa
|
|
|
154
154
|
| --- | --- |
|
|
155
155
|
| **🧭 Ontology** (`ontology/`) | the mind the rules govern, in four prose sections — **Telos** (the Pact: protect the user, the truth, the agent), **Evidence** (every claim graded by how it was obtained), **Decisions** (classify and tier by reversibility, show the real forks), **Conduct** (answer what was asked, once). Always in force, never toggleable |
|
|
156
156
|
| **🛡️ Rules** (`laws/`) | 9 universal laws the agent obeys — always in force, never toggleable: sealed-secrets, one-intent-one-act, verify-before-assert, deletion-is-deliberate, surface-failures, data-not-orders, least-privilege, root-cause, external-gate |
|
|
157
|
-
| **📐 Doctrines** (`doctrines/`) | practice packs, chosen per install at build time: **craft** (how code is written), **rigor** (how work is proven), **ops** (how the machine is operated), **process** (how a task is run). A doctrine rule may tighten a Rule, never repeal one, and the user's own `user-rules.md` outranks it. Pick with `geneseed-build --doctrines craft,rigor` (or `none`),
|
|
157
|
+
| **📐 Doctrines** (`doctrines/`) | practice packs, chosen per install at build time: **craft** (how code is written), **rigor** (how work is proven), **ops** (how the machine is operated), **process** (how a task is run). A doctrine rule may tighten a Rule, never repeal one, and the user's own `user-rules.md` outranks it. Pick with `geneseed-build --doctrines craft,rigor` (or `none`), a single rule with `--exclude-rules "process 7"`, in the setup wizard, or through the switches on the console's Constitution page; all four pack files ship on disk either way, so a citation into a pack you left out still resolves |
|
|
158
158
|
| **🤖 Agents** (17) | capability specialists: `reviewer`, `tester`, `architect`, `docs`, `security`, `explorer`, `developer` — plus a debate **council** the `council` skill convenes: `advocate`, `skeptic`, `pragmatist`, `steward`, `visionary`, `user-advocate`, `framer`, `empiricist`, `operator`, `historian` |
|
|
159
159
|
| **🛠 Skills** (47) | repeatable workflows: brainstorm · **clarify** · plan · **codebase-design** · **domain-modeling** · **wayfinder** · **tickets** · tdd · **develop** · debug · **prototype** · refactor · **ponytail** · **forge-mcp** · geneseed-code-review · **fresh-eyes** · **review-response** · commit · **ship** · **release** · **migrate** · **git-archaeology** · **git-rescue** · repo-map · document-project · **frontend-design** · **prose** · **ingest** · **research** · **learning-path** · **gap-detector** · **feynman** · **crash-course** · **drill** · **decode** · handoff · roast-me · **council** · parallel-agents · **workflow** · **wiki** · **geneseed** · **rule** · **profile** · **opencode-theme** · **herdr** · **pipeline** |
|
|
160
160
|
| **🔌 Plugins** (OpenCode) | `geneseed-context` injects project docs *and your machine wiki* every session (and across compaction); `geneseed-learn` distils memory at session end; `geneseed-guard` enforces the safety Laws and protected wiki folders at the tool boundary; `geneseed-workflow` registers the `workflow` tool that runs saved orchestration scripts; `geneseed-notify` sends a native OS notification when a long run finishes; `geneseed-ponytail` holds a minimal-code mode (`/ponytail lite\|full\|ultra\|off`), opt-in, injecting the laziest-that-works ruleset every turn so it doesn't drift; `geneseed-activity` streams what each session is doing to the web console's Activity view |
|
package/SETUP.md
CHANGED
|
@@ -100,7 +100,7 @@ hand? Pick a path below.
|
|
|
100
100
|
> **Every `geneseed-build …` below is the generator.** `npm install -g geneseed` puts it
|
|
101
101
|
> on your `PATH`; without installing anything, `npx -p geneseed geneseed-build --emit
|
|
102
102
|
> opencode-global` is the same command. From a checkout it is
|
|
103
|
-
> `node bin/
|
|
103
|
+
> `node bin/build-driver.mjs` with the same flags. Every commit re-emits with it across every
|
|
104
104
|
> theme × host × footprint combination and checks the result with `doctor --all`, on Linux
|
|
105
105
|
> and Windows both. Until 2026-08-17 that output was also compared byte for byte against
|
|
106
106
|
> recordings taken from the Python implementation; those were retired, and `docs/limits.md`
|
|
@@ -168,8 +168,10 @@ It wires:
|
|
|
168
168
|
for Doctrine `process 5`. The hook inspects the command and forces an `ask` on every
|
|
169
169
|
`git commit` or `git push` (even chained or `-C`-flagged), un-suppressible by a
|
|
170
170
|
one-time "don't ask again". Every other Bash command is deferred to the normal
|
|
171
|
-
permission flow. It is wired only when
|
|
172
|
-
`--doctrines` leaving `process` out
|
|
171
|
+
permission flow. It is wired only when **Doctrine process 5 itself** is active — build
|
|
172
|
+
with `--doctrines` leaving `process` out, or with `--exclude-rules "process 5"`, and this
|
|
173
|
+
hook is not installed at all. The prompt and the boundary move together by construction:
|
|
174
|
+
the gate is keyed on the rule, not on its pack.
|
|
173
175
|
- **SessionStart** (`startup`/`clear`) — prints `AGENT.md` and injects the project
|
|
174
176
|
context (`harness context`, which auto-discovers the repo's docs);
|
|
175
177
|
- **SessionStart** (`resume`) — refreshes the project context only, without re-printing
|
|
@@ -313,6 +315,31 @@ the default is all four:
|
|
|
313
315
|
refuses one that names a pack the checkout does not ship. Order is fixed by the harness
|
|
314
316
|
(craft → rigor → ops → process) regardless of the order you type.
|
|
315
317
|
|
|
318
|
+
### One rule at a time
|
|
319
|
+
|
|
320
|
+
A pack is coarse: `--doctrines` can only keep all of **process** or none of it.
|
|
321
|
+
`--exclude-rules` is the finer axis, and it takes rule addresses:
|
|
322
|
+
|
|
323
|
+
geneseed-build --exclude-rules "process 7" # keep the pack, drop one rule
|
|
324
|
+
geneseed-build --exclude-rules "process 5,craft 2" # several
|
|
325
|
+
geneseed-build --exclude-rules none # exclude nothing (the default)
|
|
326
|
+
|
|
327
|
+
Both spellings of an address work — `process 7` as the constitution writes it, or `process.7`
|
|
328
|
+
as the console addresses it. The two axes compose: a pack whose every rule is excluded drops
|
|
329
|
+
out of `Active packs:` entirely, so you never get a pack header with nothing under it.
|
|
330
|
+
|
|
331
|
+
An install records what it excluded in a second marker line, `Excluded rules: process 7`,
|
|
332
|
+
written **only when something is excluded** — so a build with the default keeps every byte it
|
|
333
|
+
had before this axis existed. `upgrade`, `rebuild-all` and the web console all read that line
|
|
334
|
+
back and preserve it, exactly as they preserve the pack list.
|
|
335
|
+
|
|
336
|
+
⚠ **`process 5` is special**: excluding it also unwires the commit/push consent hook, because
|
|
337
|
+
the tool boundary is keyed on that rule. That is by design — the prompt and the boundary must
|
|
338
|
+
never disagree — and both the console and the wizard say so before applying it.
|
|
339
|
+
|
|
340
|
+
The web console has the switches: **Constitution → Doctrines**, one per rule, staged locally
|
|
341
|
+
with a single **Apply** that rebuilds the install once.
|
|
342
|
+
|
|
316
343
|
The setup wizard asks too — one *all* / *choose* gate, then a yes/no per pack with its
|
|
317
344
|
one-line description — and it **pre-selects what the install already carries**, read off the
|
|
318
345
|
`Active packs:` marker line in the deployed `AGENT.md`. So re-running the wizard and holding
|
package/SHIPPED.md
CHANGED
|
@@ -20,7 +20,7 @@ historical pointers, 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.1.
|
|
23
|
+
> string. Current label: **3.1.2**.
|
|
24
24
|
|
|
25
25
|
> **Spec status audit (2026-06-15).** Every dated spec authored before today was
|
|
26
26
|
> verified against the source tree and confirmed implemented (code + tests + docs);
|