@promptci/core 0.2.2 → 0.4.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.
Files changed (181) hide show
  1. package/dist/action-pinning.d.ts.map +1 -1
  2. package/dist/action-pinning.js +86 -55
  3. package/dist/action-pinning.js.map +1 -1
  4. package/dist/agent-practices.d.ts +5 -1
  5. package/dist/agent-practices.d.ts.map +1 -1
  6. package/dist/agent-practices.js +59 -34
  7. package/dist/agent-practices.js.map +1 -1
  8. package/dist/ai-config.d.ts +13 -6
  9. package/dist/ai-config.d.ts.map +1 -1
  10. package/dist/ai-config.js +25 -78
  11. package/dist/ai-config.js.map +1 -1
  12. package/dist/baseline.d.ts +8 -0
  13. package/dist/baseline.d.ts.map +1 -1
  14. package/dist/baseline.js +15 -0
  15. package/dist/baseline.js.map +1 -1
  16. package/dist/ci-alignment.d.ts +3 -1
  17. package/dist/ci-alignment.d.ts.map +1 -1
  18. package/dist/ci-alignment.js +8 -1
  19. package/dist/ci-alignment.js.map +1 -1
  20. package/dist/close-match.d.ts +97 -0
  21. package/dist/close-match.d.ts.map +1 -0
  22. package/dist/close-match.js +215 -0
  23. package/dist/close-match.js.map +1 -0
  24. package/dist/command-context.d.ts +67 -0
  25. package/dist/command-context.d.ts.map +1 -0
  26. package/dist/command-context.js +291 -0
  27. package/dist/command-context.js.map +1 -0
  28. package/dist/command-validity.d.ts.map +1 -1
  29. package/dist/command-validity.js +510 -32
  30. package/dist/command-validity.js.map +1 -1
  31. package/dist/context-optimizer.d.ts.map +1 -1
  32. package/dist/context-optimizer.js +9 -2
  33. package/dist/context-optimizer.js.map +1 -1
  34. package/dist/dead-references.d.ts +14 -1
  35. package/dist/dead-references.d.ts.map +1 -1
  36. package/dist/dead-references.js +264 -17
  37. package/dist/dead-references.js.map +1 -1
  38. package/dist/dependency-staleness.d.ts.map +1 -1
  39. package/dist/dependency-staleness.js +24 -38
  40. package/dist/dependency-staleness.js.map +1 -1
  41. package/dist/detectors.js +1 -1
  42. package/dist/detectors.js.map +1 -1
  43. package/dist/discovery.d.ts +138 -0
  44. package/dist/discovery.d.ts.map +1 -0
  45. package/dist/discovery.js +569 -0
  46. package/dist/discovery.js.map +1 -0
  47. package/dist/duplicates.d.ts +24 -2
  48. package/dist/duplicates.d.ts.map +1 -1
  49. package/dist/duplicates.js +313 -9
  50. package/dist/duplicates.js.map +1 -1
  51. package/dist/fix-engine.d.ts.map +1 -1
  52. package/dist/fix-engine.js +75 -1
  53. package/dist/fix-engine.js.map +1 -1
  54. package/dist/frameworks/dotnet.d.ts.map +1 -1
  55. package/dist/frameworks/dotnet.js +10 -11
  56. package/dist/frameworks/dotnet.js.map +1 -1
  57. package/dist/frameworks/go.d.ts.map +1 -1
  58. package/dist/frameworks/go.js +8 -4
  59. package/dist/frameworks/go.js.map +1 -1
  60. package/dist/frameworks/nextjs.d.ts.map +1 -1
  61. package/dist/frameworks/nextjs.js +8 -17
  62. package/dist/frameworks/nextjs.js.map +1 -1
  63. package/dist/frameworks/python.d.ts.map +1 -1
  64. package/dist/frameworks/python.js +5 -3
  65. package/dist/frameworks/python.js.map +1 -1
  66. package/dist/frameworks/rust.d.ts.map +1 -1
  67. package/dist/frameworks/rust.js +3 -3
  68. package/dist/frameworks/rust.js.map +1 -1
  69. package/dist/frameworks/unity.d.ts.map +1 -1
  70. package/dist/frameworks/unity.js +6 -5
  71. package/dist/frameworks/unity.js.map +1 -1
  72. package/dist/gitignore.d.ts +31 -2
  73. package/dist/gitignore.d.ts.map +1 -1
  74. package/dist/gitignore.js +33 -8
  75. package/dist/gitignore.js.map +1 -1
  76. package/dist/health-score.d.ts +15 -1
  77. package/dist/health-score.d.ts.map +1 -1
  78. package/dist/health-score.js +25 -2
  79. package/dist/health-score.js.map +1 -1
  80. package/dist/hooks-settings-detector.d.ts.map +1 -1
  81. package/dist/hooks-settings-detector.js +5 -1
  82. package/dist/hooks-settings-detector.js.map +1 -1
  83. package/dist/index.d.ts +10 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +16 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/known-paths.d.ts +82 -0
  88. package/dist/known-paths.d.ts.map +1 -0
  89. package/dist/known-paths.js +152 -0
  90. package/dist/known-paths.js.map +1 -0
  91. package/dist/makefile.d.ts.map +1 -1
  92. package/dist/makefile.js +17 -13
  93. package/dist/makefile.js.map +1 -1
  94. package/dist/manifest-consistency.d.ts +1 -1
  95. package/dist/manifest-consistency.d.ts.map +1 -1
  96. package/dist/manifest-consistency.js +18 -8
  97. package/dist/manifest-consistency.js.map +1 -1
  98. package/dist/markdown-fences.d.ts.map +1 -1
  99. package/dist/markdown-fences.js +7 -3
  100. package/dist/markdown-fences.js.map +1 -1
  101. package/dist/mcp-config-detector.d.ts.map +1 -1
  102. package/dist/mcp-config-detector.js +5 -1
  103. package/dist/mcp-config-detector.js.map +1 -1
  104. package/dist/project-type.d.ts +2 -1
  105. package/dist/project-type.d.ts.map +1 -1
  106. package/dist/project-type.js +36 -48
  107. package/dist/project-type.js.map +1 -1
  108. package/dist/prompt-cache.d.ts.map +1 -1
  109. package/dist/prompt-cache.js +13 -2
  110. package/dist/prompt-cache.js.map +1 -1
  111. package/dist/provenance/check.d.ts +40 -0
  112. package/dist/provenance/check.d.ts.map +1 -0
  113. package/dist/provenance/check.js +157 -0
  114. package/dist/provenance/check.js.map +1 -0
  115. package/dist/provenance/index.d.ts +13 -0
  116. package/dist/provenance/index.d.ts.map +1 -0
  117. package/dist/provenance/index.js +21 -0
  118. package/dist/provenance/index.js.map +1 -0
  119. package/dist/provenance/instruction-advice.d.ts +3 -0
  120. package/dist/provenance/instruction-advice.d.ts.map +1 -0
  121. package/dist/provenance/instruction-advice.js +570 -0
  122. package/dist/provenance/instruction-advice.js.map +1 -0
  123. package/dist/provenance/repo-checks.d.ts +3 -0
  124. package/dist/provenance/repo-checks.d.ts.map +1 -0
  125. package/dist/provenance/repo-checks.js +644 -0
  126. package/dist/provenance/repo-checks.js.map +1 -0
  127. package/dist/provenance/tool-config.d.ts +3 -0
  128. package/dist/provenance/tool-config.d.ts.map +1 -0
  129. package/dist/provenance/tool-config.js +480 -0
  130. package/dist/provenance/tool-config.js.map +1 -0
  131. package/dist/provenance/types.d.ts +116 -0
  132. package/dist/provenance/types.d.ts.map +1 -0
  133. package/dist/provenance/types.js +17 -0
  134. package/dist/provenance/types.js.map +1 -0
  135. package/dist/repo-context.d.ts +9 -0
  136. package/dist/repo-context.d.ts.map +1 -1
  137. package/dist/repo-context.js +35 -41
  138. package/dist/repo-context.js.map +1 -1
  139. package/dist/repo-tree.d.ts +163 -9
  140. package/dist/repo-tree.d.ts.map +1 -1
  141. package/dist/repo-tree.js +226 -34
  142. package/dist/repo-tree.js.map +1 -1
  143. package/dist/report.d.ts.map +1 -1
  144. package/dist/report.js +6 -0
  145. package/dist/report.js.map +1 -1
  146. package/dist/sample-text.d.ts +36 -0
  147. package/dist/sample-text.d.ts.map +1 -0
  148. package/dist/sample-text.js +72 -0
  149. package/dist/sample-text.js.map +1 -0
  150. package/dist/sarif.d.ts +27 -0
  151. package/dist/sarif.d.ts.map +1 -0
  152. package/dist/sarif.js +357 -0
  153. package/dist/sarif.js.map +1 -0
  154. package/dist/scan.d.ts.map +1 -1
  155. package/dist/scan.js +8 -2
  156. package/dist/scan.js.map +1 -1
  157. package/dist/scanner.d.ts +4 -3
  158. package/dist/scanner.d.ts.map +1 -1
  159. package/dist/scanner.js +36 -77
  160. package/dist/scanner.js.map +1 -1
  161. package/dist/security-pack.d.ts.map +1 -1
  162. package/dist/security-pack.js +117 -35
  163. package/dist/security-pack.js.map +1 -1
  164. package/dist/skill-supply-chain.d.ts.map +1 -1
  165. package/dist/skill-supply-chain.js +29 -19
  166. package/dist/skill-supply-chain.js.map +1 -1
  167. package/dist/skills-detector.d.ts.map +1 -1
  168. package/dist/skills-detector.js +11 -3
  169. package/dist/skills-detector.js.map +1 -1
  170. package/dist/token-estimates.d.ts +42 -0
  171. package/dist/token-estimates.d.ts.map +1 -0
  172. package/dist/token-estimates.js +200 -0
  173. package/dist/token-estimates.js.map +1 -0
  174. package/dist/types.d.ts +99 -0
  175. package/dist/types.d.ts.map +1 -1
  176. package/dist/types.js.map +1 -1
  177. package/dist/workspace-manifests.d.ts +6 -0
  178. package/dist/workspace-manifests.d.ts.map +1 -1
  179. package/dist/workspace-manifests.js +13 -8
  180. package/dist/workspace-manifests.js.map +1 -1
  181. package/package.json +5 -2
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Text in an instruction file that is SAMPLE, not instruction, for the
3
+ * mechanical fix recipes (pcic-1ik0.4 review).
4
+ *
5
+ * A recipe that rewrites the document must leave alone what the document only
6
+ * shows or hides: an example inside a fenced block, an indented code block, a
7
+ * line in an HTML comment. Reporting such a reference is still worthwhile (a
8
+ * stale example is stale), rewriting it changes what the example says or edits
9
+ * text no reader sees. Fenced blocks and inline code spans are handled where
10
+ * the links are collected (markdown-fences.ts); this module covers the other
11
+ * two shapes.
12
+ *
13
+ * Both checks lean toward "sample": a missed edit costs a human a minute, a
14
+ * wrong automatic one lands in a stranger's repository.
15
+ */
16
+ import { scanFencedLines } from './markdown-fences.js';
17
+ /**
18
+ * `[start, end)` character ranges of every HTML comment; an unterminated one runs
19
+ * to the end. A `<!--` inside a fenced block or an inline code span is text ABOUT
20
+ * comments ("Comments start with `<!--`."), not a comment, and opens nothing.
21
+ */
22
+ export function htmlCommentRanges(content) {
23
+ const fence = scanFencedLines(content);
24
+ const ranges = [];
25
+ let lineStart = 0;
26
+ let resumeAt = 0;
27
+ content.split('\n').forEach((line, i) => {
28
+ if (fence[i]?.inFence !== true) {
29
+ for (let at = line.indexOf('<!--'); at !== -1; at = line.indexOf('<!--', at + 4)) {
30
+ const opener = lineStart + at;
31
+ if (opener < resumeAt)
32
+ continue; // inside the comment already open
33
+ if ((line.slice(0, at).match(/`/g)?.length ?? 0) % 2 === 1)
34
+ continue; // inside a code span
35
+ const close = content.indexOf('-->', opener + 4);
36
+ resumeAt = close === -1 ? content.length : close + 3;
37
+ ranges.push([opener, resumeAt]);
38
+ }
39
+ }
40
+ lineStart += line.length + 1;
41
+ });
42
+ return ranges;
43
+ }
44
+ export function inRanges(ranges, offset) {
45
+ return ranges.some(([start, end]) => offset >= start && offset < end);
46
+ }
47
+ /**
48
+ * `result[n - 1]` is true when line `n` is non-blank and indented four or more
49
+ * spaces or a tab. Markdown reads that as an indented code block, unless the line
50
+ * continues a list item; telling those apart needs the whole block structure, so
51
+ * every such line counts as code. Lines inside fenced blocks are not special-cased
52
+ * (callers already treat those as code).
53
+ */
54
+ export function indentedCodeLines(content) {
55
+ return content.split('\n').map((line) => /^(?: {4,}|\t)\S/.test(line));
56
+ }
57
+ /**
58
+ * `result[n - 1]` is true when any part of line `n` lies in an HTML comment.
59
+ * For a recipe that edits a whole line's text rather than a known offset.
60
+ */
61
+ export function htmlCommentLines(content) {
62
+ const ranges = htmlCommentRanges(content);
63
+ const flags = [];
64
+ let start = 0;
65
+ for (const line of content.split('\n')) {
66
+ const end = start + line.length;
67
+ flags.push(ranges.some(([a, b]) => a < end + 1 && b > start));
68
+ start = end + 1;
69
+ }
70
+ return flags;
71
+ }
72
+ //# sourceMappingURL=sample-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-text.js","sourceRoot":"","sources":["../src/sample-text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * SARIF 2.1.0 report generation for PromptCI scan results (pcic-aq2f).
3
+ *
4
+ * Competing tools already emit SARIF, which lands their findings in GitHub's
5
+ * Security tab for teams that gate merges on code scanning; PromptCI findings
6
+ * otherwise only show up in its own markdown/JSON report. This module maps a
7
+ * `ScanReport` onto a SARIF log without changing anything about how findings
8
+ * are detected or scored.
9
+ *
10
+ * Deterministic like the rest of the report pipeline (see report.ts /
11
+ * AGENTS.md): no timestamps, no run-invocation metadata, stable ordering.
12
+ */
13
+ import type { ScanReport } from './types.js';
14
+ /**
15
+ * Serialize a ScanReport to a SARIF 2.1.0 log.
16
+ *
17
+ * `toolVersion` is threaded in by the caller (the CLI's own `--version`
18
+ * value) rather than read from a package.json here, so this module stays
19
+ * decoupled from any particular package's on-disk layout.
20
+ *
21
+ * Active issues and suppressed issues are both included (suppressed ones
22
+ * carry a `suppressions` entry — see SUPPRESSED_JUSTIFICATION above); ruleId
23
+ * is the issue's `category`, the only detector/category identifier that is
24
+ * both present on every issue and stable across detector refactors.
25
+ */
26
+ export declare function generateSarifReport(report: ScanReport, toolVersion: string, pretty?: boolean): string;
27
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAA+C,UAAU,EAAE,MAAM,YAAY,CAAC;AAyX1F;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,UAAO,GAAG,MAAM,CAoDlG"}
package/dist/sarif.js ADDED
@@ -0,0 +1,357 @@
1
+ /**
2
+ * SARIF 2.1.0 report generation for PromptCI scan results (pcic-aq2f).
3
+ *
4
+ * Competing tools already emit SARIF, which lands their findings in GitHub's
5
+ * Security tab for teams that gate merges on code scanning; PromptCI findings
6
+ * otherwise only show up in its own markdown/JSON report. This module maps a
7
+ * `ScanReport` onto a SARIF log without changing anything about how findings
8
+ * are detected or scored.
9
+ *
10
+ * Deterministic like the rest of the report pipeline (see report.ts /
11
+ * AGENTS.md): no timestamps, no run-invocation metadata, stable ordering.
12
+ */
13
+ import * as nodePath from 'node:path';
14
+ import { INSTRUCTION_FILE_TYPES } from './types.js';
15
+ import { computeFingerprint } from './baseline.js';
16
+ const PROMPTCI_REPO_URL = 'https://github.com/SeriousGeese/PromptCI';
17
+ // No per-category anchor exists in the README today; point every rule at the
18
+ // section that documents what gets detected until one does.
19
+ const DETECTOR_REFERENCE_URL = `${PROMPTCI_REPO_URL}#what-gets-detected`;
20
+ const SARIF_SCHEMA_URI = 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/sarif-2.1/schema/sarif-schema-2.1.0.json';
21
+ /**
22
+ * Severity → SARIF level mapping (pcic-aq2f judgment call).
23
+ *
24
+ * GitHub's code-scanning UI only recognizes three levels, and `error` is the
25
+ * only one that can block a PR by default. PromptCI's two "this is a real
26
+ * problem" tiers (`critical`, `high`) both map to `error` so either one is
27
+ * visible to a security-tab gate; `warning` keeps its name; `info` (the
28
+ * lowest, advisory tier) maps to SARIF's `note`, its "worth seeing, not a
29
+ * problem" level.
30
+ */
31
+ const SEVERITY_TO_SARIF_LEVEL = {
32
+ critical: 'error',
33
+ high: 'error',
34
+ warning: 'warning',
35
+ info: 'note',
36
+ };
37
+ const CATEGORY_INFO = {
38
+ duplicate: {
39
+ name: 'Duplicate instruction content',
40
+ shortDescription: 'Repeated or near-identical guidance across sections or files.',
41
+ defaultLevel: 'warning',
42
+ },
43
+ conflict: {
44
+ name: 'Conflicting directives',
45
+ shortDescription: 'Contradictory instructions, versions, or competing framework/tech choices.',
46
+ defaultLevel: 'error',
47
+ },
48
+ context_bloat: {
49
+ name: 'Context bloat',
50
+ shortDescription: 'Instruction files exceeding size or token-budget thresholds.',
51
+ defaultLevel: 'warning',
52
+ },
53
+ missing_context: {
54
+ name: 'Missing setup context',
55
+ shortDescription: 'Missing setup, validation, or project-specific guidance.',
56
+ defaultLevel: 'warning',
57
+ },
58
+ stale_instruction: {
59
+ name: 'Stale instructions',
60
+ shortDescription: 'Old years, dated TODOs, deprecated wording, or outdated versions.',
61
+ defaultLevel: 'warning',
62
+ },
63
+ vague_guidance: {
64
+ name: 'Vague guidance',
65
+ shortDescription: 'Guidance too vague for an agent or contributor to act on.',
66
+ defaultLevel: 'note',
67
+ },
68
+ structure: {
69
+ name: 'Structural issue',
70
+ shortDescription: 'Malformed suppression annotations or other structural problems.',
71
+ defaultLevel: 'warning',
72
+ },
73
+ command_validity: {
74
+ name: 'Invalid command reference',
75
+ shortDescription: 'Documented commands, scripts, or make targets that no longer exist.',
76
+ defaultLevel: 'warning',
77
+ },
78
+ agent_practices: {
79
+ name: 'Agent practice gap',
80
+ shortDescription: 'Gaps in agent-facing operational guidance.',
81
+ defaultLevel: 'note',
82
+ },
83
+ ai_config: {
84
+ name: 'AI setup config rot',
85
+ shortDescription: 'Agent Skills, subagents, hooks/settings, MCP servers, or editor rule files drifted from filesystem reality.',
86
+ defaultLevel: 'warning',
87
+ },
88
+ security: {
89
+ name: 'Security or privacy gap',
90
+ shortDescription: 'Security or privacy gaps in instruction guidance.',
91
+ defaultLevel: 'error',
92
+ },
93
+ custom: {
94
+ name: 'Custom rule finding',
95
+ shortDescription: "A finding from the repository's own .promptci/custom-rules.json rules.",
96
+ defaultLevel: 'warning',
97
+ },
98
+ };
99
+ /**
100
+ * Suppressed findings are included rather than omitted (pcic-aq2f judgment
101
+ * call): dropping them would make a repo's suppressions invisible in the
102
+ * Security tab, where a reviewer might reasonably want to see what was
103
+ * silenced and why. SARIF's `suppressions` field marks a result as
104
+ * suppressed — GitHub's SARIF documentation does not promise any particular
105
+ * handling of a `suppressions`-bearing result, so this is "marked suppressed
106
+ * in the SARIF," not a guarantee about how a given consumer displays it. The
107
+ * justification is generic because the inline `promptci-ignore` reason text
108
+ * is not threaded onto `PromptCiIssue` today.
109
+ */
110
+ const SUPPRESSED_JUSTIFICATION = "Suppressed via an inline `promptci-ignore` annotation in the scanned repository.";
111
+ /**
112
+ * A `ScanReport.repoPath`/finding path is produced by whatever machine ran
113
+ * the scan — a Windows checkout (`C:\git\repo`) or a POSIX one
114
+ * (`/home/runner/work/repo`) — and this module must handle either SHAPE
115
+ * regardless of which platform IT is running on (a repo scanned on Windows
116
+ * can still have its SARIF generated, or tested, on Linux CI and vice versa).
117
+ * `node:path`'s plain `path.relative`/`path.isAbsolute` bind to the CURRENT
118
+ * process's platform, so on Linux they treat a Windows-shaped path like
119
+ * `C:\git\repo\sub\CLAUDE.md` as just an opaque string with no recognized
120
+ * separators — `path.relative` between two such strings does not compute a
121
+ * real relative path, and the "is this outside the repo" check in
122
+ * `toRelativeUri` below then misfires. Detect the SHAPE of the input paths
123
+ * instead and pick `path.win32` or `path.posix` explicitly, independent of
124
+ * `process.platform`.
125
+ */
126
+ function isWindowsShapedPath(p) {
127
+ return /^[a-zA-Z]:[\\/]/.test(p) || p.includes('\\');
128
+ }
129
+ /** Platform-independent basename (see isWindowsShapedPath) for a single path. */
130
+ function basenameOf(p) {
131
+ return (isWindowsShapedPath(p) ? nodePath.win32 : nodePath.posix).basename(p);
132
+ }
133
+ /**
134
+ * Forward-slash, percent-encoded, repo-relative URI for a SARIF
135
+ * artifactLocation.uri — or null when `absPath` does not resolve inside
136
+ * `repoPath` at all (such a location is dropped rather than pointing outside
137
+ * the scanned tree). `relative()` can return a path that climbs out with a
138
+ * leading `..`, or (given an unrelated absolute path) something that is not
139
+ * relative at all; only those two cases mean "outside" — a real directory or
140
+ * file NAMED `..something` (e.g. `..hidden/x`) does not start with `..`
141
+ * followed by a separator (or equal `..` outright), so it is left alone.
142
+ */
143
+ function toRelativeUri(absPath, repoPath) {
144
+ // Platform-independent (see isWindowsShapedPath): either input looking
145
+ // Windows-shaped is enough to pick path.win32 for BOTH, since relative()
146
+ // needs a consistent separator convention across the two arguments.
147
+ const pathImpl = isWindowsShapedPath(repoPath) || isWindowsShapedPath(absPath) ? nodePath.win32 : nodePath.posix;
148
+ const rel = pathImpl.relative(repoPath, absPath);
149
+ if (rel === '..' || rel.startsWith(`..${pathImpl.sep}`) || pathImpl.isAbsolute(rel)) {
150
+ return null;
151
+ }
152
+ const posix = rel.split(pathImpl.sep).join('/');
153
+ // RFC 3986: each path SEGMENT is percent-encoded independently, so a
154
+ // literal '/' produced by encoding one segment can never be mistaken for a
155
+ // path separator, and characters like '#', '%', ' ', or non-ASCII bytes in
156
+ // a real filename round-trip into a valid uri-reference.
157
+ return posix
158
+ .split('/')
159
+ .map((segment) => encodeURIComponent(segment))
160
+ .join('/');
161
+ }
162
+ /** One SARIF location for `absPath`, or null if it falls outside the repo (see toRelativeUri). */
163
+ function buildOneLocation(absPath, rel, startLine, endLine) {
164
+ const uri = rel(absPath);
165
+ if (uri === null)
166
+ return null;
167
+ // A detector-supplied line number is always >= 1 in practice, but never
168
+ // invent a line (or trust a stray 0/negative one) for a result that has
169
+ // none — SARIF regions are 1-based, and a fabricated "line 1" would point a
170
+ // reviewer at the wrong text for what is really a file-level finding.
171
+ const region = startLine !== undefined && startLine >= 1
172
+ ? { startLine, ...(endLine !== undefined && endLine >= startLine ? { endLine } : {}) }
173
+ : undefined;
174
+ return {
175
+ physicalLocation: {
176
+ artifactLocation: { uri, uriBaseId: '%SRCROOT%' },
177
+ ...(region ? { region } : {}),
178
+ },
179
+ };
180
+ }
181
+ /**
182
+ * SARIF locations for one finding, plus whether a fallback location had to
183
+ * be substituted (pcic-aq2f #3/#12): a finding with no usable location — no
184
+ * `locations` entries (or none that resolve inside the repo), and no
185
+ * `filePaths` either (or none that resolve inside the repo) — would
186
+ * otherwise serialize to `locations: []`, which GitHub's code-scanning
187
+ * ingestion silently drops. Falling back to the repo's primary instruction
188
+ * file (whichever of AGENTS.md/CLAUDE.md the scan found first, else the
189
+ * first scanned instruction file) keeps the finding visible, with no region
190
+ * attached since the fallback file is not where the finding specifically is.
191
+ * When nothing was scanned at all, there is nothing to fall back to and the
192
+ * result legitimately carries no locations.
193
+ */
194
+ function buildLocations(issue, rel, fallbackAbsPath) {
195
+ const fromLocations = issue.locations
196
+ .map((loc) => buildOneLocation(loc.filePath, rel, loc.startLine, loc.endLine))
197
+ .filter((l) => l !== null);
198
+ if (fromLocations.length > 0)
199
+ return { locations: fromLocations, usedFallback: false };
200
+ const fromFilePaths = issue.filePaths
201
+ .map((fp) => buildOneLocation(fp, rel, undefined, undefined))
202
+ .filter((l) => l !== null);
203
+ if (fromFilePaths.length > 0)
204
+ return { locations: fromFilePaths, usedFallback: false };
205
+ if (fallbackAbsPath) {
206
+ const fallback = buildOneLocation(fallbackAbsPath, rel, undefined, undefined);
207
+ if (fallback)
208
+ return { locations: [fallback], usedFallback: true };
209
+ }
210
+ return { locations: [], usedFallback: false };
211
+ }
212
+ /**
213
+ * Title + recommendation, worded as cautiously as the issue itself already
214
+ * is. Falls back to the title when `summary` is somehow empty, so a result
215
+ * never serializes with blank message text. `fallbackNote`, when set,
216
+ * documents that `locations` points at the repo's primary instruction file
217
+ * rather than the finding's actual location (see buildLocations).
218
+ */
219
+ function buildMessageText(issue, fallbackNote) {
220
+ const summary = issue.summary.trim() || issue.title.trim();
221
+ const recommendation = issue.recommendation.trim();
222
+ const base = recommendation ? `${summary} Recommendation: ${recommendation}` : summary;
223
+ return fallbackNote ? `${base} ${fallbackNote}` : base;
224
+ }
225
+ /**
226
+ * Sort key used to order results deterministically: primary file, then
227
+ * primary line, then category, then the issue's own id — independent of
228
+ * detector run order. Out-of-repo locations/filePaths are excluded the same
229
+ * way buildLocations excludes them, so the key never diverges from where a
230
+ * result's own locations actually point.
231
+ */
232
+ function sortKey(issue, rel) {
233
+ const loc = issue.locations.find((l) => l.startLine !== undefined && rel(l.filePath) !== null) ??
234
+ issue.locations.find((l) => rel(l.filePath) !== null);
235
+ const file = loc ? rel(loc.filePath) : issue.filePaths.map(rel).find((p) => p !== null) ?? '';
236
+ const line = loc?.startLine ?? 0;
237
+ return [file, String(line).padStart(10, '0'), issue.category, issue.id].join('\u0000');
238
+ }
239
+ /**
240
+ * Ordinal (UTF-16 code-unit) string comparison, not `localeCompare`:
241
+ * `localeCompare`'s collation depends on the running engine's ICU data and
242
+ * the active locale, which is not guaranteed identical between the machine
243
+ * that runs this and CI's — the same input could sort differently and break
244
+ * the "identical reports produce byte-identical SARIF" guarantee. Plain
245
+ * `<`/`>` on strings compares UTF-16 code units and is the same everywhere
246
+ * Node runs.
247
+ */
248
+ function ordinalCompare(a, b) {
249
+ return a < b ? -1 : a > b ? 1 : 0;
250
+ }
251
+ /**
252
+ * `promptci/v1` is PromptCI's OWN stable-identity key (the same
253
+ * category+title+filePaths+evidence fingerprint `--baseline` already uses),
254
+ * not GitHub's `primaryLocationLineHash` — GitHub computes and uses that one
255
+ * itself. The fingerprint deliberately excludes line numbers, so two distinct
256
+ * findings of the same category/title/evidence (e.g. the same duplicate
257
+ * check firing on two different line ranges) can share a raw value; the
258
+ * caller's trailing `:N` (rawFingerprintWithSuffix) keeps their
259
+ * partialFingerprints distinct WITHIN this run without touching what makes
260
+ * two findings "the same" ACROSS runs.
261
+ */
262
+ function buildResult(issue, rel, rawFingerprintWithSuffix, ruleIndex, suppressed, fallbackAbsPath) {
263
+ const { locations, usedFallback } = buildLocations(issue, rel, fallbackAbsPath);
264
+ const fallbackNote = usedFallback && fallbackAbsPath
265
+ ? `(No specific location was recorded for this finding; pointing at ${basenameOf(fallbackAbsPath)} as the repository's primary instruction file.)`
266
+ : undefined;
267
+ const result = {
268
+ ruleId: issue.category,
269
+ ruleIndex,
270
+ level: SEVERITY_TO_SARIF_LEVEL[issue.severity],
271
+ message: { text: buildMessageText(issue, fallbackNote) },
272
+ locations,
273
+ partialFingerprints: { 'promptci/v1': rawFingerprintWithSuffix },
274
+ };
275
+ if (suppressed) {
276
+ result.suppressions = [{ kind: 'external', justification: SUPPRESSED_JUSTIFICATION }];
277
+ }
278
+ return result;
279
+ }
280
+ function buildRule(category) {
281
+ const info = CATEGORY_INFO[category];
282
+ return {
283
+ id: category,
284
+ name: info.name,
285
+ shortDescription: { text: info.shortDescription },
286
+ helpUri: DETECTOR_REFERENCE_URL,
287
+ defaultConfiguration: { level: info.defaultLevel },
288
+ };
289
+ }
290
+ /**
291
+ * Absolute path of the repo's "primary" instruction file, for buildLocations'
292
+ * fallback: whichever of AGENTS.md/CLAUDE.md was scanned first (scan order,
293
+ * not alphabetical), else the first scanned instruction-type file, else
294
+ * undefined when nothing was scanned at all.
295
+ */
296
+ function primaryInstructionFile(report) {
297
+ const scanned = report.filesScanned.filter((f) => f.aliasOf === undefined && INSTRUCTION_FILE_TYPES.has(f.fileType));
298
+ const primary = scanned.find((f) => {
299
+ const base = basenameOf(f.path).toLowerCase();
300
+ return base === 'agents.md' || base === 'claude.md';
301
+ });
302
+ return (primary ?? scanned[0])?.path;
303
+ }
304
+ /**
305
+ * Serialize a ScanReport to a SARIF 2.1.0 log.
306
+ *
307
+ * `toolVersion` is threaded in by the caller (the CLI's own `--version`
308
+ * value) rather than read from a package.json here, so this module stays
309
+ * decoupled from any particular package's on-disk layout.
310
+ *
311
+ * Active issues and suppressed issues are both included (suppressed ones
312
+ * carry a `suppressions` entry — see SUPPRESSED_JUSTIFICATION above); ruleId
313
+ * is the issue's `category`, the only detector/category identifier that is
314
+ * both present on every issue and stable across detector refactors.
315
+ */
316
+ export function generateSarifReport(report, toolVersion, pretty = true) {
317
+ const rel = (absPath) => toRelativeUri(absPath, report.repoPath);
318
+ const fallbackAbsPath = primaryInstructionFile(report);
319
+ const entries = [
320
+ ...report.issues.map((issue) => ({ issue, suppressed: false })),
321
+ ...(report.suppressedIssues ?? []).map((issue) => ({ issue, suppressed: true })),
322
+ ];
323
+ entries.sort((a, b) => ordinalCompare(sortKey(a.issue, rel), sortKey(b.issue, rel)));
324
+ const categoriesUsed = [...new Set(entries.map(({ issue }) => issue.category))].sort(ordinalCompare);
325
+ const rules = categoriesUsed.map((category) => buildRule(category));
326
+ const ruleIndexOf = new Map(categoriesUsed.map((category, i) => [category, i]));
327
+ // Raw (pre-suffix) fingerprints can collide within a single run — the
328
+ // fingerprint excludes line numbers — so track how many of each have been
329
+ // seen, in the already-established sort order, and give each occurrence a
330
+ // 0-based `:N` suffix (see buildResult).
331
+ const fingerprintOccurrence = new Map();
332
+ const results = entries.map(({ issue, suppressed }) => {
333
+ const rawFingerprint = computeFingerprint(issue, report.repoPath);
334
+ const suffix = fingerprintOccurrence.get(rawFingerprint) ?? 0;
335
+ fingerprintOccurrence.set(rawFingerprint, suffix + 1);
336
+ return buildResult(issue, rel, `${rawFingerprint}:${suffix}`, ruleIndexOf.get(issue.category), suppressed, fallbackAbsPath);
337
+ });
338
+ const log = {
339
+ $schema: SARIF_SCHEMA_URI,
340
+ version: '2.1.0',
341
+ runs: [
342
+ {
343
+ tool: {
344
+ driver: {
345
+ name: 'PromptCI',
346
+ version: toolVersion,
347
+ informationUri: PROMPTCI_REPO_URL,
348
+ rules,
349
+ },
350
+ },
351
+ results,
352
+ },
353
+ ],
354
+ };
355
+ return pretty ? JSON.stringify(log, null, 2) : JSON.stringify(log);
356
+ }
357
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,KAAK,EAAiB,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgCvE,wBAAsB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAwDhE"}
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,KAAK,EAAiB,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgCvE,wBAAsB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CA6DhE"}
package/dist/scan.js CHANGED
@@ -8,6 +8,7 @@ import { runDetectors } from './detectors.js';
8
8
  import { parseSuppressions, buildValidationIssues, applySuppressions } from './suppression.js';
9
9
  import { computeHealthScore, selectTopFixes } from './health-score.js';
10
10
  import { filterNewIssues } from './baseline.js';
11
+ import { annotateIssueTokens, computeAddressableTokens } from './token-estimates.js';
11
12
  import { SKILL_SUPPLY_CHAIN_TAG } from './skill-supply-chain.js';
12
13
  /**
13
14
  * Inline suppression, with one carve-out: a skill-supply-chain finding is never
@@ -44,7 +45,9 @@ export async function scan(input) {
44
45
  // Suppressed issues are excluded from health score and topFixes.
45
46
  const annotations = parseSuppressions(allScannedFiles);
46
47
  const allIssues = [...issues, ...buildValidationIssues(annotations)];
47
- const { active, suppressed } = applyScanSuppressions(allIssues, annotations, context);
48
+ const { active: activeRaw, suppressed: suppressedRaw } = applyScanSuppressions(allIssues, annotations, context);
49
+ const active = annotateIssueTokens(activeRaw, allScannedFiles, context.aliasFiles);
50
+ const suppressed = annotateIssueTokens(suppressedRaw, allScannedFiles, context.aliasFiles);
48
51
  const healthScore = computeHealthScore(active);
49
52
  const topFixes = selectTopFixes(active);
50
53
  let newIssues;
@@ -60,7 +63,10 @@ export async function scan(input) {
60
63
  repoPath: context.repoRoot,
61
64
  projectType: context.projectType,
62
65
  healthScore,
63
- metrics: context.metrics,
66
+ metrics: {
67
+ ...context.metrics,
68
+ estimatedAddressableTokens: computeAddressableTokens(active, context.files, context.aliasFiles),
69
+ },
64
70
  // Symlink aliases are inventory only (see RepoContext.aliasFiles): they are
65
71
  // not scanned, so they carry no annotations to parse above. Their content and
66
72
  // counts are zeroed so a consumer summing filesScanned does not count the
package/dist/scan.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
package/dist/scanner.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { InstructionFile, InstructionSection, ScanInput } from './types.js';
2
+ import { RepoTree } from './repo-tree.js';
2
3
  import type { GitSymlinkOracle } from './git-symlinks.js';
3
- export declare const MAX_FILE_SIZE: number;
4
- export declare const BINARY_CHECK_BYTES = 512;
4
+ import { MAX_FILE_SIZE, BINARY_CHECK_BYTES } from './discovery.js';
5
+ export { MAX_FILE_SIZE, BINARY_CHECK_BYTES };
5
6
  /**
6
7
  * Splits markdown into heading-delimited sections.
7
8
  *
@@ -58,6 +59,6 @@ export declare function foldTextSymlinks(files: InstructionFile[], aliases: Inst
58
59
  * folded into an alias of that file, so both platforms scan the same repo alike
59
60
  * (see {@link foldTextSymlinks}).
60
61
  */
61
- export declare function scanFilesWithAliases(input: ScanInput): Promise<ScanFilesResult>;
62
+ export declare function scanFilesWithAliases(input: ScanInput, tree?: RepoTree): Promise<ScanFilesResult>;
62
63
  export declare function scanFiles(input: ScanInput): Promise<InstructionFile[]>;
63
64
  //# sourceMappingURL=scanner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAY,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AA8D1D,eAAO,MAAM,aAAa,QAAa,CAAC;AACxC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAiEtC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,kBAAkB,EAAE,CAuDtB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAMhD;AAyBD;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AA4HvF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,gBAAgB,GAAG,eAAe,CAgChI;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,CAiGrF;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5E"}
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAY,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI3F,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAgD,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAoBjH,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC;AAiE7C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,kBAAkB,EAAE,CAuDtB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAMhD;AAkBD;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AA4HvF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,gBAAgB,GAAG,eAAe,CAgChI;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC,CAuGtG;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAE5E"}