geneseed 3.3.0 → 3.4.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +3 -3
  3. package/SHIPPED.md +2 -2
  4. package/adapters/copilot/README.md +2 -1
  5. package/adapters/opencode/README.md +6 -2
  6. package/docs/extending.md +4 -3
  7. package/docs/web/agents.md +1 -1
  8. package/docs/web/first-session.md +1 -1
  9. package/docs/web/skills.md +1 -1
  10. package/harness.config.json +1 -1
  11. package/js/hosts/native.mjs +69 -15
  12. package/js/hosts/opencode.mjs +14 -0
  13. package/js/inspect/inventory.mjs +12 -7
  14. package/package.json +1 -1
  15. package/registry.json +86 -79
  16. package/src/AGENT.md.tmpl +14 -12
  17. package/src/agents/architect.md +4 -1
  18. package/src/agents/explorer.md +2 -0
  19. package/src/agents/operator.md +13 -0
  20. package/src/agents/pragmatist.md +12 -0
  21. package/src/agents/researcher.md +72 -0
  22. package/src/agents/security.md +7 -1
  23. package/src/agents/skeptic.md +2 -1
  24. package/src/agents/tester.md +5 -1
  25. package/src/agents/user-advocate.md +13 -0
  26. package/src/doctrines/rigor.md +1 -1
  27. package/src/skills/_self-improvement.md +19 -0
  28. package/src/skills/_template.md +1 -12
  29. package/src/skills/brainstorm.md +37 -19
  30. package/src/skills/bruno-collection-generator.md +1 -12
  31. package/src/skills/bruno-test-writer.md +1 -12
  32. package/src/skills/ci-fix.md +49 -0
  33. package/src/skills/codebase-design.md +1 -12
  34. package/src/skills/commit.md +1 -12
  35. package/src/skills/consolidate-memory.md +50 -0
  36. package/src/skills/council.md +1 -12
  37. package/src/skills/debug.md +1 -12
  38. package/src/skills/deps-audit.md +46 -0
  39. package/src/skills/develop.md +38 -20
  40. package/src/skills/document-project.md +1 -12
  41. package/src/skills/domain-modeling.md +1 -12
  42. package/src/skills/forge-mcp.md +1 -12
  43. package/src/skills/fresh-eyes.md +1 -12
  44. package/src/skills/frontend-design.md +1 -12
  45. package/src/skills/geneseed-code-review.md +1 -12
  46. package/src/skills/geneseed.md +1 -12
  47. package/src/skills/git-archaeology.md +1 -12
  48. package/src/skills/git-rescue.md +1 -12
  49. package/src/skills/handoff.md +1 -12
  50. package/src/skills/herdr.md +1 -12
  51. package/src/skills/ingest.md +1 -12
  52. package/src/skills/migrate.md +1 -12
  53. package/src/skills/opencode-theme.md +1 -12
  54. package/src/skills/parallel-agents.md +1 -12
  55. package/src/skills/pipeline.md +2 -13
  56. package/src/skills/plan.md +1 -12
  57. package/src/skills/ponytail.md +1 -12
  58. package/src/skills/profile.md +1 -12
  59. package/src/skills/prose.md +1 -12
  60. package/src/skills/prototype.md +1 -12
  61. package/src/skills/quiz.md +43 -0
  62. package/src/skills/refactor.md +1 -12
  63. package/src/skills/release.md +1 -12
  64. package/src/skills/repo-map.md +1 -12
  65. package/src/skills/research.md +5 -13
  66. package/src/skills/review-response.md +1 -12
  67. package/src/skills/roast-me.md +1 -12
  68. package/src/skills/rule.md +1 -12
  69. package/src/skills/security-audit.md +51 -0
  70. package/src/skills/ship.md +1 -12
  71. package/src/skills/skill-forge.md +59 -0
  72. package/src/skills/teach.md +50 -0
  73. package/src/skills/tickets.md +1 -12
  74. package/src/skills/wayfinder.md +1 -12
  75. package/src/skills/wiki.md +1 -12
  76. package/src/skills/workflow.md +74 -26
  77. package/src/skills/worktree.md +52 -0
  78. package/themes/_TEMPLATE.json +9 -8
  79. package/themes/biker.json +9 -8
  80. package/themes/commentator.json +9 -8
  81. package/themes/cyberpunk.json +9 -8
  82. package/themes/gamer.json +9 -8
  83. package/themes/imperial.json +9 -8
  84. package/themes/joker.json +9 -8
  85. package/themes/marvin.json +9 -8
  86. package/themes/mean.json +9 -8
  87. package/themes/military.json +9 -8
  88. package/themes/neutral.json +9 -8
  89. package/themes/pirate.json +9 -8
  90. package/themes/sports.json +9 -8
  91. package/themes/verstappen.json +9 -8
  92. package/themes/wizard.json +9 -8
  93. package/web/dist/assets/{Activity-BfVcLrda.js → Activity-DMGhhjQc.js} +1 -1
  94. package/web/dist/assets/{ActivityDetail-CQXccGPl.js → ActivityDetail-CeQcDA7e.js} +1 -1
  95. package/web/dist/assets/{CatalogRow-DALEQImZ.js → CatalogRow-CnSbDPyg.js} +1 -1
  96. package/web/dist/assets/{Diff-BIjxXx46.js → Diff-D_ksMBD1.js} +1 -1
  97. package/web/dist/assets/{Doctor-CJLbgsrw.js → Doctor-Brb3_oCT.js} +1 -1
  98. package/web/dist/assets/{FilterInput-CkUCk_lY.js → FilterInput-DbRWPhtT.js} +1 -1
  99. package/web/dist/assets/{GreenhouseView-DfC5IILJ.js → GreenhouseView-F3VNFr73.js} +1 -1
  100. package/web/dist/assets/{Harness-Dm5CCU-v.js → Harness-DJSwfYeF.js} +1 -1
  101. package/web/dist/assets/{JournalView-Cpu2eI4s.js → JournalView-BLRYRnB3.js} +1 -1
  102. package/web/dist/assets/{Laws-DDDVFuQz.js → Laws-CKYns9qe.js} +1 -1
  103. package/web/dist/assets/{Library-Dao3T9na.js → Library-BK0YloSv.js} +1 -1
  104. package/web/dist/assets/{Markdown-C__nuWX5.js → Markdown-BzTRzc7a.js} +1 -1
  105. package/web/dist/assets/{OperatorHudView-DEpCtAjP.js → OperatorHudView-D3OQSGp5.js} +1 -1
  106. package/web/dist/assets/{Profile-BlXtUlh2.js → Profile-CPA2u_0g.js} +1 -1
  107. package/web/dist/assets/{Rules-DIre6gxR.js → Rules-Lukel-Ru.js} +1 -1
  108. package/web/dist/assets/Skills-BKRLHH7m.js +1 -0
  109. package/web/dist/assets/{StatusBadge-wW_RS_my.js → StatusBadge-DI3weRKd.js} +1 -1
  110. package/web/dist/assets/{activity-DpYPKNrA.js → activity-C_H2Bx1P.js} +1 -1
  111. package/web/dist/assets/{index-PmQGRS1X.js → index-B7_Wga23.js} +1 -1
  112. package/web/dist/assets/{index-BEZvPvpF.js → index-N8dTrVro.js} +1 -1
  113. package/web/dist/assets/{index-DNQE5ydy.js → index-Py_IQjgK.js} +2 -2
  114. package/web/dist/index.html +1 -1
  115. package/src/skills/clarify.md +0 -28
  116. package/src/skills/crash-course.md +0 -29
  117. package/src/skills/decode.md +0 -29
  118. package/src/skills/drill.md +0 -29
  119. package/src/skills/feynman.md +0 -27
  120. package/src/skills/gap-detector.md +0 -27
  121. package/src/skills/learning-path.md +0 -27
  122. package/src/skills/tdd.md +0 -31
  123. package/web/dist/assets/Skills-rY13ZPhM.js +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,46 @@ label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
