agentic-qe 3.7.20 → 3.7.22

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 (115) hide show
  1. package/.claude/agents/v3/qe-deployment-advisor.md +14 -0
  2. package/.claude/agents/v3/qe-gap-detector.md +8 -0
  3. package/.claude/agents/v3/qe-impact-analyzer.md +11 -0
  4. package/.claude/agents/v3/qe-queen-coordinator.md +45 -0
  5. package/.claude/agents/v3/qe-root-cause-analyzer.md +11 -0
  6. package/.claude/agents/v3/qe-security-scanner.md +25 -16
  7. package/.claude/helpers/brain-checkpoint.cjs +7 -4
  8. package/.claude/helpers/statusline-v3.cjs +7 -4
  9. package/.claude/skills/skills-manifest.json +1 -1
  10. package/CHANGELOG.md +34 -0
  11. package/README.md +0 -12
  12. package/assets/agents/v3/qe-deployment-advisor.md +14 -0
  13. package/assets/agents/v3/qe-gap-detector.md +8 -0
  14. package/assets/agents/v3/qe-impact-analyzer.md +11 -0
  15. package/assets/agents/v3/qe-queen-coordinator.md +45 -0
  16. package/assets/agents/v3/qe-root-cause-analyzer.md +11 -0
  17. package/assets/agents/v3/qe-security-scanner.md +25 -16
  18. package/assets/helpers/statusline-v3.cjs +7 -4
  19. package/dist/adapters/claude-flow/model-router-bridge.d.ts +0 -6
  20. package/dist/adapters/claude-flow/model-router-bridge.js +4 -17
  21. package/dist/adapters/claude-flow/pretrain-bridge.d.ts +0 -6
  22. package/dist/adapters/claude-flow/pretrain-bridge.js +6 -19
  23. package/dist/adapters/claude-flow/trajectory-bridge.d.ts +0 -6
  24. package/dist/adapters/claude-flow/trajectory-bridge.js +21 -23
  25. package/dist/cli/brain-commands.js +6 -10
  26. package/dist/cli/bundle.js +3124 -3622
  27. package/dist/cli/commands/hooks.js +29 -6
  28. package/dist/cli/commands/init.js +1 -73
  29. package/dist/cli/commands/learning.js +164 -12
  30. package/dist/cli/handlers/init-handler.d.ts +0 -1
  31. package/dist/cli/handlers/init-handler.js +0 -6
  32. package/dist/cli/index.js +0 -2
  33. package/dist/context/sources/defect-source.js +2 -2
  34. package/dist/context/sources/memory-source.js +2 -2
  35. package/dist/context/sources/requirements-source.js +2 -2
  36. package/dist/coordination/protocols/security-audit.d.ts +3 -6
  37. package/dist/coordination/protocols/security-audit.js +8 -88
  38. package/dist/coordination/queen-coordinator.d.ts +13 -0
  39. package/dist/coordination/queen-coordinator.js +76 -0
  40. package/dist/coordination/queen-task-management.d.ts +2 -0
  41. package/dist/coordination/queen-task-management.js +10 -0
  42. package/dist/coordination/queen-types.d.ts +3 -0
  43. package/dist/coordination/task-executor.js +7 -5
  44. package/dist/domains/security-compliance/services/scanners/sast-scanner.d.ts +25 -1
  45. package/dist/domains/security-compliance/services/scanners/sast-scanner.js +140 -11
  46. package/dist/domains/security-compliance/services/scanners/scanner-types.d.ts +2 -0
  47. package/dist/domains/security-compliance/services/scanners/scanner-types.js +1 -0
  48. package/dist/domains/test-execution/services/mincut-test-optimizer.js +2 -0
  49. package/dist/init/agents-installer.d.ts +2 -0
  50. package/dist/init/agents-installer.js +13 -0
  51. package/dist/init/enhancements/claude-flow-adapter.js +51 -24
  52. package/dist/init/index.d.ts +0 -2
  53. package/dist/init/index.js +0 -1
  54. package/dist/init/init-wizard-steps.d.ts +10 -0
  55. package/dist/init/init-wizard-steps.js +87 -1
  56. package/dist/init/init-wizard.d.ts +1 -9
  57. package/dist/init/init-wizard.js +3 -69
  58. package/dist/init/orchestrator.js +0 -1
  59. package/dist/init/phases/01-detection.js +0 -27
  60. package/dist/init/phases/07-hooks.js +12 -10
  61. package/dist/init/phases/phase-interface.d.ts +0 -1
  62. package/dist/init/settings-merge.js +1 -1
  63. package/dist/integrations/ruvector/brain-rvf-exporter.js +14 -2
  64. package/dist/kernel/unified-memory.js +5 -6
  65. package/dist/learning/experience-capture-middleware.js +23 -1
  66. package/dist/learning/index.d.ts +0 -2
  67. package/dist/learning/index.js +0 -4
  68. package/dist/learning/metrics-tracker.js +15 -13
  69. package/dist/learning/pattern-lifecycle.d.ts +1 -1
  70. package/dist/learning/pattern-lifecycle.js +18 -20
  71. package/dist/learning/qe-reasoning-bank.js +3 -3
  72. package/dist/learning/qe-unified-memory.js +1 -28
  73. package/dist/learning/sqlite-persistence.js +16 -0
  74. package/dist/learning/token-tracker.js +4 -2
  75. package/dist/mcp/bundle.js +1162 -478
  76. package/dist/routing/agent-dependency-graph.d.ts +77 -0
  77. package/dist/routing/agent-dependency-graph.js +359 -0
  78. package/dist/routing/co-execution-repository.d.ts +68 -0
  79. package/dist/routing/co-execution-repository.js +184 -0
  80. package/dist/routing/index.d.ts +6 -0
  81. package/dist/routing/index.js +6 -0
  82. package/dist/routing/qe-task-router.d.ts +7 -0
  83. package/dist/routing/qe-task-router.js +63 -1
  84. package/dist/routing/signal-merger.d.ts +81 -0
  85. package/dist/routing/signal-merger.js +136 -0
  86. package/dist/routing/types.d.ts +1 -0
  87. package/dist/shared/llm/providers/azure-openai.js +3 -2
  88. package/dist/shared/llm/providers/bedrock.js +3 -2
  89. package/dist/shared/llm/providers/claude.js +3 -2
  90. package/dist/shared/llm/providers/gemini.js +3 -2
  91. package/dist/shared/llm/providers/openai.js +3 -2
  92. package/dist/shared/llm/providers/openrouter.js +3 -2
  93. package/dist/shared/llm/retry.d.ts +10 -0
  94. package/dist/shared/llm/retry.js +16 -0
  95. package/dist/shared/llm/router/agent-router-config.d.ts +2 -1
  96. package/dist/shared/llm/router/agent-router-config.js +38 -88
  97. package/dist/validation/index.d.ts +2 -0
  98. package/dist/validation/index.js +4 -0
  99. package/dist/validation/steps/agent-mcp-validator.d.ts +88 -0
  100. package/dist/validation/steps/agent-mcp-validator.js +254 -0
  101. package/package.json +1 -1
  102. package/dist/cli/commands/migrate.d.ts +0 -9
  103. package/dist/cli/commands/migrate.js +0 -566
  104. package/dist/init/init-wizard-migration.d.ts +0 -52
  105. package/dist/init/init-wizard-migration.js +0 -345
  106. package/dist/init/migration/config-migrator.d.ts +0 -31
  107. package/dist/init/migration/config-migrator.js +0 -149
  108. package/dist/init/migration/data-migrator.d.ts +0 -72
  109. package/dist/init/migration/data-migrator.js +0 -232
  110. package/dist/init/migration/detector.d.ts +0 -44
  111. package/dist/init/migration/detector.js +0 -105
  112. package/dist/init/migration/index.d.ts +0 -8
  113. package/dist/init/migration/index.js +0 -8
  114. package/dist/learning/v2-to-v3-migration.d.ts +0 -86
  115. package/dist/learning/v2-to-v3-migration.js +0 -529
