pr-checkmate 3.2.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +3 -9
- package/LICENSE +8 -3
- package/README.md +54 -5
- package/dist/cjs/agent/hook.d.ts +37 -0
- package/dist/cjs/agent/hook.js +175 -0
- package/dist/cjs/agent/registration.d.ts +10 -0
- package/dist/cjs/agent/registration.js +28 -0
- package/dist/cjs/agent/setup.d.ts +20 -0
- package/dist/cjs/agent/setup.js +229 -0
- package/dist/cjs/cli.js +101 -0
- package/dist/cjs/config/constants.d.ts +2 -0
- package/dist/cjs/config/constants.js +5 -1
- package/dist/cjs/config/pr-checkmate.template.json +11 -1
- package/dist/cjs/core/checks/dependencies/grype-scan.js +18 -0
- package/dist/cjs/core/checks/findings.js +33 -7
- package/dist/cjs/core/checks/git/large-files.d.ts +1 -0
- package/dist/cjs/core/checks/git/large-files.js +3 -3
- package/dist/cjs/core/checks/languages/lint.js +12 -0
- package/dist/cjs/core/checks/languages/ruff-shared.js +6 -1
- package/dist/cjs/core/checks/pr/commitlint.js +4 -2
- package/dist/cjs/core/checks/pr/pr-size-check.d.ts +2 -0
- package/dist/cjs/core/checks/pr/pr-size-check.js +5 -5
- package/dist/cjs/core/checks/quality/package-size.d.ts +23 -1
- package/dist/cjs/core/checks/quality/package-size.js +20 -4
- package/dist/cjs/core/checks/quality/spellcheck.js +8 -5
- package/dist/cjs/core/checks/security/agent-instructions.d.ts +4 -0
- package/dist/cjs/core/checks/security/agent-instructions.js +149 -0
- package/dist/cjs/core/checks/security/diff-security.d.ts +7 -0
- package/dist/cjs/core/checks/security/diff-security.js +21 -1
- package/dist/cjs/core/checks/security/security.d.ts +0 -13
- package/dist/cjs/core/checks/security/security.js +27 -0
- package/dist/cjs/core/checks/security/workflow-security.js +33 -0
- package/dist/cjs/core/commands.d.ts +6 -0
- package/dist/cjs/core/commands.js +11 -1
- package/dist/cjs/core/finding-store.d.ts +16 -0
- package/dist/cjs/core/finding-store.js +73 -0
- package/dist/cjs/core/install/doctor.js +12 -0
- package/dist/cjs/core/install/grype-db.d.ts +25 -0
- package/dist/cjs/core/install/grype-db.js +45 -0
- package/dist/cjs/core/install/profiles.d.ts +1 -1
- package/dist/cjs/core/install/profiles.js +1 -1
- package/dist/cjs/core/install/reuse.js +6 -3
- package/dist/cjs/core/registry.js +2 -0
- package/dist/cjs/core/reporters.js +9 -0
- package/dist/cjs/core/run-checks.js +15 -5
- package/dist/cjs/core/sarif.d.ts +13 -0
- package/dist/cjs/core/sarif.js +60 -0
- package/dist/cjs/core/types.d.ts +7 -2
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/init.d.ts +0 -8
- package/dist/cjs/init.js +12 -2
- package/dist/cjs/interfaces/index.d.ts +12 -0
- package/dist/cjs/mcp/config-tools.d.ts +30 -0
- package/dist/cjs/mcp/config-tools.js +320 -0
- package/dist/cjs/mcp/dependency.d.ts +33 -0
- package/dist/cjs/mcp/dependency.js +407 -0
- package/dist/cjs/mcp/protocol.d.ts +97 -0
- package/dist/cjs/mcp/protocol.js +181 -0
- package/dist/cjs/mcp/review.d.ts +63 -0
- package/dist/cjs/mcp/review.js +150 -0
- package/dist/cjs/mcp/serve.d.ts +8 -0
- package/dist/cjs/mcp/serve.js +49 -0
- package/dist/cjs/mcp/settings.d.ts +13 -0
- package/dist/cjs/mcp/settings.js +50 -0
- package/dist/cjs/mcp/tools.d.ts +23 -0
- package/dist/cjs/mcp/tools.js +633 -0
- package/dist/cjs/utils/execa.d.ts +7 -0
- package/dist/cjs/utils/execa.js +41 -1
- package/dist/cjs/utils/own-deps.js +8 -1
- package/dist/cjs/utils/resolve-bin.d.ts +2 -0
- package/dist/cjs/utils/resolve-bin.js +5 -0
- package/dist/cjs/utils/result-collector.d.ts +17 -1
- package/dist/cjs/utils/result-collector.js +7 -2
- package/dist/esm/agent/hook.d.ts +37 -0
- package/dist/esm/agent/hook.js +167 -0
- package/dist/esm/agent/registration.d.ts +10 -0
- package/dist/esm/agent/registration.js +21 -0
- package/dist/esm/agent/setup.d.ts +20 -0
- package/dist/esm/agent/setup.js +220 -0
- package/dist/esm/cli.js +100 -2
- package/dist/esm/config/constants.d.ts +2 -0
- package/dist/esm/config/constants.js +4 -0
- package/dist/esm/config/pr-checkmate.template.json +11 -1
- package/dist/esm/core/checks/dependencies/dependency-check.js +2 -2
- package/dist/esm/core/checks/dependencies/grype-scan.js +18 -0
- package/dist/esm/core/checks/dependencies/license-check.js +2 -2
- package/dist/esm/core/checks/dependencies/npm-audit.js +2 -2
- package/dist/esm/core/checks/findings.js +33 -7
- package/dist/esm/core/checks/git/diff-smell.js +1 -1
- package/dist/esm/core/checks/git/large-files.d.ts +1 -0
- package/dist/esm/core/checks/git/large-files.js +1 -1
- package/dist/esm/core/checks/languages/cpp-format.js +1 -1
- package/dist/esm/core/checks/languages/lint.js +12 -3
- package/dist/esm/core/checks/languages/prettier.js +3 -3
- package/dist/esm/core/checks/languages/python-format.js +2 -2
- package/dist/esm/core/checks/languages/python-lint.js +2 -2
- package/dist/esm/core/checks/languages/ruff-shared.js +6 -1
- package/dist/esm/core/checks/languages/typecheck.js +1 -1
- package/dist/esm/core/checks/pr/commitlint.js +4 -2
- package/dist/esm/core/checks/pr/pr-body.js +1 -1
- package/dist/esm/core/checks/pr/pr-size-check.d.ts +2 -0
- package/dist/esm/core/checks/pr/pr-size-check.js +3 -3
- package/dist/esm/core/checks/pr/pr-title-lint.js +1 -1
- package/dist/esm/core/checks/quality/dead-code.js +1 -1
- package/dist/esm/core/checks/quality/duplicate-check.js +1 -1
- package/dist/esm/core/checks/quality/markdown-lint.js +1 -1
- package/dist/esm/core/checks/quality/package-size.d.ts +23 -1
- package/dist/esm/core/checks/quality/package-size.js +19 -4
- package/dist/esm/core/checks/quality/spellcheck.js +11 -8
- package/dist/esm/core/checks/security/agent-instructions.d.ts +4 -0
- package/dist/esm/core/checks/security/agent-instructions.js +146 -0
- package/dist/esm/core/checks/security/diff-security.d.ts +7 -0
- package/dist/esm/core/checks/security/diff-security.js +21 -1
- package/dist/esm/core/checks/security/security.d.ts +0 -13
- package/dist/esm/core/checks/security/security.js +28 -1
- package/dist/esm/core/checks/security/workflow-security.js +33 -0
- package/dist/esm/core/commands.d.ts +6 -0
- package/dist/esm/core/commands.js +10 -0
- package/dist/esm/core/finding-store.d.ts +16 -0
- package/dist/esm/core/finding-store.js +67 -0
- package/dist/esm/core/install/doctor.js +12 -0
- package/dist/esm/core/install/grype-db.d.ts +25 -0
- package/dist/esm/core/install/grype-db.js +41 -0
- package/dist/esm/core/install/prepare.js +1 -1
- package/dist/esm/core/install/profiles.d.ts +1 -1
- package/dist/esm/core/install/profiles.js +1 -1
- package/dist/esm/core/install/reuse.js +6 -3
- package/dist/esm/core/registry.js +2 -0
- package/dist/esm/core/reporters.js +9 -0
- package/dist/esm/core/run-checks.js +17 -7
- package/dist/esm/core/sarif.d.ts +13 -0
- package/dist/esm/core/sarif.js +57 -0
- package/dist/esm/core/types.d.ts +7 -2
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/init.d.ts +0 -8
- package/dist/esm/init.js +15 -4
- package/dist/esm/interfaces/index.d.ts +12 -0
- package/dist/esm/mcp/config-tools.d.ts +30 -0
- package/dist/esm/mcp/config-tools.js +310 -0
- package/dist/esm/mcp/dependency.d.ts +33 -0
- package/dist/esm/mcp/dependency.js +402 -0
- package/dist/esm/mcp/protocol.d.ts +97 -0
- package/dist/esm/mcp/protocol.js +175 -0
- package/dist/esm/mcp/review.d.ts +63 -0
- package/dist/esm/mcp/review.js +139 -0
- package/dist/esm/mcp/serve.d.ts +8 -0
- package/dist/esm/mcp/serve.js +43 -0
- package/dist/esm/mcp/settings.d.ts +13 -0
- package/dist/esm/mcp/settings.js +43 -0
- package/dist/esm/mcp/tools.d.ts +23 -0
- package/dist/esm/mcp/tools.js +626 -0
- package/dist/esm/utils/execa.d.ts +7 -0
- package/dist/esm/utils/execa.js +40 -1
- package/dist/esm/utils/own-deps.js +8 -1
- package/dist/esm/utils/resolve-bin.d.ts +2 -0
- package/dist/esm/utils/resolve-bin.js +4 -0
- package/dist/esm/utils/result-collector.d.ts +17 -1
- package/dist/esm/utils/result-collector.js +7 -2
- package/eslint-default-rules.json +2 -8
- package/eslint.config.mjs +37 -8
- package/install-manifests/commitlint/package-lock.json +5 -4
- package/install-manifests/core/package-lock.json +5 -3
- package/install-manifests/js/package-lock.json +250 -571
- package/install-manifests/js/package.json +10 -8
- package/install-manifests/markdown/package-lock.json +16 -13
- package/install-manifests/markdown/package.json +3 -0
- package/install-manifests/spellcheck/package-lock.json +3 -3
- package/package.json +24 -16
- package/pr-checkmate.schema.json +35 -0
- package/src/config/.eslintrc.js +3 -9
- package/src/config/eslint-default-rules.json +2 -8
- package/src/config/pr-checkmate.schema.json +35 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from '../../utils/logger.js';
|
|
2
2
|
import { clearToolPaths, packagePresent, registerToolPaths } from '../../utils/resolve-bin.js';
|
|
3
3
|
import { ensureTooling } from './ensure.js';
|
|
4
|
-
import {
|
|
4
|
+
import { planProfiles, PROFILES } from './profiles.js';
|
|
5
5
|
/**
|
|
6
6
|
* Whether a profile needs fetching at all, or already ships inside the package.
|
|
7
7
|
*
|
|
@@ -3,7 +3,7 @@ import type { Language, LanguageUsage } from '../../utils/detect-language.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* A named bundle of tooling, and the checks that stop working without it.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
6
|
+
* The tooling totals ~233 MB, and no repository needs all of it: a
|
|
7
7
|
* Python service pays for the whole JavaScript toolchain, a repository with
|
|
8
8
|
* Spellcheck switched off still pays for cspell. Profiles are how that stops —
|
|
9
9
|
* they name which slice of the tooling a given repository actually needs.
|
|
@@ -20,9 +20,9 @@ export const PROFILES = [
|
|
|
20
20
|
'typescript',
|
|
21
21
|
'eslint',
|
|
22
22
|
'eslint-config-prettier',
|
|
23
|
-
'eslint-plugin-import-x',
|
|
24
23
|
'eslint-plugin-jsdoc',
|
|
25
24
|
'eslint-plugin-prettier',
|
|
25
|
+
'eslint-plugin-simple-import-sort',
|
|
26
26
|
'eslint-plugin-sonarjs',
|
|
27
27
|
'@typescript-eslint/eslint-plugin',
|
|
28
28
|
'@typescript-eslint/parser',
|
|
@@ -5,15 +5,18 @@ import { ownPackageRoot } from '../../utils/resolve-bin.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* The major version we declare for a tool, from our own manifest.
|
|
7
7
|
*
|
|
8
|
-
* Read from
|
|
8
|
+
* Read from the manifest rather than from the installed tree: what matters is
|
|
9
9
|
* the version our configuration was written against, and a hoisted install can
|
|
10
10
|
* resolve to something else entirely.
|
|
11
11
|
*/
|
|
12
12
|
function ownMajor(pkgName) {
|
|
13
13
|
try {
|
|
14
14
|
const manifest = path.join(ownPackageRoot(), 'package.json');
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
const parsed = JSON.parse(fs.readFileSync(manifest, 'utf-8'));
|
|
16
|
+
// Profile tooling is declared in `devDependencies` — it is fetched on demand
|
|
17
|
+
// rather than installed with us — but it is still the version our config was
|
|
18
|
+
// written against, and the manifest keeps both.
|
|
19
|
+
const range = parsed.dependencies?.[pkgName] ?? parsed.devDependencies?.[pkgName];
|
|
17
20
|
if (!range)
|
|
18
21
|
return null;
|
|
19
22
|
// `^10.6.0`, `>=3.0.0`, `~5.1` — the leading number is the major in every
|
|
@@ -38,6 +38,7 @@ import { packageSizeCheck } from './checks/quality/package-size.js';
|
|
|
38
38
|
import { spellcheckCheck } from './checks/quality/spellcheck.js';
|
|
39
39
|
import { symlinksCheck } from './checks/quality/symlinks.js';
|
|
40
40
|
import { yamlLintCheck } from './checks/quality/yaml-lint.js';
|
|
41
|
+
import { agentInstructionsCheck } from './checks/security/agent-instructions.js';
|
|
41
42
|
import { diffSecurityCheck } from './checks/security/diff-security.js';
|
|
42
43
|
import { dockerfileSecurityCheck } from './checks/security/dockerfile-security.js';
|
|
43
44
|
import { migrationSafetyCheck } from './checks/security/migration-safety.js';
|
|
@@ -63,6 +64,7 @@ export const REGISTRY = [
|
|
|
63
64
|
diffSecurityCheck,
|
|
64
65
|
workflowSecurityCheck,
|
|
65
66
|
dockerfileSecurityCheck,
|
|
67
|
+
agentInstructionsCheck,
|
|
66
68
|
caseCollisionCheck,
|
|
67
69
|
vulnScanCheck,
|
|
68
70
|
grypeScanCheck,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import { isMcpRegistered } from '../agent/registration.js';
|
|
3
|
+
import { AGENT_SETUP_COMMAND } from '../config/constants.js';
|
|
4
|
+
import { readMcpSettings } from '../mcp/settings.js';
|
|
2
5
|
import { paginate, request } from '../utils/http.js';
|
|
3
6
|
import { logger } from '../utils/index.js';
|
|
4
7
|
import { packageVersion } from '../utils/package-version.js';
|
|
@@ -100,6 +103,12 @@ function printStdout(report, cfg) {
|
|
|
100
103
|
if (cfg.include?.docsLink !== false) {
|
|
101
104
|
// The docs cover every check and config key.
|
|
102
105
|
logger.print(' DOCUMENTATION: https://pr-checkmate-docs.pages.dev/');
|
|
106
|
+
// Said once per project, and never in CI, where nobody is there to act on it.
|
|
107
|
+
if (!process.env.CI &&
|
|
108
|
+
readMcpSettings(process.cwd()).enabled &&
|
|
109
|
+
!isMcpRegistered(process.cwd())) {
|
|
110
|
+
logger.print(` AI AGENT: ${AGENT_SETUP_COMMAND} — your agent then writes code that passes.`);
|
|
111
|
+
}
|
|
103
112
|
}
|
|
104
113
|
}
|
|
105
114
|
/** Network settings shared by every platform call. */
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { isCiEnvironment, logger } from '../utils/index.js';
|
|
2
2
|
import { packageVersion } from '../utils/package-version.js';
|
|
3
|
-
import {
|
|
3
|
+
import { resolveConcurrency, runPool, Semaphore, withTimeout } from '../utils/pool.js';
|
|
4
4
|
import { clearToolPaths } from '../utils/resolve-bin.js';
|
|
5
5
|
import { ResultCollector } from '../utils/result-collector.js';
|
|
6
6
|
import { buildContext } from './context.js';
|
|
7
|
-
import {
|
|
7
|
+
import { collectFindings } from './finding-store.js';
|
|
8
|
+
import { noTooling, prepareTooling } from './install/prepare.js';
|
|
8
9
|
import { REGISTRY } from './registry.js';
|
|
9
10
|
import { report } from './reporters.js';
|
|
10
11
|
import { PHASES, } from './types.js';
|
|
@@ -169,15 +170,24 @@ async function runOne(check, ctx, collector, heavy, tooling) {
|
|
|
169
170
|
}
|
|
170
171
|
const started = Date.now();
|
|
171
172
|
const timeoutMs = ctx.config.run?.checkTimeoutMs ?? 300000;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
// Locations noted while this check runs, collected per check: the phase runs
|
|
174
|
+
// its checks in parallel, so a shared list would mix their findings.
|
|
175
|
+
let located = [];
|
|
176
|
+
const execute = async () => {
|
|
177
|
+
const { result, findings } = await collectFindings(() => withTimeout(check.run(ctx), timeoutMs, () => {
|
|
178
|
+
logger.warn(`[runChecks]: ⏱️ ${check.name} exceeded ${timeoutMs}ms`);
|
|
179
|
+
return { status: 'warn', details: `timed out after ${timeoutMs}ms` };
|
|
180
|
+
}));
|
|
181
|
+
located = findings;
|
|
182
|
+
return result;
|
|
183
|
+
};
|
|
176
184
|
const outcome = check.weight === 'heavy' ? await heavy.run(execute) : await execute();
|
|
177
185
|
if (ctx.config.run?.timings) {
|
|
178
186
|
logger.info(`[runChecks]: ${check.name} took ${Date.now() - started}ms`);
|
|
179
187
|
}
|
|
180
|
-
collector.register(check.name, applySeverity(check.name, outcome.status, ctx), outcome.details
|
|
188
|
+
collector.register(check.name, applySeverity(check.name, outcome.status, ctx), outcome.details,
|
|
189
|
+
// A clean result has nothing to locate, even when `failOn: never` filed some.
|
|
190
|
+
outcome.status === 'pass' ? undefined : (outcome.findings ?? located));
|
|
181
191
|
}
|
|
182
192
|
catch (err) {
|
|
183
193
|
// An unexpected throw in a blocking check fails the run; in informational/format
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A report as SARIF 2.1.0 — the format GitHub code scanning, VS Code and most
|
|
3
|
+
* security dashboards read, so a finding shows up inline on the line it names
|
|
4
|
+
* instead of only in a summary table.
|
|
5
|
+
*
|
|
6
|
+
* Only what a consumer can use is written. A failed or warned check that located
|
|
7
|
+
* its problems yields one result per location; one that could not yields a single
|
|
8
|
+
* result with no location, because a finding with nowhere to point is still a
|
|
9
|
+
* finding. Passes and skips are not results.
|
|
10
|
+
*/
|
|
11
|
+
import type { CheckReport } from './types.js';
|
|
12
|
+
/** Convert a report to a SARIF log object, ready for `JSON.stringify`. */
|
|
13
|
+
export declare function toSarif(report: CheckReport, toolVersion: string): Record<string, unknown>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const SARIF_SCHEMA = 'https://json.schemastore.org/sarif-2.1.0.json';
|
|
2
|
+
const ruleIdFor = (check, rule) => (rule ? `${check}/${rule}` : check);
|
|
3
|
+
function locatedResult(check, f) {
|
|
4
|
+
return {
|
|
5
|
+
ruleId: ruleIdFor(check.name, f.rule),
|
|
6
|
+
level: f.severity === 'error' ? 'error' : 'warning',
|
|
7
|
+
message: { text: f.snippet ? `${f.rule}: ${f.snippet}` : f.rule },
|
|
8
|
+
locations: [
|
|
9
|
+
{
|
|
10
|
+
physicalLocation: {
|
|
11
|
+
artifactLocation: { uri: f.file },
|
|
12
|
+
...(f.line !== undefined && { region: { startLine: f.line } }),
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function summaryResult(check) {
|
|
19
|
+
return {
|
|
20
|
+
ruleId: ruleIdFor(check.name),
|
|
21
|
+
level: check.status === 'fail' ? 'error' : 'warning',
|
|
22
|
+
message: { text: check.details ?? `${check.name} reported a problem` },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Convert a report to a SARIF log object, ready for `JSON.stringify`. */
|
|
26
|
+
export function toSarif(report, toolVersion) {
|
|
27
|
+
const results = [];
|
|
28
|
+
const rules = new Map();
|
|
29
|
+
for (const check of report.results) {
|
|
30
|
+
if (check.status !== 'fail' && check.status !== 'warn')
|
|
31
|
+
continue;
|
|
32
|
+
const found = check.findings && check.findings.length > 0
|
|
33
|
+
? check.findings.map(f => locatedResult(check, f))
|
|
34
|
+
: [summaryResult(check)];
|
|
35
|
+
for (const r of found) {
|
|
36
|
+
results.push(r);
|
|
37
|
+
rules.set(r.ruleId, { id: r.ruleId, name: r.ruleId });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
$schema: SARIF_SCHEMA,
|
|
42
|
+
version: '2.1.0',
|
|
43
|
+
runs: [
|
|
44
|
+
{
|
|
45
|
+
tool: {
|
|
46
|
+
driver: {
|
|
47
|
+
name: 'pr-checkmate',
|
|
48
|
+
version: toolVersion,
|
|
49
|
+
informationUri: 'https://www.npmjs.com/package/pr-checkmate',
|
|
50
|
+
rules: [...rules.values()],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
results,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
}
|
package/dist/esm/core/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PRCheckMateConfig, ReporterConfig } from '../interfaces/index.js';
|
|
2
2
|
import type { Language, LanguageUsage } from '../utils/detect-language.js';
|
|
3
|
-
import type { CheckResult, CheckStatus } from '../utils/result-collector.js';
|
|
4
|
-
export type { CheckResult, CheckStatus, Language, LanguageUsage };
|
|
3
|
+
import type { CheckResult, CheckStatus, Finding } from '../utils/result-collector.js';
|
|
4
|
+
export type { CheckResult, CheckStatus, Finding, Language, LanguageUsage };
|
|
5
5
|
/**
|
|
6
6
|
* Execution phases, run strictly in order. Within a phase checks run in parallel.
|
|
7
7
|
* `format` runs last because formatters (prettier) may write files.
|
|
@@ -67,6 +67,11 @@ export interface CheckContext {
|
|
|
67
67
|
export interface CheckOutcome {
|
|
68
68
|
status: CheckStatus;
|
|
69
69
|
details?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Where the problems are. Left to the orchestrator for pattern-based checks,
|
|
72
|
+
* which note locations as they scan; a check that knows better may set it.
|
|
73
|
+
*/
|
|
74
|
+
findings?: Finding[];
|
|
70
75
|
}
|
|
71
76
|
/**
|
|
72
77
|
* A single quality gate. `applies` decides relevance (language/marker gating);
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* @module pr-checkmate
|
|
5
5
|
*/
|
|
6
6
|
export { runChecks, buildContext, REGISTRY } from './core/index.js';
|
|
7
|
+
export { toSarif } from './core/sarif.js';
|
|
7
8
|
export { pass, warn, fail, skip, defineCheck } from './core/index.js';
|
|
8
|
-
export type { Check, CheckContext, CheckOutcome, CheckReport, CheckResult, CheckStatus, Language, Phase, ReporterFn, ReporterKind, RunOptions, } from './core/index.js';
|
|
9
|
+
export type { Check, CheckContext, CheckOutcome, CheckReport, CheckResult, CheckStatus, Finding, Language, Phase, ReporterFn, ReporterKind, RunOptions, } from './core/index.js';
|
|
9
10
|
export { getSourcePath, getSourcePaths, getIgnoredDirs, getPackageConfigPath, hasLocalConfig, } from './config/index.js';
|
|
10
11
|
export type { PRCheckMateConfig } from './interfaces/index.js';
|
|
11
12
|
export { Logger } from './utils/logger.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
// Primary programmatic API: run checks and receive a structured report.
|
|
7
7
|
// Never throws for violations, never calls process.exit — the caller decides.
|
|
8
8
|
export { runChecks, buildContext, REGISTRY } from './core/index.js';
|
|
9
|
+
// SARIF 2.1.0 export of a report, for code-scanning dashboards and editors.
|
|
10
|
+
export { toSarif } from './core/sarif.js';
|
|
9
11
|
// Authoring helpers for consumers writing their own checks (plugins).
|
|
10
12
|
export { pass, warn, fail, skip, defineCheck } from './core/index.js';
|
|
11
13
|
// Config helpers for consumers embedding pr-checkmate.
|
package/dist/esm/init.d.ts
CHANGED
|
@@ -30,14 +30,6 @@ export declare function setupWorkflow(root: string, mode: GateMode): void;
|
|
|
30
30
|
* heart about what should block.
|
|
31
31
|
*/
|
|
32
32
|
export declare const BLOCKING_BY_DEFAULT: readonly ["Security Scan", "Sensitive Files", "Diff Security", "Workflow Security", "Merge Conflict", "NPM Audit", "License Check", "Dependencies", "TypeScript", "ESLint", "YAML Lint"];
|
|
33
|
-
/**
|
|
34
|
-
* Every option the template documents that the file does not already carry, at
|
|
35
|
-
* its default. Without this, options such as `vulnScan` (off by default) or
|
|
36
|
-
* `licenseCheck` exist only in the docs, and nobody edits what they cannot see.
|
|
37
|
-
* Comment keys travel with the option they describe, section headers with the
|
|
38
|
-
* first option after them.
|
|
39
|
-
*/
|
|
40
|
-
export declare function templateExtras(existing: Record<string, unknown>): Record<string, unknown>;
|
|
41
33
|
export declare function buildInitialConfig(sourcePath: string, languages: string[]): Record<string, unknown>;
|
|
42
34
|
/**
|
|
43
35
|
* Initialize (or refresh) pr-checkmate configuration in the current project.
|
package/dist/esm/init.js
CHANGED
|
@@ -2,11 +2,11 @@ import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
|
2
2
|
import { dirname as __dirnameFn } from 'node:path';
|
|
3
3
|
const __dirname = __dirnameFn(__fileURLToPath(import.meta.url));
|
|
4
4
|
import fs from 'fs';
|
|
5
|
-
import path from 'path';
|
|
6
5
|
import inquirer from 'inquirer';
|
|
7
|
-
import
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { AGENT_SETUP_COMMAND, DEAD_CODE_IGNORE_DEFAULTS, DEFAULT_COMMANDS, DIFF_SECURITY_IGNORE_DEFAULTS, DOCS_URL, documentation, DUPLICATE_IGNORE_DEFAULTS, FULL_CONFIG_URL, GENERATED_DOC_FILES, IGNORED_DIRS, } from './config/index.js';
|
|
8
8
|
import { DEFAULT_DATAFLOW_WINDOW } from './core/checks/findings.js';
|
|
9
|
-
import {
|
|
9
|
+
import { detectLanguages, findOwnPackageRoot, logger } from './utils/index.js';
|
|
10
10
|
const CONFIG_FILE = path.resolve(process.cwd(), 'pr-checkmate.json');
|
|
11
11
|
/**
|
|
12
12
|
* Points editors at the bundled JSON schema. With the generated config reduced
|
|
@@ -286,7 +286,7 @@ const GRYPE_SCAN_SEED = {
|
|
|
286
286
|
* Comment keys travel with the option they describe, section headers with the
|
|
287
287
|
* first option after them.
|
|
288
288
|
*/
|
|
289
|
-
|
|
289
|
+
function templateExtras(existing) {
|
|
290
290
|
const templatePath = path.join(__dirname, 'config', 'pr-checkmate.template.json');
|
|
291
291
|
if (!fs.existsSync(templatePath)) {
|
|
292
292
|
return {};
|
|
@@ -413,6 +413,16 @@ async function createConfig(root) {
|
|
|
413
413
|
* update notice insisted `init` must not be skipped after an upgrade. Defaults
|
|
414
414
|
* now apply when the config is loaded, so there is nothing to top up.
|
|
415
415
|
*/
|
|
416
|
+
/** Adds the agent-setup command to a client's `commands` block when it is missing; nothing else in it is touched. */
|
|
417
|
+
function withAgentCommand(commands) {
|
|
418
|
+
if (commands === undefined)
|
|
419
|
+
return undefined;
|
|
420
|
+
if (typeof commands !== 'object' || commands === null || Array.isArray(commands))
|
|
421
|
+
return commands;
|
|
422
|
+
if (AGENT_SETUP_COMMAND in commands)
|
|
423
|
+
return commands;
|
|
424
|
+
return { ...commands, [AGENT_SETUP_COMMAND]: DEFAULT_COMMANDS[AGENT_SETUP_COMMAND] };
|
|
425
|
+
}
|
|
416
426
|
async function updateConfig(root) {
|
|
417
427
|
logger.info('[init]: pr-checkmate.json already exists — updating it.');
|
|
418
428
|
try {
|
|
@@ -443,6 +453,7 @@ async function updateConfig(root) {
|
|
|
443
453
|
// when missing; a client's own block is never touched.
|
|
444
454
|
grypeScan: json.grypeScan ?? structuredClone(GRYPE_SCAN_SEED),
|
|
445
455
|
...templateExtras({ ...json, grypeScan: true }),
|
|
456
|
+
commands: withAgentCommand(json.commands),
|
|
446
457
|
languages,
|
|
447
458
|
};
|
|
448
459
|
fs.writeFileSync(CONFIG_FILE, `${JSON.stringify(updated, null, 2)}\n`);
|
|
@@ -317,6 +317,18 @@ export interface PRCheckMateConfig {
|
|
|
317
317
|
severityOverrides?: Record<string, 'error' | 'warn' | 'off'>;
|
|
318
318
|
ignorePaths?: string[];
|
|
319
319
|
};
|
|
320
|
+
mcp?: {
|
|
321
|
+
enabled?: boolean;
|
|
322
|
+
disabledTools?: string[];
|
|
323
|
+
readOnly?: boolean;
|
|
324
|
+
};
|
|
325
|
+
agentInstructions?: {
|
|
326
|
+
enabled?: boolean;
|
|
327
|
+
ignore?: string[];
|
|
328
|
+
failOn?: 'error' | 'warn' | 'never';
|
|
329
|
+
severityOverrides?: Record<string, 'error' | 'warn' | 'off'>;
|
|
330
|
+
ignorePaths?: string[];
|
|
331
|
+
};
|
|
320
332
|
dockerfileSecurity?: {
|
|
321
333
|
enabled?: boolean;
|
|
322
334
|
ignore?: string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ToolResult } from './protocol.js';
|
|
2
|
+
type Json = Record<string, unknown>;
|
|
3
|
+
/** What a key means, from the schema that ships with the package. */
|
|
4
|
+
export declare function explainConfig(key?: string): ToolResult;
|
|
5
|
+
/** Problems in a proposed config, phrased so the agent can correct them. Empty means it is acceptable. */
|
|
6
|
+
export declare function validateConfig(config: Json, cwd: string): string[];
|
|
7
|
+
/** Validate and write `config` into the repository's `pr-checkmate.json`. */
|
|
8
|
+
export declare function writeConfig(cwd: string, config: unknown, overwrite: boolean): ToolResult;
|
|
9
|
+
interface Suggestion {
|
|
10
|
+
proposed: Json;
|
|
11
|
+
notes: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Look at the repository and propose a config.
|
|
15
|
+
*
|
|
16
|
+
* The baseline is a whole-repository run of the fast checks. A check that already
|
|
17
|
+
* fails is proposed as `warn`: the gate is on from the first commit, the existing
|
|
18
|
+
* debt is visible, and nothing new can slip in unnoticed — then each check is
|
|
19
|
+
* promoted back to blocking as it reaches zero. Proposing `error` everywhere would
|
|
20
|
+
* make the first CI run red for reasons nobody on the pull request caused, and the
|
|
21
|
+
* usual response to that is to switch the whole tool off.
|
|
22
|
+
*/
|
|
23
|
+
export declare function suggestConfig(cwd: string): Promise<Suggestion & {
|
|
24
|
+
languages: string[];
|
|
25
|
+
}>;
|
|
26
|
+
/** `suggest_config` as the text an agent reads. */
|
|
27
|
+
export declare function formatSuggestion(s: Suggestion & {
|
|
28
|
+
languages: string[];
|
|
29
|
+
}): ToolResult;
|
|
30
|
+
export {};
|