aspectcode 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/agentsMdRenderer.d.ts +16 -0
- package/dist/agentsMdRenderer.d.ts.map +1 -0
- package/dist/agentsMdRenderer.js +137 -0
- package/dist/agentsMdRenderer.js.map +1 -0
- package/dist/auth.d.ts +31 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +385 -0
- package/dist/auth.js.map +1 -0
- package/dist/autoResolve.d.ts +41 -0
- package/dist/autoResolve.d.ts.map +1 -0
- package/dist/autoResolve.js +196 -0
- package/dist/autoResolve.js.map +1 -0
- package/dist/changeEvaluator.d.ts +56 -0
- package/dist/changeEvaluator.d.ts.map +1 -0
- package/dist/changeEvaluator.js +674 -0
- package/dist/changeEvaluator.js.map +1 -0
- package/dist/cli.d.ts +12 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +37 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +50 -2
- package/dist/config.js.map +1 -1
- package/dist/dreamCycle.d.ts +57 -0
- package/dist/dreamCycle.d.ts.map +1 -0
- package/dist/dreamCycle.js +334 -0
- package/dist/dreamCycle.js.map +1 -0
- package/dist/kbBuilder.d.ts +1 -2
- package/dist/kbBuilder.d.ts.map +1 -1
- package/dist/kbBuilder.js +1 -2
- package/dist/kbBuilder.js.map +1 -1
- package/dist/main.d.ts +2 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +149 -8
- package/dist/main.js.map +1 -1
- package/dist/optimize.d.ts +13 -6
- package/dist/optimize.d.ts.map +1 -1
- package/dist/optimize.js +433 -142
- package/dist/optimize.js.map +1 -1
- package/dist/pipeline.d.ts +21 -18
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +1139 -162
- package/dist/pipeline.js.map +1 -1
- package/dist/preferences.d.ts +80 -0
- package/dist/preferences.d.ts.map +1 -0
- package/dist/preferences.js +238 -0
- package/dist/preferences.js.map +1 -0
- package/dist/runtimeState.d.ts +30 -0
- package/dist/runtimeState.d.ts.map +1 -0
- package/dist/runtimeState.js +39 -0
- package/dist/runtimeState.js.map +1 -0
- package/dist/scopedRules.d.ts +84 -0
- package/dist/scopedRules.d.ts.map +1 -0
- package/dist/scopedRules.js +449 -0
- package/dist/scopedRules.js.map +1 -0
- package/dist/ui/Dashboard.d.ts +4 -16
- package/dist/ui/Dashboard.d.ts.map +1 -1
- package/dist/ui/Dashboard.js +339 -141
- package/dist/ui/Dashboard.js.map +1 -1
- package/dist/ui/MemoryMap.d.ts +16 -0
- package/dist/ui/MemoryMap.d.ts.map +1 -0
- package/dist/ui/MemoryMap.js +266 -0
- package/dist/ui/MemoryMap.js.map +1 -0
- package/dist/ui/SettingsPanel.d.ts +18 -0
- package/dist/ui/SettingsPanel.d.ts.map +1 -0
- package/dist/ui/SettingsPanel.js +241 -0
- package/dist/ui/SettingsPanel.js.map +1 -0
- package/dist/ui/prompts.d.ts +7 -0
- package/dist/ui/prompts.d.ts.map +1 -1
- package/dist/ui/prompts.js +63 -0
- package/dist/ui/prompts.js.map +1 -1
- package/dist/ui/store.d.ts +154 -18
- package/dist/ui/store.d.ts.map +1 -1
- package/dist/ui/store.js +154 -24
- package/dist/ui/store.js.map +1 -1
- package/dist/ui/theme.d.ts +1 -8
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +2 -20
- package/dist/ui/theme.js.map +1 -1
- package/dist/updateChecker.d.ts +13 -0
- package/dist/updateChecker.d.ts.map +1 -0
- package/dist/updateChecker.js +66 -0
- package/dist/updateChecker.js.map +1 -0
- package/dist/usageTracker.d.ts +12 -0
- package/dist/usageTracker.d.ts.map +1 -0
- package/dist/usageTracker.js +89 -0
- package/dist/usageTracker.js.map +1 -0
- package/dist/writer.d.ts +1 -7
- package/dist/writer.d.ts.map +1 -1
- package/dist/writer.js +1 -11
- package/dist/writer.js.map +1 -1
- package/node_modules/@aspectcode/core/dist/analysis/repo.d.ts.map +1 -1
- package/node_modules/@aspectcode/core/dist/analysis/repo.js +13 -2
- package/node_modules/@aspectcode/core/dist/analysis/repo.js.map +1 -1
- package/node_modules/@aspectcode/core/dist/index.d.ts +1 -3
- package/node_modules/@aspectcode/core/dist/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/core/dist/index.js +1 -3
- package/node_modules/@aspectcode/core/dist/index.js.map +1 -1
- package/node_modules/@aspectcode/core/dist/parsers/genericExtractors.d.ts +14 -0
- package/node_modules/@aspectcode/core/dist/parsers/genericExtractors.d.ts.map +1 -0
- package/node_modules/@aspectcode/core/dist/parsers/genericExtractors.js +191 -0
- package/node_modules/@aspectcode/core/dist/parsers/genericExtractors.js.map +1 -0
- package/node_modules/@aspectcode/core/dist/parsers/index.d.ts +1 -0
- package/node_modules/@aspectcode/core/dist/parsers/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/core/dist/parsers/index.js +6 -1
- package/node_modules/@aspectcode/core/dist/parsers/index.js.map +1 -1
- package/node_modules/@aspectcode/core/dist/parsers/languages.d.ts +20 -0
- package/node_modules/@aspectcode/core/dist/parsers/languages.d.ts.map +1 -1
- package/node_modules/@aspectcode/core/dist/parsers/languages.js +25 -0
- package/node_modules/@aspectcode/core/dist/parsers/languages.js.map +1 -1
- package/node_modules/@aspectcode/core/dist/parsers/tsJsExtractors.d.ts.map +1 -1
- package/node_modules/@aspectcode/core/dist/parsers/tsJsExtractors.js +4 -1
- package/node_modules/@aspectcode/core/dist/parsers/tsJsExtractors.js.map +1 -1
- package/node_modules/@aspectcode/core/package.json +2 -2
- package/node_modules/@aspectcode/core/parsers/cpp.wasm +0 -0
- package/node_modules/@aspectcode/core/parsers/go.wasm +0 -0
- package/node_modules/@aspectcode/core/parsers/php.wasm +0 -0
- package/node_modules/@aspectcode/core/parsers/ruby.wasm +0 -0
- package/node_modules/@aspectcode/core/parsers/rust.wasm +0 -0
- package/node_modules/@aspectcode/emitters/dist/index.d.ts +1 -17
- package/node_modules/@aspectcode/emitters/dist/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/index.js +2 -89
- package/node_modules/@aspectcode/emitters/dist/index.js.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/index.d.ts +0 -2
- package/node_modules/@aspectcode/emitters/dist/instructions/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/index.js +1 -7
- package/node_modules/@aspectcode/emitters/dist/instructions/index.js.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/kb/analyzers.d.ts +0 -18
- package/node_modules/@aspectcode/emitters/dist/kb/analyzers.d.ts.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/kb/analyzers.js +0 -57
- package/node_modules/@aspectcode/emitters/dist/kb/analyzers.js.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/kb/conventions.d.ts +0 -18
- package/node_modules/@aspectcode/emitters/dist/kb/conventions.d.ts.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/kb/conventions.js +0 -130
- package/node_modules/@aspectcode/emitters/dist/kb/conventions.js.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/kb/index.d.ts +2 -4
- package/node_modules/@aspectcode/emitters/dist/kb/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/emitters/dist/kb/index.js +1 -11
- package/node_modules/@aspectcode/emitters/dist/kb/index.js.map +1 -1
- package/node_modules/@aspectcode/emitters/package.json +3 -3
- package/node_modules/@aspectcode/evaluator/dist/apply.d.ts +55 -0
- package/node_modules/@aspectcode/evaluator/dist/apply.d.ts.map +1 -0
- package/node_modules/@aspectcode/evaluator/dist/apply.js +368 -0
- package/node_modules/@aspectcode/evaluator/dist/apply.js.map +1 -0
- package/node_modules/@aspectcode/evaluator/dist/diagnosis.d.ts +16 -25
- package/node_modules/@aspectcode/evaluator/dist/diagnosis.d.ts.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/diagnosis.js +115 -138
- package/node_modules/@aspectcode/evaluator/dist/diagnosis.js.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/index.d.ts +8 -43
- package/node_modules/@aspectcode/evaluator/dist/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/index.js +15 -61
- package/node_modules/@aspectcode/evaluator/dist/index.js.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/judge.d.ts +32 -0
- package/node_modules/@aspectcode/evaluator/dist/judge.d.ts.map +1 -0
- package/node_modules/@aspectcode/evaluator/dist/judge.js +165 -0
- package/node_modules/@aspectcode/evaluator/dist/judge.js.map +1 -0
- package/node_modules/@aspectcode/evaluator/dist/llmUtil.d.ts +15 -0
- package/node_modules/@aspectcode/evaluator/dist/llmUtil.d.ts.map +1 -0
- package/node_modules/@aspectcode/evaluator/dist/llmUtil.js +41 -0
- package/node_modules/@aspectcode/evaluator/dist/llmUtil.js.map +1 -0
- package/node_modules/@aspectcode/evaluator/dist/probes.d.ts +20 -29
- package/node_modules/@aspectcode/evaluator/dist/probes.d.ts.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/probes.js +188 -204
- package/node_modules/@aspectcode/evaluator/dist/probes.js.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/runner.d.ts +7 -32
- package/node_modules/@aspectcode/evaluator/dist/runner.d.ts.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/runner.js +21 -146
- package/node_modules/@aspectcode/evaluator/dist/runner.js.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/types.d.ts +141 -99
- package/node_modules/@aspectcode/evaluator/dist/types.d.ts.map +1 -1
- package/node_modules/@aspectcode/evaluator/dist/types.js +10 -2
- package/node_modules/@aspectcode/evaluator/dist/types.js.map +1 -1
- package/node_modules/@aspectcode/evaluator/package.json +4 -4
- package/node_modules/@aspectcode/optimizer/dist/index.d.ts +3 -10
- package/node_modules/@aspectcode/optimizer/dist/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/index.js +1 -19
- package/node_modules/@aspectcode/optimizer/dist/index.js.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/anthropic.d.ts.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/anthropic.js +40 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/anthropic.js.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/aspectcode.d.ts +9 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/aspectcode.d.ts.map +1 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/aspectcode.js +83 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/aspectcode.js.map +1 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/index.d.ts +4 -3
- package/node_modules/@aspectcode/optimizer/dist/providers/index.d.ts.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/index.js +24 -10
- package/node_modules/@aspectcode/optimizer/dist/providers/index.js.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/openai.d.ts.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/openai.js +22 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/openai.js.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/retry.d.ts +14 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/retry.d.ts.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/providers/retry.js +1 -0
- package/node_modules/@aspectcode/optimizer/dist/providers/retry.js.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/types.d.ts +14 -0
- package/node_modules/@aspectcode/optimizer/dist/types.d.ts.map +1 -1
- package/node_modules/@aspectcode/optimizer/dist/types.js.map +1 -1
- package/node_modules/@aspectcode/optimizer/package.json +2 -2
- package/package.json +6 -7
- package/dist/complaintProcessor.d.ts +0 -16
- package/dist/complaintProcessor.d.ts.map +0 -1
- package/dist/complaintProcessor.js +0 -134
- package/dist/complaintProcessor.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/emitter.d.ts +0 -72
- package/node_modules/@aspectcode/emitters/dist/emitter.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/emitter.js +0 -10
- package/node_modules/@aspectcode/emitters/dist/emitter.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/content.d.ts +0 -15
- package/node_modules/@aspectcode/emitters/dist/instructions/content.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/content.js +0 -289
- package/node_modules/@aspectcode/emitters/dist/instructions/content.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/detection.d.ts +0 -13
- package/node_modules/@aspectcode/emitters/dist/instructions/detection.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/detection.js +0 -55
- package/node_modules/@aspectcode/emitters/dist/instructions/detection.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/instructionsEmitter.d.ts +0 -9
- package/node_modules/@aspectcode/emitters/dist/instructions/instructionsEmitter.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/instructions/instructionsEmitter.js +0 -30
- package/node_modules/@aspectcode/emitters/dist/instructions/instructionsEmitter.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/kb/kbEmitter.d.ts +0 -21
- package/node_modules/@aspectcode/emitters/dist/kb/kbEmitter.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/kb/kbEmitter.js +0 -125
- package/node_modules/@aspectcode/emitters/dist/kb/kbEmitter.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/manifest.d.ts +0 -37
- package/node_modules/@aspectcode/emitters/dist/manifest.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/manifest.js +0 -50
- package/node_modules/@aspectcode/emitters/dist/manifest.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/report.d.ts +0 -22
- package/node_modules/@aspectcode/emitters/dist/report.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/report.js +0 -3
- package/node_modules/@aspectcode/emitters/dist/report.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/stableJson.d.ts +0 -14
- package/node_modules/@aspectcode/emitters/dist/stableJson.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/stableJson.js +0 -40
- package/node_modules/@aspectcode/emitters/dist/stableJson.js.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/transaction.d.ts +0 -29
- package/node_modules/@aspectcode/emitters/dist/transaction.d.ts.map +0 -1
- package/node_modules/@aspectcode/emitters/dist/transaction.js +0 -104
- package/node_modules/@aspectcode/emitters/dist/transaction.js.map +0 -1
package/dist/optimize.js
CHANGED
|
@@ -2,31 +2,34 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Optimize wrapper — tries LLM optimization, falls back to static content.
|
|
4
4
|
*
|
|
5
|
-
* - If an API key is available →
|
|
6
|
-
* - If
|
|
5
|
+
* - If an API key is available → generate seed AGENTS.md from KB
|
|
6
|
+
* - If probeAndRefine=true → run multi-iteration probe-and-refine loop
|
|
7
7
|
* - If no API key → warn and write static AGENTS.md content
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.tryOptimize = tryOptimize;
|
|
11
11
|
const optimizer_1 = require("@aspectcode/optimizer");
|
|
12
12
|
const evaluator_1 = require("@aspectcode/evaluator");
|
|
13
|
-
const emitters_1 = require("@aspectcode/emitters");
|
|
14
13
|
const logger_1 = require("./logger");
|
|
15
14
|
const store_1 = require("./ui/store");
|
|
15
|
+
const auth_1 = require("./auth");
|
|
16
|
+
const usageTracker_1 = require("./usageTracker");
|
|
17
|
+
const preferences_1 = require("./preferences");
|
|
16
18
|
/**
|
|
17
19
|
* Try to generate AGENTS.md content via LLM using static analysis as context.
|
|
18
20
|
* Falls back to static instruction content when no API key is available.
|
|
21
|
+
*
|
|
22
|
+
* @param probeAndRefine When true, run the multi-iteration probe-and-refine loop
|
|
23
|
+
* after generating the seed. Only on first run or manual rerun.
|
|
19
24
|
*/
|
|
20
|
-
async function tryOptimize(ctx, kbContent,
|
|
25
|
+
async function tryOptimize(ctx, kbContent, _toolInstructions, config, _baseContent, probeAndRefine = false, preferences, userSettings, staticRules) {
|
|
21
26
|
const { flags, log, root } = ctx;
|
|
22
|
-
const optConfig = config?.optimize;
|
|
23
27
|
const evalConfig = config?.evaluate;
|
|
24
|
-
const evaluatorEnabled = evalConfig?.enabled !== false;
|
|
25
|
-
// ── Resolve settings
|
|
26
|
-
const temperature = flags.temperature ??
|
|
27
|
-
const model = flags.model ??
|
|
28
|
-
const
|
|
29
|
-
const maxTokens = optConfig?.maxTokens;
|
|
28
|
+
const evaluatorEnabled = probeAndRefine && evalConfig?.enabled !== false;
|
|
29
|
+
// ── Resolve settings (CLI flags > cloud user settings > defaults) ──
|
|
30
|
+
const temperature = flags.temperature ?? userSettings?.temperature;
|
|
31
|
+
const model = flags.model ?? userSettings?.model;
|
|
32
|
+
const maxTokens = userSettings?.maxTokens;
|
|
30
33
|
// ── Load .env and try to resolve a provider ───────────────
|
|
31
34
|
let env;
|
|
32
35
|
try {
|
|
@@ -35,8 +38,19 @@ async function tryOptimize(ctx, kbContent, toolInstructions, config, baseContent
|
|
|
35
38
|
catch {
|
|
36
39
|
env = {};
|
|
37
40
|
}
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
// Inject BYOK key from aspectcode.json if set
|
|
42
|
+
if (config?.apiKey && !env['ASPECTCODE_LLM_KEY']) {
|
|
43
|
+
env['ASPECTCODE_LLM_KEY'] = config.apiKey;
|
|
44
|
+
}
|
|
45
|
+
// Pass CLI token so the aspectcode hosted provider can authenticate
|
|
46
|
+
const creds = (0, auth_1.loadCredentials)();
|
|
47
|
+
if (creds && !env['ASPECTCODE_CLI_TOKEN']) {
|
|
48
|
+
env['ASPECTCODE_CLI_TOKEN'] = creds.token;
|
|
49
|
+
}
|
|
50
|
+
// Only set LLM_PROVIDER from CLI flags, not user settings.
|
|
51
|
+
// When logged in, the hosted proxy handles model selection server-side.
|
|
52
|
+
if (flags.provider && !env['LLM_PROVIDER']) {
|
|
53
|
+
env['LLM_PROVIDER'] = flags.provider;
|
|
40
54
|
}
|
|
41
55
|
const providerOptions = {};
|
|
42
56
|
if (model)
|
|
@@ -46,169 +60,446 @@ async function tryOptimize(ctx, kbContent, toolInstructions, config, baseContent
|
|
|
46
60
|
if (maxTokens !== undefined)
|
|
47
61
|
providerOptions.maxTokens = maxTokens;
|
|
48
62
|
let provider;
|
|
63
|
+
let diagnosisProvider; // Sonnet for higher-quality diagnosis
|
|
49
64
|
try {
|
|
50
|
-
provider = (0, optimizer_1.resolveProvider)(env, providerOptions);
|
|
65
|
+
provider = (0, usageTracker_1.withUsageTracking)((0, optimizer_1.resolveProvider)(env, providerOptions));
|
|
66
|
+
// Use Sonnet for the diagnosis step (higher quality for the most impactful call)
|
|
67
|
+
try {
|
|
68
|
+
diagnosisProvider = (0, usageTracker_1.withUsageTracking)((0, optimizer_1.resolveProvider)(env, { ...providerOptions, model: 'claude-sonnet-4-20250514' }));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
diagnosisProvider = provider; // Fall back to same provider
|
|
72
|
+
}
|
|
51
73
|
}
|
|
52
|
-
catch {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
log.warn(
|
|
56
|
-
return {
|
|
57
|
-
content: (0, emitters_1.generateCanonicalContentForMode)('safe', kbContent.length > 0),
|
|
58
|
-
reasoning: [],
|
|
59
|
-
};
|
|
74
|
+
catch (providerErr) {
|
|
75
|
+
store_1.store.addSetupNote('no LLM available — using static content');
|
|
76
|
+
const errMsg = providerErr instanceof Error ? providerErr.message : String(providerErr);
|
|
77
|
+
log.warn(`LLM failed: ${errMsg}`);
|
|
78
|
+
return { content: _baseContent, reasoning: [], scopedRules: [], deleteSlugs: [] };
|
|
60
79
|
}
|
|
61
80
|
const providerLabel = model ? `${provider.name} (${model})` : provider.name;
|
|
62
|
-
store_1.store.addSetupNote(`API key: ${provider.name}`);
|
|
63
|
-
if (evaluatorEnabled) {
|
|
64
|
-
store_1.store.addSetupNote('evaluator on');
|
|
65
|
-
}
|
|
66
81
|
log.info(`Generating with ${logger_1.fmt.cyan(provider.name)}${model ? ` (${logger_1.fmt.cyan(model)})` : ''}…`);
|
|
67
82
|
store_1.store.setProvider(providerLabel);
|
|
68
|
-
// ── Use static content only as fallback (LLM error / cancellation) ─
|
|
69
|
-
const fallbackContent = baseContent;
|
|
70
|
-
// ── Build tool instructions context string ────────────────
|
|
71
|
-
let toolContext = '';
|
|
72
|
-
if (toolInstructions.size > 0) {
|
|
73
|
-
const parts = [];
|
|
74
|
-
for (const [tool, content] of toolInstructions) {
|
|
75
|
-
parts.push(`### ${tool}\n${content}`);
|
|
76
|
-
}
|
|
77
|
-
toolContext = parts.join('\n\n');
|
|
78
|
-
}
|
|
79
|
-
// ── Progress callbacks for live dashboard updates ─────────
|
|
80
|
-
const onProgress = (step) => {
|
|
81
|
-
switch (step.kind) {
|
|
82
|
-
case 'generating':
|
|
83
|
-
store_1.store.setPhase('optimizing', 'generating AGENTS.md…');
|
|
84
|
-
break;
|
|
85
|
-
case 'done':
|
|
86
|
-
store_1.store.setPhase('optimizing', 'generation complete');
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
// ── Wrap logger for dashboard ─────────────────────────────
|
|
91
83
|
const optLog = flags.quiet ? undefined : {
|
|
92
84
|
info(msg) { log.info(msg); },
|
|
93
85
|
warn(msg) { log.warn(msg); },
|
|
94
86
|
error(msg) { log.error(msg); },
|
|
95
87
|
debug(msg) { log.debug(msg); },
|
|
96
88
|
};
|
|
97
|
-
// ──
|
|
98
|
-
let
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
harvestedPrompts = await (0, evaluator_1.harvestPrompts)({
|
|
104
|
-
root,
|
|
105
|
-
sources: evalConfig?.harvestSources,
|
|
106
|
-
maxPerSource: 50,
|
|
107
|
-
log: optLog,
|
|
108
|
-
});
|
|
109
|
-
store_1.store.setEvalStatus({ phase: 'harvesting', harvestCount: harvestedPrompts.length });
|
|
110
|
-
if (harvestedPrompts.length > 0) {
|
|
111
|
-
log.info(`Harvested ${harvestedPrompts.length} prompts from AI tool history`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
catch (err) {
|
|
115
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
116
|
-
log.debug(`Prompt harvesting failed (non-fatal): ${msg}`);
|
|
117
|
-
}
|
|
89
|
+
// ── Enrich KB with user preferences ─────────────────────
|
|
90
|
+
let enrichedKb = kbContent;
|
|
91
|
+
if (preferences) {
|
|
92
|
+
const prefBlock = (0, preferences_1.formatPreferencesForPrompt)(preferences);
|
|
93
|
+
if (prefBlock)
|
|
94
|
+
enrichedKb = kbContent + '\n\n' + prefBlock;
|
|
118
95
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
for (const reason of result.reasoning) {
|
|
128
|
-
log.debug(` ${logger_1.fmt.dim(reason)}`);
|
|
96
|
+
// ── Use base content as seed AGENTS.md ──────────────────
|
|
97
|
+
const projectName = root.split('/').pop() || root.split('\\').pop() || 'Project';
|
|
98
|
+
store_1.store.setPhase('optimizing', 'generating seed AGENTS.md…');
|
|
99
|
+
let finalContent;
|
|
100
|
+
if (evaluatorEnabled) {
|
|
101
|
+
// Use the base content (rendered directly from AnalysisModel) as the seed
|
|
102
|
+
finalContent = _baseContent;
|
|
103
|
+
log.info('Using base AGENTS.md for probe-and-refine tuning');
|
|
129
104
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
105
|
+
else {
|
|
106
|
+
// Use base content directly (already rendered from AnalysisModel)
|
|
107
|
+
finalContent = _baseContent;
|
|
133
108
|
}
|
|
134
|
-
|
|
135
|
-
|
|
109
|
+
store_1.store.setPhase('optimizing', 'generation complete');
|
|
110
|
+
// ── Probe-and-refine loop ──────────────────────────────────
|
|
111
|
+
const scopedRuleCreates = [];
|
|
112
|
+
const scopedRuleDeletes = [];
|
|
113
|
+
const allAppliedEdits = [];
|
|
136
114
|
if (evaluatorEnabled) {
|
|
115
|
+
const iterationSummaries = [];
|
|
116
|
+
let totalEditsApplied = 0;
|
|
117
|
+
// ── Abort controller for immediate cancellation ──────
|
|
118
|
+
const abortController = new AbortController();
|
|
119
|
+
const { signal } = abortController;
|
|
120
|
+
const onStoreChange = () => {
|
|
121
|
+
if (store_1.store.state.evalStatus.cancelled && !signal.aborted) {
|
|
122
|
+
abortController.abort();
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
store_1.store.on('change', onStoreChange);
|
|
137
126
|
try {
|
|
127
|
+
const loopConfig = {
|
|
128
|
+
maxIterations: evalConfig?.maxIterations ?? evaluator_1.DEFAULT_PROBE_REFINE_CONFIG.maxIterations,
|
|
129
|
+
targetProbesPerIteration: evalConfig?.maxProbes ?? evaluator_1.DEFAULT_PROBE_REFINE_CONFIG.targetProbesPerIteration,
|
|
130
|
+
maxEditsPerIteration: evalConfig?.maxEditsPerIteration ?? evaluator_1.DEFAULT_PROBE_REFINE_CONFIG.maxEditsPerIteration,
|
|
131
|
+
charBudget: evalConfig?.charBudget ?? evaluator_1.DEFAULT_PROBE_REFINE_CONFIG.charBudget,
|
|
132
|
+
};
|
|
138
133
|
store_1.store.setPhase('evaluating');
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
134
|
+
const priorTasks = [];
|
|
135
|
+
let noChangeStreak = 0;
|
|
136
|
+
let probeExhaustionStreak = 0;
|
|
137
|
+
let convergedReason;
|
|
138
|
+
/** Cooperative cancel check — returns true if the user pressed [x]. */
|
|
139
|
+
const isCancelled = () => signal.aborted;
|
|
140
|
+
/** Preserves iterationSummaries across setEvalStatus calls. */
|
|
141
|
+
const setEval = (status) => {
|
|
142
|
+
store_1.store.setEvalStatus({
|
|
143
|
+
...status,
|
|
144
|
+
iterationSummaries: iterationSummaries.length > 0 ? [...iterationSummaries] : undefined,
|
|
145
|
+
cancelled: signal.aborted,
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
for (let iteration = 1; iteration <= loopConfig.maxIterations; iteration++) {
|
|
149
|
+
if (isCancelled())
|
|
150
|
+
break;
|
|
151
|
+
log.info(`\n── Iteration ${iteration}/${loopConfig.maxIterations} ──`);
|
|
152
|
+
// ── Step 1: Generate probes ──────────────────────
|
|
153
|
+
setEval({
|
|
154
|
+
phase: 'generating-probes',
|
|
155
|
+
iteration,
|
|
156
|
+
maxIterations: loopConfig.maxIterations,
|
|
157
|
+
});
|
|
158
|
+
store_1.store.setPhase('evaluating');
|
|
159
|
+
const probes = await (0, evaluator_1.generateProbes)({
|
|
160
|
+
kb: enrichedKb,
|
|
161
|
+
currentAgentsMd: finalContent,
|
|
162
|
+
priorProbeTasks: priorTasks,
|
|
163
|
+
maxProbes: loopConfig.targetProbesPerIteration,
|
|
164
|
+
provider,
|
|
165
|
+
projectName,
|
|
166
|
+
log: optLog,
|
|
167
|
+
signal,
|
|
168
|
+
});
|
|
169
|
+
if (isCancelled())
|
|
170
|
+
break;
|
|
171
|
+
// Track prior tasks for cross-iteration dedup
|
|
172
|
+
for (const p of probes)
|
|
173
|
+
priorTasks.push(p.task);
|
|
174
|
+
if (probes.length === 0) {
|
|
175
|
+
probeExhaustionStreak++;
|
|
176
|
+
log.info(`No new probes generated (streak: ${probeExhaustionStreak})`);
|
|
177
|
+
if (probeExhaustionStreak >= 2) {
|
|
178
|
+
convergedReason = 'probe diversity exhausted';
|
|
179
|
+
log.info(`Converged: ${convergedReason}`);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
probeExhaustionStreak = 0;
|
|
186
|
+
}
|
|
187
|
+
// ── Step 2: Simulate probes ──────────────────────
|
|
188
|
+
const probeTasks = probes.map((p) => p.task);
|
|
189
|
+
setEval({
|
|
190
|
+
phase: 'probing',
|
|
191
|
+
iteration,
|
|
192
|
+
maxIterations: loopConfig.maxIterations,
|
|
193
|
+
probesTotal: probes.length,
|
|
194
|
+
probeTasks,
|
|
195
|
+
});
|
|
196
|
+
store_1.store.setPhase('evaluating');
|
|
197
|
+
const onProbeProgress = (info) => {
|
|
198
|
+
const currentTask = probes[info.probeIndex]?.task;
|
|
199
|
+
const brief = currentTask && currentTask.length > 60
|
|
200
|
+
? currentTask.slice(0, 57) + '...'
|
|
201
|
+
: currentTask;
|
|
202
|
+
setEval({
|
|
151
203
|
phase: 'probing',
|
|
152
|
-
|
|
204
|
+
iteration,
|
|
205
|
+
maxIterations: loopConfig.maxIterations,
|
|
206
|
+
probesPassed: info.probeIndex + (info.phase === 'done' ? 1 : 0),
|
|
153
207
|
probesTotal: info.total,
|
|
208
|
+
probeTasks,
|
|
209
|
+
currentProbeTask: brief,
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
const simResults = await (0, evaluator_1.runProbes)(finalContent, probes, provider, optLog, signal, onProbeProgress);
|
|
213
|
+
if (isCancelled())
|
|
214
|
+
break;
|
|
215
|
+
// ── Step 3: Judge each probe ─────────────────────
|
|
216
|
+
setEval({
|
|
217
|
+
phase: 'judging',
|
|
218
|
+
iteration,
|
|
219
|
+
maxIterations: loopConfig.maxIterations,
|
|
220
|
+
probesTotal: simResults.length,
|
|
221
|
+
judgedCount: 0,
|
|
222
|
+
weakCount: 0,
|
|
223
|
+
strongCount: 0,
|
|
224
|
+
});
|
|
225
|
+
store_1.store.setPhase('evaluating');
|
|
226
|
+
const judgedResults = [];
|
|
227
|
+
let weakCount = 0;
|
|
228
|
+
let strongCount = 0;
|
|
229
|
+
const probeResults = [];
|
|
230
|
+
// Pre-populate pending entries for all probes
|
|
231
|
+
for (const sim of simResults) {
|
|
232
|
+
const brief = sim.task.length > 60 ? sim.task.slice(0, 57) + '...' : sim.task;
|
|
233
|
+
probeResults.push({ task: brief, status: 'pending' });
|
|
234
|
+
}
|
|
235
|
+
for (let i = 0; i < simResults.length; i++) {
|
|
236
|
+
if (isCancelled())
|
|
237
|
+
break;
|
|
238
|
+
const sim = simResults[i];
|
|
239
|
+
const probe = probes[i];
|
|
240
|
+
if (!sim.response)
|
|
241
|
+
continue;
|
|
242
|
+
const judged = await (0, evaluator_1.judgeProbe)({
|
|
243
|
+
task: sim.task,
|
|
244
|
+
response: sim.response,
|
|
245
|
+
expectedBehaviors: probe.expectedBehaviors,
|
|
246
|
+
probeId: sim.probeId,
|
|
247
|
+
provider,
|
|
248
|
+
log: optLog,
|
|
249
|
+
signal,
|
|
250
|
+
});
|
|
251
|
+
judgedResults.push(judged);
|
|
252
|
+
const hasWeak = judged.behaviorReviews.some((b) => b.assessment !== 'strong');
|
|
253
|
+
if (hasWeak)
|
|
254
|
+
weakCount++;
|
|
255
|
+
else
|
|
256
|
+
strongCount++;
|
|
257
|
+
probeResults[i] = { task: probeResults[i].task, status: hasWeak ? 'weak' : 'strong' };
|
|
258
|
+
setEval({
|
|
259
|
+
phase: 'judging',
|
|
260
|
+
iteration,
|
|
261
|
+
maxIterations: loopConfig.maxIterations,
|
|
262
|
+
probesTotal: simResults.length,
|
|
263
|
+
judgedCount: i + 1,
|
|
264
|
+
weakCount,
|
|
265
|
+
strongCount,
|
|
266
|
+
currentProbeTask: probeResults[i].task,
|
|
267
|
+
probeResults: [...probeResults],
|
|
154
268
|
});
|
|
155
|
-
|
|
269
|
+
log.info(` ${hasWeak ? '✖' : '✔'} ${sim.probeId} (${hasWeak ? 'weak' : 'strong'})`);
|
|
270
|
+
}
|
|
271
|
+
if (isCancelled())
|
|
272
|
+
break;
|
|
273
|
+
// ── Step 4: Aggregate diagnosis ──────────────────
|
|
274
|
+
setEval({
|
|
275
|
+
phase: 'diagnosing',
|
|
276
|
+
iteration,
|
|
277
|
+
maxIterations: loopConfig.maxIterations,
|
|
278
|
+
weakCount,
|
|
279
|
+
strongCount,
|
|
280
|
+
probesTotal: judgedResults.length,
|
|
281
|
+
});
|
|
282
|
+
store_1.store.setPhase('evaluating');
|
|
283
|
+
// Build scoped rules context for diagnosis
|
|
284
|
+
const rulesCtx = staticRules?.map((r) => `### ${r.slug} (${r.source})\nGlobs: ${r.globs.join(', ')}\n${r.content}`).join('\n---\n') || '';
|
|
285
|
+
const staticData = staticRules?.length
|
|
286
|
+
? `${staticRules.length} candidate rules from static analysis (hubs, conventions, circular deps). The LLM decides which are worth keeping as scoped rules vs folding into AGENTS.md.`
|
|
287
|
+
: '';
|
|
288
|
+
const diagnosisEdits = await (0, evaluator_1.diagnose)({
|
|
289
|
+
judgedResults,
|
|
290
|
+
agentsContent: finalContent,
|
|
291
|
+
provider: diagnosisProvider ?? provider,
|
|
292
|
+
log: optLog,
|
|
293
|
+
signal,
|
|
294
|
+
scopedRulesContext: rulesCtx,
|
|
295
|
+
staticAnalysisData: staticData,
|
|
296
|
+
});
|
|
297
|
+
if (isCancelled())
|
|
298
|
+
break;
|
|
299
|
+
// Merge per-probe edits + diagnosis edits, deduplicate
|
|
300
|
+
const allEdits = [];
|
|
301
|
+
for (const jr of judgedResults) {
|
|
302
|
+
allEdits.push(...jr.proposedEdits);
|
|
303
|
+
}
|
|
304
|
+
allEdits.push(...diagnosisEdits);
|
|
305
|
+
// Deduplicate by content similarity
|
|
306
|
+
const seen = new Set();
|
|
307
|
+
const dedupedEdits = [];
|
|
308
|
+
for (const edit of allEdits) {
|
|
309
|
+
const key = `${edit.section}:${edit.action}:${edit.content.toLowerCase().trim()}`;
|
|
310
|
+
if (!seen.has(key)) {
|
|
311
|
+
seen.add(key);
|
|
312
|
+
dedupedEdits.push(edit);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// Separate AGENTS.md edits from scoped rule edits
|
|
316
|
+
const agentsMdEdits = dedupedEdits.filter((e) => !e.section.startsWith('scoped:'));
|
|
317
|
+
const scopedEdits = dedupedEdits.filter((e) => e.section.startsWith('scoped:'));
|
|
318
|
+
// Collect scoped rule operations for later
|
|
319
|
+
for (const edit of scopedEdits) {
|
|
320
|
+
if (edit.section.startsWith('scoped:DELETE:')) {
|
|
321
|
+
const slug = edit.section.replace('scoped:DELETE:', '');
|
|
322
|
+
scopedRuleDeletes.push(slug);
|
|
323
|
+
}
|
|
324
|
+
else if (edit.section.startsWith('scoped:CREATE:')) {
|
|
325
|
+
const slug = edit.section.replace('scoped:CREATE:', '');
|
|
326
|
+
if (edit.content && edit.globs?.length) {
|
|
327
|
+
scopedRuleCreates.push({
|
|
328
|
+
slug,
|
|
329
|
+
description: edit.description || `Rule for ${slug}`,
|
|
330
|
+
globs: edit.globs,
|
|
331
|
+
content: edit.content,
|
|
332
|
+
source: 'probe',
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
// scoped:slug — update existing rule
|
|
338
|
+
const slug = edit.section.replace('scoped:', '');
|
|
339
|
+
if (edit.content) {
|
|
340
|
+
scopedRuleCreates.push({
|
|
341
|
+
slug,
|
|
342
|
+
description: edit.description || `Updated rule for ${slug}`,
|
|
343
|
+
globs: edit.globs || [`**`],
|
|
344
|
+
content: edit.content,
|
|
345
|
+
source: 'probe',
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const cappedEdits = agentsMdEdits.slice(0, loopConfig.maxEditsPerIteration);
|
|
351
|
+
const totalEditCount = cappedEdits.length + scopedEdits.length;
|
|
352
|
+
log.info(`Applying ${cappedEdits.length} AGENTS.md edits, ${scopedEdits.length} scoped rule edits (${allEdits.length} total)`);
|
|
353
|
+
// ── Step 5: Apply AGENTS.md edits deterministically ────────
|
|
354
|
+
const pendingEditSummaries = [
|
|
355
|
+
...cappedEdits.map((e) => `${e.action} ${e.section}: "${e.content.length > 60 ? e.content.slice(0, 57) + '...' : e.content}"`),
|
|
356
|
+
...scopedEdits.map((e) => `${e.section}`),
|
|
357
|
+
];
|
|
358
|
+
setEval({
|
|
359
|
+
phase: 'applying',
|
|
360
|
+
iteration,
|
|
361
|
+
maxIterations: loopConfig.maxIterations,
|
|
362
|
+
proposedEditCount: totalEditCount,
|
|
363
|
+
editSummaries: pendingEditSummaries,
|
|
364
|
+
});
|
|
365
|
+
store_1.store.setPhase('evaluating');
|
|
366
|
+
const guidanceBefore = finalContent;
|
|
367
|
+
const applyResult = await (0, evaluator_1.applyEditsWithLlm)(finalContent, cappedEdits, loopConfig.charBudget, provider, signal);
|
|
368
|
+
finalContent = applyResult.content;
|
|
369
|
+
totalEditsApplied += applyResult.applied + scopedEdits.length;
|
|
370
|
+
allAppliedEdits.push(...cappedEdits.slice(0, applyResult.applied));
|
|
371
|
+
allAppliedEdits.push(...scopedEdits);
|
|
372
|
+
if (applyResult.trimmed > 0) {
|
|
373
|
+
log.info(`Trimmed ${applyResult.trimmed} bullets to fit ${loopConfig.charBudget}-char budget`);
|
|
374
|
+
}
|
|
375
|
+
// ── Step 6: Convergence check ────────────────────
|
|
376
|
+
const guidanceChanged = finalContent !== guidanceBefore;
|
|
377
|
+
if (guidanceChanged) {
|
|
378
|
+
noChangeStreak = 0;
|
|
379
|
+
log.info(`Guidance updated (${guidanceBefore.length} → ${finalContent.length} chars)`);
|
|
156
380
|
}
|
|
157
381
|
else {
|
|
158
|
-
|
|
159
|
-
|
|
382
|
+
noChangeStreak++;
|
|
383
|
+
log.info(`No guidance change (streak: ${noChangeStreak})`);
|
|
160
384
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
385
|
+
// Build iteration summary
|
|
386
|
+
const roundParts = [];
|
|
387
|
+
roundParts.push(`${probes.length} scenarios`);
|
|
388
|
+
if (weakCount > 0)
|
|
389
|
+
roundParts.push(`${weakCount} gap${weakCount === 1 ? '' : 's'}`);
|
|
390
|
+
else
|
|
391
|
+
roundParts.push('all passed');
|
|
392
|
+
if (applyResult.applied > 0)
|
|
393
|
+
roundParts.push(`${applyResult.applied} improvement${applyResult.applied === 1 ? '' : 's'}`);
|
|
394
|
+
iterationSummaries.push(`Round ${iteration}: ${roundParts.join(', ')}`);
|
|
395
|
+
if (noChangeStreak >= 2) {
|
|
396
|
+
convergedReason = 'guidance converged (no changes)';
|
|
397
|
+
log.info(`Converged: ${convergedReason}`);
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const editSummaries = allAppliedEdits.map((e) => {
|
|
402
|
+
const verb = { add: 'Added', remove: 'Removed', strengthen: 'Strengthened', modify: 'Updated' }[e.action];
|
|
403
|
+
const brief = e.content.length > 60 ? e.content.slice(0, 57) + '...' : e.content;
|
|
404
|
+
return `${verb}: ${brief} (${e.section})`;
|
|
405
|
+
});
|
|
406
|
+
const wasCancelled = isCancelled();
|
|
167
407
|
store_1.store.setEvalStatus({
|
|
168
|
-
phase: '
|
|
169
|
-
|
|
170
|
-
|
|
408
|
+
phase: 'done',
|
|
409
|
+
iteration: loopConfig.maxIterations,
|
|
410
|
+
maxIterations: loopConfig.maxIterations,
|
|
411
|
+
diagnosisEdits: totalEditsApplied,
|
|
412
|
+
convergedReason: wasCancelled ? undefined : convergedReason,
|
|
413
|
+
editSummaries,
|
|
414
|
+
iterationSummaries: iterationSummaries.length > 0 ? iterationSummaries : undefined,
|
|
415
|
+
cancelled: wasCancelled,
|
|
171
416
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const diagnosis = await (0, evaluator_1.diagnose)(failures, finalContent, provider, optLog);
|
|
179
|
-
if (diagnosis && diagnosis.edits.length > 0) {
|
|
180
|
-
store_1.store.setPhase('evaluating', 'applying fixes');
|
|
181
|
-
log.info(`Applying ${diagnosis.edits.length} diagnosis-driven edits…`);
|
|
182
|
-
const fixed = await (0, evaluator_1.applyDiagnosisEdits)(finalContent, diagnosis, provider, optLog);
|
|
183
|
-
finalContent = fixed.content;
|
|
184
|
-
log.info(`Diagnosis edits applied (${fixed.appliedEdits.length} changes)`);
|
|
185
|
-
}
|
|
186
|
-
store_1.store.setEvalStatus({
|
|
187
|
-
phase: 'done',
|
|
188
|
-
probesPassed: passCount,
|
|
189
|
-
probesTotal: probeResults.length,
|
|
190
|
-
diagnosisEdits: diagnosis?.edits.length ?? 0,
|
|
191
|
-
});
|
|
417
|
+
store_1.store.removeListener('change', onStoreChange);
|
|
418
|
+
if (wasCancelled) {
|
|
419
|
+
log.info(`Probe-and-refine cancelled by user (${totalEditsApplied} edits applied)`);
|
|
420
|
+
}
|
|
421
|
+
else if (convergedReason) {
|
|
422
|
+
log.info(`Probe-and-refine complete: ${convergedReason}`);
|
|
192
423
|
}
|
|
193
424
|
else {
|
|
425
|
+
log.info(`Probe-and-refine complete: max iterations reached`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
catch (err) {
|
|
429
|
+
// Clean up abort listener if we exit via exception
|
|
430
|
+
store_1.store.removeListener('change', onStoreChange);
|
|
431
|
+
// Tier exhaustion — re-throw so pipeline can show upgrade prompt
|
|
432
|
+
if (err?.tierExhausted)
|
|
433
|
+
throw err;
|
|
434
|
+
// AbortError from cancel — not a real error
|
|
435
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
436
|
+
const editSummaries = allAppliedEdits.map((e) => {
|
|
437
|
+
const verb = { add: 'Added', remove: 'Removed', strengthen: 'Strengthened', modify: 'Updated' }[e.action];
|
|
438
|
+
const brief = e.content.length > 60 ? e.content.slice(0, 57) + '...' : e.content;
|
|
439
|
+
return `${verb}: ${brief} (${e.section})`;
|
|
440
|
+
});
|
|
194
441
|
store_1.store.setEvalStatus({
|
|
195
442
|
phase: 'done',
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
443
|
+
diagnosisEdits: totalEditsApplied,
|
|
444
|
+
editSummaries,
|
|
445
|
+
iterationSummaries: iterationSummaries.length > 0 ? iterationSummaries : undefined,
|
|
446
|
+
cancelled: true,
|
|
199
447
|
});
|
|
448
|
+
log.info(`Probe-and-refine cancelled by user (${totalEditsApplied} edits applied)`);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
452
|
+
log.warn(`Probe and refine failed (non-fatal): ${msg}`);
|
|
200
453
|
}
|
|
201
454
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
455
|
+
}
|
|
456
|
+
store_1.store.setReasoning([]);
|
|
457
|
+
// ── Build final scoped rules from evaluator decisions ──────
|
|
458
|
+
// The diagnosis step decided what scoped rules to create/delete.
|
|
459
|
+
// Start with static rules, apply evaluator modifications.
|
|
460
|
+
let finalRules = staticRules ?? [];
|
|
461
|
+
if (evaluatorEnabled) {
|
|
462
|
+
// Remove rules the evaluator marked for deletion
|
|
463
|
+
if (scopedRuleDeletes.length > 0) {
|
|
464
|
+
const deleteSet = new Set(scopedRuleDeletes);
|
|
465
|
+
finalRules = finalRules.filter((r) => !deleteSet.has(r.slug));
|
|
466
|
+
log.info(`Evaluator pruned ${scopedRuleDeletes.length} scoped rule${scopedRuleDeletes.length === 1 ? '' : 's'}`);
|
|
467
|
+
}
|
|
468
|
+
// Add/update rules the evaluator created
|
|
469
|
+
if (scopedRuleCreates.length > 0) {
|
|
470
|
+
const createBySlug = new Map(scopedRuleCreates.map((r) => [r.slug, r]));
|
|
471
|
+
// Update existing rules or add new ones
|
|
472
|
+
finalRules = finalRules.map((r) => createBySlug.get(r.slug) ?? r);
|
|
473
|
+
// Add truly new rules (not updates)
|
|
474
|
+
const existingSlugs = new Set(finalRules.map((r) => r.slug));
|
|
475
|
+
for (const r of scopedRuleCreates) {
|
|
476
|
+
if (!existingSlugs.has(r.slug))
|
|
477
|
+
finalRules.push(r);
|
|
478
|
+
}
|
|
479
|
+
log.info(`Evaluator created/updated ${scopedRuleCreates.length} scoped rule${scopedRuleCreates.length === 1 ? '' : 's'}`);
|
|
205
480
|
}
|
|
206
481
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
482
|
+
// ── Save probe-refine edits as preferences ───────────────
|
|
483
|
+
if (evaluatorEnabled && allAppliedEdits.length > 0 && preferences) {
|
|
484
|
+
try {
|
|
485
|
+
let prefs = { ...preferences };
|
|
486
|
+
for (const edit of allAppliedEdits) {
|
|
487
|
+
const isSpecific = edit.section.startsWith('scoped:') ||
|
|
488
|
+
/(?:^|\s)(?:\.\/|src\/|lib\/|app\/|packages\/|test\/|tests\/)\S+\.\w{1,4}/m.test(edit.content);
|
|
489
|
+
prefs = (0, preferences_1.addPreference)(prefs, {
|
|
490
|
+
rule: `probe-refine:${edit.section}`,
|
|
491
|
+
pattern: edit.content.slice(0, 200),
|
|
492
|
+
disposition: 'deny',
|
|
493
|
+
directory: edit.globs?.[0],
|
|
494
|
+
details: `action: ${edit.action}, section: ${edit.section}`,
|
|
495
|
+
suggestion: edit.content,
|
|
496
|
+
source: isSpecific ? 'probe-refine-specific' : 'probe-refine',
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
(0, preferences_1.savePreferences)(root, prefs);
|
|
500
|
+
}
|
|
501
|
+
catch { /* best-effort — don't break the pipeline */ }
|
|
502
|
+
}
|
|
503
|
+
return { content: finalContent, reasoning: [], scopedRules: finalRules, deleteSlugs: scopedRuleDeletes };
|
|
213
504
|
}
|
|
214
505
|
//# sourceMappingURL=optimize.js.map
|