pumuki-ast-hooks 5.6.7 → 5.6.9
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 +249 -460
- package/bin/cli.js +3 -1
- package/docs/HOW_IT_WORKS.md +68 -2
- package/package.json +1 -1
- package/scripts/hooks-system/.audit-reports/auto-recovery.log +2 -0
- package/scripts/hooks-system/.audit-reports/install-wizard.log +8 -0
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +48 -0
- package/scripts/hooks-system/bin/__tests__/cli.spec.js +133 -0
- package/scripts/hooks-system/bin/cli.js +70 -9
- package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +39 -10
- package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log +6 -0
|
@@ -8,4 +8,137 @@ describe('cli', () => {
|
|
|
8
8
|
it('should be valid JavaScript', () => {
|
|
9
9
|
expect(() => require.resolve('../cli.js')).not.toThrow();
|
|
10
10
|
});
|
|
11
|
+
|
|
12
|
+
it('should expose proposeHumanIntent and infer goal from recent commits', () => {
|
|
13
|
+
const childProcess = require('child_process');
|
|
14
|
+
|
|
15
|
+
const originalExecSync = childProcess.execSync;
|
|
16
|
+
childProcess.execSync = (cmd) => {
|
|
17
|
+
const command = String(cmd);
|
|
18
|
+
if (command.includes('git log') && command.includes('--pretty=%s')) {
|
|
19
|
+
return 'fix: token economy docs, assets and MCP outputs\nRelease: 2026-01-11\n';
|
|
20
|
+
}
|
|
21
|
+
return '';
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const { proposeHumanIntent } = require('../cli.js');
|
|
25
|
+
expect(typeof proposeHumanIntent).toBe('function');
|
|
26
|
+
|
|
27
|
+
const proposed = proposeHumanIntent({
|
|
28
|
+
evidence: { ai_gate: { status: 'ALLOWED' }, platforms: {} },
|
|
29
|
+
branch: 'develop',
|
|
30
|
+
stagedFiles: []
|
|
31
|
+
});
|
|
32
|
+
expect(proposed && typeof proposed.primary_goal).toBe('string');
|
|
33
|
+
expect(proposed.primary_goal.toLowerCase()).toContain('token economy');
|
|
34
|
+
|
|
35
|
+
childProcess.execSync = originalExecSync;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('wrap-up should auto-save human_intent by default', () => {
|
|
39
|
+
const fs = require('fs');
|
|
40
|
+
const childProcess = require('child_process');
|
|
41
|
+
|
|
42
|
+
const originalConsoleLog = console.log;
|
|
43
|
+
const logSpy = jest.fn();
|
|
44
|
+
console.log = logSpy;
|
|
45
|
+
|
|
46
|
+
const originalArgv = process.argv;
|
|
47
|
+
const originalExecSync = childProcess.execSync;
|
|
48
|
+
|
|
49
|
+
const existsSyncSpy = jest.spyOn(fs, 'existsSync').mockImplementation(() => true);
|
|
50
|
+
const readFileSyncSpy = jest.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify({ ai_gate: { status: 'ALLOWED' }, platforms: {} }));
|
|
51
|
+
const writeFileSyncSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => { });
|
|
52
|
+
|
|
53
|
+
childProcess.execSync = (cmd) => {
|
|
54
|
+
const command = String(cmd);
|
|
55
|
+
if (command.includes('git rev-parse --show-toplevel')) {
|
|
56
|
+
return '/tmp/repo\n';
|
|
57
|
+
}
|
|
58
|
+
if (command.includes('git branch --show-current')) {
|
|
59
|
+
return 'main\n';
|
|
60
|
+
}
|
|
61
|
+
if (command.includes('git diff --cached --name-only')) {
|
|
62
|
+
return '\n';
|
|
63
|
+
}
|
|
64
|
+
if (command.includes('git log') && command.includes('--pretty=%s')) {
|
|
65
|
+
return 'fix: token economy docs, assets and MCP outputs\n';
|
|
66
|
+
}
|
|
67
|
+
if (command.includes('node') && command.includes('intelligent-audit.js')) {
|
|
68
|
+
return '';
|
|
69
|
+
}
|
|
70
|
+
return '';
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
process.argv = ['node', 'cli.js', 'wrap-up'];
|
|
74
|
+
jest.resetModules();
|
|
75
|
+
const { commands } = require('../cli.js');
|
|
76
|
+
commands['wrap-up']();
|
|
77
|
+
|
|
78
|
+
expect(logSpy.mock.calls.map(c => String(c[0] || '')).join('\n')).toContain('auto-saved');
|
|
79
|
+
expect(writeFileSyncSpy).toHaveBeenCalled();
|
|
80
|
+
const written = writeFileSyncSpy.mock.calls.map(c => String(c[1] || '')).join('\n');
|
|
81
|
+
expect(written).toContain('"human_intent"');
|
|
82
|
+
expect(written.toLowerCase()).toContain('token economy');
|
|
83
|
+
|
|
84
|
+
console.log = originalConsoleLog;
|
|
85
|
+
process.argv = originalArgv;
|
|
86
|
+
childProcess.execSync = originalExecSync;
|
|
87
|
+
existsSyncSpy.mockRestore();
|
|
88
|
+
readFileSyncSpy.mockRestore();
|
|
89
|
+
writeFileSyncSpy.mockRestore();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('wrap-up should not save when --no-save is provided', () => {
|
|
93
|
+
const fs = require('fs');
|
|
94
|
+
const childProcess = require('child_process');
|
|
95
|
+
|
|
96
|
+
const originalConsoleLog = console.log;
|
|
97
|
+
const logSpy = jest.fn();
|
|
98
|
+
console.log = logSpy;
|
|
99
|
+
|
|
100
|
+
const originalArgv = process.argv;
|
|
101
|
+
const originalExecSync = childProcess.execSync;
|
|
102
|
+
|
|
103
|
+
const existsSyncSpy = jest.spyOn(fs, 'existsSync').mockImplementation(() => true);
|
|
104
|
+
const readFileSyncSpy = jest.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify({ ai_gate: { status: 'ALLOWED' }, platforms: {} }));
|
|
105
|
+
const writeFileSyncSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => { });
|
|
106
|
+
|
|
107
|
+
childProcess.execSync = (cmd) => {
|
|
108
|
+
const command = String(cmd);
|
|
109
|
+
if (command.includes('git rev-parse --show-toplevel')) {
|
|
110
|
+
return '/tmp/repo\n';
|
|
111
|
+
}
|
|
112
|
+
if (command.includes('git branch --show-current')) {
|
|
113
|
+
return 'main\n';
|
|
114
|
+
}
|
|
115
|
+
if (command.includes('git diff --cached --name-only')) {
|
|
116
|
+
return '\n';
|
|
117
|
+
}
|
|
118
|
+
if (command.includes('git log') && command.includes('--pretty=%s')) {
|
|
119
|
+
return 'fix: token economy docs, assets and MCP outputs\n';
|
|
120
|
+
}
|
|
121
|
+
if (command.includes('node') && command.includes('intelligent-audit.js')) {
|
|
122
|
+
return '';
|
|
123
|
+
}
|
|
124
|
+
return '';
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
process.argv = ['node', 'cli.js', 'wrap-up', '--no-save'];
|
|
128
|
+
jest.resetModules();
|
|
129
|
+
const { commands } = require('../cli.js');
|
|
130
|
+
commands['wrap-up']();
|
|
131
|
+
|
|
132
|
+
expect(logSpy.mock.calls.map(c => String(c[0] || '')).join('\n')).toContain('proposal only');
|
|
133
|
+
expect(writeFileSyncSpy).toHaveBeenCalled();
|
|
134
|
+
const written = writeFileSyncSpy.mock.calls.map(c => String(c[1] || '')).join('\n');
|
|
135
|
+
expect(written).not.toContain('"human_intent"');
|
|
136
|
+
|
|
137
|
+
console.log = originalConsoleLog;
|
|
138
|
+
process.argv = originalArgv;
|
|
139
|
+
childProcess.execSync = originalExecSync;
|
|
140
|
+
existsSyncSpy.mockRestore();
|
|
141
|
+
readFileSyncSpy.mockRestore();
|
|
142
|
+
writeFileSyncSpy.mockRestore();
|
|
143
|
+
});
|
|
11
144
|
});
|
|
@@ -11,8 +11,8 @@ const fs = require('fs');
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const env = require('../config/env');
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
let command = process.argv[2];
|
|
15
|
+
let args = process.argv.slice(3);
|
|
16
16
|
|
|
17
17
|
const HOOKS_ROOT = path.join(__dirname, '..');
|
|
18
18
|
|
|
@@ -65,6 +65,15 @@ function getStagedFilesSafe() {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
function getRecentCommitSubjects(limit = 10) {
|
|
69
|
+
try {
|
|
70
|
+
const output = execSync(`git log -n ${limit} --pretty=%s`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
71
|
+
return String(output || '').split('\n').map(s => s.trim()).filter(Boolean);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
68
77
|
function proposeHumanIntent({ evidence, branch, stagedFiles }) {
|
|
69
78
|
const safeEvidence = (evidence && typeof evidence === 'object') ? evidence : {};
|
|
70
79
|
const safeBranch = branch || safeEvidence.current_context?.current_branch || 'unknown';
|
|
@@ -91,6 +100,20 @@ function proposeHumanIntent({ evidence, branch, stagedFiles }) {
|
|
|
91
100
|
const platformLabel = platforms.length > 0 ? platforms.join('+') : (detectedPlatforms.length > 0 ? detectedPlatforms.join('+') : 'repo');
|
|
92
101
|
|
|
93
102
|
let primaryGoal = `Continue work on ${platformLabel} changes`;
|
|
103
|
+
if (platformLabel === 'repo' && staged.length === 0 && detectedPlatforms.length === 0) {
|
|
104
|
+
const subjects = getRecentCommitSubjects(12).join(' | ').toLowerCase();
|
|
105
|
+
if (subjects.includes('token economy')) {
|
|
106
|
+
primaryGoal = 'Continue token economy improvements (docs + MCP outputs)';
|
|
107
|
+
} else if (subjects.includes('release') || subjects.includes('publish') || subjects.includes('version')) {
|
|
108
|
+
primaryGoal = 'Continue release/publish workflow maintenance';
|
|
109
|
+
} else if (subjects.includes('gitflow')) {
|
|
110
|
+
primaryGoal = 'Continue Git Flow automation maintenance';
|
|
111
|
+
} else if (subjects.includes('mcp')) {
|
|
112
|
+
primaryGoal = 'Continue MCP automation maintenance';
|
|
113
|
+
} else if (subjects.includes('readme') || subjects.includes('docs')) {
|
|
114
|
+
primaryGoal = 'Continue documentation improvements';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
94
117
|
if (gateStatus === 'BLOCKED') {
|
|
95
118
|
primaryGoal = `Unblock AI gate by fixing ${platformLabel} violations`;
|
|
96
119
|
}
|
|
@@ -250,7 +273,33 @@ const commands = {
|
|
|
250
273
|
const stagedFiles = getStagedFilesSafe();
|
|
251
274
|
const proposed = proposeHumanIntent({ evidence, branch, stagedFiles });
|
|
252
275
|
|
|
253
|
-
|
|
276
|
+
const shouldSave = !process.argv.includes('--no-save');
|
|
277
|
+
if (shouldSave) {
|
|
278
|
+
const now = new Date();
|
|
279
|
+
const expiresAt = new Date(Date.now() + 24 * 3600000).toISOString();
|
|
280
|
+
evidence.human_intent = {
|
|
281
|
+
primary_goal: proposed.primary_goal,
|
|
282
|
+
secondary_goals: proposed.secondary_goals || [],
|
|
283
|
+
non_goals: proposed.non_goals || [],
|
|
284
|
+
constraints: proposed.constraints || [],
|
|
285
|
+
confidence_level: proposed.confidence_level || 'medium',
|
|
286
|
+
set_by: 'wrap-up',
|
|
287
|
+
set_at: now.toISOString(),
|
|
288
|
+
expires_at: expiresAt,
|
|
289
|
+
preserved_at: now.toISOString(),
|
|
290
|
+
preservation_count: 0
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
fs.writeFileSync(evidencePath, JSON.stringify(evidence, null, 2), 'utf8');
|
|
295
|
+
} catch (e) {
|
|
296
|
+
if (process.env.DEBUG) {
|
|
297
|
+
process.stderr.write(`[wrap-up] Failed to save human_intent: ${e && e.message ? e.message : String(e)}\n`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
console.log(`\n💡 Suggested Human Intent (${shouldSave ? 'auto-saved' : 'proposal only'}):`);
|
|
254
303
|
console.log(` Primary Goal: ${proposed.primary_goal}`);
|
|
255
304
|
console.log(` Secondary: ${(proposed.secondary_goals || []).join(', ') || '(none)'}`);
|
|
256
305
|
console.log(` Constraints: ${(proposed.constraints || []).join(', ') || '(none)'}`);
|
|
@@ -259,9 +308,14 @@ const commands = {
|
|
|
259
308
|
console.log(` Gate: ${(proposed.derived_from && proposed.derived_from.gate_status) || '(unknown)'}`);
|
|
260
309
|
|
|
261
310
|
const suggestedCmd = `ast-hooks intent set --goal="${proposed.primary_goal}" --confidence=${proposed.confidence_level || 'medium'} --expires=24h`;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
311
|
+
if (shouldSave) {
|
|
312
|
+
console.log('\n✅ Saved to .AI_EVIDENCE.json');
|
|
313
|
+
console.log('');
|
|
314
|
+
} else {
|
|
315
|
+
console.log('\n✅ To apply it, run:');
|
|
316
|
+
console.log(` ${suggestedCmd}`);
|
|
317
|
+
console.log('');
|
|
318
|
+
}
|
|
265
319
|
} catch (error) {
|
|
266
320
|
if (process.env.DEBUG) {
|
|
267
321
|
process.stderr.write(`[wrap-up] Intent suggestion failed: ${error && error.message ? error.message : String(error)}\n`);
|
|
@@ -569,12 +623,15 @@ Documentation:
|
|
|
569
623
|
},
|
|
570
624
|
|
|
571
625
|
version: () => {
|
|
572
|
-
const pkg = require('
|
|
626
|
+
const pkg = require(path.join(__dirname, '../../../package.json'));
|
|
573
627
|
console.log(`v${pkg.version}`);
|
|
574
628
|
}
|
|
575
629
|
};
|
|
576
630
|
|
|
577
|
-
|
|
631
|
+
function runCli(argv = process.argv) {
|
|
632
|
+
command = argv[2];
|
|
633
|
+
args = argv.slice(3);
|
|
634
|
+
|
|
578
635
|
if (!command || !commands[command]) {
|
|
579
636
|
commands.help();
|
|
580
637
|
process.exit(command ? 1 : 0);
|
|
@@ -582,4 +639,8 @@ if (require.main === module) {
|
|
|
582
639
|
commands[command]();
|
|
583
640
|
}
|
|
584
641
|
|
|
585
|
-
|
|
642
|
+
if (require.main === module) {
|
|
643
|
+
runCli(process.argv);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
module.exports = { commands, proposeHumanIntent, runCli };
|
|
@@ -715,11 +715,19 @@ function cleanupStaleBranches(params) {
|
|
|
715
715
|
*/
|
|
716
716
|
async function autoExecuteAIStart(params) {
|
|
717
717
|
const useCase = getCompositionRoot().getAutoExecuteAIStartUseCase();
|
|
718
|
+
const tokenEconomyRule = 'TOKEN_ECONOMY: Prioritize token/cost efficiency. Batch related checks, avoid redundant scans, reuse cached context where possible, ask the user for missing info instead of exploring blindly, and keep responses concise.';
|
|
718
719
|
|
|
719
720
|
try {
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
|
|
721
|
+
const orchestrator = getCompositionRoot().getOrchestrator();
|
|
722
|
+
const analysis = await orchestrator.analyzeContext();
|
|
723
|
+
|
|
724
|
+
const platforms = Array.isArray(analysis?.platforms)
|
|
725
|
+
? analysis.platforms.map(p => (p && typeof p === 'object' ? (p.platform || p.name) : p)).filter(Boolean)
|
|
726
|
+
: [];
|
|
727
|
+
|
|
728
|
+
const confidence = Number.isFinite(analysis?.confidence) ? analysis.confidence : 0;
|
|
729
|
+
|
|
730
|
+
const result = await useCase.execute(platforms, confidence);
|
|
723
731
|
|
|
724
732
|
if (result.action === 'auto-executed') {
|
|
725
733
|
sendNotification(
|
|
@@ -731,6 +739,7 @@ async function autoExecuteAIStart(params) {
|
|
|
731
739
|
|
|
732
740
|
return {
|
|
733
741
|
success: true,
|
|
742
|
+
framework_rules: [tokenEconomyRule],
|
|
734
743
|
...result
|
|
735
744
|
};
|
|
736
745
|
|
|
@@ -738,6 +747,7 @@ async function autoExecuteAIStart(params) {
|
|
|
738
747
|
return {
|
|
739
748
|
success: false,
|
|
740
749
|
action: 'error',
|
|
750
|
+
framework_rules: [tokenEconomyRule],
|
|
741
751
|
message: `Failed to execute AI Start: ${error.message}`
|
|
742
752
|
};
|
|
743
753
|
}
|
|
@@ -1144,6 +1154,9 @@ function extractCriticalPatterns(content, platform) {
|
|
|
1144
1154
|
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO composición > herencia', severity: 'MANDATORY' });
|
|
1145
1155
|
}
|
|
1146
1156
|
|
|
1157
|
+
/**
|
|
1158
|
+
* Returns the patterns for the given platforms.
|
|
1159
|
+
*/
|
|
1147
1160
|
return patterns;
|
|
1148
1161
|
}
|
|
1149
1162
|
|
|
@@ -1306,6 +1319,7 @@ async function aiGateCheck() {
|
|
|
1306
1319
|
const normalizedPlatforms = Array.from(new Set(platformsForRules));
|
|
1307
1320
|
|
|
1308
1321
|
let mandatoryRules = null;
|
|
1322
|
+
const tokenEconomyRule = 'TOKEN_ECONOMY: Prioritize token/cost efficiency. Batch related checks, avoid redundant scans, reuse cached context where possible, ask the user for missing info instead of exploring blindly, and keep responses concise.';
|
|
1309
1323
|
try {
|
|
1310
1324
|
const rulesData = await loadPlatformRules(normalizedPlatforms);
|
|
1311
1325
|
const rulesSample = rulesData.criticalRules.slice(0, 5).map(r => r.rule || r);
|
|
@@ -1316,7 +1330,8 @@ async function aiGateCheck() {
|
|
|
1316
1330
|
rulesLoaded: Object.keys(rulesData.rules),
|
|
1317
1331
|
totalRulesCount: rulesCount,
|
|
1318
1332
|
rulesSample,
|
|
1319
|
-
proofOfRead: `✅ VERIFIED: ${rulesCount} critical rules loaded from ${Object.keys(rulesData.rules).join(', ')}
|
|
1333
|
+
proofOfRead: `✅ VERIFIED: ${rulesCount} critical rules loaded from ${Object.keys(rulesData.rules).join(', ')}`,
|
|
1334
|
+
framework_rules: [tokenEconomyRule]
|
|
1320
1335
|
};
|
|
1321
1336
|
} catch (error) {
|
|
1322
1337
|
if (process.env.DEBUG) {
|
|
@@ -1328,7 +1343,8 @@ async function aiGateCheck() {
|
|
|
1328
1343
|
criticalRules: [],
|
|
1329
1344
|
rulesLoaded: [],
|
|
1330
1345
|
status: 'FAILED_TO_LOAD',
|
|
1331
|
-
error: `Failed to load rules content: ${error && error.message ? error.message : String(error)}
|
|
1346
|
+
error: `Failed to load rules content: ${error && error.message ? error.message : String(error)}`,
|
|
1347
|
+
framework_rules: [tokenEconomyRule]
|
|
1332
1348
|
};
|
|
1333
1349
|
}
|
|
1334
1350
|
|
|
@@ -1373,7 +1389,7 @@ async function aiGateCheck() {
|
|
|
1373
1389
|
: `✅ ALLOWED: Gate check passed with ${warnings.length} warning(s).`,
|
|
1374
1390
|
instructions: finalBlocked
|
|
1375
1391
|
? 'Fix violations before proceeding. Run ai-start if needed.'
|
|
1376
|
-
: `✅ ${mandatoryRules.totalRulesCount} RULES LOADED. Sample: ${mandatoryRules.rulesSample.slice(0, 2).join(' | ')}... Review ALL rules in mandatory_rules.criticalRules before ANY code generation.`,
|
|
1392
|
+
: `✅ ${mandatoryRules.totalRulesCount} RULES LOADED. Sample: ${mandatoryRules.rulesSample.slice(0, 2).join(' | ')}... Review ALL rules in mandatory_rules.criticalRules before ANY code generation. Also follow mandatory_rules.framework_rules (token economy).`,
|
|
1377
1393
|
cognitive_context: humanIntent?.primary_goal
|
|
1378
1394
|
? `🎯 USER INTENT: ${humanIntent.primary_goal} (confidence: ${humanIntent.confidence_level || 'unset'})`
|
|
1379
1395
|
: null,
|
|
@@ -1444,18 +1460,25 @@ async function aiGateCheck() {
|
|
|
1444
1460
|
platforms: ['backend', 'frontend', 'ios', 'android'],
|
|
1445
1461
|
criticalRules: [],
|
|
1446
1462
|
rulesLoaded: [],
|
|
1463
|
+
framework_rules: ['TOKEN_ECONOMY: Prioritize token/cost efficiency. Batch related checks, avoid redundant scans, reuse cached context where possible, ask the user for missing info instead of exploring blindly, and keep responses concise.'],
|
|
1447
1464
|
warning: '⚠️ AI MUST read and follow these rules before ANY code generation or modification',
|
|
1448
1465
|
error: 'Rules could not be loaded due to timeout'
|
|
1449
1466
|
},
|
|
1450
1467
|
summary: '🚫 BLOCKED: Gate check timed out.',
|
|
1451
|
-
instructions: 'DO NOT proceed with user task. Retry the gate check.'
|
|
1468
|
+
instructions: 'DO NOT proceed with user task. Retry the gate check.',
|
|
1469
|
+
cognitive_context: null,
|
|
1470
|
+
human_intent: null,
|
|
1471
|
+
semantic_snapshot: null,
|
|
1472
|
+
auto_intent: null,
|
|
1473
|
+
session: {
|
|
1474
|
+
id: gateSession.sessionId,
|
|
1475
|
+
checkCount: gateSession.checkCount,
|
|
1476
|
+
validFor: gateSession.GATE_VALIDITY_MS / 60000 + ' minutes'
|
|
1477
|
+
}
|
|
1452
1478
|
};
|
|
1453
1479
|
gateSession.recordCheck(timeoutResult);
|
|
1454
1480
|
return timeoutResult;
|
|
1455
1481
|
}
|
|
1456
|
-
/**
|
|
1457
|
-
* Read platform rules handler - returns critical rules for a specific platform
|
|
1458
|
-
*/
|
|
1459
1482
|
async function readPlatformRulesHandler(params) {
|
|
1460
1483
|
const platform = params.platform;
|
|
1461
1484
|
if (!platform) {
|
|
@@ -1693,10 +1716,12 @@ function suggestHumanIntent() {
|
|
|
1693
1716
|
*/
|
|
1694
1717
|
function preFlightCheck(params) {
|
|
1695
1718
|
const { action_type, target_file, proposed_code, bypass_tdd } = params;
|
|
1719
|
+
const tokenEconomyRule = 'TOKEN_ECONOMY: Prioritize token/cost efficiency. Batch related checks, avoid redundant scans, reuse cached context where possible, ask the user for missing info instead of exploring blindly, and keep responses concise.';
|
|
1696
1720
|
|
|
1697
1721
|
if (!action_type || !target_file) {
|
|
1698
1722
|
return {
|
|
1699
1723
|
success: false,
|
|
1724
|
+
framework_rules: [tokenEconomyRule],
|
|
1700
1725
|
error: 'action_type and target_file are required',
|
|
1701
1726
|
hint: 'Call with: { action_type: "edit"|"create_file", target_file: "/path/to/file.ts", proposed_code: "..." }'
|
|
1702
1727
|
};
|
|
@@ -1716,6 +1741,7 @@ function preFlightCheck(params) {
|
|
|
1716
1741
|
success: false,
|
|
1717
1742
|
allowed: false,
|
|
1718
1743
|
blocked: true,
|
|
1744
|
+
framework_rules: [tokenEconomyRule],
|
|
1719
1745
|
reason: validation.enforcement_message,
|
|
1720
1746
|
violations: validation.violations,
|
|
1721
1747
|
tdd_status: validation.tddStatus,
|
|
@@ -1741,6 +1767,7 @@ function preFlightCheck(params) {
|
|
|
1741
1767
|
success: false,
|
|
1742
1768
|
allowed: false,
|
|
1743
1769
|
blocked: true,
|
|
1770
|
+
framework_rules: [tokenEconomyRule],
|
|
1744
1771
|
reason: '🚫 AST INTELLIGENCE BLOCKED: Critical/High violations detected in proposed code',
|
|
1745
1772
|
ast_violations: blocking,
|
|
1746
1773
|
ast_summary: astAnalysis.summary,
|
|
@@ -1765,6 +1792,7 @@ function preFlightCheck(params) {
|
|
|
1765
1792
|
success: true,
|
|
1766
1793
|
allowed: true,
|
|
1767
1794
|
has_warnings: true,
|
|
1795
|
+
framework_rules: [tokenEconomyRule],
|
|
1768
1796
|
warnings: validation.violations.filter(v => v.severity === 'WARNING'),
|
|
1769
1797
|
ast_analysis: astAnalysis,
|
|
1770
1798
|
message: '⚠️ Proceed with caution - review warnings',
|
|
@@ -1777,6 +1805,7 @@ function preFlightCheck(params) {
|
|
|
1777
1805
|
return {
|
|
1778
1806
|
success: true,
|
|
1779
1807
|
allowed: true,
|
|
1808
|
+
framework_rules: [tokenEconomyRule],
|
|
1780
1809
|
message: '✅ Pre-flight check PASSED - proceed with implementation',
|
|
1781
1810
|
ast_analysis: astAnalysis,
|
|
1782
1811
|
tdd_status: validation.tddStatus,
|
package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log
CHANGED
|
@@ -7,3 +7,9 @@
|
|
|
7
7
|
{"timestamp":"2026-01-11T00:48:11.264Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
|
|
8
8
|
{"timestamp":"2026-01-11T00:48:11.267Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
|
|
9
9
|
{"timestamp":"2026-01-11T00:48:11.267Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
|
|
10
|
+
{"timestamp":"2026-01-11T14:18:34.198Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
|
|
11
|
+
{"timestamp":"2026-01-11T14:18:34.200Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
|
|
12
|
+
{"timestamp":"2026-01-11T14:18:34.201Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
|
|
13
|
+
{"timestamp":"2026-01-11T18:11:25.198Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
|
|
14
|
+
{"timestamp":"2026-01-11T18:11:25.199Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
|
|
15
|
+
{"timestamp":"2026-01-11T18:11:25.199Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
|