mindforge-cc 11.2.0 → 11.3.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 (213) hide show
  1. package/.mindforge/config.json +3 -2
  2. package/.mindforge/imported-agents.jsonl +154 -0
  3. package/CHANGELOG.md +80 -1
  4. package/MINDFORGE.md +5 -5
  5. package/README.md +1 -1
  6. package/bin/autonomous/mesh-self-healer.js +101 -28
  7. package/bin/browser/regression-writer.js +45 -3
  8. package/bin/browser/session-manager.js +21 -17
  9. package/bin/engine/logic-drift-detector.js +14 -6
  10. package/bin/engine/logic-validator.js +155 -25
  11. package/bin/engine/orbital-guardian.js +56 -10
  12. package/bin/engine/reason-source-aligner.js +19 -6
  13. package/bin/engine/remediation-engine.js +1 -1
  14. package/bin/engine/self-corrective-synthesizer.js +1 -1
  15. package/bin/engine/sre-manager.js +33 -6
  16. package/bin/governance/policy-engine.js +17 -4
  17. package/bin/governance/ztai-archiver.js +74 -9
  18. package/bin/governance/ztai-manager.js +3 -3
  19. package/bin/installer-core.js +126 -3
  20. package/bin/memory/eis-client.js +45 -4
  21. package/bin/memory/vector-hub.js +32 -0
  22. package/bin/review/finding-synthesizer.js +35 -6
  23. package/bin/security/trust-boundaries.js +96 -4
  24. package/bin/security/trust-gate-hook.js +13 -3
  25. package/bin/skill-registry.js +31 -20
  26. package/bin/spawn-agent.js +80 -1
  27. package/bin/sre/shadow-mirror.js +90 -40
  28. package/bin/utils/append-queue.js +12 -0
  29. package/bin/utils/file-io.js +4 -45
  30. package/bin/utils/version-check.js +21 -5
  31. package/bin/wizard/theme.js +4 -3
  32. package/package.json +3 -1
  33. package/subagents/.claude-plugin/marketplace.json +93 -0
  34. package/subagents/categories/01-core-development/.claude-plugin/plugin.json +24 -0
  35. package/subagents/categories/01-core-development/README.md +146 -0
  36. package/subagents/categories/01-core-development/api-designer-cc.md +237 -0
  37. package/subagents/categories/01-core-development/backend-developer.md +222 -0
  38. package/subagents/categories/01-core-development/design-bridge.md +129 -0
  39. package/subagents/categories/01-core-development/electron-pro.md +240 -0
  40. package/subagents/categories/01-core-development/frontend-developer.md +133 -0
  41. package/subagents/categories/01-core-development/fullstack-developer.md +235 -0
  42. package/subagents/categories/01-core-development/graphql-architect.md +238 -0
  43. package/subagents/categories/01-core-development/microservices-architect.md +239 -0
  44. package/subagents/categories/01-core-development/mobile-developer.md +283 -0
  45. package/subagents/categories/01-core-development/ui-designer.md +174 -0
  46. package/subagents/categories/01-core-development/websocket-engineer.md +150 -0
  47. package/subagents/categories/02-language-specialists/.claude-plugin/plugin.json +43 -0
  48. package/subagents/categories/02-language-specialists/README.md +245 -0
  49. package/subagents/categories/02-language-specialists/angular-architect.md +287 -0
  50. package/subagents/categories/02-language-specialists/cpp-pro.md +277 -0
  51. package/subagents/categories/02-language-specialists/csharp-developer.md +287 -0
  52. package/subagents/categories/02-language-specialists/django-developer.md +287 -0
  53. package/subagents/categories/02-language-specialists/dotnet-core-expert.md +287 -0
  54. package/subagents/categories/02-language-specialists/dotnet-framework-48-expert.md +306 -0
  55. package/subagents/categories/02-language-specialists/elixir-expert.md +311 -0
  56. package/subagents/categories/02-language-specialists/expo-react-native-expert.md +268 -0
  57. package/subagents/categories/02-language-specialists/fastapi-developer.md +287 -0
  58. package/subagents/categories/02-language-specialists/flutter-expert.md +287 -0
  59. package/subagents/categories/02-language-specialists/golang-pro.md +277 -0
  60. package/subagents/categories/02-language-specialists/java-architect.md +287 -0
  61. package/subagents/categories/02-language-specialists/javascript-pro.md +277 -0
  62. package/subagents/categories/02-language-specialists/kotlin-specialist.md +287 -0
  63. package/subagents/categories/02-language-specialists/laravel-specialist.md +287 -0
  64. package/subagents/categories/02-language-specialists/nextjs-developer.md +287 -0
  65. package/subagents/categories/02-language-specialists/node-specialist.md +124 -0
  66. package/subagents/categories/02-language-specialists/php-pro.md +287 -0
  67. package/subagents/categories/02-language-specialists/powershell-51-expert.md +59 -0
  68. package/subagents/categories/02-language-specialists/powershell-7-expert.md +57 -0
  69. package/subagents/categories/02-language-specialists/python-pro.md +277 -0
  70. package/subagents/categories/02-language-specialists/rails-expert.md +358 -0
  71. package/subagents/categories/02-language-specialists/react-specialist-cc.md +287 -0
  72. package/subagents/categories/02-language-specialists/rust-engineer.md +287 -0
  73. package/subagents/categories/02-language-specialists/spring-boot-engineer.md +287 -0
  74. package/subagents/categories/02-language-specialists/sql-pro.md +287 -0
  75. package/subagents/categories/02-language-specialists/swift-expert.md +287 -0
  76. package/subagents/categories/02-language-specialists/symfony-specialist.md +354 -0
  77. package/subagents/categories/02-language-specialists/typescript-pro.md +277 -0
  78. package/subagents/categories/02-language-specialists/vue-expert.md +287 -0
  79. package/subagents/categories/03-infrastructure/.claude-plugin/plugin.json +29 -0
  80. package/subagents/categories/03-infrastructure/README.md +170 -0
  81. package/subagents/categories/03-infrastructure/azure-infra-engineer.md +53 -0
  82. package/subagents/categories/03-infrastructure/cloud-architect-cc.md +277 -0
  83. package/subagents/categories/03-infrastructure/database-administrator.md +287 -0
  84. package/subagents/categories/03-infrastructure/deployment-engineer.md +287 -0
  85. package/subagents/categories/03-infrastructure/devops-engineer-cc.md +287 -0
  86. package/subagents/categories/03-infrastructure/devops-incident-responder.md +287 -0
  87. package/subagents/categories/03-infrastructure/docker-expert.md +278 -0
  88. package/subagents/categories/03-infrastructure/incident-responder.md +287 -0
  89. package/subagents/categories/03-infrastructure/kubernetes-specialist.md +287 -0
  90. package/subagents/categories/03-infrastructure/network-engineer.md +287 -0
  91. package/subagents/categories/03-infrastructure/platform-engineer-cc.md +287 -0
  92. package/subagents/categories/03-infrastructure/security-engineer.md +277 -0
  93. package/subagents/categories/03-infrastructure/sre-engineer.md +287 -0
  94. package/subagents/categories/03-infrastructure/terraform-engineer.md +287 -0
  95. package/subagents/categories/03-infrastructure/terragrunt-expert.md +307 -0
  96. package/subagents/categories/03-infrastructure/windows-infra-admin.md +52 -0
  97. package/subagents/categories/04-quality-security/.claude-plugin/plugin.json +30 -0
  98. package/subagents/categories/04-quality-security/README.md +175 -0
  99. package/subagents/categories/04-quality-security/accessibility-tester-cc.md +277 -0
  100. package/subagents/categories/04-quality-security/ad-security-reviewer.md +56 -0
  101. package/subagents/categories/04-quality-security/ai-writing-auditor.md +77 -0
  102. package/subagents/categories/04-quality-security/architect-reviewer.md +287 -0
  103. package/subagents/categories/04-quality-security/chaos-engineer-cc.md +277 -0
  104. package/subagents/categories/04-quality-security/code-reviewer.md +287 -0
  105. package/subagents/categories/04-quality-security/compliance-auditor-cc.md +277 -0
  106. package/subagents/categories/04-quality-security/debugger-cc.md +287 -0
  107. package/subagents/categories/04-quality-security/error-detective.md +287 -0
  108. package/subagents/categories/04-quality-security/gdpr-ccpa-compliance.md +98 -0
  109. package/subagents/categories/04-quality-security/penetration-tester.md +287 -0
  110. package/subagents/categories/04-quality-security/performance-engineer.md +287 -0
  111. package/subagents/categories/04-quality-security/powershell-security-hardening.md +54 -0
  112. package/subagents/categories/04-quality-security/qa-expert.md +287 -0
  113. package/subagents/categories/04-quality-security/security-auditor.md +287 -0
  114. package/subagents/categories/04-quality-security/test-automator.md +287 -0
  115. package/subagents/categories/04-quality-security/ui-ux-tester.md +234 -0
  116. package/subagents/categories/05-data-ai/.claude-plugin/plugin.json +26 -0
  117. package/subagents/categories/05-data-ai/README.md +153 -0
  118. package/subagents/categories/05-data-ai/ai-engineer.md +287 -0
  119. package/subagents/categories/05-data-ai/data-analyst.md +277 -0
  120. package/subagents/categories/05-data-ai/data-engineer-cc.md +287 -0
  121. package/subagents/categories/05-data-ai/data-scientist.md +287 -0
  122. package/subagents/categories/05-data-ai/database-optimizer.md +287 -0
  123. package/subagents/categories/05-data-ai/llm-architect.md +287 -0
  124. package/subagents/categories/05-data-ai/machine-learning-engineer.md +277 -0
  125. package/subagents/categories/05-data-ai/ml-engineer-cc.md +287 -0
  126. package/subagents/categories/05-data-ai/mlops-engineer.md +287 -0
  127. package/subagents/categories/05-data-ai/nlp-engineer.md +287 -0
  128. package/subagents/categories/05-data-ai/postgres-pro.md +287 -0
  129. package/subagents/categories/05-data-ai/prompt-engineer-cc.md +287 -0
  130. package/subagents/categories/05-data-ai/reinforcement-learning-engineer.md +277 -0
  131. package/subagents/categories/06-developer-experience/.claude-plugin/plugin.json +28 -0
  132. package/subagents/categories/06-developer-experience/README.md +157 -0
  133. package/subagents/categories/06-developer-experience/build-engineer-cc.md +286 -0
  134. package/subagents/categories/06-developer-experience/cli-developer.md +286 -0
  135. package/subagents/categories/06-developer-experience/dependency-manager.md +286 -0
  136. package/subagents/categories/06-developer-experience/documentation-engineer.md +276 -0
  137. package/subagents/categories/06-developer-experience/dx-optimizer.md +286 -0
  138. package/subagents/categories/06-developer-experience/git-workflow-manager.md +286 -0
  139. package/subagents/categories/06-developer-experience/legacy-modernizer.md +286 -0
  140. package/subagents/categories/06-developer-experience/mcp-developer.md +275 -0
  141. package/subagents/categories/06-developer-experience/powershell-module-architect.md +58 -0
  142. package/subagents/categories/06-developer-experience/powershell-ui-architect.md +135 -0
  143. package/subagents/categories/06-developer-experience/readme-generator.md +238 -0
  144. package/subagents/categories/06-developer-experience/refactoring-specialist.md +286 -0
  145. package/subagents/categories/06-developer-experience/slack-expert.md +232 -0
  146. package/subagents/categories/06-developer-experience/tooling-engineer.md +286 -0
  147. package/subagents/categories/06-developer-experience/visual-asset-generator.md +34 -0
  148. package/subagents/categories/07-specialized-domains/.claude-plugin/plugin.json +27 -0
  149. package/subagents/categories/07-specialized-domains/README.md +161 -0
  150. package/subagents/categories/07-specialized-domains/api-documenter.md +277 -0
  151. package/subagents/categories/07-specialized-domains/blockchain-developer.md +287 -0
  152. package/subagents/categories/07-specialized-domains/embedded-systems.md +287 -0
  153. package/subagents/categories/07-specialized-domains/fintech-engineer.md +287 -0
  154. package/subagents/categories/07-specialized-domains/game-developer.md +287 -0
  155. package/subagents/categories/07-specialized-domains/healthcare-admin.md +199 -0
  156. package/subagents/categories/07-specialized-domains/hipaa-compliance.md +112 -0
  157. package/subagents/categories/07-specialized-domains/iot-engineer.md +287 -0
  158. package/subagents/categories/07-specialized-domains/m365-admin.md +48 -0
  159. package/subagents/categories/07-specialized-domains/mobile-app-developer.md +287 -0
  160. package/subagents/categories/07-specialized-domains/payment-integration.md +287 -0
  161. package/subagents/categories/07-specialized-domains/quant-analyst.md +287 -0
  162. package/subagents/categories/07-specialized-domains/risk-manager.md +287 -0
  163. package/subagents/categories/07-specialized-domains/seo-specialist-cc.md +184 -0
  164. package/subagents/categories/08-business-product/.claude-plugin/plugin.json +29 -0
  165. package/subagents/categories/08-business-product/README.md +160 -0
  166. package/subagents/categories/08-business-product/assumption-mapping.md +77 -0
  167. package/subagents/categories/08-business-product/backlog-grooming.md +88 -0
  168. package/subagents/categories/08-business-product/business-analyst-cc.md +287 -0
  169. package/subagents/categories/08-business-product/content-marketer.md +287 -0
  170. package/subagents/categories/08-business-product/content-quality-editor.md +55 -0
  171. package/subagents/categories/08-business-product/customer-success-manager.md +287 -0
  172. package/subagents/categories/08-business-product/growth-loops.md +91 -0
  173. package/subagents/categories/08-business-product/legal-advisor.md +287 -0
  174. package/subagents/categories/08-business-product/license-engineer.md +295 -0
  175. package/subagents/categories/08-business-product/product-manager-cc.md +287 -0
  176. package/subagents/categories/08-business-product/project-manager.md +287 -0
  177. package/subagents/categories/08-business-product/sales-engineer.md +287 -0
  178. package/subagents/categories/08-business-product/scrum-master.md +287 -0
  179. package/subagents/categories/08-business-product/technical-writer.md +287 -0
  180. package/subagents/categories/08-business-product/ux-researcher.md +287 -0
  181. package/subagents/categories/08-business-product/wordpress-master.md +316 -0
  182. package/subagents/categories/09-meta-orchestration/.claude-plugin/plugin.json +24 -0
  183. package/subagents/categories/09-meta-orchestration/README.md +140 -0
  184. package/subagents/categories/09-meta-orchestration/agent-installer.md +97 -0
  185. package/subagents/categories/09-meta-orchestration/agent-organizer.md +287 -0
  186. package/subagents/categories/09-meta-orchestration/codebase-orchestrator.md +249 -0
  187. package/subagents/categories/09-meta-orchestration/context-manager.md +287 -0
  188. package/subagents/categories/09-meta-orchestration/error-coordinator.md +287 -0
  189. package/subagents/categories/09-meta-orchestration/it-ops-orchestrator.md +60 -0
  190. package/subagents/categories/09-meta-orchestration/knowledge-synthesizer.md +287 -0
  191. package/subagents/categories/09-meta-orchestration/multi-agent-coordinator.md +287 -0
  192. package/subagents/categories/09-meta-orchestration/performance-monitor.md +287 -0
  193. package/subagents/categories/09-meta-orchestration/task-distributor.md +287 -0
  194. package/subagents/categories/09-meta-orchestration/workflow-orchestrator.md +287 -0
  195. package/subagents/categories/10-research-analysis/.claude-plugin/plugin.json +24 -0
  196. package/subagents/categories/10-research-analysis/README.md +141 -0
  197. package/subagents/categories/10-research-analysis/ab-test-analysis.md +101 -0
  198. package/subagents/categories/10-research-analysis/cohort-analysis.md +100 -0
  199. package/subagents/categories/10-research-analysis/competitive-analyst.md +287 -0
  200. package/subagents/categories/10-research-analysis/data-researcher.md +287 -0
  201. package/subagents/categories/10-research-analysis/first-principles-thinking.md +100 -0
  202. package/subagents/categories/10-research-analysis/market-researcher.md +287 -0
  203. package/subagents/categories/10-research-analysis/project-idea-validator.md +269 -0
  204. package/subagents/categories/10-research-analysis/research-analyst.md +287 -0
  205. package/subagents/categories/10-research-analysis/scientific-literature-researcher.md +151 -0
  206. package/subagents/categories/10-research-analysis/search-specialist.md +287 -0
  207. package/subagents/categories/10-research-analysis/trend-analyst.md +287 -0
  208. package/subagents/tools/subagent-catalog/README.md +58 -0
  209. package/subagents/tools/subagent-catalog/config.sh +94 -0
  210. package/subagents/tools/subagent-catalog/fetch.md +82 -0
  211. package/subagents/tools/subagent-catalog/invalidate.md +47 -0
  212. package/subagents/tools/subagent-catalog/list.md +54 -0
  213. package/subagents/tools/subagent-catalog/search.md +58 -0
