@vyuhlabs/dxkit 2.4.8 → 2.5.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 (243) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/README.md +360 -439
  3. package/dist/analyzers/security/aggregator.d.ts.map +1 -1
  4. package/dist/analyzers/security/aggregator.js +4 -46
  5. package/dist/analyzers/security/aggregator.js.map +1 -1
  6. package/dist/analyzers/tools/fingerprint.d.ts +91 -26
  7. package/dist/analyzers/tools/fingerprint.d.ts.map +1 -1
  8. package/dist/analyzers/tools/fingerprint.js +111 -22
  9. package/dist/analyzers/tools/fingerprint.js.map +1 -1
  10. package/dist/analyzers/tools/generic.d.ts.map +1 -1
  11. package/dist/analyzers/tools/generic.js +6 -1
  12. package/dist/analyzers/tools/generic.js.map +1 -1
  13. package/dist/analyzers/tools/gitleaks.d.ts +24 -1
  14. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
  15. package/dist/analyzers/tools/gitleaks.js +20 -11
  16. package/dist/analyzers/tools/gitleaks.js.map +1 -1
  17. package/dist/analyzers/types.d.ts +6 -4
  18. package/dist/analyzers/types.d.ts.map +1 -1
  19. package/dist/baseline/baseline-file.d.ts +104 -0
  20. package/dist/baseline/baseline-file.d.ts.map +1 -0
  21. package/dist/baseline/baseline-file.js +110 -0
  22. package/dist/baseline/baseline-file.js.map +1 -0
  23. package/dist/baseline/check-renderers.d.ts +108 -0
  24. package/dist/baseline/check-renderers.d.ts.map +1 -0
  25. package/dist/baseline/check-renderers.js +379 -0
  26. package/dist/baseline/check-renderers.js.map +1 -0
  27. package/dist/baseline/check.d.ts +127 -0
  28. package/dist/baseline/check.d.ts.map +1 -0
  29. package/dist/baseline/check.js +462 -0
  30. package/dist/baseline/check.js.map +1 -0
  31. package/dist/baseline/content-hash.d.ts +83 -0
  32. package/dist/baseline/content-hash.d.ts.map +1 -0
  33. package/dist/baseline/content-hash.js +131 -0
  34. package/dist/baseline/content-hash.js.map +1 -0
  35. package/dist/baseline/create.d.ts +96 -0
  36. package/dist/baseline/create.d.ts.map +1 -0
  37. package/dist/baseline/create.js +339 -0
  38. package/dist/baseline/create.js.map +1 -0
  39. package/dist/baseline/entry-to-located.d.ts +35 -0
  40. package/dist/baseline/entry-to-located.d.ts.map +1 -0
  41. package/dist/baseline/entry-to-located.js +72 -0
  42. package/dist/baseline/entry-to-located.js.map +1 -0
  43. package/dist/baseline/finding-identity.d.ts +47 -0
  44. package/dist/baseline/finding-identity.d.ts.map +1 -0
  45. package/dist/baseline/finding-identity.js +292 -0
  46. package/dist/baseline/finding-identity.js.map +1 -0
  47. package/dist/baseline/git-aware-match.d.ts +146 -0
  48. package/dist/baseline/git-aware-match.d.ts.map +1 -0
  49. package/dist/baseline/git-aware-match.js +439 -0
  50. package/dist/baseline/git-aware-match.js.map +1 -0
  51. package/dist/baseline/policy.d.ts +171 -0
  52. package/dist/baseline/policy.d.ts.map +1 -0
  53. package/dist/baseline/policy.js +206 -0
  54. package/dist/baseline/policy.js.map +1 -0
  55. package/dist/baseline/producers/health.d.ts +30 -0
  56. package/dist/baseline/producers/health.d.ts.map +1 -0
  57. package/dist/baseline/producers/health.js +42 -0
  58. package/dist/baseline/producers/health.js.map +1 -0
  59. package/dist/baseline/producers/index.d.ts +164 -0
  60. package/dist/baseline/producers/index.d.ts.map +1 -0
  61. package/dist/baseline/producers/index.js +200 -0
  62. package/dist/baseline/producers/index.js.map +1 -0
  63. package/dist/baseline/producers/licenses.d.ts +23 -0
  64. package/dist/baseline/producers/licenses.d.ts.map +1 -0
  65. package/dist/baseline/producers/licenses.js +46 -0
  66. package/dist/baseline/producers/licenses.js.map +1 -0
  67. package/dist/baseline/producers/quality.d.ts +39 -0
  68. package/dist/baseline/producers/quality.d.ts.map +1 -0
  69. package/dist/baseline/producers/quality.js +84 -0
  70. package/dist/baseline/producers/quality.js.map +1 -0
  71. package/dist/baseline/producers/secret-hmac.d.ts +45 -0
  72. package/dist/baseline/producers/secret-hmac.d.ts.map +1 -0
  73. package/dist/baseline/producers/secret-hmac.js +70 -0
  74. package/dist/baseline/producers/secret-hmac.js.map +1 -0
  75. package/dist/baseline/producers/security.d.ts +59 -0
  76. package/dist/baseline/producers/security.d.ts.map +1 -0
  77. package/dist/baseline/producers/security.js +135 -0
  78. package/dist/baseline/producers/security.js.map +1 -0
  79. package/dist/baseline/producers/tests.d.ts +36 -0
  80. package/dist/baseline/producers/tests.d.ts.map +1 -0
  81. package/dist/baseline/producers/tests.js +69 -0
  82. package/dist/baseline/producers/tests.js.map +1 -0
  83. package/dist/baseline/salt.d.ts +45 -0
  84. package/dist/baseline/salt.d.ts.map +1 -0
  85. package/dist/baseline/salt.js +113 -0
  86. package/dist/baseline/salt.js.map +1 -0
  87. package/dist/baseline/show.d.ts +79 -0
  88. package/dist/baseline/show.d.ts.map +1 -0
  89. package/dist/baseline/show.js +233 -0
  90. package/dist/baseline/show.js.map +1 -0
  91. package/dist/baseline/types.d.ts +482 -0
  92. package/dist/baseline/types.d.ts.map +1 -0
  93. package/dist/baseline/types.js +53 -0
  94. package/dist/baseline/types.js.map +1 -0
  95. package/dist/cli.d.ts.map +1 -1
  96. package/dist/cli.js +360 -81
  97. package/dist/cli.js.map +1 -1
  98. package/dist/codebase-scanner.d.ts.map +1 -1
  99. package/dist/codebase-scanner.js +0 -1
  100. package/dist/codebase-scanner.js.map +1 -1
  101. package/dist/constants.d.ts.map +1 -1
  102. package/dist/constants.js +0 -4
  103. package/dist/constants.js.map +1 -1
  104. package/dist/doctor.d.ts.map +1 -1
  105. package/dist/doctor.js +22 -25
  106. package/dist/doctor.js.map +1 -1
  107. package/dist/fail-on.d.ts +84 -0
  108. package/dist/fail-on.d.ts.map +1 -0
  109. package/dist/fail-on.js +128 -0
  110. package/dist/fail-on.js.map +1 -0
  111. package/dist/generator.d.ts.map +1 -1
  112. package/dist/generator.js +2 -141
  113. package/dist/generator.js.map +1 -1
  114. package/dist/languages/csharp.d.ts.map +1 -1
  115. package/dist/languages/csharp.js +0 -9
  116. package/dist/languages/csharp.js.map +1 -1
  117. package/dist/languages/go.d.ts.map +1 -1
  118. package/dist/languages/go.js +0 -15
  119. package/dist/languages/go.js.map +1 -1
  120. package/dist/languages/index.d.ts +1 -1
  121. package/dist/languages/index.d.ts.map +1 -1
  122. package/dist/languages/index.js.map +1 -1
  123. package/dist/languages/java.d.ts.map +1 -1
  124. package/dist/languages/java.js +0 -6
  125. package/dist/languages/java.js.map +1 -1
  126. package/dist/languages/kotlin.d.ts.map +1 -1
  127. package/dist/languages/kotlin.js +0 -11
  128. package/dist/languages/kotlin.js.map +1 -1
  129. package/dist/languages/python.d.ts.map +1 -1
  130. package/dist/languages/python.js +0 -15
  131. package/dist/languages/python.js.map +1 -1
  132. package/dist/languages/ruby.d.ts.map +1 -1
  133. package/dist/languages/ruby.js +0 -6
  134. package/dist/languages/ruby.js.map +1 -1
  135. package/dist/languages/rust.d.ts.map +1 -1
  136. package/dist/languages/rust.js +0 -4
  137. package/dist/languages/rust.js.map +1 -1
  138. package/dist/languages/types.d.ts +2 -28
  139. package/dist/languages/types.d.ts.map +1 -1
  140. package/dist/languages/typescript.d.ts.map +1 -1
  141. package/dist/languages/typescript.js +26 -4
  142. package/dist/languages/typescript.js.map +1 -1
  143. package/dist/lib.d.ts +2 -3
  144. package/dist/lib.d.ts.map +1 -1
  145. package/dist/lib.js +3 -6
  146. package/dist/lib.js.map +1 -1
  147. package/dist/prompts.d.ts.map +1 -1
  148. package/dist/prompts.js +0 -10
  149. package/dist/prompts.js.map +1 -1
  150. package/dist/report-schema.d.ts +42 -0
  151. package/dist/report-schema.d.ts.map +1 -0
  152. package/dist/report-schema.js +54 -0
  153. package/dist/report-schema.js.map +1 -0
  154. package/dist/ship-installers.d.ts +106 -0
  155. package/dist/ship-installers.d.ts.map +1 -0
  156. package/dist/ship-installers.js +415 -0
  157. package/dist/ship-installers.js.map +1 -0
  158. package/dist/types.d.ts +0 -4
  159. package/dist/types.d.ts.map +1 -1
  160. package/dist/update.d.ts.map +1 -1
  161. package/dist/update.js +0 -4
  162. package/dist/update.js.map +1 -1
  163. package/package.json +17 -11
  164. package/templates/.claude/agents/onboarding.md +5 -4
  165. package/templates/.claude/agents-available/codebase-explorer.md +1 -1
  166. package/templates/.claude/agents-available/debugger.md +2 -2
  167. package/templates/.claude/agents-available/health-auditor.md +2 -2
  168. package/templates/.claude/commands/doctor.md +20 -12
  169. package/templates/.claude/skills/build/SKILL.md.template +22 -30
  170. package/templates/.claude/skills/deploy/SKILL.md.template +5 -25
  171. package/templates/.claude/skills/doctor/SKILL.md +24 -47
  172. package/templates/.claude/skills/gcloud/SKILL.md +5 -5
  173. package/templates/.claude/skills/learned/SKILL.md +1 -1
  174. package/templates/.claude/skills/pulumi/SKILL.md +2 -2
  175. package/templates/.claude/skills/quality/SKILL.md.template +4 -23
  176. package/templates/.claude/skills/review/SKILL.md.template +4 -3
  177. package/templates/.claude/skills/scaffold/SKILL.md.template +5 -15
  178. package/templates/.claude/skills/secrets/SKILL.md +20 -21
  179. package/templates/.claude/skills/session/SKILL.md +20 -31
  180. package/templates/.claude/skills/test/SKILL.md.template +1 -7
  181. package/templates/.devcontainer/devcontainer.json +81 -0
  182. package/templates/.devcontainer/install-agent-clis.sh +42 -0
  183. package/templates/.devcontainer/post-create.sh +67 -0
  184. package/templates/.githooks/pre-commit +55 -0
  185. package/templates/.githooks/pre-push +63 -0
  186. package/templates/.github/workflows/dxkit-baseline-refresh.yml +78 -0
  187. package/templates/.github/workflows/dxkit-guardrails.yml +98 -0
  188. package/templates/CLAUDE.md.template +62 -196
  189. package/dist/project-yaml.d.ts +0 -13
  190. package/dist/project-yaml.d.ts.map +0 -1
  191. package/dist/project-yaml.js +0 -188
  192. package/dist/project-yaml.js.map +0 -1
  193. package/templates/.ai/README.md +0 -117
  194. package/templates/.ai/prompts/execution-prompt.md +0 -9
  195. package/templates/.ai/prompts/planning-prompt.md +0 -18
  196. package/templates/.ai/prompts/session-end-template.md +0 -182
  197. package/templates/.ai/prompts/session-end.md +0 -132
  198. package/templates/.ai/prompts/session-start.md +0 -109
  199. package/templates/.ai/prompts/step-by-step.md +0 -113
  200. package/templates/.ai/sessions/.gitkeep +0 -0
  201. package/templates/.claude/commands/setup-pr-review.md +0 -72
  202. package/templates/.devcontainer/Dockerfile.dev.template +0 -89
  203. package/templates/.devcontainer/devcontainer.json.template +0 -184
  204. package/templates/.devcontainer/docker-compose.yml.template +0 -105
  205. package/templates/.devcontainer/init-scripts/01-init.sql.template +0 -12
  206. package/templates/.devcontainer/post-create.sh.template +0 -298
  207. package/templates/.github/workflows/ci.yml.template +0 -399
  208. package/templates/.github/workflows/quality.yml.template +0 -376
  209. package/templates/.pre-commit-config.yaml.template +0 -106
  210. package/templates/.project/config/edit_config.py +0 -275
  211. package/templates/.project/config/project_config.py +0 -894
  212. package/templates/.project/scripts/codegen/generate-all.sh +0 -20
  213. package/templates/.project/scripts/codegen/validate-all.sh +0 -17
  214. package/templates/.project/scripts/docs/generate-all.sh +0 -30
  215. package/templates/.project/scripts/docs/serve.sh +0 -20
  216. package/templates/.project/scripts/quality/fix-all.sh +0 -138
  217. package/templates/.project/scripts/quality/lint-go.sh +0 -34
  218. package/templates/.project/scripts/quality/lint-python.sh +0 -54
  219. package/templates/.project/scripts/quality/run-all.sh +0 -497
  220. package/templates/.project/scripts/session/commit.sh +0 -70
  221. package/templates/.project/scripts/session/create-pr.sh +0 -165
  222. package/templates/.project/scripts/session/end.sh +0 -207
  223. package/templates/.project/scripts/session/start.sh +0 -233
  224. package/templates/.project/scripts/setup/doctor.sh +0 -404
  225. package/templates/.project/scripts/setup/interactive-setup.sh +0 -585
  226. package/templates/.project/scripts/sync/sync-template.sh +0 -328
  227. package/templates/.project/scripts/test/run-all.sh +0 -179
  228. package/templates/.project/scripts/test/run-quick.sh +0 -25
  229. package/templates/Makefile +0 -514
  230. package/templates/config/versions.yaml +0 -57
  231. package/templates/configs/go/.golangci.yml.template +0 -172
  232. package/templates/configs/go/go.mod.template +0 -15
  233. package/templates/configs/java/README.md +0 -6
  234. package/templates/configs/kotlin/README.md +0 -6
  235. package/templates/configs/node/package.json.template +0 -67
  236. package/templates/configs/node/tsconfig.json.template +0 -53
  237. package/templates/configs/python/pyproject.toml.template +0 -92
  238. package/templates/configs/python/pytest.ini.template +0 -64
  239. package/templates/configs/python/ruff.toml.template +0 -79
  240. package/templates/configs/ruby/README.md +0 -6
  241. package/templates/configs/rust/Cargo.toml.template +0 -51
  242. package/templates/configs/shared/.editorconfig +0 -67
  243. package/templates/scripts/validate-templates.sh +0 -449
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ /**
3
+ * Brownfield policy + status classifier.
4
+ *
5
+ * The matcher in `git-aware-match.ts` emits raw `MatchPair`s with one
6
+ * of four statuses (persisted / relocated / added / removed) plus a
7
+ * confidence score and structured reasons. The guardrail check needs
8
+ * a richer taxonomy — the difference between "developer introduced
9
+ * a new finding" and "a scanner update surfaced a finding that was
10
+ * always there" matters enormously for whether to block a PR.
11
+ *
12
+ * This module is the bridge. It takes a `MatchPair` plus optional
13
+ * context (severity, scanner-version diff, config diff) and a
14
+ * `BrownfieldPolicy`, then emits a `ClassifyResult` carrying the
15
+ * post-policy `FindingStatus`, the block/warn verdict, and the
16
+ * composed reason chain.
17
+ *
18
+ * Pure module — no I/O, deterministic over its inputs.
19
+ *
20
+ * Producer wiring note: today's classifier emits a subset of the full
21
+ * `FindingStatus` taxonomy. Reservations for `probable_existing`,
22
+ * `newly_detected`, and `fixed` are declared in the type space so
23
+ * Phase 3's baseline-metadata work can light them up incrementally
24
+ * without re-shaping consumer code.
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.DEFAULT_BROWNFIELD_POLICY = void 0;
28
+ exports.classify = classify;
29
+ exports.classifyAll = classifyAll;
30
+ /**
31
+ * Default brownfield policy. Captures the conservative posture from
32
+ * the agentic-brownfield strategy: block only on high-confidence new
33
+ * regressions; warn on the categories that suggest a problem might
34
+ * be real but might also be drift; legacy debt is permitted.
35
+ *
36
+ * Confidence thresholds: secrets + critical security demand a tight
37
+ * confidence threshold (a low-confidence persisted secret pairing
38
+ * gets demoted to uncertain and warned, not blocked). Lower-severity
39
+ * findings can pair on weaker signal because the cost of a false
40
+ * "secret is new" event is much higher than a false "TODO is new."
41
+ */
42
+ exports.DEFAULT_BROWNFIELD_POLICY = Object.freeze({
43
+ mode: 'brownfield',
44
+ block: Object.freeze(['added']),
45
+ warn: Object.freeze([
46
+ 'probable_existing',
47
+ 'newly_detected',
48
+ 'tooling_drift',
49
+ 'config_drift',
50
+ 'uncertain',
51
+ ]),
52
+ confidence: Object.freeze({
53
+ critical: 0.75,
54
+ high: 0.8,
55
+ medium: 0.85,
56
+ low: 0.9,
57
+ }),
58
+ blockRules: Object.freeze({
59
+ newSecret: true,
60
+ newCriticalSecurity: true,
61
+ newHighSecurity: true,
62
+ newCriticalDependencyVulnerability: true,
63
+ newHighReachableDependencyVulnerability: true,
64
+ newUntestedChangedSource: true,
65
+ newSevereQualityIssueInChangedFiles: true,
66
+ }),
67
+ addedRequiresChangedLines: Object.freeze(['code', 'hygiene']),
68
+ });
69
+ /**
70
+ * Classify one match pair against a brownfield policy.
71
+ *
72
+ * Pipeline:
73
+ * 1. Start with the matcher's `pair.status` as the candidate
74
+ * `FindingStatus`.
75
+ * 2. For `added`: check drift context. Scanner-version drift wins
76
+ * (more specific signal) over config drift; both demote to
77
+ * drift-bucket statuses regardless of severity.
78
+ * 3. For `persisted` / `relocated`: check confidence against the
79
+ * per-severity threshold. Below threshold demotes to
80
+ * `'uncertain'`.
81
+ * 4. Apply block-rule overrides: if a block-rule fires for this
82
+ * kind+severity combination AND the candidate status is
83
+ * `'added'`, the result blocks even if `'added'` weren't in the
84
+ * policy's block list.
85
+ * 5. Apply the policy's `block` / `warn` membership to the final
86
+ * status to produce the booleans.
87
+ */
88
+ function classify(pair, policy = exports.DEFAULT_BROWNFIELD_POLICY, context = {}) {
89
+ let status = pair.status;
90
+ const reasons = [...pair.reasons];
91
+ // Step 2: drift context can reclassify 'added'.
92
+ if (status === 'added') {
93
+ if (context.scannerVersionDiffers) {
94
+ status = 'tooling_drift';
95
+ reasons.push({
96
+ code: 'tooling-drift',
97
+ detail: 'scanner or advisory-db version changed between runs',
98
+ });
99
+ }
100
+ else if (context.configDiffers) {
101
+ status = 'config_drift';
102
+ reasons.push({
103
+ code: 'config-drift',
104
+ detail: 'suppression or policy config changed between runs',
105
+ });
106
+ }
107
+ else if (context.kind &&
108
+ policy.addedRequiresChangedLines.includes(context.kind) &&
109
+ context.overlapsChangedLines === false) {
110
+ // Scanner-wobble demotion: an `added` finding from a high-
111
+ // wobble scanner (semgrep code, grep-based hygiene) that
112
+ // sits outside the diff's changed lines is more likely a
113
+ // baseline gap than a real regression. Demote to `uncertain`
114
+ // (warn). The block-rules below still fire for findings the
115
+ // diff actually touched.
116
+ status = 'uncertain';
117
+ reasons.push({
118
+ code: 'unchanged-lines',
119
+ detail: `${context.kind} finding outside diff hunks — demoted from added to uncertain (likely scanner wobble, not a developer-introduced regression)`,
120
+ });
121
+ }
122
+ }
123
+ // Step 3: confidence demotion for persisted/relocated pairs.
124
+ if (status === 'persisted' || status === 'relocated') {
125
+ const threshold = context.severity
126
+ ? policy.confidence[context.severity]
127
+ : Math.min(...Object.values(policy.confidence));
128
+ if (pair.confidence < threshold) {
129
+ reasons.push({
130
+ code: 'low-confidence',
131
+ detail: `match confidence ${pair.confidence.toFixed(2)} below threshold ${threshold.toFixed(2)}` +
132
+ (context.severity ? ` for severity ${context.severity}` : ''),
133
+ });
134
+ status = 'uncertain';
135
+ }
136
+ }
137
+ // Step 4: block-rule overrides for newly-added findings.
138
+ const blockRuleHit = evaluateBlockRules(status, policy.blockRules, context);
139
+ if (blockRuleHit) {
140
+ reasons.push({
141
+ code: 'block-rule',
142
+ detail: `policy block-rule fired: ${blockRuleHit}`,
143
+ });
144
+ }
145
+ // Step 5: policy block/warn membership.
146
+ const blocks = blockRuleHit !== null || policy.block.includes(status);
147
+ const warns = policy.warn.includes(status);
148
+ return { status, blocks, warns, reasons };
149
+ }
150
+ /**
151
+ * Check whether any block-rule fires for the given classified pair.
152
+ * Returns the matching rule's name (for reason rendering) or null
153
+ * when no rule fires.
154
+ *
155
+ * Block-rules only apply to `added` status — they exist to escalate
156
+ * specific kinds of new findings beyond the generic policy. A
157
+ * `tooling_drift` reclassification means the `added` status is gone
158
+ * and the block-rule no longer applies.
159
+ */
160
+ function evaluateBlockRules(status, rules, context) {
161
+ if (status !== 'added')
162
+ return null;
163
+ if (rules.newSecret && context.kind === 'secret')
164
+ return 'newSecret';
165
+ if (rules.newCriticalSecurity && context.kind === 'code' && context.severity === 'critical') {
166
+ return 'newCriticalSecurity';
167
+ }
168
+ if (rules.newHighSecurity && context.kind === 'code' && context.severity === 'high') {
169
+ return 'newHighSecurity';
170
+ }
171
+ if (rules.newCriticalDependencyVulnerability &&
172
+ context.kind === 'dep-vuln' &&
173
+ context.severity === 'critical') {
174
+ return 'newCriticalDependencyVulnerability';
175
+ }
176
+ if (rules.newHighReachableDependencyVulnerability &&
177
+ context.kind === 'dep-vuln' &&
178
+ context.severity === 'high' &&
179
+ context.reachable === true) {
180
+ return 'newHighReachableDependencyVulnerability';
181
+ }
182
+ if (rules.newUntestedChangedSource &&
183
+ context.kind === 'test-gap' &&
184
+ context.overlapsChangedLines === true) {
185
+ return 'newUntestedChangedSource';
186
+ }
187
+ if (rules.newSevereQualityIssueInChangedFiles &&
188
+ (context.kind === 'code' || context.kind === 'hygiene') &&
189
+ (context.severity === 'critical' || context.severity === 'high') &&
190
+ context.overlapsChangedLines === true) {
191
+ return 'newSevereQualityIssueInChangedFiles';
192
+ }
193
+ return null;
194
+ }
195
+ /**
196
+ * Convenience: classify every pair in a match result against the
197
+ * same policy. Returns an array aligned with the input pair order
198
+ * so callers can render side-by-side. Per-pair context (severity,
199
+ * kind, drift flags) is supplied via the optional `contextFor`
200
+ * callback — callers map their `FindingId` back to the producer
201
+ * envelope to fill in the fields the classifier reads.
202
+ */
203
+ function classifyAll(pairs, policy = exports.DEFAULT_BROWNFIELD_POLICY, contextFor = () => ({})) {
204
+ return pairs.map((pair) => classify(pair, policy, contextFor(pair)));
205
+ }
206
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/baseline/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Health → baseline-entry producer.
3
+ *
4
+ * One kind today: `large-file` — source files whose line count
5
+ * exceeds the canonical large-file threshold (500 lines). Identity
6
+ * is per-file: the binary "this file is over the threshold" signal
7
+ * is what guardrails act on. Crossing back under the threshold
8
+ * removes the identity; crossing back over re-adds it.
9
+ *
10
+ * Producer reads from `HealthMetrics.largestFiles`, which is already
11
+ * an `Array<{ path, lines }>` produced by the canonical generic-
12
+ * metrics gather. The 500-line threshold matches the
13
+ * `filesOver500Lines` aggregate the same gather emits — keeping the
14
+ * two in sync ensures the per-file identity set sums to the
15
+ * aggregate count.
16
+ */
17
+ import type { BaselineEntry } from '../types';
18
+ import type { HealthMetrics } from '../../analyzers/types';
19
+ /** Canonical large-file threshold — file is "too large" at strictly
20
+ * more than this many lines. Mirror of the constant the generic-
21
+ * metrics gather already uses; documented as part of the file-size
22
+ * signal in the CLAUDE.md maintainability surface. */
23
+ export declare const LARGE_FILE_THRESHOLD_LINES = 500;
24
+ /**
25
+ * Build `large-file` entries from the canonical `HealthMetrics`.
26
+ * Files with `lines <= threshold` are skipped so the identity set
27
+ * matches the user-facing aggregate count.
28
+ */
29
+ export declare function largeFilesToBaselineEntries(metrics: HealthMetrics): BaselineEntry[];
30
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../src/baseline/producers/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,aAAa,EAA0B,MAAM,UAAU,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;uDAGuD;AACvD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,EAAE,CAQnF"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * Health → baseline-entry producer.
4
+ *
5
+ * One kind today: `large-file` — source files whose line count
6
+ * exceeds the canonical large-file threshold (500 lines). Identity
7
+ * is per-file: the binary "this file is over the threshold" signal
8
+ * is what guardrails act on. Crossing back under the threshold
9
+ * removes the identity; crossing back over re-adds it.
10
+ *
11
+ * Producer reads from `HealthMetrics.largestFiles`, which is already
12
+ * an `Array<{ path, lines }>` produced by the canonical generic-
13
+ * metrics gather. The 500-line threshold matches the
14
+ * `filesOver500Lines` aggregate the same gather emits — keeping the
15
+ * two in sync ensures the per-file identity set sums to the
16
+ * aggregate count.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.LARGE_FILE_THRESHOLD_LINES = void 0;
20
+ exports.largeFilesToBaselineEntries = largeFilesToBaselineEntries;
21
+ const finding_identity_1 = require("../finding-identity");
22
+ /** Canonical large-file threshold — file is "too large" at strictly
23
+ * more than this many lines. Mirror of the constant the generic-
24
+ * metrics gather already uses; documented as part of the file-size
25
+ * signal in the CLAUDE.md maintainability surface. */
26
+ exports.LARGE_FILE_THRESHOLD_LINES = 500;
27
+ /**
28
+ * Build `large-file` entries from the canonical `HealthMetrics`.
29
+ * Files with `lines <= threshold` are skipped so the identity set
30
+ * matches the user-facing aggregate count.
31
+ */
32
+ function largeFilesToBaselineEntries(metrics) {
33
+ const out = [];
34
+ for (const f of metrics.largestFiles) {
35
+ if (f.lines <= exports.LARGE_FILE_THRESHOLD_LINES)
36
+ continue;
37
+ const input = { kind: 'large-file', file: f.path };
38
+ out.push({ id: (0, finding_identity_1.identityFor)(input), kind: 'large-file', file: f.path });
39
+ }
40
+ return out;
41
+ }
42
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/baseline/producers/health.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAiBH,kEAQC;AAvBD,0DAAkD;AAIlD;;;uDAGuD;AAC1C,QAAA,0BAA0B,GAAG,GAAG,CAAC;AAE9C;;;;GAIG;AACH,SAAgB,2BAA2B,CAAC,OAAsB;IAChE,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,CAAC,CAAC,KAAK,IAAI,kCAA0B;YAAE,SAAS;QACpD,MAAM,KAAK,GAA2B,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3E,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAA,8BAAW,EAAC,KAAK,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Producer registry — the single canonical home for everything that
3
+ * turns analyzer output into `BaselineEntry`s.
4
+ *
5
+ * # Why this exists (CLAUDE.md Rule 10)
6
+ *
7
+ * The baseline file is the durable contract the guardrail check
8
+ * reads. Every analyzer that surfaces per-finding output MUST flow
9
+ * through a registered producer so guardrails don't silently miss
10
+ * its findings. Without the registry, adding a new analyzer means
11
+ * remembering to also edit `create.ts` orchestration — easy to
12
+ * forget, and the bug is invisible (the guardrail check passes even
13
+ * when a new finding kind is silently bypassed).
14
+ *
15
+ * With the registry:
16
+ * - Adding a new analyzer is a one-line `PRODUCERS.push(...)`.
17
+ * - The orchestrator iterates the registry — no per-producer
18
+ * `findings.push(...)` calls to forget.
19
+ * - A contract test asserts every `IdentityInput` discriminant
20
+ * kind is either contributed by a registered producer OR
21
+ * listed in `DEFERRED_KINDS` with explicit rationale.
22
+ * - A synthetic-producer playbook test asserts the orchestrator
23
+ * stays registry-driven (adding a fake producer to the
24
+ * registry makes its entries appear in the baseline file
25
+ * without any edits to the orchestrator).
26
+ *
27
+ * # Producer contract
28
+ *
29
+ * Each producer:
30
+ * 1. Declares the identity kinds it contributes via `contributes`.
31
+ * 2. Reads from the shared `ProducerContext` (gathered once by
32
+ * the orchestrator so multiple producers don't re-shell the
33
+ * same analyzer).
34
+ * 3. Returns `BaselineEntry[]` — pure or near-pure, depending on
35
+ * whether content-hash stamping is needed.
36
+ *
37
+ * # Adding a new identity kind
38
+ *
39
+ * 1. Add the discriminant to `IdentityInput` in `types.ts`.
40
+ * 2. Add the case branch in `identityFor`.
41
+ * 3. EITHER add a new producer here (or extend an existing one)
42
+ * so `contributes` covers the new kind, OR add the kind to
43
+ * `DEFERRED_KINDS` with rationale + landing phase.
44
+ * 4. Add a fixture row in `test/baseline/finding-identity.test.ts`
45
+ * (Rule 9 / per-kind fixture contract).
46
+ *
47
+ * The contract test enforces steps 3 + 4 at runtime; the
48
+ * exhaustive switch in `identityFor` enforces step 2 at compile
49
+ * time. The result: no new identity kind can land in a way that
50
+ * silently bypasses guardrails.
51
+ */
52
+ import type { GitleaksRawSecret } from '../../analyzers/tools/gitleaks';
53
+ import type { AnalysisResult } from '../../analysis-result';
54
+ import type { TestGapsReport } from '../../analyzers/tests/types';
55
+ import type { BaselineEntry } from '../types';
56
+ /** Every discriminant value the `BaselineEntry` union takes. Mirror
57
+ * of `IdentityInput['kind']` — kept as a separate alias because the
58
+ * registry contract speaks in terms of stored entries, not the
59
+ * identity-compute input. */
60
+ export type IdentityKind = BaselineEntry['kind'];
61
+ /**
62
+ * Hygiene-marker counts + stale-file list returned by
63
+ * `gatherHygieneMarkers`. Replicated here as the producer-context
64
+ * field type so producers don't need to depend on the analyzer
65
+ * module's gather signature.
66
+ */
67
+ export interface HygieneSnapshot {
68
+ readonly staleFiles: ReadonlyArray<string>;
69
+ readonly todoCount: number;
70
+ readonly fixmeCount: number;
71
+ readonly hackCount: number;
72
+ readonly consoleLogCount: number;
73
+ readonly mixedLanguages: boolean;
74
+ }
75
+ /**
76
+ * Per-run inputs every producer reads from. Gathered ONCE by the
77
+ * orchestrator; producers are pure (or content-hash-impure for
78
+ * stamping) over this context. Adding a new producer that needs a
79
+ * new analyzer means extending this context — a single, visible
80
+ * extension point.
81
+ */
82
+ export interface ProducerContext {
83
+ /** Absolute repo path. */
84
+ readonly cwd: string;
85
+ /** Commit SHA the baseline anchors to. Empty string when not in
86
+ * a git repo — content-hash stamping is then disabled but other
87
+ * producers still emit normally. */
88
+ readonly commitSha: string;
89
+ /** Resolved repo salt (from `resolveSalt`). Threaded into
90
+ * producers that compute HMACs. */
91
+ readonly salt: string;
92
+ /** Canonical cached analysis envelope — capabilities + metrics
93
+ * + provenance for every gather pipeline. */
94
+ readonly analysisResult: AnalysisResult;
95
+ /** Test-gaps report (separate analyzer because the gap detection
96
+ * + import-graph reachability isn't part of the cached
97
+ * envelope). */
98
+ readonly testGapsReport: TestGapsReport;
99
+ /** Hygiene-marker snapshot — stale file list + aggregate counts. */
100
+ readonly hygiene: HygieneSnapshot;
101
+ /** Raw secrets gitleaks captured (process-only; never written to
102
+ * disk; consumed by the secret-HMAC producer). */
103
+ readonly rawSecrets: ReadonlyArray<GitleaksRawSecret>;
104
+ }
105
+ /**
106
+ * The registry entry shape. A producer self-describes the kinds it
107
+ * contributes and supplies the function to produce them.
108
+ */
109
+ export interface BaselineProducer {
110
+ /** Human-readable name; surfaces in logs + contract-test
111
+ * diagnostics ("producer X contributed N entries"). */
112
+ readonly name: string;
113
+ /** Identity kinds this producer wires. The contract test reads
114
+ * the union across every producer and asserts it covers every
115
+ * `IdentityKind` value not in `DEFERRED_KINDS`. */
116
+ readonly contributes: ReadonlyArray<IdentityKind>;
117
+ /** Build `BaselineEntry`s from the shared context. Producers
118
+ * emit ZERO entries when their upstream data is missing
119
+ * (analyzer didn't run, envelope absent, etc.) — never throw
120
+ * for missing inputs. */
121
+ readonly produce: (ctx: ProducerContext) => BaselineEntry[];
122
+ }
123
+ /**
124
+ * Identity kinds declared in `IdentityInput` but not yet wired by
125
+ * any producer. Each entry MUST carry a `reason` (what blocks the
126
+ * producer today) and `landingPhase` (when we intend to wire it).
127
+ * The contract test asserts:
128
+ *
129
+ * - Every kind appearing here is NOT contributed by any
130
+ * registered producer (no double-counting).
131
+ * - Every `IdentityKind` is either contributed OR in this map.
132
+ *
133
+ * Adding a new identity kind without wiring a producer requires
134
+ * adding an entry here — the deferral becomes architecturally
135
+ * explicit rather than silently invisible.
136
+ */
137
+ export declare const DEFERRED_KINDS: Readonly<Record<string, {
138
+ readonly reason: string;
139
+ readonly landingPhase: string;
140
+ }>>;
141
+ /**
142
+ * The canonical producer list. Order is preserved in baseline-file
143
+ * output for deterministic diffs; adding a new producer appends
144
+ * here and updates the contract-test expectations.
145
+ *
146
+ * Mutable for the synthetic-producer playbook test: the test
147
+ * substitutes a wrapped registry rather than mutating PRODUCERS
148
+ * directly. Callers MUST treat this as immutable.
149
+ */
150
+ export declare const PRODUCERS: ReadonlyArray<BaselineProducer>;
151
+ /**
152
+ * Run every producer in `producers` against the shared context and
153
+ * flatten the result. The orchestrator calls this with `PRODUCERS`
154
+ * for production use; the playbook test calls it with an extended
155
+ * list to verify synthetic producers flow through.
156
+ */
157
+ export declare function runProducers(ctx: ProducerContext, producers?: ReadonlyArray<BaselineProducer>): BaselineEntry[];
158
+ /**
159
+ * Every kind currently contributed by some producer in `producers`.
160
+ * Convenience used by the contract test + by the orchestrator for
161
+ * logging "this run produced entries across N kinds."
162
+ */
163
+ export declare function wiredKinds(producers?: ReadonlyArray<BaselineProducer>): ReadonlySet<IdentityKind>;
164
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/baseline/producers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQ9C;;;8BAG8B;AAC9B,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;yCAEqC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;wCACoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;kDAC8C;IAC9C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;qBAEiB;IACjB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC;uDACmD;IACnD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;CACvD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;4DACwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;wDAEoD;IACpD,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAClD;;;8BAG0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,aAAa,EAAE,CAAC;CAC7D;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CACnC,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CA2B1E,CAAC;AAiEH;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,gBAAgB,CAOpD,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,eAAe,EACpB,SAAS,GAAE,aAAa,CAAC,gBAAgB,CAAa,GACrD,aAAa,EAAE,CAMjB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,SAAS,GAAE,aAAa,CAAC,gBAAgB,CAAa,GACrD,WAAW,CAAC,YAAY,CAAC,CAI3B"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ /**
3
+ * Producer registry — the single canonical home for everything that
4
+ * turns analyzer output into `BaselineEntry`s.
5
+ *
6
+ * # Why this exists (CLAUDE.md Rule 10)
7
+ *
8
+ * The baseline file is the durable contract the guardrail check
9
+ * reads. Every analyzer that surfaces per-finding output MUST flow
10
+ * through a registered producer so guardrails don't silently miss
11
+ * its findings. Without the registry, adding a new analyzer means
12
+ * remembering to also edit `create.ts` orchestration — easy to
13
+ * forget, and the bug is invisible (the guardrail check passes even
14
+ * when a new finding kind is silently bypassed).
15
+ *
16
+ * With the registry:
17
+ * - Adding a new analyzer is a one-line `PRODUCERS.push(...)`.
18
+ * - The orchestrator iterates the registry — no per-producer
19
+ * `findings.push(...)` calls to forget.
20
+ * - A contract test asserts every `IdentityInput` discriminant
21
+ * kind is either contributed by a registered producer OR
22
+ * listed in `DEFERRED_KINDS` with explicit rationale.
23
+ * - A synthetic-producer playbook test asserts the orchestrator
24
+ * stays registry-driven (adding a fake producer to the
25
+ * registry makes its entries appear in the baseline file
26
+ * without any edits to the orchestrator).
27
+ *
28
+ * # Producer contract
29
+ *
30
+ * Each producer:
31
+ * 1. Declares the identity kinds it contributes via `contributes`.
32
+ * 2. Reads from the shared `ProducerContext` (gathered once by
33
+ * the orchestrator so multiple producers don't re-shell the
34
+ * same analyzer).
35
+ * 3. Returns `BaselineEntry[]` — pure or near-pure, depending on
36
+ * whether content-hash stamping is needed.
37
+ *
38
+ * # Adding a new identity kind
39
+ *
40
+ * 1. Add the discriminant to `IdentityInput` in `types.ts`.
41
+ * 2. Add the case branch in `identityFor`.
42
+ * 3. EITHER add a new producer here (or extend an existing one)
43
+ * so `contributes` covers the new kind, OR add the kind to
44
+ * `DEFERRED_KINDS` with rationale + landing phase.
45
+ * 4. Add a fixture row in `test/baseline/finding-identity.test.ts`
46
+ * (Rule 9 / per-kind fixture contract).
47
+ *
48
+ * The contract test enforces steps 3 + 4 at runtime; the
49
+ * exhaustive switch in `identityFor` enforces step 2 at compile
50
+ * time. The result: no new identity kind can land in a way that
51
+ * silently bypasses guardrails.
52
+ */
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.PRODUCERS = exports.DEFERRED_KINDS = void 0;
55
+ exports.runProducers = runProducers;
56
+ exports.wiredKinds = wiredKinds;
57
+ const health_1 = require("./health");
58
+ const licenses_1 = require("./licenses");
59
+ const quality_1 = require("./quality");
60
+ const secret_hmac_1 = require("./secret-hmac");
61
+ const security_1 = require("./security");
62
+ const tests_1 = require("./tests");
63
+ /**
64
+ * Identity kinds declared in `IdentityInput` but not yet wired by
65
+ * any producer. Each entry MUST carry a `reason` (what blocks the
66
+ * producer today) and `landingPhase` (when we intend to wire it).
67
+ * The contract test asserts:
68
+ *
69
+ * - Every kind appearing here is NOT contributed by any
70
+ * registered producer (no double-counting).
71
+ * - Every `IdentityKind` is either contributed OR in this map.
72
+ *
73
+ * Adding a new identity kind without wiring a producer requires
74
+ * adding an entry here — the deferral becomes architecturally
75
+ * explicit rather than silently invisible.
76
+ */
77
+ exports.DEFERRED_KINDS = Object.freeze({
78
+ 'god-file': {
79
+ reason: 'graphify Python script does not yet surface per-file complexity offenders; ' +
80
+ 'QualityMetrics.topGodFiles is forward-declared but unpopulated. ' +
81
+ 'Substitute: large-file (>500 lines) overlaps the same files ~80%+ of the time.',
82
+ landingPhase: '2.6 / Phase 10s.2 (graphify-symbols expansion)',
83
+ },
84
+ hygiene: {
85
+ reason: 'gatherHygieneMarkers emits aggregate counts, not per-occurrence positions; ' +
86
+ 'extending to surface Array<{file, line, marker}> is a small gather refactor. ' +
87
+ 'Substitute: aggregate counts feed the Quality dimension score; ' +
88
+ 'newSevereQualityIssueInChangedFiles block rule catches high-severity overlap.',
89
+ landingPhase: 'Phase 5 (pre-launch polish)',
90
+ },
91
+ 'coverage-gap': {
92
+ reason: 'per-pack coverage adapters do not yet surface uncovered symbol ranges. ' +
93
+ 'Five of eight packs (typescript / java / kotlin / ruby / go) land in ' +
94
+ 'Phase 3.5 inside 2.5; remaining three (python / csharp / rust) decided ' +
95
+ 'mid-Phase-3.5 based on adapter complexity. ' +
96
+ 'Substitute: test-gap covers file-level untested; new uncovered functions ' +
97
+ 'inside an already-tested file remain invisible until Phase 3.5 lands.',
98
+ landingPhase: 'Phase 3.5 (5 packs) / 2.6 (remaining)',
99
+ },
100
+ });
101
+ // ─── Producer module wrappers ─────────────────────────────────────────────
102
+ // Each wraps a producer module's pure function with the registry's
103
+ // `BaselineProducer` shape. Kept in this file (rather than alongside
104
+ // each producer module) so the registry stays the single discovery
105
+ // surface — readers see every wired producer + every deferral in
106
+ // one place.
107
+ const SECURITY_PRODUCER = {
108
+ name: 'security',
109
+ contributes: ['secret', 'code', 'config', 'dep-vuln'],
110
+ produce(ctx) {
111
+ const aggregate = ctx.analysisResult.capabilities.securityAggregate;
112
+ if (!aggregate)
113
+ return [];
114
+ return (0, security_1.securityAggregateToBaselineEntries)(aggregate, {
115
+ cwd: ctx.cwd,
116
+ commitSha: ctx.commitSha || undefined,
117
+ });
118
+ },
119
+ };
120
+ const SECRET_HMAC_PRODUCER = {
121
+ name: 'secret-hmac',
122
+ contributes: ['secret-hmac'],
123
+ produce(ctx) {
124
+ return (0, secret_hmac_1.rawSecretsToBaselineEntries)({ rawSecrets: ctx.rawSecrets, salt: ctx.salt });
125
+ },
126
+ };
127
+ const QUALITY_PRODUCER = {
128
+ name: 'quality',
129
+ contributes: ['duplication', 'stale-file'],
130
+ produce(ctx) {
131
+ return [
132
+ ...(0, quality_1.duplicationToBaselineEntries)(ctx.analysisResult.capabilities.duplication),
133
+ ...(0, quality_1.staleFilesToBaselineEntries)(ctx.hygiene.staleFiles),
134
+ ];
135
+ },
136
+ };
137
+ const HEALTH_PRODUCER = {
138
+ name: 'health',
139
+ contributes: ['large-file'],
140
+ produce(ctx) {
141
+ return (0, health_1.largeFilesToBaselineEntries)(ctx.analysisResult.metrics);
142
+ },
143
+ };
144
+ const LICENSES_PRODUCER = {
145
+ name: 'licenses',
146
+ contributes: ['license'],
147
+ produce(ctx) {
148
+ return (0, licenses_1.licensesToBaselineEntries)(ctx.analysisResult.capabilities.licenses);
149
+ },
150
+ };
151
+ const TESTS_PRODUCER = {
152
+ name: 'tests',
153
+ contributes: ['test-gap', 'test-file-degradation'],
154
+ produce(ctx) {
155
+ return (0, tests_1.testGapsToBaselineEntries)(ctx.testGapsReport);
156
+ },
157
+ };
158
+ /**
159
+ * The canonical producer list. Order is preserved in baseline-file
160
+ * output for deterministic diffs; adding a new producer appends
161
+ * here and updates the contract-test expectations.
162
+ *
163
+ * Mutable for the synthetic-producer playbook test: the test
164
+ * substitutes a wrapped registry rather than mutating PRODUCERS
165
+ * directly. Callers MUST treat this as immutable.
166
+ */
167
+ exports.PRODUCERS = Object.freeze([
168
+ SECURITY_PRODUCER,
169
+ SECRET_HMAC_PRODUCER,
170
+ QUALITY_PRODUCER,
171
+ HEALTH_PRODUCER,
172
+ LICENSES_PRODUCER,
173
+ TESTS_PRODUCER,
174
+ ]);
175
+ /**
176
+ * Run every producer in `producers` against the shared context and
177
+ * flatten the result. The orchestrator calls this with `PRODUCERS`
178
+ * for production use; the playbook test calls it with an extended
179
+ * list to verify synthetic producers flow through.
180
+ */
181
+ function runProducers(ctx, producers = exports.PRODUCERS) {
182
+ const out = [];
183
+ for (const producer of producers) {
184
+ out.push(...producer.produce(ctx));
185
+ }
186
+ return out;
187
+ }
188
+ /**
189
+ * Every kind currently contributed by some producer in `producers`.
190
+ * Convenience used by the contract test + by the orchestrator for
191
+ * logging "this run produced entries across N kinds."
192
+ */
193
+ function wiredKinds(producers = exports.PRODUCERS) {
194
+ const out = new Set();
195
+ for (const p of producers)
196
+ for (const k of p.contributes)
197
+ out.add(k);
198
+ return out;
199
+ }
200
+ //# sourceMappingURL=index.js.map