@goliapkg/sentori-cli 1.9.0 → 1.10.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.
@@ -0,0 +1,149 @@
1
+ import { ruleById, rules, ruleLanguage, fileLanguage } from './rules.js';
2
+ // Deliberately small TOML schema: scalar strings/integers, single-line string
3
+ // arrays, [rules], and [[allow]]. Reject unsupported TOML rather than guessing.
4
+ export function parseConfig(source) {
5
+ const result = { version: 1, include: ['**'], exclude: [], tests: [], excludePathRegex: [], rules: {}, allow: [] };
6
+ const seen = new Set();
7
+ let section = '';
8
+ let allow;
9
+ const allowances = [];
10
+ const stringValue = (raw) => {
11
+ if (raw.startsWith("'") && raw.endsWith("'") && !raw.slice(1, -1).includes("'"))
12
+ return raw.slice(1, -1);
13
+ const value = JSON.parse(raw);
14
+ if (typeof value !== 'string')
15
+ throw Error('expected a string');
16
+ return value;
17
+ };
18
+ for (const [index, rawLine] of source.split(/\r?\n/).entries()) {
19
+ try {
20
+ // Comments are removed only outside quoted strings.
21
+ let quote = '', escaped = false, line = '';
22
+ for (const char of rawLine) {
23
+ if (!quote && char === '#')
24
+ break;
25
+ line += char;
26
+ if (escaped) {
27
+ escaped = false;
28
+ continue;
29
+ }
30
+ if (quote === '"' && char === '\\') {
31
+ escaped = true;
32
+ continue;
33
+ }
34
+ if (quote === char)
35
+ quote = '';
36
+ else if (!quote && (char === '"' || char === "'"))
37
+ quote = char;
38
+ }
39
+ line = line.trim();
40
+ if (!line)
41
+ continue;
42
+ if (line === '[rules]') {
43
+ if (seen.has('[rules]'))
44
+ throw Error('duplicate [rules]');
45
+ seen.add('[rules]');
46
+ section = 'rules';
47
+ continue;
48
+ }
49
+ if (line === '[[allow]]') {
50
+ section = 'allow';
51
+ allow = {};
52
+ allowances.push(allow);
53
+ continue;
54
+ }
55
+ const match = /^([A-Za-z][A-Za-z0-9_-]*)\s*=\s*(.+)$/.exec(line);
56
+ if (!match)
57
+ throw Error('unsupported TOML; use single-line values, [rules], or [[allow]]');
58
+ const [, key, raw] = match;
59
+ const identity = section === 'allow' ? `allow.${allowances.length}.${key}` : `${section}.${key}`;
60
+ if (seen.has(identity))
61
+ throw Error(`duplicate key ${key}`);
62
+ seen.add(identity);
63
+ if (section === 'allow') {
64
+ if (!['rule', 'path', 'reason'].includes(key))
65
+ throw Error(`unknown allowance key ${key}`);
66
+ allow[key] = stringValue(raw);
67
+ }
68
+ else if (section === 'rules') {
69
+ const rule = ruleById.get(key);
70
+ if (!rule)
71
+ throw Error(`unknown rule ${key}`);
72
+ const level = stringValue(raw);
73
+ if (!['off', 'warn', 'error'].includes(level))
74
+ throw Error(`invalid severity ${level}`);
75
+ if (rule.allowlistOnly && level !== 'error')
76
+ throw Error(`${key} requires error severity; use an allowance`);
77
+ result.rules[key] = level;
78
+ }
79
+ else if (key === 'version') {
80
+ if (raw !== '1')
81
+ throw Error('unsupported config version');
82
+ }
83
+ else if (['include', 'exclude', 'tests', 'excludePathRegex'].includes(key)) {
84
+ // Arrays use TOML basic strings, also valid JSON. No multiline arrays.
85
+ const value = JSON.parse(raw);
86
+ if (!Array.isArray(value) || value.some(v => typeof v !== 'string' || !v))
87
+ throw Error(`${key} requires nonempty strings`);
88
+ result[key] = value;
89
+ }
90
+ else
91
+ throw Error(`unknown configuration key ${key}`);
92
+ }
93
+ catch (error) {
94
+ throw Error(`config line ${index + 1}: ${error.message}`);
95
+ }
96
+ }
97
+ if (!seen.has('.version'))
98
+ throw Error('config version = 1 is required');
99
+ if (!result.include.length)
100
+ throw Error('include must not be empty');
101
+ result.allow = allowances.map(a => {
102
+ if (typeof a.rule !== 'string' || !ruleById.has(a.rule))
103
+ throw Error('allowance needs a known rule');
104
+ if (typeof a.path !== 'string' || !a.path.trim() || a.path.startsWith('/') || a.path.split('/').includes('..'))
105
+ throw Error('allowance needs a repository-relative path pattern');
106
+ if (typeof a.reason !== 'string' || !a.reason.trim())
107
+ throw Error('allowance needs a nonempty reason');
108
+ return { rule: a.rule, path: a.path, reason: a.reason.trim() };
109
+ });
110
+ for (const pattern of [...result.include, ...result.exclude, ...result.tests, ...result.allow.map(a => a.path)])
111
+ glob(pattern);
112
+ for (const pattern of result.excludePathRegex)
113
+ new RegExp(pattern, 'i');
114
+ return result;
115
+ }
116
+ export function glob(pattern) {
117
+ if (pattern.startsWith('/') || pattern.includes('\\') || pattern.split('/').includes('..') || /[\[\]{}]/.test(pattern))
118
+ throw Error(`unsupported path glob: ${pattern}`);
119
+ let regex = '^';
120
+ for (let i = 0; i < pattern.length; i++) {
121
+ const c = pattern[i];
122
+ if (c === '*' && pattern[i + 1] === '*') {
123
+ i++;
124
+ if (pattern[i + 1] === '/') {
125
+ regex += '(?:.*/)?';
126
+ i++;
127
+ }
128
+ else
129
+ regex += '.*';
130
+ }
131
+ else if (c === '*')
132
+ regex += '[^/]*';
133
+ else if (c === '?')
134
+ regex += '[^/]';
135
+ else
136
+ regex += c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
137
+ }
138
+ return new RegExp(regex + '$');
139
+ }
140
+ export function selected(path, config) {
141
+ const any = (patterns) => patterns.some(p => glob(p).test(path));
142
+ return any(config.include) && !any(config.exclude)
143
+ && (!any(config.tests) || rules.some(rule => ruleLanguage(rule.id) === fileLanguage(path) && rule.tests && (config.rules[rule.id] ?? rule.level) !== 'off'))
144
+ && !config.excludePathRegex.some(p => new RegExp(p, 'i').test(path));
145
+ }
146
+ export function isTest(path, config) {
147
+ return config.tests.some(pattern => glob(pattern).test(path));
148
+ }
149
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lint/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Config } from './config.js';
2
+ export declare function discoverFiles(root: string, config: Config, paths?: string[], changed?: string): string[];
3
+ export declare function cmdLint(argv: string[]): Promise<number>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lint/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AA8BzC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,EAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B5G;AA4BD,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwE7D"}
@@ -0,0 +1,204 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { closeSync, existsSync, fsyncSync, linkSync, lstatSync, openSync, readFileSync, realpathSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { isAbsolute, relative, resolve, sep } from 'node:path';
4
+ import { createHash, randomUUID } from 'node:crypto';
5
+ import { parseArgs } from 'node:util';
6
+ import { parseConfig, selected } from './config.js';
7
+ import { initBaseline, lowerBaseline, makeReport, sarif, textReport, validateBaseline, validateResponse } from './report.js';
8
+ import { ruleById, ruleset } from './rules.js';
9
+ const help = `sentori lint [paths...] [options]
10
+ Swift and Kotlin syntax checks (preview 0.3.0).
11
+ --config FILE default: <git-root>/sentori-lint.toml
12
+ --swift-analyzer FILE executable (or SENTORI_LINT_SWIFT; default sentori-lint-swift)
13
+ --kotlin-analyzer FILE executable (or SENTORI_LINT_KOTLIN; default sentori-lint-kotlin)
14
+ --format text|json|sarif
15
+ --baseline FILE read a versioned rule/file-count baseline
16
+ --init-baseline initialize FILE, only if it does not exist
17
+ --update-baseline lower FILE after a successful full scan
18
+ --changed REF scan git diff REF plus untracked files; never update baselines
19
+ --fix run toolchain swift format, then reanalyze
20
+ --explain RULE print rule metadata
21
+ --version print lint protocol/ruleset version
22
+ Exit codes: 0 passed, 1 rule regressions, 2 configuration/analyzer/tool failure.
23
+ Configured tests participate only in function-length checks; generated exclusions apply to all rules.
24
+ `;
25
+ function command(executable, args, cwd, input) {
26
+ const result = spawnSync(executable, args, { cwd, input, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024, timeout: 120_000 });
27
+ if (result.error || result.status !== 0) {
28
+ throw Error(`${executable} failed: ${result.error?.message ?? result.stderr.trim() ?? result.signal ?? result.status}`);
29
+ }
30
+ return result.stdout;
31
+ }
32
+ function git(root, args) { return command('git', ['--literal-pathspecs', '-C', root, ...args], root); }
33
+ function records(value) { return value.split('\0').filter(Boolean); }
34
+ export function discoverFiles(root, config, paths = [], changed) {
35
+ const all = records(git(root, ['ls-files', '--cached', '--others', '--exclude-standard', '-z']));
36
+ const changedPaths = changed === undefined ? undefined : new Set([
37
+ ...records(git(root, ['diff', '--name-only', '-z', '--diff-filter=ACMR', changed, '--'])),
38
+ ...records(git(root, ['ls-files', '--others', '--exclude-standard', '-z'])),
39
+ ]);
40
+ const prefixes = paths.map(p => {
41
+ const path = relative(root, resolve(process.cwd(), p)).split(sep).join('/');
42
+ if (path === '..' || path.startsWith('../') || isAbsolute(path))
43
+ throw Error(`path outside repository: ${p}`);
44
+ if (!existsSync(resolve(root, path)))
45
+ throw Error(`path does not exist: ${p}`);
46
+ return path;
47
+ });
48
+ return [...new Set(all)].filter(path => {
49
+ if (!/\.(swift|kt)$/.test(path) || !selected(path, config))
50
+ return false;
51
+ if (changedPaths && !changedPaths.has(path))
52
+ return false;
53
+ if (prefixes.length && !prefixes.some(p => !p || path === p || path.startsWith(p + '/')))
54
+ return false;
55
+ const fullPath = resolve(root, path);
56
+ try {
57
+ lstatSync(fullPath);
58
+ }
59
+ catch (error) {
60
+ if (error.code === 'ENOENT')
61
+ return false; // tracked deletion
62
+ throw error;
63
+ }
64
+ const rel = relative(realpathSync(root), realpathSync(fullPath));
65
+ if (rel === '..' || rel.startsWith('..' + sep) || isAbsolute(rel) || lstatSync(fullPath).isSymbolicLink())
66
+ throw Error(`refusing source symlink/outside file: ${path}`);
67
+ if (!lstatSync(fullPath).isFile())
68
+ throw Error(`not a regular source file: ${path}`);
69
+ return true;
70
+ }).sort();
71
+ }
72
+ function analyze(root, executable, files, language) {
73
+ if (!files.length)
74
+ return [];
75
+ const output = command(executable, [], root, JSON.stringify({ version: 1, files }));
76
+ return validateResponse(JSON.parse(output), files, language);
77
+ }
78
+ function writeBaseline(path, baseline, original) {
79
+ const contents = JSON.stringify(baseline, null, 2) + '\n';
80
+ const lock = `${path}.lock`;
81
+ const lockFd = openSync(lock, 'wx');
82
+ const temporary = `${path}.${randomUUID()}.tmp`;
83
+ try {
84
+ writeFileSync(lockFd, JSON.stringify({ pid: process.pid }) + '\n');
85
+ const fd = openSync(temporary, 'wx');
86
+ try {
87
+ writeFileSync(fd, contents);
88
+ fsyncSync(fd);
89
+ }
90
+ finally {
91
+ closeSync(fd);
92
+ }
93
+ if (original === undefined) {
94
+ // Atomic create without replacement: interruption cannot leave half JSON.
95
+ linkSync(temporary, path);
96
+ }
97
+ else {
98
+ if (lstatSync(path).isSymbolicLink() || readFileSync(path, 'utf8') !== original)
99
+ throw Error('baseline changed during scan or is a symlink; retry');
100
+ renameSync(temporary, path);
101
+ }
102
+ }
103
+ finally {
104
+ if (existsSync(temporary))
105
+ unlinkSync(temporary);
106
+ closeSync(lockFd);
107
+ unlinkSync(lock);
108
+ }
109
+ }
110
+ export async function cmdLint(argv) {
111
+ try {
112
+ const { values, positionals } = parseArgs({ args: argv, allowPositionals: true, options: {
113
+ config: { type: 'string' }, 'swift-analyzer': { type: 'string' }, 'kotlin-analyzer': { type: 'string' }, format: { type: 'string', default: 'text' },
114
+ baseline: { type: 'string' }, 'init-baseline': { type: 'boolean' }, 'update-baseline': { type: 'boolean' },
115
+ changed: { type: 'string' }, fix: { type: 'boolean' }, explain: { type: 'string' },
116
+ version: { type: 'boolean' }, help: { type: 'boolean', short: 'h' },
117
+ } });
118
+ if (values.help) {
119
+ console.log(help);
120
+ return 0;
121
+ }
122
+ if (values.version) {
123
+ console.log(`sentori lint preview 0.3.0 (${ruleset})`);
124
+ return 0;
125
+ }
126
+ if (values.explain) {
127
+ const rule = ruleById.get(values.explain);
128
+ if (!rule)
129
+ throw Error(`unknown rule ${values.explain}`);
130
+ console.log(JSON.stringify(rule, null, 2));
131
+ return 0;
132
+ }
133
+ if (!['text', 'json', 'sarif'].includes(values.format))
134
+ throw Error('format must be text, json, or sarif');
135
+ const initialize = values['init-baseline'], update = values['update-baseline'];
136
+ if (initialize && update)
137
+ throw Error('choose init-baseline or update-baseline');
138
+ if ((initialize || update) && !values.baseline)
139
+ throw Error('--baseline FILE is required');
140
+ if ((initialize || update) && (positionals.length || values.changed !== undefined))
141
+ throw Error('baseline writes require a full scan without paths or --changed');
142
+ if (values.changed?.startsWith('-'))
143
+ throw Error('--changed requires a git revision, not an option');
144
+ const root = command('git', ['rev-parse', '--show-toplevel'], process.cwd()).replace(/\r?\n$/, '');
145
+ const configPath = values.config ? resolve(values.config) : resolve(root, 'sentori-lint.toml');
146
+ const configSource = readFileSync(configPath, 'utf8');
147
+ const config = parseConfig(configSource);
148
+ const baselinePath = values.baseline ? resolve(values.baseline) : undefined;
149
+ if (initialize && existsSync(baselinePath))
150
+ throw Error('baseline already exists; initialization never overwrites it');
151
+ const original = baselinePath && !initialize ? readFileSync(baselinePath, 'utf8') : undefined;
152
+ const baseline = original === undefined ? undefined : validateBaseline(JSON.parse(original), config);
153
+ const files = discoverFiles(root, config, positionals, values.changed);
154
+ if (!files.length && values.changed === undefined)
155
+ throw Error('no Swift or Kotlin source files selected; check scope/exclusions');
156
+ const swiftFiles = files.filter(path => path.endsWith('.swift'));
157
+ const kotlinFiles = files.filter(path => path.endsWith('.kt'));
158
+ if (values.fix && kotlinFiles.length)
159
+ throw Error('--fix supports Swift only; select Swift paths for formatting');
160
+ const analyzerEnv = { swift: process.env.SENTORI_LINT_SWIFT, kotlin: process.env.SENTORI_LINT_KOTLIN };
161
+ const runAnalyzers = () => ['swift', 'kotlin'].flatMap(language => {
162
+ const requested = values[`${language}-analyzer`] ?? analyzerEnv[language] ?? `sentori-lint-${language}`;
163
+ const executable = requested.includes('/') || requested.includes('\\') ? resolve(requested) : requested;
164
+ return analyze(root, executable, language === 'swift' ? swiftFiles : kotlinFiles, language);
165
+ });
166
+ const sourceDigest = () => files.map(path => createHash('sha256').update(readFileSync(resolve(root, path))).digest('hex')).join(':');
167
+ let snapshot = initialize || update ? sourceDigest() : undefined;
168
+ let findings = runAnalyzers();
169
+ if (values.fix) {
170
+ // Validate all sources before touching any. Formatting is the only fix;
171
+ // the analyzer never rewrites forced operations or concurrency semantics.
172
+ for (let i = 0; i < files.length; i += 50)
173
+ command('swift', ['format', 'format', '--in-place', '--', ...files.slice(i, i + 50)], root);
174
+ snapshot = initialize || update ? sourceDigest() : undefined;
175
+ findings = runAnalyzers();
176
+ }
177
+ let report = makeReport(files, findings, config, baseline, !positionals.length && values.changed === undefined);
178
+ const cannotWrite = (initialize && report.regressions.some(r => r.kind === 'hard-limit' || ruleById.get(r.rule).allowlistOnly))
179
+ || (update && report.regressions.length > 0);
180
+ if (cannotWrite)
181
+ console.error('baseline unchanged: resolve regressions/hard limits or add reviewed allowances first');
182
+ if ((initialize || update) && !cannotWrite) {
183
+ if (readFileSync(configPath, 'utf8') !== configSource || JSON.stringify(discoverFiles(root, config)) !== JSON.stringify(files) || sourceDigest() !== snapshot)
184
+ throw Error('source selection or contents changed during scan; baseline unchanged, retry');
185
+ }
186
+ if (initialize && !cannotWrite) {
187
+ const created = initBaseline(report, config);
188
+ writeBaseline(baselinePath, created);
189
+ report = makeReport(files, findings, config, created);
190
+ }
191
+ else if (update && !cannotWrite) {
192
+ const lowered = lowerBaseline(report, baseline);
193
+ writeBaseline(baselinePath, lowered, original);
194
+ report = makeReport(files, findings, config, lowered);
195
+ }
196
+ console.log(values.format === 'text' ? textReport(report) : JSON.stringify(values.format === 'sarif' ? sarif(report) : report, null, 2));
197
+ return report.regressions.length ? 1 : 0;
198
+ }
199
+ catch (error) {
200
+ console.error(`sentori lint: ${error.message}`);
201
+ return 2;
202
+ }
203
+ }
204
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lint/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { Config } from './config.js';
2
+ import type { Level } from './rules.js';
3
+ export type Finding = {
4
+ rule: string;
5
+ path: string;
6
+ line: number;
7
+ column: number;
8
+ measured?: number;
9
+ };
10
+ export type Result = Finding & {
11
+ level: Level;
12
+ message: string;
13
+ allowance?: string;
14
+ hardLimitExceeded?: boolean;
15
+ };
16
+ export type Baseline = {
17
+ version: 1;
18
+ ruleset: string;
19
+ scope: string;
20
+ counts: Record<string, Record<string, number>>;
21
+ };
22
+ export type Regression = {
23
+ path: string;
24
+ rule: string;
25
+ count: number;
26
+ allowed: number;
27
+ kind: 'count' | 'hard-limit';
28
+ };
29
+ export type Report = {
30
+ version: 1;
31
+ ruleset: string;
32
+ language: 'swift' | 'kotlin' | 'mixed';
33
+ fullScan: boolean;
34
+ files: string[];
35
+ results: Result[];
36
+ regressions: Regression[];
37
+ baselineCanDecrease: boolean;
38
+ };
39
+ export declare function scope(config: Config): string;
40
+ export declare function validateBaseline(value: unknown, config: Config): Baseline;
41
+ export declare function validateResponse(value: unknown, files: string[], language?: 'swift' | 'kotlin'): Finding[];
42
+ export declare function makeReport(files: string[], findings: Finding[], config: Config, baseline?: Baseline, fullScan?: boolean): Report;
43
+ export declare function countResults(results: Result[]): Record<string, Record<string, number>>;
44
+ export declare function initBaseline(report: Report, config: Config): Baseline;
45
+ export declare function lowerBaseline(report: Report, baseline: Baseline): Baseline;
46
+ export declare function sarif(report: Report): unknown;
47
+ export declare function textReport(report: Report): string;
48
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/lint/report.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvC,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACrG,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AACjH,MAAM,MAAM,QAAQ,GAAG;IAAE,OAAO,EAAE,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAA;AACrH,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,YAAY,CAAA;CAAE,CAAA;AACrH,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,EAAE,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;IAC1H,WAAW,EAAE,UAAU,EAAE,CAAC;IAAC,mBAAmB,EAAE,OAAO,CAAA;CACxD,CAAA;AACD,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI5C;AACD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAYzE;AACD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,GAAE,OAAO,GAAG,QAAkB,GAAG,OAAO,EAAE,CAenH;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,UAAO,GAAG,MAAM,CAsB7H;AACD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAQtF;AACD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAIrE;AACD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAY1E;AACD,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAwB7C;AACD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMjD"}
@@ -0,0 +1,136 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { glob, isTest } from './config.js';
3
+ import { ruleById, rules, ruleset, swiftRuleset, kotlinRuleset, ruleLanguage, fileLanguage } from './rules.js';
4
+ export function scope(config) {
5
+ // A different policy is a migration, not an improvement. This also prevents
6
+ // disabling/excluding rules or files from silently erasing baseline debt.
7
+ return createHash('sha256').update(JSON.stringify({ ...config, rules: Object.fromEntries(Object.entries(config.rules).sort()) })).digest('hex');
8
+ }
9
+ export function validateBaseline(value, config) {
10
+ const b = value;
11
+ if (!b || b.version !== 1 || b.ruleset !== ruleset || b.scope !== scope(config) || !b.counts || typeof b.counts !== 'object' || Array.isArray(b.counts)) {
12
+ throw Error('baseline version/ruleset/scope mismatch; policy changes require an explicit baseline migration');
13
+ }
14
+ for (const [path, counts] of Object.entries(b.counts)) {
15
+ if (!path || path.startsWith('/') || path.split('/').includes('..') || !/\.(swift|kt)$/.test(path) || !counts || typeof counts !== 'object' || Array.isArray(counts))
16
+ throw Error('invalid baseline path/counts');
17
+ for (const [id, count] of Object.entries(counts)) {
18
+ if (!ruleById.has(id) || ruleLanguage(id) !== fileLanguage(path) || ruleById.get(id).allowlistOnly || !Number.isSafeInteger(count) || count < 0)
19
+ throw Error(`invalid baseline count for ${path}: ${id}`);
20
+ }
21
+ }
22
+ return b;
23
+ }
24
+ export function validateResponse(value, files, language = 'swift') {
25
+ const response = value;
26
+ if (!response || response.version !== 1 || response.ruleset !== (language === 'swift' ? swiftRuleset : kotlinRuleset) || !Array.isArray(response.files)
27
+ || JSON.stringify([...response.files].sort()) !== JSON.stringify([...files].sort()) || !Array.isArray(response.diagnostics))
28
+ throw Error('incomplete or incompatible analyzer response');
29
+ const paths = new Set(files), seen = new Set();
30
+ for (const d of response.diagnostics) {
31
+ if (!d || !ruleById.has(d.rule) || ruleLanguage(d.rule) !== language || fileLanguage(d.path) !== language || !paths.has(d.path) || !Number.isSafeInteger(d.line) || d.line < 1 || !Number.isSafeInteger(d.column) || d.column < 1)
32
+ throw Error('invalid analyzer diagnostic');
33
+ const thresholds = ruleById.get(d.rule).thresholds;
34
+ if (thresholds && (!Number.isSafeInteger(d.measured) || d.measured <= thresholds.target))
35
+ throw Error('missing or invalid analyzer measurement');
36
+ if (!thresholds && d.measured !== undefined)
37
+ throw Error('unexpected analyzer measurement');
38
+ const key = JSON.stringify([d.rule, d.path, d.line, d.column]);
39
+ if (seen.has(key))
40
+ throw Error('duplicate analyzer diagnostic');
41
+ seen.add(key);
42
+ }
43
+ return response.diagnostics;
44
+ }
45
+ export function makeReport(files, findings, config, baseline, fullScan = true) {
46
+ const results = findings.filter(d => !isTest(d.path, config) || ruleById.get(d.rule).tests).map(d => {
47
+ const rule = ruleById.get(d.rule);
48
+ const allowance = config.allow.find(a => a.rule === d.rule && glob(a.path).test(d.path))?.reason;
49
+ const hardLimitExceeded = rule.thresholds?.hard !== undefined && d.measured > rule.thresholds.hard;
50
+ const configured = config.rules[d.rule] ?? rule.level;
51
+ const level = configured === 'off' ? 'off' : hardLimitExceeded ? 'error' : configured;
52
+ const measured = rule.thresholds ? ` Measured ${d.measured} ${rule.thresholds.unit}; target ${rule.thresholds.target}${rule.thresholds.hard !== undefined ? `; hard limit ${rule.thresholds.hard}` : ''}.` : '';
53
+ return { ...d, level, message: rule.message + measured, ...(hardLimitExceeded ? { hardLimitExceeded: true } : {}), ...(allowance ? { allowance } : {}) };
54
+ }).filter(d => d.level !== 'off').sort((a, b) => a.path.localeCompare(b.path) || a.line - b.line || a.column - b.column || a.rule.localeCompare(b.rule));
55
+ const counts = countResults(results);
56
+ const regressions = [];
57
+ for (const [path, byRule] of Object.entries(counts)) {
58
+ for (const [rule, count] of Object.entries(byRule)) {
59
+ const allowed = ruleById.get(rule).allowlistOnly ? 0 : baseline?.counts[path]?.[rule] ?? 0;
60
+ const hard = results.some(d => d.path === path && d.rule === rule && d.hardLimitExceeded && !d.allowance);
61
+ if (hard || count > allowed)
62
+ regressions.push({ path, rule, count, allowed, kind: hard ? 'hard-limit' : 'count' });
63
+ }
64
+ }
65
+ const scanned = new Set(files);
66
+ const baselineCanDecrease = !!baseline && Object.entries(baseline.counts).some(([path, byRule]) => (fullScan || scanned.has(path)) && Object.entries(byRule).some(([rule, count]) => (counts[path]?.[rule] ?? 0) < count));
67
+ return { version: 1, ruleset, language: files.every(p => p.endsWith('.swift')) ? 'swift' : files.every(p => p.endsWith('.kt')) ? 'kotlin' : 'mixed', fullScan, files, results, regressions, baselineCanDecrease };
68
+ }
69
+ export function countResults(results) {
70
+ const counts = Object.create(null);
71
+ for (const d of results) {
72
+ if (d.allowance || d.level !== 'error')
73
+ continue;
74
+ const byRule = counts[d.path] ??= Object.create(null);
75
+ byRule[d.rule] = (byRule[d.rule] ?? 0) + 1;
76
+ }
77
+ return counts;
78
+ }
79
+ export function initBaseline(report, config) {
80
+ if (!report.fullScan)
81
+ throw Error('cannot initialize baseline from a partial scan');
82
+ if (report.regressions.some(r => r.kind === 'hard-limit' || ruleById.get(r.rule).allowlistOnly))
83
+ throw Error('hard limits and concurrency escape hatches require an allowance; they cannot enter a baseline');
84
+ return { version: 1, ruleset, scope: scope(config), counts: countResults(report.results) };
85
+ }
86
+ export function lowerBaseline(report, baseline) {
87
+ if (!report.fullScan)
88
+ throw Error('cannot update baseline from a partial scan');
89
+ if (report.regressions.length)
90
+ throw Error('cannot update baseline while violations exceed it');
91
+ const current = countResults(report.results);
92
+ const counts = Object.create(null);
93
+ for (const [path, byRule] of Object.entries(baseline.counts)) {
94
+ for (const [id, previous] of Object.entries(byRule)) {
95
+ const count = Math.min(previous, current[path]?.[id] ?? 0);
96
+ if (count)
97
+ (counts[path] ??= Object.create(null))[id] = count;
98
+ }
99
+ }
100
+ return { ...baseline, counts };
101
+ }
102
+ export function sarif(report) {
103
+ return {
104
+ $schema: 'https://json.schemastore.org/sarif-2.1.0.json', version: '2.1.0',
105
+ runs: [{
106
+ tool: { driver: { name: 'sentori-lint', semanticVersion: '0.3.0', rules: rules.map(r => ({
107
+ id: r.id, name: r.name, shortDescription: { text: r.message }, fullDescription: { text: r.rationale },
108
+ helpUri: r.reference, defaultConfiguration: { level: r.level === 'warn' ? 'warning' : 'error' },
109
+ properties: { group: r.group, basis: r.basis, section: r.section, fixable: r.fixable, allowlistOnly: r.allowlistOnly, tests: !!r.tests, ...(r.thresholds ? { thresholds: r.thresholds } : {}) },
110
+ })) } },
111
+ columnKind: 'utf16CodeUnits',
112
+ results: report.results.map(d => ({
113
+ ruleId: d.rule, ruleIndex: rules.findIndex(r => r.id === d.rule),
114
+ level: d.level === 'warn' ? 'warning' : 'error', message: { text: d.message },
115
+ locations: [{ physicalLocation: {
116
+ artifactLocation: { uri: d.path.split('/').map(encodeURIComponent).join('/') },
117
+ region: { startLine: d.line, startColumn: d.column },
118
+ } }],
119
+ ...(d.measured !== undefined ? { properties: { measured: d.measured, hardLimitExceeded: !!d.hardLimitExceeded } } : {}),
120
+ ...(d.allowance ? { suppressions: [{ kind: 'external', justification: d.allowance, status: 'accepted' }] } : {}),
121
+ })),
122
+ properties: { language: report.language, fullScan: report.fullScan, filesScanned: report.files.length, regressions: report.regressions, baselineCanDecrease: report.baselineCanDecrease },
123
+ invocations: [{ executionSuccessful: true }],
124
+ }],
125
+ };
126
+ }
127
+ export function textReport(report) {
128
+ const lines = report.results.map(d => `${d.path}:${d.line}:${d.column}: ${d.level} ${d.rule} ${d.message}${d.allowance ? ` [allowed: ${d.allowance}]` : ''}`);
129
+ for (const r of report.regressions)
130
+ lines.push(r.kind === 'hard-limit' ? `hard limit exceeded: ${r.path} ${r.rule}` : `regression: ${r.path} ${r.rule}: ${r.count} > ${r.allowed}`);
131
+ lines.push(`${report.language}: ${report.files.length} files, ${report.results.length} findings, ${report.regressions.length} failing rule/file groups.`);
132
+ if (report.baselineCanDecrease)
133
+ lines.push('Baseline can decrease; run a full scan with --update-baseline.');
134
+ return lines.join('\n');
135
+ }
136
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/lint/report.ts"],"names":[],"mappings":"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"}