@ijfw/memory-server 1.4.4 → 1.5.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 (245) hide show
  1. package/bin/ijfw-memorize +14 -7
  2. package/fixtures/team/book.json +6 -6
  3. package/fixtures/team/business.json +146 -20
  4. package/fixtures/team/content.json +6 -6
  5. package/fixtures/team/design.json +148 -20
  6. package/fixtures/team/mixed.json +206 -27
  7. package/fixtures/team/research.json +146 -20
  8. package/fixtures/team/software.json +148 -20
  9. package/fixtures/truncation-corpus/_generate-corpus.js +367 -0
  10. package/fixtures/truncation-corpus/fx-01-clean-exit-01/events.jsonl +2 -0
  11. package/fixtures/truncation-corpus/fx-01-clean-exit-01/intent-journal.jsonl +2 -0
  12. package/fixtures/truncation-corpus/fx-01-clean-exit-01/meta.json +18 -0
  13. package/fixtures/truncation-corpus/fx-01-clean-exit-01/target/.ijfw/state/workflow.json +1 -0
  14. package/fixtures/truncation-corpus/fx-01-clean-exit-02/events.jsonl +2 -0
  15. package/fixtures/truncation-corpus/fx-01-clean-exit-02/intent-journal.jsonl +2 -0
  16. package/fixtures/truncation-corpus/fx-01-clean-exit-02/meta.json +18 -0
  17. package/fixtures/truncation-corpus/fx-01-clean-exit-02/target/.ijfw/state/workflow.json +1 -0
  18. package/fixtures/truncation-corpus/fx-01-clean-exit-03/events.jsonl +2 -0
  19. package/fixtures/truncation-corpus/fx-01-clean-exit-03/intent-journal.jsonl +2 -0
  20. package/fixtures/truncation-corpus/fx-01-clean-exit-03/meta.json +18 -0
  21. package/fixtures/truncation-corpus/fx-01-clean-exit-03/target/.ijfw/state/workflow.json +1 -0
  22. package/fixtures/truncation-corpus/fx-01-clean-exit-04/events.jsonl +2 -0
  23. package/fixtures/truncation-corpus/fx-01-clean-exit-04/intent-journal.jsonl +2 -0
  24. package/fixtures/truncation-corpus/fx-01-clean-exit-04/meta.json +18 -0
  25. package/fixtures/truncation-corpus/fx-01-clean-exit-04/target/.ijfw/state/workflow.json +1 -0
  26. package/fixtures/truncation-corpus/fx-01-clean-exit-05/events.jsonl +2 -0
  27. package/fixtures/truncation-corpus/fx-01-clean-exit-05/intent-journal.jsonl +2 -0
  28. package/fixtures/truncation-corpus/fx-01-clean-exit-05/meta.json +18 -0
  29. package/fixtures/truncation-corpus/fx-01-clean-exit-05/target/.ijfw/state/workflow.json +1 -0
  30. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/events.jsonl +1 -0
  31. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/intent-journal.jsonl +3 -0
  32. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/meta.json +18 -0
  33. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/snapshots/v-midO-1-advance.json +11 -0
  34. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/target/.ijfw/state/workflow.json +1 -0
  35. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/events.jsonl +1 -0
  36. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/intent-journal.jsonl +3 -0
  37. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/meta.json +18 -0
  38. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/snapshots/v-midO-2-advance.json +11 -0
  39. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/target/.ijfw/state/workflow.json +1 -0
  40. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/events.jsonl +1 -0
  41. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/intent-journal.jsonl +3 -0
  42. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/meta.json +18 -0
  43. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/snapshots/v-midO-3-advance.json +11 -0
  44. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/target/.ijfw/state/workflow.json +1 -0
  45. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/events.jsonl +1 -0
  46. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/intent-journal.jsonl +3 -0
  47. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/meta.json +18 -0
  48. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/snapshots/v-midO-4-advance.json +11 -0
  49. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/target/.ijfw/state/workflow.json +1 -0
  50. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/events.jsonl +1 -0
  51. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/intent-journal.jsonl +3 -0
  52. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/meta.json +18 -0
  53. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/snapshots/v-midO-5-advance.json +11 -0
  54. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/target/.ijfw/state/workflow.json +1 -0
  55. package/fixtures/truncation-corpus/fx-03-mid-append-01/events.jsonl +1 -0
  56. package/fixtures/truncation-corpus/fx-03-mid-append-01/intent-journal.jsonl +3 -0
  57. package/fixtures/truncation-corpus/fx-03-mid-append-01/meta.json +18 -0
  58. package/fixtures/truncation-corpus/fx-03-mid-append-01/target/.ijfw/blackboard/decisions.jsonl +1 -0
  59. package/fixtures/truncation-corpus/fx-03-mid-append-02/events.jsonl +1 -0
  60. package/fixtures/truncation-corpus/fx-03-mid-append-02/intent-journal.jsonl +3 -0
  61. package/fixtures/truncation-corpus/fx-03-mid-append-02/meta.json +18 -0
  62. package/fixtures/truncation-corpus/fx-03-mid-append-02/target/.ijfw/blackboard/decisions.jsonl +1 -0
  63. package/fixtures/truncation-corpus/fx-03-mid-append-03/events.jsonl +1 -0
  64. package/fixtures/truncation-corpus/fx-03-mid-append-03/intent-journal.jsonl +3 -0
  65. package/fixtures/truncation-corpus/fx-03-mid-append-03/meta.json +18 -0
  66. package/fixtures/truncation-corpus/fx-03-mid-append-03/target/.ijfw/blackboard/decisions.jsonl +1 -0
  67. package/fixtures/truncation-corpus/fx-03-mid-append-04/events.jsonl +1 -0
  68. package/fixtures/truncation-corpus/fx-03-mid-append-04/intent-journal.jsonl +3 -0
  69. package/fixtures/truncation-corpus/fx-03-mid-append-04/meta.json +18 -0
  70. package/fixtures/truncation-corpus/fx-03-mid-append-04/target/.ijfw/blackboard/decisions.jsonl +1 -0
  71. package/fixtures/truncation-corpus/fx-03-mid-append-05/events.jsonl +1 -0
  72. package/fixtures/truncation-corpus/fx-03-mid-append-05/intent-journal.jsonl +3 -0
  73. package/fixtures/truncation-corpus/fx-03-mid-append-05/meta.json +18 -0
  74. package/fixtures/truncation-corpus/fx-03-mid-append-05/target/.ijfw/blackboard/decisions.jsonl +1 -0
  75. package/fixtures/truncation-corpus/fx-04-no-events-01/events.jsonl +0 -0
  76. package/fixtures/truncation-corpus/fx-04-no-events-01/intent-journal.jsonl +1 -0
  77. package/fixtures/truncation-corpus/fx-04-no-events-01/meta.json +18 -0
  78. package/fixtures/truncation-corpus/fx-04-no-events-01/snapshots/v-noEv-1-set-phase.json +11 -0
  79. package/fixtures/truncation-corpus/fx-04-no-events-01/target/.ijfw/state/workflow.json +1 -0
  80. package/fixtures/truncation-corpus/fx-04-no-events-02/events.jsonl +0 -0
  81. package/fixtures/truncation-corpus/fx-04-no-events-02/intent-journal.jsonl +1 -0
  82. package/fixtures/truncation-corpus/fx-04-no-events-02/meta.json +18 -0
  83. package/fixtures/truncation-corpus/fx-04-no-events-02/snapshots/v-noEv-2-set-phase.json +11 -0
  84. package/fixtures/truncation-corpus/fx-04-no-events-02/target/.ijfw/state/workflow.json +1 -0
  85. package/fixtures/truncation-corpus/fx-04-no-events-03/events.jsonl +0 -0
  86. package/fixtures/truncation-corpus/fx-04-no-events-03/intent-journal.jsonl +1 -0
  87. package/fixtures/truncation-corpus/fx-04-no-events-03/meta.json +18 -0
  88. package/fixtures/truncation-corpus/fx-04-no-events-03/snapshots/v-noEv-3-set-phase.json +11 -0
  89. package/fixtures/truncation-corpus/fx-04-no-events-03/target/.ijfw/state/workflow.json +1 -0
  90. package/fixtures/truncation-corpus/fx-04-no-events-04/events.jsonl +0 -0
  91. package/fixtures/truncation-corpus/fx-04-no-events-04/intent-journal.jsonl +1 -0
  92. package/fixtures/truncation-corpus/fx-04-no-events-04/meta.json +18 -0
  93. package/fixtures/truncation-corpus/fx-04-no-events-04/snapshots/v-noEv-4-set-phase.json +11 -0
  94. package/fixtures/truncation-corpus/fx-04-no-events-04/target/.ijfw/state/workflow.json +1 -0
  95. package/fixtures/truncation-corpus/fx-04-no-events-05/events.jsonl +0 -0
  96. package/fixtures/truncation-corpus/fx-04-no-events-05/intent-journal.jsonl +1 -0
  97. package/fixtures/truncation-corpus/fx-04-no-events-05/meta.json +18 -0
  98. package/fixtures/truncation-corpus/fx-04-no-events-05/snapshots/v-noEv-5-set-phase.json +11 -0
  99. package/fixtures/truncation-corpus/fx-04-no-events-05/target/.ijfw/state/workflow.json +1 -0
  100. package/fixtures/truncation-corpus/fx-05-error-terminated-01/events.jsonl +2 -0
  101. package/fixtures/truncation-corpus/fx-05-error-terminated-01/intent-journal.jsonl +3 -0
  102. package/fixtures/truncation-corpus/fx-05-error-terminated-01/meta.json +18 -0
  103. package/fixtures/truncation-corpus/fx-05-error-terminated-01/snapshots/v-errT-1-partial.json +11 -0
  104. package/fixtures/truncation-corpus/fx-05-error-terminated-01/target/.ijfw/state/workflow.json +1 -0
  105. package/fixtures/truncation-corpus/fx-05-error-terminated-02/events.jsonl +2 -0
  106. package/fixtures/truncation-corpus/fx-05-error-terminated-02/intent-journal.jsonl +3 -0
  107. package/fixtures/truncation-corpus/fx-05-error-terminated-02/meta.json +18 -0
  108. package/fixtures/truncation-corpus/fx-05-error-terminated-02/target/.ijfw/blackboard/decisions.jsonl +1 -0
  109. package/fixtures/truncation-corpus/fx-05-error-terminated-03/events.jsonl +2 -0
  110. package/fixtures/truncation-corpus/fx-05-error-terminated-03/intent-journal.jsonl +3 -0
  111. package/fixtures/truncation-corpus/fx-05-error-terminated-03/meta.json +18 -0
  112. package/fixtures/truncation-corpus/fx-05-error-terminated-03/snapshots/v-errT-3-partial.json +11 -0
  113. package/fixtures/truncation-corpus/fx-05-error-terminated-03/target/.ijfw/state/workflow.json +1 -0
  114. package/fixtures/truncation-corpus/fx-05-error-terminated-04/events.jsonl +2 -0
  115. package/fixtures/truncation-corpus/fx-05-error-terminated-04/intent-journal.jsonl +3 -0
  116. package/fixtures/truncation-corpus/fx-05-error-terminated-04/meta.json +18 -0
  117. package/fixtures/truncation-corpus/fx-05-error-terminated-04/target/.ijfw/blackboard/decisions.jsonl +1 -0
  118. package/fixtures/truncation-corpus/fx-05-error-terminated-05/events.jsonl +2 -0
  119. package/fixtures/truncation-corpus/fx-05-error-terminated-05/intent-journal.jsonl +3 -0
  120. package/fixtures/truncation-corpus/fx-05-error-terminated-05/meta.json +18 -0
  121. package/fixtures/truncation-corpus/fx-05-error-terminated-05/snapshots/v-errT-5-partial.json +11 -0
  122. package/fixtures/truncation-corpus/fx-05-error-terminated-05/target/.ijfw/state/workflow.json +1 -0
  123. package/package.json +6 -3
  124. package/src/active-extension-writer.js +144 -64
  125. package/src/api-client.js +43 -5
  126. package/src/audit-roster.js +80 -5
  127. package/src/blackboard.js +298 -6
  128. package/src/cli-run.js +33 -5
  129. package/src/codex-agents.js +96 -5
  130. package/src/cost/aggregator.js +39 -9
  131. package/src/cost/pricing.js +57 -0
  132. package/src/cost/readers/gemini.js +1 -1
  133. package/src/cross-audit-chunker.js +189 -0
  134. package/src/cross-dispatcher.js +124 -21
  135. package/src/cross-orchestrator-cli.js +754 -159
  136. package/src/cross-orchestrator.js +1065 -17
  137. package/src/cross-project-search.js +195 -9
  138. package/src/dashboard-client-waves.html +304 -0
  139. package/src/dashboard-client.html +5 -1
  140. package/src/dashboard-server.js +73 -0
  141. package/src/deploy-alerts.js +150 -0
  142. package/src/design/iframe-bridge.js +242 -0
  143. package/src/design-companion.js +144 -0
  144. package/src/dispatch/checkpoint-cli.js +97 -0
  145. package/src/dispatch/colon-syntax.js +81 -1
  146. package/src/dispatch/extension.js +26 -2
  147. package/src/dispatch/registry-cli.js +4 -1
  148. package/src/dispatch/wave-cli.js +201 -6
  149. package/src/dispatch/worktree-cli.js +40 -0
  150. package/src/dispatch-planner.js +97 -2
  151. package/src/dream/runner.mjs +47 -11
  152. package/src/dream/stage-runner.js +40 -0
  153. package/src/dream/state-file.js +102 -0
  154. package/src/extension-installer.js +70 -24
  155. package/src/extension-quota-tracker.js +4 -2
  156. package/src/extension-registry.js +289 -35
  157. package/src/feedback-detector.js +26 -0
  158. package/src/fs-lock.js +259 -7
  159. package/src/gate-result.js +95 -1
  160. package/src/hardware-signer.js +4 -2
  161. package/src/hero-line.js +86 -5
  162. package/src/intent-router.js +35 -0
  163. package/src/lib/a11y-contract.js +117 -0
  164. package/src/lib/atomic-io.js +29 -8
  165. package/src/lib/cache-keepalive.js +150 -0
  166. package/src/lib/jsonl-rotation.js +104 -0
  167. package/src/lib/lighthouse-pillar.js +121 -0
  168. package/src/lib/llm-call.js +121 -0
  169. package/src/lib/playwright-baseline.js +205 -0
  170. package/src/lib/rekor-bridge.js +221 -0
  171. package/src/lib/repo-map.js +392 -0
  172. package/src/lib/shasum-verify.js +164 -0
  173. package/src/lib/sketches-gc.js +132 -0
  174. package/src/lib/tmp-suffix.js +62 -0
  175. package/src/lib/ui-review-runner.js +595 -0
  176. package/src/lib/uispec-drift.js +301 -0
  177. package/src/lib/uispec-intake.js +381 -0
  178. package/src/lib/worktree-guards.js +118 -0
  179. package/src/lib/worktree-recovery.js +100 -0
  180. package/src/memory/auto-linker.js +267 -0
  181. package/src/memory/benchmark.js +498 -0
  182. package/src/memory/dedup.js +126 -0
  183. package/src/memory/embedding-cache.js +136 -0
  184. package/src/memory/fact-extractor.js +168 -0
  185. package/src/memory/fts5.js +65 -1
  186. package/src/memory/migration-runner.js +6 -1
  187. package/src/memory/migrations/004-bitemporal.js +91 -0
  188. package/src/memory/migrations/005-vector-cache.js +61 -0
  189. package/src/memory/migrations/006-obsidian-graph.js +46 -0
  190. package/src/memory/migrations/007-skill-telemetry.js +24 -0
  191. package/src/memory/migrations/008-write-provenance.js +41 -0
  192. package/src/memory/migrations/009-obsidian-backfill.js +50 -0
  193. package/src/memory/obsidian-parser.js +152 -0
  194. package/src/memory/query-dataview.js +86 -0
  195. package/src/memory/search.js +46 -15
  196. package/src/memory/temporal.js +529 -0
  197. package/src/memory/tokenize.js +10 -0
  198. package/src/memory-facts-handler.js +37 -0
  199. package/src/memory-feedback.js +260 -2
  200. package/src/model-refresh.js +292 -0
  201. package/src/observability/cost-anomaly.js +166 -0
  202. package/src/observability/evaluator-checkpoint-contract.js +117 -0
  203. package/src/observability/trace-id.js +163 -0
  204. package/src/orchestrator/agents-md-blackboard.js +152 -0
  205. package/src/orchestrator/checkpoint-contract.md +140 -0
  206. package/src/orchestrator/debug-trident-trigger.js +374 -0
  207. package/src/orchestrator/debug-trident.js +570 -0
  208. package/src/orchestrator/merge-block-aware.js +350 -0
  209. package/src/orchestrator/plan-checker.js +475 -0
  210. package/src/orchestrator/post-done-runner.js +277 -0
  211. package/src/orchestrator/review.js +38 -3
  212. package/src/orchestrator/skill-telemetry-sink.js +29 -0
  213. package/src/orchestrator/skill-telemetry.js +37 -0
  214. package/src/orchestrator/state-events.js +459 -0
  215. package/src/orchestrator/state-sdk.js +1932 -0
  216. package/src/orchestrator/status-protocol.js +84 -17
  217. package/src/orchestrator/subagent-telemetry.js +471 -0
  218. package/src/orchestrator/termination.js +160 -0
  219. package/src/orchestrator/verification-gate.js +200 -16
  220. package/src/orchestrator/wave-state.js +332 -23
  221. package/src/orchestrator/worktree-provision.js +77 -0
  222. package/src/override-resolver.js +5 -3
  223. package/src/override-use-registry.js +111 -5
  224. package/src/receipts.js +36 -4
  225. package/src/recovery/checkpoint.js +56 -3
  226. package/src/recovery/code-fixer.js +961 -0
  227. package/src/recovery/truncation.js +317 -0
  228. package/src/redactor.js +75 -6
  229. package/src/runtime-mediator.js +15 -1
  230. package/src/sanitizer.js +10 -0
  231. package/src/search-hybrid.js +139 -0
  232. package/src/server.js +795 -112
  233. package/src/swarm/worktree.js +27 -4
  234. package/src/swarm-config.js +102 -17
  235. package/src/team/domain-templates/book.json +51 -0
  236. package/src/team/domain-templates/business.json +44 -0
  237. package/src/team/domain-templates/content.json +50 -0
  238. package/src/team/domain-templates/design.json +44 -0
  239. package/src/team/domain-templates/research.json +44 -0
  240. package/src/team/domain-templates/software.json +40 -0
  241. package/src/team/generator.js +440 -3
  242. package/src/team/modify.js +203 -0
  243. package/src/team/schemas.js +48 -0
  244. package/src/update-apply.js +19 -3
  245. package/src/dashboard-charts.js +0 -239
