minovative-mind-cli 2.14.1 → 2.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +40 -59
  2. package/dist/services/agent/slashCommands.js +144 -13
  3. package/dist/services/agent/toolLoop.js +11 -2
  4. package/dist/services/agent/types.d.ts +9 -2
  5. package/dist/services/agent-tools.d.ts +20 -1
  6. package/dist/services/agent-tools.js +272 -47
  7. package/dist/services/agent.js +43 -18
  8. package/dist/services/ai.d.ts +9 -0
  9. package/dist/services/ai.js +71 -21
  10. package/dist/services/chatHistoryService.d.ts +5 -0
  11. package/dist/services/contextAgent.d.ts +14 -6
  12. package/dist/services/contextAgent.js +36 -10
  13. package/dist/services/orchestration/investigationAgent.js +31 -7
  14. package/dist/services/orchestration/investigationCache.js +19 -9
  15. package/dist/services/orchestration/readCache.d.ts +1 -0
  16. package/dist/services/orchestration/readCache.js +5 -2
  17. package/dist/services/orchestration/scopedTools.js +37 -10
  18. package/dist/services/orchestration/subAgent.js +16 -2
  19. package/dist/services/proxyClient.d.ts +6 -0
  20. package/dist/services/proxyClient.js +24 -10
  21. package/dist/services/sessionSettings.d.ts +66 -0
  22. package/dist/services/sessionSettings.js +126 -0
  23. package/dist/services/userProfileService.d.ts +14 -0
  24. package/dist/services/userProfileService.js +105 -3
  25. package/dist/services/verificationService.js +24 -2
  26. package/dist/utils/analysisRunner.d.ts +120 -8
  27. package/dist/utils/analysisRunner.js +946 -125
  28. package/dist/utils/antiCheatingGuard.d.ts +21 -0
  29. package/dist/utils/antiCheatingGuard.js +554 -0
  30. package/dist/utils/contextPrompts.d.ts +39 -0
  31. package/dist/utils/contextPrompts.js +81 -9
  32. package/dist/utils/contextRanker.d.ts +216 -0
  33. package/dist/utils/contextRanker.js +603 -0
  34. package/dist/utils/dependencyTracer/modules/graph.d.ts +4 -1
  35. package/dist/utils/dependencyTracer/modules/graph.js +11 -0
  36. package/dist/utils/dependencyTracer/modules/types.d.ts +10 -0
  37. package/dist/utils/dependencyTracer.d.ts +40 -2
  38. package/dist/utils/dependencyTracer.js +95 -3
  39. package/dist/utils/fileReadCache.d.ts +58 -0
  40. package/dist/utils/fileReadCache.js +162 -0
  41. package/dist/utils/projectStorage.js +2 -1
  42. package/dist/utils/symbolExtractor.d.ts +12 -0
  43. package/dist/utils/symbolExtractor.js +111 -15
  44. package/dist/utils/systemPrompts.d.ts +4 -3
  45. package/dist/utils/systemPrompts.js +66 -8
  46. package/oclif.manifest.json +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Determines whether a given file path represents a critical project configuration