10
10
 
11
11
  _Nothing yet._
12
12
 
13
+ ## [3.4.0] — 2026-09-06
14
+
15
+ ### Added
16
+
17
+ - **Six skills.** `security-audit` (the `security` agent finally has a caller — trust
18
+ boundaries, the classic classes, secrets, the supply chain, a ship / fix / block verdict),
19
+ `skill-forge` (author, sharpen, merge or retire a skill, with every satellite the host or
20
+ the source repo demands), `worktree` (isolate a task in its own tree from a clean base —
21
+ the first move when `git status` shows changes you did not make), `ci-fix` (a red CI run
22
+ reproduced under CI's conditions and fixed at the cause), `deps-audit` (a risk-ordered
23
+ upgrade plan for `migrate` to execute, installing nothing) and `consolidate-memory`
24
+ (the memory set verified against the live repo, merged, retired, re-indexed).
25
+ - **A `harness` skill class** for the skills about the agent's own apparatus — wiki,
26
+ geneseed, rule, profile, herdr, skill-forge, consolidate-memory — which sat under
27
+ `understand` before and made that class a grab-bag. The web console's Skills view
28
+ grows the chip.
29
+
30
+ ### Changed
31
+
32
+ - **A skill's emitted `description:` is now purpose + trigger.** Claude Code and Bob
33
+ match a task against that one line before loading a skill; it used to carry only what
34
+ the skill does, never when. `skillDescription()` appends `Use when: <the Trigger
35
+ paragraph>`, links reduced to text, capped at 900 chars at a sentence boundary.
36
+ - **The Self-improvement footer is one file.** `src/skills/_self-improvement.md` is
37
+ INCLUDEd by every flat skill and the template, with a four-line LEAN half; fifty
38
+ byte-identical copies are gone.
39
+ - **Merges, keeping the best of each:** `tdd` folded into `develop` (seams first, the
40
+ failing test seen to fail for the right reason, an explicit exit to ship or handoff);
41
+ `clarify` folded into `brainstorm` (charitable reading, the key-decision ledger echoed
42
+ back under Law X, then design only when there is something to design, and a routed
43
+ exit); the six learning skills folded into `teach` (crash course, decode, path) and
44
+ `quiz` (drill, feynman, gap check), both user-only. The skill count stays at 49.
45
+ - **`workflow` refined per host:** OpenCode's saved scripts versus Claude Code's native
46
+ tool (inline or `.claude/workflows/`, and only once the user has opted in), Bob and
47
+ Copilot falling back to `parallel-agents`; pick saved over inline, pass the task as
48
+ `args` so a run stays a pure function of its inputs, resume a failed run rather than
49
+ rerun it, and carry the conclusion yourself.
50
+ - **`registry.json`** stamps `last_verified: 2026-09-06` on every approved skill; the six
51
+ new ones enter as `experimental`.
52
+
13
53
  ## [3.3.0] — 2026-09-06