@@ -7,6 +7,7 @@
7
7
  import { existsSync, mkdirSync, realpathSync, rmSync } from 'node:fs';
8
8
  import { isAbsolute, join, relative, resolve } from 'node:path';
9
9
  import { spawnSync } from 'node:child_process';
10
+ import { createHash } from 'node:crypto';
10
11
  import { appendBlackboardEvent, listBlackboardTasks, updateBlackboardTask } from '../blackboard.js';
11
12
  import { createCheckpoint } from '../recovery/checkpoint.js';
12
13
 
@@ -29,12 +30,31 @@ export function createTaskWorktree(projectRoot, taskId, options = {}) {
29
30
 
30
31
  const baseRef = options.baseRef || 'HEAD';
31
32
  const worktreeDir = join(root, '.ijfw', 'worktrees');
32
- const worktreePath = join(worktreeDir, safeTaskId(taskId));
33
- if (existsSync(worktreePath)) return { ok: false, error: 'worktree-exists', path: worktreePath };
34
33
  mkdirSync(worktreeDir, { recursive: true, mode: 0o700 });
35
34
 
35
+ // v1.5.0 audit-LOW-teams-#15: safeTaskId collision detection.
36
+ // Two distinct taskIds that normalize to the same safe id (e.g. `task:1`
37
+ // and `task/1` both become `task-1`) would otherwise collide on the same
38
+ // worktree path AND the same branch name. Detect the collision by checking
39
+ // BOTH the worktree dir AND the existing branch list; if either is taken,
40
+ // suffix the safe id with a short content hash of the original taskId so
41
+ // distinct tasks get distinct worktrees + branches.
42
+ const baseSafeId = safeTaskId(taskId);
43
+ let safeId = baseSafeId;
44
+ let candidatePath = join(worktreeDir, safeId);
45
+ let candidateBranch = options.branch || `ijfw/${safeId}`;
46
+ const branchExists = (name) => git(root, ['show-ref', '--verify', '--quiet', `refs/heads/${name}`]).status === 0;
47
+ if (!options.branch && (existsSync(candidatePath) || branchExists(candidateBranch))) {
48
+ const suffix = createHash('sha256').update(String(taskId)).digest('hex').slice(0, 7);
49
+ safeId = `${baseSafeId}-${suffix}`;
50
+ candidatePath = join(worktreeDir, safeId);
51
+ candidateBranch = `ijfw/${safeId}`;
52
+ }
53
+ const worktreePath = candidatePath;
54
+ if (existsSync(worktreePath)) return { ok: false, error: 'worktree-exists', path: worktreePath };
55
+
36
56
  createCheckpoint(root, 'before-worktree-create', { actor: 'ijfw', message: taskId });
37
- const branch = options.branch || `ijfw/${safeTaskId(taskId)}`;
57
+ const branch = options.branch || candidateBranch;
38
58
  const result = git(root, ['worktree', 'add', '-b', branch, worktreePath, baseRef]);
39
59
  if (result.status !== 0) return { ok: false, error: 'worktree-add-failed', stderr: result.stderr, stdout: result.stdout };
40
60
 
@@ -81,7 +101,10 @@ export function integrateTaskWorktree(projectRoot, taskId, options = {}) {
81
101
  if (wtDirty.stdout.trim()) return { ok: false, error: 'worktree-has-uncommitted-changes', detail: wtDirty.stdout.trim().split('\n') };
82
102
 
83
103
  createCheckpoint(root, 'before-worktree-integrate', { actor: 'ijfw', message: taskId });
84
- const merge = git(root, ['merge', '--no-ff', '--no-edit', validation.branch]);
104
+ // v1.5.0 audit-LOW-teams-#14: tag merge commits with task-id so
105
+ // `git log --grep="ijfw merge: <task-id>"` recovers the merge boundary
106
+ // even after history rewrites lose the branch label.
107
+ const merge = git(root, ['merge', '--no-ff', '-m', `ijfw merge: ${taskId}`, validation.branch]);
85
108
  if (merge.status !== 0) {
86
109
  updateBlackboardTask(root, taskId, {
87
110
  worktree: { ...wt, status: 'merge-blocked', last_error: merge.stderr || merge.stdout },
@@ -25,22 +25,100 @@ const BASE = [
25
25
  const TESTS_SPECIALIST = { id: 'tests', role: 'Test coverage', agent_type: 'pr-test-analyzer' };
26
26
  const TYPES_SPECIALIST = { id: 'types', role: 'Type invariants', agent_type: 'type-design-analyzer' };
27
27
 
28
- // v1.4.4 N6 — 5 specialist agents addressing v1.4.3 build pain points
29
- const DOC_VERIFIER = { id: 'doc-verifier', role: 'Doc accuracy', agent_type: 'ijfw-doc-verifier' };
30
- const PATTERN_MAPPER = { id: 'pattern-mapper', role: 'Onboarding patterns', agent_type: 'ijfw-pattern-mapper' };
31
- const SECURITY_AUDITOR = { id: 'security-auditor', role: 'Security mitigations', agent_type: 'ijfw-security-auditor' };
32
- const INTEGRATION_CHECKER = { id: 'integration-checker', role: 'E2E flow verification', agent_type: 'ijfw-integration-checker' };
33
- const NYQUIST_AUDITOR = { id: 'nyquist-auditor', role: 'Coverage gaps', agent_type: 'ijfw-nyquist-auditor' };
28
+ // v1.4.4 N6 — 5 specialist agents addressing v1.4.3 build pain points.
29
+ // `since` is the version the specialist was introduced (lock-in #40 added
30
+ // retroactively in v1.5.0 W11-D1 so registration-history queries can sort
31
+ // by introduction).
32
+ const DOC_VERIFIER = { id: 'doc-verifier', role: 'Doc accuracy', agent_type: 'ijfw-doc-verifier', since: '1.4.4' };
33
+ const PATTERN_MAPPER = { id: 'pattern-mapper', role: 'Onboarding patterns', agent_type: 'ijfw-pattern-mapper', since: '1.4.4' };
34
+ const SECURITY_AUDITOR = { id: 'security-auditor', role: 'Security mitigations', agent_type: 'ijfw-security-auditor', since: '1.4.4' };
35
+ const INTEGRATION_CHECKER = { id: 'integration-checker', role: 'E2E flow verification', agent_type: 'ijfw-integration-checker', since: '1.4.4' };
36
+ const NYQUIST_AUDITOR = { id: 'nyquist-auditor', role: 'Coverage gaps', agent_type: 'ijfw-nyquist-auditor', since: '1.4.4' };
37
+
38
+ // v1.5.0 W11-D1 S9 — 5 NEW IJFW specialists addressing v1.4.4 build pain points.
39
+ const RALPH_LOOP_RUNNER = { id: 'ralph-loop-runner', role: 'Subagent truncation recovery', agent_type: 'ijfw-ralph-loop-runner', since: '1.5.0' };
40
+ const PLAN_CHECKER = { id: 'plan-checker', role: 'Plan vs codebase reality check', agent_type: 'ijfw-plan-checker', since: '1.5.0' };
41
+ const DEP_AUDIT = { id: 'dep-audit', role: 'Dependency / publishConfig drift', agent_type: 'ijfw-dep-audit', since: '1.5.0' };
42
+ const E2E_RUNNER = { id: 'e2e-runner', role: 'Pre-ship install/update/uninstall', agent_type: 'ijfw-e2e-runner', since: '1.5.0' };
43
+ const LLM_BUDGET_WATCHER = { id: 'llm-budget-watcher', role: 'Token-cost vs phase budget', agent_type: 'ijfw-llm-budget-watcher', since: '1.5.0' };
44
+
45
+ // v1.5.0 W11-D1 F1 — 3 GSD specialists folded in from R3 research.
46
+ const RELEASE_ENG = { id: 'release-eng', role: 'Release mechanics (version, tag, publish, rollback)', agent_type: 'ijfw-release-eng', since: '1.5.0' };
47
+ const DOC_WRITER = { id: 'doc-writer', role: 'CHANGELOG + README derivation', agent_type: 'ijfw-doc-writer', since: '1.5.0' };
48
+ const ACCESSIBILITY_ENG = { id: 'accessibility-eng', role: 'WCAG AA audit of frontend surfaces', agent_type: 'ijfw-accessibility-eng', since: '1.5.0' };
49
+
50
+ // All 8 v1.5.0 specialists, appended universally per W11-D1 spec.
51
+ const V150_SPECIALISTS = [
52
+ RALPH_LOOP_RUNNER, PLAN_CHECKER, DEP_AUDIT, E2E_RUNNER, LLM_BUDGET_WATCHER,
53
+ RELEASE_ENG, DOC_WRITER, ACCESSIBILITY_ENG,
54
+ ];
55
+
56
+ // v1.5.1 W1.5.D — non-software domain specialists, aligned with T26
57
+ // domain-templates (the canonical agent-id spec per ADR
58
+ // .planning/1.5.1/decisions/W1.5-canonical-source.md). Every `agent_type`
59
+ // here MUST resolve to a real `claude/agents/<id>.md` file on disk; the 5
60
+ // phantom constants that previously lived here (STORY_ARCHITECT,
61
+ // CONTINUITY_EDITOR, PROSE_STYLIST, COPY_EDITOR, DATA_ANALYST) were deleted
62
+ // because no markdown shipped for them.
63
+ const NARRATIVE_CONTINUITY_CHECKER = { id: 'narrative-continuity-checker', role: 'Timeline + voice continuity', agent_type: 'ijfw-narrative-continuity-checker', since: '1.5.0' };
64
+ const LINE_EDITOR = { id: 'line-editor', role: 'Sentence-level voice + pacing', agent_type: 'ijfw-line-editor', since: '1.5.0' };
65
+ const LORE_KEEPER = { id: 'lore-keeper', role: 'World/canon consistency', agent_type: 'ijfw-lore-keeper', since: '1.5.0' };
66
+ const CAMPAIGN_STRATEGIST = { id: 'campaign-strategist', role: 'Audience + funnel strategy', agent_type: 'ijfw-campaign-strategist', since: '1.5.0' };
67
+ const COPY_REVIEWER = { id: 'copy-reviewer', role: 'Channel-aware copy editing', agent_type: 'ijfw-copy-reviewer', since: '1.5.0' };
68
+ const DESIGN_CRITIC = { id: 'design-critic', role: 'Usability + design heuristics', agent_type: 'ijfw-design-critic', since: '1.5.0' };
69
+ const ACCESSIBILITY_REVIEWER = { id: 'accessibility-reviewer', role: 'WCAG + a11y audit', agent_type: 'ijfw-accessibility-reviewer', since: '1.5.0' };
70
+ const RESEARCH_LEAD = { id: 'research-lead', role: 'Methodology + literature review', agent_type: 'ijfw-research-lead', since: '1.5.1' };
71
+ const METHOD_REVIEWER = { id: 'method-reviewer', role: 'Method + bias audit', agent_type: 'ijfw-method-reviewer', since: '1.5.1' };
72
+ const STRATEGY_LEAD = { id: 'strategy-lead', role: 'Strategy + decision quality', agent_type: 'ijfw-strategy-lead', since: '1.5.1' };
73
+ const RISK_REVIEWER = { id: 'risk-reviewer', role: 'Feasibility + downside audit', agent_type: 'ijfw-risk-reviewer', since: '1.5.1' };
74
+
75
+ // Per-archetype bench definitions. Keys here track the project_archetypes
76
+ // vocabulary used by team/generator.js so a brief-detected archetype maps
77
+ // directly to the right bench without an extra translation layer.
78
+ const SOFTWARE_BENCH = [...BASE, TESTS_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
79
+ const TYPED_BENCH = [...BASE, TESTS_SPECIALIST, TYPES_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
80
+ const GO_RUST_BENCH = [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
81
+ const OTHER_BENCH = [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
82
+
83
+ const BOOK_BENCH = [NARRATIVE_CONTINUITY_CHECKER, LINE_EDITOR, LORE_KEEPER, DOC_VERIFIER, NYQUIST_AUDITOR];
84
+ const CONTENT_BENCH = [CAMPAIGN_STRATEGIST, COPY_REVIEWER, DOC_VERIFIER, NYQUIST_AUDITOR];
85
+ const DESIGN_BENCH = [DESIGN_CRITIC, ACCESSIBILITY_REVIEWER, DOC_VERIFIER, NYQUIST_AUDITOR];
86
+ const RESEARCH_BENCH = [RESEARCH_LEAD, METHOD_REVIEWER, DOC_VERIFIER, NYQUIST_AUDITOR];
87
+ const BUSINESS_BENCH = [STRATEGY_LEAD, RISK_REVIEWER, DOC_VERIFIER, NYQUIST_AUDITOR];
88
+ const MIXED_BENCH = [...BASE, DOC_VERIFIER, DESIGN_CRITIC, CAMPAIGN_STRATEGIST, NYQUIST_AUDITOR];
34
89
 
35
90
  export const DEFAULT_SPECIALISTS = {
36
- node: [...BASE, TESTS_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR],
37
- python: [...BASE, TESTS_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR],
38
- typed: [...BASE, TESTS_SPECIALIST, TYPES_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR],
39
- go: [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR],
40
- rust: [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR],
41
- other: [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR],
91
+ // Language-keyed defaults (preserved for back-compat with v1.4.x callers
92
+ // that hand in a detectProjectType() result).
93
+ node: SOFTWARE_BENCH,
94
+ python: SOFTWARE_BENCH,
95
+ typed: TYPED_BENCH,
96
+ go: GO_RUST_BENCH,
97
+ rust: GO_RUST_BENCH,
98
+ other: OTHER_BENCH,
99
+ // Archetype-keyed defaults (new in v1.5.0 audit-MED-teams-#6; bench
100
+ // mis-mappings fixed in v1.5.1 W1.5.D so every agent_type resolves to a
101
+ // real claude/agents/<id>.md file on disk).
102
+ software: SOFTWARE_BENCH,
103
+ book: BOOK_BENCH,
104
+ content: CONTENT_BENCH,
105
+ marketing: CONTENT_BENCH,
106
+ research: RESEARCH_BENCH,
107
+ design: DESIGN_BENCH, // v1.5.1 W1.5.D: was CONTENT_BENCH (mis-mapped)
108
+ business: BUSINESS_BENCH, // v1.5.1 W1.5.D: was SOFTWARE_BENCH (mis-mapped)
109
+ mixed: MIXED_BENCH, // v1.5.1 W1.5.D: was SOFTWARE_BENCH (mis-mapped)
42
110
  };
43
111
 
112
+ // F-FUN-3: helper -- pick the right bench for a (language, archetype) pair.
113
+ // Archetype wins when supplied (a "book" project running from a tmp dir
114
+ // with no package.json must still receive the book bench). Falls back to
115
+ // language and then `other` so older callers keep working.
116
+ export function specialistsFor({ archetype, language } = {}) {
117
+ if (archetype && DEFAULT_SPECIALISTS[archetype]) return DEFAULT_SPECIALISTS[archetype];
118
+ if (language && DEFAULT_SPECIALISTS[language]) return DEFAULT_SPECIALISTS[language];
119
+ return DEFAULT_SPECIALISTS.other;
120
+ }
121
+
44
122
  // Detects project type from filesystem signals in projectDir.
45
123
  // Returns 'node' | 'python' | 'go' | 'rust' | 'typed' | 'other'.
46
124
  export function detectProjectType(projectDir) {
@@ -74,14 +152,21 @@ function applySwarmDefaults(config) {
74
152
  }
75
153
 
76
154
  // Returns a fresh default config object for the given project type.
77
- function buildDefault(projectType) {
78
- const specialists = DEFAULT_SPECIALISTS[projectType] ?? DEFAULT_SPECIALISTS.other;
79
- return applySwarmDefaults({ project_type: projectType, specialists: specialists.map(s => ({ ...s })) });
155
+ // F-FUN-3: supports an optional `archetype` keyed selection so non-software
156
+ // projects (book, content, research, ...) get a domain-tailored bench.
157
+ function buildDefault(projectType, options = {}) {
158
+ const specialists = specialistsFor({ archetype: options.archetype, language: projectType });
159
+ const config = { project_type: projectType, specialists: specialists.map(s => ({ ...s })) };
160
+ if (options.archetype) config.archetype = options.archetype;
161
+ return applySwarmDefaults(config);
80
162
  }
81
163
 
82
164
  // Reads .ijfw/swarm.json if present, otherwise detects type, generates
83
165
  // default config, persists it, and returns it.
84
- export function loadSwarmConfig(projectDir) {
166
+ //
167
+ // F-FUN-3: optional `options.archetype` overrides language-only selection so
168
+ // brief-detected domains (book, content, research, ...) hit a tailored bench.
169
+ export function loadSwarmConfig(projectDir, options = {}) {
85
170
  const swarmPath = join(projectDir, '.ijfw', 'swarm.json');
86
171
 
87
172
  if (existsSync(swarmPath)) {
@@ -91,7 +176,7 @@ export function loadSwarmConfig(projectDir) {
91
176
  }
92
177
 
93
178
  const projectType = detectProjectType(projectDir);
94
- const config = buildDefault(projectType);
179
+ const config = buildDefault(projectType, { archetype: options.archetype });
95
180
 
96
181
  const ijfwDir = join(projectDir, '.ijfw');
97
182
  if (!existsSync(ijfwDir)) mkdirSync(ijfwDir, { recursive: true });
@@ -0,0 +1,51 @@
1
+ {
2
+ "schema_version": "domain-template/v1",
3
+ "domain": "book",
4
+ "display_name": "Book / Long-form Narrative",
5
+ "description": "Novels, memoirs, non-fiction books, anthologies, and other long-form narrative works.",
6
+ "agent_ids": [
7
+ "ijfw-narrative-continuity-checker",
8
+ "ijfw-line-editor",
9
+ "ijfw-lore-keeper"
10
+ ],
11
+ "agent_id_source": "domain-specialist",
12
+ "workflow_phases": ["outline", "draft", "revise", "review"],
13
+ "brief_fields": [
14
+ {
15
+ "key": "premise",
16
+ "type": "string",
17
+ "description": "Core premise or log-line — one to two sentences summarising what the book is about.",
18
+ "required": true
19
+ },
20
+ {
21
+ "key": "genre",
22
+ "type": "string",
23
+ "description": "Genre or sub-genre (e.g. literary fiction, memoir, thriller, cookbook).",
24
+ "required": false
25
+ },
26
+ {
27
+ "key": "characters",
28
+ "type": "array",
29
+ "description": "Named principal characters with a one-sentence description each.",
30
+ "required": false
31
+ },
32
+ {
33
+ "key": "themes",
34
+ "type": "array",
35
+ "description": "Central themes the work explores (e.g. identity, grief, redemption).",
36
+ "required": false
37
+ },
38
+ {
39
+ "key": "target_length",
40
+ "type": "string",
41
+ "description": "Approximate word-count target or chapter count.",
42
+ "required": false
43
+ },
44
+ {
45
+ "key": "pov",
46
+ "type": "string",
47
+ "description": "Narrative point-of-view (first-person, third-person limited, omniscient, etc.).",
48
+ "required": false
49
+ }
50
+ ]
51
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": "domain-template/v1",
3
+ "domain": "business",
4
+ "display_name": "Business / Strategy",
5
+ "description": "Business plans, strategy memos, GTM plans, investor decks, OKRs, and operational roadmaps.",
6
+ "agent_ids": [
7
+ "ijfw-strategy-lead",
8
+ "ijfw-risk-reviewer"
9
+ ],
10
+ "agent_id_source": "domain-specialist",
11
+ "workflow_phases": ["diagnose", "plan", "decide", "review"],
12
+ "brief_fields": [
13
+ {
14
+ "key": "business_objective",
15
+ "type": "string",
16
+ "description": "Primary business objective this work must serve (e.g. enter new market, cut costs, raise Series A).",
17
+ "required": true
18
+ },
19
+ {
20
+ "key": "stakeholders",
21
+ "type": "array",
22
+ "description": "Key stakeholders or decision-makers the output is written for.",
23
+ "required": false
24
+ },
25
+ {
26
+ "key": "time_horizon",
27
+ "type": "string",
28
+ "description": "Planning horizon (e.g. 90-day, annual, 3-year).",
29
+ "required": false
30
+ },
31
+ {
32
+ "key": "constraints",
33
+ "type": "array",
34
+ "description": "Known hard constraints: budget, headcount, regulatory, timeline.",
35
+ "required": false
36
+ },
37
+ {
38
+ "key": "success_metrics",
39
+ "type": "array",
40
+ "description": "Measurable success criteria (e.g. revenue target, churn rate, NPS).",
41
+ "required": false
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "schema_version": "domain-template/v1",
3
+ "domain": "content",
4
+ "display_name": "Content / Campaign",
5
+ "description": "Marketing campaigns, launch copy, blog posts, newsletters, social media, and SEO content.",
6
+ "agent_ids": [
7
+ "ijfw-campaign-strategist",
8
+ "ijfw-copy-reviewer"
9
+ ],
10
+ "agent_id_source": "domain-specialist",
11
+ "workflow_phases": ["plan", "execute", "review", "publish"],
12
+ "brief_fields": [
13
+ {
14
+ "key": "objective",
15
+ "type": "string",
16
+ "description": "Primary campaign objective (e.g. product launch, lead gen, brand awareness).",
17
+ "required": true
18
+ },
19
+ {
20
+ "key": "audience",
21
+ "type": "string",
22
+ "description": "Target audience segment — who the content is written for.",
23
+ "required": true
24
+ },
25
+ {
26
+ "key": "channels",
27
+ "type": "array",
28
+ "description": "Distribution channels in scope (e.g. blog, email, Twitter/X, LinkedIn, press).",
29
+ "required": false
30
+ },
31
+ {
32
+ "key": "tone",
33
+ "type": "string",
34
+ "description": "Brand voice and tone guidelines (e.g. authoritative, conversational, playful).",
35
+ "required": false
36
+ },
37
+ {
38
+ "key": "key_messages",
39
+ "type": "array",
40
+ "description": "Top-line messages that every piece must reinforce.",
41
+ "required": false
42
+ },
43
+ {
44
+ "key": "cta",
45
+ "type": "string",
46
+ "description": "Primary call-to-action the campaign drives toward.",
47
+ "required": false
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": "domain-template/v1",
3
+ "domain": "design",
4
+ "display_name": "Design / UX",
5
+ "description": "UI/UX design, design systems, brand identity, wireframes, and visual prototypes.",
6
+ "agent_ids": [
7
+ "ijfw-design-critic",
8
+ "ijfw-accessibility-reviewer"
9
+ ],
10
+ "agent_id_source": "domain-specialist",
11
+ "workflow_phases": ["discovery", "shape", "execute", "review"],
12
+ "brief_fields": [
13
+ {
14
+ "key": "product",
15
+ "type": "string",
16
+ "description": "The product or surface being designed (e.g. mobile app, dashboard, landing page).",
17
+ "required": true
18
+ },
19
+ {
20
+ "key": "design_goal",
21
+ "type": "string",
22
+ "description": "Primary design goal (e.g. reduce cognitive load, increase conversion, establish brand).",
23
+ "required": false
24
+ },
25
+ {
26
+ "key": "platform",
27
+ "type": "string",
28
+ "description": "Target platform(s): web, iOS, Android, desktop, cross-platform.",
29
+ "required": false
30
+ },
31
+ {
32
+ "key": "design_system",
33
+ "type": "string",
34
+ "description": "Existing design system or style guide in use (e.g. Material, Tailwind, proprietary).",
35
+ "required": false
36
+ },
37
+ {
38
+ "key": "accessibility_target",
39
+ "type": "string",
40
+ "description": "Accessibility conformance target (e.g. WCAG 2.1 AA, Section 508).",
41
+ "required": false
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": "domain-template/v1",
3
+ "domain": "research",
4
+ "display_name": "Research / Analysis",
5
+ "description": "Academic papers, whitepapers, literature reviews, studies, and investigative analysis.",
6
+ "agent_ids": [
7
+ "ijfw-research-lead",
8
+ "ijfw-method-reviewer"
9
+ ],
10
+ "agent_id_source": "domain-specialist",
11
+ "workflow_phases": ["question", "collect", "synthesize", "review"],
12
+ "brief_fields": [
13
+ {
14
+ "key": "research_question",
15
+ "type": "string",
16
+ "description": "Primary research question or hypothesis the work addresses.",
17
+ "required": true
18
+ },
19
+ {
20
+ "key": "methodology",
21
+ "type": "string",
22
+ "description": "Research methodology (e.g. qualitative, quantitative, mixed-methods, literature review).",
23
+ "required": false
24
+ },
25
+ {
26
+ "key": "sources",
27
+ "type": "array",
28
+ "description": "Key source types or corpora to consult (e.g. academic databases, proprietary data, interviews).",
29
+ "required": false
30
+ },
31
+ {
32
+ "key": "output_format",
33
+ "type": "string",
34
+ "description": "Intended output artefact (e.g. journal paper, internal report, executive summary).",
35
+ "required": false
36
+ },
37
+ {
38
+ "key": "scope_constraints",
39
+ "type": "string",
40
+ "description": "Explicit scope limits: time range, geography, population, domain.",
41
+ "required": false
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "schema_version": "domain-template/v1",
3
+ "domain": "software",
4
+ "display_name": "Software / Engineering",
5
+ "description": "Code, APIs, services, libraries, CLIs, mobile and web applications.",
6
+ "agent_ids": [
7
+ "ijfw-doc-verifier",
8
+ "ijfw-integration-checker",
9
+ "ijfw-nyquist-auditor",
10
+ "ijfw-code-fixer"
11
+ ],
12
+ "agent_id_source": "software-core",
13
+ "workflow_phases": ["plan", "execute", "review", "verify"],
14
+ "brief_fields": [
15
+ {
16
+ "key": "stack",
17
+ "type": "string",
18
+ "description": "Primary language / framework stack (e.g. Node.js + Express, Python + FastAPI).",
19
+ "required": false
20
+ },
21
+ {
22
+ "key": "architecture",
23
+ "type": "string",
24
+ "description": "High-level architecture pattern (e.g. monolith, microservices, serverless).",
25
+ "required": false
26
+ },
27
+ {
28
+ "key": "entry_points",
29
+ "type": "array",
30
+ "description": "Key modules or endpoints the team should focus on first.",
31
+ "required": false
32
+ },
33
+ {
34
+ "key": "test_strategy",
35
+ "type": "string",
36
+ "description": "Preferred test approach: unit, integration, e2e, TDD.",
37
+ "required": false
38
+ }
39
+ ]
40
+ }