@@ -11,9 +11,18 @@
11
11
  */
12
12
  import { detectClaudeFlow } from '../../adapters/claude-flow/detect.js';
13
13
  import { safeJsonParse } from '../../shared/safe-json.js';
14
- /** Shared execSync options for cross-platform CLI calls */
15
- const SHELL = process.platform === 'win32' ? 'cmd.exe' : '/bin/sh';
16
- const EXEC_OPTS = { encoding: 'utf-8', shell: SHELL };
14
+ /** Shared execFileSync options */
15
+ const EXEC_OPTS = { encoding: 'utf-8' };
16
+ /**
17
+ * Build args array for npx @claude-flow/cli calls.
18
+ * Using execFileSync with explicit args prevents shell injection.
19
+ */
20
+ function cfCliArgs(...subcommand) {
21
+ return {
22
+ bin: 'npx',
23
+ args: ['--no-install', '@claude-flow/cli', ...subcommand],
24
+ };
25
+ }
17
26
  /**
18
27
  * Claude Flow Adapter Implementation
19
28
  * Falls back gracefully when Claude Flow is not available
@@ -86,9 +95,12 @@ export class ClaudeFlowAdapterImpl {
86
95
  return `aqe-trajectory-${Date.now()}`;
87
96
  }
88
97
  try {
89
- const { execSync } = await import('child_process');
90
- const agentArg = agent ? `--agent "${agent}"` : '';
91
- const result = execSync(`npx --no-install @claude-flow/cli hooks intelligence trajectory-start --task "${task}" ${agentArg}`, { ...EXEC_OPTS, timeout: 10000 });
98
+ const { execFileSync } = await import('child_process');
99
+ const { bin, args } = cfCliArgs('hooks', 'intelligence', 'trajectory-start', '--task', task);
100
+ if (agent) {
101
+ args.push('--agent', agent);
102
+ }
103
+ const result = execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
92
104
  // Parse trajectory ID from result
93
105
  const match = result.match(/trajectoryId[:\s]+["']?([^"'\s]+)/i);
94
106
  return match?.[1] || `cf-trajectory-${Date.now()}`;
@@ -104,10 +116,15 @@ export class ClaudeFlowAdapterImpl {
104
116
  if (!this.available)
105
117
  return;
106
118
  try {
107
- const { execSync } = await import('child_process');
108
- const resultArg = result ? `--result "${result}"` : '';
109
- const qualityArg = quality !== undefined ? `--quality ${quality}` : '';
110
- execSync(`npx --no-install @claude-flow/cli hooks intelligence trajectory-step --trajectory-id "${trajectoryId}" --action "${action}" ${resultArg} ${qualityArg}`, { ...EXEC_OPTS, timeout: 10000 });
119
+ const { execFileSync } = await import('child_process');
120
+ const { bin, args } = cfCliArgs('hooks', 'intelligence', 'trajectory-step', '--trajectory-id', trajectoryId, '--action', action);
121
+ if (result) {
122
+ args.push('--result', result);
123
+ }
124
+ if (quality !== undefined) {
125
+ args.push('--quality', String(quality));
126
+ }
127
+ execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
111
128
  }
112
129
  catch (error) {
113
130
  // Non-critical: trajectory tracking is optional
@@ -121,9 +138,12 @@ export class ClaudeFlowAdapterImpl {
121
138
  if (!this.available)
122
139
  return;
123
140
  try {
124
- const { execSync } = await import('child_process');
125
- const feedbackArg = feedback ? `--feedback "${feedback}"` : '';
126
- execSync(`npx --no-install @claude-flow/cli hooks intelligence trajectory-end --trajectory-id "${trajectoryId}" --success ${success} ${feedbackArg}`, { ...EXEC_OPTS, timeout: 10000 });
141
+ const { execFileSync } = await import('child_process');
142
+ const { bin, args } = cfCliArgs('hooks', 'intelligence', 'trajectory-end', '--trajectory-id', trajectoryId, '--success', String(success));
143
+ if (feedback) {
144
+ args.push('--feedback', feedback);
145
+ }
146
+ execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
127
147
  }
128
148
  catch (error) {
129
149
  // Non-critical: trajectory end is optional
@@ -139,8 +159,9 @@ export class ClaudeFlowAdapterImpl {
139
159
  return { model: 'sonnet', confidence: 0.5 };
140
160
  }
141
161
  try {
142
- const { execSync } = await import('child_process');
143
- const result = execSync(`npx --no-install @claude-flow/cli hooks model-route --task "${task}"`, { ...EXEC_OPTS, timeout: 10000 });
162
+ const { execFileSync } = await import('child_process');
163
+ const { bin, args } = cfCliArgs('hooks', 'model-route', '--task', task);
164
+ const result = execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
144
165
  // Parse result
145
166
  const modelMatch = result.match(/model[:\s]+["']?(haiku|sonnet|opus)/i);
146
167
  const confMatch = result.match(/confidence[:\s]+([0-9.]+)/i);
@@ -162,8 +183,9 @@ export class ClaudeFlowAdapterImpl {
162
183
  if (!this.available)
163
184
  return;
164
185
  try {
165
- const { execSync } = await import('child_process');
166
- execSync(`npx --no-install @claude-flow/cli hooks model-outcome --task "${task}" --model ${model} --outcome ${outcome}`, { ...EXEC_OPTS, timeout: 10000 });
186
+ const { execFileSync } = await import('child_process');
187
+ const { bin, args } = cfCliArgs('hooks', 'model-outcome', '--task', task, '--model', model, '--outcome', outcome);
188
+ execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
167
189
  }
168
190
  catch (error) {
169
191
  // Non-critical: outcome recording is optional
@@ -178,8 +200,9 @@ export class ClaudeFlowAdapterImpl {
178
200
  return { success: false, reason: 'Claude Flow not available' };
179
201
  }
180
202
  try {
181
- const { execSync } = await import('child_process');
182
- const result = execSync(`npx --no-install @claude-flow/cli hooks pretrain --path "${path}" --depth ${depth}`, { ...EXEC_OPTS, timeout: 60000 });
203
+ const { execFileSync } = await import('child_process');
204
+ const { bin, args } = cfCliArgs('hooks', 'pretrain', '--path', path, '--depth', depth);
205
+ const result = execFileSync(bin, args, { ...EXEC_OPTS, timeout: 60000 });
183
206
  // Try to parse JSON result
184
207
  try {
185
208
  return safeJsonParse(result);
@@ -199,9 +222,12 @@ export class ClaudeFlowAdapterImpl {
199
222
  if (!this.available)
200
223
  return;
201
224
  try {
202
- const { execSync } = await import('child_process');
203
- const metadataArg = metadata ? `--metadata '${JSON.stringify(metadata)}'` : '';
204
- execSync(`npx --no-install @claude-flow/cli hooks intelligence pattern-store --pattern "${pattern}" --type ${type} --confidence ${confidence} ${metadataArg}`, { ...EXEC_OPTS, timeout: 10000 });
225
+ const { execFileSync } = await import('child_process');
226
+ const { bin, args } = cfCliArgs('hooks', 'intelligence', 'pattern-store', '--pattern', pattern, '--type', type, '--confidence', String(confidence));
227
+ if (metadata) {
228
+ args.push('--metadata', JSON.stringify(metadata));
229
+ }
230
+ execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
205
231
  }
206
232
  catch (error) {
207
233
  // Non-critical: pattern storage is optional
@@ -216,8 +242,9 @@ export class ClaudeFlowAdapterImpl {
216
242
  return [];
217
243
  }
218
244
  try {
219
- const { execSync } = await import('child_process');
220
- const result = execSync(`npx --no-install @claude-flow/cli hooks intelligence pattern-search --query "${query}" --top-k ${topK}`, { ...EXEC_OPTS, timeout: 10000 });
245
+ const { execFileSync } = await import('child_process');
246
+ const { bin, args } = cfCliArgs('hooks', 'intelligence', 'pattern-search', '--query', query, '--top-k', String(topK));
247
+ const result = execFileSync(bin, args, { ...EXEC_OPTS, timeout: 10000 });
221
248
  // Try to parse JSON result
222
249
  try {
223
250
  const parsed = safeJsonParse(result);
@@ -41,6 +41,4 @@ export type { WindsurfInstallerOptions, WindsurfInstallResult } from './windsurf
41
41
  export { WindsurfInstaller, createWindsurfInstaller } from './windsurf-installer.js';
42
42
  export type { ContinueDevInstallerOptions, ContinueDevInstallResult } from './continuedev-installer.js';
43
43
  export { ContinueDevInstaller, createContinueDevInstaller } from './continuedev-installer.js';
44
- export type { V2DetectionInfo, MigrationResult, } from './migration/index.js';
45
- export { V2Detector, createV2Detector, V2DataMigrator, createV2DataMigrator, V2ConfigMigrator, createV2ConfigMigrator, } from './migration/index.js';
46
44
  //# sourceMappingURL=index.d.ts.map
@@ -24,5 +24,4 @@ export { RooCodeInstaller, createRooCodeInstaller } from './roocode-installer.js
24
24
  export { CodexInstaller, createCodexInstaller } from './codex-installer.js';
25
25
  export { WindsurfInstaller, createWindsurfInstaller } from './windsurf-installer.js';
26
26
  export { ContinueDevInstaller, createContinueDevInstaller } from './continuedev-installer.js';
27
- export { V2Detector, createV2Detector, V2DataMigrator, createV2DataMigrator, V2ConfigMigrator, createV2ConfigMigrator, } from './migration/index.js';
28
27
  //# sourceMappingURL=index.js.map
@@ -6,6 +6,16 @@
6
6
  * Extracted from init-wizard.ts.
7
7
  */