14
54
 
15
55
  The host-gap release: every host now gets the hook surface its runtime actually
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![zero dependencies](https://img.shields.io/badge/deps-zero-success)](package.json)
12
12
  [![Themes](https://img.shields.io/badge/themes-14-9cf)](themes/)
13
13
  [![Skills](https://img.shields.io/badge/skills-49-blueviolet)](src/skills/)
14
- [![Agents](https://img.shields.io/badge/agents-17-orange)](src/agents/)
14
+ [![Agents](https://img.shields.io/badge/agents-18-orange)](src/agents/)
15
15
  [![Laws](https://img.shields.io/badge/laws-11-critical)](src/laws/universal.md)
16
16
  [![Plugins](https://img.shields.io/badge/plugins-7-teal)](adapters/opencode/plugins/)
17
17
  [![OpenCode · Claude Code · Bob · Copilot · AGENT.md](https://img.shields.io/badge/works%20with-OpenCode%20·%20Claude%20Code%20·%20Bob%20·%20Copilot%20·%20AGENT.md-1f6feb)](#-supported-harnesses)
@@ -155,8 +155,8 @@ The harness ships as a small set of layers, and the web console's rail is the sa
155
155
  | **🧭 Ontology** (`ontology/`) | the mind the rules govern, in four prose sections — **Telos** (the Pact: protect the user, the truth, the agent), **Evidence** (every claim graded by how it was obtained), **Decisions** (classify and tier by reversibility, show the real forks), **Conduct** (answer what was asked, once). Always in force, never toggleable |
156
156
  | **🛡️ Rules** (`laws/`) | 11 universal laws the agent obeys — always in force, never toggleable: sealed-secrets, one-intent-one-act, verify-before-assert, deletion-is-deliberate, surface-failures, data-not-orders, least-privilege, root-cause, external-gate, echo-the-intent, absence-is-a-claim |
157
157
  | **📐 Doctrines** (`doctrines/`) | practice packs, chosen per install at build time: **craft** (how code is written), **rigor** (how work is proven), **ops** (how the machine is operated), **process** (how a task is run). A doctrine rule may tighten a Rule, never repeal one, and the user's own `user-rules.md` outranks it. Pick with `geneseed-build --doctrines craft,rigor` (or `none`), a single rule with `--exclude-rules "process 7"`, in the setup wizard, or through the switches on the console's Constitution page; all four pack files ship on disk either way, so a citation into a pack you left out still resolves |
158
- | **🤖 Agents** (17) | capability specialists: `reviewer`, `tester`, `architect`, `docs`, `security`, `explorer`, `developer` — plus a debate **council** the `council` skill convenes: `advocate`, `skeptic`, `pragmatist`, `steward`, `visionary`, `user-advocate`, `framer`, `empiricist`, `operator`, `historian` |
159
- | **🛠 Skills** (49) | repeatable workflows: brainstorm · **clarify** · plan · **codebase-design** · **domain-modeling** · **wayfinder** · **tickets** · tdd · **develop** · debug · **prototype** · refactor · **ponytail** · **forge-mcp** · **bruno-collection-generator** · **bruno-test-writer** · geneseed-code-review · **fresh-eyes** · **review-response** · commit · **ship** · **release** · **migrate** · **git-archaeology** · **git-rescue** · repo-map · document-project · **frontend-design** · **prose** · **ingest** · **research** · **learning-path** · **gap-detector** · **feynman** · **crash-course** · **drill** · **decode** · handoff · roast-me · **council** · parallel-agents · **workflow** · **wiki** · **geneseed** · **rule** · **profile** · **opencode-theme** · **herdr** · **pipeline** |
158
+ | **🤖 Agents** (18) | capability specialists: `reviewer`, `tester`, `architect`, `docs`, `security`, `explorer`, `researcher`, `developer` — plus a debate **council** the `council` skill convenes: `advocate`, `skeptic`, `pragmatist`, `steward`, `visionary`, `user-advocate`, `framer`, `empiricist`, `operator`, `historian` |
159
+ | **🛠 Skills** (49) | repeatable workflows: brainstorm · plan · **codebase-design** · **domain-modeling** · **wayfinder** · **tickets** · **develop** · **worktree** · debug · **prototype** · refactor · **ponytail** · **forge-mcp** · **bruno-collection-generator** · **bruno-test-writer** · geneseed-code-review · **fresh-eyes** · **security-audit** · **ci-fix** · **deps-audit** · **review-response** · commit · **ship** · **release** · **migrate** · **git-archaeology** · **git-rescue** · repo-map · document-project · **frontend-design** · **prose** · **ingest** · **research** · **teach** · **quiz** · handoff · roast-me · **council** · parallel-agents · **workflow** · **wiki** · **geneseed** · **rule** · **profile** · **consolidate-memory** · **skill-forge** · **opencode-theme** · **herdr** · **pipeline** |
160
160
  | **🔌 Plugins** (OpenCode) | `geneseed-context` injects project docs *and your machine wiki* every session (and across compaction); `geneseed-learn` distils memory at session end; `geneseed-guard` enforces the safety Laws and protected wiki folders at the tool boundary; `geneseed-workflow` registers the `workflow` tool that runs saved orchestration scripts; `geneseed-notify` sends a native OS notification when a long run finishes; `geneseed-ponytail` holds a minimal-code mode (`/ponytail lite\|full\|ultra\|off`), opt-in, injecting the laziest-that-works ruleset every turn so it doesn't drift; `geneseed-activity` streams what each session is doing to the web console's Activity view |
161
161
  | **🧠 Memory** (`memory/`) | one-fact-per-file durable knowledge, indexed by `MEMORY.md` (git-ignored, personal) |
162
162
  | **📓 Notebook** (`notebook/`) | the agent's sovereign space — any medium (code, tools, data, notes), self-ruled via a seed-once charter, always git-ignored; only its `.gitignore` is build-asserted |
package/SHIPPED.md CHANGED
@@ -20,7 +20,7 @@ historical pointers, not files distributed with the repo.
20
20
  > **On version numbers.** [`harness.config.json`](harness.config.json)'s `version` is a
21
21
  > human-readable label only. The canonical identity of an installed harness is the
22
22
  > **source fingerprint** stamped in `.geneseed-version` (see `geneseed version`), not the
23
- > string. Current label: **3.3.0**.
23
+ > string. Current label: **3.4.0**.
24
24
 
25
25
  > **Spec status audit (2026-06-15).** Every dated spec authored before today was
26
26
  > verified against the source tree and confirmed implemented (code + tests + docs);
@@ -35,7 +35,7 @@ Every row below is present in the tree today; "Spec" links the design record.
35
35
  | Capability | What it is | Spec |
36
36
  | --- | --- | --- |
37
37
  | **Themed generator** | One neutral `src/` → 14 themed bundles via `geneseed-build` (zero dependencies); structure stays theme-independent | [DESIGN.md](DESIGN.md) |
38
- | **Laws / Agents / Skills / Memory / Notebook** | 11 laws, 17 agents, 49 skills, the memory convention, and the agent's sovereign notebook | [notebook](docs/specs/2026-06-11-notebook-sovereign-space.md) · [agent-own-space](docs/specs/2026-06-10-notebook-agent-own-space.md) |
38
+ | **Laws / Agents / Skills / Memory / Notebook** | 11 laws, 18 agents, 49 skills, the memory convention, and the agent's sovereign notebook | [notebook](docs/specs/2026-06-11-notebook-sovereign-space.md) · [agent-own-space](docs/specs/2026-06-10-notebook-agent-own-space.md) |
39
39
  | **Three-tier constitution** | The governance surface splits into an always-on **Ontology** (Telos, Evidence, Decisions, Conduct — the Pact absorbed into Telos), the eleven always-on **Invariants** (IX and XI retired in place — folded into rigor 5 and Law III, numbers kept), and four toggleable **Doctrine** packs (craft, rigor, ops, process) addressed `<pack> <n>`. Packs are chosen at build time with `--doctrines` or the setup wizard; the whole catalogue ships on disk either way, so a citation into an inactive pack still resolves. Precedence, in order: Ontology + Invariants, then the user's `user-rules.md`, then the active Doctrines, then `PROFILE.md`. `doctor`'s `constitutionProblems` gates pack numbering, the per-rule Principle column, every `{{DOCTRINE}}` citation in `src/`, and the rule that an always-on tier may never cite a toggleable one | [three-tier-constitution](docs/specs/2026-08-19-three-tier-constitution-design.md) |
40
40
  | **`doctor`** | One check: unresolved tokens, dead/non-hermetic links, theme-key parity, authoring gates, rendered-bundle drift | [theme-aware doctor/diff](docs/specs/2026-06-07-theme-aware-doctor-diff.md) |
41
41
  | **`diff` + improvements export** | Deployed-vs-source drift report; export an `improvements.md` back-port | [improvements-export](docs/specs/2026-06-12-improvements-export.md) |
@@ -23,7 +23,8 @@ no "ask the user" tier, so this page is mostly about what those hooks *can* and
23
23
  - `agents/<name>.agent.md` — Copilot's **custom-agent dialect** (`.agent.md`
24
24
  extension; a `tools:` **allowlist**, not Claude's denylist — a read-only
25
25
  agent lists the tool ids it keeps: `read, search, todo, agent`, plus
26
- `execute` only when the spec opts in with `<!-- bash: allow -->`). Sibling
26
+ `execute` only when the spec opts in with `<!-- bash: allow -->`, `fetch` only
27
+ with `<!-- webfetch: allow -->`). Sibling
27
28
  agent links are rewritten to the `.agent.md` filename.
28
29
  - `skills/<name>/SKILL.md` — **byte-identical** to every other host.
29
30
 
@@ -57,7 +57,8 @@ your-repo/
57
57
  - Read-only agents (their spec says *Read-only*) get an OpenCode `permission` block
58
58
  — `edit: deny`, `webfetch: deny`, and `bash: deny`, so a read-only agent can't
59
59
  mutate via the shell either. One that must run read-only commands (tests, linters,
60
- scanners) declares `<!-- bash: allow -->` in its spec, which gates bash to `ask`
60
+ scanners) declares `<!-- bash: allow -->` in its spec, which gates bash to `ask`;
61
+ `<!-- webfetch: allow -->` (the researcher) re-opens web fetch the same way
61
62
  instead. The rest keep edit access.
62
63
  - OpenCode invokes a subagent via the task tool, e.g. `subagent_type: "reviewer"`.
63
64
  - **Skills are native, not slash commands** — model-invoked via the `skill` tool
@@ -357,7 +358,10 @@ behaviour** — nothing changes the machine's current agent/model unless you opt
357
358
  { "agents": { "reviewer": { "model": "anthropic/claude-haiku-4-5", "temperature": 0.1, "variant": "high", "steps": 20 } } }
358
359
  ```
359
360
  Re-emit to apply. (A future TUI screen will edit this map.) Unlisted keys are omitted,
360
- so the agent inherits OpenCode's defaults.
361
+ so the agent inherits OpenCode's defaults. The stub also carries an inert
362
+ `_recommended.cheap-tier` list — the read-and-summarise seats (explorer, researcher,
363
+ tester, and the council bench) worth routing to a cheaper model; copy the names you
364
+ want into `agents`, nothing applies by itself.
361
365
  - **Agent colours.** Each capability agent is emitted with a `color:` set to an OpenCode
362
366
  *named theme slot*, sourced from the active harness theme's `AGENT_COLORS` map
363
367
  (`themes/_TEMPLATE.json`; the shipped default — architect=`primary`, reviewer=`warning`,
package/docs/extending.md CHANGED
@@ -293,7 +293,7 @@ emit leaves the prior install intact.
293
293
  a blank line, then a `>` blockquote holding `{{DESC_<NAME>}}` — title, blockquote, nothing
294
294
  between. `doctor` checks both the presence of the purpose line and that the blockquote is the
295
295
  *first* block (`authoringProblems`, via `firstBlockquote` and `descBlockProblem`).
296
- 2. One row in the hand-authored table in `src/AGENT.md.tmpl` (agents `125-141`, skills `183-229`).
296
+ 2. One row in the hand-authored table in `src/AGENT.md.tmpl` (the `## 3.` table for agents, the `## 4.` one for skills).
297
297
  Gated both ways: a row with no file, and a file with no row.
298
298
  3. `DESC_<NAME>` in **all fourteen** themes. Theme parity catches a missing one; nothing catches
299
299
  an unstyled placeholder.
@@ -318,8 +318,9 @@ and **skip steps 2, 4, 6, 7**: the flat-spec globs only see `*.md` at the top le
318
318
  Two traps worth knowing before you write the spec:
319
319
 
320
320
  - **The word "Read-only" anywhere in an agent spec locks its emit.** It is a bare substring test
321
- (`js/hosts/native.mjs:148`). The escape hatch is an explicit `<!-- bash: allow -->` marker, which
322
- re-opens bash on all three hosts.
321
+ (`js/hosts/native.mjs:148`). The escape hatches are explicit markers: `<!-- bash: allow -->`
322
+ re-opens bash on all three hosts (OpenCode gates it to `ask`), and `<!-- webfetch: allow -->`
323
+ re-opens web fetch — the researcher is the one spec that carries it.
323
324
  - **The console has a fourth, ungated copy of the skill taxonomy.** `SKILL_CATS` in
324
325
  `web/src/pages/Skills.jsx:19` mirrors `SKILL_CLASS` with nothing comparing them (contrast
325
326
  `LAW_META`, which *is* cross-checked). Inventing a new *category* means editing that file —
@@ -5,4 +5,4 @@ title: "Agents"
5
5
  kind: "concept"
6
6
  link: {"hash": "#/section/agents", "label": "Browse the catalog →"}
7
7
  ---
8
- {N_AGENTS} capability specialists — `reviewer`, `tester`, `architect`, `developer`, `docs`, `security`, `explorer`, plus a debate **council** the [[council]] skill convenes (`advocate`, `skeptic`, `pragmatist`, `steward`, `visionary`, `user-advocate`, `framer`, `empiricist`, `operator`, `historian`). You delegate by capability, not by folder: the harness picks the right specialist from the request.
8
+ {N_AGENTS} capability specialists — `reviewer`, `tester`, `architect`, `developer`, `docs`, `security`, `explorer`, `researcher`, plus a debate **council** the [[council]] skill convenes (`advocate`, `skeptic`, `pragmatist`, `steward`, `visionary`, `user-advocate`, `framer`, `empiricist`, `operator`, `historian`). You delegate by capability, not by folder: the harness picks the right specialist from the request.
@@ -16,7 +16,7 @@ Once installed, the agent doesn't change *how* you talk to your tool — it chan
16
16
  ### Try these prompts
17
17
 
18
18
  - *"Use the **profile** skill"* — a short interview that drafts `PROFILE.md` (seeded empty at install), so the agent knows who you are and how you like answers pitched.
19
- - *"Use the **clarify** skill on this feature request."*
19
+ - *"Use the **brainstorm** skill on this feature request."*
20
20
  - *"Delegate to the **reviewer** agent on the staged diff."*
21
21
  - *"Use **brainstorm** then **plan** for how to add X."*
22
22
  - *"Use **council** to debate whether we should ship Y now."*
@@ -5,4 +5,4 @@ title: "Skills"
5
5
  kind: "concept"
6
6
  link: {"hash": "#/section/skills", "label": "Browse the catalog →"}
7
7
  ---
8
- {N_SKILLS} repeatable workflows the agent can invoke by name — from [[brainstorm]], [[clarify]], [[plan]], [[tdd]] and [[debug]] through [[council]], [[research]] and [[ship]] to [[roast-me]]. A skill is a markdown playbook under `src/skills/`; the agent reads it before acting. The catalog link lists every one, live.
8
+ {N_SKILLS} repeatable workflows the agent can invoke by name — from [[brainstorm]], [[plan]], [[develop]] and [[debug]] through [[council]], [[research]] and [[ship]] to [[roast-me]]. A skill is a markdown playbook under `src/skills/`; the agent reads it before acting. The catalog link lists every one, live.
@@ -2,5 +2,5 @@
2
2
  "_comment": "version is a human-readable release label only; the canonical identity of an installed harness is the source fingerprint stamped in .geneseed-version (see `harness version`), not this string.",
3
3
  "theme": "neutral",
4
4
  "product": "Geneseed",
5
- "version": "3.3.0"
5
+ "version": "3.4.0"
6
6
  }
@@ -112,6 +112,53 @@ export function descOf(text) {
112
112
  return firstBlockquote(text);
113
113
  }
114
114
 
115
+ /**
116
+ * The `**Trigger:**` paragraph of a skill, flattened to one line — markdown links reduced
117
+ * to their text, HTML comments dropped, whitespace collapsed. '' when the skill has none.
118
+ *
119
+ * Why it exists: on Claude Code (and Bob) the frontmatter `description:` is the ONLY text
120
+ * the model matches a task against before deciding to load a skill. The purpose line says
121
+ * what a skill does; the trigger says WHEN — and a catalogue of purposes alone left the
122
+ * model choosing `tdd` from "Drive implementation with tests" without ever seeing "before
123
+ * writing implementation code". The AGENT.md §4 table carried the triggers, but native
124
+ * hosts collapse that table to a pointer (`hostCatalogsNatively`), so the trigger reached
125
+ * no host at all. `skillDescription` below concatenates the two.
126
+ */
127
+ export function triggerOf(text) {
128
+ const lines = text.split('\n');
129
+ const start = lines.findIndex((ln) => /^\*\*Trigger:\*\*/.test(ln.trim()));
130
+ if (start < 0) return '';
131
+ const para = [];
132
+ for (let i = start; i < lines.length; i += 1) {
133
+ const s = lines[i].trim();
134
+ if (i > start && (s === '' || s.startsWith('#') || s.startsWith('**'))) break;
135
+ para.push(s);
136
+ }
137
+ return para.join(' ')
138
+ .replace(/^\*\*Trigger:\*\*\s*/, '')
139
+ .replace(HTML_COMMENT_RE, '')
140
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
141
+ .replace(/\s+/g, ' ')
142
+ .trim();
143
+ }
144
+
145
+ /**
146
+ * Purpose + trigger, the emitted `description:` of a skill. Capped so a long trigger (a
147
+ * few carry three sentences of disambiguation) cannot blow past what hosts display —
148
+ * cut at the last sentence end inside the cap, never mid-word.
149
+ */
150
+ const DESCRIPTION_CAP = 900;
151
+ export function skillDescription(text) {
152
+ const desc = descOf(text);
153
+ const trig = triggerOf(text);
154
+ if (!trig) return desc;
155
+ const full = `${desc} Use when: ${trig}`;
156
+ if (full.length <= DESCRIPTION_CAP) return full;
157
+ const cut = full.slice(0, DESCRIPTION_CAP);
158
+ const end = Math.max(cut.lastIndexOf('. '), cut.lastIndexOf('; '));
159
+ return end > desc.length ? cut.slice(0, end + 1) : cut.replace(/\s+\S*$/, '') + '…';
160
+ }
161
+
115
162
  /** `_build_render._HTML_COMMENT_RE`. */
116
163
  const HTML_COMMENT_RE = /<!--[\s\S]*?-->/g;
117
164
 
@@ -244,22 +291,28 @@ export function pushOverrideLines(fm, ov) {
244
291
  if (given(ov.steps)) fm.push(`steps: ${formatValue(ov.steps)}`);
245
292
  }
246
293
 
294
+ /** The two opt-in markers a read-only spec may carry. Bare substring tests, like `isReadonly`. */
295
+ const BASH_MARKER = '<!-- bash: allow -->';
296
+ const WEBFETCH_MARKER = '<!-- webfetch: allow -->';
297
+
247
298
  /**
248
299
  * The readonly-tool line `claudeAgentFrontmatter`/`copilotAgentFrontmatter` each emit — a
249
300
  * DENYLIST for Claude, an ALLOWLIST for Copilot — differing only in the key, the base list,
250
- * the one extra entry the `<!-- bash: allow -->` marker toggles, and whether the value is
251
- * bracketed. `extraWhenBashAllowed` is `false` for Claude (Bash is denied UNLESS the marker
252
- * allows it) and `true` for Copilot (`execute` is allowed ONLY IF the marker is present) —
253
- * the same marker, read in the opposite sense a denylist and an allowlist require.
301
+ * the gated entries the markers toggle, and whether the value is bracketed. Each `gated`
302
+ * row is `[tool, marker, listedWhenMarked]`: `false` for Claude (the tool is denied UNLESS
303
+ * the marker allows it) and `true` for Copilot (the tool is allowed ONLY IF the marker is
304
+ * present) — the same marker, read in the opposite sense a denylist and an allowlist
305
+ * require. Row order is emit order: WebFetch before Bash keeps the unmarked Claude line
306
+ * byte-identical to what it was before the webfetch marker existed.
254
307
  */
255
308
  const READONLY_TOOLS = {
256
309
  claude: {
257
- key: 'disallowedTools', tools: ['Write', 'Edit', 'NotebookEdit', 'WebFetch'],
258
- extra: 'Bash', extraWhenBashAllowed: false, brackets: false,
310
+ key: 'disallowedTools', tools: ['Write', 'Edit', 'NotebookEdit'], brackets: false,
311
+ gated: [['WebFetch', WEBFETCH_MARKER, false], ['Bash', BASH_MARKER, false]],
259
312
  },
260
313
  copilot: {
261
- key: 'tools', tools: ['read', 'search', 'todo', 'agent'],
262
- extra: 'execute', extraWhenBashAllowed: true, brackets: true,
314
+ key: 'tools', tools: ['read', 'search', 'todo', 'agent'], brackets: true,
315
+ gated: [['fetch', WEBFETCH_MARKER, true], ['execute', BASH_MARKER, true]],
263
316
  },
264
317
  };
265
318
 
@@ -269,11 +322,11 @@ function claudeCopilotAgentFrontmatter(host, stem, text, overrides) {
269
322
  const ov = agentOverride(overrides, stem);
270
323
  if (isTruthy(ov.model)) fm.push(`model: ${formatValue(ov.model)}`);
271
324
  if (isReadonly(text)) {
272
- const {
273
- key, tools, extra, extraWhenBashAllowed, brackets,
274
- } = READONLY_TOOLS[host];
325
+ const { key, tools, brackets, gated } = READONLY_TOOLS[host];
275
326
  const list = [...tools];
276
- if (text.includes('<!-- bash: allow -->') === extraWhenBashAllowed) list.push(extra);
327
+ for (const [tool, marker, listedWhenMarked] of gated) {
328
+ if (text.includes(marker) === listedWhenMarked) list.push(tool);
329
+ }
277
330
  fm.push(`${key}: ${brackets ? `[${list.join(', ')}]` : list.join(', ')}`);
278
331
  }
279
332
  return fm;
@@ -294,8 +347,9 @@ function opencodeAgentFrontmatter(stem, text, overrides, theme = null) {
294
347
  fm.push(`color: ${agentColor(stem, theme)}`);
295
348
  pushOverrideLines(fm, agentOverride(overrides, stem));
296
349
  if (isReadonly(text)) {
297
- fm.push('permission:', ' edit: deny', ' webfetch: deny');
298
- if (text.includes('<!-- bash: allow -->')) fm.push(' bash:', ' "*": ask');
350
+ fm.push('permission:', ' edit: deny',
351
+ ` webfetch: ${text.includes(WEBFETCH_MARKER) ? 'allow' : 'deny'}`);
352
+ if (text.includes(BASH_MARKER)) fm.push(' bash:', ' "*": ask');
299
353
  else fm.push(' bash: deny');
300
354
  }
301
355
  return fm;
@@ -435,7 +489,7 @@ export function writeNativeLayer(items, agentsDir, skillsDir, overrides = null,
435
489
  // Skills are BYTE-IDENTICAL across hosts: name + description, body link-stripped.
436
490
  // The user-only key is emitted for every host too — Claude Code and Bob honour it,
437
491
  // OpenCode and Copilot ignore an unknown key — so the identity holds.
438
- fm = [`name: ${stem}`, `description: ${jsonDumps(descOf(text))}`];
492
+ fm = [`name: ${stem}`, `description: ${jsonDumps(skillDescription(text))}`];
439
493
  if (isUserInvokedOnly(text)) fm.push('disable-model-invocation: true');
440
494
  body = stripSkillBodyLinks(body);
441
495
  dest = path.join(skillsDir, stem, 'SKILL.md');
@@ -78,6 +78,20 @@ const AGENT_OVERRIDES_STUB = {
78
78
  + 'Host-specific; git-ignored. A future TUI screen edits this — rebuild to apply.'
79
79
  ),
80
80
  agents: {},
81
+ // Inert: `loadAgentOverrides` reads `agents` only. This is the starting point the README
82
+ // used to describe in prose — the seats whose work is read-and-summarise, where a smaller
83
+ // model loses little and a council convenes 3–6 of them at once.
84
+ _recommended: {
85
+ _comment: (
86
+ 'Cheap-tier seats: copy the ones you want into "agents" with your host\'s cheap '
87
+ + 'model id (OpenCode: "anthropic/claude-haiku-4-5"; Claude Code / Copilot: "haiku"). '
88
+ + 'Read-and-summarise work — a council convenes several at once, so this is where '
89
+ + 'the savings compound. Nothing applies until you copy it.'
90
+ ),
91
+ 'cheap-tier': ['explorer', 'researcher', 'tester', 'advocate', 'skeptic', 'pragmatist',
92
+ 'steward', 'visionary', 'user-advocate', 'framer', 'empiricist', 'operator',
93
+ 'historian'],
94
+ },
81
95
  };
82
96
 
83
97
  /** Mirrors `_build_emit.COMMAND_SET` — the hot skills worth a one-keystroke trigger. */
@@ -90,21 +90,26 @@ export const LAW_CLASSES = ['security', 'process', 'verify', 'craft', 'context',
90
90
 
91
91
  /** `_harness_tui.SKILL_CLASS` — each skill's category, keyed by file stem. */
92
92
  export const SKILL_CLASS = {
93
- brainstorm: 'design', clarify: 'design', plan: 'design', council: 'design',
93
+ brainstorm: 'design', plan: 'design', council: 'design',
94
94
  workflow: 'design', 'parallel-agents': 'design', pipeline: 'design',
95
95
  'codebase-design': 'design', 'domain-modeling': 'design', wayfinder: 'design',
96
96
  tickets: 'design',
97
- tdd: 'build', develop: 'build', refactor: 'build', debug: 'build', migrate: 'build',
97
+ develop: 'build', refactor: 'build', debug: 'build', migrate: 'build',
98
98
  'frontend-design': 'build', 'opencode-theme': 'build', prototype: 'build',
99
99
  'forge-mcp': 'build', 'bruno-collection-generator': 'build', 'bruno-test-writer': 'build',
100
- 'geneseed-code-review': 'review', 'fresh-eyes': 'review', 'gap-detector': 'review',
100
+ worktree: 'build', 'ci-fix': 'build', 'deps-audit': 'build',
101
+ 'geneseed-code-review': 'review', 'fresh-eyes': 'review', 'security-audit': 'review',
101
102
  'roast-me': 'review', 'review-response': 'review', ponytail: 'review',
102
103
  commit: 'ship', ship: 'ship', release: 'ship', handoff: 'ship', 'git-rescue': 'ship',
103
- 'repo-map': 'understand', 'git-archaeology': 'understand', decode: 'understand',
104
+ 'repo-map': 'understand', 'git-archaeology': 'understand',
104
105
  research: 'understand', ingest: 'understand', 'document-project': 'understand',
105
- wiki: 'understand', prose: 'understand', geneseed: 'understand', rule: 'understand',
106
- profile: 'understand', herdr: 'understand',
107
- 'crash-course': 'learn', drill: 'learn', feynman: 'learn', 'learning-path': 'learn',
106
+ prose: 'understand',
107
+ // `harness` — skills about the agent's own apparatus (its harness, memory, rules,
108
+ // knowledge base, terminal) rather than about the user's code. They sat under
109
+ // `understand` before, which made that class a grab-bag.
110
+ wiki: 'harness', geneseed: 'harness', rule: 'harness', profile: 'harness',
111
+ herdr: 'harness', 'skill-forge': 'harness', 'consolidate-memory': 'harness',
112
+ teach: 'learn', quiz: 'learn',
108
113
  };
109
114
 
110
115
  /** `k in dict` — own keys only, where `k in obj` also finds `Object.prototype` members. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "Every field here is argued and gated in tests/unit/package_manifest.test.mjs. `files`, `bin` and `engines` each have a test that fails when reality drifts from this file; `version` mirrors harness.config.json and is gated too. Read that docblock before editing this one.",
3
3
  "name": "geneseed",
4
- "version": "3.3.0",
4
+ "version": "3.4.0",
5
5
  "description": "A portable, theme-able harness you implant once and use everywhere to grow a disciplined AI coding agent.",
6
6
  "keywords": [
7
7
  "ai",