@ijfw/memory-server 1.4.3 → 1.5.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 (233) hide show
  1. package/fixtures/truncation-corpus/_generate-corpus.js +367 -0
  2. package/fixtures/truncation-corpus/fx-01-clean-exit-01/events.jsonl +2 -0
  3. package/fixtures/truncation-corpus/fx-01-clean-exit-01/intent-journal.jsonl +2 -0
  4. package/fixtures/truncation-corpus/fx-01-clean-exit-01/meta.json +18 -0
  5. package/fixtures/truncation-corpus/fx-01-clean-exit-01/target/.ijfw/state/workflow.json +1 -0
  6. package/fixtures/truncation-corpus/fx-01-clean-exit-02/events.jsonl +2 -0
  7. package/fixtures/truncation-corpus/fx-01-clean-exit-02/intent-journal.jsonl +2 -0
  8. package/fixtures/truncation-corpus/fx-01-clean-exit-02/meta.json +18 -0
  9. package/fixtures/truncation-corpus/fx-01-clean-exit-02/target/.ijfw/state/workflow.json +1 -0
  10. package/fixtures/truncation-corpus/fx-01-clean-exit-03/events.jsonl +2 -0
  11. package/fixtures/truncation-corpus/fx-01-clean-exit-03/intent-journal.jsonl +2 -0
  12. package/fixtures/truncation-corpus/fx-01-clean-exit-03/meta.json +18 -0
  13. package/fixtures/truncation-corpus/fx-01-clean-exit-03/target/.ijfw/state/workflow.json +1 -0
  14. package/fixtures/truncation-corpus/fx-01-clean-exit-04/events.jsonl +2 -0
  15. package/fixtures/truncation-corpus/fx-01-clean-exit-04/intent-journal.jsonl +2 -0
  16. package/fixtures/truncation-corpus/fx-01-clean-exit-04/meta.json +18 -0
  17. package/fixtures/truncation-corpus/fx-01-clean-exit-04/target/.ijfw/state/workflow.json +1 -0
  18. package/fixtures/truncation-corpus/fx-01-clean-exit-05/events.jsonl +2 -0
  19. package/fixtures/truncation-corpus/fx-01-clean-exit-05/intent-journal.jsonl +2 -0
  20. package/fixtures/truncation-corpus/fx-01-clean-exit-05/meta.json +18 -0
  21. package/fixtures/truncation-corpus/fx-01-clean-exit-05/target/.ijfw/state/workflow.json +1 -0
  22. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/events.jsonl +1 -0
  23. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/intent-journal.jsonl +3 -0
  24. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/meta.json +18 -0
  25. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/snapshots/v-midO-1-advance.json +11 -0
  26. package/fixtures/truncation-corpus/fx-02-mid-overwrite-01/target/.ijfw/state/workflow.json +1 -0
  27. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/events.jsonl +1 -0
  28. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/intent-journal.jsonl +3 -0
  29. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/meta.json +18 -0
  30. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/snapshots/v-midO-2-advance.json +11 -0
  31. package/fixtures/truncation-corpus/fx-02-mid-overwrite-02/target/.ijfw/state/workflow.json +1 -0
  32. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/events.jsonl +1 -0
  33. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/intent-journal.jsonl +3 -0
  34. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/meta.json +18 -0
  35. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/snapshots/v-midO-3-advance.json +11 -0
  36. package/fixtures/truncation-corpus/fx-02-mid-overwrite-03/target/.ijfw/state/workflow.json +1 -0
  37. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/events.jsonl +1 -0
  38. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/intent-journal.jsonl +3 -0
  39. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/meta.json +18 -0
  40. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/snapshots/v-midO-4-advance.json +11 -0
  41. package/fixtures/truncation-corpus/fx-02-mid-overwrite-04/target/.ijfw/state/workflow.json +1 -0
  42. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/events.jsonl +1 -0
  43. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/intent-journal.jsonl +3 -0
  44. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/meta.json +18 -0
  45. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/snapshots/v-midO-5-advance.json +11 -0
  46. package/fixtures/truncation-corpus/fx-02-mid-overwrite-05/target/.ijfw/state/workflow.json +1 -0
  47. package/fixtures/truncation-corpus/fx-03-mid-append-01/events.jsonl +1 -0
  48. package/fixtures/truncation-corpus/fx-03-mid-append-01/intent-journal.jsonl +3 -0
  49. package/fixtures/truncation-corpus/fx-03-mid-append-01/meta.json +18 -0
  50. package/fixtures/truncation-corpus/fx-03-mid-append-01/target/.ijfw/blackboard/decisions.jsonl +1 -0
  51. package/fixtures/truncation-corpus/fx-03-mid-append-02/events.jsonl +1 -0
  52. package/fixtures/truncation-corpus/fx-03-mid-append-02/intent-journal.jsonl +3 -0
  53. package/fixtures/truncation-corpus/fx-03-mid-append-02/meta.json +18 -0
  54. package/fixtures/truncation-corpus/fx-03-mid-append-02/target/.ijfw/blackboard/decisions.jsonl +1 -0
  55. package/fixtures/truncation-corpus/fx-03-mid-append-03/events.jsonl +1 -0
  56. package/fixtures/truncation-corpus/fx-03-mid-append-03/intent-journal.jsonl +3 -0
  57. package/fixtures/truncation-corpus/fx-03-mid-append-03/meta.json +18 -0
  58. package/fixtures/truncation-corpus/fx-03-mid-append-03/target/.ijfw/blackboard/decisions.jsonl +1 -0
  59. package/fixtures/truncation-corpus/fx-03-mid-append-04/events.jsonl +1 -0
  60. package/fixtures/truncation-corpus/fx-03-mid-append-04/intent-journal.jsonl +3 -0
  61. package/fixtures/truncation-corpus/fx-03-mid-append-04/meta.json +18 -0
  62. package/fixtures/truncation-corpus/fx-03-mid-append-04/target/.ijfw/blackboard/decisions.jsonl +1 -0
  63. package/fixtures/truncation-corpus/fx-03-mid-append-05/events.jsonl +1 -0
  64. package/fixtures/truncation-corpus/fx-03-mid-append-05/intent-journal.jsonl +3 -0
  65. package/fixtures/truncation-corpus/fx-03-mid-append-05/meta.json +18 -0
  66. package/fixtures/truncation-corpus/fx-03-mid-append-05/target/.ijfw/blackboard/decisions.jsonl +1 -0
  67. package/fixtures/truncation-corpus/fx-04-no-events-01/events.jsonl +0 -0
  68. package/fixtures/truncation-corpus/fx-04-no-events-01/intent-journal.jsonl +1 -0
  69. package/fixtures/truncation-corpus/fx-04-no-events-01/meta.json +18 -0
  70. package/fixtures/truncation-corpus/fx-04-no-events-01/snapshots/v-noEv-1-set-phase.json +11 -0
  71. package/fixtures/truncation-corpus/fx-04-no-events-01/target/.ijfw/state/workflow.json +1 -0
  72. package/fixtures/truncation-corpus/fx-04-no-events-02/events.jsonl +0 -0
  73. package/fixtures/truncation-corpus/fx-04-no-events-02/intent-journal.jsonl +1 -0
  74. package/fixtures/truncation-corpus/fx-04-no-events-02/meta.json +18 -0
  75. package/fixtures/truncation-corpus/fx-04-no-events-02/snapshots/v-noEv-2-set-phase.json +11 -0
  76. package/fixtures/truncation-corpus/fx-04-no-events-02/target/.ijfw/state/workflow.json +1 -0
  77. package/fixtures/truncation-corpus/fx-04-no-events-03/events.jsonl +0 -0
  78. package/fixtures/truncation-corpus/fx-04-no-events-03/intent-journal.jsonl +1 -0
  79. package/fixtures/truncation-corpus/fx-04-no-events-03/meta.json +18 -0
  80. package/fixtures/truncation-corpus/fx-04-no-events-03/snapshots/v-noEv-3-set-phase.json +11 -0
  81. package/fixtures/truncation-corpus/fx-04-no-events-03/target/.ijfw/state/workflow.json +1 -0
  82. package/fixtures/truncation-corpus/fx-04-no-events-04/events.jsonl +0 -0
  83. package/fixtures/truncation-corpus/fx-04-no-events-04/intent-journal.jsonl +1 -0
  84. package/fixtures/truncation-corpus/fx-04-no-events-04/meta.json +18 -0
  85. package/fixtures/truncation-corpus/fx-04-no-events-04/snapshots/v-noEv-4-set-phase.json +11 -0
  86. package/fixtures/truncation-corpus/fx-04-no-events-04/target/.ijfw/state/workflow.json +1 -0
  87. package/fixtures/truncation-corpus/fx-04-no-events-05/events.jsonl +0 -0
  88. package/fixtures/truncation-corpus/fx-04-no-events-05/intent-journal.jsonl +1 -0
  89. package/fixtures/truncation-corpus/fx-04-no-events-05/meta.json +18 -0
  90. package/fixtures/truncation-corpus/fx-04-no-events-05/snapshots/v-noEv-5-set-phase.json +11 -0
  91. package/fixtures/truncation-corpus/fx-04-no-events-05/target/.ijfw/state/workflow.json +1 -0
  92. package/fixtures/truncation-corpus/fx-05-error-terminated-01/events.jsonl +2 -0
  93. package/fixtures/truncation-corpus/fx-05-error-terminated-01/intent-journal.jsonl +3 -0
  94. package/fixtures/truncation-corpus/fx-05-error-terminated-01/meta.json +18 -0
  95. package/fixtures/truncation-corpus/fx-05-error-terminated-01/snapshots/v-errT-1-partial.json +11 -0
  96. package/fixtures/truncation-corpus/fx-05-error-terminated-01/target/.ijfw/state/workflow.json +1 -0
  97. package/fixtures/truncation-corpus/fx-05-error-terminated-02/events.jsonl +2 -0
  98. package/fixtures/truncation-corpus/fx-05-error-terminated-02/intent-journal.jsonl +3 -0
  99. package/fixtures/truncation-corpus/fx-05-error-terminated-02/meta.json +18 -0
  100. package/fixtures/truncation-corpus/fx-05-error-terminated-02/target/.ijfw/blackboard/decisions.jsonl +1 -0
  101. package/fixtures/truncation-corpus/fx-05-error-terminated-03/events.jsonl +2 -0
  102. package/fixtures/truncation-corpus/fx-05-error-terminated-03/intent-journal.jsonl +3 -0
  103. package/fixtures/truncation-corpus/fx-05-error-terminated-03/meta.json +18 -0
  104. package/fixtures/truncation-corpus/fx-05-error-terminated-03/snapshots/v-errT-3-partial.json +11 -0
  105. package/fixtures/truncation-corpus/fx-05-error-terminated-03/target/.ijfw/state/workflow.json +1 -0
  106. package/fixtures/truncation-corpus/fx-05-error-terminated-04/events.jsonl +2 -0
  107. package/fixtures/truncation-corpus/fx-05-error-terminated-04/intent-journal.jsonl +3 -0
  108. package/fixtures/truncation-corpus/fx-05-error-terminated-04/meta.json +18 -0
  109. package/fixtures/truncation-corpus/fx-05-error-terminated-04/target/.ijfw/blackboard/decisions.jsonl +1 -0
  110. package/fixtures/truncation-corpus/fx-05-error-terminated-05/events.jsonl +2 -0
  111. package/fixtures/truncation-corpus/fx-05-error-terminated-05/intent-journal.jsonl +3 -0
  112. package/fixtures/truncation-corpus/fx-05-error-terminated-05/meta.json +18 -0
  113. package/fixtures/truncation-corpus/fx-05-error-terminated-05/snapshots/v-errT-5-partial.json +11 -0
  114. package/fixtures/truncation-corpus/fx-05-error-terminated-05/target/.ijfw/state/workflow.json +1 -0
  115. package/package.json +1 -1
  116. package/src/active-extension-writer.js +144 -64
  117. package/src/api-client.js +43 -5
  118. package/src/audit-roster.js +80 -5
  119. package/src/blackboard.js +298 -6
  120. package/src/cli-run.js +33 -5
  121. package/src/codex-agents.js +96 -5
  122. package/src/cost/aggregator.js +39 -9
  123. package/src/cost/pricing.js +57 -0
  124. package/src/cost/readers/gemini.js +1 -1
  125. package/src/cross-audit-chunker.js +189 -0
  126. package/src/cross-dispatcher.js +124 -21
  127. package/src/cross-orchestrator-cli.js +550 -14
  128. package/src/cross-orchestrator.js +1171 -10
  129. package/src/cross-project-search.js +195 -9
  130. package/src/dashboard-client-planning.html +273 -0
  131. package/src/dashboard-client-waves.html +304 -0
  132. package/src/dashboard-client.html +17 -2
  133. package/src/dashboard-server.js +152 -0
  134. package/src/deploy-alerts.js +150 -0
  135. package/src/design/iframe-bridge.js +242 -0
  136. package/src/design-companion.js +144 -0
  137. package/src/dispatch/checkpoint-cli.js +97 -0
  138. package/src/dispatch/colon-syntax.js +81 -1
  139. package/src/dispatch/extension.js +27 -1
  140. package/src/dispatch/registry-cli.js +4 -1
  141. package/src/dispatch/wave-cli.js +323 -0
  142. package/src/dispatch/worktree-cli.js +40 -0
  143. package/src/dispatch-planner.js +97 -2
  144. package/src/dream/runner.mjs +47 -11
  145. package/src/dream/stage-runner.js +40 -0
  146. package/src/dream/state-file.js +102 -0
  147. package/src/extension-installer.js +70 -24
  148. package/src/extension-quota-tracker.js +4 -2
  149. package/src/extension-registry.js +289 -35
  150. package/src/feedback-detector.js +26 -0
  151. package/src/fs-lock.js +259 -7
  152. package/src/gate-result.js +95 -1
  153. package/src/hero-line.js +86 -5
  154. package/src/intent-router.js +35 -0
  155. package/src/lib/a11y-contract.js +117 -0
  156. package/src/lib/atomic-io.js +29 -8
  157. package/src/lib/cache-keepalive.js +150 -0
  158. package/src/lib/jsonl-rotation.js +104 -0
  159. package/src/lib/lighthouse-pillar.js +121 -0
  160. package/src/lib/llm-call.js +121 -0
  161. package/src/lib/playwright-baseline.js +205 -0
  162. package/src/lib/rekor-bridge.js +221 -0
  163. package/src/lib/repo-map.js +392 -0
  164. package/src/lib/shasum-verify.js +164 -0
  165. package/src/lib/sketches-gc.js +132 -0
  166. package/src/lib/tmp-suffix.js +62 -0
  167. package/src/lib/ui-review-runner.js +554 -0
  168. package/src/lib/uispec-drift.js +301 -0
  169. package/src/lib/uispec-intake.js +381 -0
  170. package/src/lib/worktree-guards.js +118 -0
  171. package/src/lib/worktree-recovery.js +100 -0
  172. package/src/memory/auto-linker.js +152 -0
  173. package/src/memory/benchmark.js +498 -0
  174. package/src/memory/dedup.js +126 -0
  175. package/src/memory/embedding-cache.js +136 -0
  176. package/src/memory/fact-extractor.js +168 -0
  177. package/src/memory/fts5.js +65 -1
  178. package/src/memory/migrations/004-bitemporal.js +91 -0
  179. package/src/memory/migrations/005-vector-cache.js +61 -0
  180. package/src/memory/migrations/006-obsidian-graph.js +46 -0
  181. package/src/memory/migrations/007-skill-telemetry.js +24 -0
  182. package/src/memory/migrations/008-write-provenance.js +41 -0
  183. package/src/memory/obsidian-parser.js +91 -0
  184. package/src/memory/query-dataview.js +86 -0
  185. package/src/memory/search.js +10 -0
  186. package/src/memory/temporal.js +529 -0
  187. package/src/memory/tokenize.js +10 -0
  188. package/src/memory-facts-handler.js +37 -0
  189. package/src/memory-feedback.js +260 -2
  190. package/src/model-refresh.js +292 -0
  191. package/src/observability/cost-anomaly.js +166 -0
  192. package/src/observability/evaluator-checkpoint-contract.js +117 -0
  193. package/src/observability/trace-id.js +163 -0
  194. package/src/orchestrator/agents-md-blackboard.js +152 -0
  195. package/src/orchestrator/checkpoint-contract.md +140 -0
  196. package/src/orchestrator/debug-trident.js +570 -0
  197. package/src/orchestrator/merge-block-aware.js +350 -0
  198. package/src/orchestrator/plan-checker.js +475 -0
  199. package/src/orchestrator/post-done-runner.js +249 -0
  200. package/src/orchestrator/review.js +136 -0
  201. package/src/orchestrator/runtime-loop.js +430 -0
  202. package/src/orchestrator/skill-telemetry-sink.js +29 -0
  203. package/src/orchestrator/skill-telemetry.js +37 -0
  204. package/src/orchestrator/state-events.js +459 -0
  205. package/src/orchestrator/state-sdk.js +1764 -0
  206. package/src/orchestrator/status-protocol.js +235 -0
  207. package/src/orchestrator/subagent-telemetry.js +452 -0
  208. package/src/orchestrator/termination.js +160 -0
  209. package/src/orchestrator/verification-gate.js +281 -0
  210. package/src/orchestrator/wave-state.js +564 -0
  211. package/src/orchestrator/worktree-provision.js +77 -0
  212. package/src/override-use-registry.js +111 -5
  213. package/src/receipts.js +36 -4
  214. package/src/recovery/checkpoint.js +56 -3
  215. package/src/recovery/code-fixer.js +656 -0
  216. package/src/recovery/truncation.js +317 -0
  217. package/src/redactor.js +75 -6
  218. package/src/runtime-mediator.js +15 -0
  219. package/src/sanitizer.js +10 -0
  220. package/src/search-hybrid.js +139 -0
  221. package/src/server.js +603 -59
  222. package/src/swarm/worktree.js +27 -4
  223. package/src/swarm-config.js +113 -12
  224. package/src/team/domain-templates/book.json +51 -0
  225. package/src/team/domain-templates/business.json +41 -0
  226. package/src/team/domain-templates/content.json +50 -0
  227. package/src/team/domain-templates/design.json +44 -0
  228. package/src/team/domain-templates/research.json +41 -0
  229. package/src/team/domain-templates/software.json +40 -0
  230. package/src/team/generator.js +278 -3
  231. package/src/team/modify.js +203 -0
  232. package/src/team/schemas.js +48 -0
  233. package/src/update-apply.js +19 -3
