@studiomeyer-io/skilldoctor 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 +21 -0
- package/README.md +187 -0
- package/SECURITY.md +53 -0
- package/dist/cli.cjs +1718 -0
- package/dist/cli.d.cts +31 -0
- package/dist/cli.d.ts +31 -0
- package/dist/cli.js +1715 -0
- package/dist/index.cjs +1569 -0
- package/dist/index.d.cts +220 -0
- package/dist/index.d.ts +220 -0
- package/dist/index.js +1540 -0
- package/dist/types-lUfaWSNG.d.cts +117 -0
- package/dist/types-lUfaWSNG.d.ts +117 -0
- package/package.json +77 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { A as AnalyzeOptions, F as FileReport, a as AnalysisReport, P as ParsedFile, b as ParsedFrontmatter, c as FileKind, d as Finding, G as Grade, S as Severity, R as RuleDescriptor } from './types-lUfaWSNG.cjs';
|
|
2
|
+
export { e as FindingCategory, f as SEVERITY_RANK } from './types-lUfaWSNG.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Analyzer — the central orchestration layer. Parses, lints, security-scans,
|
|
6
|
+
* and grades one file or a set of files, and runs cross-file rules
|
|
7
|
+
* (duplicate names).
|
|
8
|
+
*
|
|
9
|
+
* This module is pure with respect to the filesystem when given content
|
|
10
|
+
* directly (`analyzeContent`); `analyzePaths` reads files for convenience.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Analyze a single file given its content. */
|
|
14
|
+
declare function analyzeContent(filePath: string, content: string, options?: AnalyzeOptions): FileReport;
|
|
15
|
+
/** Analyze multiple files given their {path, content} pairs (no FS access). */
|
|
16
|
+
declare function analyzeFiles(inputs: readonly {
|
|
17
|
+
filePath: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}[], options?: AnalyzeOptions): AnalysisReport;
|
|
20
|
+
/** Analyze a list of file paths, reading each from disk. */
|
|
21
|
+
declare function analyzePaths(paths: readonly string[], options?: AnalyzeOptions): AnalysisReport;
|
|
22
|
+
/** Re-parse content (used by the CLI to feed the fixer). */
|
|
23
|
+
declare function parseForFix(filePath: string, content: string): ParsedFile;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parsing layer: split an agent-instruction file into frontmatter + body,
|
|
27
|
+
* parse the YAML frontmatter, and classify the file kind.
|
|
28
|
+
*
|
|
29
|
+
* We do NOT execute anything. We only read text. The YAML parser is configured
|
|
30
|
+
* defensively (no custom tags, no anchors expansion blow-up via the default
|
|
31
|
+
* parser limits in the `yaml` package).
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Extract a frontmatter block from raw file contents.
|
|
36
|
+
*
|
|
37
|
+
* Frontmatter must start on line 1 with `---` and end with a line that is
|
|
38
|
+
* exactly `---` (optionally followed by trailing whitespace). Anything after
|
|
39
|
+
* the closing fence is the body.
|
|
40
|
+
*/
|
|
41
|
+
declare function extractFrontmatter(raw: string): {
|
|
42
|
+
frontmatter: ParsedFrontmatter;
|
|
43
|
+
body: string;
|
|
44
|
+
bodyStartLine: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Classify the file kind from its path and parsed frontmatter.
|
|
48
|
+
*
|
|
49
|
+
* Heuristics (deliberately conservative — when unsure we lean "skill" only if
|
|
50
|
+
* the filename is SKILL.md, otherwise "unknown" or "agents-md"):
|
|
51
|
+
* - `AGENTS.md` (any case) -> agents-md
|
|
52
|
+
* - `SKILL.md` (any case) -> skill
|
|
53
|
+
* - a `.md` file inside an `agents/` directory with frontmatter -> subagent
|
|
54
|
+
* - a `.md` file with `name`+`description` frontmatter -> skill (best guess)
|
|
55
|
+
* - otherwise -> unknown
|
|
56
|
+
*/
|
|
57
|
+
declare function detectKind(filePath: string, frontmatter: ParsedFrontmatter): FileKind;
|
|
58
|
+
/** Parse raw file contents at a given path into a ParsedFile. */
|
|
59
|
+
declare function parseFile(filePath: string, raw: string, forceKind?: FileKind): ParsedFile;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Grading: turn a set of findings into a 0-100 score and an A-F letter grade.
|
|
63
|
+
*
|
|
64
|
+
* Security findings are weighted more heavily than lint findings, because the
|
|
65
|
+
* whole point of skilldoctor is to surface supply-chain risk. The mapping is
|
|
66
|
+
* deterministic and documented so grades are reproducible.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/** Compute a 0-100 score from findings (100 = clean). */
|
|
70
|
+
declare function scoreFindings(findings: readonly Finding[]): number;
|
|
71
|
+
/** Map a numeric score to a letter grade. */
|
|
72
|
+
declare function scoreToGrade(score: number): Grade;
|
|
73
|
+
/** Tally findings by severity. */
|
|
74
|
+
declare function tally(findings: readonly Finding[]): Record<Severity, number>;
|
|
75
|
+
/**
|
|
76
|
+
* Aggregate per-file scores into one overall score. We use a worst-weighted
|
|
77
|
+
* average: the mean of file scores, pulled toward the single worst file so a
|
|
78
|
+
* batch with one dangerous skill cannot be averaged into a good grade.
|
|
79
|
+
*/
|
|
80
|
+
declare function aggregateScore(fileScores: readonly number[]): number;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Central rule registry — the single source of truth for every rule
|
|
84
|
+
* skilldoctor can emit. SARIF requires every emitted `ruleId` to have a
|
|
85
|
+
* matching `reportingDescriptor` in `driver.rules`, so we generate that list
|
|
86
|
+
* from here. The README rule table is also derived from this.
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
declare const RULES: readonly RuleDescriptor[];
|
|
90
|
+
/** Look up a rule descriptor by id. Throws if unknown (programmer error). */
|
|
91
|
+
declare function getRule(ruleId: string): RuleDescriptor;
|
|
92
|
+
/** All registered rule ids. */
|
|
93
|
+
declare function allRuleIds(): string[];
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* --fix engine. Mechanically repairs the safe, unambiguous subset of findings.
|
|
97
|
+
*
|
|
98
|
+
* HARD RULE: we never rewrite the markdown body content (that could neutralize
|
|
99
|
+
* malicious instructions silently, or mangle legitimate prose). We only touch
|
|
100
|
+
* the YAML frontmatter, and only in deterministic, reversible ways:
|
|
101
|
+
* 1. trim trailing whitespace on frontmatter lines
|
|
102
|
+
* 2. add a missing `description:` stub with a TODO marker
|
|
103
|
+
* 3. de-duplicate tools within `allowed-tools` / `tools` (preserving order)
|
|
104
|
+
*
|
|
105
|
+
* The fixer is idempotent: running it twice produces identical output.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/** Marker used for an inserted stub so humans (and tests) can find it. */
|
|
109
|
+
declare const DESCRIPTION_STUB = "TODO describe what this skill does and when to use it.";
|
|
110
|
+
interface FixResult {
|
|
111
|
+
/** The (possibly) rewritten file contents. */
|
|
112
|
+
output: string;
|
|
113
|
+
/** True if anything changed. */
|
|
114
|
+
changed: boolean;
|
|
115
|
+
/** Names of the fixes applied. */
|
|
116
|
+
applied: string[];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Apply mechanical fixes to a parsed file's raw text and return the result.
|
|
120
|
+
* Only skill/subagent files with frontmatter are fixed; AGENTS.md/unknown are
|
|
121
|
+
* returned unchanged.
|
|
122
|
+
*/
|
|
123
|
+
declare function fixFile(file: ParsedFile): FixResult;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* File discovery. Given path(s) — a file, a directory, or a glob — resolve the
|
|
127
|
+
* set of candidate markdown files to analyze.
|
|
128
|
+
*
|
|
129
|
+
* Deliberately dependency-free: a small recursive walker plus a minimal glob
|
|
130
|
+
* matcher cover our needs (`**`, `*`, `?`) without pulling in fast-glob/globby.
|
|
131
|
+
*/
|
|
132
|
+
/** True if a path string contains glob metacharacters. */
|
|
133
|
+
declare function isGlob(p: string): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Convert a glob to an anchored RegExp. Supports `**` (any depth, incl. zero),
|
|
136
|
+
* `*` (within a path segment), `?` (single char), and literal text. Forward
|
|
137
|
+
* slashes only (we normalize input to posix).
|
|
138
|
+
*/
|
|
139
|
+
declare function globToRegExp(glob: string): RegExp;
|
|
140
|
+
/**
|
|
141
|
+
* Resolve one or more input specs into a deduplicated, sorted list of absolute
|
|
142
|
+
* file paths. Each spec may be a file, a directory, or a glob.
|
|
143
|
+
*/
|
|
144
|
+
declare function discoverFiles(specs: readonly string[]): string[];
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Terminal reporter. Human-readable, optionally colorized (auto-disabled when
|
|
148
|
+
* not a TTY or when NO_COLOR is set). No external dependency — small ANSI
|
|
149
|
+
* helpers only.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
interface TerminalOptions {
|
|
153
|
+
/** Force color on/off. Defaults to auto-detect. */
|
|
154
|
+
color?: boolean;
|
|
155
|
+
}
|
|
156
|
+
/** Render a full analysis report as a terminal string. */
|
|
157
|
+
declare function renderTerminal(report: AnalysisReport, options?: TerminalOptions): string;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* JSON reporter. A stable, documented machine-readable shape of an analysis
|
|
161
|
+
* report. Keep this versioned so downstream consumers can rely on it.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
declare const JSON_REPORT_VERSION: 1;
|
|
165
|
+
interface JsonReport {
|
|
166
|
+
/** Schema version of this JSON output. */
|
|
167
|
+
schemaVersion: typeof JSON_REPORT_VERSION;
|
|
168
|
+
/** The tool that produced it. */
|
|
169
|
+
tool: {
|
|
170
|
+
name: "skilldoctor";
|
|
171
|
+
version: string;
|
|
172
|
+
};
|
|
173
|
+
/** Aggregate grade + score. */
|
|
174
|
+
summary: {
|
|
175
|
+
grade: string;
|
|
176
|
+
score: number;
|
|
177
|
+
fileCount: number;
|
|
178
|
+
errors: number;
|
|
179
|
+
warnings: number;
|
|
180
|
+
infos: number;
|
|
181
|
+
};
|
|
182
|
+
/** Per-file results. */
|
|
183
|
+
files: AnalysisReport["files"];
|
|
184
|
+
}
|
|
185
|
+
/** Build the JSON report object. */
|
|
186
|
+
declare function toJsonReport(report: AnalysisReport, toolVersion: string): JsonReport;
|
|
187
|
+
/** Serialize the JSON report. */
|
|
188
|
+
declare function jsonString(report: AnalysisReport, toolVersion: string): string;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* SARIF 2.1.0 reporter.
|
|
192
|
+
*
|
|
193
|
+
* Produces a valid SARIF log that GitHub code scanning accepts:
|
|
194
|
+
* - exactly one run with a tool.driver
|
|
195
|
+
* - driver.rules[] contains a reportingDescriptor for EVERY ruleId we emit
|
|
196
|
+
* (so no result references a missing rule)
|
|
197
|
+
* - each result has a ruleId, ruleIndex, level, message, and a physical
|
|
198
|
+
* location with a region (1-based line/column)
|
|
199
|
+
* - each result carries partialFingerprints for stable de-duplication across
|
|
200
|
+
* runs (we hash ruleId + relative file + a normalized snippet, NOT the line
|
|
201
|
+
* number, so cosmetic line shifts don't churn fingerprints)
|
|
202
|
+
*
|
|
203
|
+
* Spec ref: SARIF v2.1.0 (OASIS). Schema:
|
|
204
|
+
* https://json.schemastore.org/sarif-2.1.0.json
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
declare const SARIF_VERSION = "2.1.0";
|
|
208
|
+
declare const SARIF_SCHEMA = "https://json.schemastore.org/sarif-2.1.0.json";
|
|
209
|
+
/** Build the SARIF log object for an analysis report. */
|
|
210
|
+
declare function toSarif(report: AnalysisReport, options?: {
|
|
211
|
+
baseDir?: string;
|
|
212
|
+
version?: string;
|
|
213
|
+
}): unknown;
|
|
214
|
+
/** Serialize the SARIF log to a JSON string. */
|
|
215
|
+
declare function sarifString(report: AnalysisReport, options?: {
|
|
216
|
+
baseDir?: string;
|
|
217
|
+
version?: string;
|
|
218
|
+
}): string;
|
|
219
|
+
|
|
220
|
+
export { AnalysisReport, AnalyzeOptions, DESCRIPTION_STUB, FileKind, FileReport, Finding, type FixResult, Grade, JSON_REPORT_VERSION, type JsonReport, ParsedFile, ParsedFrontmatter, RULES, RuleDescriptor, SARIF_SCHEMA, SARIF_VERSION, Severity, aggregateScore, allRuleIds, analyzeContent, analyzeFiles, analyzePaths, detectKind, discoverFiles, extractFrontmatter, fixFile, getRule, globToRegExp, isGlob, jsonString, parseFile, parseForFix, renderTerminal, sarifString, scoreFindings, scoreToGrade, tally, toJsonReport, toSarif };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { A as AnalyzeOptions, F as FileReport, a as AnalysisReport, P as ParsedFile, b as ParsedFrontmatter, c as FileKind, d as Finding, G as Grade, S as Severity, R as RuleDescriptor } from './types-lUfaWSNG.js';
|
|
2
|
+
export { e as FindingCategory, f as SEVERITY_RANK } from './types-lUfaWSNG.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Analyzer — the central orchestration layer. Parses, lints, security-scans,
|
|
6
|
+
* and grades one file or a set of files, and runs cross-file rules
|
|
7
|
+
* (duplicate names).
|
|
8
|
+
*
|
|
9
|
+
* This module is pure with respect to the filesystem when given content
|
|
10
|
+
* directly (`analyzeContent`); `analyzePaths` reads files for convenience.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Analyze a single file given its content. */
|
|
14
|
+
declare function analyzeContent(filePath: string, content: string, options?: AnalyzeOptions): FileReport;
|
|
15
|
+
/** Analyze multiple files given their {path, content} pairs (no FS access). */
|
|
16
|
+
declare function analyzeFiles(inputs: readonly {
|
|
17
|
+
filePath: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}[], options?: AnalyzeOptions): AnalysisReport;
|
|
20
|
+
/** Analyze a list of file paths, reading each from disk. */
|
|
21
|
+
declare function analyzePaths(paths: readonly string[], options?: AnalyzeOptions): AnalysisReport;
|
|
22
|
+
/** Re-parse content (used by the CLI to feed the fixer). */
|
|
23
|
+
declare function parseForFix(filePath: string, content: string): ParsedFile;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parsing layer: split an agent-instruction file into frontmatter + body,
|
|
27
|
+
* parse the YAML frontmatter, and classify the file kind.
|
|
28
|
+
*
|
|
29
|
+
* We do NOT execute anything. We only read text. The YAML parser is configured
|
|
30
|
+
* defensively (no custom tags, no anchors expansion blow-up via the default
|
|
31
|
+
* parser limits in the `yaml` package).
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Extract a frontmatter block from raw file contents.
|
|
36
|
+
*
|
|
37
|
+
* Frontmatter must start on line 1 with `---` and end with a line that is
|
|
38
|
+
* exactly `---` (optionally followed by trailing whitespace). Anything after
|
|
39
|
+
* the closing fence is the body.
|
|
40
|
+
*/
|
|
41
|
+
declare function extractFrontmatter(raw: string): {
|
|
42
|
+
frontmatter: ParsedFrontmatter;
|
|
43
|
+
body: string;
|
|
44
|
+
bodyStartLine: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Classify the file kind from its path and parsed frontmatter.
|
|
48
|
+
*
|
|
49
|
+
* Heuristics (deliberately conservative — when unsure we lean "skill" only if
|
|
50
|
+
* the filename is SKILL.md, otherwise "unknown" or "agents-md"):
|
|
51
|
+
* - `AGENTS.md` (any case) -> agents-md
|
|
52
|
+
* - `SKILL.md` (any case) -> skill
|
|
53
|
+
* - a `.md` file inside an `agents/` directory with frontmatter -> subagent
|
|
54
|
+
* - a `.md` file with `name`+`description` frontmatter -> skill (best guess)
|
|
55
|
+
* - otherwise -> unknown
|
|
56
|
+
*/
|
|
57
|
+
declare function detectKind(filePath: string, frontmatter: ParsedFrontmatter): FileKind;
|
|
58
|
+
/** Parse raw file contents at a given path into a ParsedFile. */
|
|
59
|
+
declare function parseFile(filePath: string, raw: string, forceKind?: FileKind): ParsedFile;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Grading: turn a set of findings into a 0-100 score and an A-F letter grade.
|
|
63
|
+
*
|
|
64
|
+
* Security findings are weighted more heavily than lint findings, because the
|
|
65
|
+
* whole point of skilldoctor is to surface supply-chain risk. The mapping is
|
|
66
|
+
* deterministic and documented so grades are reproducible.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/** Compute a 0-100 score from findings (100 = clean). */
|
|
70
|
+
declare function scoreFindings(findings: readonly Finding[]): number;
|
|
71
|
+
/** Map a numeric score to a letter grade. */
|
|
72
|
+
declare function scoreToGrade(score: number): Grade;
|
|
73
|
+
/** Tally findings by severity. */
|
|
74
|
+
declare function tally(findings: readonly Finding[]): Record<Severity, number>;
|
|
75
|
+
/**
|
|
76
|
+
* Aggregate per-file scores into one overall score. We use a worst-weighted
|
|
77
|
+
* average: the mean of file scores, pulled toward the single worst file so a
|
|
78
|
+
* batch with one dangerous skill cannot be averaged into a good grade.
|
|
79
|
+
*/
|
|
80
|
+
declare function aggregateScore(fileScores: readonly number[]): number;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Central rule registry — the single source of truth for every rule
|
|
84
|
+
* skilldoctor can emit. SARIF requires every emitted `ruleId` to have a
|
|
85
|
+
* matching `reportingDescriptor` in `driver.rules`, so we generate that list
|
|
86
|
+
* from here. The README rule table is also derived from this.
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
declare const RULES: readonly RuleDescriptor[];
|
|
90
|
+
/** Look up a rule descriptor by id. Throws if unknown (programmer error). */
|
|
91
|
+
declare function getRule(ruleId: string): RuleDescriptor;
|
|
92
|
+
/** All registered rule ids. */
|
|
93
|
+
declare function allRuleIds(): string[];
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* --fix engine. Mechanically repairs the safe, unambiguous subset of findings.
|
|
97
|
+
*
|
|
98
|
+
* HARD RULE: we never rewrite the markdown body content (that could neutralize
|
|
99
|
+
* malicious instructions silently, or mangle legitimate prose). We only touch
|
|
100
|
+
* the YAML frontmatter, and only in deterministic, reversible ways:
|
|
101
|
+
* 1. trim trailing whitespace on frontmatter lines
|
|
102
|
+
* 2. add a missing `description:` stub with a TODO marker
|
|
103
|
+
* 3. de-duplicate tools within `allowed-tools` / `tools` (preserving order)
|
|
104
|
+
*
|
|
105
|
+
* The fixer is idempotent: running it twice produces identical output.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/** Marker used for an inserted stub so humans (and tests) can find it. */
|
|
109
|
+
declare const DESCRIPTION_STUB = "TODO describe what this skill does and when to use it.";
|
|
110
|
+
interface FixResult {
|
|
111
|
+
/** The (possibly) rewritten file contents. */
|
|
112
|
+
output: string;
|
|
113
|
+
/** True if anything changed. */
|
|
114
|
+
changed: boolean;
|
|
115
|
+
/** Names of the fixes applied. */
|
|
116
|
+
applied: string[];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Apply mechanical fixes to a parsed file's raw text and return the result.
|
|
120
|
+
* Only skill/subagent files with frontmatter are fixed; AGENTS.md/unknown are
|
|
121
|
+
* returned unchanged.
|
|
122
|
+
*/
|
|
123
|
+
declare function fixFile(file: ParsedFile): FixResult;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* File discovery. Given path(s) — a file, a directory, or a glob — resolve the
|
|
127
|
+
* set of candidate markdown files to analyze.
|
|
128
|
+
*
|
|
129
|
+
* Deliberately dependency-free: a small recursive walker plus a minimal glob
|
|
130
|
+
* matcher cover our needs (`**`, `*`, `?`) without pulling in fast-glob/globby.
|
|
131
|
+
*/
|
|
132
|
+
/** True if a path string contains glob metacharacters. */
|
|
133
|
+
declare function isGlob(p: string): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Convert a glob to an anchored RegExp. Supports `**` (any depth, incl. zero),
|
|
136
|
+
* `*` (within a path segment), `?` (single char), and literal text. Forward
|
|
137
|
+
* slashes only (we normalize input to posix).
|
|
138
|
+
*/
|
|
139
|
+
declare function globToRegExp(glob: string): RegExp;
|
|
140
|
+
/**
|
|
141
|
+
* Resolve one or more input specs into a deduplicated, sorted list of absolute
|
|
142
|
+
* file paths. Each spec may be a file, a directory, or a glob.
|
|
143
|
+
*/
|
|
144
|
+
declare function discoverFiles(specs: readonly string[]): string[];
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Terminal reporter. Human-readable, optionally colorized (auto-disabled when
|
|
148
|
+
* not a TTY or when NO_COLOR is set). No external dependency — small ANSI
|
|
149
|
+
* helpers only.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
interface TerminalOptions {
|
|
153
|
+
/** Force color on/off. Defaults to auto-detect. */
|
|
154
|
+
color?: boolean;
|
|
155
|
+
}
|
|
156
|
+
/** Render a full analysis report as a terminal string. */
|
|
157
|
+
declare function renderTerminal(report: AnalysisReport, options?: TerminalOptions): string;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* JSON reporter. A stable, documented machine-readable shape of an analysis
|
|
161
|
+
* report. Keep this versioned so downstream consumers can rely on it.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
declare const JSON_REPORT_VERSION: 1;
|
|
165
|
+
interface JsonReport {
|
|
166
|
+
/** Schema version of this JSON output. */
|
|
167
|
+
schemaVersion: typeof JSON_REPORT_VERSION;
|
|
168
|
+
/** The tool that produced it. */
|
|
169
|
+
tool: {
|
|
170
|
+
name: "skilldoctor";
|
|
171
|
+
version: string;
|
|
172
|
+
};
|
|
173
|
+
/** Aggregate grade + score. */
|
|
174
|
+
summary: {
|
|
175
|
+
grade: string;
|
|
176
|
+
score: number;
|
|
177
|
+
fileCount: number;
|
|
178
|
+
errors: number;
|
|
179
|
+
warnings: number;
|
|
180
|
+
infos: number;
|
|
181
|
+
};
|
|
182
|
+
/** Per-file results. */
|
|
183
|
+
files: AnalysisReport["files"];
|
|
184
|
+
}
|
|
185
|
+
/** Build the JSON report object. */
|
|
186
|
+
declare function toJsonReport(report: AnalysisReport, toolVersion: string): JsonReport;
|
|
187
|
+
/** Serialize the JSON report. */
|
|
188
|
+
declare function jsonString(report: AnalysisReport, toolVersion: string): string;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* SARIF 2.1.0 reporter.
|
|
192
|
+
*
|
|
193
|
+
* Produces a valid SARIF log that GitHub code scanning accepts:
|
|
194
|
+
* - exactly one run with a tool.driver
|
|
195
|
+
* - driver.rules[] contains a reportingDescriptor for EVERY ruleId we emit
|
|
196
|
+
* (so no result references a missing rule)
|
|
197
|
+
* - each result has a ruleId, ruleIndex, level, message, and a physical
|
|
198
|
+
* location with a region (1-based line/column)
|
|
199
|
+
* - each result carries partialFingerprints for stable de-duplication across
|
|
200
|
+
* runs (we hash ruleId + relative file + a normalized snippet, NOT the line
|
|
201
|
+
* number, so cosmetic line shifts don't churn fingerprints)
|
|
202
|
+
*
|
|
203
|
+
* Spec ref: SARIF v2.1.0 (OASIS). Schema:
|
|
204
|
+
* https://json.schemastore.org/sarif-2.1.0.json
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
declare const SARIF_VERSION = "2.1.0";
|
|
208
|
+
declare const SARIF_SCHEMA = "https://json.schemastore.org/sarif-2.1.0.json";
|
|
209
|
+
/** Build the SARIF log object for an analysis report. */
|
|
210
|
+
declare function toSarif(report: AnalysisReport, options?: {
|
|
211
|
+
baseDir?: string;
|
|
212
|
+
version?: string;
|
|
213
|
+
}): unknown;
|
|
214
|
+
/** Serialize the SARIF log to a JSON string. */
|
|
215
|
+
declare function sarifString(report: AnalysisReport, options?: {
|
|
216
|
+
baseDir?: string;
|
|
217
|
+
version?: string;
|
|
218
|
+
}): string;
|
|
219
|
+
|
|
220
|
+
export { AnalysisReport, AnalyzeOptions, DESCRIPTION_STUB, FileKind, FileReport, Finding, type FixResult, Grade, JSON_REPORT_VERSION, type JsonReport, ParsedFile, ParsedFrontmatter, RULES, RuleDescriptor, SARIF_SCHEMA, SARIF_VERSION, Severity, aggregateScore, allRuleIds, analyzeContent, analyzeFiles, analyzePaths, detectKind, discoverFiles, extractFrontmatter, fixFile, getRule, globToRegExp, isGlob, jsonString, parseFile, parseForFix, renderTerminal, sarifString, scoreFindings, scoreToGrade, tally, toJsonReport, toSarif };
|