8
8
  import type { AQEInitConfig, PretrainedLibrary } from './types.js';
9
+ /**
10
+ * Read AQE version directly from memory.db without full initialization.
11
+ * Returns undefined if no version is stored.
12
+ */
13
+ export declare function readVersionFromDb(dbPath: string): string | undefined;
14
+ /**
15
+ * Write AQE version to memory.db in _system namespace.
16
+ * Used by init wizard to mark installation version.
17
+ */
18
+ export declare function writeVersionToDb(projectRoot: string, version: string): Promise<boolean>;
9
19
  /**
10
20
  * Initialize the persistence database (REQUIRED).
11
21
  * Creates the SQLite database file with proper schema.
@@ -6,12 +6,98 @@
6
6
  * Extracted from init-wizard.ts.
7
7
  */
8
8
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
9
- import { join } from 'path';
9
+ import { join, dirname } from 'path';
10
10
  import { createSkillsInstaller } from './skills-installer.js';
11
11
  import { createAgentsInstaller } from './agents-installer.js';
12
12
  import { createN8nInstaller } from './n8n-installer.js';
13
13
  import { toErrorMessage } from '../shared/error-utils.js';
14
14
  import { openDatabase } from '../shared/safe-db.js';
15
+ import { safeJsonParse } from '../shared/safe-json.js';
16
+ // ============================================================================
17
+ // Version Management
18
+ // ============================================================================
19
+ /**
20
+ * Read AQE version directly from memory.db without full initialization.
21
+ * Returns undefined if no version is stored.
22
+ */
23
+ export function readVersionFromDb(dbPath) {
24
+ try {
25
+ const db = openDatabase(dbPath, { readonly: true, fileMustExist: true });
26
+ try {
27
+ const tableExists = db.prepare(`
28
+ SELECT name FROM sqlite_master
29
+ WHERE type='table' AND name='kv_store'
30
+ `).get();
31
+ if (!tableExists) {
32
+ db.close();
33
+ return undefined;
34
+ }
35
+ const row = db.prepare(`
36
+ SELECT value FROM kv_store
37
+ WHERE key = 'aqe_version' AND namespace = '_system'
38
+ `).get();
39
+ db.close();
40
+ if (row) {
41
+ return safeJsonParse(row.value);
42
+ }
43
+ return undefined;
44
+ }
45
+ catch {
46
+ db.close();
47
+ return undefined;
48
+ }
49
+ }
50
+ catch {
51
+ return undefined;
52
+ }
53
+ }
54
+ /**
55
+ * Write AQE version to memory.db in _system namespace.
56
+ * Used by init wizard to mark installation version.
57
+ */
58
+ export async function writeVersionToDb(projectRoot, version) {
59
+ const memoryDbPath = join(projectRoot, '.agentic-qe', 'memory.db');
60
+ try {
61
+ const dir = dirname(memoryDbPath);
62
+ if (!existsSync(dir)) {
63
+ mkdirSync(dir, { recursive: true });
64
+ }
65
+ const db = openDatabase(memoryDbPath);
66
+ try {
67
+ db.exec(`
68
+ CREATE TABLE IF NOT EXISTS kv_store (
69
+ key TEXT NOT NULL,
70
+ namespace TEXT NOT NULL,
71
+ value TEXT NOT NULL,
72
+ expires_at INTEGER,
73
+ created_at INTEGER DEFAULT (strftime('%s', 'now') * 1000),
74
+ PRIMARY KEY (namespace, key)
75
+ );
76
+ `);
77
+ const now = Date.now();
78
+ db.prepare(`
79
+ INSERT OR REPLACE INTO kv_store (key, namespace, value, created_at)
80
+ VALUES (?, '_system', ?, ?)
81
+ `).run('aqe_version', JSON.stringify(version), now);
82
+ db.prepare(`
83
+ INSERT OR REPLACE INTO kv_store (key, namespace, value, created_at)
84
+ VALUES (?, '_system', ?, ?)
85
+ `).run('init_timestamp', JSON.stringify(new Date().toISOString()), now);
86
+ db.close();
87
+ console.log(` ✓ Version ${version} written to memory.db`);
88
+ return true;
89
+ }
90
+ catch (err) {
91
+ db.close();
92
+ console.warn(` ⚠ Could not write version: ${toErrorMessage(err)}`);
93
+ return false;
94
+ }
95
+ }
96
+ catch (err) {
97
+ console.warn(` ⚠ Could not open memory.db: ${toErrorMessage(err)}`);
98
+ return false;
99
+ }
100
+ }
15
101
  // ============================================================================