3
+ * file or root manifest that should never be deleted or renamed by the agent.
4
+ *
5
+ * @param filePath - Relative or absolute path to check
6
+ * @returns True if the file is a protected critical config file
7
+ */
8
+ export declare function isCriticalConfigFile(filePath: string): boolean;
9
+ /**
10
+ * Evaluates whether a proposed file modification or write introduces anti-cheating violations
11
+ * by attempting to silence, ignore, or bypass build, compiler, type, or lint errors.
12
+ *
13
+ * This function is strictly diff-aware: if the existing file already had an error-ignoring flag,
14
+ * modifying unrelated sections of the file will not trigger a false positive.
15
+ *
16
+ * @param filePath - Path to the file being created or modified
17
+ * @param newContent - The proposed new content of the file
18
+ * @param existingContent - The previous content of the file (if it already existed on disk)
19
+ * @returns An error message string if an anti-cheating violation is detected, or null if clean.
20
+ */
21
+ export declare function detectAntiCheatingViolations(filePath: string, newContent: string, existingContent?: string): string | null;
@@ -0,0 +1,554 @@
1
+ import path from 'node:path';
2
+ /**
3
+ * List of critical root configuration files, lockfiles, and manifests that the agent
4
+ * is strictly forbidden from deleting or renaming as an error-bypassing evasion strategy.
5
+ */
6
+ const CRITICAL_CONFIG_FILES = new Set([
7
+ // Node / JavaScript / TypeScript
8
+ 'package.json',
9
+ 'package-lock.json',
10
+ 'pnpm-lock.yaml',
11
+ 'yarn.lock',
12
+ 'bun.lockb',
13
+ 'bun.lock',
14
+ 'tsconfig.json',
15
+ 'tsconfig.base.json',
16
+ 'tsconfig.build.json',
17
+ 'tsconfig.app.json',
18
+ 'tsconfig.node.json',
19
+ 'jsconfig.json',
20
+ 'next.config.js',
21
+ 'next.config.ts',
22
+ 'next.config.mjs',
23
+ 'next.config.cjs',
24
+ 'vite.config.js',
25
+ 'vite.config.ts',
26
+ 'vite.config.mjs',
27
+ 'vite.config.cjs',
28
+ 'webpack.config.js',
29
+ 'webpack.config.ts',
30
+ 'webpack.config.mjs',
31
+ 'rollup.config.js',
32
+ 'rollup.config.ts',
33
+ 'rollup.config.mjs',
34
+ 'babel.config.js',
35
+ 'babel.config.json',
36
+ '.babelrc',
37
+ 'svelte.config.js',
38
+ 'astro.config.mjs',
39
+ 'nuxt.config.ts',
40
+ 'remix.config.js',
41
+ 'angular.json',
42
+ 'vitest.config.ts',
43
+ 'vitest.config.js',
44
+ 'jest.config.js',
45
+ 'jest.config.ts',
46
+ '.eslintrc',
47
+ '.eslintrc.js',
48
+ '.eslintrc.json',
49
+ '.eslintrc.yaml',
50
+ '.eslintrc.yml',
51
+ 'eslint.config.js',
52
+ 'eslint.config.mjs',
53
+ 'eslint.config.ts',
54
+ // Rust
55
+ 'cargo.toml',
56
+ 'cargo.lock',
57
+ // Go
58
+ 'go.mod',
59
+ 'go.sum',
60
+ // Python
61
+ 'pyproject.toml',
62
+ 'setup.py',
63
+ 'setup.cfg',
64
+ 'requirements.txt',
65
+ 'pipfile',
66
+ 'pipfile.lock',
67
+ 'poetry.lock',
68
+ 'mypy.ini',
69
+ // Java / Kotlin
70
+ 'pom.xml',
71
+ 'build.gradle',
72
+ 'build.gradle.kts',
73
+ 'settings.gradle',
74
+ 'settings.gradle.kts',
75
+ // C / C++
76
+ 'cmakelists.txt',
77
+ 'makefile',
78
+ 'meson.build',
79
+ // Ruby
80
+ 'gemfile',
81
+ 'gemfile.lock',
82
+ // PHP
83
+ 'composer.json',
84
+ 'composer.lock',
85
+ // Swift & Dart
86
+ 'package.swift',
87
+ 'pubspec.yaml',
88
+ 'pubspec.lock',
89
+ ]);
90
+ /**
91
+ * Determines whether a given file path represents a critical project configuration
92
+ * file or root manifest that should never be deleted or renamed by the agent.
93
+ *
94
+ * @param filePath - Relative or absolute path to check
95
+ * @returns True if the file is a protected critical config file
96
+ */
97
+ export function isCriticalConfigFile(filePath) {
98
+ const base = path.basename(filePath).toLowerCase();
99
+ return CRITICAL_CONFIG_FILES.has(base);
100
+ }
101
+ /**
102
+ * Checks if a Next.js configuration contains error-ignoring flags.
103
+ * Handles variations like:
104
+ * typescript: { ignoreBuildErrors: true }
105
+ * eslint: { ignoreDuringBuilds: true }
106
+ */
107
+ function hasNextConfigCheats(content) {
108
+ // Check typescript.ignoreBuildErrors
109
+ if (/\bignoreBuildErrors\s*:\s*(?:true|1|Boolean\s*\(\s*true\s*\))/i.test(content)) {
110
+ return {
111
+ cheat: true,
112
+ reason: 'Attempted to set "ignoreBuildErrors: true" in Next.js configuration to bypass type checking.',
113
+ };
114
+ }
115
+ // Check eslint.ignoreDuringBuilds
116
+ if (/\bignoreDuringBuilds\s*:\s*(?:true|1|Boolean\s*\(\s*true\s*\))/i.test(content)) {
117
+ return {
118
+ cheat: true,
119
+ reason: 'Attempted to set "ignoreDuringBuilds: true" in Next.js configuration to bypass ESLint checks.',
120
+ };
121
+ }
122
+ return { cheat: false };
123
+ }
124
+ /**
125
+ * Checks if a TypeScript configuration (tsconfig*.json) was downgraded to disable type safety.
126
+ */
127
+ function hasTsConfigCheats(content, existingContent) {
128
+ // Check for strict: false replacing strict: true or being newly introduced
129
+ if (/"strict"\s*:\s*false/i.test(content)) {
130
+ if (!existingContent || !/"strict"\s*:\s*false/i.test(existingContent)) {
131
+ return {
132
+ cheat: true,
133
+ reason: 'Attempted to disable TypeScript strict mode ("strict": false) in tsconfig.',
134
+ };
135
+ }
136
+ }
137
+ // Check for suppressImplicitAnyIndexErrors
138
+ if (/"suppressImplicitAnyIndexErrors"\s*:\s*true/i.test(content)) {
139
+ if (!existingContent || !/"suppressImplicitAnyIndexErrors"\s*:\s*true/i.test(existingContent)) {
140
+ return {
141
+ cheat: true,
142
+ reason: 'Attempted to enable "suppressImplicitAnyIndexErrors: true" in tsconfig.',
143
+ };
144
+ }
145
+ }
146
+ // Check for noCheck: true
147
+ if (/"noCheck"\s*:\s*true/i.test(content)) {
148
+ if (!existingContent || !/"noCheck"\s*:\s*true/i.test(existingContent)) {
149
+ return {
150
+ cheat: true,
151
+ reason: 'Attempted to set "noCheck: true" in tsconfig.',
152
+ };
153
+ }
154
+ }
155
+ // Check for noEmitOnError: false being added when previously true or not false
156
+ if (/"noEmitOnError"\s*:\s*false/i.test(content)) {
157
+ if (!existingContent || !/"noEmitOnError"\s*:\s*false/i.test(existingContent)) {
158
+ return {
159
+ cheat: true,
160
+ reason: 'Attempted to set "noEmitOnError: false" in tsconfig to emit outputs despite compilation errors.',
161
+ };
162
+ }
163
+ }
164
+ return { cheat: false };
165
+ }
166
+ /**
167
+ * Checks if package.json scripts were modified to swallow errors (e.g. appending "|| true", "|| exit 0")
168
+ * or stripping type check commands (e.g. removing "tsc" from build).
169
+ */
170
+ function hasPackageJsonCheats(content, existingContent) {
171
+ // Check for script swallowing failures: "|| true", "|| exit 0", "; exit 0" inside scripts
172
+ const swallowMatch = /"(?:build|typecheck|test|lint|check)"\s*:\s*"[^"]*(?:\|\|\s*true|\|\|\s*exit\s+0|;\s*exit\s+0)/i.test(content);
173
+ if (swallowMatch) {
174
+ if (!existingContent || !/"(?:build|typecheck|test|lint|check)"\s*:\s*"[^"]*(?:\|\|\s*true|\|\|\s*exit\s+0|;\s*exit\s+0)/i.test(existingContent)) {
175
+ return {
176
+ cheat: true,
177
+ reason: 'Attempted to append error-swallowing directives ("|| true" or "|| exit 0") to package.json scripts.',
178
+ };
179
+ }
180
+ }
181
+ // Check if existing package.json had a build script with tsc / typecheck, and the new one removed it
182
+ if (existingContent) {
183
+ try {
184
+ const oldPkg = JSON.parse(existingContent);
185
+ const newPkg = JSON.parse(content);
186
+ const oldBuild = oldPkg?.scripts?.build;
187
+ const newBuild = newPkg?.scripts?.build;
188
+ if (typeof oldBuild === 'string' && typeof newBuild === 'string') {
189
+ const hadTsc = /\btsc\b/i.test(oldBuild);
190
+ const hasTsc = /\btsc\b/i.test(newBuild);
191
+ if (hadTsc && !hasTsc) {
192
+ return {
193
+ cheat: true,
194
+ reason: 'Attempted to strip "tsc" type checking from the "build" script in package.json to bypass errors.',
195
+ };
196
+ }
197
+ }
198
+ }
199
+ catch {
200
+ // Ignore JSON parse errors in partial content
201
+ }
202
+ }
203
+ return { cheat: false };
204
+ }
205
+ /**
206
+ * Checks ESLint configuration files (eslint.config.*, .eslintrc*) for attempts to
207
+ * disable all rules or ignore all files.
208
+ */
209
+ function hasLinterConfigCheats(content, existingContent) {
210
+ // Check for blanket ignores in flat config: ignores: ['**/*', '**', 'src/**']
211
+ if (/\bignores\s*:\s*\[\s*['"`](?:\*\*|\*\*\/\*|\*|src\/\*\*)['"`]\s*\]/i.test(content)) {
212
+ if (!existingContent || !/\bignores\s*:\s*\[\s*['"`](?:\*\*|\*\*\/\*|\*|src\/\*\*)['"`]\s*\]/i.test(existingContent)) {
213
+ return {
214
+ cheat: true,
215
+ reason: 'Attempted to ignore all source files in ESLint configuration.',
216
+ };
217
+ }
218
+ }
219
+ // Check for ignorePatterns in legacy .eslintrc: ignorePatterns: ["**/*", "*"]
220
+ if (/"ignorePatterns"\s*:\s*\[\s*["'](?:\*\*|\*\*\/\*|\*|src\/\*\*)["']\s*\]/i.test(content)) {
221
+ if (!existingContent || !/"ignorePatterns"\s*:\s*\[\s*["'](?:\*\*|\*\*\/\*|\*|src\/\*\*)["']\s*\]/i.test(existingContent)) {
222
+ return {
223
+ cheat: true,
224
+ reason: 'Attempted to add blanket ignorePatterns in ESLint configuration.',
225
+ };
226
+ }
227
+ }
228
+ return { cheat: false };
229
+ }
230
+ /**
231
+ * Checks linter and build ignore files (.eslintignore, .prettierignore) for blanket wildcard exclusions.
232
+ */
233
+ function hasIgnoreFileCheats(filePath, content, existingContent) {
234
+ const base = path.basename(filePath).toLowerCase();
235
+ if (base === '.eslintignore' || base === '.prettierignore') {
236
+ const lines = content.split('\n').map((l) => l.trim()).filter((l) => l && !l.startsWith('#'));
237
+ const oldLines = existingContent ? existingContent.split('\n').map((l) => l.trim()).filter((l) => l && !l.startsWith('#')) : [];
238
+ for (const line of lines) {
239
+ if (['*', '**', '**/*', 'src', 'src/*', 'src/**'].includes(line)) {
240
+ if (!oldLines.includes(line)) {
241
+ return {
242
+ cheat: true,
243
+ reason: `Attempted to add wildcard exclusion "${line}" to ${base} to silence verification.`,
244
+ };
245
+ }
246
+ }
247
+ }
248
+ }
249
+ return { cheat: false };
250
+ }
251
+ /**
252
+ * Checks environment files (.env, .env.local, .env.development, .env.production) for bypass variables.
253
+ */
254
+ function hasEnvFileCheats(filePath, content, existingContent) {
255
+ const base = path.basename(filePath).toLowerCase();
256
+ if (base === '.env' || base.startsWith('.env.')) {
257
+ const bypassVars = [
258
+ 'NEXT_DISABLE_ESLINT',
259
+ 'TSC_COMPILE_ON_ERROR',
260
+ 'ESLINT_NO_DEV_ERRORS',
261
+ ];
262
+ for (const v of bypassVars) {
263
+ const regex = new RegExp(`^\\s*${v}\\s*=\\s*(?:1|true)`, 'im');
264
+ if (regex.test(content)) {
265
+ if (!existingContent || !regex.test(existingContent)) {
266
+ return {
267
+ cheat: true,
268
+ reason: `Attempted to set bypass environment variable "${v}" in ${base}.`,
269
+ };
270
+ }
271
+ }
272
+ }
273
+ }
274
+ return { cheat: false };
275
+ }
276
+ /**
277
+ * Checks build tools and test runners (Vite, Vitest, Webpack, Jest) for error suppressions.
278
+ */
279
+ function hasBundlerOrRunnerCheats(content, existingContent) {
280
+ // Check for passWithNoTests: true or bail: false in Jest/Vitest configs to mask missing tests
281
+ if (/\bpassWithNoTests\s*:\s*true/i.test(content)) {
282
+ if (!existingContent || !/\bpassWithNoTests\s*:\s*true/i.test(existingContent)) {
283
+ return {
284
+ cheat: true,
285
+ reason: 'Attempted to enable "passWithNoTests: true" in test runner configuration.',
286
+ };
287
+ }
288
+ }
289
+ return { cheat: false };
290
+ }
291
+ /**
292
+ * Checks for blanket error suppressions in source code:
293
+ * - Newly introduced //@ts-nocheck
294
+ * - Unscoped /* eslint-disable *\/ at the file header
295
+ * - Go //go:build ignore
296
+ * - Rust #![allow(warnings)]
297
+ * - Python file-wide # flake8: noqa
298
+ */
299
+ function hasSourceCodeCheats(content, existingContent) {
300
+ // 1. Check for @ts-nocheck
301
+ if (/\/\/\s*@ts-nocheck\b/i.test(content) || /\/\*\s*@ts-nocheck\s*\*\//i.test(content)) {
302
+ if (!existingContent || (!/\/\/\s*@ts-nocheck\b/i.test(existingContent) && !/\/\*\s*@ts-nocheck\s*\*\//i.test(existingContent))) {
303
+ return {
304
+ cheat: true,
305
+ reason: 'Attempted to add "@ts-nocheck" to disable TypeScript type checking for this file.',
306
+ };
307
+ }
308
+ }
309
+ // 2. Check for unscoped /* eslint-disable */ (blanket disable without specific rule names)
310
+ if (/\/\*\s*eslint-disable\s*\*\//i.test(content)) {
311
+ if (!existingContent || !/\/\*\s*eslint-disable\s*\*\//i.test(existingContent)) {
312
+ return {
313
+ cheat: true,
314
+ reason: 'Attempted to add blanket "/* eslint-disable */" to silence all linter rules for this file.',
315
+ };
316
+ }
317
+ }
318
+ // 3. Rust crate-level #![allow(warnings)]
319
+ if (/#!\s*\[\s*allow\s*\(\s*warnings\s*\)\s*\]/i.test(content)) {
320
+ if (!existingContent || !/#!\s*\[\s*allow\s*\(\s*warnings\s*\)\s*\]/i.test(existingContent)) {
321
+ return {
322
+ cheat: true,
323
+ reason: 'Attempted to add "#![allow(warnings)]" to silence all Rust compiler warnings.',
324
+ };
325
+ }
326
+ }
327
+ // 4. Go //go:build ignore on existing source files
328
+ if (/\/\/\s*go:build\s+ignore\b/i.test(content)) {
329
+ if (!existingContent || !/\/\/\s*go:build\s+ignore\b/i.test(existingContent)) {
330
+ return {
331
+ cheat: true,
332
+ reason: 'Attempted to add "//go:build ignore" to exclude this Go file from compilation.',
333
+ };
334
+ }
335
+ }
336
+ // 5. Python # flake8: noqa file-wide disable
337
+ if (/#\s*flake8:\s*noqa\b/i.test(content)) {
338
+ if (!existingContent || !/#\s*flake8:\s*noqa\b/i.test(existingContent)) {
339
+ return {
340
+ cheat: true,
341
+ reason: 'Attempted to add "# flake8: noqa" to disable lint checking for this Python file.',
342
+ };
343
+ }
344
+ }
345
+ return { cheat: false };
346
+ }
347
+ /**
348
+ * Checks if a test file had its test assertions neutered or skipped (e.g. newly introduced it.skip/test.skip,
349
+ * or commenting out assertions).
350
+ */
351
+ function hasTestCheats(filePath, content, existingContent) {
352
+ const isTestFile = /\.(?:test|spec)\.[a-z0-9]+$/i.test(filePath) || filePath.includes('/__tests__/');
353
+ if (!isTestFile)
354
+ return { cheat: false };
355
+ // 1. Count newly introduced .skip calls
356
+ const oldSkipCount = existingContent ? (existingContent.match(/\b(?:it|test|describe)\.skip\b/g) || []).length : 0;
357
+ const newSkipCount = (content.match(/\b(?:it|test|describe)\.skip\b/g) || []).length;
358
+ if (newSkipCount > oldSkipCount) {
359
+ return {
360
+ cheat: true,
361
+ reason: `Attempted to skip failing test cases (${newSkipCount - oldSkipCount} newly added .skip calls) instead of fixing the implementation.`,
362
+ };
363
+ }
364
+ // 2. Detect commenting out assertions (e.g. converting `expect(...)` or `assert(...)` into `// expect(...)`)
365
+ if (existingContent) {
366
+ const oldExpectCount = (existingContent.match(/(?<!\/\/.*|\/\*.*)\b(?:expect|assert)\s*\(/g) || []).length;
367
+ const newExpectCount = (content.match(/(?<!\/\/.*|\/\*.*)\b(?:expect|assert)\s*\(/g) || []).length;
368
+ // If more than 50% of assertions were commented out/deleted while test cases remained
369
+ const oldTestCount = (existingContent.match(/\b(?:it|test)\s*\(/g) || []).length;
370
+ const newTestCount = (content.match(/\b(?:it|test)\s*\(/g) || []).length;
371
+ if (oldTestCount > 0 && newTestCount >= oldTestCount && oldExpectCount >= 2 && newExpectCount < Math.floor(oldExpectCount / 2)) {
372
+ return {
373
+ cheat: true,
374
+ reason: `Attempted to neuter test assertions (${oldExpectCount} assertions reduced to ${newExpectCount}) instead of fixing broken code.`,
375
+ };
376
+ }
377
+ }
378
+ return { cheat: false };
379
+ }
380
+ /**
381
+ * Checks Python configuration files (mypy.ini, pyproject.toml, setup.cfg) for type checking disables.
382
+ */
383
+ function hasPythonCheats(content, existingContent) {
384
+ // Check for mypy ignore_errors = true
385
+ if (/\bignore_errors\s*=\s*(?:true|1)\b/i.test(content)) {
386
+ if (!existingContent || !/\bignore_errors\s*=\s*(?:true|1)\b/i.test(existingContent)) {
387
+ return {
388
+ cheat: true,
389
+ reason: 'Attempted to set "ignore_errors = True" in Python typing configuration.',
390
+ };
391
+ }
392
+ }
393
+ // Check for ruff ignore all rules: ignore = ["ALL"] or select = []
394
+ if (/\bignore\s*=\s*\[\s*["']ALL["']\s*\]/i.test(content)) {
395
+ if (!existingContent || !/\bignore\s*=\s*\[\s*["']ALL["']\s*\]/i.test(existingContent)) {
396
+ return {
397
+ cheat: true,
398
+ reason: 'Attempted to set `ignore = ["ALL"]` in Python Ruff linter configuration.',
399
+ };
400
+ }
401
+ }
402
+ return { cheat: false };
403
+ }
404
+ /**
405
+ * Checks compiled and native build configurations (CMakeLists.txt, Makefile, Gradle, Maven)
406
+ * for error suppression flags.
407
+ */
408
+ function hasCompiledSystemsCheats(filePath, content, existingContent) {
409
+ const base = path.basename(filePath).toLowerCase();
410
+ // CMake: adding -w to CMAKE_C_FLAGS or CMAKE_CXX_FLAGS
411
+ if (base === 'cmakelists.txt') {
412
+ if (/(?:CMAKE_C_FLAGS|CMAKE_CXX_FLAGS)\s+[^)]*-w\b/i.test(content)) {
413
+ if (!existingContent || !/(?:CMAKE_C_FLAGS|CMAKE_CXX_FLAGS)\s+[^)]*-w\b/i.test(existingContent)) {
414
+ return {
415
+ cheat: true,
416
+ reason: 'Attempted to add "-w" warning suppression flag in CMakeLists.txt.',
417
+ };
418
+ }
419
+ }
420
+ }
421
+ // Gradle: test.ignoreFailures = true or ignoreFailures = true
422
+ if (base === 'build.gradle' || base === 'build.gradle.kts') {
423
+ if (/\bignoreFailures\s*=\s*true/i.test(content)) {
424
+ if (!existingContent || !/\bignoreFailures\s*=\s*true/i.test(existingContent)) {
425
+ return {
426
+ cheat: true,
427
+ reason: 'Attempted to set "ignoreFailures = true" in Gradle build script.',
428
+ };
429
+ }
430
+ }
431
+ }
432
+ // Maven: <testFailureIgnore>true</testFailureIgnore>
433
+ if (base === 'pom.xml') {
434
+ if (/<testFailureIgnore>\s*true\s*<\/testFailureIgnore>/i.test(content)) {
435
+ if (!existingContent || !/<testFailureIgnore>\s*true\s*<\/testFailureIgnore>/i.test(existingContent)) {
436
+ return {
437
+ cheat: true,
438
+ reason: 'Attempted to set "<testFailureIgnore>true</testFailureIgnore>" in Maven pom.xml.',
439
+ };
440
+ }
441
+ }
442
+ }
443
+ return { cheat: false };
444
+ }
445
+ /**
446
+ * Evaluates whether a proposed file modification or write introduces anti-cheating violations
447
+ * by attempting to silence, ignore, or bypass build, compiler, type, or lint errors.
448
+ *
449
+ * This function is strictly diff-aware: if the existing file already had an error-ignoring flag,
450
+ * modifying unrelated sections of the file will not trigger a false positive.
451
+ *
452
+ * @param filePath - Path to the file being created or modified
453
+ * @param newContent - The proposed new content of the file
454
+ * @param existingContent - The previous content of the file (if it already existed on disk)
455
+ * @returns An error message string if an anti-cheating violation is detected, or null if clean.
456
+ */
457
+ export function detectAntiCheatingViolations(filePath, newContent, existingContent) {
458
+ const base = path.basename(filePath).toLowerCase();
459
+ // 1. Next.js configuration files
460
+ if (base.startsWith('next.config.')) {
461
+ const nextCheck = hasNextConfigCheats(newContent);
462
+ if (nextCheck.cheat) {
463
+ if (!existingContent || !hasNextConfigCheats(existingContent).cheat) {
464
+ return (`Anti-cheating violation: ${nextCheck.reason}\n` +
465
+ `You are strictly forbidden from modifying build configuration files to ignore or bypass errors.\n` +
466
+ `Actionable guidance: You must fix all build, compiler, type, and lint errors head-on in the application source code.`);
467
+ }
468
+ }
469
+ }
470
+ // 2. TypeScript configuration files (tsconfig.json, tsconfig.*.json, jsconfig.json)
471
+ if (base === 'tsconfig.json' || base === 'jsconfig.json' || (base.startsWith('tsconfig.') && base.endsWith('.json'))) {
472
+ const tsCheck = hasTsConfigCheats(newContent, existingContent);
473
+ if (tsCheck.cheat) {
474
+ return (`Anti-cheating violation: ${tsCheck.reason}\n` +
475
+ `You are strictly forbidden from downgrading TypeScript configuration to bypass errors.\n` +
476
+ `Actionable guidance: Fix the type errors directly in the TypeScript source files.`);
477
+ }
478
+ }
479
+ // 3. package.json scripts
480
+ if (base === 'package.json') {
481
+ const pkgCheck = hasPackageJsonCheats(newContent, existingContent);
482
+ if (pkgCheck.cheat) {
483
+ return (`Anti-cheating violation: ${pkgCheck.reason}\n` +
484
+ `You are strictly forbidden from altering build scripts to swallow or skip verification failures.\n` +
485
+ `Actionable guidance: Ensure build scripts run proper verification and resolve the underlying code errors.`);
486
+ }
487
+ }
488
+ // 4. ESLint configuration files (eslint.config.*, .eslintrc*)
489
+ if (base.startsWith('eslint.config.') || base === '.eslintrc' || base.startsWith('.eslintrc.')) {
490
+ const linterCheck = hasLinterConfigCheats(newContent, existingContent);
491
+ if (linterCheck.cheat) {
492
+ return (`Anti-cheating violation: ${linterCheck.reason}\n` +
493
+ `You are strictly forbidden from disabling linter rules in ESLint configuration.\n` +
494
+ `Actionable guidance: Fix the code to conform to linting standards.`);
495
+ }
496
+ }
497
+ // 5. Ignore files (.eslintignore, .prettierignore)
498
+ const ignoreCheck = hasIgnoreFileCheats(filePath, newContent, existingContent);
499
+ if (ignoreCheck.cheat) {
500
+ return (`Anti-cheating violation: ${ignoreCheck.reason}\n` +
501
+ `You are strictly forbidden from adding wildcard ignore patterns to bypass verification.\n` +
502
+ `Actionable guidance: Fix the source code rather than excluding it from checks.`);
503
+ }
504
+ // 6. Environment files (.env, .env.*)
505
+ const envCheck = hasEnvFileCheats(filePath, newContent, existingContent);
506
+ if (envCheck.cheat) {
507
+ return (`Anti-cheating violation: ${envCheck.reason}\n` +
508
+ `You are strictly forbidden from setting bypass environment variables.\n` +
509
+ `Actionable guidance: Fix the underlying errors in your code.`);
510
+ }
511
+ // 7. Bundlers & test runners (vite.config.*, vitest.config.*, jest.config.*)
512
+ if (base.startsWith('vite.config.') || base.startsWith('vitest.config.') || base.startsWith('jest.config.')) {
513
+ const bundlerCheck = hasBundlerOrRunnerCheats(newContent, existingContent);
514
+ if (bundlerCheck.cheat) {
515
+ return (`Anti-cheating violation: ${bundlerCheck.reason}\n` +
516
+ `You are strictly forbidden from configuring test runners or bundlers to bypass checks.\n` +
517
+ `Actionable guidance: Address the root cause in the application or test code.`);
518
+ }
519
+ }
520
+ // 8. Python typing configs (mypy.ini, pyproject.toml, setup.cfg)
521
+ if (base === 'mypy.ini' || base === 'pyproject.toml' || base === 'setup.cfg') {
522
+ const pyCheck = hasPythonCheats(newContent, existingContent);
523
+ if (pyCheck.cheat) {
524
+ return (`Anti-cheating violation: ${pyCheck.reason}\n` +
525
+ `You are strictly forbidden from disabling Python type checking or linting.\n` +
526
+ `Actionable guidance: Resolve typing errors in the Python source code.`);
527
+ }
528
+ }
529
+ // 9. Compiled build systems (CMakeLists.txt, Makefile, build.gradle, pom.xml)
530
+ const compiledCheck = hasCompiledSystemsCheats(filePath, newContent, existingContent);
531
+ if (compiledCheck.cheat) {
532
+ return (`Anti-cheating violation: ${compiledCheck.reason}\n` +
533
+ `You are strictly forbidden from suppressing compilation warnings or test failures.\n` +
534
+ `Actionable guidance: Resolve compiler warnings and test failures in your code.`);
535
+ }
536
+ // 10. Source code file blanket suppressions (@ts-nocheck, /* eslint-disable */, #![allow(warnings)], etc.)
537
+ const ext = path.extname(filePath).toLowerCase();
538
+ if (['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts', '.rs', '.go', '.py'].includes(ext)) {
539
+ const srcCheck = hasSourceCodeCheats(newContent, existingContent);
540
+ if (srcCheck.cheat) {
541
+ return (`Anti-cheating violation: ${srcCheck.reason}\n` +
542
+ `You are strictly forbidden from adding blanket error suppressions to silence errors.\n` +
543
+ `Actionable guidance: Fix the underlying type, syntax, and lint issues directly.`);
544
+ }
545
+ // 11. Test assertion neutering and skipping
546
+ const testCheck = hasTestCheats(filePath, newContent, existingContent);
547
+ if (testCheck.cheat) {
548
+ return (`Anti-cheating violation: ${testCheck.reason}\n` +
549
+ `You are strictly forbidden from skipping test cases or removing assertions to pass verification.\n` +
550
+ `Actionable guidance: Fix the application code so that the tests pass cleanly.`);
551
+ }
552
+ }
553
+ return null;
554
+ }
@@ -9,6 +9,10 @@ export declare const CONTEXT_BUDGET_CONFIG: {
9
9
  readonly DEFAULT_SCOPED_MAX_CHARS: 120000;
10
10
  /** Estimated characters per token heuristic */
11
11
  readonly ESTIMATED_CHARS_PER_TOKEN: 4;
12
+ /** Maximum fraction of budget allocated to Tier 1 full files in tiered context (70%) */
13
+ readonly TIER1_BUDGET_RATIO: 0.7;
14
+ /** Maximum fraction of budget allocated to Tier 2 AST skeletons in tiered context (30%) */
15
+ readonly TIER2_BUDGET_RATIO: 0.3;
12
16
  };
13
17
  /**
14
18
  * Estimates token count from a given text string.
@@ -25,6 +29,15 @@ export declare function estimateTokens(text: string): number;
25
29
  * @returns The sanitized string safe to place inside a CDATA section.
26
30
  */
27
31
  export declare function sanitizeForCDATA(content: string): string;
32
+ /**
33
+ * Formats a single file entry wrapped in XML workspace_file and CDATA tags.
34
+ *
35
+ * @param filePath Path or alias of the file.
36
+ * @param contentText File content or declarations outline.
37
+ * @param scoped Whether this content represents an AST-scoped outline.
38
+ * @returns Formatted workspace_file block.
39
+ */
40
+ export declare function formatWorkspaceFileBlock(filePath: string, contentText: string, scoped?: boolean): string;
28
41
  /**
29
42
  * Constructs a structured XML/Markdown-like project context string from ContextAgentResult.
30
43
  * This is used to inject project profiles, directories, summary, and relevant files'
@@ -50,6 +63,32 @@ export declare function buildContextInjection(context: ContextAgentResult, maxCh
50
63
  * @returns A formatted string containing project profile, structure, investigation summaries, and AST-scoped file outlines.
51
64
  */
52
65
  export declare function buildScopedContextInjection(context: ContextAgentResult, maxChars?: number): string;
66
+ /**
67
+ * Options for tiered context injection assembly.
68
+ */
69
+ export interface TieredContextOptions {
70
+ /** User prompt or task description for BM25 ranking */
71
+ prompt?: string;
72
+ /** Maximum total character budget */
73
+ maxChars?: number;
74
+ /** Dependency graph to derive structural centrality from */
75
+ graph?: any;
76
+ /** Pre-computed tier partition result */
77
+ tierPartition?: any;
78
+ }
79
+ /**
80
+ * Constructs a tiered, asymmetric XML/Markdown-like project context string.
81
+ *
82
+ * Automatically partitions files into:
83
+ * - Tier 1: Primary edit targets & high-relevance files with 100% full raw source code.
84
+ * - Tier 2: Peripheral hubs & dependent modules with compact AST declaration skeletons (scoped="outline").
85
+ * - Tier 3: Budget overflow files (omitted with token budget omission notice).
86
+ *
87
+ * @param context The collected context data from ContextAgent.
88
+ * @param options Tiered context options or maximum character budget.
89
+ * @returns A formatted string containing project profile, structure, investigation summaries, and tiered file blocks.
90
+ */
91
+ export declare function buildTieredContextInjection(context: ContextAgentResult, options?: TieredContextOptions | number): string;
53
92
  /**
54
93
  * Formats an array of resolved context mention blocks into a single structured
55
94
  * XML `<context_mentions>` block adhering to character/token budget constraints.