geneseed 4.10.0 → 4.15.1

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 (147) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +5 -4
  3. package/SHIPPED.md +1 -1
  4. package/adapters/opencode/plugins/geneseed-guard.js +16 -1
  5. package/adapters/opencode/plugins/geneseed-learn.js +28 -12
  6. package/adapters/opencode/plugins/geneseed-workflow.js +19 -2
  7. package/docs/concepts/kits.md +14 -2
  8. package/docs/concepts/skills.md +1 -1
  9. package/docs/extending.md +3 -4
  10. package/docs/guides/install-bob.md +3 -1
  11. package/docs/guides/run-anywhere.md +2 -2
  12. package/docs/guides/upgrade.md +2 -2
  13. package/docs/reference/troubleshoot-install.md +1 -1
  14. package/docs/web-ui.md +6 -1
  15. package/harness.config.json +1 -1
  16. package/js/build/emit-claude.mjs +4 -2
  17. package/js/build/stubs.mjs +13 -0
  18. package/js/hosts/link.mjs +88 -1
  19. package/js/inspect/checks-build.mjs +8 -2
  20. package/js/inspect/cost.mjs +1 -1
  21. package/js/inspect/diff.mjs +53 -7
  22. package/js/inspect/inventory.mjs +1 -0
  23. package/js/lib/prompt.mjs +19 -2
  24. package/js/maintain/setup.mjs +92 -28
  25. package/js/maintain/update.mjs +2 -2
  26. package/js/web/actions.mjs +8 -0
  27. package/js/web/api.mjs +39 -17
  28. package/js/web/catalog.mjs +17 -2
  29. package/js/web/handler.mjs +1 -0
  30. package/js/web/server.mjs +11 -5
  31. package/js/web/state.mjs +38 -3
  32. package/package.json +1 -1
  33. package/registry.json +28 -0
  34. package/src/AGENT.md.tmpl +5 -5
  35. package/src/agents/_self-improvement.md +11 -0
  36. package/src/agents/_template.md +1 -8
  37. package/src/agents/advocate.md +1 -8
  38. package/src/agents/architect.md +1 -8
  39. package/src/agents/developer.md +1 -8
  40. package/src/agents/devops-engineer.md +1 -9
  41. package/src/agents/docker-expert.md +1 -9
  42. package/src/agents/docs.md +1 -8
  43. package/src/agents/empiricist.md +1 -8
  44. package/src/agents/explorer.md +1 -8
  45. package/src/agents/framer.md +1 -8
  46. package/src/agents/historian.md +1 -8
  47. package/src/agents/kubernetes-specialist.md +1 -9
  48. package/src/agents/memory-curator.md +1 -8
  49. package/src/agents/operator.md +1 -8
  50. package/src/agents/performance.md +1 -8
  51. package/src/agents/pragmatist.md +1 -8
  52. package/src/agents/react-engineer.md +38 -0
  53. package/src/agents/react-reviewer.md +42 -0
  54. package/src/agents/researcher.md +5 -10
  55. package/src/agents/reviewer.md +1 -8
  56. package/src/agents/security.md +1 -8
  57. package/src/agents/skeptic.md +1 -8
  58. package/src/agents/spring-boot-engineer.md +1 -9
  59. package/src/agents/spring-reviewer.md +1 -9
  60. package/src/agents/spring-security.md +1 -9
  61. package/src/agents/steward.md +1 -8
  62. package/src/agents/tester.md +1 -8
  63. package/src/agents/user-advocate.md +1 -8
  64. package/src/agents/visionary.md +1 -8
  65. package/src/doctrines/comms.md +21 -0
  66. package/src/kits/react/rules.md +13 -0
  67. package/src/kits/react.json +18 -0
  68. package/src/licenses/everything-claude-code.txt +21 -0
  69. package/src/skills/_self-improvement.md +22 -5
  70. package/src/skills/brainstorm.md +7 -2
  71. package/src/skills/codebase-design.md +6 -2
  72. package/src/skills/debug.md +1 -1
  73. package/src/skills/develop.md +4 -2
  74. package/src/skills/handoff.md +1 -1
  75. package/src/skills/parallel-agents.md +3 -1
  76. package/src/skills/plan.md +5 -2
  77. package/src/skills/prototype.md +4 -2
  78. package/src/skills/react/a11y.md +33 -0
  79. package/src/skills/react/vite.md +35 -0
  80. package/src/skills/react/webpack.md +40 -0
  81. package/src/skills/react-testing.md +68 -0
  82. package/src/skills/react.md +63 -0
  83. package/src/skills/research.md +4 -2
  84. package/src/skills/rule.md +4 -2
  85. package/src/skills/ship.md +6 -4
  86. package/src/skills/skill-forge.md +10 -5
  87. package/src/skills/wayfinder.md +6 -2
  88. package/src/skills/wiki.md +18 -5
  89. package/src/upstreams.json +7 -0
  90. package/themes/_TEMPLATE.json +5 -0
  91. package/themes/biker.json +5 -0
  92. package/themes/commentator.json +5 -0
  93. package/themes/cyberpunk.json +5 -0
  94. package/themes/gamer.json +5 -0
  95. package/themes/imperial.json +5 -0
  96. package/themes/joker.json +5 -0
  97. package/themes/marvin.json +5 -0
  98. package/themes/mean.json +5 -0
  99. package/themes/military.json +5 -0
  100. package/themes/neutral.json +5 -0
  101. package/themes/pirate.json +5 -0
  102. package/themes/sports.json +5 -0
  103. package/themes/verstappen.json +5 -0
  104. package/themes/wizard.json +5 -0
  105. package/web/dist/assets/Activity-M5qj6CxJ.js +1 -0
  106. package/web/dist/assets/ActivityDetail-DVCdNy73.js +1 -0
  107. package/web/dist/assets/Dashboard-B1rpgTz-.js +2 -0
  108. package/web/dist/assets/{Docs-DLVckkew.js → Docs-D-EixVuX.js} +3 -3
  109. package/web/dist/assets/FilterInput-CZREvrjX.js +1 -0
  110. package/web/dist/assets/GreenhouseView-BvA4t12P.js +2 -0
  111. package/web/dist/assets/Installs-DP4WjTpD.js +3 -0
  112. package/web/dist/assets/JournalView-hf2eO133.js +1 -0
  113. package/web/dist/assets/KitApply-aORiqjFC.js +1 -0
  114. package/web/dist/assets/Kits-DpIEozdv.js +1 -0
  115. package/web/dist/assets/{Laws-BkKnZOBI.js → Laws-cM_4CG9i.js} +2 -2
  116. package/web/dist/assets/Library-I1zEH3UW.js +1 -0
  117. package/web/dist/assets/Loops-CDa_mxP9.js +2 -0
  118. package/web/dist/assets/{Markdown-iHvBrpRN.js → Markdown-zaXXXHz9.js} +13 -13
  119. package/web/dist/assets/OperatorHudView-CMf1DQMB.js +2 -0
  120. package/web/dist/assets/Personal-BqU9Pzt1.js +1 -0
  121. package/web/dist/assets/Tabs-JZ2FQBcz.js +1 -0
  122. package/web/dist/assets/activity-Jw8XcPiP.js +1 -0
  123. package/web/dist/assets/{drawable-CgYi0Dtg.js → drawable-svc6-2Gp.js} +1 -1
  124. package/web/dist/assets/index-CZFrNe4N.js +2 -0
  125. package/web/dist/assets/{index-BCJz4_8C.css → index-jYlWihN-.css} +1 -1
  126. package/web/dist/assets/{react-BOF6yL40.js → react-DlYQp10C.js} +1 -1
  127. package/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
  128. package/web/dist/assets/sections-ChwaobfW.js +1 -0
  129. package/web/dist/assets/usePoll-bDFN-Hr6.js +1 -0
  130. package/web/dist/index.html +5 -4
  131. package/web/src/pages/Laws.jsx +5 -0
  132. package/web/dist/assets/Activity-BjyJaf8e.js +0 -1
  133. package/web/dist/assets/ActivityDetail-Bo9nRDNV.js +0 -1
  134. package/web/dist/assets/Dashboard-BQJGU7vE.js +0 -2
  135. package/web/dist/assets/FilterInput-zLFXoSt6.js +0 -1
  136. package/web/dist/assets/GreenhouseView--DML7CW3.js +0 -2
  137. package/web/dist/assets/Installs-CxCiln1F.js +0 -3
  138. package/web/dist/assets/JournalView-ymgZleHi.js +0 -1
  139. package/web/dist/assets/Library-C8ercIZv.js +0 -1
  140. package/web/dist/assets/Loops-C95zhbFl.js +0 -2
  141. package/web/dist/assets/OperatorHudView-B9qwc3w3.js +0 -2
  142. package/web/dist/assets/Personal-DyR72AF-.js +0 -1
  143. package/web/dist/assets/Tabs-ChCr_HqV.js +0 -1
  144. package/web/dist/assets/activity-DvPxoS4Y.js +0 -1
  145. package/web/dist/assets/index-B32EvfDT.js +0 -2
  146. package/web/dist/assets/sections-BET3c1WT.js +0 -1
  147. package/web/dist/assets/usePoll-NSTzLOF4.js +0 -1