16
102
  // Persistence Database
17
103
  // ============================================================================
@@ -6,11 +6,9 @@
6
6
  *
7
7
  * This is a facade module. Implementation details are extracted to:
8
8
  * - init-wizard-hooks.ts (hook configuration, MCP, CLAUDE.md generation)
9
- * - init-wizard-migration.ts (V2 detection, migration, config conversion)
10
- * - init-wizard-steps.ts (persistence, learning, workers, skills, agents, config)
9
+ * - init-wizard-steps.ts (persistence, learning, workers, skills, agents, config, version)
11
10
  */
12
11
  import type { InitResult, WizardStep, PretrainedLibrary } from './types.js';
13
- export type { V2DetectionResult } from './init-wizard-migration.js';
14
12
  export interface InitOrchestratorOptions {
15
13
  /** Project root directory */
16
14
  projectRoot: string;
@@ -31,8 +29,6 @@ export interface InitOrchestratorOptions {
31
29
  baseUrl?: string;
32
30
  apiKey?: string;
33
31
  };
34
- /** Automatically migrate from v2 if detected */
35
- autoMigrate?: boolean;
36
32
  }
37
33
  export declare class InitOrchestrator {
38
34
  private projectRoot;
@@ -49,10 +45,6 @@ export declare class InitOrchestrator {
49
45
  * Get wizard steps
50
46
  */
51
47
  getWizardSteps(): WizardStep[];
52
- /**
53
- * Handle V2 detection - returns early result if migration not auto, null otherwise.
54
- */
55
- private handleV2Detection;
56
48
  /**
57
49
  * Run a single initialization step with timing and status tracking
58
50
  */
@@ -6,16 +6,15 @@
6
6
  *
7
7
  * This is a facade module. Implementation details are extracted to:
8
8
  * - init-wizard-hooks.ts (hook configuration, MCP, CLAUDE.md generation)
9
- * - init-wizard-migration.ts (V2 detection, migration, config conversion)
10
- * - init-wizard-steps.ts (persistence, learning, workers, skills, agents, config)
9
+ * - init-wizard-steps.ts (persistence, learning, workers, skills, agents, config, version)
11
10
  */
12
11
  import { createDefaultConfig } from './types.js';
13
12
  import { createProjectAnalyzer } from './project-analyzer.js';
14
13
  import { createSelfConfigurator } from './self-configurator.js';
15
- import { detectV2Installation, runV2Migration, writeVersionToDb, } from './init-wizard-migration.js';
14
+ // Import from extracted modules
16
15
  import { configureHooks, configureMCP, generateCLAUDEmd, } from './init-wizard-hooks.js';
17
16
  import { toErrorMessage } from '../shared/error-utils.js';
18
- import { initializePersistenceDatabase, checkCodeIntelligenceIndex, runCodeIntelligenceScan, getKGEntryCount, initializeLearningSystem, startWorkers, installSkills, installAgents, installN8n, saveConfig, } from './init-wizard-steps.js';
17
+ import { initializePersistenceDatabase, checkCodeIntelligenceIndex, runCodeIntelligenceScan, getKGEntryCount, initializeLearningSystem, startWorkers, installSkills, installAgents, installN8n, saveConfig, writeVersionToDb, } from './init-wizard-steps.js';
19
18
  // ============================================================================
20
19
  // Wizard Step Definitions
21
20
  // ============================================================================
@@ -105,13 +104,6 @@ export class InitOrchestrator {
105
104
  async initialize() {
106
105
  const startTime = Date.now();
107
106
  try {
108
- // Step 0: Check for existing v2 installation
109
- const v2Detection = await detectV2Installation(this.projectRoot);
110
- if (v2Detection.detected) {
111
- const earlyResult = this.handleV2Detection(v2Detection, startTime);
112
- if (earlyResult)
113
- return earlyResult;
114
- }
115
107
  // Step 1: Analyze project
116
108
  const analysis = await this.runStep('Project Analysis', async () => {
117
109
  return await this.analyzer.analyze();
@@ -251,64 +243,6 @@ export class InitOrchestrator {
251
243
  getWizardSteps() {
252
244
  return WIZARD_STEPS;
253
245
  }
254
- /**
255
- * Handle V2 detection - returns early result if migration not auto, null otherwise.
256
- */
257
- handleV2Detection(v2Detection, startTime) {
258
- console.log('\n' + '='.repeat(60));
259
- console.log(' EXISTING V2 INSTALLATION DETECTED');
260
- console.log('='.repeat(60) + '\n');
261
- console.log('Found v2 installation at:');
262
- if (v2Detection.hasMemoryDb) {
263
- console.log(` - Memory DB: .agentic-qe/memory.db`);
264
- }
265
- if (v2Detection.hasConfig) {
266
- console.log(` - Config: .agentic-qe/config/`);
267
- }
268
- if (v2Detection.hasAgents) {
269
- console.log(` - Agents: .claude/agents/`);
270
- }
271
- console.log('');
272
- if (this.options.autoMigrate) {
273
- console.log('Auto-migrate mode enabled. Running migration...\n');
274
- // Fire and forget - the caller will await initialize() which runs migration inline
275
- runV2Migration(this.projectRoot, v2Detection).catch(() => { });
276
- return null;
277
- }
278
- // Warn and suggest migration
279
- console.log('RECOMMENDED: Run migration before init:\n');
280
- console.log(' npx aqe migrate status # Check what needs migration');
281
- console.log(' npx aqe migrate run --dry-run # Preview changes');
282
- console.log(' npx aqe migrate run # Execute migration\n');
283
- console.log('Or continue with:');
284
- console.log(' aqe init --auto-migrate # Auto-migrate during init\n');
285
- console.log('='.repeat(60) + '\n');
286
- return {
287
- success: false,
288
- config: createDefaultConfig('unknown', this.projectRoot),
289
- steps: [{
290
- step: 'V2 Detection',
291
- status: 'error',
292
- message: 'Existing v2 installation detected. Run migration first.',
293
- durationMs: Date.now() - startTime,
294
- }],
295
- summary: {
296
- projectAnalyzed: false,
297
- configGenerated: false,
298
- codeIntelligenceIndexed: 0,
299
- patternsLoaded: 0,
300
- skillsInstalled: 0,
301
- agentsInstalled: 0,
302
- hooksConfigured: false,
303
- mcpConfigured: false,
304
- claudeMdGenerated: false,
305
- workersStarted: 0,
306
- },
307
- totalDurationMs: Date.now() - startTime,
308
- timestamp: new Date(),
309
- v2Detected: true,
310
- };
311
- }
312
246
  /**
313
247
  * Run a single initialization step with timing and status tracking
314
248
  */
@@ -32,7 +32,6 @@ export class ModularInitOrchestrator {
32
32
  upgrade: options.upgrade,
33
33
  skipPatterns: options.skipPatterns,
34
34
  minimal: options.minimal,
35
- autoMigrate: options.autoMigrate,
36
35
  withN8n: options.withN8n,
37
36
  withOpenCode: options.withOpenCode,
38
37
  withKiro: options.withKiro,
@@ -27,33 +27,6 @@ export class DetectionPhase extends BasePhase {
27
27
  const freshInstall = !v2Detected && !v3Detected;
28
28
  // Store v2 detection in context for other phases
29
29
  context.v2Detection = v2Detection;
30
- if (v2Detected && !context.options.autoMigrate) {
31
- context.services.log('');
32
- context.services.log('═'.repeat(60));
33
- context.services.log('⚠️ EXISTING V2 INSTALLATION DETECTED');
34
- context.services.log('═'.repeat(60));
35
- context.services.log('');
36
- context.services.log('Found v2 installation at:');
37
- if (v2Detection.hasMemoryDb) {
38
- context.services.log(' • Memory DB: .agentic-qe/memory.db');
39
- }
40
- if (v2Detection.hasConfig) {
41
- context.services.log(' • Config: .agentic-qe/config/');
42
- }
43
- if (v2Detection.hasAgents) {
44
- context.services.log(' • Agents: .claude/agents/');
45
- }
46
- context.services.log('');
47
- context.services.log('📋 RECOMMENDED: Run with --auto-migrate:');
48
- context.services.log(' aqe init --auto-migrate');
49
- context.services.log('');
50
- return {
51
- v2Detected: true,
52
- v3Detected,
53
- freshInstall: false,
54
- v2Detection,
55
- };
56
- }
57
30
  return {
58
31
  v2Detected,
59
32
  v3Detected,
@@ -285,23 +285,24 @@ export class HooksPhase extends BasePhase {
285
285
  */
286
286
  const fs = require('fs');
287
287
  const path = require('path');
288
- const { execSync } = require('child_process');
288
+ const { execFileSync } = require('child_process');
289
289
 
290
- function q(cmd, d) { try { return execSync(cmd, { encoding: 'utf-8', timeout: 3000 }).trim(); } catch { return d || ''; } }
290
+ function q(bin, args, d) { try { return execFileSync(bin, args, { encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] }).trim(); } catch { return d || ''; } }
291
291
 
292
- const dir = process.cwd();
292
+ const dir = path.resolve(__dirname, '..', '..');
293
293
  const dbPath = path.join(dir, '.agentic-qe', 'memory.db');
294
294
  let patterns = 0;
295
295
  try {
296
296
  if (fs.existsSync(dbPath)) {
297
297
  const Database = require('better-sqlite3');
298
298
  const db = new Database(dbPath, { readonly: true, fileMustExist: true });
299
+ db.pragma('busy_timeout = 5000');
299
300
  patterns = db.prepare('SELECT COUNT(*) AS c FROM qe_patterns').get()?.c || 0;
300
301
  db.close();
301
302
  }
302
303
  } catch { /* ignore */ }
303
304
 
304
- const branch = q('git branch --show-current 2>/dev/null');
305
+ const branch = q('git', ['branch', '--show-current']);
305
306
  const branchStr = branch ? \` \\x1b[34m⎇ \${branch}\\x1b[0m\` : '';
306
307
  const patStr = patterns > 0 ? \` \\x1b[35m🎓 \${patterns} patterns\\x1b[0m\` : '';
307
308
 
@@ -321,11 +322,12 @@ console.log(\`\\x1b[1m\\x1b[35m▊ Agentic QE v3\\x1b[0m\${branchStr}\${patStr}\
321
322
  * node brain-checkpoint.cjs export # Export brain to aqe.rvf (session-end)
322
323
  * node brain-checkpoint.cjs verify # Verify aqe.rvf exists (session-start)
323
324
  */
324
- const { execSync } = require('child_process');
325
+ const { execFileSync } = require('child_process');
325
326
  const fs = require('fs');
326
327
  const path = require('path');
327
328
 
328
- const AQE_DIR = path.join(process.cwd(), '.agentic-qe');
329
+ const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
330
+ const AQE_DIR = path.join(PROJECT_ROOT, '.agentic-qe');
329
331
  const RVF_PATH = path.join(AQE_DIR, 'aqe.rvf');
330
332
  const DB_PATH = path.join(AQE_DIR, 'memory.db');
331
333
  const MAX_AGE_HOURS = 24;
@@ -338,8 +340,8 @@ function exportBrain() {
338
340
  if (fs.existsSync(RVF_PATH)) fs.unlinkSync(RVF_PATH);
339
341
  const idmap = RVF_PATH + '.idmap.json';
340
342
  if (fs.existsSync(idmap)) fs.unlinkSync(idmap);
341
- const result = execSync(
342
- 'npx agentic-qe brain export -o "' + RVF_PATH + '" --format rvf 2>&1',
343
+ const result = execFileSync(
344
+ 'npx', ['agentic-qe', 'brain', 'export', '-o', RVF_PATH, '--format', 'rvf'],
343
345
  { timeout: 60000, encoding: 'utf-8' }
344
346
  );
345
347
  const m = result.match(/Patterns:\\s+(\\d+)/);
@@ -496,7 +498,7 @@ if (process.argv.includes('--json')) process.stdout.write(JSON.stringify(result)
496
498
  hooks: [
497
499
  {
498
500
  type: 'command',
499
- command: 'node .claude/helpers/brain-checkpoint.cjs verify --json',
501
+ command: 'node "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.claude/helpers/brain-checkpoint.cjs" verify --json',
500
502
  timeout: 5000,
501
503
  continueOnError: true,
502
504
  },
@@ -518,7 +520,7 @@ if (process.argv.includes('--json')) process.stdout.write(JSON.stringify(result)
518
520
  hooks: [
519
521
  {
520
522
  type: 'command',
521
- command: 'node .claude/helpers/brain-checkpoint.cjs export --json',
523
+ command: 'node "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.claude/helpers/brain-checkpoint.cjs" export --json',
522
524
  timeout: 60000,
523
525
  continueOnError: true,
524
526
  },
@@ -73,7 +73,6 @@ export interface InitOptions {
73
73
  /** Minimal configuration (no skills, patterns, workers) */
74
74
  minimal?: boolean;
75
75
  /** Automatically migrate from v2 if detected */
76
- autoMigrate?: boolean;
77
76
  /** Install n8n workflow testing platform */
78
77
  withN8n?: boolean;
79
78
  /** N8n API configuration */
@@ -97,7 +97,7 @@ export function generateV3SettingsSections(config) {
97
97
  },
98
98
  statusLine: {
99
99
  type: 'command',
100
- command: 'node .claude/helpers/statusline-v3.cjs 2>/dev/null || echo "▊ Agentic QE v3"',
100
+ command: 'node "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.claude/helpers/statusline-v3.cjs" 2>/dev/null || echo "▊ Agentic QE v3"',
101
101
  refreshMs: 5000,
102
102
  enabled: true,
103
103
  },
@@ -195,7 +195,13 @@ export function importBrainFromRvf(db, rvfPath, options) {
195
195
  if (!kernel || !kernel.image) {
196
196
  throw new Error('No brain data found in RVF file (missing kernel segment)');
197
197
  }
198
- const brainData = JSON.parse(kernel.image.toString('utf-8'));
198
+ let brainData;
199
+ try {
200
+ brainData = JSON.parse(kernel.image.toString('utf-8'));
201
+ }
202
+ catch (parseErr) {
203
+ throw new Error(`Failed to parse brain kernel data as JSON: ${parseErr instanceof Error ? parseErr.message : parseErr}`);
204
+ }
199
205
  if (options.dryRun) {
200
206
  let total = 0;
201
207
  if (brainData.tables) {
@@ -296,7 +302,13 @@ export function brainInfoFromRvf(rvfPath) {
296
302
  throw new Error('No brain data found in RVF file');
297
303
  }
298
304
  const brainJson = kernel.image.toString('utf-8');
299
- const brainData = JSON.parse(brainJson);
305
+ let brainData;
306
+ try {
307
+ brainData = JSON.parse(brainJson);
308
+ }
309
+ catch (parseErr) {
310
+ throw new Error(`Failed to parse brain kernel data as JSON: ${parseErr instanceof Error ? parseErr.message : parseErr}`);
311
+ }
300
312
  const status = rvf.status();
301
313
  const fileSize = statSync(filePath).size;
302
314
  const t = brainData.tables;
@@ -21,7 +21,7 @@
21
21
  * - unified-memory-hnsw.ts: HNSW index + BinaryHeap
22
22
  * - unified-memory.ts: UnifiedMemoryManager class (this file, facade)
23
23
  */
24
- import Database from 'better-sqlite3';
24
+ import { openDatabase as openSafeDatabase } from '../shared/safe-db.js';
25
25
  import { safeJsonParse } from '../shared/safe-json.js';
26
26
  import { toErrorMessage } from '../shared/error-utils.js';
27
27
  import * as fs from 'fs';
@@ -278,13 +278,12 @@ export class UnifiedMemoryManager {
278
278
  dbSizeBefore = newest.size;
279
279
  }
280
280
  }
281
- this.db = new Database(this.config.dbPath);
282
- if (this.config.walMode) {
283
- this.db.pragma('journal_mode = WAL');
284
- }
281
+ this.db = openSafeDatabase(this.config.dbPath, {
282
+ walMode: this.config.walMode,
283
+ busyTimeout: this.config.busyTimeout,
284
+ });
285
285
  this.db.pragma(`mmap_size = ${this.config.mmapSize}`);
286
286
  this.db.pragma(`cache_size = ${this.config.cacheSize}`);
287
- this.db.pragma(`busy_timeout = ${this.config.busyTimeout}`);
288
287
  this.db.pragma('foreign_keys = ON');
289
288
  await this.runMigrations();
290
289
  // DATA LOSS PREVENTION: After migration, if the DB existed before and was
@@ -14,6 +14,8 @@
14
14
  import { v4 as uuidv4 } from 'uuid';
15
15
  import { getUnifiedMemory } from '../kernel/unified-memory.js';
16
16
  import { toErrorMessage } from '../shared/error-utils.js';
17
+ import { createLogger } from '../logging/logger-factory.js';
18
+ const ecLogger = createLogger('ExperienceCapture');
17
19
  // ============================================================================
18
20
  // Active Experience Tracking
19
21
  // ============================================================================
@@ -168,6 +170,26 @@ async function doInitialize() {
168
170
  CREATE INDEX IF NOT EXISTS idx_captured_exp_agent ON captured_experiences(agent);
169
171
  CREATE INDEX IF NOT EXISTS idx_captured_exp_completed ON captured_experiences(completed_at DESC);
170
172
  `);
173
+ // Add consolidation columns if missing (needed by ExperienceConsolidator)
174
+ const colNames = new Set(db.prepare('PRAGMA table_info(captured_experiences)').all().map(c => c.name));
175
+ const consolidationCols = [
176
+ ['application_count', 'INTEGER DEFAULT 0'],
177
+ ['avg_token_savings', 'REAL DEFAULT 0'],
178
+ ['embedding', 'BLOB'],
179
+ ['embedding_dimension', 'INTEGER'],
180
+ ['tags', 'TEXT'],
181
+ ['last_applied_at', 'TEXT'],
182
+ ['consolidated_into', 'TEXT DEFAULT NULL'],
183
+ ['consolidation_count', 'INTEGER DEFAULT 1'],
184
+ ['quality_updated_at', 'TEXT DEFAULT NULL'],
185
+ ['reuse_success_count', 'INTEGER DEFAULT 0'],
186
+ ['reuse_failure_count', 'INTEGER DEFAULT 0'],
187
+ ];
188
+ for (const [col, def] of consolidationCols) {
189
+ if (!colNames.has(col)) {
190
+ db.exec(`ALTER TABLE captured_experiences ADD COLUMN ${col} ${def}`);
191
+ }
192
+ }
171
193
  }
172
194
  // Start periodic cleanup of stale experiences
173
195
  startCleanupTimer();
@@ -269,7 +291,7 @@ async function persistExperience(context, outcome) {
269
291
  `);
270
292
  stmt.run(outcome.id, context.task, context.agent, context.domain, outcome.success ? 1 : 0, outcome.quality, outcome.durationMs, context.modelTier || null, safeJsonStringify(context.routing), safeJsonStringify(outcome.steps), safeJsonStringify(outcome.result), outcome.error || null, context.startedAt.toISOString(), 'middleware');
271
293
  // Fire-and-forget: compute and store embedding for this experience
272
- computeExperienceEmbedding(db, outcome.id, context.task, context.domain).catch(() => { });
294
+ computeExperienceEmbedding(db, outcome.id, context.task, context.domain).catch((e) => { ecLogger.warn('Embedding computation failed', { error: e instanceof Error ? e.message : String(e), experienceId: outcome.id, domain: context.domain }); });
273
295
  }
274
296
  catch (error) {
275
297
  console.error('[ExperienceCaptureMiddleware] Failed to persist experience:', error);