@triedotdev/mcp 1.0.138 → 1.0.140
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.
- package/README.md +184 -38
- package/dist/{autonomy-config-TZ6HF4FA.js → autonomy-config-ZCOSTMPD.js} +2 -2
- package/dist/{chunk-X3F5QDER.js → chunk-4O2KRHK4.js} +934 -132
- package/dist/chunk-4O2KRHK4.js.map +1 -0
- package/dist/{chunk-J5EMP4XW.js → chunk-5KJ4UJOY.js} +9 -4
- package/dist/chunk-5KJ4UJOY.js.map +1 -0
- package/dist/chunk-62POBLFC.js +1925 -0
- package/dist/chunk-62POBLFC.js.map +1 -0
- package/dist/{chunk-GFFUDJMK.js → chunk-75ADWWUF.js} +13 -13
- package/dist/chunk-75ADWWUF.js.map +1 -0
- package/dist/{chunk-D3AS5LY7.js → chunk-7OJ6JIPL.js} +39 -604
- package/dist/chunk-7OJ6JIPL.js.map +1 -0
- package/dist/{chunk-3RRXWX3V.js → chunk-AF2APASP.js} +38 -4
- package/dist/{chunk-3RRXWX3V.js.map → chunk-AF2APASP.js.map} +1 -1
- package/dist/{chunk-QSWUPSLK.js → chunk-FH335WL5.js} +9 -1
- package/dist/chunk-FH335WL5.js.map +1 -0
- package/dist/{chunk-Y32FM3MR.js → chunk-FPEMP54L.js} +21 -15
- package/dist/chunk-FPEMP54L.js.map +1 -0
- package/dist/{chunk-EDDT4ZIH.js → chunk-GXF6JOCN.js} +21 -323
- package/dist/chunk-GXF6JOCN.js.map +1 -0
- package/dist/chunk-LD7ZEFNY.js +132 -0
- package/dist/chunk-LD7ZEFNY.js.map +1 -0
- package/dist/chunk-NKHO34UZ.js +467 -0
- package/dist/chunk-NKHO34UZ.js.map +1 -0
- package/dist/{chunk-YOKQ25IW.js → chunk-OQ4A3RDY.js} +14 -14
- package/dist/{chunk-6LLH3TBZ.js → chunk-UOSTOLU7.js} +12 -12
- package/dist/{chunk-67GSG2ST.js → chunk-XTTZAQWJ.js} +18 -15
- package/dist/chunk-XTTZAQWJ.js.map +1 -0
- package/dist/{chunk-FOCXXIXY.js → chunk-YEIJW6X6.js} +2 -2
- package/dist/chunk-YOJGSRZK.js +216 -0
- package/dist/chunk-YOJGSRZK.js.map +1 -0
- package/dist/cli/main.js +573 -59
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +15 -13
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{client-JTU5TRLB.js → client-INNE2GGZ.js} +2 -2
- package/dist/{codebase-index-FNJ4GCBE.js → codebase-index-5SEOESWM.js} +3 -3
- package/dist/fast-analyzer-AYLZB5TW.js +216 -0
- package/dist/fast-analyzer-AYLZB5TW.js.map +1 -0
- package/dist/github-ingester-J2ZFYXVE.js +11 -0
- package/dist/{goal-manager-6BJQ36AH.js → goal-manager-ZBWKWEML.js} +3 -3
- package/dist/{goal-validator-GISXYANK.js → goal-validator-HNXXUCPW.js} +3 -3
- package/dist/{graph-X2FMRQLG.js → graph-J4OGTYCO.js} +2 -2
- package/dist/{hypothesis-K3KQJOXJ.js → hypothesis-JCUMZKTG.js} +3 -3
- package/dist/index.js +1090 -108
- package/dist/index.js.map +1 -1
- package/dist/{issue-store-BO5OWLJW.js → issue-store-LZWZIGM7.js} +2 -2
- package/dist/linear-ingester-JRDQAIAA.js +11 -0
- package/dist/linear-ingester-JRDQAIAA.js.map +1 -0
- package/dist/{trie-agent-XMSGMD7E.js → trie-agent-M6PHM6UD.js} +10 -10
- package/dist/trie-agent-M6PHM6UD.js.map +1 -0
- package/package.json +15 -8
- package/dist/chunk-67GSG2ST.js.map +0 -1
- package/dist/chunk-D3AS5LY7.js.map +0 -1
- package/dist/chunk-EDDT4ZIH.js.map +0 -1
- package/dist/chunk-GFFUDJMK.js.map +0 -1
- package/dist/chunk-J5EMP4XW.js.map +0 -1
- package/dist/chunk-QSWUPSLK.js.map +0 -1
- package/dist/chunk-X3F5QDER.js.map +0 -1
- package/dist/chunk-Y32FM3MR.js.map +0 -1
- package/dist/chunk-Z2P4WST6.js +0 -883
- package/dist/chunk-Z2P4WST6.js.map +0 -1
- /package/dist/{autonomy-config-TZ6HF4FA.js.map → autonomy-config-ZCOSTMPD.js.map} +0 -0
- /package/dist/{chunk-YOKQ25IW.js.map → chunk-OQ4A3RDY.js.map} +0 -0
- /package/dist/{chunk-6LLH3TBZ.js.map → chunk-UOSTOLU7.js.map} +0 -0
- /package/dist/{chunk-FOCXXIXY.js.map → chunk-YEIJW6X6.js.map} +0 -0
- /package/dist/{client-JTU5TRLB.js.map → client-INNE2GGZ.js.map} +0 -0
- /package/dist/{codebase-index-FNJ4GCBE.js.map → codebase-index-5SEOESWM.js.map} +0 -0
- /package/dist/{goal-manager-6BJQ36AH.js.map → github-ingester-J2ZFYXVE.js.map} +0 -0
- /package/dist/{goal-validator-GISXYANK.js.map → goal-manager-ZBWKWEML.js.map} +0 -0
- /package/dist/{graph-X2FMRQLG.js.map → goal-validator-HNXXUCPW.js.map} +0 -0
- /package/dist/{hypothesis-K3KQJOXJ.js.map → graph-J4OGTYCO.js.map} +0 -0
- /package/dist/{issue-store-BO5OWLJW.js.map → hypothesis-JCUMZKTG.js.map} +0 -0
- /package/dist/{trie-agent-XMSGMD7E.js.map → issue-store-LZWZIGM7.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/checkpoint.ts","../src/utils/trie-init.ts","../src/context/sync.ts","../src/utils/errors.ts","../src/skills/audit-logger.ts","../src/agent/git.ts","../src/utils/command-runner.ts","../src/agent/confidence.ts","../src/agent/learning.ts","../src/agent/learning-engine.ts","../src/agent/perceive.ts","../src/agent/diff-analyzer.ts","../src/agent/risk-scorer.ts","../src/agent/pattern-matcher.ts","../src/orchestrator/triager.ts","../src/utils/parallel-executor.ts","../src/utils/cache-manager.ts","../src/orchestrator/executor.ts","../src/agent/reason.ts"],"sourcesContent":["/**\n * Checkpoint CLI\n * \n * Save your work context to .trie/ without running a full scan.\n * Think of it as a quick save - captures what you're working on.\n */\n\nimport { existsSync } from 'fs';\nimport { mkdir, writeFile, readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from '../utils/workspace.js';\n\nexport interface Checkpoint {\n id: string;\n timestamp: string;\n message?: string;\n files: string[];\n notes?: string;\n createdBy: 'cli' | 'mcp';\n}\n\nexport interface CheckpointLog {\n checkpoints: Checkpoint[];\n lastCheckpoint?: string;\n}\n\n/**\n * Save a checkpoint\n */\nexport async function saveCheckpoint(options: {\n message?: string;\n files?: string[];\n notes?: string;\n workDir?: string;\n createdBy?: 'cli' | 'mcp';\n}): Promise<Checkpoint> {\n const workDir = options.workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(workDir);\n const checkpointPath = join(trieDir, 'checkpoints.json');\n \n await mkdir(trieDir, { recursive: true });\n \n // Load existing checkpoints\n let log: CheckpointLog = { checkpoints: [] };\n try {\n if (existsSync(checkpointPath)) {\n log = JSON.parse(await readFile(checkpointPath, 'utf-8'));\n }\n } catch {\n log = { checkpoints: [] };\n }\n \n // Create new checkpoint\n const checkpoint: Checkpoint = {\n id: `cp-${Date.now().toString(36)}`,\n timestamp: new Date().toISOString(),\n files: options.files || [],\n createdBy: options.createdBy || 'cli',\n };\n if (options.message) checkpoint.message = options.message;\n if (options.notes) checkpoint.notes = options.notes;\n \n // Add to log\n log.checkpoints.push(checkpoint);\n log.lastCheckpoint = checkpoint.id;\n \n // Keep last 50 checkpoints\n if (log.checkpoints.length > 50) {\n log.checkpoints = log.checkpoints.slice(-50);\n }\n \n // Save\n await writeFile(checkpointPath, JSON.stringify(log, null, 2));\n \n // Also update AGENTS.md with checkpoint note\n await updateAgentsMdWithCheckpoint(checkpoint, workDir);\n \n return checkpoint;\n}\n\n/**\n * List checkpoints\n */\nexport async function listCheckpoints(workDir?: string): Promise<Checkpoint[]> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const checkpointPath = join(getTrieDirectory(dir), 'checkpoints.json');\n \n try {\n if (existsSync(checkpointPath)) {\n const log: CheckpointLog = JSON.parse(await readFile(checkpointPath, 'utf-8'));\n return log.checkpoints;\n }\n } catch {\n // File doesn't exist or is corrupted\n }\n \n return [];\n}\n\n/**\n * Get the last checkpoint\n */\nexport async function getLastCheckpoint(workDir?: string): Promise<Checkpoint | null> {\n const checkpoints = await listCheckpoints(workDir);\n const last = checkpoints[checkpoints.length - 1];\n return last ?? null;\n}\n\n/**\n * Update AGENTS.md with checkpoint info\n */\nasync function updateAgentsMdWithCheckpoint(checkpoint: Checkpoint, workDir: string): Promise<void> {\n const agentsPath = join(getTrieDirectory(workDir), 'AGENTS.md');\n \n let content = '';\n try {\n if (existsSync(agentsPath)) {\n content = await readFile(agentsPath, 'utf-8');\n }\n } catch {\n content = '';\n }\n \n // Find or create checkpoint section\n const checkpointSection = `\n## Last Checkpoint\n\n- **ID:** ${checkpoint.id}\n- **Time:** ${checkpoint.timestamp}\n${checkpoint.message ? `- **Message:** ${checkpoint.message}` : ''}\n${checkpoint.files.length > 0 ? `- **Files:** ${checkpoint.files.length} files` : ''}\n${checkpoint.notes ? `- **Notes:** ${checkpoint.notes}` : ''}\n`;\n \n // Replace existing checkpoint section or append\n const checkpointRegex = /## Last Checkpoint[\\s\\S]*?(?=\\n## |\\n---|\\Z)/;\n if (checkpointRegex.test(content)) {\n content = content.replace(checkpointRegex, checkpointSection.trim());\n } else {\n content = content.trim() + '\\n\\n' + checkpointSection.trim() + '\\n';\n }\n \n await writeFile(agentsPath, content);\n}\n\n/**\n * CLI handler for checkpoint command\n */\nexport async function handleCheckpointCommand(args: string[]): Promise<void> {\n const subcommand = args[0] || 'save';\n \n switch (subcommand) {\n case 'save': {\n // Parse options\n let message: string | undefined;\n let notes: string | undefined;\n const files: string[] = [];\n \n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n if (arg === '-m' || arg === '--message') {\n message = args[++i] ?? '';\n } else if (arg === '-n' || arg === '--notes') {\n notes = args[++i] ?? '';\n } else if (arg === '-f' || arg === '--file') {\n const file = args[++i];\n if (file) files.push(file);\n } else if (arg && !arg.startsWith('-')) {\n // Treat as message if no flag\n message = arg;\n }\n }\n \n const opts: { message?: string; files?: string[]; notes?: string } = { files };\n if (message) opts.message = message;\n if (notes) opts.notes = notes;\n const checkpoint = await saveCheckpoint(opts);\n \n console.log('\\n Checkpoint saved\\n');\n console.log(` ID: ${checkpoint.id}`);\n console.log(` Time: ${checkpoint.timestamp}`);\n if (checkpoint.message) {\n console.log(` Message: ${checkpoint.message}`);\n }\n if (checkpoint.files.length > 0) {\n console.log(` Files: ${checkpoint.files.join(', ')}`);\n }\n console.log('\\n Context saved to .trie/\\n');\n break;\n }\n \n case 'list': {\n const checkpoints = await listCheckpoints();\n \n if (checkpoints.length === 0) {\n console.log('\\n No checkpoints yet. Run `trie checkpoint` to save one.\\n');\n return;\n }\n \n console.log('\\n Checkpoints:\\n');\n for (const cp of checkpoints.slice(-10).reverse()) {\n const date = new Date(cp.timestamp).toLocaleString();\n console.log(` ${cp.id} ${date} ${cp.message || '(no message)'}`);\n }\n console.log('');\n break;\n }\n \n case 'last': {\n const checkpoint = await getLastCheckpoint();\n \n if (!checkpoint) {\n console.log('\\n No checkpoints yet. Run `trie checkpoint` to save one.\\n');\n return;\n }\n \n console.log('\\n Last Checkpoint:\\n');\n console.log(` ID: ${checkpoint.id}`);\n console.log(` Time: ${new Date(checkpoint.timestamp).toLocaleString()}`);\n if (checkpoint.message) {\n console.log(` Message: ${checkpoint.message}`);\n }\n if (checkpoint.notes) {\n console.log(` Notes: ${checkpoint.notes}`);\n }\n if (checkpoint.files.length > 0) {\n console.log(` Files: ${checkpoint.files.join(', ')}`);\n }\n console.log('');\n break;\n }\n \n default:\n console.log(`\n Usage: trie checkpoint [command] [options]\n\n Commands:\n save [message] Save a checkpoint (default)\n list List recent checkpoints\n last Show the last checkpoint\n\n Options:\n -m, --message Checkpoint message\n -n, --notes Additional notes\n -f, --file File to include (can be repeated)\n\n Examples:\n trie checkpoint \"finished auth flow\"\n trie checkpoint save -m \"WIP: payment integration\" -n \"needs testing\"\n trie checkpoint list\n`);\n }\n}\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from './workspace.js';\n\nconst INIT_MARKERS = [\n 'PROJECT.md',\n 'RULES.md',\n 'TEAM.md',\n 'BOOTSTRAP.md',\n 'AGENTS.md',\n 'config.json',\n];\n\nexport function isTrieInitialized(workDir?: string): boolean {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(dir);\n return INIT_MARKERS.some((marker) => existsSync(join(trieDir, marker)));\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { getTrieDirectory } from '../utils/workspace.js';\n\nimport { ContextGraph } from './graph.js';\nimport type { ContextSnapshot } from './types.js';\n\nconst DEFAULT_JSON_NAME = 'context.json';\n\nexport async function exportToJson(graph: ContextGraph, targetPath?: string): Promise<string> {\n const snapshot = await graph.getSnapshot();\n const json = JSON.stringify(snapshot, null, 2);\n\n const outputPath = targetPath ?? path.join(getTrieDirectory(graph.projectRoot), DEFAULT_JSON_NAME);\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, json, 'utf8');\n\n return json;\n}\n\nexport async function importFromJson(\n graph: ContextGraph,\n json: string,\n sourcePath?: string\n): Promise<void> {\n const payload =\n json.trim().length > 0\n ? json\n : await fs.readFile(sourcePath ?? path.join(getTrieDirectory(graph.projectRoot), DEFAULT_JSON_NAME), 'utf8');\n\n const snapshot = JSON.parse(payload) as ContextSnapshot;\n await graph.applySnapshot(snapshot);\n}\n","export class TrieError extends Error {\n code: string;\n recoverable: boolean;\n userMessage: string;\n\n constructor(message: string, code: string, userMessage: string, recoverable = true) {\n super(message);\n this.code = code;\n this.recoverable = recoverable;\n this.userMessage = userMessage;\n }\n}\n\nexport class GraphError extends TrieError {\n constructor(message: string) {\n super(\n message,\n 'GRAPH_ERROR',\n 'Trie had trouble accessing its memory. Try again or re-run trie reconcile.',\n true\n );\n }\n}\n\nexport class GitError extends TrieError {\n constructor(message: string) {\n super(\n message,\n 'GIT_ERROR',\n 'Git info is unavailable. Is this a git repo? Commit once, or pass --files to trie check.',\n true\n );\n }\n}\n\nexport class NetworkError extends TrieError {\n constructor(message: string) {\n super(\n message,\n 'NETWORK_ERROR',\n 'Network unavailable. Running in offline mode; AI calls skipped.',\n true\n );\n }\n}\n\nexport class MissingAPIKeyError extends TrieError {\n constructor(message = 'Missing ANTHROPIC_API_KEY') {\n super(\n message,\n 'MISSING_API_KEY',\n 'No API key detected. Set ANTHROPIC_API_KEY for AI-powered analysis (deeper issue detection, smarter fixes). Running in pattern-only mode.',\n true\n );\n }\n}\n\nexport function formatFriendlyError(error: unknown): { userMessage: string; code: string } {\n if (error instanceof TrieError) {\n return { userMessage: error.userMessage, code: error.code };\n }\n return {\n userMessage: 'Something went wrong. Try again or run with --offline.',\n code: 'UNKNOWN'\n };\n}\n","/**\n * Audit logger stub\n * Audit functionality has been integrated into decision ledger\n */\n\nexport interface AuditStatistics {\n totalScans: number;\n totalIssues: number;\n criticalCount: number;\n seriousCount: number;\n moderateCount: number;\n lowCount: number;\n totalExecutions: number;\n successfulExecutions: number;\n failedExecutions: number;\n uniqueSkills: number;\n totalCommands: number;\n blockedCommands: number;\n totalNetworkCalls: number;\n blockedNetworkCalls: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n command: string;\n status: string;\n commands?: ExecutedCommand[];\n}\n\nexport interface ExecutedCommand {\n command: string;\n timestamp: string;\n exitCode?: number;\n duration?: number;\n stdout?: string;\n stderr?: string;\n}\n\nexport interface SkillExecution {\n skillName: string;\n skillSource: string;\n triggeredBy: 'scan' | 'mcp' | 'cli' | 'watch' | 'manual';\n targetPath: string;\n startedAt: string;\n completedAt?: string;\n success?: boolean;\n error?: string;\n commands?: ExecutedCommand[];\n}\n\nexport function formatAuditLog(_entry: AuditEntry): string {\n return 'Audit logging has been integrated into the decision ledger';\n}\n\nexport function getAuditStatistics(): AuditStatistics {\n return {\n totalScans: 0,\n totalIssues: 0,\n criticalCount: 0,\n seriousCount: 0,\n moderateCount: 0,\n lowCount: 0,\n totalExecutions: 0,\n successfulExecutions: 0,\n failedExecutions: 0,\n uniqueSkills: 0,\n totalCommands: 0,\n blockedCommands: 0,\n totalNetworkCalls: 0,\n blockedNetworkCalls: 0,\n };\n}\n\nexport function createAuditEntry(\n skillName: string, \n skillSource: string, \n triggeredBy: SkillExecution['triggeredBy'], \n targetPath: string\n): SkillExecution {\n return {\n skillName,\n skillSource,\n triggeredBy,\n targetPath,\n startedAt: new Date().toISOString(),\n commands: [],\n };\n}\n\nexport function completeAuditEntry(\n entry: SkillExecution, \n success: boolean, \n error?: string\n): SkillExecution {\n const result: SkillExecution = {\n ...entry,\n completedAt: new Date().toISOString(),\n success,\n };\n if (error !== undefined) {\n result.error = error;\n }\n return result;\n}\n\nexport async function logSkillExecution(_execution: SkillExecution): Promise<void> {\n // Stub - no-op\n}\n\nexport async function getRecentAuditLogs(_limit: number = 10): Promise<AuditEntry[]> {\n return [];\n}\n\nexport async function getSkillAuditLogs(_skillName: string): Promise<AuditEntry[]> {\n return [];\n}\n","import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { runExecFile } from '../utils/command-runner.js';\n\nexport interface Commit {\n hash: string;\n author: string;\n date: string;\n message: string;\n}\n\nexport interface Change {\n path: string;\n status: string;\n oldPath?: string;\n}\n\nasync function execGit(args: string[], cwd: string): Promise<string | null> {\n try {\n const { stdout } = await runExecFile(\n 'git',\n ['-C', cwd, ...args],\n { actor: 'internal:git', triggeredBy: 'manual', targetPath: cwd },\n { maxBuffer: 10 * 1024 * 1024, captureOutput: false }\n );\n return stdout.trim();\n } catch (error: any) {\n const stderr: string | undefined = error?.stderr?.toString();\n // Gracefully handle non-git directories and repos with no commits\n if (stderr?.includes('not a git repository') || stderr?.includes('does not have any commits')) {\n return null;\n }\n throw error;\n }\n}\n\nasync function ensureRepo(projectPath: string): Promise<boolean> {\n const result = await execGit(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\nfunction parseNameStatus(output: string): Change[] {\n return output\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const parts = line.split('\\t');\n const status = parts[0] ?? '';\n const filePath = parts[1] ?? '';\n const oldPath = parts[2];\n const change: Change = { status, path: filePath };\n if (oldPath) change.oldPath = oldPath;\n return change;\n })\n .filter((entry) => entry.path.length > 0);\n}\n\nexport async function getRecentCommits(projectPath: string, limit: number): Promise<Commit[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const output = await execGit(\n ['log', `-n`, String(limit), '--pretty=format:%H%x09%an%x09%ad%x09%s', '--date=iso'],\n projectPath\n );\n\n if (!output) return [];\n\n return output.split('\\n').map((line) => {\n const [hash, author, date, message] = line.split('\\t');\n return { hash, author, date, message } as Commit;\n });\n}\n\nexport async function getLastCommit(projectPath: string): Promise<Commit | null> {\n const commits = await getRecentCommits(projectPath, 1);\n return commits[0] ?? null;\n}\n\nexport async function getStagedChanges(projectPath: string): Promise<Change[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const output = await execGit(['diff', '--cached', '--name-status'], projectPath);\n if (!output) return [];\n return parseNameStatus(output);\n}\n\nexport async function getUncommittedChanges(projectPath: string): Promise<Change[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const changes: Change[] = [];\n\n const unstaged = await execGit(['diff', '--name-status'], projectPath);\n if (unstaged) {\n changes.push(...parseNameStatus(unstaged));\n }\n\n const untracked = await execGit(['ls-files', '--others', '--exclude-standard'], projectPath);\n if (untracked) {\n changes.push(\n ...untracked\n .split('\\n')\n .map((p) => p.trim())\n .filter(Boolean)\n .map((p) => ({ status: '??', path: p }))\n );\n }\n\n return changes;\n}\n\n/**\n * Get a flat list of changed file paths in the working tree.\n * Convenience helper used by tooling (e.g. cache invalidation).\n *\n * Returns null if not a git repository.\n */\nexport async function getGitChangedFiles(projectPath: string): Promise<string[] | null> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return null;\n\n const [staged, uncommitted] = await Promise.all([\n getStagedChanges(projectPath).catch(() => []),\n getUncommittedChanges(projectPath).catch(() => []),\n ]);\n\n const paths = new Set<string>();\n for (const change of [...staged, ...uncommitted]) {\n if (change.path) paths.add(change.path);\n if (change.oldPath) paths.add(change.oldPath);\n }\n\n return [...paths];\n}\n\nexport async function getDiff(projectPath: string, commitHash: string): Promise<string> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return '';\n\n const diff = await execGit(['show', commitHash, '--unified=3', '--no-color'], projectPath);\n return diff ?? '';\n}\n\nexport async function getWorkingTreeDiff(projectPath: string, stagedOnly = false): Promise<string> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return '';\n\n const args = stagedOnly ? ['diff', '--cached', '--unified=3', '--no-color'] : ['diff', '--unified=3', '--no-color'];\n const diff = await execGit(args, projectPath);\n return diff ?? '';\n}\n\nexport async function getUnpushedCommits(projectPath: string): Promise<Commit[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n // Handles detached HEAD by falling back to HEAD if upstream missing\n const upstream = await execGit(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], projectPath);\n if (!upstream) {\n return getRecentCommits(projectPath, 10);\n }\n\n const output = await execGit(['log', `${upstream}..HEAD`, '--pretty=format:%H%x09%an%x09%ad%x09%s', '--date=iso'], projectPath);\n if (!output) return [];\n\n return output.split('\\n').filter(Boolean).map((line) => {\n const [hash, author, date, message] = line.split('\\t');\n return { hash, author, date, message } as Commit;\n });\n}\n\nexport function resolveRepoPath(projectPath: string): string {\n const gitDir = path.join(projectPath, '.git');\n if (existsSync(gitDir)) return projectPath;\n return projectPath;\n}\n\n/**\n * Check if the given path is inside a git repository\n */\nexport async function isGitRepo(projectPath: string): Promise<boolean> {\n const result = await execGit(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\n/**\n * Get files changed since a given timestamp\n * Uses git log to find commits after timestamp, then gets affected files\n * Returns null if not a git repo or on error\n */\nexport async function getChangedFilesSinceTimestamp(\n projectPath: string,\n timestamp: number\n): Promise<string[] | null> {\n const isRepo = await isGitRepo(projectPath);\n if (!isRepo) return null;\n\n try {\n // Convert timestamp to ISO date for git\n const sinceDate = new Date(timestamp).toISOString();\n \n // Set timeout for git operations (5 seconds total)\n const GIT_TIMEOUT_MS = 5000;\n const startTime = Date.now();\n \n // Get all files that changed in commits since the timestamp\n // Use Promise.race to timeout if git operations take too long\n const committedChangesPromise = execGit(\n ['log', `--since=${sinceDate}`, '--name-only', '--pretty=format:'],\n projectPath\n );\n const committedChangesTimeout = new Promise<string | null>((resolve) => {\n setTimeout(() => resolve(null), GIT_TIMEOUT_MS);\n });\n const committedChanges = await Promise.race([committedChangesPromise, committedChangesTimeout]);\n\n // Check if we've exceeded timeout\n if (Date.now() - startTime > GIT_TIMEOUT_MS) {\n return null;\n }\n\n // Get currently modified files (staged + unstaged) - run in parallel with timeout\n const stagedPromise = execGit(['diff', '--cached', '--name-only'], projectPath);\n const unstagedPromise = execGit(['diff', '--name-only'], projectPath);\n const untrackedPromise = execGit(\n ['ls-files', '--others', '--exclude-standard'],\n projectPath\n );\n \n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), Math.max(0, GIT_TIMEOUT_MS - (Date.now() - startTime)));\n });\n \n const [stagedChanges, unstagedChanges, untrackedFiles] = await Promise.race([\n Promise.all([stagedPromise, unstagedPromise, untrackedPromise]),\n timeoutPromise.then(() => [null, null, null] as const)\n ]);\n\n // Combine all changed files\n const changedFiles = new Set<string>();\n \n const addFiles = (output: string | null) => {\n if (output) {\n output.split('\\n')\n .map(f => f.trim())\n .filter(Boolean)\n .forEach(f => changedFiles.add(path.join(projectPath, f)));\n }\n };\n\n addFiles(committedChanges);\n addFiles(stagedChanges);\n addFiles(unstagedChanges);\n addFiles(untrackedFiles);\n\n return Array.from(changedFiles);\n } catch {\n return null;\n }\n}\n","/**\n * Command Runner (with audit logging)\n *\n * Goal: Whenever Trie runs a shell command, record:\n * - command string\n * - exit code\n * - duration\n * - optional (redacted) stdout/stderr\n */\nimport { exec, execFile, execSync, type ExecException } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport {\n createAuditEntry,\n completeAuditEntry,\n logSkillExecution,\n type ExecutedCommand,\n type SkillExecution,\n} from '../skills/audit-logger.js';\n\nconst execAsync = promisify(exec);\nconst execFileAsync = promisify(execFile);\n\nexport type { ExecutedCommand, SkillExecution };\nexport type AuditTriggeredBy = SkillExecution['triggeredBy'];\n\nexport interface CommandAuditContext {\n /** Shown as `skillName` in audit logs; use something like `tool:pr-review` */\n actor: string;\n /** Where this came from in the product flow */\n triggeredBy: AuditTriggeredBy;\n /** Usually the working directory / repo path */\n targetPath: string;\n /** Optional string for `skillSource` */\n source?: string;\n}\n\nexport interface RunCommandOptions {\n cwd?: string;\n timeoutMs?: number;\n maxBuffer?: number;\n\n /** Capture stdout/stderr in the audit log */\n captureOutput?: boolean;\n /** Redact obvious secrets from captured output */\n redactOutput?: boolean;\n /** Max chars to keep per output stream */\n maxOutputChars?: number;\n}\n\nfunction redact(text: string): string {\n // Keep this conservative to avoid false redaction and avoid expensive processing.\n return text\n // Common key=value secrets\n .replace(/\\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\\s*=\\s*([^\\s\"'`]+)/gi, '$1_<REDACTED>=<REDACTED>')\n // Bearer tokens\n .replace(/\\bBearer\\s+[A-Za-z0-9\\-._~+/]+=*\\b/g, 'Bearer <REDACTED>')\n // GitHub tokens / generic tokens\n .replace(/\\bghp_[A-Za-z0-9]{20,}\\b/g, 'ghp_<REDACTED>')\n .replace(/\\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\\b/g, '<REDACTED_SLACK_TOKEN>')\n // AWS access key id (best-effort)\n .replace(/\\bAKIA[0-9A-Z]{16}\\b/g, 'AKIA<REDACTED>');\n}\n\nfunction clampOutput(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars) + `\\n…(truncated ${text.length - maxChars} chars)`;\n}\n\nfunction buildCommandRecord(command: string): ExecutedCommand {\n return {\n command,\n timestamp: new Date().toISOString(),\n };\n}\n\nasync function finalizeAndWrite(\n entry: SkillExecution,\n cmd: ExecutedCommand,\n outcome: { success: boolean; exitCode?: number; stdout?: string; stderr?: string; error?: string; startedAt: number },\n options?: Pick<RunCommandOptions, 'captureOutput' | 'redactOutput' | 'maxOutputChars'>\n): Promise<void> {\n const duration = Date.now() - outcome.startedAt;\n cmd.duration = duration;\n if (outcome.exitCode !== undefined) {\n cmd.exitCode = outcome.exitCode;\n }\n\n const captureOutput = options?.captureOutput ?? false;\n const redactOutput = options?.redactOutput ?? true;\n const maxOutputChars = options?.maxOutputChars ?? 2000;\n\n if (captureOutput) {\n const out = outcome.stdout ?? '';\n const err = outcome.stderr ?? '';\n cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);\n cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);\n }\n\n const completed = completeAuditEntry(entry, outcome.success, outcome.error);\n await logSkillExecution(completed);\n}\n\nexport async function runShellCommand(\n command: string,\n audit: CommandAuditContext,\n options?: RunCommandOptions\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr, startedAt }, options);\n return { stdout: stdout ?? '', stderr: stderr ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n // Capture output for failures by default (so audits are useful)\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, stderr, exitCode };\n }\n}\n\nexport function runShellCommandSync(\n command: string,\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): { stdout: string; exitCode: number } {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const stdout = execSync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Fire-and-forget write; sync APIs can’t await.\n void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: '', startedAt }, options);\n return { stdout: stdout ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; status?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.status === 'number' ? err.status : 1;\n\n void finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, exitCode };\n }\n}\n\nexport async function runExecFile(\n file: string,\n args: string[],\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const command = [file, ...args].join(' ');\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execFileAsync(file, args, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), startedAt }, options);\n return { stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n return { stdout, stderr, exitCode };\n }\n}\n\n","/**\n * Lightweight Bayesian-style confidence updater.\n * Treats confidence as probability in [0,1].\n */\n\nexport function bayesianUpdate(prior: number, evidence: number, weight = 1): number {\n const p = clamp(prior);\n const e = clamp(evidence);\n const w = Math.max(0, weight);\n // Blend prior with evidence weighted by w\n const posterior = (p * (1 - w)) + (e * w);\n return clamp(posterior);\n}\n\nexport function adjustConfidence(current: number, outcome: 'positive' | 'negative', step = 0.1): number {\n const delta = outcome === 'positive' ? step : -step;\n return clamp(current + delta);\n}\n\nfunction clamp(value: number): number {\n if (Number.isNaN(value)) return 0.5;\n return Math.min(1, Math.max(0, value));\n}\n","import { ContextGraph } from '../context/graph.js';\nimport type { IncidentNode, PatternNode } from '../context/nodes.js';\nimport { IncidentIndex } from '../context/incident-index.js';\nimport { adjustConfidence } from './confidence.js';\nimport { TriePatternDiscovery } from './pattern-discovery.js';\n\nexport class LearningSystem {\n private incidentIndex: IncidentIndex;\n private discovery: TriePatternDiscovery;\n\n constructor(private graph: ContextGraph, projectPath: string) {\n this.incidentIndex = new IncidentIndex(graph, projectPath);\n this.discovery = new TriePatternDiscovery(graph, this.incidentIndex);\n }\n\n async onWarningHeeded(files: string[]): Promise<void> {\n await this.adjustPatterns(files, 'positive');\n }\n\n async onWarningIgnored(files: string[]): Promise<void> {\n await this.adjustPatterns(files, 'negative');\n }\n\n async onIncidentReported(incidentId: string, files: string[]): Promise<void> {\n const incident = await this.graph.getNode('incident', incidentId);\n if (incident && incident.type === 'incident') {\n this.incidentIndex.addIncidentToTrie(incident as IncidentNode, files);\n }\n await this.discoverAndStorePatterns();\n }\n\n async onFeedback(helpful: boolean, files: string[] = []): Promise<void> {\n await this.adjustPatterns(files, helpful ? 'positive' : 'negative');\n }\n\n private async adjustPatterns(files: string[], outcome: 'positive' | 'negative'): Promise<void> {\n if (!files.length) return;\n for (const file of files) {\n const patterns = await this.graph.getPatternsForFile(file);\n await Promise.all(patterns.map((p) => this.updatePatternConfidence(p, outcome)));\n }\n }\n\n private async updatePatternConfidence(pattern: PatternNode, outcome: 'positive' | 'negative'): Promise<void> {\n const current = pattern.data.confidence ?? 0.5;\n const updated = adjustConfidence(current, outcome, 0.05);\n await this.graph.updateNode('pattern', pattern.id, { confidence: updated, lastSeen: new Date().toISOString() });\n }\n\n private async discoverAndStorePatterns(): Promise<void> {\n const hotPatterns = this.discovery.discoverHotPatterns();\n for (const hot of hotPatterns) {\n await this.graph.addNode('pattern', {\n description: `${hot.type === 'directory' ? 'Directory' : 'File'} hot zone: ${hot.path}`,\n appliesTo: [hot.path],\n confidence: hot.confidence,\n occurrences: hot.incidentCount,\n firstSeen: new Date().toISOString(),\n lastSeen: new Date().toISOString(),\n isAntiPattern: true,\n source: 'local'\n });\n }\n }\n}\n","import { getRecentCommits, getDiff } from '../agent/git.js';\nimport { storeIssues } from '../memory/issue-store.js';\nimport { scanForVulnerabilities } from '../trie/vulnerability-signatures.js';\nimport { scanForVibeCodeIssues } from '../trie/vibe-code-signatures.js';\nimport type { Issue } from '../types/index.js';\nimport { ContextGraph } from '../context/graph.js';\nimport type { DecisionNodeData } from '../context/nodes.js';\nimport { LearningSystem } from '../agent/learning.js';\nimport path from 'node:path';\n\nexport interface LearningResult {\n learned: number;\n source: 'git-history' | 'manual-feedback';\n}\n\nexport class LearningEngine {\n private readonly projectPath: string;\n private readonly graph: ContextGraph;\n private readonly learningSystem: LearningSystem;\n\n constructor(projectPath: string, graph?: ContextGraph) {\n this.projectPath = projectPath;\n this.graph = graph || new ContextGraph(projectPath);\n this.learningSystem = new LearningSystem(this.graph, projectPath);\n }\n\n /**\n * Unified learning method: Scans history AND processes manual feedback\n */\n async learn(options: { \n limit?: number; \n manualFeedback?: { helpful: boolean; files: string[]; note?: string } \n } = {}): Promise<LearningResult[]> {\n const results: LearningResult[] = [];\n\n // 1. Implicit Learning from Git History\n if (!options.manualFeedback) {\n const implicitCount = await this.learnFromHistory(options.limit || 20);\n results.push({ learned: implicitCount, source: 'git-history' });\n }\n\n // 2. Manual Feedback Learning\n if (options.manualFeedback) {\n await this.recordManualFeedback(\n options.manualFeedback.helpful, \n options.manualFeedback.files, \n options.manualFeedback.note\n );\n results.push({ learned: options.manualFeedback.files.length || 1, source: 'manual-feedback' });\n }\n\n return results;\n }\n\n /**\n * Scan recent commits for implicit failure signals (reverts, fixes)\n */\n private async learnFromHistory(limit: number = 20): Promise<number> {\n const commits = await getRecentCommits(this.projectPath, limit);\n const issuesToStore: Issue[] = [];\n\n for (const commit of commits) {\n const isRevert = commit.message.toLowerCase().includes('revert') || commit.message.startsWith('Revert \"');\n const isFix = /fix(es|ed)?\\s+#\\d+/i.test(commit.message) || commit.message.toLowerCase().includes('bugfix');\n\n if (isRevert || isFix) {\n const type = isRevert ? 'revert' : 'fix';\n const diff = await getDiff(this.projectPath, commit.hash);\n const files = this.extractFilesFromDiff(diff);\n \n for (const file of files) {\n const learnedIssues = await this.extractIssuesFromDiff(diff, file, type, commit.message);\n issuesToStore.push(...learnedIssues);\n }\n }\n }\n\n if (issuesToStore.length > 0) {\n const result = await storeIssues(issuesToStore, path.basename(this.projectPath), this.projectPath);\n return result.stored;\n }\n\n return 0;\n }\n\n /**\n * Record manual feedback (trie ok/bad) and adjust pattern confidence\n */\n private async recordManualFeedback(helpful: boolean, files: string[], note?: string): Promise<void> {\n const context = files[0] ?? 'unspecified';\n const decision = await this.graph.addNode('decision', {\n context,\n decision: helpful ? 'helpful' : 'not helpful',\n reasoning: note ?? null,\n outcome: helpful ? 'good' : 'bad',\n timestamp: new Date().toISOString(),\n } satisfies DecisionNodeData);\n\n if (files.length > 0) {\n for (const file of files) {\n const fileNode = await this.graph.getNode('file', file);\n if (fileNode) {\n await this.graph.addEdge(decision.id, fileNode.id, 'affects');\n }\n }\n await this.learningSystem.onFeedback(helpful, files);\n }\n }\n\n private extractFilesFromDiff(diff: string): string[] {\n const files = new Set<string>();\n const lines = diff.split('\\n');\n for (const line of lines) {\n if (line.startsWith('+++ b/')) {\n files.add(line.slice(6));\n }\n }\n return Array.from(files);\n }\n\n private async extractIssuesFromDiff(diff: string, file: string, type: 'revert' | 'fix', message: string): Promise<Issue[]> {\n const issues: Issue[] = [];\n const badLines = this.getBadLinesFromDiff(diff, file, type);\n const content = badLines.join('\\n');\n\n if (!content) return [];\n\n const vulnerabilities = await scanForVulnerabilities(content, file);\n const vibeIssues = await scanForVibeCodeIssues(content, file);\n\n const allMatches = [...vulnerabilities, ...vibeIssues];\n\n for (const match of allMatches) {\n issues.push({\n id: `implicit-${type}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n severity: 'serious',\n issue: `Implicit failure detected via ${type}: ${message}. Linked to pattern: ${match.category}`,\n fix: `Review the ${type} commit and avoid this pattern in ${file}.`,\n file: file,\n confidence: 0.7,\n autoFixable: false,\n agent: 'implicit-learning',\n category: match.category\n });\n }\n\n if (issues.length === 0) {\n issues.push({\n id: `implicit-${type}-${Date.now()}`,\n severity: 'moderate',\n issue: `Historical ${type} detected: ${message}`,\n fix: `Review the changes in ${file} from this commit to avoid regression.`,\n file: file,\n confidence: 0.5,\n autoFixable: false,\n agent: 'implicit-learning'\n });\n }\n\n return issues;\n }\n\n private getBadLinesFromDiff(diff: string, file: string, type: 'revert' | 'fix'): string[] {\n const badLines: string[] = [];\n const lines = diff.split('\\n');\n let inTargetFile = false;\n\n for (const line of lines) {\n if (line.startsWith('+++ b/') || line.startsWith('--- a/')) {\n inTargetFile = line.includes(file);\n continue;\n }\n\n if (!inTargetFile) continue;\n\n if (type === 'fix' && line.startsWith('-') && !line.startsWith('---')) {\n badLines.push(line.slice(1));\n } else if (type === 'revert' && line.startsWith('+') && !line.startsWith('+++')) {\n badLines.push(line.slice(1));\n }\n }\n\n return badLines;\n }\n}\n","import path from 'node:path';\n\nimport { analyzeDiff, type DiffSummary } from './diff-analyzer.js';\nimport {\n getStagedChanges,\n getUncommittedChanges,\n getWorkingTreeDiff,\n type Change\n} from './git.js';\nimport { ContextGraph } from '../context/graph.js';\nimport type { FileNode, FileNodeData } from '../context/nodes.js';\n\nexport interface PerceptionResult {\n staged: Change[];\n unstaged: Change[];\n diffSummary: DiffSummary;\n changeNodeId?: string;\n}\n\nexport async function perceiveCurrentChanges(\n projectPath: string,\n graph?: ContextGraph\n): Promise<PerceptionResult> {\n const ctxGraph = graph ?? new ContextGraph(projectPath);\n\n const [staged, unstaged] = await Promise.all([\n getStagedChanges(projectPath),\n getUncommittedChanges(projectPath)\n ]);\n\n const stagedDiff = await getWorkingTreeDiff(projectPath, true);\n const unstagedDiff = await getWorkingTreeDiff(projectPath, false);\n const combinedDiff = [stagedDiff, unstagedDiff].filter(Boolean).join('\\n');\n const diffSummary = analyzeDiff(combinedDiff);\n\n const filesTouched = new Set<string>();\n staged.forEach((c) => filesTouched.add(c.path));\n unstaged.forEach((c) => filesTouched.add(c.path));\n diffSummary.files.forEach((f) => filesTouched.add(f.filePath));\n\n const changeId = await upsertWorkingChange(ctxGraph, Array.from(filesTouched), projectPath);\n\n const result: PerceptionResult = {\n staged,\n unstaged,\n diffSummary\n };\n if (changeId) result.changeNodeId = changeId;\n return result;\n}\n\nasync function upsertWorkingChange(\n graph: ContextGraph,\n files: string[],\n projectPath: string\n): Promise<string | undefined> {\n if (files.length === 0) return undefined;\n\n const now = new Date().toISOString();\n const change = await graph.addNode('change', {\n commitHash: null,\n files,\n message: 'workspace changes',\n diff: null,\n author: null,\n timestamp: now,\n outcome: 'unknown'\n });\n\n for (const filePath of files) {\n const fileNode = await ensureFileNode(graph, filePath, projectPath);\n await graph.addEdge(change.id, fileNode.id, 'affects');\n }\n\n return change.id;\n}\n\nasync function ensureFileNode(\n graph: ContextGraph,\n filePath: string,\n projectPath: string\n): Promise<FileNode> {\n const normalized = path.resolve(projectPath, filePath);\n const existing = await graph.getNode('file', normalized);\n\n const now = new Date().toISOString();\n if (existing) {\n const data = existing.data as FileNodeData;\n await graph.updateNode('file', existing.id, {\n changeCount: (data.changeCount ?? 0) + 1,\n lastChanged: now\n });\n return (await graph.getNode('file', existing.id)) as FileNode;\n }\n\n const data: FileNodeData = {\n path: filePath,\n extension: path.extname(filePath),\n purpose: '',\n riskLevel: 'medium',\n whyRisky: null,\n changeCount: 1,\n lastChanged: now,\n incidentCount: 0,\n createdAt: now\n };\n\n return (await graph.addNode('file', data)) as FileNode;\n}\n","export interface DiffFileSummary {\n filePath: string;\n added: number;\n removed: number;\n functionsModified: string[];\n riskyPatterns: string[];\n}\n\nexport interface DiffSummary {\n files: DiffFileSummary[];\n totalAdded: number;\n totalRemoved: number;\n riskyFiles: string[];\n}\n\nconst RISKY_PATTERNS = [/auth/i, /token/i, /password/i, /secret/i, /validate/i, /sanitize/i];\n\nexport function analyzeDiff(diff: string): DiffSummary {\n const files: DiffFileSummary[] = [];\n let current: DiffFileSummary | null = null;\n\n const lines = diff.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('+++ b/')) {\n const filePath = line.replace('+++ b/', '').trim();\n current = {\n filePath,\n added: 0,\n removed: 0,\n functionsModified: [],\n riskyPatterns: []\n };\n files.push(current);\n continue;\n }\n\n if (!current) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n // Capture function names or signatures in hunk headers\n const match = line.match(/@@.*?(function\\s+([\\w$]+)|class\\s+([\\w$]+)|([\\w$]+\\s*\\())/i);\n const fnName = match?.[2] || match?.[3] || match?.[4];\n if (fnName) {\n current.functionsModified.push(fnName.replace('(', '').trim());\n }\n continue;\n }\n\n if (line.startsWith('+') && !line.startsWith('+++')) {\n current.added += 1;\n markRisk(line, current);\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n current.removed += 1;\n markRisk(line, current);\n }\n }\n\n const totalAdded = files.reduce((acc, f) => acc + f.added, 0);\n const totalRemoved = files.reduce((acc, f) => acc + f.removed, 0);\n const riskyFiles = files.filter((f) => f.riskyPatterns.length > 0).map((f) => f.filePath);\n\n return {\n files,\n totalAdded,\n totalRemoved,\n riskyFiles\n };\n}\n\nfunction markRisk(line: string, file: DiffFileSummary): void {\n for (const pattern of RISKY_PATTERNS) {\n if (pattern.test(line)) {\n const label = pattern.toString();\n if (!file.riskyPatterns.includes(label)) {\n file.riskyPatterns.push(label);\n }\n }\n }\n}\n","import path from 'node:path';\n\nimport type { RiskLevel } from '../types/index.js';\nimport type { PatternNode } from '../context/types.js';\nimport type { ContextGraph } from '../context/graph.js';\nimport type { FileNodeData, IncidentNode } from '../context/nodes.js';\n\nexport interface FileRiskResult {\n file: string;\n score: number;\n level: RiskLevel;\n reasons: string[];\n incidents: IncidentNode[];\n matchedPatterns: PatternNode[];\n}\n\nexport interface ChangeRiskResult {\n files: FileRiskResult[];\n overall: RiskLevel;\n score: number;\n shouldEscalate: boolean;\n}\n\nconst BASE_RISK: Record<RiskLevel, number> = {\n low: 10,\n medium: 35,\n high: 65,\n critical: 85\n};\n\nconst SENSITIVE_PATHS: { pattern: RegExp; weight: number; reason: string }[] = [\n { pattern: /auth|login|token|session/i, weight: 20, reason: 'touches authentication' },\n { pattern: /payment|billing|stripe|paypal|checkout/i, weight: 25, reason: 'touches payments' },\n { pattern: /secret|credential|env|config\\/security/i, weight: 15, reason: 'touches secrets/security config' },\n];\n\nfunction levelFromScore(score: number): RiskLevel {\n if (score >= 90) return 'critical';\n if (score >= 65) return 'high';\n if (score >= 40) return 'medium';\n return 'low';\n}\n\nexport async function scoreFile(\n graph: ContextGraph,\n filePath: string,\n matchedPatterns: PatternNode[] = []\n): Promise<FileRiskResult> {\n const reasons: string[] = [];\n const normalized = path.resolve(graph.projectRoot, filePath);\n const node = await graph.getNode('file', normalized);\n const incidents = await graph.getIncidentsForFile(filePath);\n\n let score = 10;\n const data = node?.data as FileNodeData | undefined;\n\n if (data) {\n score = BASE_RISK[data.riskLevel] ?? score;\n reasons.push(`baseline ${data.riskLevel}`);\n\n if (data.incidentCount > 0) {\n const incBoost = Math.min(data.incidentCount * 12, 36);\n score += incBoost;\n reasons.push(`historical incidents (+${incBoost})`);\n }\n\n if (data.changeCount > 5) {\n const changeBoost = Math.min((data.changeCount - 5) * 2, 12);\n score += changeBoost;\n reasons.push(`frequent changes (+${changeBoost})`);\n }\n\n if (data.lastChanged) {\n const lastChanged = new Date(data.lastChanged).getTime();\n const days = (Date.now() - lastChanged) / (1000 * 60 * 60 * 24);\n if (days > 60 && data.incidentCount === 0) {\n score -= 5;\n reasons.push('stable for 60d (-5)');\n }\n }\n }\n\n for (const { pattern, weight, reason } of SENSITIVE_PATHS) {\n if (pattern.test(filePath)) {\n score += weight;\n reasons.push(reason);\n }\n }\n\n if (matchedPatterns.length > 0) {\n const patternBoost = Math.min(\n matchedPatterns.reduce((acc, p) => acc + (p.data.confidence ?? 50) / 10, 0),\n 20\n );\n score += patternBoost;\n reasons.push(`pattern match (+${Math.round(patternBoost)})`);\n }\n\n if (incidents.length > 0) {\n const timestamps = incidents\n .map((i) => new Date(i.data.timestamp).getTime())\n .sort((a, b) => b - a);\n const recent = timestamps[0]!;\n const daysSince = (Date.now() - recent) / (1000 * 60 * 60 * 24);\n if (daysSince > 90) {\n score -= 5;\n reasons.push('no incidents in 90d (-5)');\n } else {\n score += 8;\n reasons.push('recent incident (+8)');\n }\n }\n\n const level = levelFromScore(score);\n return {\n file: filePath,\n score,\n level,\n reasons,\n incidents,\n matchedPatterns\n };\n}\n\nexport async function scoreChangeSet(\n graph: ContextGraph,\n files: string[],\n patternMatches: Record<string, PatternNode[]> = {}\n): Promise<ChangeRiskResult> {\n const fileResults: FileRiskResult[] = [];\n\n for (const file of files) {\n const patterns = patternMatches[file] ?? [];\n fileResults.push(await scoreFile(graph, file, patterns));\n }\n\n // Aggregate: use max file score, but boost if many files touched\n const maxScore = Math.max(...fileResults.map((f) => f.score), 10);\n const spreadBoost = files.length > 5 ? Math.min((files.length - 5) * 2, 10) : 0;\n const overallScore = maxScore + spreadBoost;\n const overall = levelFromScore(overallScore);\n\n const shouldEscalate = overall === 'critical' || overall === 'high';\n\n return {\n files: fileResults,\n overall,\n score: overallScore,\n shouldEscalate\n };\n}\n","import { ContextGraph } from '../context/graph.js';\nimport type { PatternNode } from '../context/nodes.js';\n\nexport interface PatternMatch {\n file: string;\n pattern: PatternNode;\n confidence: number;\n isAntiPattern: boolean;\n}\n\nexport async function matchPatternsForFiles(\n graph: ContextGraph,\n files: string[]\n): Promise<{ matches: PatternMatch[]; byFile: Record<string, PatternNode[]> }> {\n const matches: PatternMatch[] = [];\n const byFile: Record<string, PatternNode[]> = {};\n\n for (const file of files) {\n const patterns = await graph.getPatternsForFile(file);\n if (patterns.length === 0) continue;\n\n byFile[file] = patterns;\n\n for (const pattern of patterns) {\n matches.push({\n file,\n pattern,\n confidence: pattern.data.confidence,\n isAntiPattern: pattern.data.isAntiPattern\n });\n }\n }\n\n return { matches, byFile };\n}\n","import type { CodeContext, Agent, TriagingConfig } from '../types/index.js';\n\nexport class Triager {\n constructor(_config?: Partial<TriagingConfig>) {\n // Config no longer used - Trie is now purely a decision ledger\n }\n\n /**\n * Triage a change to select appropriate agents\n * Note: Skills/agents have been removed - Trie is now purely a decision ledger\n */\n async triage(\n _context: CodeContext,\n _forceAgents?: string[]\n ): Promise<Agent[]> {\n // No skills to triage - return empty array\n // Trie now focuses on decision ledger and learning from incidents\n return [];\n }\n\n /**\n * Get all available agent names (deprecated - returns empty array)\n */\n getAvailableAgents(): string[] {\n return [];\n }\n}\n","import { Worker } from 'worker_threads';\nimport { cpus } from 'os';\nimport { existsSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport type { Agent, AgentResult, ScanContext } from '../types/index.js';\nimport { StreamingManager } from './streaming.js';\nimport { CacheManager } from './cache-manager.js';\nimport { isInteractiveMode } from './progress.js';\n\ninterface ParallelTask {\n agent: Agent;\n files: string[];\n context: ScanContext;\n priority: number;\n timeoutMs: number;\n}\n\ninterface ParallelResult {\n agent: string;\n result: AgentResult;\n fromCache: boolean;\n executionTime: number;\n}\n\n/**\n * Parallel execution engine for Trie agents\n *\n * Features:\n * - True parallel execution using worker threads\n * - Intelligent scheduling based on agent priority\n * - Result caching and cache-aware scheduling\n * - Real-time progress streaming\n * - Dynamic resource management\n */\nexport class ParallelExecutor {\n private maxWorkers: number;\n private cache: CacheManager | null;\n private streaming?: StreamingManager;\n private activeWorkers: Set<Worker> = new Set();\n private cacheEnabled: boolean = true;\n private useWorkerThreads: boolean = false;\n private workerAvailable: boolean | null = null;\n private warnedWorkerFallback: boolean = false;\n\n constructor(\n cacheManager: CacheManager | null,\n maxWorkers: number = Math.max(2, Math.min(cpus().length - 1, 8)),\n options?: { cacheEnabled?: boolean; useWorkerThreads?: boolean }\n ) {\n this.maxWorkers = maxWorkers;\n this.cache = cacheManager;\n this.cacheEnabled = options?.cacheEnabled ?? true;\n this.useWorkerThreads = options?.useWorkerThreads ?? false;\n }\n\n /**\n * Set streaming manager for real-time updates\n */\n setStreaming(streaming: StreamingManager): void {\n this.streaming = streaming;\n }\n\n /**\n * Execute agents in parallel with intelligent scheduling\n */\n async executeAgents(\n agents: Agent[],\n files: string[],\n context: ScanContext\n ): Promise<Map<string, AgentResult>> {\n if (agents.length === 0) {\n return new Map();\n }\n\n // Initialize streaming\n if (this.streaming && this.streaming.getProgress().totalFiles === 0) {\n this.streaming.startScan(files.length);\n }\n\n // Check cache for existing results\n const cacheResults = new Map<string, AgentResult>();\n const uncachedTasks: ParallelTask[] = [];\n\n for (const agent of agents) {\n const cached = await this.checkAgentCache(agent, files);\n if (cached) {\n cacheResults.set(agent.name, cached);\n this.streaming?.completeAgent(agent.name, cached.issues);\n } else {\n uncachedTasks.push({\n agent,\n files,\n context,\n priority: agent.priority?.tier || 2,\n timeoutMs: context?.config?.timeoutMs || 120000\n });\n }\n }\n\n // Sort tasks by priority (tier 1 = highest priority)\n uncachedTasks.sort((a, b) => a.priority - b.priority);\n\n // Execute uncached tasks in parallel\n const parallelResults = await this.executeTasksParallel(uncachedTasks);\n\n // Cache new results\n await this.cacheResults(parallelResults);\n\n // Combine cached and new results\n const allResults = new Map<string, AgentResult>();\n\n // Add cached results\n for (const [agent, result] of cacheResults) {\n allResults.set(agent, result);\n }\n\n // Add new results\n for (const result of parallelResults) {\n allResults.set(result.agent, result.result);\n }\n\n // Complete streaming\n const allIssues = Array.from(allResults.values()).flatMap(r => r.issues);\n this.streaming?.completeScan(allIssues);\n\n return allResults;\n }\n\n /**\n * Check if agent has cached results for given files\n */\n private async checkAgentCache(agent: Agent, files: string[]): Promise<AgentResult | null> {\n if (!this.cacheEnabled || !this.cache) {\n return null;\n }\n\n const cachedIssues = await this.cache.getCachedBatch(files, agent.name);\n\n // Only use cache if we have results for ALL files\n if (cachedIssues.size === files.length) {\n const allIssues = Array.from(cachedIssues.values()).flat();\n return {\n agent: agent.name,\n issues: allIssues,\n executionTime: 0, // Cached\n success: true,\n metadata: {\n filesAnalyzed: files.length,\n linesAnalyzed: 0\n }\n };\n }\n\n return null;\n }\n\n /**\n * Execute tasks in parallel batches\n */\n private async executeTasksParallel(tasks: ParallelTask[]): Promise<ParallelResult[]> {\n if (tasks.length === 0) {\n return [];\n }\n\n const results: ParallelResult[] = [];\n const batches = this.createBatches(tasks, this.maxWorkers);\n\n for (const batch of batches) {\n const batchResults = await Promise.all(\n batch.map(task => this.executeTask(task))\n );\n results.push(...batchResults);\n }\n\n return results;\n }\n\n /**\n * Create batches for parallel execution\n */\n private createBatches(tasks: ParallelTask[], batchSize: number): ParallelTask[][] {\n const batches: ParallelTask[][] = [];\n\n for (let i = 0; i < tasks.length; i += batchSize) {\n batches.push(tasks.slice(i, i + batchSize));\n }\n\n return batches;\n }\n\n /**\n * Execute a single task\n */\n private async executeTask(task: ParallelTask): Promise<ParallelResult> {\n const startTime = Date.now();\n\n this.streaming?.startAgent(task.agent.name);\n\n try {\n const result = this.canUseWorkers()\n ? await this.executeTaskInWorker(task)\n : await task.agent.scan(task.files, task.context);\n const executionTime = Date.now() - startTime;\n\n this.streaming?.completeAgent(task.agent.name, result.issues);\n\n return {\n agent: task.agent.name,\n result,\n fromCache: false,\n executionTime\n };\n } catch (error) {\n const executionTime = Date.now() - startTime;\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n this.streaming?.reportError(new Error(errorMessage), `Agent: ${task.agent.name}`);\n\n return {\n agent: task.agent.name,\n result: {\n agent: task.agent.name,\n issues: [],\n executionTime,\n success: false,\n error: errorMessage\n },\n fromCache: false,\n executionTime\n };\n }\n }\n\n private canUseWorkers(): boolean {\n if (!this.useWorkerThreads) {\n return false;\n }\n if (this.workerAvailable !== null) {\n return this.workerAvailable;\n }\n const workerUrl = this.getWorkerUrl();\n this.workerAvailable = existsSync(fileURLToPath(workerUrl));\n if (!this.workerAvailable && !this.warnedWorkerFallback && !isInteractiveMode()) {\n console.error('Worker threads unavailable; falling back to in-process agents.');\n this.warnedWorkerFallback = true;\n }\n return this.workerAvailable;\n }\n\n private getWorkerUrl(): URL {\n const distDir = new URL('.', import.meta.url);\n return new URL('workers/agent-worker.js', distDir);\n }\n\n private async executeTaskInWorker(task: ParallelTask): Promise<AgentResult> {\n // Use dirname to get the dist folder, then resolve to workers subfolder\n // This works whether the code is bundled into chunks or in utils/ folder\n const workerUrl = this.getWorkerUrl();\n\n return new Promise((resolve, reject) => {\n const worker = new Worker(workerUrl, {\n workerData: {\n agentName: task.agent.name,\n files: task.files,\n context: task.context\n }\n } as ConstructorParameters<typeof Worker>[1]);\n\n this.activeWorkers.add(worker);\n\n const timeout = setTimeout(() => {\n worker.terminate().catch(() => undefined);\n reject(new Error(`Agent ${task.agent.name} timed out after ${task.timeoutMs}ms`));\n }, task.timeoutMs);\n\n worker.on('message', (message) => {\n if (message?.type === 'result') {\n clearTimeout(timeout);\n resolve(message.result as AgentResult);\n } else if (message?.type === 'error') {\n clearTimeout(timeout);\n reject(new Error(message.error));\n }\n });\n\n worker.on('error', (error) => {\n clearTimeout(timeout);\n reject(error);\n });\n\n worker.on('exit', (code) => {\n this.activeWorkers.delete(worker);\n if (code !== 0) {\n clearTimeout(timeout);\n reject(new Error(`Worker stopped with exit code ${code}`));\n }\n });\n });\n }\n\n /**\n * Cache results for future use\n */\n private async cacheResults(results: ParallelResult[]): Promise<void> {\n if (!this.cacheEnabled || !this.cache) {\n return;\n }\n\n const cachePromises = results\n .filter(r => r.result.success && !r.fromCache)\n .map(r => {\n const issuesByFile = this.groupIssuesByFile(r.result.issues);\n const perFilePromises = Object.entries(issuesByFile).map(([file, issues]) =>\n this.cache!.setCached(file, r.agent, issues, r.executionTime)\n );\n return Promise.all(perFilePromises);\n });\n\n await Promise.allSettled(cachePromises);\n }\n\n /**\n * Cleanup resources\n */\n async cleanup(): Promise<void> {\n // Terminate any active workers\n const terminationPromises = Array.from(this.activeWorkers).map(worker =>\n worker.terminate()\n );\n\n await Promise.allSettled(terminationPromises);\n this.activeWorkers.clear();\n }\n\n private groupIssuesByFile(issues: AgentResult['issues']): Record<string, AgentResult['issues']> {\n const grouped: Record<string, AgentResult['issues']> = {};\n\n for (const issue of issues) {\n if (!grouped[issue.file]) {\n grouped[issue.file] = [];\n }\n grouped[issue.file]!.push(issue);\n }\n\n return grouped;\n }\n}\n\n/**\n * Smart agent prioritization based on dependencies and execution characteristics\n */\nexport function prioritizeAgents(agents: Agent[]): Agent[] {\n const prioritized = [...agents];\n\n // Sort by priority tier, then by estimated execution time\n prioritized.sort((a, b) => {\n const aTier = a.priority?.tier || 2;\n const bTier = b.priority?.tier || 2;\n\n if (aTier !== bTier) {\n return aTier - bTier; // Lower tier = higher priority\n }\n\n // Within same tier, prioritize faster agents\n const aTime = a.priority?.estimatedTimeMs || 1000;\n const bTime = b.priority?.estimatedTimeMs || 1000;\n\n return aTime - bTime;\n });\n\n return prioritized;\n}\n\n/**\n * Calculate optimal concurrency based on system resources and agent characteristics\n */\nexport function calculateOptimalConcurrency(): number {\n const numCPUs = cpus().length;\n const availableMemoryGB = process.memoryUsage().rss / 1024 / 1024 / 1024;\n\n // Conservative concurrency for stability\n let optimal = Math.max(2, Math.min(numCPUs - 1, 8));\n\n // Reduce concurrency if low memory\n if (availableMemoryGB < 2) {\n optimal = Math.max(2, Math.floor(optimal / 2));\n }\n\n // Increase slightly for systems with lots of CPU cores\n if (numCPUs > 8) {\n optimal = Math.min(optimal + 2, 12);\n }\n\n return optimal;\n}","import { readFile, writeFile, mkdir, stat } from 'fs/promises';\nimport { join } from 'path';\nimport { createHash } from 'crypto';\nimport type { Issue } from '../types/index.js';\nimport { isInteractiveMode } from './progress.js';\nimport { getTrieDirectory } from './workspace.js';\n\ninterface CacheEntry {\n version: string;\n timestamp: number;\n fileHash: string;\n fileSize: number;\n agent: string;\n issues: Issue[];\n executionTime: number;\n}\n\ninterface CacheIndex {\n version: string;\n created: number;\n entries: Record<string, CacheEntry>;\n}\n\nexport class CacheManager {\n private cacheDir: string;\n private indexPath: string;\n private readonly VERSION = '1.0.0';\n private readonly MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours\n private readonly MAX_ENTRIES = 1000;\n\n constructor(baseDir: string) {\n this.cacheDir = join(getTrieDirectory(baseDir), 'cache');\n this.indexPath = join(this.cacheDir, 'index.json');\n }\n\n /**\n * Generate cache key for a file and agent combination\n */\n private generateCacheKey(filePath: string, agent: string, fileHash: string): string {\n const key = `${filePath}:${agent}:${fileHash}`;\n return createHash('sha256').update(key).digest('hex').slice(0, 16);\n }\n\n /**\n * Get file hash for cache validation\n */\n private async getFileHash(filePath: string): Promise<{ hash: string; size: number; mtime: number }> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const stats = await stat(filePath);\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 16);\n return {\n hash,\n size: stats.size,\n mtime: stats.mtime.getTime()\n };\n } catch {\n return { hash: '', size: 0, mtime: 0 };\n }\n }\n\n /**\n * Load cache index\n */\n private async loadIndex(): Promise<CacheIndex> {\n try {\n const content = await readFile(this.indexPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return {\n version: this.VERSION,\n created: Date.now(),\n entries: {}\n };\n }\n }\n\n /**\n * Save cache index\n */\n private async saveIndex(index: CacheIndex): Promise<void> {\n try {\n await mkdir(this.cacheDir, { recursive: true });\n await writeFile(this.indexPath, JSON.stringify(index, null, 2));\n } catch (error) {\n if (!isInteractiveMode()) {\n console.warn('Failed to save cache index:', error);\n }\n }\n }\n\n /**\n * Clean up expired entries\n */\n private cleanupExpired(index: CacheIndex): CacheIndex {\n const now = Date.now();\n const validEntries: Record<string, CacheEntry> = {};\n\n for (const [key, entry] of Object.entries(index.entries)) {\n if (now - entry.timestamp < this.MAX_AGE_MS) {\n validEntries[key] = entry;\n }\n }\n\n // If still too many, keep the most recent ones\n const entries = Object.entries(validEntries);\n if (entries.length > this.MAX_ENTRIES) {\n entries.sort((a, b) => b[1].timestamp - a[1].timestamp);\n const limited = entries.slice(0, this.MAX_ENTRIES);\n return {\n ...index,\n entries: Object.fromEntries(limited)\n };\n }\n\n return {\n ...index,\n entries: validEntries\n };\n }\n\n /**\n * Get cached result for a file and agent\n * \n * Cache automatically invalidates when files change:\n * - Cache key includes file hash: hash(filePath:agent:fileHash)\n * - When file changes, hash changes, so cache key changes\n * - Old cache entry won't be found (different key)\n * - File is automatically rescanned\n * \n * This means cache auto-updates when Claude fixes code - no manual invalidation needed!\n */\n async getCached(filePath: string, agent: string): Promise<Issue[] | null> {\n try {\n const { hash, size: _size, mtime: _mtime } = await this.getFileHash(filePath);\n if (!hash) return null;\n\n const index = await this.loadIndex();\n const cacheKey = this.generateCacheKey(filePath, agent, hash);\n const entry = index.entries[cacheKey];\n\n if (!entry) return null;\n\n // Validate entry is still fresh\n // Double-check hash matches (defense in depth)\n const isValid = entry.fileHash === hash &&\n entry.version === this.VERSION &&\n (Date.now() - entry.timestamp) < this.MAX_AGE_MS;\n\n if (!isValid) {\n delete index.entries[cacheKey];\n await this.saveIndex(index);\n return null;\n }\n\n return entry.issues;\n } catch {\n return null;\n }\n }\n\n /**\n * Cache result for a file and agent\n */\n async setCached(\n filePath: string,\n agent: string,\n issues: Issue[],\n executionTime: number\n ): Promise<void> {\n try {\n const { hash, size } = await this.getFileHash(filePath);\n if (!hash) return;\n\n const index = await this.loadIndex();\n const cacheKey = this.generateCacheKey(filePath, agent, hash);\n\n index.entries[cacheKey] = {\n version: this.VERSION,\n timestamp: Date.now(),\n fileHash: hash,\n fileSize: size,\n agent,\n issues,\n executionTime\n };\n\n // Clean up old entries\n const cleanedIndex = this.cleanupExpired(index);\n await this.saveIndex(cleanedIndex);\n } catch (error) {\n if (!isInteractiveMode()) {\n console.warn('Failed to cache result:', error);\n }\n }\n }\n\n /**\n * Check if multiple files have cached results\n */\n async getCachedBatch(files: string[], agent: string): Promise<Map<string, Issue[]>> {\n const results = new Map<string, Issue[]>();\n\n await Promise.all(\n files.map(async (file) => {\n const cached = await this.getCached(file, agent);\n if (cached) {\n results.set(file, cached);\n }\n })\n );\n\n return results;\n }\n\n /**\n * Get cache statistics\n */\n async getStats(): Promise<{\n totalEntries: number;\n totalSizeKB: number;\n oldestEntry: number | null;\n newestEntry: number | null;\n agents: string[];\n hitRate?: number;\n }> {\n try {\n const index = await this.loadIndex();\n const entries = Object.values(index.entries);\n\n const totalSizeKB = entries.reduce((acc, entry) => acc + entry.fileSize, 0) / 1024;\n const timestamps = entries.map(e => e.timestamp);\n const agents = [...new Set(entries.map(e => e.agent))];\n\n return {\n totalEntries: entries.length,\n totalSizeKB: Math.round(totalSizeKB),\n oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : null,\n newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : null,\n agents\n };\n } catch {\n return {\n totalEntries: 0,\n totalSizeKB: 0,\n oldestEntry: null,\n newestEntry: null,\n agents: []\n };\n }\n }\n\n /**\n * Clean up stale cache entries by verifying file hashes\n * This removes entries where files have changed or no longer exist\n * Called periodically to keep cache clean\n * \n * Note: Since cache keys are hashed, we can't easily reverse-engineer file paths.\n * However, when getCached() is called, it naturally invalidates stale entries\n * by checking if the current file hash matches the cached hash. This method\n * proactively cleans up entries for known changed files.\n */\n async cleanupStaleEntries(filePaths?: string[]): Promise<number> {\n try {\n const index = await this.loadIndex();\n let removedCount = 0;\n const keysToRemove: string[] = [];\n\n // If specific files provided, check those files against all cache entries\n // We can't perfectly match entries to files without storing paths, but we can\n // try to identify likely matches by checking if regenerating keys matches\n if (filePaths && filePaths.length > 0) {\n // Get all unique agents from cache entries\n const agents = new Set<string>();\n for (const entry of Object.values(index.entries)) {\n agents.add(entry.agent);\n }\n\n // For each file+agent combination, check if cache entry is stale\n for (const filePath of filePaths) {\n try {\n const { hash: currentHash } = await this.getFileHash(filePath);\n if (!currentHash) {\n // File doesn't exist - can't clean up without knowing which entries are for it\n continue;\n }\n\n // Check each agent's potential cache entries for this file\n for (const agent of agents) {\n // Check all entries to find ones that might be for this file\n for (const [key, entry] of Object.entries(index.entries)) {\n if (entry.agent !== agent) continue;\n \n // If entry hash doesn't match current hash, it might be stale\n if (entry.fileHash !== currentHash) {\n // Check if this key was generated with the old hash for this file\n const oldKey = this.generateCacheKey(filePath, agent, entry.fileHash);\n if (oldKey === key) {\n // This entry is for this file but hash doesn't match - stale!\n keysToRemove.push(key);\n removedCount++;\n }\n }\n }\n }\n } catch {\n // File doesn't exist or can't be read - skip\n continue;\n }\n }\n }\n\n // Remove stale entries (avoid duplicates)\n const uniqueKeys = [...new Set(keysToRemove)];\n for (const key of uniqueKeys) {\n delete index.entries[key];\n }\n\n if (removedCount > 0) {\n await this.saveIndex(index);\n }\n\n return removedCount;\n } catch (error) {\n if (!isInteractiveMode()) {\n console.warn('Failed to cleanup stale cache entries:', error);\n }\n return 0;\n }\n }\n\n /**\n * Clear all cache\n */\n async clear(): Promise<void> {\n try {\n const emptyIndex: CacheIndex = {\n version: this.VERSION,\n created: Date.now(),\n entries: {}\n };\n await this.saveIndex(emptyIndex);\n } catch (error) {\n if (!isInteractiveMode()) {\n console.warn('Failed to clear cache:', error);\n }\n }\n }\n}","import type { Agent, AgentResult, ScanContext } from '../types/index.js';\nimport { ParallelExecutor, calculateOptimalConcurrency } from '../utils/parallel-executor.js';\nimport { CacheManager } from '../utils/cache-manager.js';\nimport type { StreamingManager } from '../utils/streaming.js';\nimport { isInteractiveMode } from '../utils/progress.js';\n\nexport class Executor {\n async executeAgents(\n agents: Agent[],\n files: string[],\n context: ScanContext,\n options?: {\n streaming?: StreamingManager;\n parallel?: boolean;\n cacheEnabled?: boolean;\n maxConcurrency?: number;\n useWorkerThreads?: boolean;\n timeoutMs?: number;\n }\n ): Promise<AgentResult[]> {\n const parallel = options?.parallel ?? true;\n const cacheEnabled = options?.cacheEnabled ?? true;\n const maxConcurrency = options?.maxConcurrency ?? calculateOptimalConcurrency();\n const useWorkerThreads = options?.useWorkerThreads ?? false;\n\n if (!isInteractiveMode()) {\n console.error(`Executing ${agents.length} scouts ${parallel ? 'in parallel' : 'sequentially'}...`);\n }\n\n if (parallel) {\n const cacheManager = cacheEnabled ? new CacheManager(context.workingDir) : null;\n const executor = new ParallelExecutor(cacheManager, maxConcurrency, {\n cacheEnabled,\n useWorkerThreads\n });\n\n if (options?.streaming) {\n executor.setStreaming(options.streaming);\n }\n\n const results = await executor.executeAgents(agents, files, {\n ...context,\n config: { timeoutMs: options?.timeoutMs ?? 120000 }\n });\n\n return agents.map(agent => results.get(agent.name)!).filter(Boolean);\n }\n\n // Execute scouts in parallel with timeout\n const promises = agents.map(agent =>\n this.executeAgentWithTimeout(agent, files, context, options?.timeoutMs ?? 30000)\n );\n\n try {\n const results = await Promise.allSettled(promises);\n return results.map((result, index) => {\n if (result.status === 'fulfilled') {\n if (!isInteractiveMode()) {\n console.error(`${agents[index]!.name} completed in ${result.value.executionTime}ms`);\n }\n return result.value;\n } else {\n if (!isInteractiveMode()) {\n console.error(`${agents[index]!.name} failed:`, result.reason);\n }\n return {\n agent: agents[index]!.name,\n issues: [],\n executionTime: 0,\n success: false,\n error: result.reason instanceof Error ? result.reason.message : String(result.reason)\n };\n }\n });\n } catch (error) {\n if (!isInteractiveMode()) {\n console.error('Executor error:', error);\n }\n return agents.map(agent => ({\n agent: agent.name,\n issues: [],\n executionTime: 0,\n success: false,\n error: 'Execution failed'\n }));\n }\n }\n\n private async executeAgentWithTimeout(\n agent: Agent,\n files: string[],\n context: ScanContext,\n timeoutMs: number = 30000 // 30 second timeout\n ): Promise<AgentResult> {\n return new Promise(async (resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Agent ${agent.name} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n try {\n const result = await agent.scan(files, context);\n clearTimeout(timeout);\n resolve(result);\n } catch (error) {\n clearTimeout(timeout);\n reject(error);\n }\n });\n }\n}","import { ContextGraph } from '../context/graph.js';\nimport type { IncidentNode, PatternNode } from '../context/nodes.js';\nimport type { RiskLevel, AgentResult, CodeContext, ScanContext } from '../types/index.js';\nimport { scoreChangeSet, type ChangeRiskResult, type FileRiskResult } from './risk-scorer.js';\nimport { matchPatternsForFiles } from './pattern-matcher.js';\nimport { Triager } from '../orchestrator/triager.js';\nimport { Executor } from '../orchestrator/executor.js';\n\nexport interface Reasoning {\n riskLevel: RiskLevel;\n shouldBlock: boolean;\n explanation: string;\n relevantIncidents: IncidentNode[];\n matchedPatterns: PatternNode[];\n recommendation: string;\n files: FileRiskResult[];\n agentResults?: AgentResult[];\n}\n\nexport interface ReasonOptions {\n runAgents?: boolean;\n codeContext?: CodeContext;\n scanContext?: Partial<ScanContext>;\n}\n\nfunction buildDefaultCodeContext(): CodeContext {\n return {\n changeType: 'general',\n isNewFeature: false,\n touchesUserData: false,\n touchesAuth: false,\n touchesPayments: false,\n touchesDatabase: false,\n touchesAPI: false,\n touchesUI: false,\n touchesHealthData: false,\n touchesSecurityConfig: false,\n linesChanged: 50,\n filePatterns: [],\n framework: 'unknown',\n language: 'typescript',\n touchesCrypto: false,\n touchesFileSystem: false,\n touchesThirdPartyAPI: false,\n touchesLogging: false,\n touchesErrorHandling: false,\n hasTests: false,\n complexity: 'medium',\n patterns: {\n hasAsyncCode: false,\n hasFormHandling: false,\n hasFileUploads: false,\n hasEmailHandling: false,\n hasRateLimiting: false,\n hasWebSockets: false,\n hasCaching: false,\n hasQueue: false\n }\n };\n}\n\nfunction buildExplanation(result: ChangeRiskResult): string {\n const top = [...result.files].sort((a, b) => b.score - a.score)[0];\n if (!top) return `Risk level ${result.overall} (no files provided)`;\n return `Risk level ${result.overall} because ${top.file} ${top.reasons.join(', ')}`;\n}\n\nfunction buildRecommendation(risk: RiskLevel, hasAntiPattern: boolean): string {\n if (hasAntiPattern || risk === 'critical') {\n return 'Block until reviewed: address anti-patterns and rerun targeted tests.';\n }\n if (risk === 'high') {\n return 'Require senior review and run full test suite before merge.';\n }\n if (risk === 'medium') {\n return 'Proceed with caution; run impacted tests and sanity checks.';\n }\n return 'Low risk; proceed but keep an eye on recent changes.';\n}\n\nexport async function reasonAboutChanges(\n projectPath: string,\n files: string[],\n options: ReasonOptions = {}\n): Promise<Reasoning> {\n const graph = new ContextGraph(projectPath);\n const { matches, byFile } = await matchPatternsForFiles(graph, files);\n const changeRisk = await scoreChangeSet(graph, files, byFile);\n\n const incidents: IncidentNode[] = [];\n for (const file of files) {\n const fileIncidents = await graph.getIncidentsForFile(file);\n incidents.push(...fileIncidents);\n }\n\n const hasAntiPattern = matches.some((m) => m.isAntiPattern);\n const riskLevel: RiskLevel = hasAntiPattern ? 'critical' : changeRisk.overall;\n const shouldBlock = hasAntiPattern || riskLevel === 'critical' || riskLevel === 'high';\n\n const reasoning: Reasoning = {\n riskLevel,\n shouldBlock,\n explanation: buildExplanation(changeRisk),\n relevantIncidents: incidents,\n matchedPatterns: matches.map((m) => m.pattern),\n recommendation: buildRecommendation(riskLevel, hasAntiPattern),\n files: changeRisk.files\n };\n\n if (options.runAgents) {\n const codeContext = options.codeContext ?? buildDefaultCodeContext();\n const triager = new Triager();\n // Skills removed - decision ledger now handles risk analysis\n const agents = await triager.triage(codeContext);\n\n if (agents.length > 0) {\n const executor = new Executor();\n const scanContext: ScanContext = {\n workingDir: projectPath,\n ...options.scanContext\n };\n if (codeContext.framework) scanContext.framework = codeContext.framework;\n if (codeContext.language) scanContext.language = codeContext.language;\n\n reasoning.agentResults = await executor.executeAgents(agents, files, scanContext, {\n parallel: true,\n timeoutMs: options.scanContext?.config?.timeoutMs ?? 60000\n });\n } else {\n reasoning.agentResults = [];\n }\n }\n\n return reasoning;\n}\n\n// Convenience wrapper to keep future CLI/MCP integration simple\nexport async function reasonAboutChangesHumanReadable(\n projectPath: string,\n files: string[],\n options: ReasonOptions = {}\n) {\n const reasoning = await reasonAboutChanges(projectPath, files, options);\n const { humanizeReasoning } = await import('../comprehension/index.js');\n return humanizeReasoning(reasoning);\n}\n"],"mappings":"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","names":["existsSync","join","existsSync","join","existsSync","path","path","path","path","path","data","path","existsSync","existsSync","readFile","writeFile","mkdir","join","join","readFile","mkdir","writeFile"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent/goal-validator.ts"],"sourcesContent":["/**\n * Goal Validator - Helpers for goal tracking\n * \n * Goal detection is handled entirely by the AI watcher in watch.ts.\n * The AI (Anthropic) checks every changed file against user-defined goals,\n * using the Trie's priority scoring for cost control.\n * \n * This module provides:\n * - getActiveGoals: loads active goals for the AI prompt\n * - recordGoalViolationCaught: tracks when a violation is detected\n * - recordGoalViolationFixed: tracks when a violation is auto-fixed\n * - measureInitialGoalValue: measures current state for new goals\n */\n\nimport type { Goal } from './project-state.js';\nimport { getProjectState } from './project-state.js';\nimport { searchIssues } from '../memory/issue-store.js';\n\n/**\n * Get active goals for a project (used by the AI watcher)\n */\nexport async function getActiveGoals(projectPath: string): Promise<Goal[]> {\n const projectState = getProjectState(projectPath);\n await projectState.load();\n return projectState.getAllGoals().filter(g => g.status === 'active');\n}\n\nexport async function recordGoalViolationCaught(\n goal: Goal,\n file: string,\n projectPath: string\n): Promise<void> {\n const projectState = getProjectState(projectPath);\n await projectState.load();\n \n const metadata = goal.metadata || {};\n const caughtCount = (metadata.caughtCount || 0) + 1;\n \n await projectState.updateGoal(goal.id, {\n metadata: {\n ...metadata,\n caughtCount,\n lastCaught: new Date().toISOString(),\n lastCaughtFile: file,\n },\n });\n}\n\nexport async function recordGoalViolationFixed(\n goal: Goal,\n file: string,\n projectPath: string\n): Promise<void> {\n const projectState = getProjectState(projectPath);\n await projectState.load();\n \n const metadata = goal.metadata || {};\n const fixedCount = (metadata.fixedCount || 0) + 1;\n \n await projectState.updateGoal(goal.id, {\n metadata: {\n ...metadata,\n fixedCount,\n lastFixed: new Date().toISOString(),\n lastFixedFile: file,\n },\n });\n \n // Resolve the goal-violation issue in the issue store\n // This is the source of truth - measureGoalMetric() will query from here\n const { resolveGoalViolation } = await import('../memory/issue-store.js');\n await resolveGoalViolation(file, goal.description, projectPath);\n \n // Trigger immediate progress update so UI reflects the fix\n const { getGoalManager } = await import('./goal-manager.js');\n const goalManager = getGoalManager(projectPath);\n await goalManager.updateGoalProgress();\n}\n\n/**\n * Measure the initial value for a new goal based on existing issues.\n * This sets a proper baseline so progress calculation works correctly.\n * \n * For reduction goals (like \"no emojis\"), we count current violations.\n * For other goals, we use semantic matching against existing issues.\n * \n * Returns the count to use as both startValue and currentValue.\n */\nexport async function measureInitialGoalValue(\n description: string,\n projectPath: string\n): Promise<number> {\n try {\n const issues = await searchIssues('', {\n workDir: projectPath,\n limit: 1000,\n includeResolved: false,\n });\n \n if (issues.length === 0) {\n return 0;\n }\n \n const desc = description.toLowerCase();\n \n // Check for goal-violation issues that might already exist for similar goals\n const goalViolations = issues.filter(r => \n r.issue.agent === 'goal-violation' &&\n r.issue.issue.toLowerCase().includes(desc.slice(0, 30))\n );\n if (goalViolations.length > 0) {\n return goalViolations.length;\n }\n \n // Security goals\n if (desc.includes('security') || desc.includes('vulnerab')) {\n return issues.filter(r => \n r.issue.agent === 'security' || r.issue.severity === 'critical'\n ).length;\n }\n \n // Type safety goals\n if (desc.includes('type') || desc.includes('typescript') || desc.includes('any type')) {\n return issues.filter(r => \n r.issue.agent === 'typecheck' ||\n r.issue.issue.toLowerCase().includes('type')\n ).length;\n }\n \n // Bug-related goals\n if (desc.includes('bug') || desc.includes('error')) {\n return issues.filter(r => \n r.issue.agent === 'bug-finding' ||\n r.issue.severity === 'critical' ||\n r.issue.severity === 'serious'\n ).length;\n }\n \n // Dead code / unused code goals\n if (desc.includes('dead code') || desc.includes('unused')) {\n return issues.filter(r => {\n const msg = r.issue.issue.toLowerCase();\n return msg.includes('unused') || msg.includes('dead code') || msg.includes('never used');\n }).length;\n }\n \n // For custom goals like \"no emojis\", we start at 0 and let the AI scanner find violations\n // This is correct because we don't know the count until a scan runs\n return 0;\n } catch {\n return 0;\n }\n}\n\n/**\n * Manually check files against goals\n * Returns violations found\n * \n * NOW WITH CACHING: Uses CodebaseIndex to avoid re-scanning unchanged files\n */\nexport async function checkFilesForGoalViolations(\n goals: Goal[],\n projectPath: string,\n filesToCheck?: string[],\n onProgress?: (message: string) => void\n): Promise<Array<{ file: string; message: string; severity: 'critical' | 'warning' | 'info' }>> {\n // Import AI client and codebase index\n const { isAIAvailable, runAIAnalysis } = await import('../ai/client.js');\n const { CodebaseIndex } = await import('../context/codebase-index.js');\n \n if (!isAIAvailable()) {\n throw new Error('AI not available - ANTHROPIC_API_KEY not set');\n }\n \n // Initialize codebase index for caching\n const codebaseIndex = new CodebaseIndex(projectPath);\n \n // Check if index needs to be built\n if (codebaseIndex.isEmpty()) {\n onProgress?.('Building codebase index (first-time, may take a minute)...');\n console.error('[Goal Check] Codebase index is empty - building index first...');\n console.error('[Goal Check] This is a one-time operation. Future checks will be much faster.');\n \n // Auto-index using same file selection as checks (most recently modified) so cache overlaps\n const { glob } = await import('glob');\n const { stat } = await import('fs/promises');\n const indexPattern = `${projectPath}/**/*.{ts,tsx,js,jsx,mjs,vue,svelte,astro,py,go,rs,java,c,cpp,h,hpp,cs,rb,php,css,scss,html}`;\n const indexFiles = await glob(indexPattern, {\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.trie/**', '**/coverage/**'],\n nodir: true,\n });\n \n const withStats = await Promise.all(\n indexFiles.map(async (f) => {\n try {\n const stats = await stat(f);\n return { file: f, mtime: stats.mtime.getTime() };\n } catch {\n return null;\n }\n })\n );\n const toIndex = withStats\n .filter((f): f is { file: string; mtime: number } => f !== null)\n .sort((a, b) => b.mtime - a.mtime)\n .slice(0, 500)\n .map((f) => f.file);\n \n let indexed = 0;\n for (const filePath of toIndex) {\n let relativePath = filePath;\n if (filePath.toLowerCase().startsWith(projectPath.toLowerCase() + '/')) {\n relativePath = filePath.slice(projectPath.length + 1);\n }\n const result = await codebaseIndex.indexFile(relativePath);\n if (result) indexed++;\n if (indexed % 50 === 0) {\n onProgress?.(`Indexing files (${indexed}/${toIndex.length})...`);\n }\n }\n \n await codebaseIndex.save();\n console.error(`[Goal Check] Index built: ${indexed} files indexed`);\n }\n \n // Get files to check\n let files: string[] = [];\n if (filesToCheck && filesToCheck.length > 0) {\n files = filesToCheck;\n } else {\n // MANUAL CHECK MODE: Scan ALL relevant files, not just recently modified\n const { glob } = await import('glob');\n \n const pattern = `${projectPath}/**/*.{ts,tsx,js,jsx,py,go,rs,java,c,cpp,h,hpp,cs,rb,php,css,scss,html,vue,svelte}`;\n const allFiles = await glob(pattern, {\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.trie/**', '**/coverage/**'],\n nodir: true,\n });\n \n // For manual checks, use more files but still reasonable limit\n // Sort by modification time to prioritize recently modified\n const { stat } = await import('fs/promises');\n const withStats = await Promise.all(\n allFiles.map(async (f) => {\n try {\n const stats = await stat(f);\n return { file: f, mtime: stats.mtime.getTime() };\n } catch {\n return null;\n }\n })\n );\n \n files = withStats\n .filter((f): f is { file: string; mtime: number } => f !== null)\n .sort((a, b) => b.mtime - a.mtime)\n .slice(0, 100) // Check up to 100 files for manual scans\n .map(f => f.file);\n }\n \n if (files.length === 0) {\n throw new Error('No files found to check');\n }\n\n // Pre-index the files we're about to check so cache lookups work.\n // The initial index may have indexed different files (first 500 from glob), while we check\n // the 100 most recently modified - these can have zero overlap, causing every run to scan.\n for (const filePath of files) {\n let rel = filePath;\n if (filePath.toLowerCase().startsWith(projectPath.toLowerCase() + '/')) {\n rel = filePath.slice(projectPath.length + 1);\n } else if (filePath.startsWith('/') && !filePath.toLowerCase().startsWith(projectPath.toLowerCase())) {\n continue;\n }\n await codebaseIndex.indexFile(rel);\n }\n \n // Check which files need scanning vs can use cached results\n const filesToScan: string[] = [];\n const cachedViolations: Array<{ file: string; message: string; severity: 'critical' | 'warning' | 'info' }> = [];\n \n for (const filePath of files) {\n // Handle case-insensitive filesystems (macOS) and ensure we get a proper relative path\n let relativePath = filePath;\n if (filePath.toLowerCase().startsWith(projectPath.toLowerCase() + '/')) {\n relativePath = filePath.slice(projectPath.length + 1);\n } else if (filePath.startsWith('/')) {\n // Already absolute but doesn't match projectPath - skip this file\n // This can happen with stale cache entries from different projects\n continue;\n }\n const hasChanged = await codebaseIndex.hasChanged(relativePath);\n \n if (hasChanged) {\n // File changed or not indexed - needs scanning\n // Try to index the file first; skip if it doesn't exist\n const indexed = await codebaseIndex.indexFile(relativePath);\n if (indexed) {\n filesToScan.push(filePath);\n }\n // If indexFile returns null, file doesn't exist - skip it silently\n } else {\n // File unchanged - check cache for each goal\n for (const goal of goals) {\n const cached = codebaseIndex.getCachedViolations(relativePath, goal.id);\n if (cached && cached.length > 0) {\n const violation = cached[0];\n if (violation && violation.found) {\n cachedViolations.push({\n file: relativePath,\n message: `Goal \"${goal.description}\" violated in ${relativePath}: ${violation.details || 'Violation found'} [${violation.confidence || 90}% confidence] (cached)`,\n severity: 'warning',\n });\n }\n } else {\n // No cache for this goal - needs scanning\n if (!filesToScan.includes(filePath)) {\n filesToScan.push(filePath);\n }\n }\n }\n }\n }\n \n onProgress?.(`Checking ${filesToScan.length} files for violations...`);\n console.error(`[Goal Check] ${files.length} files total, ${filesToScan.length} need scanning, ${files.length - filesToScan.length} using cache`);\n \n // Process files that need scanning in batches\n const allViolations: Array<{ file: string; message: string; severity: 'critical' | 'warning' | 'info' }> = [...cachedViolations];\n \n if (filesToScan.length === 0) {\n // All results from cache!\n await codebaseIndex.save();\n return allViolations;\n }\n \n // For large file sets, process in batches to avoid token limits\n const BATCH_SIZE = 25; // Process 25 files at a time\n \n const totalBatches = Math.ceil(filesToScan.length / BATCH_SIZE);\n for (let batchStart = 0; batchStart < filesToScan.length; batchStart += BATCH_SIZE) {\n const batchNum = Math.floor(batchStart / BATCH_SIZE) + 1;\n onProgress?.(`Analyzing files (batch ${batchNum}/${totalBatches})...`);\n const batchFiles = filesToScan.slice(batchStart, batchStart + BATCH_SIZE);\n \n // Read file contents for this batch\n const { readFile } = await import('fs/promises');\n const fileContents = await Promise.all(\n batchFiles.map(async (filePath) => {\n try {\n const content = await readFile(filePath, 'utf-8');\n const relativePath = filePath.replace(projectPath + '/', '');\n return {\n path: relativePath,\n content: content.slice(0, 10000), // Increased limit for manual checks\n };\n } catch {\n return null;\n }\n })\n );\n \n const validFiles = fileContents.filter((f): f is { path: string; content: string } => f !== null);\n \n if (validFiles.length === 0) continue;\n \n // Build files block for AI\n const filesBlock = validFiles\n .map(f => `--- ${f.path} ---\\n${f.content}`)\n .join('\\n\\n');\n \n // Build goals section\n const goalsSection = `\nUSER-DEFINED GOALS (check EVERY file against ALL goals):\n${goals.map((g, i) => ` ${i + 1}. \"${g.description}\"`).join('\\n')}\n\nThis is a MANUAL CHECK requested by the user. Report ALL goal violations you find.\nFor emoji detection, look for Unicode emoji characters.\n`;\n \n // Run AI analysis\n const result = await runAIAnalysis({\n systemPrompt: `You are checking code for GOAL VIOLATIONS ONLY.\n${goalsSection}\nReply ONLY with a JSON array. Each element must have:\n- \"file\": relative file path\n- \"severity\": \"critical\" | \"major\" | \"minor\"\n- \"description\": 1-sentence description of the goal violation with specific examples\n- \"confidence\": number 0-100, how confident you are this is a violation\n- \"isGoalViolation\": true (always true for this scan)\n- \"goalIndex\": 0-based index of the violated goal\n\nCRITICAL DETECTION RULES:\n\n**EMOJIS**: Any Unicode emoji characters including but not limited to:\n- Emoticons: 😀😃😄😊🙂🙃😉😇🥰😍🤩😘😗☺️😚😙🥲\n- Symbols: ⚡️⚠️✅❌➜→←↑↓►◄▲▼★☆●○◆◇■□▪️▫️\n- Objects: 📊📈📉💻🖥️📱⌨️🖱️💾💿📀🔧🔨⚙️🛠️\n- Actions: 🔥💪👍👎👏🙌🤝✊👊🎯🎉🎊🚀\n- Weather: ☀️🌤️⛅☁️🌦️🌧️⛈️🌩️🌨️❄️\n- ALL OTHER Unicode emoji in ranges U+1F300-U+1F9FF, U+2600-U+27BF, U+2B00-U+2BFF\n\n**COLORS**: For \"purple\" or \"gradient\" goals, check:\n- CSS: purple, #purple, hsl(purple), rgb(purple), violet, #8B00FF, #9B59D6, etc.\n- Gradients: linear-gradient, radial-gradient, conic-gradient, background-image with gradients\n- Tailwind: purple-*, violet-*, bg-gradient-*\n- Styled components or CSS-in-JS with purple/violet/gradient\n\nBe EXTREMELY thorough. Check:\n1. String literals and template literals\n2. JSX/HTML content\n3. CSS files and style blocks\n4. Comments (emojis in comments still violate \"no emojis\")\n5. console.log statements\n6. Component names, variable names (if they contain emojis)\n\nIf a goal says \"no emojis\" and you see ANY emoji ANYWHERE in the file, report it.\nIf a goal says \"no console.log\" and you see console.log ANYWHERE, report it.\nIf a goal says \"no purple/gradient\" and you see ANY purple color or gradient, report it.\n\nIf no violations found, reply with: []\nOutput ONLY the JSON array, no markdown fences, no commentary.`,\n userPrompt: `Check these ${validFiles.length} files for goal violations:\\n\\n${filesBlock}`,\n maxTokens: 8192, // Increased for larger codebases\n temperature: 0.1,\n });\n \n // Parse response\n let issues: Array<{\n file: string;\n severity: 'critical' | 'major' | 'minor';\n description: string;\n confidence: number;\n isGoalViolation: boolean;\n goalIndex?: number;\n }> = [];\n \n try {\n const cleaned = result.content.replace(/```json?\\n?|\\n?```/g, '').trim();\n issues = JSON.parse(cleaned);\n if (!Array.isArray(issues)) issues = [];\n } catch (err) {\n // Parse failed - continue to next batch\n console.debug('[Goal Check] Batch parse failed:', err);\n continue;\n }\n \n // Convert to violation format and record\n for (const issue of issues) {\n if (!issue.isGoalViolation || issue.confidence < 50) continue;\n if (issue.goalIndex == null || issue.goalIndex < 0 || issue.goalIndex >= goals.length) continue;\n \n const goal = goals[issue.goalIndex];\n if (!goal) continue; // Defensive check\n const severity = issue.severity === 'critical' ? 'critical' : 'warning';\n const message = `Goal \"${goal.description}\" violated in ${issue.file}: ${issue.description} [${issue.confidence}% confidence]`;\n \n allViolations.push({\n file: issue.file,\n message,\n severity,\n });\n \n // Cache the result in codebase index\n codebaseIndex.recordViolation(\n issue.file,\n goal.id,\n goal.description,\n true, // found\n issue.description,\n issue.confidence\n );\n \n // Record violation\n await recordGoalViolationCaught(goal, issue.file, projectPath);\n }\n \n // Also record \"no violation\" for scanned files\n for (const file of validFiles) {\n for (let goalIdx = 0; goalIdx < goals.length; goalIdx++) {\n const goal = goals[goalIdx];\n if (!goal) continue;\n const hasViolation = issues.some(i => i.file === file.path && i.goalIndex === goalIdx);\n if (!hasViolation) {\n codebaseIndex.recordViolation(\n file.path,\n goal.id,\n goal.description,\n false, // not found\n undefined,\n 100\n );\n }\n }\n }\n }\n \n // Save updated index\n await codebaseIndex.save();\n \n return allViolations;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/autonomy-config.ts","../src/types/autonomy.ts"],"sourcesContent":["/**\n * Autonomy Configuration Loader\n * \n * Loads, saves, and manages autonomy settings from .trie/config.json\n */\n\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getTrieDirectory } from './workspace.js';\nimport type { \n AutonomyConfig, \n IssueOccurrence,\n AutoFixAction,\n PushBlockResult \n} from '../types/autonomy.js';\nimport { DEFAULT_AUTONOMY_CONFIG } from '../types/autonomy.js';\nimport { createHash } from 'crypto';\n\n// ============================================================================\n// Config Loading/Saving\n// ============================================================================\n\n/**\n * Load autonomy config from .trie/config.json\n */\nexport async function loadAutonomyConfig(projectPath: string): Promise<AutonomyConfig> {\n const configPath = join(getTrieDirectory(projectPath), 'config.json');\n \n try {\n if (!existsSync(configPath)) {\n return { ...DEFAULT_AUTONOMY_CONFIG };\n }\n \n const content = await readFile(configPath, 'utf-8');\n const config = JSON.parse(content);\n \n // Merge with defaults to ensure all fields exist\n return mergeWithDefaults(config.autonomy || {});\n } catch (error) {\n console.error('Failed to load autonomy config:', error);\n return { ...DEFAULT_AUTONOMY_CONFIG };\n }\n}\n\n/**\n * Save autonomy config to .trie/config.json\n */\nexport async function saveAutonomyConfig(\n projectPath: string, \n autonomyConfig: Partial<AutonomyConfig>\n): Promise<void> {\n const configPath = join(getTrieDirectory(projectPath), 'config.json');\n const trieDir = getTrieDirectory(projectPath);\n \n try {\n // Ensure .trie directory exists\n if (!existsSync(trieDir)) {\n await mkdir(trieDir, { recursive: true });\n }\n \n // Load existing config\n let fullConfig: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n const content = await readFile(configPath, 'utf-8');\n fullConfig = JSON.parse(content);\n }\n \n // Merge autonomy config\n fullConfig.autonomy = mergeWithDefaults(autonomyConfig);\n \n // Save atomically\n const tempPath = configPath + '.tmp';\n await writeFile(tempPath, JSON.stringify(fullConfig, null, 2));\n await writeFile(configPath, JSON.stringify(fullConfig, null, 2));\n \n } catch (error) {\n console.error('Failed to save autonomy config:', error);\n throw error;\n }\n}\n\n/**\n * Merge partial config with defaults\n */\nfunction mergeWithDefaults(partial: Partial<AutonomyConfig>): AutonomyConfig {\n return {\n level: partial.level ?? DEFAULT_AUTONOMY_CONFIG.level,\n autoCheck: {\n ...DEFAULT_AUTONOMY_CONFIG.autoCheck,\n ...(partial.autoCheck || {}),\n },\n autoFix: {\n ...DEFAULT_AUTONOMY_CONFIG.autoFix,\n ...(partial.autoFix || {}),\n },\n pushBlocking: {\n ...DEFAULT_AUTONOMY_CONFIG.pushBlocking,\n ...(partial.pushBlocking || {}),\n },\n progressiveEscalation: {\n ...DEFAULT_AUTONOMY_CONFIG.progressiveEscalation,\n ...(partial.progressiveEscalation || {}),\n thresholds: {\n ...DEFAULT_AUTONOMY_CONFIG.progressiveEscalation.thresholds,\n ...(partial.progressiveEscalation?.thresholds || {}),\n },\n },\n aiWatcher: {\n ...DEFAULT_AUTONOMY_CONFIG.aiWatcher,\n ...(partial.aiWatcher || {}),\n },\n };\n}\n\n// ============================================================================\n// Issue Occurrence Tracking (for progressive escalation)\n// ============================================================================\n\nconst occurrenceCache = new Map<string, Map<string, IssueOccurrence>>();\n\n/**\n * Get occurrence tracker for a project\n */\nasync function getOccurrences(projectPath: string): Promise<Map<string, IssueOccurrence>> {\n if (occurrenceCache.has(projectPath)) {\n return occurrenceCache.get(projectPath)!;\n }\n \n const occurrencesPath = join(getTrieDirectory(projectPath), 'memory', 'occurrences.json');\n const occurrences = new Map<string, IssueOccurrence>();\n \n try {\n if (existsSync(occurrencesPath)) {\n const content = await readFile(occurrencesPath, 'utf-8');\n const data = JSON.parse(content);\n for (const [hash, occ] of Object.entries(data)) {\n occurrences.set(hash, occ as IssueOccurrence);\n }\n }\n } catch {\n // Start fresh\n }\n \n occurrenceCache.set(projectPath, occurrences);\n return occurrences;\n}\n\n/**\n * Save occurrences to disk\n */\nasync function saveOccurrences(projectPath: string): Promise<void> {\n const occurrences = occurrenceCache.get(projectPath);\n if (!occurrences) return;\n \n const occurrencesPath = join(getTrieDirectory(projectPath), 'memory', 'occurrences.json');\n const memoryDir = join(getTrieDirectory(projectPath), 'memory');\n \n try {\n if (!existsSync(memoryDir)) {\n await mkdir(memoryDir, { recursive: true });\n }\n \n const data: Record<string, IssueOccurrence> = {};\n for (const [hash, occ] of occurrences.entries()) {\n data[hash] = occ;\n }\n \n await writeFile(occurrencesPath, JSON.stringify(data, null, 2));\n } catch (error) {\n console.error('Failed to save occurrences:', error);\n }\n}\n\n/**\n * Create a hash for an issue (for deduplication)\n */\nexport function createIssueHash(file: string, line: number | undefined, issueType: string): string {\n const input = `${file}:${line || 0}:${issueType}`;\n return createHash('md5').update(input).digest('hex').slice(0, 12);\n}\n\n/**\n * Track an issue occurrence\n */\nexport async function trackIssueOccurrence(\n projectPath: string,\n file: string,\n line: number | undefined,\n issueType: string,\n config: AutonomyConfig\n): Promise<IssueOccurrence> {\n const occurrences = await getOccurrences(projectPath);\n const hash = createIssueHash(file, line, issueType);\n const now = Date.now();\n \n let occurrence = occurrences.get(hash);\n \n if (occurrence) {\n // Check if within time window\n const windowMs = config.progressiveEscalation.windowMs;\n if (now - occurrence.firstSeen > windowMs) {\n // Reset if outside window\n occurrence = {\n hash,\n firstSeen: now,\n lastSeen: now,\n count: 1,\n escalationLevel: 'suggest',\n notified: false,\n bypassed: false,\n bypassHistory: occurrence.bypassHistory, // Keep bypass history\n };\n } else {\n // Increment within window\n occurrence.lastSeen = now;\n occurrence.count++;\n \n // Update escalation level\n const thresholds = config.progressiveEscalation.thresholds;\n if (occurrence.count >= thresholds.block) {\n occurrence.escalationLevel = 'block';\n } else if (occurrence.count >= thresholds.escalate) {\n occurrence.escalationLevel = 'escalate';\n } else if (occurrence.count >= thresholds.autoCheck) {\n occurrence.escalationLevel = 'autoCheck';\n }\n }\n } else {\n // New occurrence\n occurrence = {\n hash,\n firstSeen: now,\n lastSeen: now,\n count: 1,\n escalationLevel: 'suggest',\n notified: false,\n bypassed: false,\n bypassHistory: [],\n };\n }\n \n occurrences.set(hash, occurrence);\n await saveOccurrences(projectPath);\n \n return occurrence;\n}\n\n/**\n * Get escalation level for an issue\n */\nexport async function getEscalationLevel(\n projectPath: string,\n file: string,\n line: number | undefined,\n issueType: string\n): Promise<IssueOccurrence['escalationLevel']> {\n const occurrences = await getOccurrences(projectPath);\n const hash = createIssueHash(file, line, issueType);\n \n const occurrence = occurrences.get(hash);\n return occurrence?.escalationLevel ?? 'suggest';\n}\n\n/**\n * Record a bypass\n */\nexport async function recordBypass(\n projectPath: string,\n file: string,\n line: number | undefined,\n issueType: string,\n method: string,\n reason?: string\n): Promise<void> {\n const occurrences = await getOccurrences(projectPath);\n const hash = createIssueHash(file, line, issueType);\n \n const occurrence = occurrences.get(hash);\n if (occurrence) {\n occurrence.bypassed = true;\n occurrence.bypassHistory.push({\n timestamp: Date.now(),\n method,\n ...(reason !== undefined ? { reason } : {}),\n });\n await saveOccurrences(projectPath);\n }\n}\n\n// ============================================================================\n// Auto-fix Helpers\n// ============================================================================\n\n/**\n * Check if a fix should be auto-applied based on config\n */\nexport function shouldAutoFix(\n fix: AutoFixAction,\n config: AutonomyConfig\n): boolean {\n if (!config.autoFix.enabled) {\n return false;\n }\n \n // Check if category is allowed\n const allowedCategories = config.autoFix.categories as string[];\n if (!allowedCategories.includes(fix.category) && \n !allowedCategories.includes('all')) {\n return false;\n }\n \n // Check if specific fix type is allowed\n if (config.autoFix.allowedFixTypes.length > 0 &&\n !config.autoFix.allowedFixTypes.includes(fix.type)) {\n return false;\n }\n \n // Check confidence threshold (require high confidence for auto-fix)\n if (fix.confidence < 0.9) {\n return false;\n }\n \n return true;\n}\n\n/**\n * Group fixes by file for batch application\n */\nexport function groupFixesByFile(fixes: AutoFixAction[]): Map<string, AutoFixAction[]> {\n const grouped = new Map<string, AutoFixAction[]>();\n \n for (const fix of fixes) {\n const existing = grouped.get(fix.file) || [];\n existing.push(fix);\n grouped.set(fix.file, existing);\n }\n \n return grouped;\n}\n\n// ============================================================================\n// Push Blocking Helpers\n// ============================================================================\n\n/**\n * Check if push should be blocked\n */\nexport function shouldBlockPush(\n issues: Array<{ severity: string; file: string; line?: number; issue: string }>,\n config: AutonomyConfig\n): PushBlockResult {\n if (!config.pushBlocking.enabled) {\n return {\n blocked: false,\n blockingIssues: [],\n bypassed: false,\n };\n }\n \n // Find blocking issues\n const blockingIssues = issues.filter(issue => \n config.pushBlocking.blockOn.includes(issue.severity as 'critical' | 'serious' | 'moderate')\n );\n \n if (blockingIssues.length === 0) {\n return {\n blocked: false,\n blockingIssues: [],\n bypassed: false,\n };\n }\n \n // Check for bypass\n const envBypass = process.env.TRIE_BYPASS === '1' || process.env.TRIE_BYPASS === 'true';\n \n if (envBypass && config.pushBlocking.allowBypass) {\n return {\n blocked: false,\n blockingIssues,\n bypassed: true,\n bypassMethod: 'env',\n };\n }\n \n // Build bypass instructions\n const bypassInstructions = buildBypassInstructions(config);\n \n return {\n blocked: true,\n reason: `${blockingIssues.length} ${blockingIssues[0]?.severity || 'critical'} issue(s) must be fixed before pushing`,\n blockingIssues,\n bypassInstructions,\n bypassed: false,\n };\n}\n\n/**\n * Build bypass instructions based on config\n */\nfunction buildBypassInstructions(config: AutonomyConfig): string {\n const instructions: string[] = [];\n \n if (config.pushBlocking.bypassMethods.includes('env')) {\n instructions.push('• Set TRIE_BYPASS=1 to bypass: TRIE_BYPASS=1 git push');\n }\n \n if (config.pushBlocking.bypassMethods.includes('flag')) {\n instructions.push('• Use --no-verify flag: git push --no-verify');\n }\n \n if (config.pushBlocking.bypassMethods.includes('confirm')) {\n instructions.push('• Run: trie bypass --confirm to bypass this push');\n }\n \n return instructions.join('\\n');\n}\n\n// ============================================================================\n// Singleton Config Cache\n// ============================================================================\n\nconst configCache = new Map<string, { config: AutonomyConfig; loadedAt: number }>();\nconst CACHE_TTL = 60000; // 1 minute\n\n/**\n * Get autonomy config with caching\n */\nexport async function getAutonomyConfig(projectPath: string): Promise<AutonomyConfig> {\n const cached = configCache.get(projectPath);\n \n if (cached && Date.now() - cached.loadedAt < CACHE_TTL) {\n return cached.config;\n }\n \n const config = await loadAutonomyConfig(projectPath);\n configCache.set(projectPath, { config, loadedAt: Date.now() });\n \n return config;\n}\n\n/**\n * Clear config cache (for testing or after config changes)\n */\nexport function clearConfigCache(): void {\n configCache.clear();\n occurrenceCache.clear();\n}\n","/**\n * Autonomy Configuration Types\n * \n * Controls how autonomous Trie behaves:\n * - Auto-check: Run full checks when issues detected\n * - Auto-fix: Apply fixes with human confirmation\n * - Push blocking: Block git push on critical issues\n * - Progressive escalation: Escalate based on occurrence count\n */\n\n/**\n * Overall autonomy level\n */\nexport type AutonomyLevel = \n | 'passive' // Only report, never act\n | 'suggest' // Suggest actions, don't execute\n | 'proactive' // Auto-check, ask before fixing\n | 'aggressive'; // Auto-check, auto-fix trivial, block on critical\n\n/**\n * Auto-check configuration\n */\nexport interface AutoCheckConfig {\n /** Enable auto-running full checks */\n enabled: boolean;\n /** Issue count threshold to trigger auto-check */\n threshold: number;\n /** Always trigger on critical issues */\n onCritical: boolean;\n /** Cooldown between auto-checks (ms) */\n cooldownMs: number;\n}\n\n/**\n * Auto-fix configuration\n */\nexport interface AutoFixConfig {\n /** Enable auto-fix suggestions */\n enabled: boolean;\n /** Always ask user before applying fixes (human-in-the-loop) */\n askFirst: boolean;\n /** Categories of fixes to auto-apply */\n categories: ('trivial' | 'safe' | 'moderate' | 'all')[];\n /** Specific fix types to auto-apply */\n allowedFixTypes: string[];\n}\n\n/**\n * Push blocking configuration\n */\nexport interface PushBlockingConfig {\n /** Enable push blocking */\n enabled: boolean;\n /** Allow user to bypass with flag */\n allowBypass: boolean;\n /** Severities that trigger blocking */\n blockOn: ('critical' | 'serious' | 'moderate')[];\n /** Bypass methods */\n bypassMethods: ('env' | 'flag' | 'confirm')[];\n /** Log bypasses for audit */\n logBypasses: boolean;\n}\n\n/**\n * Progressive escalation thresholds\n */\nexport interface ProgressiveEscalationConfig {\n /** Enable progressive escalation */\n enabled: boolean;\n /** Thresholds for different actions */\n thresholds: {\n /** First occurrence: suggest fix */\n suggest: number;\n /** N occurrences: auto-run full check */\n autoCheck: number;\n /** N occurrences: escalate to Slack/email */\n escalate: number;\n /** N occurrences: block until fixed */\n block: number;\n };\n /** Time window for counting occurrences (ms) */\n windowMs: number;\n}\n\n/**\n * AI Watcher configuration -- controls the Claude-powered file watcher\n */\nexport interface AIWatcherConfig {\n /** Enable AI-powered file watching */\n enabled: boolean;\n /** Max tokens to spend per hour on AI scans */\n hourlyTokenLimit: number;\n /** Minimum seconds between AI scans */\n scanCooldownSec: number;\n /** Seconds before re-scanning a file that was clean */\n cleanFileCooldownSec: number;\n /** Max files to include in a single AI scan */\n maxFilesPerScan: number;\n /** Max characters to send per file */\n maxCharsPerFile: number;\n}\n\n/**\n * Full autonomy configuration\n */\nexport interface AutonomyConfig {\n /** Overall autonomy level (can be overridden by specific settings) */\n level: AutonomyLevel;\n /** Auto-check settings */\n autoCheck: AutoCheckConfig;\n /** Auto-fix settings */\n autoFix: AutoFixConfig;\n /** Push blocking settings */\n pushBlocking: PushBlockingConfig;\n /** Progressive escalation settings */\n progressiveEscalation: ProgressiveEscalationConfig;\n /** AI watcher settings (Claude-powered file scanning) */\n aiWatcher: AIWatcherConfig;\n}\n\n/**\n * Default autonomy configuration - proactive but safe\n */\nexport const DEFAULT_AUTONOMY_CONFIG: AutonomyConfig = {\n level: 'proactive',\n autoCheck: {\n enabled: true,\n threshold: 5,\n onCritical: true,\n cooldownMs: 30000, // 30 seconds\n },\n autoFix: {\n enabled: true,\n askFirst: true, // Always ask (human-in-the-loop)\n categories: ['trivial', 'safe'],\n allowedFixTypes: [\n 'remove-console-log',\n 'remove-debugger',\n 'remove-emoji',\n 'remove-unused-import',\n 'add-missing-await',\n 'fix-typo',\n ],\n },\n pushBlocking: {\n enabled: true,\n allowBypass: true,\n blockOn: ['critical'],\n bypassMethods: ['env', 'flag', 'confirm'],\n logBypasses: true,\n },\n progressiveEscalation: {\n enabled: true,\n thresholds: {\n suggest: 1,\n autoCheck: 3,\n escalate: 5,\n block: 10,\n },\n windowMs: 24 * 60 * 60 * 1000, // 24 hours\n },\n aiWatcher: {\n enabled: true,\n hourlyTokenLimit: 50_000,\n scanCooldownSec: 30,\n cleanFileCooldownSec: 300,\n maxFilesPerScan: 5,\n maxCharsPerFile: 4000,\n },\n};\n\n/**\n * Issue occurrence tracking for progressive escalation\n */\nexport interface IssueOccurrence {\n /** Issue hash (file + line + type) */\n hash: string;\n /** First seen timestamp */\n firstSeen: number;\n /** Last seen timestamp */\n lastSeen: number;\n /** Total occurrence count */\n count: number;\n /** Current escalation level */\n escalationLevel: 'suggest' | 'autoCheck' | 'escalate' | 'block';\n /** Whether user has been notified at current level */\n notified: boolean;\n /** Whether issue has been bypassed */\n bypassed: boolean;\n /** Bypass history */\n bypassHistory: Array<{\n timestamp: number;\n method: string;\n reason?: string;\n }>;\n}\n\n/**\n * Auto-fix action\n */\nexport interface AutoFixAction {\n /** Unique ID for this fix */\n id: string;\n /** File to fix */\n file: string;\n /** Line number */\n line?: number;\n /** Original code */\n original: string;\n /** Fixed code */\n fixed: string;\n /** Type of fix */\n type: 'remove-console-log' | 'remove-debugger' | 'remove-emoji' | 'remove-unused-import' | \n 'add-missing-await' | 'fix-typo' | 'goal-violation' | 'custom' | string;\n /** Category of fix */\n category: 'trivial' | 'safe' | 'moderate' | 'risky' | 'goal-violation';\n /** Description of what the fix does */\n description: string;\n /** Confidence in the fix (0-1) */\n confidence: number;\n}\n\n/**\n * Push block result\n */\nexport interface PushBlockResult {\n /** Whether push is blocked */\n blocked: boolean;\n /** Reason for blocking */\n reason?: string;\n /** Issues causing the block */\n blockingIssues: Array<{\n file: string;\n line?: number;\n severity: string;\n issue: string;\n }>;\n /** Bypass instructions */\n bypassInstructions?: string;\n /** Whether user chose to bypass */\n bypassed: boolean;\n /** Bypass method used */\n bypassMethod?: string;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/graph.ts","../src/context/store.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport path from 'node:path';\n\nimport type { RiskLevel } from '../types/index.js';\nimport { ContextStore } from './store.js';\nimport type {\n ChangeNode,\n ChangeNodeData,\n ContextSnapshot,\n DecisionNode,\n DecisionNodeData,\n Edge,\n EdgeDirection,\n EdgeType,\n FileNode,\n FileNodeData,\n FixNode,\n FixNodeData,\n IncidentNode,\n IncidentNodeData,\n IssueNode,\n IssueNodeData,\n LinearTicketNode,\n LinearTicketNodeData,\n Node,\n NodeData,\n NodeType,\n PatternNode,\n PatternNodeData\n} from './types.js';\n\nexport class ContextGraph {\n private readonly store: ContextStore;\n private readonly projectPath: string;\n\n constructor(projectPath: string, dbPath?: string, store?: ContextStore) {\n this.projectPath = projectPath;\n this.store = store ?? new ContextStore(projectPath, dbPath);\n }\n\n get projectRoot(): string {\n return this.projectPath;\n }\n\n async addNode(type: 'file', data: FileNodeData): Promise<FileNode>;\n async addNode(type: 'change', data: ChangeNodeData): Promise<ChangeNode>;\n async addNode(type: 'incident', data: IncidentNodeData): Promise<IncidentNode>;\n async addNode(type: 'issue', data: IssueNodeData): Promise<IssueNode>;\n async addNode(type: 'pattern', data: PatternNodeData): Promise<PatternNode>;\n async addNode(type: 'fix', data: FixNodeData): Promise<FixNode>;\n async addNode(type: 'decision', data: DecisionNodeData): Promise<DecisionNode>;\n async addNode(type: 'linear-ticket', data: LinearTicketNodeData): Promise<LinearTicketNode>;\n async addNode(type: NodeType, data: NodeData): Promise<Node> {\n const now = new Date().toISOString();\n const id = this.generateNodeId(type, data);\n const node = {\n id,\n type,\n data,\n created_at: now,\n updated_at: now\n } as Node;\n\n this.store.addNode(node);\n return node;\n }\n\n async getNode(type: NodeType, id: string): Promise<Node | null> {\n return this.store.getNodeByType(type, id);\n }\n\n async updateNode(type: NodeType, id: string, updates: Partial<NodeData>): Promise<void> {\n const updated = this.store.updateNode(id, updates, new Date().toISOString());\n if (updated && updated.type !== type) {\n throw new Error(`Type mismatch for node ${id}: expected ${type} but found ${updated.type}`);\n }\n }\n\n async deleteNode(_type: NodeType, id: string): Promise<void> {\n this.store.deleteNode(id);\n }\n\n async addEdge(\n fromId: string,\n toId: string,\n type: EdgeType,\n metadata: Record<string, unknown> = {},\n weight = 1\n ): Promise<Edge> {\n const edge: Edge = {\n id: crypto.randomUUID(),\n from_id: fromId,\n to_id: toId,\n type,\n weight,\n metadata,\n created_at: new Date().toISOString()\n };\n\n this.store.addEdge(edge);\n return edge;\n }\n\n async getEdges(nodeId: string, direction: EdgeDirection = 'both'): Promise<Edge[]> {\n return this.store.getEdges(nodeId, direction);\n }\n\n async getIncidentsForFile(filePath: string): Promise<IncidentNode[]> {\n const fileNode = this.findFileNode(filePath);\n if (!fileNode) return [];\n\n const incidents = new Map<string, IncidentNode>();\n\n const affectEdges = this.store.getEdges(fileNode.id, 'in').filter((edge) => edge.type === 'affects');\n for (const edge of affectEdges) {\n const changeId = edge.from_id;\n const leadEdges = this.store.getEdges(changeId, 'out').filter((e) => e.type === 'leadTo');\n const causedByEdges = this.store.getEdges(changeId, 'in').filter((e) => e.type === 'causedBy');\n\n for (const le of leadEdges) {\n const incident = this.store.getNodeByType('incident', le.to_id);\n if (incident) incidents.set(incident.id, incident as IncidentNode);\n }\n\n for (const ce of causedByEdges) {\n const incident = this.store.getNodeByType('incident', ce.from_id);\n if (incident) incidents.set(incident.id, incident as IncidentNode);\n }\n }\n\n return Array.from(incidents.values());\n }\n\n async getPatternsForFile(filePath: string): Promise<PatternNode[]> {\n const normalized = this.normalizePath(filePath);\n const nodes = this.store.findNodesByType('pattern') as PatternNode[];\n\n return nodes.filter((node) =>\n node.data.appliesTo.some((pattern) => normalized.includes(pattern) || filePath.includes(pattern))\n );\n }\n\n async getRecentChanges(limit: number): Promise<ChangeNode[]> {\n const nodes = this.store.findNodesByType('change') as ChangeNode[];\n return nodes\n .sort((a, b) => new Date(b.data.timestamp).getTime() - new Date(a.data.timestamp).getTime())\n .slice(0, limit);\n }\n\n async calculateFileRisk(filePath: string): Promise<RiskLevel> {\n const fileNode = this.findFileNode(filePath);\n if (!fileNode) return 'low';\n\n // Simple heuristic based on incidents and changes\n const incidentScore = Math.min(fileNode.data.incidentCount * 2, 6);\n const changeScore = Math.min(fileNode.data.changeCount, 4);\n const baseScore = this.riskLevelToScore(fileNode.data.riskLevel);\n const total = baseScore + incidentScore + changeScore;\n\n if (total >= 10) return 'critical';\n if (total >= 7) return 'high';\n if (total >= 4) return 'medium';\n return 'low';\n }\n\n async listNodes(): Promise<Node[]> {\n return this.store.listNodes();\n }\n\n async listEdges(): Promise<Edge[]> {\n return this.store.listEdges();\n }\n\n async deleteEdge(id: string): Promise<void> {\n this.store.deleteEdge(id);\n }\n\n async getSnapshot(): Promise<ContextSnapshot> {\n return {\n nodes: this.store.listNodes(),\n edges: this.store.listEdges(),\n exported_at: new Date().toISOString()\n };\n }\n\n async applySnapshot(snapshot: ContextSnapshot): Promise<void> {\n for (const node of snapshot.nodes) {\n const existing = this.store.getNode(node.id);\n if (!existing || this.isNewer(node.updated_at, existing.updated_at)) {\n this.store.upsertNode(node);\n }\n }\n\n for (const edge of snapshot.edges) {\n const existing = this.store.getEdge(edge.id);\n if (!existing) {\n this.store.upsertEdge(edge);\n }\n }\n }\n\n private generateNodeId(type: NodeType, data: NodeData): string {\n if (type === 'file') {\n const fileData = data as FileNodeData;\n return this.normalizePath(fileData.path);\n }\n\n if (type === 'change') {\n const changeData = data as ChangeNodeData;\n if (changeData.commitHash) {\n return changeData.commitHash;\n }\n }\n\n if (type === 'linear-ticket') {\n const ticketData = data as LinearTicketNodeData;\n return `linear:${ticketData.ticketId}`;\n }\n\n return crypto.randomUUID();\n }\n\n private findFileNode(filePath: string): FileNode | null {\n const normalized = this.normalizePath(filePath);\n const nodes = this.store.findNodesByType('file') as FileNode[];\n return (\n nodes.find(\n (node) =>\n node.id === normalized ||\n this.normalizePath(node.data.path) === normalized ||\n node.data.path === filePath\n ) ?? null\n );\n }\n\n private normalizePath(filePath: string): string {\n return path.resolve(this.projectPath, filePath);\n }\n\n private riskLevelToScore(level: RiskLevel): number {\n switch (level) {\n case 'critical':\n return 6;\n case 'high':\n return 4;\n case 'medium':\n return 2;\n default:\n return 0;\n }\n }\n\n private isNewer(incoming: string, existing: string): boolean {\n return new Date(incoming).getTime() >= new Date(existing).getTime();\n }\n}\n","import Database, { type Database as DatabaseType } from 'better-sqlite3';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { getTrieDirectory } from '../utils/workspace.js';\n\nimport type { Edge, EdgeDirection, EdgeType, Node, NodeData, NodeType } from './types.js';\n\ntype NodeRow = {\n id: string;\n type: NodeType;\n data: string;\n created_at: string;\n updated_at: string;\n};\n\ntype EdgeRow = {\n id: string;\n from_id: string;\n to_id: string;\n type: EdgeType;\n weight: number;\n metadata: string | null;\n created_at: string;\n};\n\nexport class ContextStore {\n private db: DatabaseType;\n private readonly dbFilePath: string;\n\n constructor(projectPath: string, dbFilePath?: string) {\n this.dbFilePath = dbFilePath ?? path.join(getTrieDirectory(projectPath), 'context.db');\n this.ensureDirectory();\n\n this.db = new Database(this.dbFilePath);\n this.configure();\n this.prepareSchema();\n }\n\n get databasePath(): string {\n return this.dbFilePath;\n }\n\n addNode(node: Node): Node {\n const stmt = this.db.prepare(\n `INSERT INTO nodes (id, type, data, created_at, updated_at)\n VALUES (@id, @type, @data, @created_at, @updated_at)`\n );\n\n stmt.run({\n id: node.id,\n type: node.type,\n data: JSON.stringify(node.data),\n created_at: node.created_at,\n updated_at: node.updated_at\n });\n\n return node;\n }\n\n upsertNode(node: Node): Node {\n const stmt = this.db.prepare(\n `INSERT INTO nodes (id, type, data, created_at, updated_at)\n VALUES (@id, @type, @data, @created_at, @updated_at)\n ON CONFLICT(id) DO UPDATE SET\n type=excluded.type,\n data=excluded.data,\n updated_at=excluded.updated_at`\n );\n\n stmt.run({\n id: node.id,\n type: node.type,\n data: JSON.stringify(node.data),\n created_at: node.created_at,\n updated_at: node.updated_at\n });\n\n return node;\n }\n\n getNode(id: string): Node | null {\n const row = this.db.prepare('SELECT * FROM nodes WHERE id = ?').get(id) as NodeRow | undefined;\n return row ? this.mapNodeRow(row) : null;\n }\n\n getNodeByType(type: NodeType, id: string): Node | null {\n const row = this.db\n .prepare('SELECT * FROM nodes WHERE id = ? AND type = ?')\n .get(id, type) as NodeRow | undefined;\n return row ? this.mapNodeRow(row) : null;\n }\n\n updateNode(id: string, updates: Partial<NodeData>, updatedAt: string): Node | null {\n const existing = this.getNode(id);\n if (!existing) {\n return null;\n }\n\n const merged = {\n ...existing,\n data: { ...existing.data, ...updates },\n updated_at: updatedAt\n } as Node;\n\n this.db\n .prepare(\n `UPDATE nodes SET data = @data, updated_at = @updated_at\n WHERE id = @id`\n )\n .run({\n id,\n data: JSON.stringify(merged.data),\n updated_at: merged.updated_at\n });\n\n return merged;\n }\n\n deleteNode(id: string): void {\n const deleteEdges = this.db.prepare('DELETE FROM edges WHERE from_id = ? OR to_id = ?');\n const deleteNodeStmt = this.db.prepare('DELETE FROM nodes WHERE id = ?');\n\n const transaction = this.db.transaction((nodeId: string) => {\n deleteEdges.run(nodeId, nodeId);\n deleteNodeStmt.run(nodeId);\n });\n\n transaction(id);\n }\n\n listNodes(): Node[] {\n const rows = this.db.prepare('SELECT * FROM nodes').all() as NodeRow[];\n return rows.map((row) => this.mapNodeRow(row));\n }\n\n findNodesByType(type: NodeType): Node[] {\n const rows = this.db.prepare('SELECT * FROM nodes WHERE type = ?').all(type) as NodeRow[];\n return rows.map((row) => this.mapNodeRow(row));\n }\n\n addEdge(edge: Edge): Edge {\n const stmt = this.db.prepare(\n `INSERT INTO edges (id, from_id, to_id, type, weight, metadata, created_at)\n VALUES (@id, @from_id, @to_id, @type, @weight, @metadata, @created_at)`\n );\n\n stmt.run({\n id: edge.id,\n from_id: edge.from_id,\n to_id: edge.to_id,\n type: edge.type,\n weight: edge.weight,\n metadata: JSON.stringify(edge.metadata ?? {}),\n created_at: edge.created_at\n });\n\n return edge;\n }\n\n upsertEdge(edge: Edge): Edge {\n const stmt = this.db.prepare(\n `INSERT INTO edges (id, from_id, to_id, type, weight, metadata, created_at)\n VALUES (@id, @from_id, @to_id, @type, @weight, @metadata, @created_at)\n ON CONFLICT(id) DO UPDATE SET\n from_id=excluded.from_id,\n to_id=excluded.to_id,\n type=excluded.type,\n weight=excluded.weight,\n metadata=excluded.metadata`\n );\n\n stmt.run({\n id: edge.id,\n from_id: edge.from_id,\n to_id: edge.to_id,\n type: edge.type,\n weight: edge.weight,\n metadata: JSON.stringify(edge.metadata ?? {}),\n created_at: edge.created_at\n });\n\n return edge;\n }\n\n getEdge(id: string): Edge | null {\n const row = this.db.prepare('SELECT * FROM edges WHERE id = ?').get(id) as EdgeRow | undefined;\n return row ? this.mapEdgeRow(row) : null;\n }\n\n getEdges(nodeId: string, direction: EdgeDirection = 'both'): Edge[] {\n let rows: EdgeRow[];\n\n if (direction === 'in') {\n rows = this.db.prepare('SELECT * FROM edges WHERE to_id = ?').all(nodeId) as EdgeRow[];\n } else if (direction === 'out') {\n rows = this.db.prepare('SELECT * FROM edges WHERE from_id = ?').all(nodeId) as EdgeRow[];\n } else {\n rows = this.db\n .prepare('SELECT * FROM edges WHERE from_id = ? OR to_id = ?')\n .all(nodeId, nodeId) as EdgeRow[];\n }\n\n return rows.map((row) => this.mapEdgeRow(row));\n }\n\n listEdges(): Edge[] {\n const rows = this.db.prepare('SELECT * FROM edges').all() as EdgeRow[];\n return rows.map((row) => this.mapEdgeRow(row));\n }\n\n deleteEdge(id: string): void {\n this.db.prepare('DELETE FROM edges WHERE id = ?').run(id);\n }\n\n close(): void {\n this.db.close();\n }\n\n private ensureDirectory(): void {\n fs.mkdirSync(path.dirname(this.dbFilePath), { recursive: true });\n }\n\n private configure(): void {\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('busy_timeout = 5000');\n this.db.pragma('synchronous = NORMAL');\n }\n\n private prepareSchema(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS nodes (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n data TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS edges (\n id TEXT PRIMARY KEY,\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n type TEXT NOT NULL,\n weight REAL NOT NULL DEFAULT 1,\n metadata TEXT DEFAULT '{}',\n created_at TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type);\n CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id);\n CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id);\n CREATE INDEX IF NOT EXISTS idx_edges_type ON edges(type);\n `);\n }\n\n private mapNodeRow(row: NodeRow): Node {\n return {\n id: row.id,\n type: row.type,\n data: JSON.parse(row.data),\n created_at: row.created_at,\n updated_at: row.updated_at\n } as Node;\n }\n\n private mapEdgeRow(row: EdgeRow): Edge {\n return {\n id: row.id,\n from_id: row.from_id,\n to_id: row.to_id,\n type: row.type,\n weight: row.weight,\n created_at: row.created_at,\n metadata: row.metadata ? (JSON.parse(row.metadata) as Record<string, unknown>) : {}\n };\n }\n}\n"],"mappings":"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","names":["path","path"]}
|