@@ -24,6 +24,7 @@ import { readText, withDiscardableStderr, isDir, isFile } from '../lib/fs.mjs';
24
24
  import { comparePaths, normcase, within } from '../lib/paths.mjs';
25
25
  import { stripWhitespace } from '../lib/text.mjs';
26
26
  import { readJsonc } from '../hosts/settings.mjs';
27
+ import { loadKits } from '../build/source.mjs';
27
28
 
28
29
  /** A requested catalog section or item that does not exist. */
29
30
  export class NotFound extends Error {}
@@ -466,16 +467,29 @@ function constitutionItems(inv) {
466
467
  ];
467
468
  }
468
469
 
470
+ /** `Map<'skills/x' | 'agents/y', kit>` from the shipped manifests; a broken manifest means no badges, not a 500. */
471
+ function kitOwners() {
472
+ const owner = new Map();
473
+ try {
474
+ for (const [kit, m] of loadKits()) {
475
+ for (const n of m.skills ?? []) owner.set(`skill:${n}`, kit);
476
+ for (const n of m.agents ?? []) owner.set(`agent:${n}`, kit);
477
+ }
478
+ } catch { /* shortcut: unreadable manifests hide the badge; apiKits reports the error */ }
479
+ return owner;
480
+ }
481
+
469
482
  export function apiCatalog(state, section) {
470
483
  if (!SECTIONS.includes(section)) throw new NotFound(section);
471
484
  const inv = state.inventory;
472
485
  let items;
486
+ const owner = kitOwners();
473
487
  if (section === 'agents') {
474
488
  items = inv.agents.map((e) => ({ name: e.name, title: e.name, desc: e.desc,
475
- source: e.source ?? null, status: e.status ?? 'unknown' }));
489
+ source: e.source ?? null, status: e.status ?? 'unknown', kit: owner.get(`agent:${e.name}`) ?? null }));
476
490
  } else if (section === 'skills') {
477
491
  items = inv.skills.map((e) => ({ name: e.name, title: e.name, desc: e.desc,
478
- source: e.source ?? null, klass: e.klass ?? 'build', status: e.status ?? 'unknown' }));
492
+ source: e.source ?? null, klass: e.klass ?? 'build', status: e.status ?? 'unknown', kit: owner.get(`skill:${e.name}`) ?? null }));
479
493
  } else if (section === 'laws') {
480
494
  items = constitutionItems(inv);
481
495
  } else if (section === 'memory') {
@@ -499,6 +513,7 @@ export function apiItem(state, type, name) {
499
513
  links: resolveLinks(state, e.body), source: e.source ?? null };
500
514
  if (type === 'skill') out.klass = e.klass ?? 'build';
501
515
  out.status = e.status ?? 'unknown';
516
+ out.kit = kitOwners().get(`${type}:${name}`) ?? null;
502
517
  return out;
503
518
  }
