@triedotdev/mcp 1.0.149 → 1.0.154
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/LICENSE +21 -0
- package/README.md +150 -36
- package/dist/{autonomy-config-ZCOSTMPD.js → autonomy-config-RKLZW4XL.js} +4 -4
- package/dist/{chat-store-OJLJCJFI.js → chat-store-O3IJ5PMN.js} +4 -4
- package/dist/{chunk-IXO4G4D3.js → chunk-2LAJKFWU.js} +2 -2
- package/dist/{chunk-23RJT5WT.js → chunk-3CYMLM35.js} +2 -2
- package/dist/{chunk-QH77RQB3.js → chunk-4ZAFQEP6.js} +5 -6
- package/dist/chunk-4ZAFQEP6.js.map +1 -0
- package/dist/{chunk-SH7H3WRU.js → chunk-7F2R2ITA.js} +4 -4
- package/dist/{chunk-SH7H3WRU.js.map → chunk-7F2R2ITA.js.map} +1 -1
- package/dist/{chunk-FG467PDD.js → chunk-ALSCZ7WR.js} +2 -2
- package/dist/{chunk-YOJGSRZK.js → chunk-CBAMZERA.js} +2 -2
- package/dist/{chunk-53KUI7RQ.js → chunk-EMJ7RVWB.js} +38 -13
- package/dist/{chunk-53KUI7RQ.js.map → chunk-EMJ7RVWB.js.map} +1 -1
- package/dist/{chunk-NKHO34UZ.js → chunk-FTOF3FHT.js} +3 -3
- package/dist/{chunk-LD7ZEFNY.js → chunk-FXZAABXO.js} +2 -2
- package/dist/{chunk-ZUEAHFSY.js → chunk-HD5H7YSW.js} +313 -61
- package/dist/chunk-HD5H7YSW.js.map +1 -0
- package/dist/{chunk-APMV77PU.js → chunk-JKEEQAG2.js} +1 -1
- package/dist/chunk-JKEEQAG2.js.map +1 -0
- package/dist/{chunk-FH335WL5.js → chunk-JYWGYUKX.js} +2 -2
- package/dist/{chunk-TIMIKBY2.js → chunk-KLMJKM63.js} +2 -2
- package/dist/{chunk-4C67GV3O.js → chunk-KYKADM7P.js} +2 -2
- package/dist/{chunk-CU5VDH6F.js → chunk-L4FODDDB.js} +2 -2
- package/dist/{chunk-ILGMFND2.js → chunk-LFNH3CSN.js} +4 -4
- package/dist/{chunk-GAL7OIYU.js → chunk-LJISDV3A.js} +15 -15
- package/dist/{chunk-72KSLD7A.js → chunk-NVZZUUEU.js} +5 -5
- package/dist/{chunk-7OJ6JIPL.js → chunk-OVSYTWUU.js} +7 -150
- package/dist/chunk-OVSYTWUU.js.map +1 -0
- package/dist/{chunk-B2AHQ2IR.js → chunk-OWSGJUUR.js} +12 -12
- package/dist/{chunk-HYNDXZAU.js → chunk-QAM5X5HM.js} +1535 -90
- package/dist/chunk-QAM5X5HM.js.map +1 -0
- package/dist/{chunk-OTQEFXHU.js → chunk-T7UAH7GE.js} +2 -2
- package/dist/{chunk-FPEMP54L.js → chunk-UL337UDQ.js} +2 -2
- package/dist/{chunk-F4NJ4CBP.js → chunk-WO7CC5FH.js} +2 -2
- package/dist/{chunk-5KJ4UJOY.js → chunk-XD2HKZVB.js} +2 -2
- package/dist/{chunk-V7AY2EJO.js → chunk-YEQXKKZQ.js} +2 -2
- package/dist/{chunk-ZDDE442Q.js → chunk-Z2E7X4WI.js} +8 -8
- package/dist/{chunk-ZDDE442Q.js.map → chunk-Z2E7X4WI.js.map} +1 -1
- package/dist/cli/create-agent.js +9 -41
- package/dist/cli/create-agent.js.map +1 -1
- package/dist/cli/main.js +58 -96
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +65 -28
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{client-INNE2GGZ.js → client-ZHOLZTRW.js} +4 -4
- package/dist/{codebase-index-FMIULFZQ.js → codebase-index-N37NDF2A.js} +4 -4
- package/dist/{fast-analyzer-CTT3MCPE.js → fast-analyzer-U6URGNQT.js} +6 -6
- package/dist/github-ingester-AR5A4RAC.js +11 -0
- package/dist/{goal-manager-IGUMDGCA.js → goal-manager-5QDITJKE.js} +8 -8
- package/dist/{goal-validator-DV6DRSGF.js → goal-validator-FU5QWDQT.js} +7 -7
- package/dist/graph-JO7GG65P.js +10 -0
- package/dist/{hypothesis-O72ZLVOW.js → hypothesis-JURDWVDC.js} +8 -8
- package/dist/incident-index-7CAXUNTL.js +11 -0
- package/dist/index.js +136 -1740
- package/dist/index.js.map +1 -1
- package/dist/{insight-store-Q62UGMTF.js → insight-store-AMEP5PPF.js} +4 -4
- package/dist/{issue-store-4FPABLC6.js → issue-store-RM3XLLKG.js} +5 -5
- package/dist/{ledger-43SIVE7X.js → ledger-PLE3C3X4.js} +14 -6
- package/dist/linear-ingester-NHFMKJBZ.js +11 -0
- package/dist/{output-manager-DZO5LGSG.js → output-manager-FX4V7ERT.js} +3 -3
- package/dist/{progress-PQVEM7BR.js → progress-PAYTY7BF.js} +2 -2
- package/dist/tiered-storage-3TUUR3L2.js +12 -0
- package/dist/trie-agent-QHPS4C5Z.js +27 -0
- package/dist/{vibe-code-signatures-ELEWJFGZ.js → vibe-code-signatures-J4GD4JOV.js} +3 -3
- package/dist/{vulnerability-signatures-EIJQX2TS.js → vulnerability-signatures-EIKOHFPK.js} +3 -3
- package/package.json +4 -6
- package/dist/chunk-7OJ6JIPL.js.map +0 -1
- package/dist/chunk-APMV77PU.js.map +0 -1
- package/dist/chunk-G76DYVGX.js +0 -136
- package/dist/chunk-G76DYVGX.js.map +0 -1
- package/dist/chunk-HYNDXZAU.js.map +0 -1
- package/dist/chunk-QH77RQB3.js.map +0 -1
- package/dist/chunk-ZUEAHFSY.js.map +0 -1
- package/dist/comprehension-46F7ZNKL.js +0 -821
- package/dist/comprehension-46F7ZNKL.js.map +0 -1
- package/dist/github-ingester-J2ZFYXVE.js +0 -11
- package/dist/graph-J4OGTYCO.js +0 -10
- package/dist/incident-index-BWW2UEY7.js +0 -11
- package/dist/linear-ingester-JRDQAIAA.js +0 -11
- package/dist/tiered-storage-VZL7KK64.js +0 -12
- package/dist/trie-agent-ET3DAP5Y.js +0 -27
- package/dist/workers/agent-worker.d.ts +0 -2
- package/dist/workers/agent-worker.js +0 -28
- package/dist/workers/agent-worker.js.map +0 -1
- /package/dist/{autonomy-config-ZCOSTMPD.js.map → autonomy-config-RKLZW4XL.js.map} +0 -0
- /package/dist/{chat-store-OJLJCJFI.js.map → chat-store-O3IJ5PMN.js.map} +0 -0
- /package/dist/{chunk-IXO4G4D3.js.map → chunk-2LAJKFWU.js.map} +0 -0
- /package/dist/{chunk-23RJT5WT.js.map → chunk-3CYMLM35.js.map} +0 -0
- /package/dist/{chunk-FG467PDD.js.map → chunk-ALSCZ7WR.js.map} +0 -0
- /package/dist/{chunk-YOJGSRZK.js.map → chunk-CBAMZERA.js.map} +0 -0
- /package/dist/{chunk-NKHO34UZ.js.map → chunk-FTOF3FHT.js.map} +0 -0
- /package/dist/{chunk-LD7ZEFNY.js.map → chunk-FXZAABXO.js.map} +0 -0
- /package/dist/{chunk-FH335WL5.js.map → chunk-JYWGYUKX.js.map} +0 -0
- /package/dist/{chunk-TIMIKBY2.js.map → chunk-KLMJKM63.js.map} +0 -0
- /package/dist/{chunk-4C67GV3O.js.map → chunk-KYKADM7P.js.map} +0 -0
- /package/dist/{chunk-CU5VDH6F.js.map → chunk-L4FODDDB.js.map} +0 -0
- /package/dist/{chunk-ILGMFND2.js.map → chunk-LFNH3CSN.js.map} +0 -0
- /package/dist/{chunk-GAL7OIYU.js.map → chunk-LJISDV3A.js.map} +0 -0
- /package/dist/{chunk-72KSLD7A.js.map → chunk-NVZZUUEU.js.map} +0 -0
- /package/dist/{chunk-B2AHQ2IR.js.map → chunk-OWSGJUUR.js.map} +0 -0
- /package/dist/{chunk-OTQEFXHU.js.map → chunk-T7UAH7GE.js.map} +0 -0
- /package/dist/{chunk-FPEMP54L.js.map → chunk-UL337UDQ.js.map} +0 -0
- /package/dist/{chunk-F4NJ4CBP.js.map → chunk-WO7CC5FH.js.map} +0 -0
- /package/dist/{chunk-5KJ4UJOY.js.map → chunk-XD2HKZVB.js.map} +0 -0
- /package/dist/{chunk-V7AY2EJO.js.map → chunk-YEQXKKZQ.js.map} +0 -0
- /package/dist/{client-INNE2GGZ.js.map → client-ZHOLZTRW.js.map} +0 -0
- /package/dist/{codebase-index-FMIULFZQ.js.map → codebase-index-N37NDF2A.js.map} +0 -0
- /package/dist/{fast-analyzer-CTT3MCPE.js.map → fast-analyzer-U6URGNQT.js.map} +0 -0
- /package/dist/{github-ingester-J2ZFYXVE.js.map → github-ingester-AR5A4RAC.js.map} +0 -0
- /package/dist/{goal-manager-IGUMDGCA.js.map → goal-manager-5QDITJKE.js.map} +0 -0
- /package/dist/{goal-validator-DV6DRSGF.js.map → goal-validator-FU5QWDQT.js.map} +0 -0
- /package/dist/{graph-J4OGTYCO.js.map → graph-JO7GG65P.js.map} +0 -0
- /package/dist/{hypothesis-O72ZLVOW.js.map → hypothesis-JURDWVDC.js.map} +0 -0
- /package/dist/{incident-index-BWW2UEY7.js.map → incident-index-7CAXUNTL.js.map} +0 -0
- /package/dist/{insight-store-Q62UGMTF.js.map → insight-store-AMEP5PPF.js.map} +0 -0
- /package/dist/{issue-store-4FPABLC6.js.map → issue-store-RM3XLLKG.js.map} +0 -0
- /package/dist/{ledger-43SIVE7X.js.map → ledger-PLE3C3X4.js.map} +0 -0
- /package/dist/{linear-ingester-JRDQAIAA.js.map → linear-ingester-NHFMKJBZ.js.map} +0 -0
- /package/dist/{output-manager-DZO5LGSG.js.map → output-manager-FX4V7ERT.js.map} +0 -0
- /package/dist/{progress-PQVEM7BR.js.map → progress-PAYTY7BF.js.map} +0 -0
- /package/dist/{tiered-storage-VZL7KK64.js.map → tiered-storage-3TUUR3L2.js.map} +0 -0
- /package/dist/{trie-agent-ET3DAP5Y.js.map → trie-agent-QHPS4C5Z.js.map} +0 -0
- /package/dist/{vibe-code-signatures-ELEWJFGZ.js.map → vibe-code-signatures-J4GD4JOV.js.map} +0 -0
- /package/dist/{vulnerability-signatures-EIJQX2TS.js.map → vulnerability-signatures-EIKOHFPK.js.map} +0 -0
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-43X6JBEM.js";
|
|
8
8
|
import {
|
|
9
9
|
getTrieDirectory
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7F2R2ITA.js";
|
|
11
11
|
|
|
12
12
|
// src/agent/insight-store.ts
|
|
13
13
|
import { mkdir, readFile } from "fs/promises";
|
|
@@ -437,4 +437,4 @@ export {
|
|
|
437
437
|
getInsightStore,
|
|
438
438
|
clearInsightStores
|
|
439
439
|
};
|
|
440
|
-
//# sourceMappingURL=chunk-
|
|
440
|
+
//# sourceMappingURL=chunk-T7UAH7GE.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getTrieDirectory,
|
|
3
3
|
getWorkingDirectory
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7F2R2ITA.js";
|
|
5
5
|
|
|
6
6
|
// src/ai/client.ts
|
|
7
7
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -358,4 +358,4 @@ export {
|
|
|
358
358
|
getAIStatusMessage,
|
|
359
359
|
runAIWithTools
|
|
360
360
|
};
|
|
361
|
-
//# sourceMappingURL=chunk-
|
|
361
|
+
//# sourceMappingURL=chunk-UL337UDQ.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-6NLHFIYA.js";
|
|
4
4
|
import {
|
|
5
5
|
isInteractiveMode
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JKEEQAG2.js";
|
|
7
7
|
|
|
8
8
|
// src/trie/vulnerability-signatures.ts
|
|
9
9
|
var ALWAYS_EXCLUDED_FILES = [
|
|
@@ -980,4 +980,4 @@ export {
|
|
|
980
980
|
scanForVulnerabilities,
|
|
981
981
|
getVulnerabilityStats
|
|
982
982
|
};
|
|
983
|
-
//# sourceMappingURL=chunk-
|
|
983
|
+
//# sourceMappingURL=chunk-WO7CC5FH.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getTrieDirectory
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7F2R2ITA.js";
|
|
4
4
|
|
|
5
5
|
// src/utils/autonomy-config.ts
|
|
6
6
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
@@ -342,4 +342,4 @@ export {
|
|
|
342
342
|
getAutonomyConfig,
|
|
343
343
|
clearConfigCache
|
|
344
344
|
};
|
|
345
|
-
//# sourceMappingURL=chunk-
|
|
345
|
+
//# sourceMappingURL=chunk-XD2HKZVB.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-43X6JBEM.js";
|
|
7
7
|
import {
|
|
8
8
|
getTrieDirectory
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7F2R2ITA.js";
|
|
10
10
|
|
|
11
11
|
// src/context/codebase-index.ts
|
|
12
12
|
import { readFile, stat } from "fs/promises";
|
|
@@ -251,4 +251,4 @@ var CodebaseIndex = class {
|
|
|
251
251
|
export {
|
|
252
252
|
CodebaseIndex
|
|
253
253
|
};
|
|
254
|
-
//# sourceMappingURL=chunk-
|
|
254
|
+
//# sourceMappingURL=chunk-YEQXKKZQ.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getProjectState
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-L4FODDDB.js";
|
|
4
4
|
import {
|
|
5
5
|
searchIssues
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4ZAFQEP6.js";
|
|
7
7
|
|
|
8
8
|
// src/agent/goal-validator.ts
|
|
9
9
|
async function getActiveGoals(projectPath) {
|
|
@@ -38,9 +38,9 @@ async function recordGoalViolationFixed(goal, file, projectPath) {
|
|
|
38
38
|
lastFixedFile: file
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
|
-
const { resolveGoalViolation } = await import("./issue-store-
|
|
41
|
+
const { resolveGoalViolation } = await import("./issue-store-RM3XLLKG.js");
|
|
42
42
|
await resolveGoalViolation(file, goal.description, projectPath);
|
|
43
|
-
const { getGoalManager } = await import("./goal-manager-
|
|
43
|
+
const { getGoalManager } = await import("./goal-manager-5QDITJKE.js");
|
|
44
44
|
const goalManager = getGoalManager(projectPath);
|
|
45
45
|
await goalManager.updateGoalProgress();
|
|
46
46
|
}
|
|
@@ -88,8 +88,8 @@ async function measureInitialGoalValue(description, projectPath) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
async function checkFilesForGoalViolations(goals, projectPath, filesToCheck, onProgress, signal) {
|
|
91
|
-
const { isAIAvailable, runAIAnalysis } = await import("./client-
|
|
92
|
-
const { CodebaseIndex } = await import("./codebase-index-
|
|
91
|
+
const { isAIAvailable, runAIAnalysis } = await import("./client-ZHOLZTRW.js");
|
|
92
|
+
const { CodebaseIndex } = await import("./codebase-index-N37NDF2A.js");
|
|
93
93
|
if (!isAIAvailable()) {
|
|
94
94
|
throw new Error("AI not available - ANTHROPIC_API_KEY not set");
|
|
95
95
|
}
|
|
@@ -241,7 +241,7 @@ This is a MANUAL CHECK requested by the user. Report ALL goal violations you fin
|
|
|
241
241
|
For emoji detection, look for Unicode emoji characters.
|
|
242
242
|
`;
|
|
243
243
|
const result = await runAIAnalysis({
|
|
244
|
-
signal,
|
|
244
|
+
...signal && { signal },
|
|
245
245
|
systemPrompt: `You are checking code for GOAL VIOLATIONS ONLY.
|
|
246
246
|
${goalsSection}
|
|
247
247
|
Reply ONLY with a JSON array. Each element must have:
|
|
@@ -351,4 +351,4 @@ export {
|
|
|
351
351
|
measureInitialGoalValue,
|
|
352
352
|
checkFilesForGoalViolations
|
|
353
353
|
};
|
|
354
|
-
//# sourceMappingURL=chunk-
|
|
354
|
+
//# sourceMappingURL=chunk-Z2E7X4WI.js.map
|
|
@@ -1 +1 @@
|
|
|
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 signal?: AbortSignal\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 \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 if (signal?.aborted) {\n throw new DOMException('Scan cancelled', 'AbortError');\n }\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 }\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 \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, // Never truncate text in Trie Watch\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 signal,\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
|
+
{"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 signal?: AbortSignal\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 \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 if (signal?.aborted) {\n throw new DOMException('Scan cancelled', 'AbortError');\n }\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 }\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 \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, // Never truncate text in Trie Watch\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 ...(signal && { signal }),\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":[]}
|
package/dist/cli/create-agent.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getTrieDirectory,
|
|
4
4
|
getWorkingDirectory
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-7F2R2ITA.js";
|
|
6
|
+
import "../chunk-JKEEQAG2.js";
|
|
7
7
|
import "../chunk-DGUM43GV.js";
|
|
8
8
|
|
|
9
9
|
// src/ingest/agent-builder.ts
|
|
@@ -16,7 +16,7 @@ async function parseDocument(filePath) {
|
|
|
16
16
|
const ext = extname(filePath).toLowerCase();
|
|
17
17
|
const fileType = getFileType(ext);
|
|
18
18
|
if (!fileType) {
|
|
19
|
-
throw new Error(`Unsupported file type: ${ext}. Supported: .
|
|
19
|
+
throw new Error(`Unsupported file type: ${ext}. Supported: .txt, .md, .rtf`);
|
|
20
20
|
}
|
|
21
21
|
let rawText;
|
|
22
22
|
let metadata = {
|
|
@@ -25,14 +25,6 @@ async function parseDocument(filePath) {
|
|
|
25
25
|
parsedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26
26
|
};
|
|
27
27
|
switch (fileType) {
|
|
28
|
-
case "pdf":
|
|
29
|
-
const pdfResult = await parsePDF(filePath);
|
|
30
|
-
rawText = pdfResult.text;
|
|
31
|
-
metadata.pageCount = pdfResult.pageCount;
|
|
32
|
-
if (pdfResult.title !== void 0) {
|
|
33
|
-
metadata.title = pdfResult.title;
|
|
34
|
-
}
|
|
35
|
-
break;
|
|
36
28
|
case "txt":
|
|
37
29
|
rawText = await parseTXT(filePath);
|
|
38
30
|
break;
|
|
@@ -58,7 +50,6 @@ async function parseDocument(filePath) {
|
|
|
58
50
|
}
|
|
59
51
|
function getFileType(ext) {
|
|
60
52
|
const typeMap = {
|
|
61
|
-
".pdf": "pdf",
|
|
62
53
|
".txt": "txt",
|
|
63
54
|
".md": "md",
|
|
64
55
|
".markdown": "md",
|
|
@@ -66,28 +57,6 @@ function getFileType(ext) {
|
|
|
66
57
|
};
|
|
67
58
|
return typeMap[ext] || null;
|
|
68
59
|
}
|
|
69
|
-
async function parsePDF(filePath) {
|
|
70
|
-
try {
|
|
71
|
-
const pdfParse = (await import("pdf-parse")).default;
|
|
72
|
-
const dataBuffer = await readFile(filePath);
|
|
73
|
-
const data = await pdfParse(dataBuffer);
|
|
74
|
-
const result = {
|
|
75
|
-
text: data.text,
|
|
76
|
-
pageCount: data.numpages
|
|
77
|
-
};
|
|
78
|
-
if (data.info?.Title) {
|
|
79
|
-
result.title = data.info.Title;
|
|
80
|
-
}
|
|
81
|
-
return result;
|
|
82
|
-
} catch (error) {
|
|
83
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
84
|
-
throw new Error(
|
|
85
|
-
"PDF parsing requires the pdf-parse package. Install it with: npm install pdf-parse"
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
throw error;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
60
|
async function parseTXT(filePath) {
|
|
92
61
|
return await readFile(filePath, "utf-8");
|
|
93
62
|
}
|
|
@@ -989,7 +958,7 @@ Usage:
|
|
|
989
958
|
trie-create <file-path> [agent-name] [options]
|
|
990
959
|
|
|
991
960
|
Arguments:
|
|
992
|
-
file-path Path to
|
|
961
|
+
file-path Path to TXT, MD, or RTF file (drag & drop supported!)
|
|
993
962
|
agent-name Name for the agent (optional - auto-generated from filename)
|
|
994
963
|
|
|
995
964
|
Options:
|
|
@@ -1000,19 +969,18 @@ Options:
|
|
|
1000
969
|
|
|
1001
970
|
Examples:
|
|
1002
971
|
# Basic usage
|
|
1003
|
-
trie-create ./react-
|
|
972
|
+
trie-create ./react-guide.md react-fundamentals
|
|
1004
973
|
|
|
1005
974
|
# With options
|
|
1006
|
-
trie-create ./gdpr-guide.
|
|
975
|
+
trie-create ./gdpr-guide.txt gdpr-compliance --category legal
|
|
1007
976
|
|
|
1008
977
|
# Auto-generate name from filename
|
|
1009
|
-
trie-create ./clean-code.
|
|
978
|
+
trie-create ./clean-code.txt
|
|
1010
979
|
|
|
1011
980
|
# Drag & drop a file to terminal, then add name
|
|
1012
|
-
trie-create /Users/you/Downloads/my-
|
|
981
|
+
trie-create /Users/you/Downloads/my-guide.md my-agent
|
|
1013
982
|
|
|
1014
983
|
Supported File Types:
|
|
1015
|
-
\u2022 PDF (.pdf) - Requires pdf-parse: npm install pdf-parse
|
|
1016
984
|
\u2022 Text (.txt) - Plain text files
|
|
1017
985
|
\u2022 Markdown (.md, .markdown)
|
|
1018
986
|
\u2022 RTF (.rtf) - Rich Text Format
|
|
@@ -1034,7 +1002,7 @@ async function main() {
|
|
|
1034
1002
|
process.exit(1);
|
|
1035
1003
|
}
|
|
1036
1004
|
const ext = extname2(options.filePath).toLowerCase();
|
|
1037
|
-
const supportedTypes = [".
|
|
1005
|
+
const supportedTypes = [".txt", ".md", ".markdown", ".rtf"];
|
|
1038
1006
|
if (!supportedTypes.includes(ext)) {
|
|
1039
1007
|
console.error(`Unsupported file type: ${ext}`);
|
|
1040
1008
|
console.error(` Supported types: ${supportedTypes.join(", ")}`);
|