geneseed 2.0.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 +938 -0
- package/DESIGN.md +1423 -0
- package/LICENSE +21 -0
- package/QUICKSTART.md +48 -0
- package/README.md +336 -0
- package/SETUP.md +1027 -0
- package/SHIPPED.md +70 -0
- package/adapters/bob/README.md +100 -0
- package/adapters/claude-code/README.md +101 -0
- package/adapters/claude-code/settings.json +47 -0
- package/adapters/claude-code/skills/geneseed/SKILL.md +72 -0
- package/adapters/copilot/README.md +76 -0
- package/adapters/opencode/GLOBAL-HARNESS-SPEC.md +434 -0
- package/adapters/opencode/HOW-OPENCODE-LOADS.md +158 -0
- package/adapters/opencode/README.md +582 -0
- package/adapters/opencode/agents/orchestrator.md +25 -0
- package/adapters/opencode/opencode.json +44 -0
- package/adapters/opencode/plugins/geneseed-activity.js +430 -0
- package/adapters/opencode/plugins/geneseed-context.js +876 -0
- package/adapters/opencode/plugins/geneseed-guard.js +290 -0
- package/adapters/opencode/plugins/geneseed-learn.js +396 -0
- package/adapters/opencode/plugins/geneseed-notify.js +142 -0
- package/adapters/opencode/plugins/geneseed-ponytail.js +148 -0
- package/adapters/opencode/plugins/geneseed-workflow.js +183 -0
- package/adapters/opencode/workflows/_runtime.js +277 -0
- package/adapters/opencode/workflows/council.js +64 -0
- package/adapters/opencode/workflows/dispatch.js +89 -0
- package/adapters/opencode/workflows/research-plan-implement.js +43 -0
- package/adapters/opencode/workflows/review.js +57 -0
- package/bin/geneseed-cli.mjs +412 -0
- package/bin/geneseed-hook.mjs +129 -0
- package/bin/geneseed.mjs +1086 -0
- package/docs/declined.md +149 -0
- package/docs/limits.md +270 -0
- package/docs/opencode-plugin-setup.md +64 -0
- package/docs/token-footprint.md +68 -0
- package/docs/web/_groups.json +45 -0
- package/docs/web/about.md +6 -0
- package/docs/web/adapters-claude-code.md +8 -0
- package/docs/web/adapters-opencode-loads.md +8 -0
- package/docs/web/adapters-opencode-spec.md +8 -0
- package/docs/web/adapters-opencode.md +8 -0
- package/docs/web/agents.md +8 -0
- package/docs/web/authoring.md +11 -0
- package/docs/web/autostart.md +9 -0
- package/docs/web/claude-hooks.md +36 -0
- package/docs/web/cli.md +6 -0
- package/docs/web/collaboration.md +27 -0
- package/docs/web/configure-wiki.md +9 -0
- package/docs/web/design.md +7 -0
- package/docs/web/env-knobs.md +9 -0
- package/docs/web/exclusions.md +26 -0
- package/docs/web/first-session.md +28 -0
- package/docs/web/footprint.md +31 -0
- package/docs/web/foreman-mode.md +33 -0
- package/docs/web/glossary.md +6 -0
- package/docs/web/harnesses.md +28 -0
- package/docs/web/headless.md +9 -0
- package/docs/web/ingest-docs.md +9 -0
- package/docs/web/install-paths.md +9 -0
- package/docs/web/install-quick.md +35 -0
- package/docs/web/lsp-overview.md +37 -0
- package/docs/web/mcp-claude-code.md +10 -0
- package/docs/web/mcp-filesystem.md +9 -0
- package/docs/web/mcp-gitlab.md +9 -0
- package/docs/web/mcp-markitdown.md +9 -0
- package/docs/web/mcp-overview.md +34 -0
- package/docs/web/mcp-trouble.md +9 -0
- package/docs/web/mcp-verify.md +9 -0
- package/docs/web/memory.md +7 -0
- package/docs/web/migrate.md +39 -0
- package/docs/web/model.md +20 -0
- package/docs/web/notebook.md +7 -0
- package/docs/web/pipelines.md +24 -0
- package/docs/web/plugin-activity.md +23 -0
- package/docs/web/plugin-context.md +26 -0
- package/docs/web/plugin-guard.md +24 -0
- package/docs/web/plugin-learn.md +27 -0
- package/docs/web/plugin-notify.md +24 -0
- package/docs/web/plugin-ponytail.md +23 -0
- package/docs/web/plugin-setup.md +7 -0
- package/docs/web/plugin-workflow.md +24 -0
- package/docs/web/plugins.md +17 -0
- package/docs/web/project-context.md +9 -0
- package/docs/web/rules.md +8 -0
- package/docs/web/run-anywhere.md +9 -0
- package/docs/web/self-improve.md +8 -0
- package/docs/web/setup-choices.md +39 -0
- package/docs/web/skills.md +8 -0
- package/docs/web/themes-author.md +8 -0
- package/docs/web/themes.md +9 -0
- package/docs/web/token-footprint.md +7 -0
- package/docs/web/trouble.md +38 -0
- package/docs/web/upgrade.md +9 -0
- package/docs/web/verify.md +30 -0
- package/docs/web/wiki.md +7 -0
- package/docs/web/worktree.md +10 -0
- package/docs/web-ui.md +144 -0
- package/docs/wiki.md +43 -0
- package/geneseed +39 -0
- package/geneseed.cmd +34 -0
- package/harness.config.json +6 -0
- package/js/anim.mjs +326 -0
- package/js/catalog.mjs +112 -0
- package/js/checkout.mjs +88 -0
- package/js/cli-table.json +1034 -0
- package/js/cli.mjs +498 -0
- package/js/diff.mjs +384 -0
- package/js/doctor.mjs +1364 -0
- package/js/emit.mjs +1373 -0
- package/js/excludes.mjs +271 -0
- package/js/generate.mjs +379 -0
- package/js/hooks.mjs +1026 -0
- package/js/hosts.mjs +253 -0
- package/js/installs.mjs +378 -0
- package/js/inventory.mjs +175 -0
- package/js/lib/fs.mjs +913 -0
- package/js/lib/proc.mjs +28 -0
- package/js/lib/udiff.mjs +275 -0
- package/js/link.mjs +286 -0
- package/js/mcp.mjs +335 -0
- package/js/memory.mjs +108 -0
- package/js/menu.mjs +118 -0
- package/js/migrate.mjs +251 -0
- package/js/native.mjs +426 -0
- package/js/opencode.mjs +325 -0
- package/js/registry.mjs +110 -0
- package/js/render.mjs +282 -0
- package/js/settings.mjs +924 -0
- package/js/setup.mjs +492 -0
- package/js/status.mjs +281 -0
- package/js/themes.mjs +195 -0
- package/js/tui.mjs +444 -0
- package/js/uninstall.mjs +1137 -0
- package/js/update.mjs +910 -0
- package/js/web/actions.mjs +868 -0
- package/js/web/activity.mjs +284 -0
- package/js/web/api.mjs +873 -0
- package/js/web/docs.mjs +531 -0
- package/js/web/graph.mjs +0 -0
- package/js/web/jobs.mjs +480 -0
- package/js/web/server.mjs +1135 -0
- package/package.json +54 -0
- package/registry.json +474 -0
- package/src/AGENT.md.tmpl +390 -0
- package/src/agents/_template.md +76 -0
- package/src/agents/advocate.md +36 -0
- package/src/agents/architect.md +55 -0
- package/src/agents/developer.md +66 -0
- package/src/agents/docs.md +54 -0
- package/src/agents/empiricist.md +39 -0
- package/src/agents/explorer.md +54 -0
- package/src/agents/framer.md +36 -0
- package/src/agents/historian.md +51 -0
- package/src/agents/operator.md +37 -0
- package/src/agents/pragmatist.md +37 -0
- package/src/agents/reviewer.md +52 -0
- package/src/agents/security.md +57 -0
- package/src/agents/skeptic.md +48 -0
- package/src/agents/steward.md +36 -0
- package/src/agents/tester.md +54 -0
- package/src/agents/user-advocate.md +36 -0
- package/src/agents/visionary.md +36 -0
- package/src/laws/universal.md +387 -0
- package/src/memory/README.md +109 -0
- package/src/memory/gitignore +6 -0
- package/src/modes/README.md +26 -0
- package/src/modes/direct.md +2 -0
- package/src/modes/foreman.md +19 -0
- package/src/notebook/README.md +39 -0
- package/src/notebook/gitignore +7 -0
- package/src/postures/README.md +31 -0
- package/src/postures/artisan.md +14 -0
- package/src/postures/assistant.md +12 -0
- package/src/postures/expert.md +11 -0
- package/src/postures/mentor.md +11 -0
- package/src/postures/peer.md +12 -0
- package/src/skills/_template.md +47 -0
- package/src/skills/brainstorm.md +28 -0
- package/src/skills/clarify.md +28 -0
- package/src/skills/codebase-design.md +44 -0
- package/src/skills/commit.md +48 -0
- package/src/skills/council.md +34 -0
- package/src/skills/crash-course.md +28 -0
- package/src/skills/daydream/.claude-plugin/plugin.json +9 -0
- package/src/skills/daydream/SKILL.md +74 -0
- package/src/skills/daydream/VENDOR.md +25 -0
- package/src/skills/daydream/critic-prompt.md +38 -0
- package/src/skills/daydream/instructions.md +422 -0
- package/src/skills/daydream/synthesizer-prompt.md +41 -0
- package/src/skills/debug.md +37 -0
- package/src/skills/decode.md +28 -0
- package/src/skills/develop.md +29 -0
- package/src/skills/document-project.md +79 -0
- package/src/skills/domain-modeling.md +38 -0
- package/src/skills/drill.md +28 -0
- package/src/skills/feynman.md +26 -0
- package/src/skills/forge-mcp.md +48 -0
- package/src/skills/fresh-eyes.md +29 -0
- package/src/skills/frontend-design.md +58 -0
- package/src/skills/gap-detector.md +27 -0
- package/src/skills/geneseed-code-review.md +33 -0
- package/src/skills/geneseed.md +29 -0
- package/src/skills/git-archaeology.md +47 -0
- package/src/skills/git-rescue.md +68 -0
- package/src/skills/handoff.md +29 -0
- package/src/skills/herdr.md +164 -0
- package/src/skills/ingest.md +49 -0
- package/src/skills/learning-path.md +26 -0
- package/src/skills/migrate.md +45 -0
- package/src/skills/opencode-theme.md +52 -0
- package/src/skills/parallel-agents.md +28 -0
- package/src/skills/pipeline.md +52 -0
- package/src/skills/plan.md +45 -0
- package/src/skills/ponytail.md +29 -0
- package/src/skills/profile.md +58 -0
- package/src/skills/prose.md +42 -0
- package/src/skills/prototype.md +44 -0
- package/src/skills/react-view-transitions/AGENTS.md +955 -0
- package/src/skills/react-view-transitions/README.md +42 -0
- package/src/skills/react-view-transitions/SKILL.md +320 -0
- package/src/skills/react-view-transitions/VENDOR.md +16 -0
- package/src/skills/react-view-transitions/metadata.json +12 -0
- package/src/skills/react-view-transitions/references/css-recipes.md +242 -0
- package/src/skills/react-view-transitions/references/implementation.md +182 -0
- package/src/skills/react-view-transitions/references/nextjs.md +176 -0
- package/src/skills/react-view-transitions/references/patterns.md +262 -0
- package/src/skills/refactor.md +32 -0
- package/src/skills/release.md +43 -0
- package/src/skills/repo-map.md +36 -0
- package/src/skills/research.md +42 -0
- package/src/skills/review-response.md +36 -0
- package/src/skills/roast-me.md +28 -0
- package/src/skills/rule.md +100 -0
- package/src/skills/ship.md +49 -0
- package/src/skills/tdd.md +31 -0
- package/src/skills/tickets.md +44 -0
- package/src/skills/token-report/SKILL.md +76 -0
- package/src/skills/token-report/VENDOR.md +23 -0
- package/src/skills/token-report/scripts/token_report.mjs +1301 -0
- package/src/skills/wayfinder.md +49 -0
- package/src/skills/wiki.md +68 -0
- package/src/skills/workflow.md +38 -0
- package/themes/README.md +69 -0
- package/themes/_TEMPLATE.json +147 -0
- package/themes/biker.json +147 -0
- package/themes/commentator.json +147 -0
- package/themes/cyberpunk.json +147 -0
- package/themes/gamer.json +147 -0
- package/themes/imperial.json +147 -0
- package/themes/joker.json +147 -0
- package/themes/marvin.json +147 -0
- package/themes/mean.json +147 -0
- package/themes/military.json +147 -0
- package/themes/neutral.json +147 -0
- package/themes/opencode/README.md +58 -0
- package/themes/opencode/catppuccin.json +27 -0
- package/themes/opencode/dracula.json +27 -0
- package/themes/opencode/everforest.json +27 -0
- package/themes/opencode/gruvbox.json +27 -0
- package/themes/opencode/kanagawa.json +27 -0
- package/themes/opencode/neon.json +27 -0
- package/themes/opencode/nord.json +27 -0
- package/themes/opencode/rosepine.json +27 -0
- package/themes/opencode/tokyonight.json +27 -0
- package/themes/pirate.json +147 -0
- package/themes/sports.json +147 -0
- package/themes/verstappen.json +147 -0
- package/themes/wizard.json +147 -0
- package/web/dist/assets/About-DX1-VTBP.js +1 -0
- package/web/dist/assets/Activity-Dp9NaXOn.js +1 -0
- package/web/dist/assets/ActivityDetail-HpOBtrXS.js +1 -0
- package/web/dist/assets/Diff-Ct4G3Se8.js +5 -0
- package/web/dist/assets/Doctor-DGjkZFuA.js +1 -0
- package/web/dist/assets/Graph-b8o-S6kv.js +1 -0
- package/web/dist/assets/Harnesses-gr3-aHBF.js +1 -0
- package/web/dist/assets/Laws-DTwF5tTC.js +1 -0
- package/web/dist/assets/Library-BEZscyaQ.js +1 -0
- package/web/dist/assets/Markdown-k_LSLBGq.js +1 -0
- package/web/dist/assets/Profile-DydukTxP.js +1 -0
- package/web/dist/assets/Rules-CIRG4Ldt.js +1 -0
- package/web/dist/assets/Skills-Buoi1IBr.js +1 -0
- package/web/dist/assets/StatusBadge-CE_AJttl.js +1 -0
- package/web/dist/assets/Themes-CI4o3gJC.js +2 -0
- package/web/dist/assets/activity-BCW7e6Cy.js +1 -0
- package/web/dist/assets/audiowide-latin-400-normal-6GFCX7ni.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-400-normal-DKaoCDn5.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-500-normal-C3sF8Y1B.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-600-normal-BHzjB6_C.woff2 +0 -0
- package/web/dist/assets/hanken-grotesk-latin-400-italic-Bserb8X5.woff2 +0 -0
- package/web/dist/assets/hanken-grotesk-latin-400-normal-BG6hkEXj.woff2 +0 -0
- package/web/dist/assets/hanken-grotesk-latin-500-italic-BGfwwhek.woff2 +0 -0
- package/web/dist/assets/hanken-grotesk-latin-500-normal-DrDcrrxK.woff2 +0 -0
- package/web/dist/assets/hanken-grotesk-latin-600-normal-CIXX6EOa.woff2 +0 -0
- package/web/dist/assets/hanken-grotesk-latin-700-normal-CeQ8H3UY.woff2 +0 -0
- package/web/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/web/dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/web/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/web/dist/assets/ibm-plex-serif-latin-400-normal-BIGslYFI.woff2 +0 -0
- package/web/dist/assets/ibm-plex-serif-latin-500-normal-REKAfBVG.woff2 +0 -0
- package/web/dist/assets/ibm-plex-serif-latin-600-normal-DAxitmSu.woff2 +0 -0
- package/web/dist/assets/index-B1PIx7RM.js +1 -0
- package/web/dist/assets/index-BnTQUSUz.js +12 -0
- package/web/dist/assets/index-Ck2iCdaC.js +2 -0
- package/web/dist/assets/index-DUCsDv7z.css +1 -0
- package/web/dist/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
- package/web/dist/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
- package/web/dist/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
- package/web/dist/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
- package/web/dist/assets/marked.esm-JKvyS0Pp.js +46 -0
- package/web/dist/assets/oswald-latin-400-normal-BAFo8sP8.woff2 +0 -0
- package/web/dist/assets/oswald-latin-500-normal-B-eyT0Dw.woff2 +0 -0
- package/web/dist/assets/oswald-latin-600-normal-plFmSr5g.woff2 +0 -0
- package/web/dist/assets/oswald-latin-700-normal-vy6hmKSr.woff2 +0 -0
- package/web/dist/assets/poppins-latin-400-normal-cpxAROuN.woff2 +0 -0
- package/web/dist/assets/poppins-latin-500-normal-C8OXljZJ.woff2 +0 -0
- package/web/dist/assets/poppins-latin-600-normal-zEkxB9Mr.woff2 +0 -0
- package/web/dist/assets/poppins-latin-700-normal-Qrb0O0WB.woff2 +0 -0
- package/web/dist/assets/react-DOpiTn5v.js +32 -0
- package/web/dist/assets/roman-DkYN0LX9.js +1 -0
- package/web/dist/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-600-normal-DjKNqYRj.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
- package/web/dist/assets/space-mono-latin-400-italic-YylcN9Ay.woff2 +0 -0
- package/web/dist/assets/space-mono-latin-400-normal-Rg4St2Dn.woff2 +0 -0
- package/web/dist/assets/space-mono-latin-700-italic-vNvENeTh.woff2 +0 -0
- package/web/dist/assets/space-mono-latin-700-normal-mWgeinG7.woff2 +0 -0
- package/web/dist/icon-maskable.svg +10 -0
- package/web/dist/icon.svg +8 -0
- package/web/dist/index.html +21 -0
- package/web/dist/manifest.webmanifest +14 -0
- package/web/dist/sw.js +40 -0
- package/web/src/pages/Laws.jsx +230 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,938 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Geneseed are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/); versions are the human-readable
|
|
5
|
+
labels in `harness.config.json`. The canonical identity of an *installed* harness
|
|
6
|
+
is the source fingerprint in `.geneseed-version` (see `geneseed version`), not this
|
|
7
|
+
label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **`npx geneseed setup` is now the way in, and the README says exactly where that stops
|
|
13
|
+
being true.** The install docs assume npm first: one command, no clone, no Python, on
|
|
14
|
+
macOS, Linux and Windows alike. **All 25 commands** run from Node, along with all
|
|
15
|
+
four hooks, every web-console endpoint and both generators, producing byte-identical
|
|
16
|
+
output. Three things still need Python and each is now named in the README and the Setup
|
|
17
|
+
guide rather than discovered: the full-screen browse panel that `tui` and `menu` open on a
|
|
18
|
+
terminal is still Python — from Node both refuse the panel by name and print the command
|
|
19
|
+
list, while off a terminal the two runtimes print the same bytes, and `geneseed home` opens
|
|
20
|
+
the web console exactly as it does under Python; the self-update commands (`upgrade`, `update`, `sync-self`, `bootstrap`) are for
|
|
21
|
+
a git checkout and now point an npm install at `npm install -g geneseed@latest` instead of
|
|
22
|
+
telling it to re-clone; and **every bundle carries one Python script**, the `token-report`
|
|
23
|
+
skill's own, which runs when the agent invokes that skill and at no other time. In the web
|
|
24
|
+
console, the "browse…" folder picker needs an OS-native dialog and reports itself
|
|
25
|
+
unavailable on the Node server — the path field beside it stays editable.
|
|
26
|
+
A publishing workflow ships with it, using npm's trusted publishing (OIDC): no long-lived
|
|
27
|
+
token in the repository, manual trigger only, and it explains the one step that has to be
|
|
28
|
+
done by hand on the npm side. Nothing has been published.
|
|
29
|
+
- **`geneseed migrate` moves an existing install to the npm shape, in one pass.** If you
|
|
30
|
+
installed by cloning the repository, your hooks run through a small machine-wide shim that
|
|
31
|
+
hands every call to your checkout's Python; installing from npm changes where that code
|
|
32
|
+
lives. `migrate` surveys every install you already have, re-emits each one **in its own
|
|
33
|
+
theme, emit, footprint, posture and mode** — nothing is defaulted, so it can never quietly
|
|
34
|
+
change what you chose — and re-points the shim. `--dry-run` prints the plan and writes
|
|
35
|
+
nothing. Run it once; a second run says so and does nothing.
|
|
36
|
+
**It is all-or-nothing**: every settings file it will touch is copied first, and if any
|
|
37
|
+
install fails to rebuild, everything is put back. You are never left half on one shape and
|
|
38
|
+
half on the other. **It refuses rather than guesses**: an install whose marker names
|
|
39
|
+
something unrecognised stops the whole run with the offending path named, because
|
|
40
|
+
re-emitting an install as something its owner never chose is worse than stopping.
|
|
41
|
+
**And it does not touch what it did not write** — your own hooks, third-party hooks, and
|
|
42
|
+
the login autostart entry you created by hand are reported, never rewritten. See the new
|
|
43
|
+
*Migrate an existing install to npx* page in the docs. Your old clone keeps working for a
|
|
44
|
+
full release; there is no cliff.
|
|
45
|
+
- **Geneseed is an npm package now — as a file on disk, not yet as something you can
|
|
46
|
+
install.** The repository carries a `package.json` with three commands (`geneseed`,
|
|
47
|
+
`geneseed-hook`, `geneseed-build`), a minimum Node version of 22.3.0, and an explicit list
|
|
48
|
+
of what a release would contain. Packing it and installing the result works today: all
|
|
49
|
+
three commands run, and `geneseed-build` renders a full bundle from the installed copy.
|
|
50
|
+
Two problems had to be fixed first, both found by installing it rather than by reading it:
|
|
51
|
+
npm rewrote the two `.gitignore` files that guard the agent's `memory/` and `notebook/`
|
|
52
|
+
directories, which would have let an agent's private notes be committed into your
|
|
53
|
+
repository, and the notebook's charter page went missing from the bundle. Both are fixed at
|
|
54
|
+
the source — those two files are stored without their leading dot and the renderer puts it
|
|
55
|
+
back — so nothing an install produces differs from what a git clone produces, byte for byte.
|
|
56
|
+
Nothing has been published yet.
|
|
57
|
+
- **The web console's CLI reference page works without Python, and the harness's command
|
|
58
|
+
surface now has exactly one description.** The Docs page that lists every command and every
|
|
59
|
+
flag used to be readable only from Python, because it walked the harness's own argument
|
|
60
|
+
parser — 24 commands, 43 arguments. That metadata is now generated into a tracked
|
|
61
|
+
`cli.json` that both runtimes read, so the page works on either, and `geneseed doctor`
|
|
62
|
+
reports it as a problem — on either runtime — when the file and the parser part company.
|
|
63
|
+
The page itself is unchanged. What changed is that there is no longer a second,
|
|
64
|
+
hand-maintained copy of the command list that could quietly disagree with the commands you
|
|
65
|
+
actually have.
|
|
66
|
+
- **`geneseed bootstrap`, `geneseed sync-self` and `geneseed update` have Node twins, and the
|
|
67
|
+
web console's Update button works without Python.** Nineteen of the harness's 24 commands
|
|
68
|
+
now run from `node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`. The
|
|
69
|
+
About page in the web console works there too — it reads your install's own git origin, so
|
|
70
|
+
the links on it point at the repository your updates actually come from.
|
|
71
|
+
- **A real fix in `geneseed bootstrap`: it now runs the setup wizard again.** `bootstrap`
|
|
72
|
+
updates everything and then hands off to `setup` — and that handoff was pointed at an
|
|
73
|
+
internal module instead of the harness, so it did nothing at all and exited 0. `./geneseed`
|
|
74
|
+
with no arguments takes that path. If bootstrap has been "succeeding" without ever showing
|
|
75
|
+
you the wizard, this is why.
|
|
76
|
+
|
|
77
|
+
### Removed
|
|
78
|
+
- **`upgrade.sh` and `sync-self.sh` are gone.** Each was a few lines of bash that found a
|
|
79
|
+
Python interpreter and then ran `rituals/harness.py upgrade` (or `sync-self`) — the same
|
|
80
|
+
command every launcher already runs, on every OS, and one that native Windows could never
|
|
81
|
+
reach through a `.sh` file at all. Use `./geneseed upgrade` (or `.\geneseed.cmd upgrade`,
|
|
82
|
+
`.\geneseed.ps1 upgrade`, `python rituals/harness.py upgrade`, or the web console's Update
|
|
83
|
+
button) — all of which is what they did. Nothing else changes: the launchers' self-repair
|
|
84
|
+
path for a factory too old to know the subcommand never went through either script and is
|
|
85
|
+
untouched.
|
|
86
|
+
|
|
87
|
+
- **`geneseed upgrade` has a Node twin — the one command a "no Python needed" install could
|
|
88
|
+
not do without Python.** Seventeen of the harness's 24 commands now run from
|
|
89
|
+
`node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`, and this is the
|
|
90
|
+
one that mattered most: an install that shelled out to Python to update ITSELF would have
|
|
91
|
+
had Python as a hard requirement of the only command you must always be able to run.
|
|
92
|
+
Everything about the update is unchanged — it still fast-forwards your own checkout's
|
|
93
|
+
origin and never pushes, still refuses to touch a dirty tree, a detached HEAD or a branch
|
|
94
|
+
with no upstream, still validates the pulled source with `doctor` before trusting it and
|
|
95
|
+
**rolls the checkout back to the previous commit if that validation fails**, and still
|
|
96
|
+
rebuilds the bundle plus every registered install afterwards. Local edits you made to a
|
|
97
|
+
deployed harness are still exported to an improvements file first, so a rebuild cannot
|
|
98
|
+
quietly overwrite them.
|
|
99
|
+
**One real fix rides with it, on Windows.** The `[rebuild-all]` lines an upgrade printed
|
|
100
|
+
while refreshing your other installs were being discarded — including the FAILED rows the
|
|
101
|
+
error message tells you to look for. They now appear, in the terminal and in
|
|
102
|
+
`~/.geneseed-install.log` both.
|
|
103
|
+
- **The port's nineteenth piece: `geneseed setup` has a Node twin — and it is the first one
|
|
104
|
+
that ASKS YOU QUESTIONS.** Fifteen of the harness's 24 commands now run from
|
|
105
|
+
`node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`. The wizard behaves
|
|
106
|
+
the same: the same five questions, the same menus, each one pre-selecting what you already
|
|
107
|
+
have installed rather than a stock default, the same plan printed before anything is
|
|
108
|
+
written, and the same "nothing is written until you confirm". It still refuses outright
|
|
109
|
+
when there is no terminal to ask on, and still offers a health check at the end.
|
|
110
|
+
**One thing you can see is different, on macOS and Linux only.** The Python version tries a
|
|
111
|
+
full-screen version of the wizard first and falls back to plain prompts when it cannot; the
|
|
112
|
+
Node one goes straight to the prompts. On Windows that is what the Python has always done
|
|
113
|
+
too. The full-screen console is a later piece of the port and will bring its own wizard
|
|
114
|
+
with it.
|
|
115
|
+
**What is genuinely better: the pre-selected answers.** The install detector had been
|
|
116
|
+
reporting only the theme and install mode of what it found; the wizard also asks about
|
|
117
|
+
posture, mode and footprint, so those three questions had been quietly offering the
|
|
118
|
+
configured default instead of what is actually deployed. All five now come from the
|
|
119
|
+
install.
|
|
120
|
+
**And the checking had to grow a new shape.** A wizard cannot be tested by running the
|
|
121
|
+
command — it refuses without a terminal, which is exactly what a test gives it. So the two
|
|
122
|
+
implementations are now driven by a *file of answers* fed to them as if typed, and their
|
|
123
|
+
entire output compared character for character: every prompt, every menu line, every
|
|
124
|
+
default marker, the plan, and the choices they came back with. That immediately caught a
|
|
125
|
+
real bug in the new code — an answer containing a non-ASCII character (an accent, a
|
|
126
|
+
non-Latin digit) was being mangled before anything read it.
|
|
127
|
+
- **The port's eighteenth piece: `geneseed uninstall` has a Node twin — and it is the first
|
|
128
|
+
one that DELETES.** Fourteen of the harness's 24 commands now run from
|
|
129
|
+
`node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`. Nothing about what
|
|
130
|
+
`uninstall` does has changed: it still removes only what the install's manifest claims,
|
|
131
|
+
still leaves your own files where they are, still never deletes `memory/` or `notebook/`
|
|
132
|
+
(`--archive-memory` moves them aside to a timestamped sibling), and still refuses to
|
|
133
|
+
proceed without `--yes` when it cannot ask.
|
|
134
|
+
**What changed is how it is checked.** Every earlier verb was proved by comparing what the
|
|
135
|
+
two implementations *wrote*. A removal needs the opposite question, and two implementations
|
|
136
|
+
that had both stopped deleting would have agreed perfectly in every test forever. So the
|
|
137
|
+
test harness grew two things: a record of every *directory* in the sandbox — an empty
|
|
138
|
+
leftover folder was invisible to all 219 previous cases, and cleaning up after itself is
|
|
139
|
+
half of what this command is for — and a way to state that a file or folder must be
|
|
140
|
+
**gone**. Thirty-five new cases, each of which also seeds a file the manifest does *not*
|
|
141
|
+
own and insists it survives: the difference between "removed the install" and "removed the
|
|
142
|
+
directory" is not a comment, it is a control.
|
|
143
|
+
**Two things the checking found, both in the existing Python.** When a file you own keeps
|
|
144
|
+
one of Geneseed's directories alive, the uninstall reports INCOMPLETE and tells you the
|
|
145
|
+
install marker was kept so you can retry — but for a *global* install the marker is already
|
|
146
|
+
gone by then, so the retry reports no install at all. And any unclaimed file under
|
|
147
|
+
`agents/` or `skills/` triggers that report even when everything Geneseed owned was removed
|
|
148
|
+
cleanly. Both are recorded as behaviour both implementations must share, not quietly fixed
|
|
149
|
+
on one side; the fix belongs to a change that can be reviewed on its own.
|
|
150
|
+
- **The port's seventeenth piece: `geneseed doctor` has a Node twin.** Thirteen of the
|
|
151
|
+
harness's 24 commands now run from `node bin/geneseed-cli.mjs` as well as from
|
|
152
|
+
`python rituals/harness.py`: the one that validates the build — unresolved tokens, dead
|
|
153
|
+
links, links that escape the bundle, theme-key parity, colour palettes, the authoring gates
|
|
154
|
+
on every spec, the credential sweep, the vendored-skill pins, the count mirrors in the
|
|
155
|
+
README and the web pages, the hook shim, and whether a committed bundle still matches a
|
|
156
|
+
fresh render of the source.
|
|
157
|
+
**Checking it was harder than porting it, and that is the news.** `doctor` prints
|
|
158
|
+
`[doctor] ok` when all fifteen of its checks find nothing, so two versions that had both
|
|
159
|
+
stopped checking would agree perfectly. Ten of the fifteen read the checkout itself, which
|
|
160
|
+
no sandboxed test could write to. So each test now gets its own copy of the checkout, breaks
|
|
161
|
+
exactly one thing in it, and runs both versions from that copy — 30 checks, one planted
|
|
162
|
+
fault at a time.
|
|
163
|
+
|
|
164
|
+
- **The port's sixteenth piece: `geneseed diff` and `geneseed rebuild-all` have Node twins.**
|
|
165
|
+
Twelve of the harness's 24 commands now run from `node bin/geneseed-cli.mjs` as well as from
|
|
166
|
+
`python rituals/harness.py`: the drift report that shows what your deployed harness has that
|
|
167
|
+
a fresh render of the source does not (and exports it as a file you can hand to an agent to
|
|
168
|
+
back-port), and the sweep that re-emits every active install in place. 21 new side-by-side
|
|
169
|
+
checks compare everything either one can be observed doing — for `rebuild-all` that includes
|
|
170
|
+
every file of every rebuilt install.
|
|
171
|
+
**Your diffs are the same diffs.** Python's `difflib` makes specific choices about how to
|
|
172
|
+
line two files up, so the Node side reproduces it rather than using a different diff that
|
|
173
|
+
would also be correct and would not match. 176 generated cases check that, including files
|
|
174
|
+
long enough to trigger the heuristic Python applies only past 200 lines.
|
|
175
|
+
**Both commands preserve what an install already is.** A rebuild re-emits each install in
|
|
176
|
+
its own theme, host, footprint, posture and mode, read back off the install itself; `diff`
|
|
177
|
+
renders its "expected" copy the same way, so themed wording and a lean footprint are not
|
|
178
|
+
reported as your local edits.
|
|
179
|
+
|
|
180
|
+
### Fixed
|
|
181
|
+
- **`rebuild-all`'s progress lines came out in the wrong order when its output was redirected
|
|
182
|
+
to a file or a log** — every `[rebuild-all] <install>` line appeared *after* the build it
|
|
183
|
+
introduced, so each one named the wrong install. Only visible outside a terminal, which is
|
|
184
|
+
where the web UI's "build all" job log lives. Same helper, and the same shape, as the
|
|
185
|
+
swallowed-output fix in the previous release.
|
|
186
|
+
- **The Node builder's console output now ends its lines the way the Python one does on
|
|
187
|
+
Windows.** Nothing you could see on screen, and a difference if you piped it into anything
|
|
188
|
+
that counts bytes.
|
|
189
|
+
|
|
190
|
+
- **The port's fifteenth piece: `geneseed build`, `geneseed prompt` and `geneseed theme`
|
|
191
|
+
have Node twins.** Ten of the harness's 24 commands now run from
|
|
192
|
+
`node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`: rendering the
|
|
193
|
+
bundle, writing the self-contained install prompt, and creating a custom OpenCode colour
|
|
194
|
+
theme. 23 new side-by-side checks compare everything either one can be observed doing —
|
|
195
|
+
for `build` that includes the whole rendered tree, file for file.
|
|
196
|
+
**`build` does not start a second program.** The Python version runs the builder as a
|
|
197
|
+
separate process; the Node one calls it directly, because it is already part of the same
|
|
198
|
+
program. Nothing about the bundle you get changes.
|
|
199
|
+
**Three commands deliberately did not move.** `sync-self` is an alias for `update`, which
|
|
200
|
+
the self-update work replaces outright rather than translating. `link` and `unlink` put
|
|
201
|
+
`geneseed` on your PATH, and that is exactly what installing from npm will do for you — so
|
|
202
|
+
they belong with the packaging work, not here. They keep working as they always have.
|
|
203
|
+
|
|
204
|
+
- **The port's fourteenth piece: `geneseed status` and `geneseed version` have Node twins.**
|
|
205
|
+
The install dashboard — theme, install mode, how many agents/skills/laws you have, where
|
|
206
|
+
your memory store is and how many facts are in it, and whether the installed build matches
|
|
207
|
+
the source — and the fingerprint comparison behind it now run from
|
|
208
|
+
`node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`. The panel is
|
|
209
|
+
compared line for line, in colour and in plain ASCII, against the Python one.
|
|
210
|
+
**Colour still works on a real terminal**, and that took a different kind of test to
|
|
211
|
+
prove. Every side-by-side check captures output through a pipe, and a pipe is never a
|
|
212
|
+
terminal, so the coloured panel is invisible to all of them — a version that quietly
|
|
213
|
+
dropped every escape code would have looked perfect. The panel renderer is called directly
|
|
214
|
+
instead, on both sides, over a list of made-up dashboards, which also covers three other
|
|
215
|
+
things no ordinary check can reach.
|
|
216
|
+
**A real bug came out of it, in something already shipped.** The Node hook had its own
|
|
217
|
+
private copy of a path helper, under a different name from the shared one, and the two had
|
|
218
|
+
drifted: an exclusion entry written by hand with a `..` in it would make the Node hook go
|
|
219
|
+
quiet for a repository the Python one still watches. There is now one copy, and a check
|
|
220
|
+
for exactly that entry.
|
|
221
|
+
- **The port's thirteenth piece, and the first command that is not a hook: `geneseed exclude`
|
|
222
|
+
has a Node twin.** `exclude add`, `exclude remove` and `exclude list` — the sovereign-repo
|
|
223
|
+
exclusions, the folders where your global install goes quiet — now run from
|
|
224
|
+
`node bin/geneseed-cli.mjs` as well as from `python rituals/harness.py`. Both maintain the
|
|
225
|
+
same `excludes.json` in every global install, both wire the same per-host suppression into
|
|
226
|
+
the excluded folder, and 22 side-by-side checks compare everything either one can be
|
|
227
|
+
observed doing.
|
|
228
|
+
**Why a new command file rather than an existing one.** The hook launcher is deliberately
|
|
229
|
+
tiny — it runs on *every* tool call — and the builder is under a rule that it may not start
|
|
230
|
+
other programs, which is half of what proves it is a real second implementation. Neither
|
|
231
|
+
was the right home for an ordinary CLI command, so there is now a third: the hook launcher,
|
|
232
|
+
the builder, and this. Nothing you have installed changes.
|
|
233
|
+
**Nothing about your existing exclusions changes**, and the Python command is still there —
|
|
234
|
+
the web UI's exclusions page calls straight into it, so both stay until that page moves too.
|
|
235
|
+
- **The port's twelfth piece: an install built with `node bin/geneseed.mjs` no longer needs
|
|
236
|
+
Python at all.** The hooks it wires now launch the Node twin, so building and running a
|
|
237
|
+
Claude or Bob install is Python-free end to end. Building one used to stop with an error
|
|
238
|
+
if no Python could be found; there is nothing left to find, so that error is gone.
|
|
239
|
+
**One thing worth knowing if you have several installs on one machine.** The small
|
|
240
|
+
launcher your hooks go through (`~/.geneseed/bin/geneseed-hook`, or `.cmd` on Windows) is
|
|
241
|
+
*shared* — one file for the whole machine, not one per install. It always was, and while
|
|
242
|
+
both commands wrote the same thing into it that made no difference. It does now: whichever
|
|
243
|
+
command you ran **last** decides what every install's hooks launch. Both answer the four
|
|
244
|
+
hook commands identically, and a check enforces that they keep doing so, so in practice
|
|
245
|
+
you should see nothing — but if you mix `python build.py` and `node bin/geneseed.mjs`,
|
|
246
|
+
that is the rule.
|
|
247
|
+
Also fixed on the way: on Windows the Node hooks ended their lines differently from the
|
|
248
|
+
Python ones. No host was affected — they all read JSON or plain text — but it was a real
|
|
249
|
+
difference in the one place the side-by-side checks structurally could not see, so it is
|
|
250
|
+
fixed and now checked in raw bytes.
|
|
251
|
+
- **The port's eleventh piece, and the first that is not the builder: the four hooks your
|
|
252
|
+
install runs every session have a Node twin.** `context` (the one that injects your repo's
|
|
253
|
+
docs at session start), `git-gate` and `rule-gate` (the two that make the host ask before a
|
|
254
|
+
commit or a memory write), and `learn` (the one that distils a session into memory) all now
|
|
255
|
+
run from `node bin/geneseed-hook.mjs` as well as from `python rituals/harness.py`.
|
|
256
|
+
**At the time, nothing about your installs changed.** Wiring the new twin in was kept a
|
|
257
|
+
separate step, deliberately — an install's hooks are the part that fails *silently* when it
|
|
258
|
+
is wrong, so it moved once and with the evidence in hand. That step is the entry above.
|
|
259
|
+
What is in hand: 103 side-by-side checks covering both, comparing everything either one can
|
|
260
|
+
be observed doing — what it prints, what it warns, the exit code it returns, and every file
|
|
261
|
+
it writes. Discovery with and without a `context.json`, globs, `extend`, the
|
|
262
|
+
project-bypasses-global stand-down, sovereign-repo exclusions, malformed payloads, memory
|
|
263
|
+
dedup, transcripts, per-agent lessons and `--consolidate`.
|
|
264
|
+
- **Fixed on the way: a distilled memory containing an accent or an em dash could be
|
|
265
|
+
corrupted as it was stored.** `learn` read the model CLI's reply using the console's legacy
|
|
266
|
+
code page on Windows rather than UTF-8, and the mangled text was then written into your
|
|
267
|
+
memory store — so the damage outlived the run. It now reads UTF-8 on both paths.
|
|
268
|
+
- **Changed: a `context.json` with a syntax error now names the file and tells you to fix it,
|
|
269
|
+
instead of quoting the JSON parser's own message.** The old message came straight from
|
|
270
|
+
Python's decoder, and no second implementation can reproduce it — the two engines disagree
|
|
271
|
+
about both the wording and where the error is. An unreadable (as opposed to invalid) file is
|
|
272
|
+
now reported separately, which it never was.
|
|
273
|
+
- **The port's tenth piece: every install mode now works from `node bin/geneseed.mjs`,
|
|
274
|
+
including the four that install hooks.** `claude`, `claude-global`, `bob` and `bob-global`
|
|
275
|
+
were the last four on Python, and they were last because of one honest problem: a hook is
|
|
276
|
+
a small script that launches the Python harness, so whatever writes one has to name a
|
|
277
|
+
Python interpreter on your machine — and the Node command has no way to inherit the answer
|
|
278
|
+
the Python command simply knows about itself.
|
|
279
|
+
**At the time it found one, and refused to build if it could not** — superseded by the
|
|
280
|
+
twelfth piece above, where the hooks stopped being Python and there was no longer anything
|
|
281
|
+
to find. It looked at `$PYTHON` first (the
|
|
282
|
+
same variable the `geneseed` launchers honour), then for `py`, `python` and `python3` on
|
|
283
|
+
your `PATH`, and stopped with a clear message having written nothing if none was there.
|
|
284
|
+
That refusal was the point rather than a limitation: hooks that name a missing interpreter
|
|
285
|
+
do not fail loudly, they simply never fire, and an install that looks finished with six
|
|
286
|
+
dead hooks is worse than a build that stopped and told you.
|
|
287
|
+
On Windows it deliberately stepped past the Microsoft Store's `python.exe` placeholder, the
|
|
288
|
+
one that opens the Store instead of running anything.
|
|
289
|
+
Everything else is unchanged and verified: same files, same console output, same exit
|
|
290
|
+
codes as `python build.py`, across every theme, both footprints, all five postures and
|
|
291
|
+
both modes — and now with nothing narrowed out of that comparison. The emitted hooks are
|
|
292
|
+
checked to actually run, not merely to exist.
|
|
293
|
+
Still no `package.json` and no published package; that remains a later phase. What exists
|
|
294
|
+
today is a runnable script in the checkout.
|
|
295
|
+
- **The port's ninth piece, and the first one you can run without Python: `node
|
|
296
|
+
bin/geneseed.mjs` builds the bundle.** Everything before this rendered *inside* a build
|
|
297
|
+
that Python started; this is a second front door. `node bin/geneseed.mjs --theme imperial`
|
|
298
|
+
produces the same bundle, the same console output and the same exit code as `python
|
|
299
|
+
build.py --theme imperial` — verified byte-for-byte over every theme, both footprints, all
|
|
300
|
+
five postures and both modes.
|
|
301
|
+
**Five modes worked this way when this entry was written** — the plain bundle (`--emit
|
|
302
|
+
files`), both OpenCode installs (`opencode`, `opencode-global`) and both Copilot ones
|
|
303
|
+
(`copilot`, `copilot-global`) — including the parts that only happen on your *second*
|
|
304
|
+
build: the Node driver reads the previous manifest, removes what the layer no longer owns,
|
|
305
|
+
and rewrites the manifest exactly as Python does. `$OPENCODE_CONFIG_DIR` and
|
|
306
|
+
`$COPILOT_CONFIG_DIR` relocate the global targets on the Node side too, so keeping your
|
|
307
|
+
harness in a git-tracked folder works unchanged. (The remaining four followed — see the
|
|
308
|
+
entry above.) Nothing about the Python command changes at any point: it is still the one
|
|
309
|
+
the wizard, the web console, doctor and upgrade all use.
|
|
310
|
+
Two flags are deliberately *not* coming to the Node side. `--sync-themes` edits this
|
|
311
|
+
repository's own theme files — maintainer tooling, not something an installed copy should
|
|
312
|
+
carry — and `--validate-only` needs the Python doctor to do its second half. Both say so
|
|
313
|
+
and point you at `python build.py`.
|
|
314
|
+
There is no `package.json` and no published package yet; that is a later phase. What
|
|
315
|
+
exists today is a runnable script in the checkout.
|
|
316
|
+
- **The port's eighth piece: `--emit opencode-global` renders through Node too, and now
|
|
317
|
+
*every* emit does — counted this time, not claimed.** It was the one mode still on
|
|
318
|
+
Python, which the entry below corrects the record about; it now takes the same path as
|
|
319
|
+
the other eight, so the same promise applies: same files, same console output, same exit
|
|
320
|
+
code, and no Node means nothing changes at all.
|
|
321
|
+
What is worth knowing is what it took to say "every" honestly. The test that counts the
|
|
322
|
+
modes refuses one that crosses with no comparison behind it — and this mode had never
|
|
323
|
+
been compared between the two runtimes at all, only against itself. So it arrived with
|
|
324
|
+
six new cases: a plain install and the rebuild over it; the lean footprint's standalone
|
|
325
|
+
laws file; the opt-in primary agent and slash commands; an old harness to carry a memory
|
|
326
|
+
store over from; a config dir you already keep your own agents, wiki and exclude list in,
|
|
327
|
+
with the stores then edited between the two builds — the only way a byte comparison can
|
|
328
|
+
tell "kept your memory" from "re-seeded it"; and an `opencode.jsonc` you have commented.
|
|
329
|
+
One thing that reads like a detail and is not: `--out` is **not** where this emit writes.
|
|
330
|
+
It renders into your OpenCode config dir and takes `--out` only as an old bundle to carry
|
|
331
|
+
a memory or notebook store over from. Every earlier test left those two the same
|
|
332
|
+
directory, so nothing could tell them apart.
|
|
333
|
+
- **The port's seventh piece: the code that edits *your* config files is now the code that
|
|
334
|
+
runs when you build with Node.** The twin added last time was proven and unused; it is
|
|
335
|
+
wired in now, so a build merges your `settings.json` / `settings.local.json` hooks, the
|
|
336
|
+
managed block in your `CLAUDE.md`, and your `opencode.json` in the same Node process that
|
|
337
|
+
renders. As with the six pieces before it, you should not be able to tell: same files,
|
|
338
|
+
same console output, same exit code, and no Node means nothing changes at all.
|
|
339
|
+
Two things stay on the Python side, and both are deliberate. The **check that runs after
|
|
340
|
+
every build** — the one that re-reads your settings file and warns if the hooks did not
|
|
341
|
+
actually land — now verifies Node's work from the other implementation, on every build,
|
|
342
|
+
which is a stronger guarantee than either half could give alone. And the **hook shim**
|
|
343
|
+
still pointed at Python and `harness.py` at that stage, because the hooks themselves were
|
|
344
|
+
still Python — so nothing already deployed changed. (It points at Node as of the twelfth
|
|
345
|
+
piece above.) That last one used to be invisible to every test — the shim is deliberately
|
|
346
|
+
excluded from the byte comparison so a version-to-version run is not drowned in noise —
|
|
347
|
+
so the boundary test now compares it directly.
|
|
348
|
+
Newly watched, because nothing reached them before: a `settings.local.json` you have
|
|
349
|
+
added comments to (left untouched, and it says so), an `opencode.jsonc` likewise, and an
|
|
350
|
+
install that has accumulated more than one recorded exclude — where the *order* they are
|
|
351
|
+
recorded in is part of the file and one entry was never enough to notice.
|
|
352
|
+
- **A count in these notes and in DESIGN.md was wrong for two releases: `--emit
|
|
353
|
+
opencode-global` never rendered through Node.** "Every emit now renders through Node" was
|
|
354
|
+
eight of the nine. That mode still runs the Python, exactly as it always has, so nothing
|
|
355
|
+
about it has changed or broken — but the sentence claiming otherwise has, and there is now
|
|
356
|
+
a test that counts the modes instead of trusting the prose.
|
|
357
|
+
- **The port's sixth piece: the layer that edits *your* config files now has a Node twin
|
|
358
|
+
too — proven, not yet wired in.** Nothing about your builds changes with this; the new
|
|
359
|
+
code is not called yet. What changes is that the merging into `settings.json`, the
|
|
360
|
+
`opencode.json` wiring, the managed block in `CLAUDE.md` and the hook shim are now
|
|
361
|
+
compared byte for byte between the two runtimes, across states no ordinary build ever
|
|
362
|
+
reaches: a settings file carrying your own hooks beside Geneseed's, one with comments in
|
|
363
|
+
it (which the harness refuses to rewrite, and says so), one that is not valid JSON, and
|
|
364
|
+
an older install whose hooks were wired into a different file and have to be unwired
|
|
365
|
+
there. These are the paths `deactivate`, `remerge`, `reactivate`, `uninstall` and
|
|
366
|
+
`exclude` run on a real machine, and nothing had ever compared them.
|
|
367
|
+
- **The rebuild's clean-up of files it no longer produces is now actually tested.** The
|
|
368
|
+
build removes what a previous build owned and this one does not — a dropped skill, a
|
|
369
|
+
footprint switch, a theme change. The acceptance harness re-emitted the *same*
|
|
370
|
+
configuration twice, so there was never anything to remove and the clean-up ran empty
|
|
371
|
+
every time. It now builds one configuration, builds a different one on top, and checks
|
|
372
|
+
the result matches a fresh build of the second — which catches both a clean-up that
|
|
373
|
+
leaves stale files behind and one that deletes files the new build still needs.
|
|
374
|
+
- **The port's fifth piece: eight of the nine emits now render through Node when you have
|
|
375
|
+
it — Claude, Bob and Copilot included, per-repo and global.** Before this, only `build`
|
|
376
|
+
and `--emit opencode` did; six more moved here. (This entry originally said "every emit"
|
|
377
|
+
and "the other six"; it was seven that remained, and `--emit opencode-global` is the one
|
|
378
|
+
still on Python. Corrected in the seventh piece above.) As with the last four
|
|
379
|
+
pieces, the whole point is that you cannot tell: same files, same console output, same
|
|
380
|
+
exit code. No Node, or `GENESEED_NO_JS=1`, and nothing changes at all.
|
|
381
|
+
What is worth knowing is what the new tests now watch, because these emits touch files
|
|
382
|
+
you co-own and files you own outright. Your `settings.json` / `settings.local.json` hook
|
|
383
|
+
merge and the managed block inside `CLAUDE.md` / `AGENTS.md` are compared byte for byte
|
|
384
|
+
between the two runtimes for the first time, and so are the cases that only happen on a
|
|
385
|
+
real machine: an install migrating a `memory/` or `notebook/` store in from an older
|
|
386
|
+
bundle, a project `.claude/` where you already put your own agent or `.gitignore`, and
|
|
387
|
+
every seeded-once file — `excludes.json`, `user-rules.md`, `PROFILE.md`, `wiki.jsonc`,
|
|
388
|
+
your memory index — **edited between two builds**, which is the only way a comparison can
|
|
389
|
+
prove a rebuild left them alone instead of rewriting them with the same bytes.
|
|
390
|
+
- **The port's fourth piece, and the first one you actually run: if you have Node
|
|
391
|
+
installed, `geneseed build` and `--emit opencode` now render through it.** This is the
|
|
392
|
+
first change in the port that touches your machine, and the point is that you should not
|
|
393
|
+
be able to tell — the bundle is byte-for-byte what Python produced, down to the progress
|
|
394
|
+
lines. No Node, or `GENESEED_NO_JS=1`, and the Python path runs exactly as before; there
|
|
395
|
+
is nothing to install and nothing to configure either way.
|
|
396
|
+
The new gate is what makes that claim checkable: it builds the same target twice, once
|
|
397
|
+
each way, and compares the files, both output streams and the exit code — including
|
|
398
|
+
cases a normal build never produces, like a second build over an existing one, a
|
|
399
|
+
hand-edited `.geneseed-srcdirs.json` pointing outside the bundle, and files you edited
|
|
400
|
+
between two builds that the harness promises never to overwrite. The build-comparison
|
|
401
|
+
harness now checks the console output too, which nothing had ever compared.
|
|
402
|
+
- **The port's third piece: the OpenCode extras — colour themes, the opt-in primary agent
|
|
403
|
+
and slash commands, the plugin and workflow copies, and the `agent-overrides.json`
|
|
404
|
+
stub.** Still nothing changes about running Geneseed; Python remains what builds your
|
|
405
|
+
harness. The point again is what the new test reaches. Two of these layers only exist
|
|
406
|
+
when `GENESEED_PRIMARY` or `GENESEED_COMMANDS` is set, so a normal build never writes
|
|
407
|
+
them and no build-and-compare test ever had — they are now checked in both languages
|
|
408
|
+
with the flags on and off, along with the "your overrides predate an upgrade" notice in
|
|
409
|
+
each of its four states.
|
|
410
|
+
- **The port's second piece: the layer that writes your host-native agents and skills now
|
|
411
|
+
exists in JavaScript too, with a test that covers the cases a normal build never
|
|
412
|
+
reaches.** Nothing about running Geneseed changes yet — Python still builds your harness.
|
|
413
|
+
What is new is the gate. Until now every acceptance test emitted into an empty folder with
|
|
414
|
+
an empty `agent-overrides.json`, so three behaviours had never been checked in either
|
|
415
|
+
language: what happens when you *have* overrides, what happens when a file already exists
|
|
416
|
+
that Geneseed did not write (it is left alone, and you are told), and what the three host
|
|
417
|
+
dialects do differently. `tests/test_native_layer_parity.py` runs all of them in both
|
|
418
|
+
languages and compares the files, the ownership record and the warnings.
|
|
419
|
+
- **A bug this found before anyone hit it:** an `agent-overrides.json` setting
|
|
420
|
+
`"temperature": 1.0` would have emitted `temperature: 1.0` from Python and
|
|
421
|
+
`temperature: 1` from JavaScript, because JavaScript has one number type where Python has
|
|
422
|
+
two. No build-and-compare test could have caught it — the build always writes an *empty*
|
|
423
|
+
overrides file, so no such test has ever had an override to render. Fixed, and pinned by a
|
|
424
|
+
test that compares number formatting directly.
|
|
425
|
+
- **The generator's render core now exists in JavaScript as well as Python, and a test
|
|
426
|
+
proves the two produce identical bytes.** Nothing about running Geneseed changes yet —
|
|
427
|
+
Python is still what builds your harness — but this is the first piece of the runtime to
|
|
428
|
+
be ported, and it lands with the gate that will keep the rest honest:
|
|
429
|
+
`tests/test_render_parity.py` renders every theme in both languages, on every footprint,
|
|
430
|
+
catalogue, posture and mode axis, writes both trees to disk and compares them byte for
|
|
431
|
+
byte. Writing to disk rather than comparing strings is deliberate: on Windows, Python's
|
|
432
|
+
text writer silently turns every `\n` into `\r\n` and Node's does not, so a port that
|
|
433
|
+
skipped that detail would differ in every single file while looking correct in a diff
|
|
434
|
+
viewer.
|
|
435
|
+
- **Every emit now runs its stages in one fixed order** — render everything Geneseed owns,
|
|
436
|
+
then reconcile the files you co-own (`settings.json`, `opencode.json`, the CLAUDE.md
|
|
437
|
+
block), then prune, then record the manifest, then verify. Three emits used to interleave
|
|
438
|
+
those stages differently. Output is unchanged, byte for byte, on all 259 theme × host ×
|
|
439
|
+
footprint combinations; what changes is that there is now a single seam between "files
|
|
440
|
+
Geneseed writes wholesale" and "files you co-own", which is what lets the render half
|
|
441
|
+
move to another language without the merge logic following it.
|
|
442
|
+
- **Emitted hooks now go through a stable shim, so moving the checkout no longer kills
|
|
443
|
+
every install at once.** Until now each of the four Claude/Bob hook commands embedded
|
|
444
|
+
two machine-absolute paths — this machine's Python interpreter and this clone's
|
|
445
|
+
`rituals/harness.py` — directly in your `settings.json`. Relocating or replacing the
|
|
446
|
+
checkout therefore broke the gates in every deployed install simultaneously, and the
|
|
447
|
+
only repair was re-emitting every config. The emit now writes one small shim at
|
|
448
|
+
`~/.geneseed/bin/geneseed-hook` (`geneseed-hook.cmd` on Windows, relocatable with
|
|
449
|
+
`GENESEED_HOME`) and points every hook at that single stable path; the shim holds the
|
|
450
|
+
two volatile paths instead. Re-pointing every install at a new checkout is now one
|
|
451
|
+
file write. The shim is refreshed on every emit — that refresh is what replaces the
|
|
452
|
+
accidental self-heal the old form had, since a config that no longer names the
|
|
453
|
+
checkout can no longer detect that the checkout moved — and a new `doctor` gate reads
|
|
454
|
+
it back and reports a shim that points at nothing. The shim is deliberately silent:
|
|
455
|
+
`git-gate` and `rule-gate` return success on every path and signal their verdict as
|
|
456
|
+
JSON on **stdout**, so a single stray byte would turn a blocking gate into a silently
|
|
457
|
+
permissive one. Existing installs migrate on their next build — the manifest-driven
|
|
458
|
+
prune replaces the old hook groups exactly, and the orphan scan now recognises both
|
|
459
|
+
the legacy and the shim shape so a stranded hook still surfaces.
|
|
460
|
+
- **The `rule` skill becomes the front door to both durable stores, behind a Law VI
|
|
461
|
+
gate**: nothing reaches `user-rules.md` or `memory/` on the agent's own initiative
|
|
462
|
+
any more. The skill now opens on a fork it must put to the user — *a standing rule,
|
|
463
|
+
or a fact to remember?* — because the agent silently arbitrating that was the actual
|
|
464
|
+
defect: a passing preference got legislated as a permanent rule, or a real rule was
|
|
465
|
+
filed away as a forgettable note. The memory branch asks for the binding `force`
|
|
466
|
+
(constraint · choice · conviction · tempered) and shows the exact file, frontmatter
|
|
467
|
+
included, before writing. The rule branch pressure-tests instead of drafting: the
|
|
468
|
+
user restates the rule as they would to a colleague on day one and gets interrupted
|
|
469
|
+
on jargon they cannot unpack, a missing step, or a simplification that makes the rule
|
|
470
|
+
false (the feynman skill's mechanic, borrowed — not delegated to); then a **mandatory
|
|
471
|
+
counter-example**, where the agent builds the case the rule would harm and the user
|
|
472
|
+
must either accept it or narrow the rule. A rule that cannot survive its own worst
|
|
473
|
+
case was never generic, only never contradicted. The asymmetry in cost between the
|
|
474
|
+
two branches is deliberate — cheap to remember, expensive to legislate, or the rule
|
|
475
|
+
set inflates. Enforced at the tool boundary, not just in prose: a new
|
|
476
|
+
`harness.py rule-gate` PreToolUse hook makes Claude Code and Bob **ask** before any
|
|
477
|
+
write to `user-rules.md` or a memory file, and `geneseed-guard.js` speed-bumps the
|
|
478
|
+
first such write on OpenCode (its `tool.execute.before` has no ask tier — a re-issued
|
|
479
|
+
write goes through, so nothing is ever trapped). Copilot has no hook mechanism and is
|
|
480
|
+
held by the Law and the preamble alone.
|
|
481
|
+
- **`token-report` folder skill — session token usage breakdown on every host**: a
|
|
482
|
+
first-party folder skill (the first non-vendored entry in `VENDORED_SKILL_DIRS`,
|
|
483
|
+
which the folder mechanism carries because it bundles an executable script) that
|
|
484
|
+
renders the session's token usage as markdown tables: exact recorded totals
|
|
485
|
+
(output, fresh input, cache reads/writes; main thread vs subagents), context
|
|
486
|
+
window occupancy (session-start harness baseline, current/peak vs limit), an
|
|
487
|
+
estimated per-category attribution of what filled the context (user messages,
|
|
488
|
+
replies, thinking, per-tool calls/results, injected skill content), and the
|
|
489
|
+
heaviest single items. `scripts/token_report.py` auto-detects the host by most
|
|
490
|
+
recent session activity: exact usage on Claude Code, IBM Bob (`$BOB_CONFIG_DIR`
|
|
491
|
+
honoured) and OpenCode; best-effort harvesting on GitHub Copilot, whose
|
|
492
|
+
session-state schema is undocumented. OpenCode reads the v1.2+ SQLite store
|
|
493
|
+
(`opencode.db`: `session`/`message`/`part` tables, JSON `data` columns,
|
|
494
|
+
step-finish fallback when a message record carries no tokens, child sessions
|
|
495
|
+
attributed as subagent usage) and falls back to the pre-1.2 `storage/` JSON
|
|
496
|
+
files when no DB exists. Carrier ceiling (full) raised 49_000 → 51_000 for
|
|
497
|
+
the new AGENT.md folder-skill entry.
|
|
498
|
+
- **GitHub Copilot host — `--emit copilot` / `--emit copilot-global`**: the fourth
|
|
499
|
+
first-class host, riding the Claude-shaped emit engine. Per-repo: root `AGENTS.md`
|
|
500
|
+
(auto-loaded by the Copilot CLI, coding agent, and VS Code agent mode) + a layer in
|
|
501
|
+
the shared `.github/` dir — `agents/<name>.agent.md` in Copilot's custom-agent
|
|
502
|
+
dialect (`tools:` allowlist for read-only agents, sibling links rewritten to the
|
|
503
|
+
`.agent.md` extension) and byte-identical `skills/` (Copilot Agent Skills).
|
|
504
|
+
Personal: `~/.copilot` (`$COPILOT_CONFIG_DIR` relocates) with the preamble as a
|
|
505
|
+
managed block in `copilot-instructions.md`, which the CLI auto-loads — no Bob-style
|
|
506
|
+
rules-folder workaround needed. Copilot has no settings.json or hook mechanism, so
|
|
507
|
+
the settings/hooks/excludes stage is skipped entirely (memory rides the preamble's
|
|
508
|
+
instructions); with no exclude mechanism either, the global emit warns when project
|
|
509
|
+
installs exist (both preambles stack). Writing into `.github/` is safe by
|
|
510
|
+
construction: the ownership manifest + claim-on-create never touch user files.
|
|
511
|
+
Full lifecycle parity — setup wizard/TUI rows, web console deploy option +
|
|
512
|
+
Harnesses rows, MCP wiring (`~/.copilot/mcp-config.json`, `mcpServers` with the
|
|
513
|
+
CLI's required `type`/`tools` keys, global-only), doctor per-repo emit validation,
|
|
514
|
+
rebuild-all, diff/restore, deactivate/reactivate/uninstall, footprint dial, and
|
|
515
|
+
theme detection via the `copilot-instructions.md` sigil fallback.
|
|
516
|
+
- **User rules — `user-rules.md`**: a seed-once file beside AGENT.md for the user's
|
|
517
|
+
own standing rules, obeyed with the same force as the laws (they may tighten a
|
|
518
|
+
law, never repeal one). Same host-state contract as `context.json`: every emit
|
|
519
|
+
seeds it once, never overwrites it, never records it in an owned manifest — so
|
|
520
|
+
user governance survives updates, reinstalls, and theme switches; unlike
|
|
521
|
+
`context.json` it is committable, so project rules can travel with a repo and
|
|
522
|
+
bind the team. Named `user-rules.md` (not `rules.md`) because the neutral theme
|
|
523
|
+
renders the laws themselves as "Rules". The context plugin and Claude hook
|
|
524
|
+
eager-load it in discovery mode. A new **rule skill** drafts and triages rules
|
|
525
|
+
(rule vs memory vs `context.json` vs already-covered), refuses law conflicts,
|
|
526
|
+
promotes recurring feedback memories into trial rules with consent, and runs
|
|
527
|
+
the review flow (graduate / demote / delete). Memory and notebook READMEs now
|
|
528
|
+
route "share with the team" there instead of the regenerated laws.
|
|
529
|
+
- **Web console Rules page** (`#/rules`, right under Laws in the rail): list your
|
|
530
|
+
rules with scope and trial chips, add/edit/retire them, graduate a trial rule,
|
|
531
|
+
and watch a budget meter that turns amber as the always-loaded set grows. A
|
|
532
|
+
**Promote to rule** control on memory facts turns a recurring lesson into a
|
|
533
|
+
trial rule with provenance and deletes the source fact. Backed by
|
|
534
|
+
`GET/POST /api/rules` + `/api/rules/promote` (token-gated); every write carries
|
|
535
|
+
a content fingerprint and 409s when an agent session edited the file
|
|
536
|
+
concurrently, and mutations splice one rule's block — the rest of the user's
|
|
537
|
+
file is never regenerated.
|
|
538
|
+
|
|
539
|
+
### Fixed
|
|
540
|
+
- **On Windows, `geneseed build > log.txt` wrote an empty log.** Anything the harness ran as
|
|
541
|
+
a child process — the builder behind `build` and `rebuild-all`, and the same builder behind
|
|
542
|
+
the web UI's "build all" — had its output silently thrown away whenever the harness's own
|
|
543
|
+
output was redirected to a file or a pipe rather than going straight to a terminal. In a
|
|
544
|
+
terminal it looked fine, which is why it survived: the flag that suppresses console
|
|
545
|
+
pop-ups also hands the child a fresh hidden console to print into when nobody has asked
|
|
546
|
+
for the output to be piped. It is now applied only when the harness is capturing the child
|
|
547
|
+
itself, which is the case it was added for; console pop-ups are still suppressed there.
|
|
548
|
+
Found by the Node port — the same command printed the builder's summary line on one side
|
|
549
|
+
and nothing on the other.
|
|
550
|
+
- **The golden acceptance harness could render into your real install.** `tests/golden.py`
|
|
551
|
+
runs the generator over 259 cells, ~126 of which are `*-global` emits whose whole job is
|
|
552
|
+
to write into a host's global config dir, and it sandboxes them by redirecting `HOME`
|
|
553
|
+
and `XDG_CONFIG_HOME`. That was not enough: each host resolver checks its own relocation
|
|
554
|
+
variable *first* and returns before ever consulting those paths, so anyone with
|
|
555
|
+
`OPENCODE_CONFIG_DIR` set — the documented way to keep the harness in a git-tracked
|
|
556
|
+
folder — had every global cell rendering straight into the real target. Reproduced
|
|
557
|
+
against the pre-fix code: a single `opencode-global` cell wrote 135 files outside the
|
|
558
|
+
sandbox. The cell environment now clears `OPENCODE_CONFIG_DIR`, `BOB_CONFIG_DIR` and
|
|
559
|
+
`COPILOT_CONFIG_DIR`, plus every `GENESEED_*` knob except the one it sets itself —
|
|
560
|
+
cleared by prefix, so a knob added later is neutralised by default. Four tests pin it,
|
|
561
|
+
including one that re-derives the variable list from `_build_core`'s own source rather
|
|
562
|
+
than trusting a hand-written list to stay current.
|
|
563
|
+
- **Every login launcher told you to start the web UI in the foreground**: the VBS,
|
|
564
|
+
the `schtasks` task and the macOS LaunchAgent in SETUP.md (and its `autostart`
|
|
565
|
+
web slice) all ran `geneseed web --no-browser`. Only `web start` daemonizes and
|
|
566
|
+
writes the `.geneseed-web.json` pid record — bare `web` blocks in the foreground
|
|
567
|
+
and records nothing, so the server that came up at every login was invisible to
|
|
568
|
+
`web stop`, `web restart` and `web status`. They reported "no live server" while
|
|
569
|
+
it kept serving; worse, `restart` then spawned a second daemon that could not bind
|
|
570
|
+
the taken port, leaving three live processes and the *stale* one still answering.
|
|
571
|
+
That is how a `web/dist` rebuild turned into hard MIME failures in the browser: the
|
|
572
|
+
old server kept handing out the previous `index.html`, whose chunk hashes no longer
|
|
573
|
+
existed on disk, and the SPA 404-fallback returned them as `text/html`. All four
|
|
574
|
+
launchers now use `web start`, and the section says why in a callout.
|
|
575
|
+
- **Laws XXXVI and XXXVII render their Principle in the web ledger**: both shipped
|
|
576
|
+
with no row in `LAW_META` (`web/src/pages/Laws.jsx`), the map that holds each
|
|
577
|
+
rule's one-line Principle — display copy that lives nowhere else in the tree. An
|
|
578
|
+
absent row falls back to `['craft', '']`, so the two newest laws showed a blank
|
|
579
|
+
description and a wrong class chip while everything upstream stayed correct: the
|
|
580
|
+
catalog served them, the page rendered, `LAW_CLASS` was complete, doctor and both
|
|
581
|
+
suites were green. Rows added (XXXVI · security, XXXVII · process), and `doctor`
|
|
582
|
+
gained the gate that was missing (`_law_meta_problems`): every rule in
|
|
583
|
+
`universal.md` must have a `LAW_META` row with a non-empty principle and a known
|
|
584
|
+
class that agrees with `LAW_CLASS`, and no row may outlive its rule. Sibling of
|
|
585
|
+
the `LAW_CLASS` completeness gate added after Law XXXV shipped mis-classified —
|
|
586
|
+
same failure shape, the other half of the pair. `DESIGN.md` now lists the six
|
|
587
|
+
satellite edits a new Law drags along, so the next one is a checklist, not a
|
|
588
|
+
rediscovery.
|
|
589
|
+
- **Claude/Bob emits no longer ship dead skill-table links**: CLAUDE.md/AGENTS.md's
|
|
590
|
+
per-row skill/agent links (e.g. `.claude/skills/council.md`) were dead — the
|
|
591
|
+
native layer writes each skill as a folder (`.claude/skills/council/SKILL.md`).
|
|
592
|
+
`_strip_capability_links` already ran on this path, but `CAPABILITY_LINK_RE`
|
|
593
|
+
only matched a BARE `agents/`/`skills/` prefix; the claude/bob project-scope
|
|
594
|
+
render re-prefixes those tokens (`.claude/`, `.bob/`, `../`), which slid straight
|
|
595
|
+
past the regex. It now tolerates an optional relative-path prefix (never
|
|
596
|
+
`http(s)://` or a leading `/`), so the existing strip catches every prefixed form
|
|
597
|
+
too — same fix benefits the OpenCode emits' own prefixed edge cases. `doctor`
|
|
598
|
+
gained a matching check (`_claude_bob_emit_problems`): it previously validated
|
|
599
|
+
the `files` build and the opencode-global emit but never the claude/bob per-repo
|
|
600
|
+
emits, which is why this shipped unnoticed; `--validate-only --emit claude`/`bob`
|
|
601
|
+
are clean again, and the stale SETUP.md "known limitation" note is removed.
|
|
602
|
+
- **Renamed DIR_* dirs in the portable bundle no longer orphan**: the bundle's
|
|
603
|
+
owned dirs (`laws`/`agents`/`skills`, in their themed form) are wiped and
|
|
604
|
+
rebuilt each run, but the wipe was keyed only to the CURRENT theme's dir name —
|
|
605
|
+
if a theme ever renamed one of them between two builds into the same target,
|
|
606
|
+
the old dir was never targeted and lingered forever. A new local marker
|
|
607
|
+
(`.geneseed-srcdirs.json`) now remembers which dir name was actually used last
|
|
608
|
+
time, so a rename is also pruned. (Shipped themes don't currently vary DIR_*, so
|
|
609
|
+
this is future-proofing rather than an active drift; the global/Claude/Bob
|
|
610
|
+
scopes' equivalent case — a lean-footprint standalone laws dir surviving a
|
|
611
|
+
switch back to full — is already covered by the owned-file manifest.)
|
|
612
|
+
- **Bob installs now actually load the preamble/theme**: IBM Bob's only
|
|
613
|
+
always-injected instruction channel is the rules folder — a global
|
|
614
|
+
`~/.bob/AGENTS.md` is never auto-loaded (only a project-root one is), which left
|
|
615
|
+
Bob installs with working skills but no harness voice. Both Bob emits now also
|
|
616
|
+
ship the preamble as `rules/geneseed.md` (project `.bob/rules/`, global
|
|
617
|
+
`~/.bob/rules/`). The Claude-only `claudeMdExcludes` key is no longer written for
|
|
618
|
+
Bob (its Bob semantics are undocumented and a filename-keyed match would suppress
|
|
619
|
+
the project's own `AGENTS.md`); a re-emit strips one left by an older install.
|
|
620
|
+
Project-bypasses-global on Bob now rides on its native rule precedence: the
|
|
621
|
+
workspace `rules/geneseed.md` shadows the same-named global rule.
|
|
622
|
+
- **Lean installs no longer report permanent phantom drift — and Restore no longer
|
|
623
|
+
converts them to full**: everything that renders an "expected" copy of an install
|
|
624
|
+
must render it at that install's OWN footprint, read from its `.geneseed-footprint`
|
|
625
|
+
marker. Three callers did not. `diff` (and the Local-edits panel it feeds) rendered
|
|
626
|
+
at `full`, so every lean install reported two edits it could never clear by
|
|
627
|
+
rebuilding — `AGENT.md` (terse §1 digest vs the inlined laws) and
|
|
628
|
+
`laws/universal.md`, which only the lean global emit writes. `doctor` validated the
|
|
629
|
+
full emit only, so a lean-only regression could ship green. Worst of the three,
|
|
630
|
+
`Restore` in the web console rendered at `full` too: discarding a local edit on a
|
|
631
|
+
lean install rewrote `AGENT.md` with the inlined laws and DELETED
|
|
632
|
+
`laws/universal.md` — silently promoting the install to a full footprint. All three
|
|
633
|
+
now read the marker. Note that the web UI serves the code it was launched with:
|
|
634
|
+
restart the daemon (`geneseed web restart`) after upgrading, or the panel keeps
|
|
635
|
+
reporting the old verdict.
|
|
636
|
+
|
|
637
|
+
### Changed
|
|
638
|
+
- **The host-config wiring moved into its own module, `_build_settings.py`.** The emit was
|
|
639
|
+
doing two unrelated jobs in one file: computing bundle content, and reconciling
|
|
640
|
+
Geneseed's claim inside files you also edit — `settings.json`, `opencode.json`, the
|
|
641
|
+
managed `CLAUDE.md` block — through JSONC parsing and surgical merges. The second job is
|
|
642
|
+
not really part of generation at all: nine of its ten entry points are called by the
|
|
643
|
+
*runtime* (deactivate, remerge, reactivate, uninstall, plus `exclude` and `mcp`), not by
|
|
644
|
+
a build. Splitting them takes `_build_emit.py` from 1466 lines to 734 and leaves a layer
|
|
645
|
+
whose dependency closure points one way only — nothing in it calls back into the render
|
|
646
|
+
or emit code. Nothing moved namespace: `build.py` splices the new module alongside the
|
|
647
|
+
others, so every existing call site resolves unchanged, and emitted output is identical
|
|
648
|
+
across all 259 golden cells. If you monkeypatch any of it, patch `_build_settings` —
|
|
649
|
+
patching another submodule's spliced copy binds a copy the real caller never reads, and
|
|
650
|
+
a test now fails on that shape.
|
|
651
|
+
- **The generator's configuration now has one owner instead of five copies.** `build.py`
|
|
652
|
+
splices its four `_build_*` submodules into a shared namespace, which gave each of them
|
|
653
|
+
its own copy of `SRC`, `THEMES`, `ROOT`, `CONFIG`, `PLUGIN_SRC`, `WORKFLOW_SRC`,
|
|
654
|
+
`COLOR_THEMES`, `CAPABILITY_LINK_RE`, `VENDORED_SKILL_DIRS`, the four
|
|
655
|
+
`_<host>_config_dir` resolvers and the posture/mode selection — and forced a facade
|
|
656
|
+
`__setattr__` that mirrored every write out to all four so that redirecting one
|
|
657
|
+
actually reached the render code. `_build_core` now owns those names outright: they are
|
|
658
|
+
held back from both its `__all__` and the splice, so no copy exists, and the mirror is
|
|
659
|
+
deleted. Emitted output is unchanged — verified byte-for-byte against the previous
|
|
660
|
+
revision across the full 259-cell matrix (14 themes × 9 emit modes × 2 footprints, plus
|
|
661
|
+
every posture and mode). Two consequences for anyone working on the generator: read
|
|
662
|
+
them as `_build_core.SRC`, not a bare `SRC` (a bare one now raises `NameError` instead
|
|
663
|
+
of silently reading a stale copy), and redirect them by writing `_build_core.SRC` —
|
|
664
|
+
`build.SRC` still reads but refuses writes, because `mock.patch.object(build, "SRC", …)`
|
|
665
|
+
deleted rather than restored the attribute on exit and leaked the redirect into every
|
|
666
|
+
later test in the process. A test now walks the suite and fails on any redirect of a
|
|
667
|
+
shared-but-unowned name, the shape that quietly stops covering what it claims to —
|
|
668
|
+
`_opencode_config_dir` was already in that state, one missing `cfg=` argument away from
|
|
669
|
+
sending a global emit into the developer's own `~/.config/opencode`.
|
|
670
|
+
- **`docs/specs/`, `docs/reviews/`, and `docs/superpowers/` are local working docs
|
|
671
|
+
now**: untracked from git and added to `.gitignore`. They are per-machine work
|
|
672
|
+
artifacts (dated specs are drafted, executed, then dropped — the existing
|
|
673
|
+
lifecycle); the repo's prose (README, DESIGN, SHIPPED) no longer links them as
|
|
674
|
+
distributed folders, and SHIPPED.md states its spec links are historical
|
|
675
|
+
pointers into that local record.
|
|
676
|
+
- **Bob installs stopped double-paying the preamble**: a per-repo Bob install's
|
|
677
|
+
`.bob/rules/geneseed.md` is now a slim shadow stub instead of a full second copy
|
|
678
|
+
of the preamble — the repo-root `AGENTS.md` (auto-loaded) carries the
|
|
679
|
+
instructions, and the stub's only job is to shadow the same-named global rules
|
|
680
|
+
file (Bob injects every workspace rule each turn, so the full copy doubled the
|
|
681
|
+
install's fixed per-turn token cost). The global Bob emit no longer writes
|
|
682
|
+
`~/.bob/AGENTS.md` at all — Bob never auto-loads a global one; `rules/geneseed.md`
|
|
683
|
+
is the sole carrier — and a re-emit removes the stale copy an older install left
|
|
684
|
+
behind. Existing installs heal on the next rebuild/upgrade.
|
|
685
|
+
- **Self-update is now `git pull`**: `geneseed upgrade`/`update`/`sync-self` fast-forward
|
|
686
|
+
the install's own git origin (host-agnostic — wherever it was cloned from), doctor-gate
|
|
687
|
+
the result (rolling back on failure), then rebuild — replacing the bespoke curl/urllib
|
|
688
|
+
archive-zip download stack. A dirty tree or non-git checkout is reported (CLI message + a
|
|
689
|
+
web info popup) instead of failing mid-run.
|
|
690
|
+
|
|
691
|
+
### Removed
|
|
692
|
+
- The offline `geneseed upgrade --zip <file>` path and the web "Offline package" download
|
|
693
|
+
(`/api/offline-zip`) — use `git pull` directly.
|
|
694
|
+
|
|
695
|
+
### Added
|
|
696
|
+
- **Per-agent memory** — each capability agent now keeps durable lessons in
|
|
697
|
+
`memory/agents/<name>.md`. Every agent spec reads its own file first at dispatch
|
|
698
|
+
(step 0 of its procedure); the write-back is mechanical and lands on **all three
|
|
699
|
+
hosts equally**: the OpenCode `geneseed-learn` plugin distils a finished subagent
|
|
700
|
+
session into one per-agent lesson, and the claude/bob emits gain a `SubagentStop`
|
|
701
|
+
hook that routes to the same Python path (`learn` reads the payload's
|
|
702
|
+
`hook_event_name`). Unresolvable subagent name → silent no-op, never a wrong write.
|
|
703
|
+
- **`learn --consolidate`** — rebuilds `MEMORY.md` from the fact files on disk:
|
|
704
|
+
re-indexes orphaned facts, prunes dead index lines, and reports duplicate
|
|
705
|
+
descriptions for the user to merge (never auto-merged).
|
|
706
|
+
- **`dispatch` workflow** — a saved OpenCode workflow that decomposes a multi-domain
|
|
707
|
+
goal, routes each subtask to its owning capability agent, and converges the
|
|
708
|
+
results. Where a host has no `workflow` tool, the same shape runs model-driven via
|
|
709
|
+
the parallel-agents skill. The **handoff envelope** (subtask goal, inputs, output
|
|
710
|
+
contract; no commit/push — Law XX stays with the caller; gaps reported, never
|
|
711
|
+
invented) is now written into `AGENT.md` for every emit, the OpenCode orchestrator,
|
|
712
|
+
the parallel-agents skill, and the agent template.
|
|
713
|
+
- **Downgrade warning + stale-overrides notice**: re-emitting over an existing
|
|
714
|
+
install now compares the deployed release (stamped in `.geneseed-version`
|
|
715
|
+
alongside the fingerprint) against the source tree's `harness.config.json`
|
|
716
|
+
version and prints a loud, warn-only notice when the deployed build is newer
|
|
717
|
+
("did you forget git pull?") — never blocks, since a deliberate downgrade must
|
|
718
|
+
stay possible. `agent-overrides.json` is now stamped with `_version` at
|
|
719
|
+
creation; the file itself is never rewritten on re-emit, but if it carries real
|
|
720
|
+
overrides and its `_version` no longer matches the source, a one-line notice
|
|
721
|
+
points you at reviewing them against the updated agent specs.
|
|
722
|
+
- **`build.py --validate-only`**: a dry run — full render, all doctor validations,
|
|
723
|
+
and a sandboxed emit of the requested target, written to a temp dir and
|
|
724
|
+
discarded. Exits non-zero on any problem, writes nothing real. (Note: `--emit
|
|
725
|
+
claude|bob` currently reports known pre-existing dead skill-link problems;
|
|
726
|
+
that fix is tracked separately.)
|
|
727
|
+
- **`build.py --sync-themes`**: fills any key `themes/_TEMPLATE.json` has but a
|
|
728
|
+
theme JSON is missing — surgical line insertion in template order (no file
|
|
729
|
+
churn), never removes extras, and exits 1 when it changed files so CI can use
|
|
730
|
+
it as a check. The doctor's parity failure now points at it.
|
|
731
|
+
- **`AGENT_COLORS` theme key**: the OpenCode agent→colour-slot map moved from a
|
|
732
|
+
hardcoded table in the emitter into `themes/_TEMPLATE.json` (and all shipped
|
|
733
|
+
themes), so a theme can restyle agent UI grouping. Unknown slot values warn
|
|
734
|
+
and fall back to `secondary`; themes missing the key fall back to the old
|
|
735
|
+
built-in map.
|
|
736
|
+
- **Ask-tier bash for research agents**: `explorer` and `empiricist` now carry
|
|
737
|
+
the same marker `historian` already had — OpenCode emits `bash: ask` (instead
|
|
738
|
+
of deny) and Claude Code leaves Bash to its own permission prompts, so
|
|
739
|
+
read-only searches (grep, git log) no longer dead-end. Every other read-only
|
|
740
|
+
agent keeps the blanket deny.
|
|
741
|
+
- **`.opencode/` re-emits stopped wiping user files**: the project OpenCode emit
|
|
742
|
+
now tracks what it owns in `.opencode/.geneseed-manifest.json` and prunes only
|
|
743
|
+
stale owned files (write-before-delete), skipping user-authored files with a
|
|
744
|
+
warning — the same claim-on-create model the Claude path always had. The first
|
|
745
|
+
re-emit over a pre-manifest install treats existing files as yours and says so.
|
|
746
|
+
- **`harness uninstall` hardening**: a global uninstall now prints an inventory of
|
|
747
|
+
any surviving PROJECT installs elsewhere (each is self-contained — its hooks call
|
|
748
|
+
the shared checkout by absolute path, not the global config dir being removed —
|
|
749
|
+
so nothing is touched, just listed with the exact `--target` to remove it too); a
|
|
750
|
+
project uninstall now checks whether another host (Claude/OpenCode/Bob) also has
|
|
751
|
+
an install at the same repo root and says so. A settings.json left with a
|
|
752
|
+
leftover/locked owned file (Windows-plausible) no longer silently drops its
|
|
753
|
+
`.geneseed-emit` marker — the marker is kept and the run is reported INCOMPLETE
|
|
754
|
+
so the install can be found and retried. After every settings.json merge/unwire
|
|
755
|
+
(emit, deactivate, uninstall), a new integrity check (`_settings_integrity_check`)
|
|
756
|
+
verifies the manifest's claimed hooks/excludes actually match the file and warns
|
|
757
|
+
(never auto-fixes) on drift or an unrecorded Geneseed-pattern hook left behind.
|
|
758
|
+
- **Project bypasses global harness**: when a repo carries its own Geneseed
|
|
759
|
+
install, the same host's GLOBAL harness no longer double-loads there. For
|
|
760
|
+
Claude/Bob a project emit writes the global preamble into `claudeMdExcludes`
|
|
761
|
+
(native, repo-scoped) and the global SessionStart context hook stands down via
|
|
762
|
+
an up-walk marker check — so a session started anywhere in the repo gets the
|
|
763
|
+
project harness only, and the global one elsewhere. OpenCode already scopes its
|
|
764
|
+
context to the cwd (the context plugin dedups), and its `instructions[]`
|
|
765
|
+
preamble double-load remains the documented harmless cost (moving it would
|
|
766
|
+
strip subagents of the laws). Opt out — restore stacking — with
|
|
767
|
+
`GENESEED_STACK_GLOBAL=1` (honoured at emit and in the hook).
|
|
768
|
+
- **Law XXI — Commands Must Return**: a non-interactive-shell law forbidding
|
|
769
|
+
commands that hang on a TTY (interactive prompts, pagers, REPLs, editors,
|
|
770
|
+
unbounded processes) and directing the agent to the non-interactive form
|
|
771
|
+
(`--yes`, `--no-pager`, piped input, bounded long runs). Brings the law count
|
|
772
|
+
to 21. (Distilled from awesome-opencode's *Shell Strategy* plugin.)
|
|
773
|
+
- **Context plugin — self-awareness & command discovery**: `geneseed-context`
|
|
774
|
+
now surfaces the session's live model (read from the transcript, with a
|
|
775
|
+
`GENESEED_MODEL` fallback) and the project's runnable command targets
|
|
776
|
+
(`Makefile`, `package.json` scripts, `justfile`, `Taskfile`) in the injected
|
|
777
|
+
PROJECT CONTEXT block. (Distilled from awesome-opencode's *Model Announcer* and
|
|
778
|
+
*Command Inject* plugins.)
|
|
779
|
+
- **`geneseed-notify` plugin** (OpenCode): a fifth plugin that sends a native,
|
|
780
|
+
dependency-free OS notification (macOS `osascript`, Linux `notify-send`, Windows
|
|
781
|
+
PowerShell) when the agent finishes a turn — gated by `GENESEED_NOTIFY_MIN_SECONDS`
|
|
782
|
+
(default 30) so only genuinely long runs ping, and skipping subagent/throwaway
|
|
783
|
+
sessions. Toggle with `GENESEED_NOTIFY=off`. (Distilled from awesome-opencode's
|
|
784
|
+
*Opencode Notify*.)
|
|
785
|
+
- Three learning skills that teach the user rather than do the work for them:
|
|
786
|
+
- `crash-course` — go from zero to functional in a skill fast: what to learn
|
|
787
|
+
first, what to ignore, and the one high-leverage exercise.
|
|
788
|
+
- `drill` — turn shaky knowledge into reflex through Socratic practice on
|
|
789
|
+
realistic mistakes, withholding the answer until the user has tried.
|
|
790
|
+
- `decode` — make confusing material click via one keystone sentence, an
|
|
791
|
+
everyday analogy, and a three-question comprehension check.
|
|
792
|
+
These join `learning-path`, `gap-detector`, and `feynman`, bringing the
|
|
793
|
+
skill count to 33.
|
|
794
|
+
|
|
795
|
+
## [2.0.0] — not yet published
|
|
796
|
+
|
|
797
|
+
*Nothing described here has been published to any registry: there is no tag, no release and no
|
|
798
|
+
install URL. `harness.config.json` and `package.json` both read `2.0.0`, which is the version this
|
|
799
|
+
build stamps into every bundle it emits — it is not evidence that anything was shipped.*
|
|
800
|
+
|
|
801
|
+
*⚠ The bump itself was the last thing this release found. Moving the label reddened 224 of 259
|
|
802
|
+
recorded emit cells, because the configured version is stamped into two places and only one of them
|
|
803
|
+
was ever blanked before comparison: `.geneseed-version`'s `[release …]`, and — undestamped until
|
|
804
|
+
now — `"_version"` inside the `agent-overrides.json` stub in every bundle. It hid because the sweep
|
|
805
|
+
that added the first arm hunted the bracketed spelling, and because `1.0.0` and `2.0.0` are the same
|
|
806
|
+
length, so the file size never moved. Left unfixed, the frozen corpus would have pinned this project
|
|
807
|
+
at `1.0.0` forever — every bump, not just this one. The comparison now blanks both sites; no recorded
|
|
808
|
+
byte was edited. See `docs/limits.md`.*
|
|
809
|
+
|
|
810
|
+
### ⚠ Breaking — RE-INSTALL, do not upgrade
|
|
811
|
+
|
|
812
|
+
**If you installed Geneseed by cloning this repository, install the npm package fresh instead
|
|
813
|
+
of pulling this release into your checkout.** The reason is specific, and it is about your
|
|
814
|
+
hooks rather than about the code:
|
|
815
|
+
|
|
816
|
+
- A machine whose last emit ran through the old Python driver has a machine-wide hook shim at
|
|
817
|
+
`~/.geneseed/bin/geneseed-hook` whose body names your checkout's `rituals/harness.py`.
|
|
818
|
+
This release deletes that file. Pull 2.0 into that checkout and the shim points at nothing.
|
|
819
|
+
- **A dead gate does not shout.** `git-gate` (Law XX — approval before a commit or a push) and
|
|
820
|
+
`rule-gate` (Law VI — writes into your memory store) return 0 on *every* path and deliver
|
|
821
|
+
their verdict as a JSON document on **stdout**. No JSON, no verdict: the tool call proceeds
|
|
822
|
+
with nothing asked. A gate that cannot launch does not fail closed, it simply stops being
|
|
823
|
+
consulted — which is the failure you would rather find in release notes than in a diff you
|
|
824
|
+
did not approve. (The two gate commands are emitted without a `|| exit 0` tail, unlike the
|
|
825
|
+
`context` and `learn` hooks, so the launch failure itself is not swallowed. The missing
|
|
826
|
+
verdict still is.)
|
|
827
|
+
- **`geneseed doctor` catches the dead pointer.** Its shim check reads every quoted path back
|
|
828
|
+
out of the shim body and reports any that does not exist — `[shim] … pointed at …, which
|
|
829
|
+
does not exist — every hook in every install was dead`. That is the state a pulled checkout
|
|
830
|
+
leaves. It is *not* a check for "you are still on the old shape": a clone you leave untouched
|
|
831
|
+
keeps a shim whose two baked paths both still exist, so doctor is quiet about it and the
|
|
832
|
+
classification lives in `migrate` instead.
|
|
833
|
+
- **`geneseed migrate` is the repair**, and it is the supported path if you would rather move
|
|
834
|
+
an existing machine than start clean. It surveys every active install first and writes
|
|
835
|
+
nothing until the survey passes; it re-emits each one in *its own* theme, emit, footprint,
|
|
836
|
+
posture and mode; it refuses the whole run rather than guess at an install whose marker it
|
|
837
|
+
does not recognise; it copies every settings file it will touch and rolls all of them back if
|
|
838
|
+
any install fails, so you are never half-migrated; and it reports — never rewrites — hooks it
|
|
839
|
+
did not write and login-autostart entries you created by hand. `--dry-run` prints the plan.
|
|
840
|
+
A second run is a no-op. See *Migrate an existing install to npx* in the docs.
|
|
841
|
+
|
|
842
|
+
Either way, run `geneseed doctor` afterwards and confirm it reports no `[shim]` row.
|
|
843
|
+
|
|
844
|
+
### What this release actually guarantees
|
|
845
|
+
|
|
846
|
+
**Less than the previous one, and this is the honest place to say so.** Until now there were
|
|
847
|
+
two implementations of this harness side by side, and three harnesses ran both on every cell
|
|
848
|
+
and compared every emitted byte, both streams and the exit code. That second implementation is
|
|
849
|
+
deleted. What replaced it is a **recording** of the answers it gave, frozen under
|
|
850
|
+
`tests/__snapshots__/` and replayed against the code that ships.
|
|
851
|
+
|
|
852
|
+
A green replay says *this code still answers what it answered when the recording was taken.*
|
|
853
|
+
It does not say the answer was ever right: where the two implementations agreed and were both
|
|
854
|
+
wrong, the recording froze the agreement, and there is no longer a second party who could
|
|
855
|
+
disagree. The recordings also cannot be re-taken — every program that could write one is gone,
|
|
856
|
+
and the replayers refuse to record — so a change that moves a recorded byte is a finding rather
|
|
857
|
+
than a step. `docs/limits.md` is the standing list of what that costs, row by row, including
|
|
858
|
+
four strings that are known to be wrong and are now permanently unfixable.
|
|
859
|
+
|
|
860
|
+
### Removed
|
|
861
|
+
|
|
862
|
+
- **The second implementation.** 85 Python files, and with them the full-screen curses panel
|
|
863
|
+
(`tui` and `menu` are now verbs that refuse it by name and print the command list), the
|
|
864
|
+
Python launchers, and every `.py` in the tree — there are zero left.
|
|
865
|
+
- **The last Python inside a bundle.** The `token-report` skill shipped one script; it is now
|
|
866
|
+
`scripts/token_report.mjs` and runs under `node`. Nothing a bundle installs needs an
|
|
867
|
+
interpreter on any host, theme or footprint.
|
|
868
|
+
- **Python as a dependency of anything.** Including the one command you must always be able to
|
|
869
|
+
run: `geneseed upgrade` no longer shells out to an interpreter to update itself.
|
|
870
|
+
|
|
871
|
+
### Added
|
|
872
|
+
|
|
873
|
+
- **Three verbs that were never subcommands of the old CLI**, because they are new faces on
|
|
874
|
+
capabilities that had only ever been web endpoints:
|
|
875
|
+
- `geneseed catalog agents|skills|laws` — everything this harness ships, each with its
|
|
876
|
+
one-line purpose and lifecycle status.
|
|
877
|
+
- `geneseed mcp` — the MCP servers wired into each active install, and the presets on offer.
|
|
878
|
+
- `geneseed memory list|rm` — the facts the agent reads, and removal by name.
|
|
879
|
+
- **A package with zero runtime dependencies.** No `dependencies`, `peerDependencies` or
|
|
880
|
+
`optionalDependencies`, and a test that fails if any appear. Node 22.3.0 or newer, three
|
|
881
|
+
commands (`geneseed`, `geneseed-hook`, `geneseed-build`), and the standard library.
|
|
882
|
+
|
|
883
|
+
### Changed
|
|
884
|
+
|
|
885
|
+
- **All 25 subcommands and all four hook verbs answer from Node**, along with every web-console
|
|
886
|
+
endpoint and both generators. Nothing is left behind an interpreter.
|
|
887
|
+
- **`docs/port-ledger.md` is now `docs/limits.md`.** The file stopped being a ledger of a
|
|
888
|
+
migration in progress and became the standing answer to *what does this tool not prove about
|
|
889
|
+
itself?* — which outlives the port that started it. Read it before trusting a green suite.
|
|
890
|
+
|
|
891
|
+
## [1.0.0] — 2026-06-13
|
|
892
|
+
|
|
893
|
+
First stable release. The harness, its tooling, and the local web console are
|
|
894
|
+
feature-complete and validated by a dependency-free CI (doctor + unit/node/web
|
|
895
|
+
suites) on Linux and Windows.
|
|
896
|
+
|
|
897
|
+
### Harness
|
|
898
|
+
- One neutral `src/` rendered by a stdlib-only generator (`build.py`) into 14
|
|
899
|
+
themed, tool-agnostic bundles; structure stays theme-independent.
|
|
900
|
+
- 20 universal laws, 16 capability agents (6 execution + a 10-seat debate council),
|
|
901
|
+
30 skills, the one-fact-per-file memory convention, and the agent's sovereign
|
|
902
|
+
notebook.
|
|
903
|
+
|
|
904
|
+
### Tooling
|
|
905
|
+
- `geneseed` launchers for bash, cmd, and PowerShell; run-from-anywhere via
|
|
906
|
+
`link`/`unlink`; `bootstrap`/`upgrade`/`sync-self` with SHA-pinned, self-healing
|
|
907
|
+
updates.
|
|
908
|
+
- `doctor` (tokens, links, theme parity, authoring gates, bundle drift), `diff` +
|
|
909
|
+
improvements export, `status`/`version`, a curses TUI with a native-Windows VT
|
|
910
|
+
backend, and MCP wiring.
|
|
911
|
+
|
|
912
|
+
### Web console
|
|
913
|
+
- Local, offline, installable (PWA) browser UI over the deployed harness: Dashboard,
|
|
914
|
+
Library, Graph, Docs, Specs, Changes, Doctor, Themes, Settings, About, plus a
|
|
915
|
+
Spotlight search and a streaming job console. Background daemon; `127.0.0.1`-bound
|
|
916
|
+
with a per-session CSRF token on every mutation.
|
|
917
|
+
|
|
918
|
+
### Adapters
|
|
919
|
+
- OpenCode native agent/skill mapping and four plugins (context, learn, guard,
|
|
920
|
+
workflow); a Claude Code hook adapter.
|
|
921
|
+
|
|
922
|
+
### Documentation & quality (this release)
|
|
923
|
+
- Added a whole-project review (`docs/reviews/`), a `SHIPPED.md` capability registry,
|
|
924
|
+
and a `docs/web-ui.md` console guide; demarcated `docs/superpowers/` as an archive.
|
|
925
|
+
- Added `themes/_TEMPLATE.json` + a theme-authoring guide, routed every theme
|
|
926
|
+
enumeration through a single `build.theme_files()` helper (scaffolds excluded).
|
|
927
|
+
- Tightened the safety net: fixture tests for all three emit modes, self-tests for
|
|
928
|
+
the doctor parity gate, the `context_delivery` node suite wired into CI, and a
|
|
929
|
+
universal `prefers-reduced-motion` pass in the web UI.
|
|
930
|
+
- Removed a leaked authoring note from Law VII.
|
|
931
|
+
|
|
932
|
+
### Known follow-ups
|
|
933
|
+
Structural refactors identified in the review remain as post-1.0 work: generating the
|
|
934
|
+
`AGENT.md` capability tables from `src/`, unifying the three emit paths in `build.py`,
|
|
935
|
+
a route table for `web.py`, and replacing the `harness.py` namespace-merge facade with
|
|
936
|
+
explicit imports. None affect behaviour today.
|
|
937
|
+
|
|
938
|
+
[1.0.0]: https://github.com/Arylmera/Geneseed/releases/tag/v1.0.0
|