@@ -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 },
@@ -12,6 +12,9 @@ import { join } from 'node:path';
12
12
  export const SCHEMA = {
13
13
  project_type: 'string',
14
14
  specialists: [{ id: 'string', role: 'string', agent_type: 'string' }],
15
+ // v1.4.4 N10: auditor roster for phase-e-auto
16
+ auditors: ['string'], // roster IDs to use for Cross-Audit Phase; default ['codex','gemini','claude']
17
+ auditor_count: 'number', // number of lenses; default 3
15
18
  };
16
19
 
17
20
  const BASE = [
@@ -22,15 +25,92 @@ const BASE = [
22
25
  const TESTS_SPECIALIST = { id: 'tests', role: 'Test coverage', agent_type: 'pr-test-analyzer' };
23
26
  const TYPES_SPECIALIST = { id: 'types', role: 'Type invariants', agent_type: 'type-design-analyzer' };
24
27
 
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
+ // F-FUN-3 (audit-MED-teams-#6): non-software domain specialists. Mirrors
57
+ // the fixture role definitions so we don't duplicate prompts; the IDs here
58
+ // are the *bench* names the swarm config tracks. Selecting a non-software
59
+ // archetype yields a bench tailored to the domain (book gets story-architect,
60
+ // not accessibility-eng). Software remains the default to preserve back-compat.
61
+ const STORY_ARCHITECT = { id: 'story-architect', role: 'Plot + structure architecture', agent_type: 'ijfw-story-architect', since: '1.5.0' };
62
+ const CONTINUITY_EDITOR = { id: 'continuity-editor', role: 'Timeline + voice continuity', agent_type: 'ijfw-continuity-editor', since: '1.5.0' };
63
+ const PROSE_STYLIST = { id: 'prose-stylist', role: 'Sentence-level voice + pacing', agent_type: 'ijfw-prose-stylist', since: '1.5.0' };
64
+
65
+ const CAMPAIGN_STRATEGIST = { id: 'campaign-strategist', role: 'Audience + funnel strategy', agent_type: 'ijfw-campaign-strategist', since: '1.5.0' };
66
+ const COPY_EDITOR = { id: 'copy-editor', role: 'Channel-aware copy editing', agent_type: 'ijfw-copy-editor', since: '1.5.0' };
67
+
68
+ const RESEARCH_LEAD = { id: 'research-lead', role: 'Methodology + literature review', agent_type: 'ijfw-research-lead', since: '1.5.0' };
69
+ const DATA_ANALYST = { id: 'data-analyst', role: 'Quantitative analysis', agent_type: 'ijfw-data-analyst', since: '1.5.0' };
70
+
71
+ // Per-archetype bench definitions. Keys here track the project_archetypes
72
+ // vocabulary used by team/generator.js so a brief-detected archetype maps
73
+ // directly to the right bench without an extra translation layer.
74
+ const SOFTWARE_BENCH = [...BASE, TESTS_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
75
+ const TYPED_BENCH = [...BASE, TESTS_SPECIALIST, TYPES_SPECIALIST, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
76
+ const GO_RUST_BENCH = [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
77
+ const OTHER_BENCH = [...BASE, DOC_VERIFIER, PATTERN_MAPPER, SECURITY_AUDITOR, INTEGRATION_CHECKER, NYQUIST_AUDITOR, ...V150_SPECIALISTS];
78
+
79
+ const BOOK_BENCH = [STORY_ARCHITECT, CONTINUITY_EDITOR, PROSE_STYLIST, DOC_VERIFIER, NYQUIST_AUDITOR];
80
+ const CONTENT_BENCH = [CAMPAIGN_STRATEGIST, COPY_EDITOR, DOC_VERIFIER, NYQUIST_AUDITOR];
81
+ const RESEARCH_BENCH = [RESEARCH_LEAD, DATA_ANALYST, DOC_VERIFIER, NYQUIST_AUDITOR];
82
+
25
83
  export const DEFAULT_SPECIALISTS = {
26
- node: [...BASE, TESTS_SPECIALIST],
27
- python: [...BASE, TESTS_SPECIALIST],
28
- typed: [...BASE, TESTS_SPECIALIST, TYPES_SPECIALIST],
29
- go: [...BASE],
30
- rust: [...BASE],
31
- other: [...BASE],
84
+ // Language-keyed defaults (preserved for back-compat with v1.4.x callers
85
+ // that hand in a detectProjectType() result).
86
+ node: SOFTWARE_BENCH,
87
+ python: SOFTWARE_BENCH,
88
+ typed: TYPED_BENCH,
89
+ go: GO_RUST_BENCH,
90
+ rust: GO_RUST_BENCH,
91
+ other: OTHER_BENCH,
92
+ // Archetype-keyed defaults (new in v1.5.0 audit-MED-teams-#6) -- selected
93
+ // when the caller hands in a project archetype from the team detector.
94
+ software: SOFTWARE_BENCH,
95
+ book: BOOK_BENCH,
96
+ content: CONTENT_BENCH,
97
+ marketing: CONTENT_BENCH,
98
+ research: RESEARCH_BENCH,
99
+ design: CONTENT_BENCH,
100
+ business: SOFTWARE_BENCH,
101
+ mixed: SOFTWARE_BENCH,
32
102
  };
33
103
 
104
+ // F-FUN-3: helper -- pick the right bench for a (language, archetype) pair.
105
+ // Archetype wins when supplied (a "book" project running from a tmp dir
106
+ // with no package.json must still receive the book bench). Falls back to
107
+ // language and then `other` so older callers keep working.
108
+ export function specialistsFor({ archetype, language } = {}) {
109
+ if (archetype && DEFAULT_SPECIALISTS[archetype]) return DEFAULT_SPECIALISTS[archetype];
110
+ if (language && DEFAULT_SPECIALISTS[language]) return DEFAULT_SPECIALISTS[language];
111
+ return DEFAULT_SPECIALISTS.other;
112
+ }
113
+
34
114
  // Detects project type from filesystem signals in projectDir.
35
115
  // Returns 'node' | 'python' | 'go' | 'rust' | 'typed' | 'other'.
36
116
  export function detectProjectType(projectDir) {
@@ -51,23 +131,44 @@ export function detectProjectType(projectDir) {
51
131
  return 'other';
52
132
  }
53
133
 
134
+ // Default auditor IDs for Cross-Audit Phase (N10).
135
+ export const DEFAULT_AUDITORS = ['codex', 'gemini', 'claude'];
136
+ export const DEFAULT_AUDITOR_COUNT = 3;
137
+
138
+ // Merge v1.4.4 N10 defaults into a raw config object (non-destructive).
139
+ function applySwarmDefaults(config) {
140
+ const out = { ...config };
141
+ if (!Array.isArray(out.auditors)) out.auditors = [...DEFAULT_AUDITORS];
142
+ if (typeof out.auditor_count !== 'number' || out.auditor_count < 1) out.auditor_count = DEFAULT_AUDITOR_COUNT;
143
+ return out;
144
+ }
145
+
54
146
  // Returns a fresh default config object for the given project type.
55
- function buildDefault(projectType) {
56
- const specialists = DEFAULT_SPECIALISTS[projectType] ?? DEFAULT_SPECIALISTS.other;
57
- return { project_type: projectType, specialists: specialists.map(s => ({ ...s })) };
147
+ // F-FUN-3: supports an optional `archetype` keyed selection so non-software
148
+ // projects (book, content, research, ...) get a domain-tailored bench.
149
+ function buildDefault(projectType, options = {}) {
150
+ const specialists = specialistsFor({ archetype: options.archetype, language: projectType });
151
+ const config = { project_type: projectType, specialists: specialists.map(s => ({ ...s })) };
152
+ if (options.archetype) config.archetype = options.archetype;
153
+ return applySwarmDefaults(config);
58
154
  }
59
155
 
60
156
  // Reads .ijfw/swarm.json if present, otherwise detects type, generates
61
157
  // default config, persists it, and returns it.
62
- export function loadSwarmConfig(projectDir) {
158
+ //
159
+ // F-FUN-3: optional `options.archetype` overrides language-only selection so
160
+ // brief-detected domains (book, content, research, ...) hit a tailored bench.
161
+ export function loadSwarmConfig(projectDir, options = {}) {
63
162
  const swarmPath = join(projectDir, '.ijfw', 'swarm.json');
64
163
 
65
164
  if (existsSync(swarmPath)) {
66
- return JSON.parse(readFileSync(swarmPath, 'utf8'));
165
+ const raw = JSON.parse(readFileSync(swarmPath, 'utf8'));
166
+ // Merge defaults for v1.4.4 N10 fields so older swarm.json files work.
167
+ return applySwarmDefaults(raw);
67
168
  }
68
169
 
69
170
  const projectType = detectProjectType(projectDir);
70
- const config = buildDefault(projectType);
171
+ const config = buildDefault(projectType, { archetype: options.archetype });
71
172
 
72
173
  const ijfwDir = join(projectDir, '.ijfw');
73
174
  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,41 @@
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
+ "agent_id_source": "domain-specialist",
8
+ "workflow_phases": ["diagnose", "plan", "decide", "review"],
9
+ "brief_fields": [
10
+ {
11
+ "key": "business_objective",
12
+ "type": "string",
13
+ "description": "Primary business objective this work must serve (e.g. enter new market, cut costs, raise Series A).",
14
+ "required": true
15
+ },
16
+ {
17
+ "key": "stakeholders",
18
+ "type": "array",
19
+ "description": "Key stakeholders or decision-makers the output is written for.",
20
+ "required": false
21
+ },
22
+ {
23
+ "key": "time_horizon",
24
+ "type": "string",
25
+ "description": "Planning horizon (e.g. 90-day, annual, 3-year).",
26
+ "required": false
27
+ },
28
+ {
29
+ "key": "constraints",
30
+ "type": "array",
31
+ "description": "Known hard constraints: budget, headcount, regulatory, timeline.",
32
+ "required": false
33
+ },
34
+ {
35
+ "key": "success_metrics",
36
+ "type": "array",
37
+ "description": "Measurable success criteria (e.g. revenue target, churn rate, NPS).",
38
+ "required": false
39
+ }
40
+ ]
41
+ }
@@ -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,41 @@
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
+ "agent_id_source": "domain-specialist",
8
+ "workflow_phases": ["question", "collect", "synthesize", "review"],
9
+ "brief_fields": [
10
+ {
11
+ "key": "research_question",
12
+ "type": "string",
13
+ "description": "Primary research question or hypothesis the work addresses.",
14
+ "required": true
15
+ },
16
+ {
17
+ "key": "methodology",
18
+ "type": "string",
19
+ "description": "Research methodology (e.g. qualitative, quantitative, mixed-methods, literature review).",
20
+ "required": false
21
+ },
22
+ {
23
+ "key": "sources",
24
+ "type": "array",
25
+ "description": "Key source types or corpora to consult (e.g. academic databases, proprietary data, interviews).",
26
+ "required": false
27
+ },
28
+ {
29
+ "key": "output_format",
30
+ "type": "string",
31
+ "description": "Intended output artefact (e.g. journal paper, internal report, executive summary).",
32
+ "required": false
33
+ },
34
+ {
35
+ "key": "scope_constraints",
36
+ "type": "string",
37
+ "description": "Explicit scope limits: time range, geography, population, domain.",
38
+ "required": false
39
+ }
40
+ ]
41
+ }
@@ -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
+ }