@@ -16,13 +16,23 @@ process.stdin.on('end', () => {
16
16
  }
17
17
 
18
18
  const fullCommand = event.tool_input?.command || '';
19
- const command = fullCommand.split('\n')[0];
20
19
 
21
- if (isHighImpact(command)) {
20
+ // Check the whole command AND every individual line, blocking if ANY
21
+ // segment is high-impact. Per-line scanning means a benign first line
22
+ // cannot cloak a destructive command on a later line; the whole-string
23
+ // check catches patterns a line split might fragment. This is a security
24
+ // gate, so it errs toward blocking: a destructive keyword in (e.g.) a
25
+ // commit message will prompt for approval rather than risk a cloaked
26
+ // command slipping through. Approval friction is preferable to a bypass.
27
+ const lines = fullCommand.split('\n');
28
+ const offending = [fullCommand, ...lines].find((segment) => isHighImpact(segment));
29
+
30
+ if (offending) {
31
+ const display = offending.length > 80 ? offending.slice(0, 80) + '...' : offending;
22
32
  // Output a block reason (Claude Code shows this to the user)
23
33
  process.stdout.write(JSON.stringify({
24
34
  decision: 'block',
25
- reason: `[TrustGate] High-impact command detected: "${command.substring(0, 80)}..." — requires explicit user approval`
35
+ reason: `[TrustGate] High-impact command detected: "${display}" — requires explicit user approval`
26
36
  }));
27
37
  process.exit(2); // block
28
38
  }
@@ -124,31 +124,42 @@ function handleInstall() {
124
124
  if (tier === '1') targetBase = '.mindforge/skills';
125
125
  if (tier === '3') targetBase = '.mindforge/project-skills';
126
126
 
127
+ // Resolve a real local source for the skill. There is no remote registry
128
+ // backend, so the ONLY honest sources are an examples/ entry or a SKILL.md in
129
+ // the current working directory (the agentic authoring flow).
130
+ const exampleSrc = path.join(process.cwd(), 'examples', 'skills', `${skillName}.md`);
131
+ const localSrc = path.join(process.cwd(), 'SKILL.md');
132
+
133
+ let source = null;
134
+ if (fs.existsSync(exampleSrc)) {
135
+ source = exampleSrc;
136
+ } else if (fs.existsSync(localSrc)) {
137
+ source = localSrc;
138
+ }
139
+
140
+ if (!source) {
141
+ // HONEST REFUSAL (UC-22): no local source and no remote registry is
142
+ // configured. Do NOT write a placeholder file that masquerades as an
143
+ // installed skill — that would falsely report success. Refuse clearly and
144
+ // exit non-zero so callers can detect the failure.
145
+ console.error(
146
+ `❌ Skill '${skillName}' not found locally and no remote registry is configured — nothing installed.`
147
+ );
148
+ console.error(
149
+ ' Provide a source first: place a SKILL.md in the current directory ' +
150
+ `or add examples/skills/${skillName}.md, then re-run.`
151
+ );
152
+ process.exit(1);
153
+ }
154
+
155
+ // Real source found → perform the actual install.
127
156
  const targetDir = path.join(process.cwd(), targetBase, skillName);
128
157
  if (!fs.existsSync(targetDir)) {
129
158
  fs.mkdirSync(targetDir, { recursive: true });
130
159
  }
131
-
132
- // Mock behavior for Day 3/4 testing if no real registry
133
- // Expect source to be in examples/ if it exists, otherwise just touch it
134
- const mockSrc = path.join(process.cwd(), 'examples', 'skills', `${skillName}.md`);
135
160
  const targetFile = path.join(targetDir, 'SKILL.md');
136
-
137
- if (fs.existsSync(mockSrc)) {
138
- fs.copyFileSync(mockSrc, targetFile);
139
- console.log(` ✅ Copied from ${mockSrc}`);
140
- } else {
141
- // If no source, we look for it in the current dir for the agentic flow
142
- const localSrc = path.join(process.cwd(), 'SKILL.md');
143
- if (fs.existsSync(localSrc)) {
144
- fs.copyFileSync(localSrc, targetFile);
145
- console.log(' ✅ Copied from local SKILL.md');
146
- } else {
147
- // Just create a placeholder for testing if nothing else
148
- fs.writeFileSync(targetFile, `---\nname: ${skillName}\nversion: 1.0.0\nstatus: alpha\ntriggers: test, mock, placeholder\n---\n# ${skillName}\nPlaceholder for ${skillName} skill.\n`);
149
- console.log(' ⚠️ Created mock SKILL.md (no source found)');
150
- }
151
- }
161
+ fs.copyFileSync(source, targetFile);
162
+ console.log(` ✅ Installed ${skillName} from ${path.relative(process.cwd(), source)}`);
152
163
 
153
164
  process.exit(0);
154
165
  }
@@ -10,17 +10,83 @@ const fs = require('fs');
10
10
  const path = require('path');
11
11
 
12
12
  const ARGS = process.argv.slice(2);
13
- const MODE = ARGS[0]; // 'spawn' or 'identity'
13
+ const MODE = ARGS[0]; // 'spawn', 'identity', or 'subagent'
14
14
  const TARGET = ARGS[1];
15
15
  const IS_DRY_RUN = ARGS.includes('--dry-run');
16
16
 
17
17
  const ROOT = path.resolve(__dirname, '..');
18
+ const SUBAGENTS_DIR = path.join(ROOT, 'subagents');
19
+ const INDEX_PATH = path.join(ROOT, '.mindforge', 'imported-agents.jsonl');
20
+
21
+ // Names are restricted to a strict allowlist: no path separators, no '..', and
22
+ // only [A-Za-z0-9-_]. This is the first line of defense against path traversal
23
+ // in the `subagent` mode — names that fail this never touch the filesystem.
24
+ const SAFE_NAME_PATTERN = /^[A-Za-z0-9-_]+$/;
18
25
 
19
26
  if (!MODE || !TARGET) {
20
27
  console.error('❌ Usage: node bin/spawn-agent.js <mode> <target> [--dry-run]');
28
+ console.error(' modes: identity | spawn | subagent');
21
29
  process.exit(1);
22
30
  }
23
31
 
32
+ /**
33
+ * Validate a user-supplied subagent name against the strict allowlist. Rejects
34
+ * path separators, parent-dir tokens, and any character outside [A-Za-z0-9-_].
35
+ * Exits the process on violation rather than returning, so no unsafe name can
36
+ * proceed to a filesystem lookup.
37
+ */
38
+ function assertSafeName(name) {
39
+ if (!SAFE_NAME_PATTERN.test(name)) {
40
+ console.error(`❌ Invalid subagent name: "${name}" (allowed: A-Z a-z 0-9 - _)`);
41
+ process.exit(1);
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Resolve a subagent name to its index entry by EXACT name match. Never builds
47
+ * a path from user input — only paths recorded in the trusted index are used.
48
+ * Returns the matching entry or null if no entry matches.
49
+ */
50
+ function findIndexEntry(name) {
51
+ if (!fs.existsSync(INDEX_PATH)) {
52
+ console.error(`❌ Subagent index not found: ${INDEX_PATH}`);
53
+ console.error(' Run: node scripts/build-subagent-index.js');
54
+ process.exit(1);
55
+ }
56
+
57
+ const lines = fs.readFileSync(INDEX_PATH, 'utf8').split('\n');
58
+ for (const line of lines) {
59
+ if (!line.trim()) {
60
+ continue;
61
+ }
62
+ const entry = JSON.parse(line);
63
+ if (entry.name === name) {
64
+ return entry;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+
70
+ /**
71
+ * Resolve and verify the absolute path for an index entry. Confirms the
72
+ * resolved path stays within the repo's subagents/ directory before returning
73
+ * it (defense in depth against a tampered index). Exits on any violation.
74
+ */
75
+ function resolveSubagentPath(entry) {
76
+ const absolutePath = path.resolve(ROOT, entry.path);
77
+ const containmentRoot = SUBAGENTS_DIR + path.sep;
78
+
79
+ if (!absolutePath.startsWith(containmentRoot)) {
80
+ console.error(`❌ Resolved path escapes subagents/: ${absolutePath}`);
81
+ process.exit(1);
82
+ }
83
+ if (!fs.existsSync(absolutePath)) {
84
+ console.error(`❌ Subagent file missing: ${absolutePath}`);
85
+ process.exit(1);
86
+ }
87
+ return absolutePath;
88
+ }
89
+
24
90
  async function run() {
25
91
  let identityPath;
26
92
  let personaPath;
@@ -39,6 +105,19 @@ async function run() {
39
105
  process.exit(1);
40
106
  }
41
107
  console.log(`🌌 Spawning persona essence: ${TARGET}`);
108
+ } else if (MODE === 'subagent') {
109
+ assertSafeName(TARGET);
110
+ const entry = findIndexEntry(TARGET);
111
+ if (!entry) {
112
+ console.error(`❌ Subagent not found in index: ${TARGET}`);
113
+ process.exit(1);
114
+ }
115
+ const subagentPath = resolveSubagentPath(entry);
116
+ fs.readFileSync(subagentPath, 'utf8'); // verify readability before dispatch
117
+ console.log(`🧬 Loading imported subagent: ${TARGET} [${entry.category}/${entry.model}]`);
118
+ } else {
119
+ console.error(`❌ Unknown mode: ${MODE} (expected identity | spawn | subagent)`);
120
+ process.exit(1);
42
121
  }
43
122
 
44
123
  if (IS_DRY_RUN) {
@@ -1,13 +1,28 @@
1
1
  /**
2
2
  * MindForge v9.0.0 — Temporal Shadow Mirror (Pillar XXI)
3
- * Hybrid isolation for incident replication.
3
+ *
4
+ * Incident replication via git-worktree isolation.
5
+ *
6
+ * ISOLATION HONESTY (audit finding #24 / UC-22):
7
+ * This module provides GIT WORKTREE isolation only — a separate working tree
8
+ * and branch off the current repo. It does NOT provide container/Docker
9
+ * isolation (no separate kernel, network, filesystem, or process namespaces).
10
+ * A `docker --version` probe gates an "enhanced" path, but that path still runs
11
+ * in a git worktree; real Docker orchestration (build/run/mount) is a
12
+ * NOT-YET-IMPLEMENTED future enhancement. The returned mirror is always a
13
+ * worktree, and `activeMirror.isolation` reports the actual level provided.
4
14
  */
5
15
  'use strict';
6
16
 
7
- const { execSync } = require('node:child_process');
17
+ const { execSync, execFileSync } = require('node:child_process');
8
18
  const fs = require('node:fs');
9
19
  const path = require('node:path');
10
- const crypto = require('node:crypto');
20
+
21
+ // remediation_id flows from the SRE sentinel (a trust boundary) into git
22
+ // branch/worktree names. Only allow a safe identifier charset and reject
23
+ // anything that could be read as a flag or shell metacharacter. Defence in
24
+ // depth on top of execFileSync (argv array, no shell). Fail-closed.
25
+ const SAFE_REMEDIATION_ID = /^[A-Za-z0-9._-]+$/;
11
26
 
12
27
  class ShadowMirror {
13
28
  constructor(options = {}) {
@@ -15,32 +30,58 @@ class ShadowMirror {
15
30
  this.activeMirror = null;
16
31
  }
17
32
 
33
+ /**
34
+ * Validates a remediation_id (trust-boundary input) before it is used to
35
+ * build git branch/worktree names. Fail-closed: throws on missing, empty,
36
+ * overlong, flag-like, or metacharacter-bearing ids. Returns the id on pass.
37
+ * Static so it can be unit-tested in isolation.
38
+ */
39
+ static sanitizeRemediationId(id) {
40
+ if (typeof id !== 'string' || id.length === 0 || id.length > 128) {
41
+ throw new Error('[ShadowMirror] invalid remediation_id: must be a non-empty string of <=128 chars');
42
+ }
43
+ if (id.startsWith('-')) {
44
+ throw new Error('[ShadowMirror] invalid remediation_id: must not start with "-"');
45
+ }
46
+ if (!SAFE_REMEDIATION_ID.test(id)) {
47
+ throw new Error('[ShadowMirror] invalid remediation_id: only [A-Za-z0-9._-] characters allowed');
48
+ }
49
+ return id;
50
+ }
51
+
18
52
  /**
19
53
  * Orchestrates replication based on incident severity and requirements.
20
54
  */
21
55
  async replicate(incident) {
22
56
  console.log(`🌀 Shadow Mirror: Replicating incident [${incident.remediation_id}]...`);
23
-
24
- // Choose isolation level
25
- const level = (incident.details?.severity === 'CRITICAL') ? 2 : 1;
26
-
27
- if (level === 2 && this.isDockerAvailable()) {
28
- return this.replicateLevel2(incident);
29
- } else {
30
- return this.replicateLevel1(incident);
57
+
58
+ // All replication currently runs in a git worktree (see file header).
59
+ // For CRITICAL incidents where a Docker toolchain is present we note that a
60
+ // future container-isolation path could be used, but we DO NOT claim to run
61
+ // it we still replicate in a worktree and label it honestly.
62
+ const wantsContainer = incident.details?.severity === 'CRITICAL' && this.isDockerAvailable();
63
+
64
+ if (wantsContainer) {
65
+ return this.replicateCriticalWorktree(incident);
31
66
  }
67
+ return this.replicateLevel1(incident);
32
68
  }
33
69
 
34
70
  /**
35
71
  * Level 1 Replication: Git Worktree
36
- * High-speed, lightweight logic isolation.
72
+ * High-speed, lightweight logic isolation (NOT container isolation).
73
+ *
74
+ * Provides a separate working tree + branch off the current repo. This
75
+ * isolates source/logic changes; it shares the host kernel, network,
76
+ * filesystem and process namespaces with the running engine.
37
77
  */
38
78
  async replicateLevel1(incident) {
39
- const mirrorId = `mirror-${incident.remediation_id}`;
79
+ const remediationId = ShadowMirror.sanitizeRemediationId(incident.remediation_id);
80
+ const mirrorId = `mirror-${remediationId}`;
40
81
  const mirrorPath = path.join(this.baseDir, mirrorId);
41
- const branchName = `sre-repro-${incident.remediation_id}`;
82
+ const branchName = `sre-repro-${remediationId}`;
42
83
 
43
- console.log(`[Level 1] Creating git worktree at ${mirrorPath}...`);
84
+ console.log(`[worktree] Creating git worktree at ${mirrorPath}...`);
44
85
 
45
86
  try {
46
87
  if (!fs.existsSync(this.baseDir)) {
@@ -49,41 +90,46 @@ class ShadowMirror {
49
90
 
50
91
  // 1. Create a reproduction branch and add worktree in one step (Atomic)
51
92
  // In a real system, we'd base this on the commit hash from the trace_id
52
- execSync(`git worktree add -b ${branchName} ${mirrorPath}`, { stdio: 'ignore' });
53
-
54
- this.activeMirror = { path: mirrorPath, branch: branchName, type: 'worktree' };
93
+ // execFileSync with an argv array no shell, so branchName/mirrorPath
94
+ // cannot inject commands even if they somehow contained metacharacters.
95
+ execFileSync('git', ['worktree', 'add', '-b', branchName, mirrorPath], { stdio: 'ignore' });
96
+
97
+ this.activeMirror = {
98
+ path: mirrorPath,
99
+ branch: branchName,
100
+ type: 'worktree-isolation',
101
+ // Honest disclosure of the isolation actually provided.
102
+ isolation: 'git-worktree',
103
+ };
55
104
 
56
105
  // 3. Inject incident metadata for the agent to use
57
106
  fs.writeFileSync(path.join(mirrorPath, 'REPLICATION.json'), JSON.stringify(incident, null, 2));
58
107
 
59
108
  return mirrorPath;
60
109
  } catch (err) {
61
- console.error(`[ShadowMirror] Level 1 replication failed: ${err.message}`);
110
+ console.error(`[ShadowMirror] worktree replication failed: ${err.message}`);
62
111
  throw err;
63
112
  }
64
113
  }
65
114
 
66
115
  /**
67
- * Level 2 Replication: Docker Sandbox
68
- * Full environment isolation for state-bound incidents.
116
+ * CRITICAL-incident replication when a Docker toolchain is detected.
117
+ *
118
+ * HONESTY: This still replicates in a GIT WORKTREE. It does not build or run
119
+ * a container, does not mount any volume, and does not provide container
120
+ * isolation. Real Docker sandboxing (build/run/mount) is a NOT-YET-IMPLEMENTED
121
+ * enhancement tracked separately; until it lands, this path is identical in
122
+ * isolation guarantees to {@link replicateLevel1} and is labelled as such.
69
123
  */
70
- async replicateLevel2(incident) {
71
- console.log('[Level 2] Initializing Docker sandbox interface...');
72
- // For the hackathon demo, we'll scaffold the Docker-ready worktree which would then be mounted
124
+ async replicateCriticalWorktree(incident) {
125
+ console.log('[worktree] CRITICAL incident: replicating in git worktree (container isolation not implemented).');
73
126
  const mirrorPath = await this.replicateLevel1(incident);
74
-
75
- const dockerfile = `
76
- FROM node:18-slim
77
- WORKDIR /app
78
- COPY . .
79
- RUN npm install --production
80
- CMD ["node", "bin/engine/logic-validator.js"]
81
- `;
82
-
83
- fs.writeFileSync(path.join(mirrorPath, 'Dockerfile.sre'), dockerfile);
84
- console.log(`[Level 2] Dockerfile.sre generated at ${mirrorPath}. Mounting volume for isolation.`);
85
-
86
- this.activeMirror.type = 'docker-hybrid';
127
+
128
+ // Note the unimplemented future path without claiming it ran.
129
+ this.activeMirror.dockerAvailable = true;
130
+ this.activeMirror.note =
131
+ 'docker binary detected; real container isolation is a future enhancement — this mirror used git-worktree isolation only';
132
+
87
133
  return mirrorPath;
88
134
  }
89
135
 
@@ -104,9 +150,13 @@ CMD ["node", "bin/engine/logic-validator.js"]
104
150
 
105
151
  console.log(`🧹 Cleaning up Shadow Mirror: ${this.activeMirror.path}...`);
106
152
  try {
107
- if (this.activeMirror.type === 'worktree' || this.activeMirror.type === 'docker-hybrid') {
108
- execSync(`git worktree remove ${this.activeMirror.path} --force`, { stdio: 'ignore' });
109
- execSync(`git branch -D ${this.activeMirror.branch}`, { stdio: 'ignore' });
153
+ // Every mirror this module produces is a git worktree (see replicate()).
154
+ // Accept the legacy 'worktree'/'docker-hybrid' labels for backward compat
155
+ // in case an older serialized mirror is handed in.
156
+ const worktreeTypes = ['worktree-isolation', 'worktree', 'docker-hybrid'];
157
+ if (worktreeTypes.includes(this.activeMirror.type)) {
158
+ execFileSync('git', ['worktree', 'remove', this.activeMirror.path, '--force'], { stdio: 'ignore' });
159
+ execFileSync('git', ['branch', '-D', this.activeMirror.branch], { stdio: 'ignore' });
110
160
  // Clean up the folder just in case
111
161
  if (fs.existsSync(this.activeMirror.path)) {
112
162
  fs.rmSync(this.activeMirror.path, { recursive: true });
@@ -17,6 +17,18 @@ const fs = require('fs');
17
17
  // unboundedly. Revisit with an LRU/eviction policy if dynamic paths are needed.
18
18
  const queues = new Map();
19
19
 
20
+ /**
21
+ * @deprecated No production caller. The real durable-append path is
22
+ * `appendDurableSync` in `bin/memory/knowledge-store.js` (synchronous
23
+ * openSync+writeSync+fsyncSync+closeSync), which all audit/KB write sites use.
24
+ * This async single-writer queue is retained only as a tested reference
25
+ * implementation for the in-process serialized-append pattern (UC-09) and is
26
+ * exercised solely by `tests/append-queue.test.js`. Do NOT wire it into new
27
+ * code without first reconciling it with the canonical sync path.
28
+ *
29
+ * @param {string} filePath — file to serialize appends for
30
+ * @returns {{append: (line: string) => Promise<void>, drain: () => Promise<void>}}
31
+ */
20
32
  function createAppendQueue(filePath) {
21
33
  if (!queues.has(filePath)) queues.set(filePath, Promise.resolve());
22
34
 
@@ -3,7 +3,6 @@
3
3
  const fs = require('fs');
4
4
  const fsp = require('fs/promises');
5
5
  const path = require('path');
6
- const zlib = require('zlib');
7
6
 
8
7
  /**
9
8
  * Hash-chained audit writer (class API preserved for nexus-tracer + policy-engine).
@@ -28,8 +27,9 @@ class AuditWriter {
28
27
  }
29
28
 
30
29
  async write(entry) {
31
- // Lazy require to avoid a require-cycle: audit-writer.js requires this file
32
- // (AuditRotator) at load time, so we cannot require it at module top level.
30
+ // Lazy require (not module-top-level) to keep this leaf utility free of a
31
+ // load-time dependency on the autonomous layer and avoid any future require
32
+ // cycle: bin/autonomous/audit-writer.js is the canonical durable-append site.
33
33
  const { appendAuditEntrySync } = require('../autonomous/audit-writer');
34
34
  const chained = appendAuditEntrySync(this._path, entry);
35
35
  this._lastHash = chained._hash;
@@ -110,45 +110,4 @@ async function atomicWriteJSONAsync(filePath, data) {
110
110
  await fsp.rename(tmpPath, filePath);
111
111
  }
112
112
 
113
- class AuditRotator {
114
- constructor(options = {}) {
115
- this.maxLines = options.maxLines || 5000;
116
- }
117
-
118
- shouldRotate(filePath) {
119
- if (!fs.existsSync(filePath)) return false;
120
- const content = fs.readFileSync(filePath, 'utf8');
121
- const lineCount = content.split('\n').filter(l => l.trim()).length;
122
- return lineCount >= this.maxLines;
123
- }
124
-
125
- rotate(filePath, archiveDir) {
126
- const dir = archiveDir || path.join(path.dirname(filePath), '..', 'audit-archive');
127
- if (!fs.existsSync(dir)) {
128
- fs.mkdirSync(dir, { recursive: true });
129
- }
130
-
131
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
132
- const baseName = path.basename(filePath, path.extname(filePath));
133
- const archiveName = `${baseName}-${timestamp}.jsonl.gz`;
134
- const archivePath = path.join(dir, archiveName);
135
-
136
- // Crash-safe: write archive FIRST, then truncate source
137
- const content = fs.readFileSync(filePath);
138
- const compressed = zlib.gzipSync(content);
139
- fs.writeFileSync(archivePath, compressed);
140
-
141
- const lines = content.toString('utf8').split('\n').filter(l => l.trim());
142
- const carryover = lines.slice(-100).join('\n') + '\n';
143
- const tmpPath = filePath + '.tmp.' + process.pid;
144
- const fd = fs.openSync(tmpPath, 'w');
145
- fs.writeSync(fd, carryover);
146
- fs.fsyncSync(fd);
147
- fs.closeSync(fd);
148
- fs.renameSync(tmpPath, filePath);
149
-
150
- return archivePath;
151
- }
152
- }
153
-
154
- module.exports = { AuditWriter, AuditRotator, readJSON, writeJSON, readJSONL, readJSONSync, atomicWriteJSON, atomicWriteJSONAsync };
113
+ module.exports = { AuditWriter, readJSON, writeJSON, readJSONL, readJSONSync, atomicWriteJSON, atomicWriteJSONAsync };
@@ -3,12 +3,25 @@
3
3
  * MindForge version single-source-of-truth + drift detector.
4
4
  * package.json is canonical; everything else must agree.
5
5
  */
6
+ const fs = require('fs');
6
7
  const path = require('path');
7
8
  // Use the repo's stricter reader: returns null only on ENOENT and RE-THROWS on
8
9
  // parse errors. Re-throwing on a corrupt JSON source is the fail-closed
9
10
  // behavior we want — a file we cannot parse means we cannot establish truth.
10
11
  const { readJSONSync } = require('./file-io');
11
12
 
13
+ /**
14
+ * Extracts `[VERSION] = X` from MINDFORGE.md. Returns null when the file is
15
+ * absent or the marker is missing (treated as skip, not drift).
16
+ */
17
+ function readMindforgeMdVersion(projectRoot) {
18
+ const mdPath = path.join(projectRoot, 'MINDFORGE.md');
19
+ if (!fs.existsSync(mdPath)) return null;
20
+ const text = fs.readFileSync(mdPath, 'utf8');
21
+ const match = text.match(/\[VERSION\]\s*=\s*([^\s]+)/);
22
+ return match ? match[1].trim() : null;
23
+ }
24
+
12
25
  /**
13
26
  * @param {string} projectRoot
14
27
  * @returns {{ canonical: string|null, sources: Record<string,string|null>, drift: string[] }}
@@ -18,14 +31,17 @@ function checkVersionConsistency(projectRoot) {
18
31
  const canonical = pkg ? pkg.version : null;
19
32
 
20
33
  const configJson = readJSONSync(path.join(projectRoot, '.mindforge', 'config.json'));
21
- // Runtime drift coverage is intentionally limited to package.json (canonical)
22
- // vs .mindforge/config.json — the live config is the operational drift risk
23
- // during `auto`. Wider agreement (sdk/package.json, MINDFORGE.md [VERSION]) is
24
- // enforced by the test suite (tests/version-consistency.test.js), not at
25
- // runtime do not assume this checker provides full version coverage.
34
+ const sdkPkg = readJSONSync(path.join(projectRoot, 'sdk', 'package.json'));
35
+ const mindforgeMdVersion = readMindforgeMdVersion(projectRoot);
36
+ // Runtime coverage now spans every source the test suite knows about, so
37
+ // drift in any of them halts `auto` — not just the live config. Absent
38
+ // optional sources (no sdk/, no MINDFORGE.md) read as null and are SKIPPED
39
+ // (not counted as drift); only a present-but-mismatched source flags drift.
26
40
  const sources = {
27
41
  'package.json': canonical,
28
42
  '.mindforge/config.json': configJson ? configJson.version : null,
43
+ 'sdk/package.json': sdkPkg ? sdkPkg.version : null,
44
+ 'MINDFORGE.md': mindforgeMdVersion,
29
45
  };
30
46
 
31
47
  const drift = [];
@@ -125,14 +125,15 @@ const Theme = {
125
125
  * Print Manifest (Hardened for V2)
126
126
  */
127
127
  printManifest(stats = {}) {
128
- const { personas = 117, skills = 20, governance = 4, integrations = 7, actions = 71, docs = 12, templates = 21 } = stats;
129
-
128
+ const { personas = 117, skills = 20, subagents = 154, governance = 4, integrations = 7, actions = 71, docs = 12, templates = 21 } = stats;
129
+
130
130
  console.log(` ${this.colors.bold('PAYLOAD MANIFEST')}`);
131
131
  console.log(` ${this.colors.dim('┌' + '─'.repeat(74) + '┐')}`);
132
-
132
+
133
133
  const rows = [
134
134
  ['PERSONAS', personas, 'The autonomous persona ecosystem'],
135
135
  ['SKILLS', skills, 'Enterprise-grade skill packs'],
136
+ ['SUBAGENTS', subagents, 'Specialized Claude Code subagents'],
136
137
  ['GOVERNANCE', governance, 'Compliance and safety modules'],
137
138
  ['INTEGRATIONS', integrations, 'Multi-platform connector suite'],
138
139
  ['REFERENCES', docs, 'Standardized architecture references'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindforge-cc",
3
- "version": "11.2.0",
3
+ "version": "11.3.0",
4
4
  "description": "MindForge \u2014 Sovereign Agentic Intelligence Framework. Sovereign Stability: Production-Hardened Agentic Intelligence (v11)",
5
5
  "bin": {
6
6
  "mindforge-cc": "bin/install.js",
@@ -16,6 +16,8 @@
16
16
  ".mindforge/skills/",
17
17
  ".mindforge/engine/",
18
18
  "bin/",
19
+ "subagents/",
20
+ ".mindforge/imported-agents.jsonl",
19
21
  "docs/getting-started.md",
20
22
  "docs/user-guide.md",
21
23
  "docs/sdk-reference.md",
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "mindforge-subagents",
3
+ "owner": {
4
+ "name": "MindForge Team",
5
+ "url": "https://github.com/sairam0424"
6
+ },
7
+ "metadata": {
8
+ "version": "1.0.3",
9
+ "description": "Curated collection of 154 specialized Claude Code subagents organized into 10 focused categories"
10
+ },
11
+ "plugins": [
12
+ {
13
+ "name": "mindforge-core-dev",
14
+ "source": "./categories/01-core-development",
15
+ "description": "Essential development subagents for everyday coding tasks - backend, frontend, fullstack, mobile, and API design",
16
+ "version": "1.0.2",
17
+ "category": "development",
18
+ "keywords": ["backend", "frontend", "fullstack", "mobile", "api", "microservices"]
19
+ },
20
+ {
21
+ "name": "mindforge-lang",
22
+ "source": "./categories/02-language-specialists",
23
+ "description": "Language-specific expert agents with deep framework knowledge - Python, TypeScript, Go, Rust, Java, and more",
24
+ "version": "1.0.4",
25
+ "category": "development",
26
+ "keywords": ["python", "typescript", "golang", "rust", "java", "react", "vue", "angular", "expo", "react-native", "node"]
27
+ },
28
+ {
29
+ "name": "mindforge-infra",
30
+ "source": "./categories/03-infrastructure",
31
+ "description": "DevOps, cloud, and deployment specialists - Kubernetes, Terraform, AWS, Azure, GCP, and SRE",
32
+ "version": "1.0.1",
33
+ "category": "infrastructure",
34
+ "keywords": ["devops", "docker", "kubernetes", "terraform", "aws", "azure", "gcp", "sre", "cloud"]
35
+ },
36
+ {
37
+ "name": "mindforge-qa-sec",
38
+ "source": "./categories/04-quality-security",
39
+ "description": "Testing, security, and code quality experts - code review, penetration testing, QA automation",
40
+ "version": "1.1.1",
41
+ "category": "quality",
42
+ "keywords": ["testing", "security", "code-review", "qa", "penetration-testing", "compliance", "ui-testing", "ux-testing"]
43
+ },
44
+ {
45
+ "name": "mindforge-data-ai",
46
+ "source": "./categories/05-data-ai",
47
+ "description": "Data engineering, ML, and AI specialists - data pipelines, machine learning, LLM architecture",
48
+ "version": "1.0.2",
49
+ "category": "data",
50
+ "keywords": ["data-engineering", "machine-learning", "ai", "llm", "mlops", "nlp"]
51
+ },
52
+ {
53
+ "name": "mindforge-dev-exp",
54
+ "source": "./categories/06-developer-experience",
55
+ "description": "Tooling and developer productivity experts - CLI tools, documentation, README generation, and DX optimization",
56
+ "version": "1.0.3",
57
+ "category": "tooling",
58
+ "keywords": ["developer-experience", "cli", "documentation", "readme", "tooling", "build", "dx"]
59
+ },
60
+ {
61
+ "name": "mindforge-domains",
62
+ "source": "./categories/07-specialized-domains",
63
+ "description": "Domain-specific technology experts - blockchain, fintech, gaming, IoT, payments",
64
+ "version": "1.0.2",
65
+ "category": "specialized",
66
+ "keywords": ["blockchain", "fintech", "gaming", "iot", "payments", "embedded"]
67
+ },
68
+ {
69
+ "name": "mindforge-biz",
70
+ "source": "./categories/08-business-product",
71
+ "description": "Product, legal, and business specialists - product strategy, licensing, project management, UX research",
72
+ "version": "1.0.3",
73
+ "category": "business",
74
+ "keywords": ["product-management", "business-analysis", "legal", "licensing", "ux", "scrum", "project-management"]
75
+ },
76
+ {
77
+ "name": "mindforge-meta",
78
+ "source": "./categories/09-meta-orchestration",
79
+ "description": "Agent coordination and meta-programming - multi-agent orchestration, workflow automation, and safe refactor governance. Works best with other mindforge plugins installed.",
80
+ "version": "1.0.3",
81
+ "category": "orchestration",
82
+ "keywords": ["multi-agent", "orchestration", "workflow", "coordination", "meta", "refactor", "codebase-governance"]
83
+ },
84
+ {
85
+ "name": "mindforge-research",
86
+ "source": "./categories/10-research-analysis",
87
+ "description": "Research, search, and analysis specialists - market research, competitive analysis, trend forecasting, and idea validation",
88
+ "version": "1.0.4",
89
+ "category": "research",
90
+ "keywords": ["research", "analysis", "market-research", "competitive-analysis", "trends", "idea-validation", "product-strategy"]
91
+ }
92
+ ]
93
+ }