504
519
  if (type === 'law') {
@@ -303,6 +303,7 @@ export function makeHandler(state, jm, token, dist, holder = null) {
303
303
  // Build resolves its argv off the install (`buildActionCmds`); the other actions take no
304
304
  // axes and self-resolve the deployed theme downstream.
305
305
  const cmds = action === 'build' ? buildActionCmds(state, body) : actionCommands(action);
306
+ if (cmds && Object.hasOwn(cmds, 'error')) return sendJson(res, cmds, 400, ae);
306
307
  if (!isTruthy(cmds)) {
307
308
  return sendJson(res, { error: `unknown action ${action}` }, 404, ae);
308
309
  }
package/js/web/server.mjs CHANGED
@@ -27,7 +27,7 @@ import { isFile, printOut } from '../lib/fs.mjs';
27
27
  import { which } from '../lib/paths.mjs';
28
28
  import { parseIntStrict } from '../lib/text.mjs';
29
29
  import { promptLine } from '../lib/prompt.mjs';
30
- import { warmDoctor, webState } from './state.mjs';
30
+ import { fallbackView, warmDoctor, webState } from './state.mjs';
31
31
  import { clearDaemon, codeStamp, openUrl, readDaemon, restartDaemon, startDaemon, statusDaemon, stopDaemon, writeDaemon } from './daemon.mjs';
32
32
  import { makeHandler } from './handler.mjs';
33
33
  import { JobManager } from './jobs.mjs';
@@ -132,6 +132,12 @@ export async function serve({ theme = null, port = 4747, openBrowser = true,
132
132
  }
133
133
  }
134
134
  const state = webState(theme);
135
+ // The daemon record and the job file stay at the DEFAULT target, captured before the view
136
+ // moves: `geneseed web stop`/`status` find them through `webState(theme).target`, which never
137
+ // moves, and a view that followed a Bob-only install into ~/.bob would hide the record.
138
+ const home = state.target;
139
+ const fallback = fallbackView(home);
140
+ if (fallback) state.selectView(...fallback);
135
141
  if (!existsSync(join(state.target, GLOBAL_MANIFEST))) {
136
142
  printOut(`[web] no deployed harness at ${state.target}.\n`);
137
143
  printOut(' Run `geneseed setup` first — serving anyway (read-only UI).\n');
@@ -143,7 +149,7 @@ export async function serve({ theme = null, port = 4747, openBrowser = true,
143
149
  const holder = {};
144
150
  // The console's job list survives a reload and a restart because it is a FILE on disk,
145
151
  // not held in process memory.
146
- const jm = new JobManager(join(state.target, '.geneseed-web-runs.json'));
152
+ const jm = new JobManager(join(home, '.geneseed-web-runs.json'));
147
153
  const srv = createServer(makeHandler(state, jm, token, dist, holder));
148
154
  holder.srv = srv;
149
155
  return new Promise((done) => {
@@ -157,7 +163,7 @@ export async function serve({ theme = null, port = 4747, openBrowser = true,
157
163
  const hostPort = /** @type {import('node:net').AddressInfo} */ (srv.address()).port;
158
164
  const url = `http://127.0.0.1:${hostPort}`;
159
165
  if (daemon) {
160
- writeDaemon(state.target, {
166
+ writeDaemon(home, {
161
167
  pid: process.pid, port: hostPort, url,
162
168
  token, theme: state.theme, started: Math.floor(Date.now() / 1000), code: startCode,
163
169
  });
@@ -177,8 +183,8 @@ export async function serve({ theme = null, port = 4747, openBrowser = true,
177
183
  });
178
184
  srv.on('close', () => {
179
185
  if (daemon) {
180
- const st = readDaemon(state.target);
181
- if (!st || st.pid === process.pid) clearDaemon(state.target);
186
+ const st = readDaemon(home);
187
+ if (!st || st.pid === process.pid) clearDaemon(home);
182
188
  }
183
189
  done(0);
184
190
  });
package/js/web/state.mjs CHANGED
@@ -8,10 +8,10 @@
8
8
  import { existsSync } from 'node:fs';
9
9
  import path from 'node:path';
10
10
 
11
- import { opencodeConfigDir } from '../hosts/hosts.mjs';
11
+ import { CLAUDE_STYLE, GLOBAL_MANIFEST, HOSTS, opencodeConfigDir } from '../hosts/hosts.mjs';
12
12
  import {
13
- EMIT_HOST_SCOPE, footprintOfDir, installedDefaults, modeOfDir, postureOfDir, themeOfDir,
14
- trustOfDir,
13
+ EMIT_HOST_SCOPE, footprintOfDir, installState, installTargets, installedDefaults, modeOfDir,
14
+ postureOfDir, themeOfDir, trustOfDir,
15
15
  } from '../hosts/installs.mjs';
16
16
  import { doctorCollect } from '../inspect/doctor.mjs';
17
17
  import { DEFAULT_PRESET } from '../loop/score.mjs';
@@ -19,6 +19,36 @@ import { readText, isFile } from '../lib/fs.mjs';
19
19
  import { stripWhitespace } from '../lib/text.mjs';
20
20
  import { inventoryFor } from './catalog.mjs';
21
21
 
22
+ /**
23
+ * The data dir an install's inventory/memory/diff is read from. Host-driven, so a new
24
+ * nested-marker host cannot silently read the bare root.
25
+ */
26
+ export function viewCfg(host, scope, root) {
27
+ if (scope === 'project' && CLAUDE_STYLE.includes(host)) {
28
+ return path.join(root, HOSTS.find((h) => h.host === host).projectMarker);
29
+ }
30
+ return root;
31
+ }
32
+
33
+ /**
34
+ * `[target, root]` for the install the console should show when nothing picked one, or null
35
+ * when the current target is already deployed or nothing is.
36
+ *
37
+ * The console used to open on the OpenCode global dir unconditionally. On a machine with only
38
+ * IBM Bob (reported 2026-10) nothing is deployed there, so Overview showed the onboarding form
39
+ * over a perfectly good `~/.bob`, and the selector that could re-point it hides itself below two
40
+ * installs. So when `current` holds no manifest, the first ACTIVE install `installTargets`
41
+ * finds is shown instead — a global before a project, in its host order.
42
+ */
43
+ export function fallbackView(current, targets = installTargets()) {
44
+ if (existsSync(path.join(current, GLOBAL_MANIFEST))) return null;
45
+ const active = targets.filter(([host, scope, root]) => {
46
+ try { return installState(root, host, scope) === 'active'; } catch { return false; }
47
+ });
48
+ const pick = active.find(([, scope]) => scope === 'global') || active[0];
49
+ return pick ? [viewCfg(...pick), pick[2]] : null;
50
+ }
51
+
22
52
  /**
23
53
  * `YYYY-MM-DD HH:MM`, LOCAL time — `toISOString` would be UTC, which reads wrong in every
24
54
  * timezone but one for a user-facing timestamp.
@@ -154,6 +184,11 @@ export function webState(theme = null, target = null) {
154
184
  st._doctor = null;
155
185
  };
156
186
  st.refresh = ({ doctor = true } = {}) => {
187
+ // A job may have deployed the first install while the view still points at an empty
188
+ // default (the onboarding Build), or removed the one in view: follow it to one that exists.
189
+ // Only on a full refresh: `{ doctor: false }` marks a mutation that cannot change installs.
190
+ const fallback = doctor ? fallbackView(st.target) : null;
191
+ if (fallback) { st.selectView(...fallback); return; }
157
192
  st._inv = null;
158
193
  if (doctor) st._doctor = null;
159
194
  st.emit = st.detectEmit() || st.emit;
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": "4.10.0",
4
+ "version": "4.15.1",
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",
package/registry.json CHANGED
@@ -99,6 +99,20 @@
99
99
  "added": "2026-06-08",
100
100
  "last_verified": ""
101
101
  },
102
+ "agents/react-engineer": {
103
+ "status": "experimental",
104
+ "version": "1.0.0",
105
+ "owner": "Guillaume Lemer",
106
+ "added": "2026-10-21",
107
+ "last_verified": ""
108
+ },
109
+ "agents/react-reviewer": {
110
+ "status": "experimental",
111
+ "version": "1.0.0",
112
+ "owner": "Guillaume Lemer",
113
+ "added": "2026-10-21",
114
+ "last_verified": ""
115
+ },
102
116
  "agents/researcher": {
103
117
  "status": "approved",
104
118
  "version": "1.0.0",
@@ -400,6 +414,20 @@
400
414
  "added": "2026-09-06",
401
415
  "last_verified": ""
402
416
  },
417
+ "skills/react": {
418
+ "status": "experimental",
419
+ "version": "1.0.0",
420
+ "owner": "Guillaume Lemer",
421
+ "added": "2026-10-21",
422
+ "last_verified": ""
423
+ },
424
+ "skills/react-testing": {
425
+ "status": "experimental",
426
+ "version": "1.0.0",
427
+ "owner": "Guillaume Lemer",
428
+ "added": "2026-10-21",
429
+ "last_verified": ""
430
+ },
403
431
  "skills/react-view-transitions": {
404
432
  "status": "approved",
405
433
  "version": "1.0.0",
package/src/AGENT.md.tmpl CHANGED
@@ -187,9 +187,9 @@ contract you do not already know.
187
187
  **Rule of delegation:** read-only investigation can be dispatched freely; any
188
188
  {{AGENT}} that *writes* must return a summary of exactly what it changed. Every
189
189
  {{AGENT}} spec ends with a **self-improvement loop**: when a report carries a
190
- `spec-feedback:` line, weigh it — fold a real flaw back into that {{AGENT}}'s
191
- file (with the user's assent); {{MEMORY}} gets a record only when it clears
192
- {{DOCTRINE:persist-insight}}'s bar.
190
+ `spec-feedback:` line, weigh it — record a real flaw (with the user's assent) in
191
+ `{{DIR_NOTEBOOK}}/agent-notes/<name>.md` and pass it to later dispatches;
192
+ {{MEMORY}} gets a record only when it clears {{DOCTRINE:persist-insight}}'s bar.
193
193
 
194
194
  <!-- LEAN:begin -->
195
195
  **Dispatching a multi-part goal.** When a goal spans several capabilities,
@@ -293,8 +293,8 @@ When a task repeats and no {{SKILL}} covers it, forge one through the
293
293
  [skill-forge]({{DIR_SKILLS}}/skill-forge.md) {{SKILL}}: copy
294
294
  [`{{DIR_SKILLS}}/_template.md`]({{DIR_SKILLS}}/_template.md), keep it to one coherent
295
295
  domain ({{DOCTRINE:automate-repetition}}), and list it wherever this file carries a catalogue. Every {{SKILL}} ends with a
296
- **self-improvement loop** — honour it: fold what a run teaches back into the
297
- file, or into {{MEMORY}} ({{DOCTRINE:persist-insight}}).
296
+ **self-improvement loop** — honour it: a lesson goes to its notes, never into
297
+ the file, or to {{MEMORY}} ({{DOCTRINE:persist-insight}}).
298
298
 
299
299
  ---
300
300
 
@@ -0,0 +1,11 @@
1
+ ## Self-improvement
2
+
3
+ If this spec misled you — an input you needed but were not given, a boundary
4
+ that proved wrong, a step you could not execute — end your report with one line:
5
+ `spec-feedback: [agent|general] <the one-line fix> — seen: <what happened, against
6
+ what this spec led you to expect>`. `general` marks a fix other {{AGENTS}} need too.
7
+ Omit the line when there is no friction. The caller weighs the feedback and, with the
8
+ user's assent, writes a real flaw, dated, into `{{DIR_NOTEBOOK}}/agent-notes/<name>.md`
9
+ — never into this rendered file, which a rebuild overwrites — and hands those notes
10
+ to every later dispatch of this {{AGENT}}. It records the feedback to {{MEMORY}} only if it clears
11
+ {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
@@ -67,11 +67,4 @@ tells pipeline orchestration who to recruit; it changes nothing about how this
67
67
  - **Delivers:** what it must hand the next seat or the parent — same shape as
68
68
  its own output contract above, nothing looser.
69
69
 
70
- ## Self-improvement
71
-
72
- If this spec misled you — an input you needed but were not given, a boundary
73
- that proved wrong, a step you could not execute — end your report with one line:
74
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
75
- friction. The caller weighs the feedback, folds a real flaw back into this file
76
- with the user's assent, and records it to {{MEMORY}} only if it clears
77
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
70
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -26,11 +26,4 @@
26
26
  - A tight brief: the position in one line, the 2–4 load-bearing arguments for it, the key supporting evidence (`file:line` or facts), and the one objection it must beat. No hedging, no filler.
27
27
  - If the motion has fewer than two defensible upsides, report that the case cannot honestly be made — an invented argument loses the council more than a conceded seat.
28
28
 
29
- ## Self-improvement
30
-
31
- If this spec misled you — an input you needed but were not given, a boundary
32
- that proved wrong, a step you could not execute — end your report with one line:
33
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
34
- friction. The caller weighs the feedback, folds a real flaw back into this file
35
- with the user's assent, and records it to {{MEMORY}} only if it clears
36
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
29
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -48,11 +48,4 @@ independently.)*
48
48
  - **Delivers:** the plan for the developer seat to implement, same shape as its
49
49
  own output contract above.
50
50
 
51
- ## Self-improvement
52
-
53
- If this spec misled you — an input you needed but were not given, a boundary
54
- that proved wrong, a step you could not execute — end your report with one line:
55
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
56
- friction. The caller weighs the feedback, folds a real flaw back into this file
57
- with the user's assent, and records it to {{MEMORY}} only if it clears
58
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
51
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -56,11 +56,4 @@ independently.)*
56
56
  - **Delivers:** the changed files and a one-line summary, handed to the tester
57
57
  seat for validation.
58
58
 
59
- ## Self-improvement
60
-
61
- If this spec misled you — an input you needed but were not given, a boundary
62
- that proved wrong, a step you could not execute — end your report with one line:
63
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
64
- friction. The caller weighs the feedback, folds a real flaw back into this file
65
- with the user's assent, and records it to {{MEMORY}} only if it clears
66
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
59
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -34,12 +34,4 @@ Builds CI/CD pipelines and delivery automation for Spring Boot applications.
34
34
  ## Output contract
35
35
  - Files changed, the stage list and what was validated.
36
36
 
37
- ## Self-improvement
38
-
39
- If this spec misled you — an input you needed but were not given, a boundary
40
- that proved wrong, a step you could not execute — end your report with one line:
41
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
42
- friction. The caller weighs the feedback, folds a real flaw back into this file
43
- with the user's assent, and records it to {{MEMORY}} only if it clears
44
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
45
-
37
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -34,12 +34,4 @@ Builds small, safe container images for Spring Boot 4 applications.
34
34
  ## Output contract
35
35
  - Files changed, the build command and whether the image built and started.
36
36
 
37
- ## Self-improvement
38
-
39
- If this spec misled you — an input you needed but were not given, a boundary
40
- that proved wrong, a step you could not execute — end your report with one line:
41
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
42
- friction. The caller weighs the feedback, folds a real flaw back into this file
43
- with the user's assent, and records it to {{MEMORY}} only if it clears
44
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
45
-
37
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -49,11 +49,4 @@ independently.)*
49
49
  - **Receives:** the analyst's brief describing what changed and what needs documenting.
50
50
  - **Delivers:** the doc files written/updated, ready for the parent's merge decision.
51
51
 
52
- ## Self-improvement
53
-
54
- If this spec misled you — an input you needed but were not given, a boundary
55
- that proved wrong, a step you could not execute — end your report with one line:
56
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
57
- friction. The caller weighs the feedback, folds a real flaw back into this file
58
- with the user's assent, and records it to {{MEMORY}} only if it clears
59
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
52
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -29,11 +29,4 @@
29
29
  - A claims ledger: each load-bearing claim → evidenced? → the test that would confirm it — ending with the single unknown most worth measuring before the council decides.
30
30
  - If no evidence exists on either side, say exactly that — an empty ledger is a finding; padding it with plausible-sounding data is the one failure this seat cannot commit.
31
31
 
32
- ## Self-improvement
33
-
34
- If this spec misled you — an input you needed but were not given, a boundary
35
- that proved wrong, a step you could not execute — end your report with one line:
36
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
37
- friction. The caller weighs the feedback, folds a real flaw back into this file
38
- with the user's assent, and records it to {{MEMORY}} only if it clears
39
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
32
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -47,11 +47,4 @@ independently.)*
47
47
  - **Delivers:** a distilled brief the next seat (developer/docs) can act on
48
48
  directly — the scope, the relevant files, and any constraint already found.
49
49
 
50
- ## Self-improvement
51
-
52
- If this spec misled you — an input you needed but were not given, a boundary
53
- that proved wrong, a step you could not execute — end your report with one line:
54
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
55
- friction. The caller weighs the feedback, folds a real flaw back into this file
56
- with the user's assent, and records it to {{MEMORY}} only if it clears
57
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
50
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -26,11 +26,4 @@
26
26
  - The framing read: the real problem in one line, whether the motion fits it, the reframe if the framing is wrong, and the question the council should be debating instead.
27
27
  - If the framing holds up under attack, say so plainly and yield — a reframe invented to justify the seat derails a debate that was already sound.
28
28
 
29
- ## Self-improvement
30
-
31
- If this spec misled you — an input you needed but were not given, a boundary
32
- that proved wrong, a step you could not execute — end your report with one line:
33
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
34
- friction. The caller weighs the feedback, folds a real flaw back into this file
35
- with the user's assent, and records it to {{MEMORY}} only if it clears
36
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
29
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -41,11 +41,4 @@ independently.)*
41
41
  - **Delivers:** the precedent and its lesson, same shape as its own output
42
42
  contract above.
43
43
 
44
- ## Self-improvement
45
-
46
- If this spec misled you — an input you needed but were not given, a boundary
47
- that proved wrong, a step you could not execute — end your report with one line:
48
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
49
- friction. The caller weighs the feedback, folds a real flaw back into this file
50
- with the user's assent, and records it to {{MEMORY}} only if it clears
51
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
44
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -34,12 +34,4 @@ Deploys Spring Boot 4 applications on Kubernetes.
34
34
  ## Output contract
35
35
  - Files changed and a one-line summary; say what was validated and what was not.
36
36
 
37
- ## Self-improvement
38
-
39
- If this spec misled you — an input you needed but were not given, a boundary
40
- that proved wrong, a step you could not execute — end your report with one line:
41
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
42
- friction. The caller weighs the feedback, folds a real flaw back into this file
43
- with the user's assent, and records it to {{MEMORY}} only if it clears
44
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
45
-
37
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -61,11 +61,4 @@
61
61
  and report what was planned and what was applied — never a partial merge left
62
62
  unreported ({{LAW:surface-failures}}).
63
63
 
64
- ## Self-improvement
65
-
66
- If this spec misled you — an input you needed but were not given, a boundary
67
- that proved wrong, a step you could not execute — end your report with one line:
68
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
69
- friction. The caller weighs the feedback, folds a real flaw back into this file
70
- with the user's assent, and records it to {{MEMORY}} only if it clears
71
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
64
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -40,11 +40,4 @@ independently.)*
40
40
  - **Delivers:** the operability read and the rollback check, same shape as its
41
41
  own output contract above.
42
42
 
43
- ## Self-improvement
44
-
45
- If this spec misled you — an input you needed but were not given, a boundary
46
- that proved wrong, a step you could not execute — end your report with one line:
47
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
48
- friction. The caller weighs the feedback, folds a real flaw back into this file
49
- with the user's assent, and records it to {{MEMORY}} only if it clears
50
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
43
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -62,11 +62,4 @@ independently.)*
62
62
  - **Delivers:** measured findings and a verdict, same shape as its own output
63
63
  contract above.
64
64
 
65
- ## Self-improvement
66
-
67
- If this spec misled you — an input you needed but were not given, a boundary
68
- that proved wrong, a step you could not execute — end your report with one line:
69
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
70
- friction. The caller weighs the feedback, folds a real flaw back into this file
71
- with the user's assent, and records it to {{MEMORY}} only if it clears
72
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
65
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -39,11 +39,4 @@ independently.)*
39
39
  - **Delivers:** the cheapest viable path and what to cut, before any code is
40
40
  written — same shape as its own output contract above.
41
41
 
42
- ## Self-improvement
43
-
44
- If this spec misled you — an input you needed but were not given, a boundary
45
- that proved wrong, a step you could not execute — end your report with one line:
46
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
47
- friction. The caller weighs the feedback, folds a real flaw back into this file
48
- with the user's assent, and records it to {{MEMORY}} only if it clears
49
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
42
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -0,0 +1,38 @@
1
+ # {{AGENT}}: react-engineer
2
+
3
+ > {{DESC_REACT_ENGINEER}}
4
+
5
+ {{CREDIT:everything-claude-code:skills/react-patterns/SKILL.md}}
6
+
7
+ Implements React features in a Vite or webpack app, TypeScript or JavaScript, following the react and react-testing skills.
8
+
9
+ ## When to dispatch
10
+ - A React component, page, hook or form is scoped and code must be written, or a Vite or webpack build or Jest run is broken and must be made green.
11
+
12
+ ## When NOT to dispatch
13
+ - The design is unclear — use [architect](architect.md) first. The visual direction is open — the frontend-design skill first.
14
+ - Tests only — use [tester](tester.md). Non-React code — use [developer](developer.md).
15
+
16
+ ## Inputs
17
+ - The scoped task, the target folder or worktree, and the acceptance criteria.
18
+
19
+ ## Allowed tools
20
+ - **Read + write to the assigned worktree.** May run the project's lint, typecheck, test and build scripts.
21
+ <!-- bash: allow -->
22
+ - Never commits or pushes ({{DOCTRINE:consent-before-push}}).
23
+
24
+ ## Procedure
25
+ 0. If `{{DIR_MEMORY}}/agents/<your-name>.md` exists, read it first — your durable lessons from prior dispatches ({{DOCTRINE:persist-insight}}).
26
+ 1. Read `package.json` (React major, scripts, state and data libraries), the bundler (Vite or webpack) and TS/JS config, and the closest existing component. Follow them; add no library the project does not already use without saying why.
27
+ 2. Keep the folder's language: `.tsx` with typed props and no `any`, or `.jsx`.
28
+ 3. Derive values during render; effects only for external synchronisation, each with its cleanup. Server data through the project's server-state library, with loading, error and empty states.
29
+ 4. Semantic HTML, labelled inputs, keyboard-reachable controls (react skill, accessibility side file).
30
+ 5. Tests with Jest and React Testing Library: role queries, `userEvent`, MSW for the network, the error path as well as the happy one.
31
+ 6. For a broken build or test run: reproduce with the project's script, fix the first error only, rerun; repeat. Never `@ts-ignore`, `any` or a disabled lint rule to get green. Stop and report after three failed attempts at one error.
32
+ 7. Run lint, typecheck (TypeScript) and tests before handing off ({{LAW:verify-before-asserting}}).
33
+
34
+ ## Output contract
35
+ - Files changed, a one-line summary, and each command run with its result.
36
+ - If the task cannot be done as given, report the blocker instead of guessing.
37
+
38
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -0,0 +1,42 @@
1
+ # {{AGENT}}: react-reviewer
2
+
3
+ > {{DESC_REACT_REVIEWER}}
4
+
5
+ {{CREDIT:everything-claude-code:agents/react-reviewer.md}}
6
+
7
+ React-specific review only. Generic correctness, naming and structure belong to [reviewer](reviewer.md); defer to it and do not repeat its checks.
8
+
9
+ ## When to dispatch
10
+ - A change touches `.tsx` / `.jsx` files, hooks or React tests and needs a framework-aware pass.
11
+
12
+ ## When NOT to dispatch
13
+ - No React code in the diff, or a generic review — use [reviewer](reviewer.md).
14
+ - A wider security question (auth design, the API behind the UI) — use [security](security.md).
15
+
16
+ ## Inputs
17
+ - The base..head range (or the diff) and the task it was meant to satisfy.
18
+
19
+ ## Allowed tools
20
+ - **Read-only.** May read code, run the lint, typecheck and test scripts, inspect history.
21
+ - Does not edit code; it reports. Never moves HEAD, the index or the working tree.
22
+ <!-- bash: allow -->
23
+
24
+ ## Procedure
25
+ 0. If `{{DIR_MEMORY}}/agents/<your-name>.md` exists, read it first — your durable lessons from prior dispatches ({{DOCTRINE:persist-insight}}).
26
+ 1. Read the changed files and `package.json` for the React major. Run lint and, for TypeScript, the typecheck; a missing `react-hooks/rules-of-hooks` or `react-hooks/exhaustive-deps` rule is itself a finding.
27
+ 2. Check, in this order:
28
+ - Security: `dangerouslySetInnerHTML` without a sanitiser at the call site; a user-supplied URL in `href`/`src` without a scheme check; a secret in a bundler-inlined env value (`import.meta.env.VITE_*`, webpack `DefinePlugin`); a session token in `localStorage`.
29
+ - Hooks: a hook behind a condition, loop or early return; a missing effect dependency, or an `exhaustive-deps` disable without a reason; an effect without cleanup; a stale closure in a timer or async handler.
30
+ - State: mutation before `setState`; state duplicated or derived through an effect; an effect chain setting state that triggers another effect; `key={index}` on a list that changes.
31
+ - Data: `useEffect` + `fetch` where the project has a server-state library; a request with no loading, error or empty state; a fetch without abort.
32
+ - Accessibility: `<div onClick>`, an unlabelled input, `<img>` without `alt`, an error shown by colour alone, a modal that does not manage focus.
33
+ - Types (TypeScript): `any`, a non-null `!` or an `as` cast that hides a real case, untyped props.
34
+ - Tests: queries by test id or `querySelector` where a role query works, `fireEvent` where `userEvent` fits, sleeps, component snapshots, the error path untested.
35
+ - Performance, only with evidence: memoisation with no measured gain, an inline object defeating a `React.memo` child, a long list not virtualised.
36
+ 3. Verify by running the tests rather than assuming ({{LAW:verify-before-asserting}}).
37
+
38
+ ## Output contract
39
+ - Findings as Conventional Comments, `label (decoration): file:line — problem — suggested fix`, most serious first; then a **Set aside:** list (or `none`) and a one-line verdict: any blocking → block, any if-minor and nothing blocking → fix-then-ship, otherwise ship.
40
+ - Name any check that was impossible instead of issuing a verdict on partial evidence.
41
+
42
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -39,8 +39,10 @@
39
39
  and one empty result is not absence ({{LAW:verify-before-asserting}}).
40
40
  3. Open the most promising sources and extract only the relevant slice, never
41
41
  the whole page. Prefer primary and recent sources.
42
- 4. Cross-check every material claim against at least two independent sources.
43
- A single-source or unsourced claim stays marked unverified.
42
+ 4. Cross-check every material claim: one read in the source that owns it (spec, source
43
+ code, official docs, at the version in question) stands on that source; any other needs
44
+ two independent sources.
45
+ Any other single-source or unsourced claim stays marked unverified.
44
46
  5. Note recency — flag anything that may be out of date.
45
47
 
46
48
  ## Output contract
@@ -63,11 +65,4 @@ independently.)*
63
65
  - **Delivers:** the sourced findings list, same shape as its own output
64
66
  contract above.
65
67
 
66
- ## Self-improvement
67
-
68
- If this spec misled you — an input you needed but were not given, a boundary
69
- that proved wrong, a step you could not execute — end your report with one line:
70
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
71
- friction. The caller weighs the feedback, folds a real flaw back into this file
72
- with the user's assent, and records it to {{MEMORY}} only if it clears
73
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
68
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -55,11 +55,4 @@ independently.)*
55
55
  - **Delivers:** the findings list and ship/fix-then-ship/block verdict, same
56
56
  shape as its own output contract above.
57
57
 
58
- ## Self-improvement
59
-
60
- If this spec misled you — an input you needed but were not given, a boundary
61
- that proved wrong, a step you could not execute — end your report with one line:
62
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
63
- friction. The caller weighs the feedback, folds a real flaw back into this file
64
- with the user's assent, and records it to {{MEMORY}} only if it clears
65
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
58
+ <!-- INCLUDE: agents/_self-improvement.md -->
@@ -53,11 +53,4 @@ independently.)*
53
53
  - **Delivers:** severity-ranked findings and a ship/fix-required verdict, same
54
54
  shape as its own output contract above.
55
55
 
56
- ## Self-improvement
57
-
58
- If this spec misled you — an input you needed but were not given, a boundary
59
- that proved wrong, a step you could not execute — end your report with one line:
60
- `spec-feedback: <what failed — the one-line fix>`. Omit it when there is no
61
- friction. The caller weighs the feedback, folds a real flaw back into this file
62
- with the user's assent, and records it to {{MEMORY}} only if it clears
63
- {{DOCTRINE:persist-insight}}'s bar — most reports carry no feedback at all.
56
+ <!-- INCLUDE: agents/_self-improvement.md -->