@promptci/core 0.0.1 → 0.1.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/LICENSE +201 -201
- package/README.md +29 -30
- package/dist/agent-practices.d.ts +2 -0
- package/dist/agent-practices.d.ts.map +1 -1
- package/dist/agent-practices.js +91 -51
- package/dist/agent-practices.js.map +1 -1
- package/dist/ai-config.d.ts +139 -0
- package/dist/ai-config.d.ts.map +1 -0
- package/dist/ai-config.js +523 -0
- package/dist/ai-config.js.map +1 -0
- package/dist/baseline.d.ts +17 -1
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +5 -1
- package/dist/baseline.js.map +1 -1
- package/dist/buried-critical.d.ts +17 -0
- package/dist/buried-critical.d.ts.map +1 -0
- package/dist/buried-critical.js +112 -0
- package/dist/buried-critical.js.map +1 -0
- package/dist/canonical-owner.d.ts.map +1 -1
- package/dist/canonical-owner.js +18 -8
- package/dist/canonical-owner.js.map +1 -1
- package/dist/command-validity.d.ts.map +1 -1
- package/dist/command-validity.js +53 -74
- package/dist/command-validity.js.map +1 -1
- package/dist/conflicts.d.ts.map +1 -1
- package/dist/conflicts.js +1 -42
- package/dist/conflicts.js.map +1 -1
- package/dist/context-analysis.d.ts.map +1 -1
- package/dist/context-analysis.js +13 -2
- package/dist/context-analysis.js.map +1 -1
- package/dist/context-bloat.d.ts +19 -0
- package/dist/context-bloat.d.ts.map +1 -1
- package/dist/context-bloat.js +82 -9
- package/dist/context-bloat.js.map +1 -1
- package/dist/context-optimizer.d.ts.map +1 -1
- package/dist/context-optimizer.js +15 -54
- package/dist/context-optimizer.js.map +1 -1
- package/dist/copilot-instructions-detector.d.ts +24 -0
- package/dist/copilot-instructions-detector.d.ts.map +1 -0
- package/dist/copilot-instructions-detector.js +145 -0
- package/dist/copilot-instructions-detector.js.map +1 -0
- package/dist/cursor-rules-detector.d.ts +17 -0
- package/dist/cursor-rules-detector.d.ts.map +1 -0
- package/dist/cursor-rules-detector.js +110 -0
- package/dist/cursor-rules-detector.js.map +1 -0
- package/dist/custom-rules.d.ts +52 -0
- package/dist/custom-rules.d.ts.map +1 -0
- package/dist/custom-rules.js +298 -0
- package/dist/custom-rules.js.map +1 -0
- package/dist/dead-references.js +11 -9
- package/dist/dead-references.js.map +1 -1
- package/dist/detectors.d.ts +1 -3
- package/dist/detectors.d.ts.map +1 -1
- package/dist/detectors.js +46 -53
- package/dist/detectors.js.map +1 -1
- package/dist/duplicates.d.ts.map +1 -1
- package/dist/duplicates.js +10 -5
- package/dist/duplicates.js.map +1 -1
- package/dist/evidence.d.ts +28 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +38 -0
- package/dist/evidence.js.map +1 -0
- package/dist/fix-engine.d.ts +11 -0
- package/dist/fix-engine.d.ts.map +1 -1
- package/dist/fix-engine.js +88 -71
- package/dist/fix-engine.js.map +1 -1
- package/dist/frameworks/python.d.ts.map +1 -1
- package/dist/frameworks/python.js +5 -2
- package/dist/frameworks/python.js.map +1 -1
- package/dist/health-score.d.ts.map +1 -1
- package/dist/health-score.js +1 -0
- package/dist/health-score.js.map +1 -1
- package/dist/hooks-settings-detector.d.ts +17 -0
- package/dist/hooks-settings-detector.d.ts.map +1 -0
- package/dist/hooks-settings-detector.js +228 -0
- package/dist/hooks-settings-detector.js.map +1 -0
- package/dist/index.d.ts +22 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -6
- package/dist/index.js.map +1 -1
- package/dist/manifest-consistency.d.ts +6 -0
- package/dist/manifest-consistency.d.ts.map +1 -1
- package/dist/manifest-consistency.js +26 -5
- package/dist/manifest-consistency.js.map +1 -1
- package/dist/markdown-fences.d.ts +112 -0
- package/dist/markdown-fences.d.ts.map +1 -0
- package/dist/markdown-fences.js +174 -0
- package/dist/markdown-fences.js.map +1 -0
- package/dist/mcp-config-detector.d.ts +20 -0
- package/dist/mcp-config-detector.d.ts.map +1 -0
- package/dist/mcp-config-detector.js +237 -0
- package/dist/mcp-config-detector.js.map +1 -0
- package/dist/missing-context.d.ts.map +1 -1
- package/dist/missing-context.js +2 -52
- package/dist/missing-context.js.map +1 -1
- package/dist/model-budgets.d.ts +69 -0
- package/dist/model-budgets.d.ts.map +1 -0
- package/dist/model-budgets.js +110 -0
- package/dist/model-budgets.js.map +1 -0
- package/dist/negative-instructions.d.ts +26 -0
- package/dist/negative-instructions.d.ts.map +1 -0
- package/dist/negative-instructions.js +174 -0
- package/dist/negative-instructions.js.map +1 -0
- package/dist/path-containment.d.ts +12 -0
- package/dist/path-containment.d.ts.map +1 -0
- package/dist/path-containment.js +53 -0
- package/dist/path-containment.js.map +1 -0
- package/dist/project-type.d.ts +12 -2
- package/dist/project-type.d.ts.map +1 -1
- package/dist/project-type.js +25 -12
- package/dist/project-type.js.map +1 -1
- package/dist/prompt-cache.d.ts.map +1 -1
- package/dist/prompt-cache.js +26 -19
- package/dist/prompt-cache.js.map +1 -1
- package/dist/promptci-gitignore.d.ts +34 -0
- package/dist/promptci-gitignore.d.ts.map +1 -0
- package/dist/promptci-gitignore.js +42 -0
- package/dist/promptci-gitignore.js.map +1 -0
- package/dist/repo-context.d.ts +27 -0
- package/dist/repo-context.d.ts.map +1 -1
- package/dist/repo-context.js +42 -11
- package/dist/repo-context.js.map +1 -1
- package/dist/report.d.ts +1 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +132 -61
- package/dist/report.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +7 -3
- package/dist/scan.js.map +1 -1
- package/dist/scanner.d.ts +13 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +49 -37
- package/dist/scanner.js.map +1 -1
- package/dist/security-pack.d.ts +20 -0
- package/dist/security-pack.d.ts.map +1 -1
- package/dist/security-pack.js +27 -10
- package/dist/security-pack.js.map +1 -1
- package/dist/skills-detector.d.ts +19 -0
- package/dist/skills-detector.d.ts.map +1 -0
- package/dist/skills-detector.js +203 -0
- package/dist/skills-detector.js.map +1 -0
- package/dist/stale-instructions.d.ts +4 -1
- package/dist/stale-instructions.d.ts.map +1 -1
- package/dist/stale-instructions.js +51 -54
- package/dist/stale-instructions.js.map +1 -1
- package/dist/subagents-detector.d.ts +19 -0
- package/dist/subagents-detector.d.ts.map +1 -0
- package/dist/subagents-detector.js +155 -0
- package/dist/subagents-detector.js.map +1 -0
- package/dist/suppression.d.ts.map +1 -1
- package/dist/suppression.js +11 -45
- package/dist/suppression.js.map +1 -1
- package/dist/types.d.ts +28 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +25 -1
- package/dist/types.js.map +1 -1
- package/dist/vague-guidance.d.ts +15 -2
- package/dist/vague-guidance.d.ts.map +1 -1
- package/dist/vague-guidance.js +42 -40
- package/dist/vague-guidance.js.map +1 -1
- package/dist/windsurf-detector.d.ts +22 -0
- package/dist/windsurf-detector.d.ts.map +1 -0
- package/dist/windsurf-detector.js +87 -0
- package/dist/windsurf-detector.js.map +1 -0
- package/dist/within-section-dedup.d.ts +16 -0
- package/dist/within-section-dedup.d.ts.map +1 -0
- package/dist/within-section-dedup.js +153 -0
- package/dist/within-section-dedup.js.map +1 -0
- package/package.json +11 -8
- package/dist/cheap-model-routing.d.ts +0 -4
- package/dist/cheap-model-routing.d.ts.map +0 -1
- package/dist/cheap-model-routing.js +0 -43
- package/dist/cheap-model-routing.js.map +0 -1
- package/dist/cli-output-filter.d.ts +0 -16
- package/dist/cli-output-filter.d.ts.map +0 -1
- package/dist/cli-output-filter.js +0 -88
- package/dist/cli-output-filter.js.map +0 -1
- package/dist/context-cost.d.ts +0 -4
- package/dist/context-cost.d.ts.map +0 -1
- package/dist/context-cost.js +0 -70
- package/dist/context-cost.js.map +0 -1
- package/dist/context-recommender.d.ts +0 -3
- package/dist/context-recommender.d.ts.map +0 -1
- package/dist/context-recommender.js +0 -329
- package/dist/context-recommender.js.map +0 -1
- package/dist/llm.d.ts +0 -6
- package/dist/llm.d.ts.map +0 -1
- package/dist/llm.js +0 -67
- package/dist/llm.js.map +0 -1
- package/dist/mcp-detector.d.ts +0 -4
- package/dist/mcp-detector.d.ts.map +0 -1
- package/dist/mcp-detector.js +0 -131
- package/dist/mcp-detector.js.map +0 -1
- package/dist/native-tool-preference.d.ts +0 -20
- package/dist/native-tool-preference.d.ts.map +0 -1
- package/dist/native-tool-preference.js +0 -94
- package/dist/native-tool-preference.js.map +0 -1
- package/dist/output-verbosity.d.ts +0 -3
- package/dist/output-verbosity.d.ts.map +0 -1
- package/dist/output-verbosity.js +0 -83
- package/dist/output-verbosity.js.map +0 -1
- package/dist/product-boundary.d.ts +0 -11
- package/dist/product-boundary.d.ts.map +0 -1
- package/dist/product-boundary.js +0 -301
- package/dist/product-boundary.js.map +0 -1
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared support for the AI-setup config detectors (issue #23).
|
|
3
|
+
*
|
|
4
|
+
* These detectors audit the non-markdown surfaces of a 2026 AI setup — skills,
|
|
5
|
+
* subagents, hooks/permissions, MCP servers, and Cursor rules — against
|
|
6
|
+
* filesystem reality, the same way `command-validity` verifies documented
|
|
7
|
+
* commands. Everything here is deterministic and offline: no network, no LLM,
|
|
8
|
+
* identical output for identical input.
|
|
9
|
+
*
|
|
10
|
+
* This module holds the pieces every one of those detectors needs: a minimal
|
|
11
|
+
* YAML-frontmatter parser, root-relative path helpers that refuse to escape the
|
|
12
|
+
* repo, a stable file lister, and issue path normalization.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import * as crypto from 'node:crypto';
|
|
17
|
+
import fg from 'fast-glob';
|
|
18
|
+
import micromatch from 'micromatch';
|
|
19
|
+
import { MAX_FILE_SIZE, BINARY_CHECK_BYTES, isBinary } from './scanner.js';
|
|
20
|
+
import { resolveWithinRoot } from './path-containment.js';
|
|
21
|
+
// ── Path helpers ──────────────────────────────────────────────────────────────
|
|
22
|
+
/** Convert a filesystem path to forward-slash form for stable, portable output. */
|
|
23
|
+
export function toPosix(p) {
|
|
24
|
+
return p.replace(/\\/g, '/');
|
|
25
|
+
}
|
|
26
|
+
// Re-exported so the many `resolveWithinRoot` importers under core keep their
|
|
27
|
+
// import path while the implementation lives in the shared path-containment
|
|
28
|
+
// module. Every filesystem read below routes through it so a hostile config
|
|
29
|
+
// value cannot point the detector at `/etc/passwd`.
|
|
30
|
+
export { resolveWithinRoot };
|
|
31
|
+
/** True when a repo-relative path exists and is a regular file. */
|
|
32
|
+
export function isFileWithinRoot(repoRoot, relativePath) {
|
|
33
|
+
const abs = resolveWithinRoot(repoRoot, relativePath);
|
|
34
|
+
if (!abs)
|
|
35
|
+
return false;
|
|
36
|
+
try {
|
|
37
|
+
return fs.statSync(abs).isFile();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Read a repo-relative text file, or `undefined` if it is absent/unreadable. */
|
|
44
|
+
export function readTextWithinRoot(repoRoot, relativePath) {
|
|
45
|
+
const abs = resolveWithinRoot(repoRoot, relativePath);
|
|
46
|
+
if (!abs)
|
|
47
|
+
return undefined;
|
|
48
|
+
try {
|
|
49
|
+
return fs.readFileSync(abs, 'utf8');
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Directory names excluded when discovering config files: dependency trees and
|
|
57
|
+
* vendored copies whose own `.claude/` must never pollute the scan. This is a
|
|
58
|
+
* *discovery* policy — do not reuse it to answer "does glob X match anything in
|
|
59
|
+
* the repo" (see detectCursorRules, which needs `dist/`/`build/` visible).
|
|
60
|
+
*/
|
|
61
|
+
const DISCOVERY_IGNORE = [
|
|
62
|
+
'**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**',
|
|
63
|
+
'**/worktrees/**', '**/.worktrees/**',
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* List files under `repoRoot` matching `patterns`, returned as repo-relative
|
|
67
|
+
* POSIX paths in sorted order. Dotfiles are included (these configs all live in
|
|
68
|
+
* dot-directories). Pass `ignore` to override the default discovery excludes.
|
|
69
|
+
*/
|
|
70
|
+
export function listFiles(repoRoot, patterns, ignore = DISCOVERY_IGNORE) {
|
|
71
|
+
let matches;
|
|
72
|
+
try {
|
|
73
|
+
matches = fg.sync(patterns, {
|
|
74
|
+
cwd: repoRoot,
|
|
75
|
+
dot: true,
|
|
76
|
+
onlyFiles: true,
|
|
77
|
+
followSymbolicLinks: false,
|
|
78
|
+
ignore,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
return matches.map(toPosix).sort();
|
|
85
|
+
}
|
|
86
|
+
// ── Config-file discovery ─────────────────────────────────────────────────────
|
|
87
|
+
/** Repo-relative globs for each config surface the ai_config detectors audit. */
|
|
88
|
+
const AI_CONFIG_GLOBS = {
|
|
89
|
+
skills: ['.claude/**/SKILL.md'],
|
|
90
|
+
agents: ['.claude/agents/**/*.md'],
|
|
91
|
+
settings: ['.claude/settings.json', '.claude/settings.local.json'],
|
|
92
|
+
mcp: ['.mcp.json'],
|
|
93
|
+
cursorRules: ['.cursor/rules/**/*.mdc'],
|
|
94
|
+
// GitHub Copilot per-file instructions. The legacy single-file
|
|
95
|
+
// `.github/copilot-instructions.md` has no `applyTo` support, so it is NOT
|
|
96
|
+
// discovered here — only the per-file format under `.github/instructions/`.
|
|
97
|
+
copilotInstructions: ['.github/instructions/**/*.md'],
|
|
98
|
+
};
|
|
99
|
+
/** An AiConfigFiles with every surface empty — for contexts built without discovery. */
|
|
100
|
+
export function emptyAiConfigFiles() {
|
|
101
|
+
return { skills: [], agents: [], settings: [], mcp: [], cursorRules: [], copilotInstructions: [] };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Same size/binary gate the markdown scanner applies before reading a file
|
|
105
|
+
* (scanner.ts): regular file, at most MAX_FILE_SIZE bytes, no NUL byte in the
|
|
106
|
+
* leading BINARY_CHECK_BYTES.
|
|
107
|
+
*/
|
|
108
|
+
function passesScanGuards(repoRoot, relativePath) {
|
|
109
|
+
const abs = resolveWithinRoot(repoRoot, relativePath);
|
|
110
|
+
if (!abs)
|
|
111
|
+
return false;
|
|
112
|
+
try {
|
|
113
|
+
const stat = fs.statSync(abs);
|
|
114
|
+
if (!stat.isFile() || stat.size > MAX_FILE_SIZE)
|
|
115
|
+
return false;
|
|
116
|
+
const fd = fs.openSync(abs, 'r');
|
|
117
|
+
try {
|
|
118
|
+
const head = Buffer.alloc(Math.min(stat.size, BINARY_CHECK_BYTES));
|
|
119
|
+
const read = fs.readSync(fd, head, 0, head.length, 0);
|
|
120
|
+
return !isBinary(head.subarray(0, read));
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
fs.closeSync(fd);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Discover the config files the ai_config detectors audit, honoring the same
|
|
132
|
+
* user-facing scan policy the markdown scanner applies: `exclude` patterns
|
|
133
|
+
* always remove files, an explicit `include` list bounds the scan scope (when
|
|
134
|
+
* unset, each surface's own globs are the scope — these configs are not in the
|
|
135
|
+
* scanner's DEFAULT_PATTERNS), and oversized or binary files are skipped.
|
|
136
|
+
*
|
|
137
|
+
* Called from buildRepoContext so detectors consume pre-discovered lists; a
|
|
138
|
+
* `--exclude` that silences a markdown finding for a file silences that file's
|
|
139
|
+
* ai_config findings too, instead of the detectors re-walking the repo with a
|
|
140
|
+
* policy of their own.
|
|
141
|
+
*/
|
|
142
|
+
export function discoverAiConfigFiles(repoRoot, policy = {}) {
|
|
143
|
+
const ignore = [...DISCOVERY_IGNORE, ...(policy.exclude ?? [])];
|
|
144
|
+
const include = policy.include && policy.include.length > 0 ? policy.include : undefined;
|
|
145
|
+
const discover = (patterns) => {
|
|
146
|
+
let files = listFiles(repoRoot, [...patterns], ignore);
|
|
147
|
+
if (include)
|
|
148
|
+
files = micromatch(files, include, { dot: true }).sort();
|
|
149
|
+
return files.filter((file) => passesScanGuards(repoRoot, file));
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
skills: discover(AI_CONFIG_GLOBS.skills),
|
|
153
|
+
agents: discover(AI_CONFIG_GLOBS.agents),
|
|
154
|
+
settings: discover(AI_CONFIG_GLOBS.settings),
|
|
155
|
+
mcp: discover(AI_CONFIG_GLOBS.mcp),
|
|
156
|
+
cursorRules: discover(AI_CONFIG_GLOBS.cursorRules),
|
|
157
|
+
copilotInstructions: discover(AI_CONFIG_GLOBS.copilotInstructions),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/** Stable short hash for building per-finding IDs. */
|
|
161
|
+
export function shortHash(input) {
|
|
162
|
+
return crypto.createHash('sha1').update(input).digest('hex').slice(0, 12);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Rewrite an issue's `filePaths`/`locations` from the detectors' repo-relative
|
|
166
|
+
* POSIX form to the absolute form the scanner stores in `InstructionFile.path`.
|
|
167
|
+
* Inline `promptci-ignore` suppressions match on exact path equality with the
|
|
168
|
+
* scanned file, so detector output must speak the same dialect or the
|
|
169
|
+
* `ai_config` category is unsuppressable. Display strings (titles, summaries,
|
|
170
|
+
* evidence) keep the friendly relative form; baseline fingerprints re-normalize
|
|
171
|
+
* absolute paths back to repo-relative, so they are unaffected.
|
|
172
|
+
*/
|
|
173
|
+
export function withScannerPaths(repoRoot, issues) {
|
|
174
|
+
const abs = (p) => path.resolve(repoRoot, p);
|
|
175
|
+
return issues.map((issue) => ({
|
|
176
|
+
...issue,
|
|
177
|
+
filePaths: issue.filePaths.map(abs),
|
|
178
|
+
locations: issue.locations.map((loc) => ({ ...loc, filePath: abs(loc.filePath) })),
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
/** Extensions treated as invokable local scripts in hook/MCP command strings. */
|
|
182
|
+
export const SCRIPT_EXT_RE = /\.(sh|bash|zsh|js|mjs|cjs|ts|py|rb|ps1)$/i;
|
|
183
|
+
/**
|
|
184
|
+
* 1-based line where `needle` first appears in `raw`, or 1 when not found.
|
|
185
|
+
* JSON sources store strings escaped, so a parsed command containing quotes or
|
|
186
|
+
* backslashes never appears verbatim — fall back to the JSON-escaped form
|
|
187
|
+
* before giving up on a real line number.
|
|
188
|
+
*/
|
|
189
|
+
export function lineOf(raw, needle) {
|
|
190
|
+
let idx = raw.indexOf(needle);
|
|
191
|
+
if (idx < 0)
|
|
192
|
+
idx = raw.indexOf(JSON.stringify(needle).slice(1, -1));
|
|
193
|
+
if (idx < 0)
|
|
194
|
+
return 1;
|
|
195
|
+
return raw.slice(0, idx).split(/\r?\n/).length;
|
|
196
|
+
}
|
|
197
|
+
function stripBom(s) {
|
|
198
|
+
return s.charCodeAt(0) === 0xfeff ? s.slice(1) : s;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* A closing fence must sit at column 0. An indented `---` is content — most
|
|
202
|
+
* commonly a markdown horizontal rule inside a `|` block-scalar description —
|
|
203
|
+
* and must not terminate the frontmatter.
|
|
204
|
+
*/
|
|
205
|
+
const FENCE_RE = /^(?:---|\.\.\.)[ \t]*$/;
|
|
206
|
+
/**
|
|
207
|
+
* Strip a YAML trailing comment (` #` onward) from a raw value, tracking quote
|
|
208
|
+
* state so a `#` inside a quoted string survives. A quote only *opens* at the
|
|
209
|
+
* start of the value or after whitespace/`[`/`{`/`(`/`,` — an apostrophe inside
|
|
210
|
+
* a word (o'brien) is content, not a quote.
|
|
211
|
+
*/
|
|
212
|
+
function stripTrailingComment(raw) {
|
|
213
|
+
let quote = '';
|
|
214
|
+
let prev = '';
|
|
215
|
+
for (let i = 0; i < raw.length; i++) {
|
|
216
|
+
const c = raw[i];
|
|
217
|
+
if (quote) {
|
|
218
|
+
if (c === quote)
|
|
219
|
+
quote = '';
|
|
220
|
+
}
|
|
221
|
+
else if ((c === '"' || c === "'") && (prev === '' || /[\s[{(,]/.test(prev))) {
|
|
222
|
+
quote = c;
|
|
223
|
+
}
|
|
224
|
+
else if (c === '#' && (prev === '' || /\s/.test(prev))) {
|
|
225
|
+
return raw.slice(0, i).trimEnd();
|
|
226
|
+
}
|
|
227
|
+
prev = c;
|
|
228
|
+
}
|
|
229
|
+
return raw;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Split on top-level `,` only — commas inside quotes or `[]`/`{}`/`()` are left
|
|
233
|
+
* alone. Without this, a glob with a brace-expansion pattern such as a
|
|
234
|
+
* `{ts,tsx}` suffix would be shredded at the inner comma, producing bogus
|
|
235
|
+
* dead-glob findings. A quote only opens at the start of an item, so an
|
|
236
|
+
* apostrophe inside a path does not swallow the following commas.
|
|
237
|
+
*/
|
|
238
|
+
function splitTopLevelCommas(inner) {
|
|
239
|
+
const parts = [];
|
|
240
|
+
let cur = '';
|
|
241
|
+
let depth = 0;
|
|
242
|
+
let quote = '';
|
|
243
|
+
for (const c of inner) {
|
|
244
|
+
if (quote) {
|
|
245
|
+
cur += c;
|
|
246
|
+
if (c === quote)
|
|
247
|
+
quote = '';
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if ((c === '"' || c === "'") && cur.trim() === '') {
|
|
251
|
+
quote = c;
|
|
252
|
+
cur += c;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (c === '[' || c === '{' || c === '(') {
|
|
256
|
+
depth++;
|
|
257
|
+
cur += c;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (c === ']' || c === '}' || c === ')') {
|
|
261
|
+
if (depth > 0)
|
|
262
|
+
depth--;
|
|
263
|
+
cur += c;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (c === ',' && depth === 0) {
|
|
267
|
+
parts.push(cur);
|
|
268
|
+
cur = '';
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
cur += c;
|
|
272
|
+
}
|
|
273
|
+
parts.push(cur);
|
|
274
|
+
return parts.map((s) => unquote(s.trim())).filter((s) => s !== '');
|
|
275
|
+
}
|
|
276
|
+
function unquote(s) {
|
|
277
|
+
if (s.length >= 2 && ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'")))) {
|
|
278
|
+
return s.slice(1, -1);
|
|
279
|
+
}
|
|
280
|
+
return s;
|
|
281
|
+
}
|
|
282
|
+
function parseScalar(raw) {
|
|
283
|
+
// Comment stripping happens BEFORE dispatch so `globs: ["*.ts"] # note` is
|
|
284
|
+
// still recognized as a sequence, not left behind as a raw bracketed string.
|
|
285
|
+
const value = stripTrailingComment(raw).trim();
|
|
286
|
+
if (value === '')
|
|
287
|
+
return null;
|
|
288
|
+
// Fully-quoted string: contents verbatim (a `#` inside was preserved above).
|
|
289
|
+
const unquoted = unquote(value);
|
|
290
|
+
if (unquoted !== value)
|
|
291
|
+
return unquoted;
|
|
292
|
+
// Inline flow sequence: [a, b, c]
|
|
293
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
294
|
+
const inner = value.slice(1, -1).trim();
|
|
295
|
+
if (inner === '')
|
|
296
|
+
return [];
|
|
297
|
+
return splitTopLevelCommas(inner);
|
|
298
|
+
}
|
|
299
|
+
if (value === 'true')
|
|
300
|
+
return true;
|
|
301
|
+
if (value === 'false')
|
|
302
|
+
return false;
|
|
303
|
+
if (value === 'null' || value === '~')
|
|
304
|
+
return null;
|
|
305
|
+
if (/^-?\d+(\.\d+)?$/.test(value))
|
|
306
|
+
return Number(value);
|
|
307
|
+
return value;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Parse a minimal YAML frontmatter block from the top of a document.
|
|
311
|
+
*
|
|
312
|
+
* Handles the subset these config files actually use: top-level `key: value`
|
|
313
|
+
* scalars, quoted strings, booleans/numbers, inline `[a, b]` sequences, block
|
|
314
|
+
* lists (` - item`), and `|`/`>` block scalars. Nested mappings are recorded
|
|
315
|
+
* as errors rather than silently dropped, since none of the audited surfaces
|
|
316
|
+
* use them and a nested block is far more likely to be a mistake.
|
|
317
|
+
*
|
|
318
|
+
* This is deliberately not a full YAML engine — it exists to answer "is the
|
|
319
|
+
* frontmatter structurally sane and what are its top-level keys", not to load
|
|
320
|
+
* arbitrary YAML.
|
|
321
|
+
*/
|
|
322
|
+
export function parseFrontmatter(content) {
|
|
323
|
+
const text = stripBom(content);
|
|
324
|
+
const lines = text.split(/\r?\n/);
|
|
325
|
+
const result = {
|
|
326
|
+
present: false,
|
|
327
|
+
closed: false,
|
|
328
|
+
data: {},
|
|
329
|
+
keyLines: {},
|
|
330
|
+
fenceEndLine: -1,
|
|
331
|
+
bodyStartLine: 1,
|
|
332
|
+
errors: [],
|
|
333
|
+
};
|
|
334
|
+
if (lines.length === 0 || lines[0].trim() !== '---') {
|
|
335
|
+
return result; // no frontmatter — whole file is body
|
|
336
|
+
}
|
|
337
|
+
result.present = true;
|
|
338
|
+
let lastListKey = null;
|
|
339
|
+
let blockScalarKey = null;
|
|
340
|
+
let blockScalarFold = false;
|
|
341
|
+
let blockScalarLines = [];
|
|
342
|
+
const flushBlockScalar = () => {
|
|
343
|
+
if (blockScalarKey === null)
|
|
344
|
+
return;
|
|
345
|
+
const joined = blockScalarFold ? blockScalarLines.join(' ') : blockScalarLines.join('\n');
|
|
346
|
+
result.data[blockScalarKey] = joined.trim();
|
|
347
|
+
blockScalarKey = null;
|
|
348
|
+
blockScalarLines = [];
|
|
349
|
+
};
|
|
350
|
+
let i = 1;
|
|
351
|
+
for (; i < lines.length; i++) {
|
|
352
|
+
const line = lines[i];
|
|
353
|
+
const trimmed = line.trim();
|
|
354
|
+
if (blockScalarKey !== null) {
|
|
355
|
+
// Block scalar continues while lines are indented or blank; the closing
|
|
356
|
+
// fence (column 0 only) or a non-indented line ends it.
|
|
357
|
+
if (FENCE_RE.test(line)) {
|
|
358
|
+
flushBlockScalar();
|
|
359
|
+
result.closed = true;
|
|
360
|
+
result.fenceEndLine = i + 1;
|
|
361
|
+
result.bodyStartLine = i + 2;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
if (trimmed === '' || /^\s/.test(line)) {
|
|
365
|
+
blockScalarLines.push(trimmed);
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
flushBlockScalar();
|
|
369
|
+
// fall through to normal handling of this line
|
|
370
|
+
}
|
|
371
|
+
if (FENCE_RE.test(line)) {
|
|
372
|
+
result.closed = true;
|
|
373
|
+
result.fenceEndLine = i + 1;
|
|
374
|
+
result.bodyStartLine = i + 2;
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
if (trimmed === '' || trimmed.startsWith('#'))
|
|
378
|
+
continue;
|
|
379
|
+
// Block list item belonging to the most recent empty-valued key.
|
|
380
|
+
const listMatch = /^(\s*)-\s+(.*)$/.exec(line);
|
|
381
|
+
if (listMatch && lastListKey) {
|
|
382
|
+
const arr = result.data[lastListKey];
|
|
383
|
+
const item = unquote(stripTrailingComment(listMatch[2]).trim());
|
|
384
|
+
if (item !== '') {
|
|
385
|
+
if (Array.isArray(arr))
|
|
386
|
+
arr.push(item);
|
|
387
|
+
else
|
|
388
|
+
result.data[lastListKey] = [item];
|
|
389
|
+
}
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const kvMatch = /^(\s*)([^:\s][^:]*):\s?(.*)$/.exec(line);
|
|
393
|
+
if (!kvMatch) {
|
|
394
|
+
result.errors.push(`Unparseable frontmatter line ${i + 1}: ${trimmed.slice(0, 60)}`);
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const indent = kvMatch[1].length;
|
|
398
|
+
const key = kvMatch[2].trim();
|
|
399
|
+
const rawValue = kvMatch[3];
|
|
400
|
+
if (indent > 0) {
|
|
401
|
+
// Nested mapping — outside the supported subset.
|
|
402
|
+
result.errors.push(`Nested frontmatter key "${key}" on line ${i + 1} is not supported`);
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (Object.prototype.hasOwnProperty.call(result.data, key)) {
|
|
406
|
+
result.errors.push(`Duplicate frontmatter key "${key}" (line ${i + 1})`);
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
result.keyLines[key] = i + 1; // first occurrence
|
|
410
|
+
}
|
|
411
|
+
const valueTrimmed = rawValue.trim();
|
|
412
|
+
if (valueTrimmed === '|' || valueTrimmed === '|-' || valueTrimmed === '|+' ||
|
|
413
|
+
valueTrimmed === '>' || valueTrimmed === '>-' || valueTrimmed === '>+') {
|
|
414
|
+
blockScalarKey = key;
|
|
415
|
+
blockScalarFold = valueTrimmed.startsWith('>');
|
|
416
|
+
blockScalarLines = [];
|
|
417
|
+
lastListKey = null;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (valueTrimmed === '') {
|
|
421
|
+
// Either an empty scalar or the header of a block list on following lines.
|
|
422
|
+
result.data[key] = null;
|
|
423
|
+
lastListKey = key;
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
result.data[key] = parseScalar(rawValue);
|
|
427
|
+
lastListKey = null;
|
|
428
|
+
}
|
|
429
|
+
if (blockScalarKey !== null)
|
|
430
|
+
flushBlockScalar();
|
|
431
|
+
if (!result.closed) {
|
|
432
|
+
// Unterminated frontmatter — the whole remainder was consumed as fm.
|
|
433
|
+
result.bodyStartLine = lines.length + 1;
|
|
434
|
+
}
|
|
435
|
+
return result;
|
|
436
|
+
}
|
|
437
|
+
/** Coerce a frontmatter value that may be a list or comma/newline string into a string[]. */
|
|
438
|
+
export function asStringList(value) {
|
|
439
|
+
if (value === null || value === undefined)
|
|
440
|
+
return [];
|
|
441
|
+
if (Array.isArray(value))
|
|
442
|
+
return value.map((v) => String(v).trim()).filter(Boolean);
|
|
443
|
+
if (typeof value === 'string') {
|
|
444
|
+
// Top-level commas only — `*.{ts,tsx}` is one glob, not two fragments.
|
|
445
|
+
return value.split('\n').flatMap((line) => splitTopLevelCommas(line));
|
|
446
|
+
}
|
|
447
|
+
return [String(value)];
|
|
448
|
+
}
|
|
449
|
+
// ── Shared finding shapes ─────────────────────────────────────────────────────
|
|
450
|
+
/** Fill in the defaults every ai_config finding shares. */
|
|
451
|
+
export function aiConfigIssue(issue) {
|
|
452
|
+
return {
|
|
453
|
+
severity: 'warning',
|
|
454
|
+
category: 'ai_config',
|
|
455
|
+
confidence: 0.8,
|
|
456
|
+
...issue,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* The three structural frontmatter findings every frontmatter-bearing surface
|
|
461
|
+
* (skills, subagents, Cursor rules) shares: block missing entirely, block never
|
|
462
|
+
* closed, and parse errors inside the block. When the block is missing the
|
|
463
|
+
* caller should skip its per-surface field checks, keyed off `fm.present` as
|
|
464
|
+
* before — this helper only builds the findings.
|
|
465
|
+
*/
|
|
466
|
+
export function frontmatterStructureIssues(filePath, content, fm, surface) {
|
|
467
|
+
const sid = (kind, key) => `ai-config-${surface.idPrefix}-${kind}-${shortHash(key)}`;
|
|
468
|
+
if (!fm.present) {
|
|
469
|
+
return [aiConfigIssue({
|
|
470
|
+
id: sid('no-frontmatter', filePath),
|
|
471
|
+
severity: surface.noFrontmatterSeverity ?? 'high',
|
|
472
|
+
title: surface.noFrontmatterTitle ?? `${surface.noun} is missing YAML frontmatter`,
|
|
473
|
+
summary: `${filePath} has no \`---\` frontmatter block. ${surface.why}`,
|
|
474
|
+
filePaths: [filePath],
|
|
475
|
+
locations: [{ filePath, startLine: 1, endLine: 1 }],
|
|
476
|
+
evidence: [`First line: ${content.split(/\r?\n/)[0]?.slice(0, 60) ?? '(empty)'}`],
|
|
477
|
+
recommendation: surface.recommendation,
|
|
478
|
+
confidence: surface.noFrontmatterConfidence ?? 0.85,
|
|
479
|
+
})];
|
|
480
|
+
}
|
|
481
|
+
const issues = [];
|
|
482
|
+
if (!fm.closed) {
|
|
483
|
+
issues.push(aiConfigIssue({
|
|
484
|
+
id: sid('unterminated', filePath),
|
|
485
|
+
severity: 'high',
|
|
486
|
+
title: `${surface.noun} frontmatter is not closed`,
|
|
487
|
+
summary: `${filePath} opens a \`---\` frontmatter block that is never closed.`,
|
|
488
|
+
filePaths: [filePath],
|
|
489
|
+
locations: [{ filePath, startLine: 1, endLine: 1 }],
|
|
490
|
+
evidence: ['Opening `---` on line 1 has no closing `---`.'],
|
|
491
|
+
recommendation: 'Close the frontmatter block with a `---` line.',
|
|
492
|
+
confidence: 0.9,
|
|
493
|
+
}));
|
|
494
|
+
}
|
|
495
|
+
for (const err of fm.errors) {
|
|
496
|
+
// BUG-007: surface a clear, user-facing finding that names the offending
|
|
497
|
+
// key and points at the offending line, rather than a generic "structural
|
|
498
|
+
// problem" anchored to the whole fence. The parser embeds the key (in
|
|
499
|
+
// quotes) and the line number in each error string; lift both out so the
|
|
500
|
+
// title and location are specific. Nested maps are the common trigger —
|
|
501
|
+
// e.g. `tools:` followed by an indented `read: true`.
|
|
502
|
+
const offendingKey = /"([^"]+)"/.exec(err)?.[1];
|
|
503
|
+
const errLine = Number(/\bline (\d+)\b/.exec(err)?.[1]);
|
|
504
|
+
const anchorLine = Number.isInteger(errLine) && errLine > 0
|
|
505
|
+
? errLine
|
|
506
|
+
: (fm.fenceEndLine > 0 ? fm.fenceEndLine : 1);
|
|
507
|
+
issues.push(aiConfigIssue({
|
|
508
|
+
id: sid('fm-error', `${filePath}|${err}`),
|
|
509
|
+
title: offendingKey
|
|
510
|
+
? `${surface.noun} frontmatter has an unsupported key "${offendingKey}"`
|
|
511
|
+
: `${surface.noun} frontmatter has a structural problem`,
|
|
512
|
+
summary: `${filePath}: ${err}.`,
|
|
513
|
+
filePaths: [filePath],
|
|
514
|
+
locations: [{ filePath, startLine: anchorLine, endLine: anchorLine }],
|
|
515
|
+
evidence: [err],
|
|
516
|
+
recommendation: 'Fix the frontmatter so it is valid YAML with flat, unique keys. ' +
|
|
517
|
+
'Nested maps are not supported — flatten the offending key or move it into the body.',
|
|
518
|
+
confidence: 0.7,
|
|
519
|
+
}));
|
|
520
|
+
}
|
|
521
|
+
return issues;
|
|
522
|
+
}
|
|
523
|
+
//# sourceMappingURL=ai-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-config.js","sourceRoot":"","sources":["../src/ai-config.ts"],"names":[],"mappings":"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"}
|
package/dist/baseline.d.ts
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import type { PromptCiIssue, Baseline } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The fields identity is computed from. Structural rather than
|
|
4
|
+
* `PromptCiIssue`, so an issue rehydrated from a report's JSON — where
|
|
5
|
+
* `category` is a plain string — fingerprints identically to the live one.
|
|
6
|
+
*/
|
|
7
|
+
export type FingerprintableIssue = {
|
|
8
|
+
category: string;
|
|
9
|
+
title: string;
|
|
10
|
+
filePaths: string[];
|
|
11
|
+
evidence: string[];
|
|
12
|
+
};
|
|
2
13
|
/**
|
|
3
14
|
* Computes a stable fingerprint for an issue.
|
|
4
15
|
*
|
|
16
|
+
* This is the ONE answer to "are these two findings the same issue?" — the
|
|
17
|
+
* report's trend section used to carry a second, incompatible one that keyed
|
|
18
|
+
* on severity, so a severity bump read as "resolved + new" in the trend while
|
|
19
|
+
* the baseline correctly reported one issue that had worsened.
|
|
20
|
+
*
|
|
5
21
|
* Excluded from fingerprint:
|
|
6
22
|
* - `id` (may change between versions)
|
|
7
23
|
* - `severity` (tracked separately for worsening detection)
|
|
@@ -11,7 +27,7 @@ import type { PromptCiIssue, Baseline } from './types.js';
|
|
|
11
27
|
* Included:
|
|
12
28
|
* - `category`, `title`, sorted `filePaths`, sorted `evidence`
|
|
13
29
|
*/
|
|
14
|
-
export declare function computeFingerprint(issue:
|
|
30
|
+
export declare function computeFingerprint(issue: FingerprintableIssue, repoRoot?: string): string;
|
|
15
31
|
/**
|
|
16
32
|
* Creates a baseline from a list of active issues.
|
|
17
33
|
* Produces deterministic JSON when sorted by fingerprint.
|
package/dist/baseline.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../src/baseline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,aAAa,EAAiB,QAAQ,EAAE,MAAM,YAAY,CAAC;AA4ExF
|
|
1
|
+
{"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../src/baseline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,aAAa,EAAiB,QAAQ,EAAE,MAAM,YAAY,CAAC;AA4ExF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAgBzF;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAWnF;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAiB7E;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EAAE,EACvB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAAC,eAAe,EAAE,aAAa,EAAE,CAAA;CAAE,CA2BlE"}
|
package/dist/baseline.js
CHANGED
|
@@ -63,10 +63,14 @@ function normalizeEvidenceForRoot(evidence, repoRoot) {
|
|
|
63
63
|
];
|
|
64
64
|
return rootCandidates.reduce((current, normalizedRoot) => current.replaceAll(normalizedRoot, '<repo>'), normalizedEvidence);
|
|
65
65
|
}
|
|
66
|
-
// ── Fingerprinting ────────────────────────────────────────────────────────────
|
|
67
66
|
/**
|
|
68
67
|
* Computes a stable fingerprint for an issue.
|
|
69
68
|
*
|
|
69
|
+
* This is the ONE answer to "are these two findings the same issue?" — the
|
|
70
|
+
* report's trend section used to carry a second, incompatible one that keyed
|
|
71
|
+
* on severity, so a severity bump read as "resolved + new" in the trend while
|
|
72
|
+
* the baseline correctly reported one issue that had worsened.
|
|
73
|
+
*
|
|
70
74
|
* Excluded from fingerprint:
|
|
71
75
|
* - `id` (may change between versions)
|
|
72
76
|
* - `severity` (tracked separately for worsening detection)
|
package/dist/baseline.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../src/baseline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC;;;;;;;;;;;;;GAaG;AAEH,iFAAiF;AAEjF,MAAM,cAAc,GAAkC;IACpD,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,cAAc,CAAC,CAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,QAAiB;IAC/D,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE/B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzE,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IAED,MAAM,cAAc,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG;QACrB,gBAAgB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;KAC7D,CAAC;IACF,KAAK,MAAM,cAAc,IAAI,cAAc,EAAE,CAAC;QAC5C,IAAI,cAAc,KAAK,cAAc;YAAE,OAAO,GAAG,CAAC;QAClD,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,GAAG,CAAC,EAAE,CAAC;YACpD,OAAO,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,wBAAwB,CAAC,QAAgB,EAAE,QAAiB;IACnE,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE/B,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,cAAc,GAAG;QACrB,gBAAgB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;KAC7D,CAAC;IACF,OAAO,cAAc,CAAC,MAAM,CAC1B,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,QAAQ,CAAC,EACzE,kBAAkB,CACnB,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../src/baseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buried critical-instruction detector (FEAT-011).
|
|
3
|
+
*
|
|
4
|
+
* Models weight earlier context more heavily than later context. A long file
|
|
5
|
+
* that puts its highest-stakes instructions ("never", "critical", "MUST NOT",
|
|
6
|
+
* "security", "dangerous") at the very bottom risks having them under-weighted.
|
|
7
|
+
*
|
|
8
|
+
* Heuristic: for files longer than 100 lines, find the lines carrying a
|
|
9
|
+
* high-severity keyword. If more than 60% of those lines sit in the bottom half
|
|
10
|
+
* of the file, emit an info finding suggesting the critical guidance be
|
|
11
|
+
* promoted toward the top.
|
|
12
|
+
*
|
|
13
|
+
* Deterministic and rule-based: no clock, network, or randomness.
|
|
14
|
+
*/
|
|
15
|
+
import type { InstructionFile, PromptCiIssue } from './types.js';
|
|
16
|
+
export declare function detectBuriedCriticalInstructions(files: InstructionFile[]): PromptCiIssue[];
|
|
17
|
+
//# sourceMappingURL=buried-critical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buried-critical.d.ts","sourceRoot":"","sources":["../src/buried-critical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAsCjE,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CAqE1F"}
|