@xenos1996/usa 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +335 -0
  3. package/USA.md +597 -0
  4. package/dist/bootstrap/catalog.d.ts +46 -0
  5. package/dist/bootstrap/catalog.d.ts.map +1 -0
  6. package/dist/bootstrap/catalog.js +312 -0
  7. package/dist/bootstrap/catalog.js.map +1 -0
  8. package/dist/bootstrap/index.d.ts +36 -0
  9. package/dist/bootstrap/index.d.ts.map +1 -0
  10. package/dist/bootstrap/index.js +177 -0
  11. package/dist/bootstrap/index.js.map +1 -0
  12. package/dist/cli.d.ts +5 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +706 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/config.d.ts +7 -0
  17. package/dist/config.d.ts.map +1 -0
  18. package/dist/config.js +88 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/detect/index.d.ts +58 -0
  21. package/dist/detect/index.d.ts.map +1 -0
  22. package/dist/detect/index.js +329 -0
  23. package/dist/detect/index.js.map +1 -0
  24. package/dist/engine/audit.d.ts +32 -0
  25. package/dist/engine/audit.d.ts.map +1 -0
  26. package/dist/engine/audit.js +366 -0
  27. package/dist/engine/audit.js.map +1 -0
  28. package/dist/engine/diff.d.ts +24 -0
  29. package/dist/engine/diff.d.ts.map +1 -0
  30. package/dist/engine/diff.js +136 -0
  31. package/dist/engine/diff.js.map +1 -0
  32. package/dist/engine/evaluate.d.ts +19 -0
  33. package/dist/engine/evaluate.d.ts.map +1 -0
  34. package/dist/engine/evaluate.js +377 -0
  35. package/dist/engine/evaluate.js.map +1 -0
  36. package/dist/engine/gate.d.ts +19 -0
  37. package/dist/engine/gate.d.ts.map +1 -0
  38. package/dist/engine/gate.js +47 -0
  39. package/dist/engine/gate.js.map +1 -0
  40. package/dist/engine/loader.d.ts +37 -0
  41. package/dist/engine/loader.d.ts.map +1 -0
  42. package/dist/engine/loader.js +388 -0
  43. package/dist/engine/loader.js.map +1 -0
  44. package/dist/engine/maturity.d.ts +20 -0
  45. package/dist/engine/maturity.d.ts.map +1 -0
  46. package/dist/engine/maturity.js +157 -0
  47. package/dist/engine/maturity.js.map +1 -0
  48. package/dist/engine/score.d.ts +19 -0
  49. package/dist/engine/score.d.ts.map +1 -0
  50. package/dist/engine/score.js +141 -0
  51. package/dist/engine/score.js.map +1 -0
  52. package/dist/engine/sections.d.ts +14 -0
  53. package/dist/engine/sections.d.ts.map +1 -0
  54. package/dist/engine/sections.js +50 -0
  55. package/dist/engine/sections.js.map +1 -0
  56. package/dist/evolution/benchmark.d.ts +12 -0
  57. package/dist/evolution/benchmark.d.ts.map +1 -0
  58. package/dist/evolution/benchmark.js +107 -0
  59. package/dist/evolution/benchmark.js.map +1 -0
  60. package/dist/evolution/capability.d.ts +22 -0
  61. package/dist/evolution/capability.d.ts.map +1 -0
  62. package/dist/evolution/capability.js +69 -0
  63. package/dist/evolution/capability.js.map +1 -0
  64. package/dist/evolution/coverage.d.ts +15 -0
  65. package/dist/evolution/coverage.d.ts.map +1 -0
  66. package/dist/evolution/coverage.js +65 -0
  67. package/dist/evolution/coverage.js.map +1 -0
  68. package/dist/evolution/gap.d.ts +10 -0
  69. package/dist/evolution/gap.d.ts.map +1 -0
  70. package/dist/evolution/gap.js +52 -0
  71. package/dist/evolution/gap.js.map +1 -0
  72. package/dist/evolution/propose.d.ts +50 -0
  73. package/dist/evolution/propose.d.ts.map +1 -0
  74. package/dist/evolution/propose.js +188 -0
  75. package/dist/evolution/propose.js.map +1 -0
  76. package/dist/evolution/queue.d.ts +64 -0
  77. package/dist/evolution/queue.d.ts.map +1 -0
  78. package/dist/evolution/queue.js +192 -0
  79. package/dist/evolution/queue.js.map +1 -0
  80. package/dist/evolution/release.d.ts +11 -0
  81. package/dist/evolution/release.d.ts.map +1 -0
  82. package/dist/evolution/release.js +55 -0
  83. package/dist/evolution/release.js.map +1 -0
  84. package/dist/evolution/run.d.ts +88 -0
  85. package/dist/evolution/run.d.ts.map +1 -0
  86. package/dist/evolution/run.js +258 -0
  87. package/dist/evolution/run.js.map +1 -0
  88. package/dist/evolution/schedule.d.ts +59 -0
  89. package/dist/evolution/schedule.d.ts.map +1 -0
  90. package/dist/evolution/schedule.js +77 -0
  91. package/dist/evolution/schedule.js.map +1 -0
  92. package/dist/evolution/types.d.ts +174 -0
  93. package/dist/evolution/types.d.ts.map +1 -0
  94. package/dist/evolution/types.js +8 -0
  95. package/dist/evolution/types.js.map +1 -0
  96. package/dist/index.d.ts +36 -0
  97. package/dist/index.d.ts.map +1 -0
  98. package/dist/index.js +30 -0
  99. package/dist/index.js.map +1 -0
  100. package/dist/learn/index.d.ts +27 -0
  101. package/dist/learn/index.d.ts.map +1 -0
  102. package/dist/learn/index.js +196 -0
  103. package/dist/learn/index.js.map +1 -0
  104. package/dist/report/markdown.d.ts +16 -0
  105. package/dist/report/markdown.d.ts.map +1 -0
  106. package/dist/report/markdown.js +488 -0
  107. package/dist/report/markdown.js.map +1 -0
  108. package/dist/snapshot/index.d.ts +55 -0
  109. package/dist/snapshot/index.d.ts.map +1 -0
  110. package/dist/snapshot/index.js +76 -0
  111. package/dist/snapshot/index.js.map +1 -0
  112. package/dist/store/index.d.ts +31 -0
  113. package/dist/store/index.d.ts.map +1 -0
  114. package/dist/store/index.js +69 -0
  115. package/dist/store/index.js.map +1 -0
  116. package/dist/types.d.ts +287 -0
  117. package/dist/types.d.ts.map +1 -0
  118. package/dist/types.js +16 -0
  119. package/dist/types.js.map +1 -0
  120. package/dist/util/glob.d.ts +11 -0
  121. package/dist/util/glob.d.ts.map +1 -0
  122. package/dist/util/glob.js +86 -0
  123. package/dist/util/glob.js.map +1 -0
  124. package/dist/util/project.d.ts +90 -0
  125. package/dist/util/project.d.ts.map +1 -0
  126. package/dist/util/project.js +636 -0
  127. package/dist/util/project.js.map +1 -0
  128. package/dist/util/yaml.d.ts +28 -0
  129. package/dist/util/yaml.d.ts.map +1 -0
  130. package/dist/util/yaml.js +48 -0
  131. package/dist/util/yaml.js.map +1 -0
  132. package/package.json +94 -0
  133. package/rules/core/architecture.yaml +190 -0
  134. package/rules/core/cicd.yaml +212 -0
  135. package/rules/core/code-quality.yaml +261 -0
  136. package/rules/core/dependencies.yaml +132 -0
  137. package/rules/core/documentation.yaml +119 -0
  138. package/rules/core/future-readiness.yaml +91 -0
  139. package/rules/core/release.yaml +131 -0
  140. package/rules/core/repo.yaml +313 -0
  141. package/rules/core/security.yaml +496 -0
  142. package/rules/core/supply-chain.yaml +357 -0
  143. package/rules/core/testing.yaml +266 -0
  144. package/rules/detectors.yaml +2028 -0
  145. package/rules/index.yaml +42 -0
  146. package/rules/profiles/maturity.yaml +135 -0
  147. package/rules/stacks/ai-era.yaml +193 -0
  148. package/rules/stacks/api-backend.yaml +121 -0
  149. package/rules/stacks/cli.yaml +105 -0
  150. package/rules/stacks/compliance.yaml +157 -0
  151. package/rules/stacks/containers.yaml +124 -0
  152. package/rules/stacks/data.yaml +165 -0
  153. package/rules/stacks/go.yaml +134 -0
  154. package/rules/stacks/iac.yaml +128 -0
  155. package/rules/stacks/jvm.yaml +150 -0
  156. package/rules/stacks/ml-ai.yaml +140 -0
  157. package/rules/stacks/mobile.yaml +121 -0
  158. package/rules/stacks/node-typescript.yaml +166 -0
  159. package/rules/stacks/python.yaml +175 -0
  160. package/rules/stacks/rust.yaml +129 -0
  161. package/rules/stacks/solidity.yaml +139 -0
  162. package/rules/stacks/swift.yaml +100 -0
  163. package/rules/stacks/web-frontend.yaml +159 -0
@@ -0,0 +1,388 @@
1
+ import { parse as parseYaml } from 'yaml';
2
+ import { asMap, isMap, list, num, scalar, str, strList } from '../util/yaml.js';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ export const SEVERITY_LADDER = ['FUTURE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];
6
+ export const RULE_CLASSES = [
7
+ 'security',
8
+ 'supply-chain',
9
+ 'correctness',
10
+ 'maintainability',
11
+ 'operations',
12
+ 'performance',
13
+ 'compliance',
14
+ 'documentation',
15
+ 'style',
16
+ ];
17
+ export const DEFAULT_WEIGHT = {
18
+ CRITICAL: 10,
19
+ HIGH: 6,
20
+ MEDIUM: 3,
21
+ LOW: 1.5,
22
+ FUTURE: 0.5,
23
+ };
24
+ /**
25
+ * Load a single pack file (not the registry). Used by the evolution CLI to load
26
+ * a candidate capability pack that is *not* (yet) in `rules/index.yaml`.
27
+ */
28
+ export function loadPackFile(file) {
29
+ const warnings = [];
30
+ const pack = parsePack(path.resolve(file), new Map(), warnings);
31
+ if (pack)
32
+ pack.source = path.basename(file);
33
+ return { pack, warnings };
34
+ }
35
+ /** Read `rules/index.yaml` and every pack it references. */
36
+ export function loadRulePacks(rulesDir) {
37
+ const warnings = [];
38
+ const indexPath = path.join(rulesDir, 'index.yaml');
39
+ if (!fs.existsSync(indexPath)) {
40
+ throw new Error(`Rule index not found at ${indexPath}. Pass --rules-dir or run \`usa init\`.`);
41
+ }
42
+ let indexDoc;
43
+ try {
44
+ indexDoc = parseYaml(fs.readFileSync(indexPath, 'utf8'));
45
+ }
46
+ catch (err) {
47
+ // A corrupt index must not abort the audit with a stack trace: warn and
48
+ // continue with zero packs rather than zero findings with no explanation.
49
+ warnings.push(`rule index ${indexPath} is not valid YAML (${err.message}) — no packs loaded`);
50
+ return { packs: [], warnings };
51
+ }
52
+ const entries = indexDoc?.packs ?? [];
53
+ const packs = [];
54
+ const seenIds = new Set();
55
+ const seenRuleIds = new Map();
56
+ for (const entry of entries) {
57
+ processIndexEntry(entry, rulesDir, packs, seenIds, seenRuleIds, warnings);
58
+ }
59
+ return { packs, warnings };
60
+ }
61
+ function processIndexEntry(entry, rulesDir, packs, seenIds, seenRuleIds, warnings) {
62
+ const file = typeof entry === 'string' ? entry : entry.file;
63
+ const enabled = typeof entry === 'string' ? true : entry.enabled !== false;
64
+ if (!enabled)
65
+ return;
66
+ const abs = path.resolve(rulesDir, file);
67
+ if (!fs.existsSync(abs)) {
68
+ warnings.push(`pack listed in index but missing on disk: ${file}`);
69
+ return;
70
+ }
71
+ const pack = parsePack(abs, seenRuleIds, warnings);
72
+ if (!pack)
73
+ return;
74
+ if (seenIds.has(pack.id)) {
75
+ warnings.push(`duplicate pack id "${pack.id}" (${file}) — later pack ignored`);
76
+ return;
77
+ }
78
+ seenIds.add(pack.id);
79
+ pack.source = path.relative(path.dirname(rulesDir), abs) || file;
80
+ packs.push(pack);
81
+ }
82
+ function parsePack(file, seenRuleIds, warnings) {
83
+ let text;
84
+ try {
85
+ text = fs.readFileSync(file, 'utf8');
86
+ }
87
+ catch (err) {
88
+ warnings.push(`pack ${file} could not be read (${err.message}) — pack skipped`);
89
+ return null;
90
+ }
91
+ return parsePackText(text, file, seenRuleIds, warnings);
92
+ }
93
+ /**
94
+ * Parse a rule pack from YAML text in memory. Shared by the file loader and the
95
+ * evolution proposal stage, which renders a candidate pack (from the bootstrap
96
+ * catalog) without ever touching the checked-in registry. `sourceName` is only
97
+ * used in warnings and as the fallback pack id.
98
+ */
99
+ export function parsePackText(text, sourceName, seenRuleIds = new Map(), warnings = []) {
100
+ let raw;
101
+ try {
102
+ raw = parseYaml(text);
103
+ }
104
+ catch (err) {
105
+ // One corrupt pack must not abort the whole audit: skip it loudly.
106
+ warnings.push(`pack ${sourceName} is not valid YAML (${err.message}) — pack skipped`);
107
+ return null;
108
+ }
109
+ if (!isMap(raw)) {
110
+ warnings.push(`${sourceName}: not a YAML mapping`);
111
+ return null;
112
+ }
113
+ const id = str(raw.id) ?? path.basename(sourceName, path.extname(sourceName));
114
+ const rules = [];
115
+ (list(raw.rules) ?? []).forEach((r, i) => {
116
+ const parsed = parseRule(r, id, i, warnings);
117
+ if (!parsed)
118
+ return;
119
+ const firstSeen = seenRuleIds.get(parsed.id);
120
+ if (firstSeen !== undefined) {
121
+ // Duplicate rule IDs double-count weight in scoring and collide as
122
+ // duplicate YAML keys in the report trailer (second silently wins in
123
+ // `usa diff`). First definition wins; the later one is dropped loudly.
124
+ warnings.push(`duplicate rule id "${parsed.id}" in pack "${id}" (first defined in pack "${firstSeen}") — later rule ignored`);
125
+ return;
126
+ }
127
+ seenRuleIds.set(parsed.id, id);
128
+ rules.push(parsed);
129
+ });
130
+ return {
131
+ id,
132
+ title: str(raw.title) ?? id,
133
+ description: str(raw.description),
134
+ version: str(raw.version),
135
+ section: str(raw.section),
136
+ sectionTitle: str(raw.section_title),
137
+ skipWhen: isMap(raw.skip_when) ? raw.skip_when : undefined,
138
+ provides: strList(raw.provides),
139
+ rules,
140
+ };
141
+ }
142
+ function parseRule(raw, packId, index, warnings) {
143
+ const where = `${packId}[${index}]`;
144
+ const head = readRuleHead(raw, where, warnings);
145
+ if (!head)
146
+ return null;
147
+ const { map: r, id, severity } = head;
148
+ const ruleClass = resolveRuleClass(r, where, id, warnings);
149
+ const check = parseCheck(r.check, `${where} ${id}`, warnings);
150
+ if (!check)
151
+ return null;
152
+ validatePredicate(r.applies_when, `${where} ${id}`, warnings);
153
+ return assembleRule(r, id, severity, ruleClass, check);
154
+ }
155
+ function assembleRule(r, id, severity, ruleClass, check) {
156
+ const depths = Array.isArray(r.depths) ? r.depths.filter(isDepth) : undefined;
157
+ return {
158
+ id,
159
+ title: String(r.title ?? id),
160
+ section: String(r.section ?? 'S0'),
161
+ sectionTitle: optText(r.section_title),
162
+ severity,
163
+ weight: optNumber(r.weight),
164
+ ruleClass,
165
+ appliesWhen: r.applies_when,
166
+ depths,
167
+ check,
168
+ why: optText(r.why),
169
+ evidence: optText(r.evidence),
170
+ remediation: optText(r.remediation),
171
+ references: optStrArray(r.references),
172
+ tags: optStrArray(r.tags),
173
+ };
174
+ }
175
+ function optText(v) {
176
+ return v ? String(v) : undefined;
177
+ }
178
+ function optNumber(v) {
179
+ return typeof v === 'number' ? v : undefined;
180
+ }
181
+ function optStrArray(v) {
182
+ return Array.isArray(v) ? v.map(String) : undefined;
183
+ }
184
+ function readRuleHead(raw, where, warnings) {
185
+ if (!isMap(raw)) {
186
+ warnings.push(`${where}: rule is not a mapping`);
187
+ return null;
188
+ }
189
+ const id = raw.id ? String(raw.id) : null;
190
+ if (!id) {
191
+ warnings.push(`${where}: rule missing "id"`);
192
+ return null;
193
+ }
194
+ const severity = normalizeSeverity(raw.severity);
195
+ if (!severity) {
196
+ warnings.push(`${where} ${id}: invalid severity "${String(raw.severity)}"`);
197
+ return null;
198
+ }
199
+ return { map: raw, id, severity };
200
+ }
201
+ function resolveRuleClass(r, where, id, warnings) {
202
+ const declaredClass = str(r.class);
203
+ if (declaredClass && !RULE_CLASSES.includes(declaredClass)) {
204
+ warnings.push(`${where} ${id}: unknown class "${declaredClass}" → maintainability`);
205
+ }
206
+ return declaredClass && RULE_CLASSES.includes(declaredClass)
207
+ ? declaredClass
208
+ : 'maintainability';
209
+ }
210
+ /** One check kind per entry — adding a kind means adding a line, not a branch. */
211
+ const CHECK_BUILDERS = {
212
+ manual: () => ({ kind: 'manual' }),
213
+ info: () => ({ kind: 'info' }),
214
+ file_exists: (c) => ({ kind: 'file_exists', files: toStringArray(c.files) }),
215
+ file_absent: (c) => ({ kind: 'file_absent', files: toStringArray(c.files) }),
216
+ any_file: (c) => ({ kind: 'any_file', patterns: toStringArray(c.patterns ?? c.files) }),
217
+ grep_present: (c) => grepCheck('grep_present', c),
218
+ grep_absent: (c) => grepCheck('grep_absent', c),
219
+ grep_wrong: (c) => grepCheck('grep_wrong', c),
220
+ grep_deprecated: (c) => grepCheck('grep_deprecated', c),
221
+ json_path: (c) => ({
222
+ kind: 'json_path',
223
+ file: String(c.file ?? ''),
224
+ path: String(c.path ?? ''),
225
+ equals: scalar(c.equals) ?? undefined,
226
+ }),
227
+ tracked_present: (c) => ({
228
+ kind: 'tracked_present',
229
+ patterns: toStringArray(c.patterns ?? c.files),
230
+ }),
231
+ tracked_absent: (c) => ({
232
+ kind: 'tracked_absent',
233
+ patterns: toStringArray(c.patterns ?? c.files),
234
+ }),
235
+ file_lines_max: (c) => ({
236
+ kind: 'file_lines_max',
237
+ patterns: toStringArray(c.patterns ?? c.files),
238
+ max_lines: num(c.max_lines) ?? 800,
239
+ }),
240
+ count_min: (c) => ({
241
+ kind: 'count_min',
242
+ patterns: toStringArray(c.patterns ?? c.files),
243
+ min: num(c.min) ?? 1,
244
+ }),
245
+ command: (c) => ({
246
+ kind: 'command',
247
+ run: str(c.run) ?? '',
248
+ expect_exit: num(c.expect_exit) ?? 0,
249
+ }),
250
+ };
251
+ function parseCheck(raw, where, warnings) {
252
+ const c = asMap(raw);
253
+ const kind = str(c.kind);
254
+ if (!kind) {
255
+ warnings.push(`${where}: check missing "kind"`);
256
+ return null;
257
+ }
258
+ const build = CHECK_BUILDERS[kind];
259
+ if (!build) {
260
+ warnings.push(`${where}: unsupported check kind "${String(c.kind)}"`);
261
+ return null;
262
+ }
263
+ const built = build(c);
264
+ if (built.kind.startsWith('grep_') && 'pattern' in built && built.pattern === '') {
265
+ // `new RegExp('')` matches every line: a grep_absent rule with a missing
266
+ // pattern FAILs the whole repo, a grep_present one awards free credit.
267
+ // A malformed rule must never become a score weapon — drop it loudly.
268
+ warnings.push(`${where}: ${built.kind} has an empty pattern (matches every line) — rule ignored`);
269
+ return null;
270
+ }
271
+ return built;
272
+ }
273
+ /** Predicate operators the evaluator understands. Anything else fails closed. */
274
+ const PREDICATE_OPS = new Set([
275
+ 'exists',
276
+ 'absent',
277
+ 'eq',
278
+ 'neq',
279
+ 'in',
280
+ 'includes',
281
+ 'gt',
282
+ 'lt',
283
+ 'matches',
284
+ ]);
285
+ /**
286
+ * `applies_when` is author-controlled input to the audit hot loop. An unknown
287
+ * key, a non-list `all`/`any`, or an uncompilable `matches` regex must warn at
288
+ * load time, because evaluation fails closed (rule skipped) on all of them.
289
+ */
290
+ export function validatePredicate(p, where, warnings) {
291
+ if (p === undefined || p === null)
292
+ return;
293
+ if (!isMap(p)) {
294
+ warnings.push(`${where}: applies_when must be a mapping — constraint ignored, rule skipped`);
295
+ return;
296
+ }
297
+ const keys = Object.keys(p);
298
+ if (keys.length === 0)
299
+ return;
300
+ for (const k of keys) {
301
+ validatePredicateKey(p, k, where, warnings);
302
+ }
303
+ }
304
+ function validatePredicateKey(p, k, where, warnings) {
305
+ if (k === 'all' || k === 'any') {
306
+ validatePredicateList(p[k], `${where}: applies_when.${k}`, warnings);
307
+ return;
308
+ }
309
+ if (k === 'not') {
310
+ validatePredicate(p.not, where, warnings);
311
+ return;
312
+ }
313
+ if (k === 'fact') {
314
+ validateFactPredicate(p, where, warnings);
315
+ return;
316
+ }
317
+ if (k === 'op' || k === 'value') {
318
+ // `op`/`value` are operands of a sibling `fact` — meaningful only there.
319
+ if (typeof p.fact !== 'string') {
320
+ warnings.push(`${where}: "${k}" without a "fact" — ignoring`);
321
+ }
322
+ return;
323
+ }
324
+ warnings.push(`${where}: unknown applies_when key "${k}" — constraint ignored, rule skipped`);
325
+ }
326
+ function validatePredicateList(v, where, warnings) {
327
+ const items = list(v);
328
+ if (!items) {
329
+ warnings.push(`${where} must be a list — constraint ignored`);
330
+ return;
331
+ }
332
+ for (const item of items)
333
+ validatePredicate(item, where, warnings);
334
+ }
335
+ function validateFactPredicate(p, where, warnings) {
336
+ const op = str(p.op) ?? 'exists';
337
+ if (!PREDICATE_OPS.has(op)) {
338
+ warnings.push(`${where}: unknown predicate op "${op}" — rule will never apply`);
339
+ return;
340
+ }
341
+ if (op === 'matches' && typeof p.value === 'string') {
342
+ try {
343
+ new RegExp(p.value);
344
+ }
345
+ catch {
346
+ warnings.push(`${where}: invalid regex in matches predicate ("${String(p.value)}") — rule will never apply`);
347
+ }
348
+ }
349
+ }
350
+ /** The four grep_* kinds share a shape; they differ only in polarity. */
351
+ function grepCheck(kind, c) {
352
+ return {
353
+ kind,
354
+ pattern: str(c.pattern) ?? '',
355
+ include: toStringArray(c.include),
356
+ exclude: c.exclude ? toStringArray(c.exclude) : undefined,
357
+ flags: str(c.flags),
358
+ };
359
+ }
360
+ function toStringArray(v) {
361
+ if (Array.isArray(v))
362
+ return v.map(String);
363
+ if (typeof v === 'string')
364
+ return [v];
365
+ return [];
366
+ }
367
+ function normalizeSeverity(v) {
368
+ const s = String(v ?? '').toUpperCase();
369
+ return SEVERITY_LADDER.includes(s) ? s : null;
370
+ }
371
+ function isDepth(v) {
372
+ return v === 'quick' || v === 'standard' || v === 'deep';
373
+ }
374
+ /** Merge config-driven rule overrides onto loaded packs. */
375
+ export function applyRuleOverrides(packs, overrides) {
376
+ for (const pack of packs) {
377
+ for (const rule of pack.rules) {
378
+ const o = overrides[rule.id];
379
+ if (!o)
380
+ continue;
381
+ if (o.severity)
382
+ rule.severity = o.severity;
383
+ if (typeof o.weight === 'number')
384
+ rule.weight = o.weight;
385
+ }
386
+ }
387
+ }
388
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/engine/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Maturity, RuleClass, Severity } from '../types.js';
2
+ export interface MaturityProfile {
3
+ key: Maturity;
4
+ label: string;
5
+ summary: string;
6
+ dampen: Record<RuleClass, number>;
7
+ expectedBand: [number, number];
8
+ focus: string[];
9
+ defer: string[];
10
+ }
11
+ export declare function loadProfiles(rulesDir: string): Record<Maturity, MaturityProfile>;
12
+ /**
13
+ * Apply the maturity profile to a rule's declared severity.
14
+ * CRITICAL is never dampened — see the hard rule in profiles/maturity.yaml.
15
+ */
16
+ export declare function dampen(severity: Severity, ruleClass: RuleClass, profile: MaturityProfile): {
17
+ severity: Severity;
18
+ dampened: boolean;
19
+ };
20
+ //# sourceMappingURL=maturity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maturity.d.ts","sourceRoot":"","sources":["../../src/engine/maturity.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AA+GD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,CAwBhF;AAED;;;GAGG;AACH,wBAAgB,MAAM,CACpB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,eAAe,GACvB;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAU3C"}
@@ -0,0 +1,157 @@
1
+ import { parse as parseYaml } from 'yaml';
2
+ import { asMap, list, num, str, strList } from '../util/yaml.js';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ const LADDER = ['FUTURE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];
6
+ const FALLBACK = {
7
+ prototype: {
8
+ key: 'prototype',
9
+ label: 'Prototype / Spike',
10
+ summary: 'Proving an idea.',
11
+ dampen: {
12
+ security: 1,
13
+ 'supply-chain': 1,
14
+ correctness: 1,
15
+ maintainability: 2,
16
+ operations: 2,
17
+ performance: 2,
18
+ compliance: 2,
19
+ documentation: 2,
20
+ style: 2,
21
+ },
22
+ expectedBand: [30, 65],
23
+ focus: [],
24
+ defer: [],
25
+ },
26
+ mvp: {
27
+ key: 'mvp',
28
+ label: 'MVP / Early product',
29
+ summary: 'Real users, real data.',
30
+ dampen: {
31
+ security: 0,
32
+ 'supply-chain': 1,
33
+ correctness: 1,
34
+ maintainability: 1,
35
+ operations: 1,
36
+ performance: 1,
37
+ compliance: 1,
38
+ documentation: 2,
39
+ style: 2,
40
+ },
41
+ expectedBand: [45, 75],
42
+ focus: [],
43
+ defer: [],
44
+ },
45
+ beta: {
46
+ key: 'beta',
47
+ label: 'Beta / Growing',
48
+ summary: 'Scaling users and contributors.',
49
+ dampen: {
50
+ security: 0,
51
+ 'supply-chain': 0,
52
+ correctness: 0,
53
+ maintainability: 1,
54
+ operations: 1,
55
+ performance: 1,
56
+ compliance: 1,
57
+ documentation: 1,
58
+ style: 1,
59
+ },
60
+ expectedBand: [60, 85],
61
+ focus: [],
62
+ defer: [],
63
+ },
64
+ production: {
65
+ key: 'production',
66
+ label: 'Production / GA',
67
+ summary: 'Full bar.',
68
+ dampen: {
69
+ security: 0,
70
+ 'supply-chain': 0,
71
+ correctness: 0,
72
+ maintainability: 0,
73
+ operations: 0,
74
+ performance: 0,
75
+ compliance: 0,
76
+ documentation: 0,
77
+ style: 0,
78
+ },
79
+ expectedBand: [75, 95],
80
+ focus: [],
81
+ defer: [],
82
+ },
83
+ legacy: {
84
+ key: 'legacy',
85
+ label: 'Legacy / Maintenance',
86
+ summary: 'Contain risk, plan exit.',
87
+ dampen: {
88
+ security: 0,
89
+ 'supply-chain': 0,
90
+ correctness: 0,
91
+ maintainability: 1,
92
+ operations: 0,
93
+ performance: 1,
94
+ compliance: 0,
95
+ documentation: 1,
96
+ style: 1,
97
+ },
98
+ expectedBand: [40, 70],
99
+ focus: [],
100
+ defer: [],
101
+ },
102
+ };
103
+ /** `[min, max]` if the pack wrote a two-number band, else the built-in. */
104
+ function expectedBand(v, fallback) {
105
+ const band = list(v);
106
+ if (!band || band.length < 2)
107
+ return fallback;
108
+ const min = num(band[0]);
109
+ const max = num(band[1]);
110
+ return min !== undefined && max !== undefined ? [min, max] : fallback;
111
+ }
112
+ export function loadProfiles(rulesDir) {
113
+ const file = path.join(rulesDir, 'profiles', 'maturity.yaml');
114
+ if (!fs.existsSync(file))
115
+ return { ...FALLBACK };
116
+ try {
117
+ const doc = asMap(parseYaml(fs.readFileSync(file, 'utf8')));
118
+ const profiles = asMap(doc.profiles);
119
+ const out = { ...FALLBACK };
120
+ for (const key of Object.keys(FALLBACK)) {
121
+ const p = asMap(profiles[key]);
122
+ if (!profiles[key])
123
+ continue;
124
+ out[key] = {
125
+ key,
126
+ label: str(p.label) ?? FALLBACK[key].label,
127
+ summary: (str(p.summary) ?? '').trim(),
128
+ dampen: { ...FALLBACK[key].dampen, ...asMap(p.dampen) },
129
+ expectedBand: expectedBand(p.expected_band, FALLBACK[key].expectedBand),
130
+ focus: strList(p.focus) ?? [],
131
+ defer: strList(p.defer) ?? [],
132
+ };
133
+ }
134
+ return out;
135
+ }
136
+ catch {
137
+ return { ...FALLBACK };
138
+ }
139
+ }
140
+ /**
141
+ * Apply the maturity profile to a rule's declared severity.
142
+ * CRITICAL is never dampened — see the hard rule in profiles/maturity.yaml.
143
+ */
144
+ export function dampen(severity, ruleClass, profile) {
145
+ if (severity === 'CRITICAL')
146
+ return { severity, dampened: false };
147
+ const raw = profile.dampen[ruleClass] ?? 0;
148
+ // Pack-supplied dampen steps are untrusted input: a fractional step indexes
149
+ // the ladder at a hole (severity: undefined → NaN scores downstream), so
150
+ // only non-negative integers dampen. Anything else means full severity.
151
+ if (!Number.isInteger(raw) || raw <= 0)
152
+ return { severity, dampened: false };
153
+ const idx = LADDER.indexOf(severity);
154
+ const next = Math.max(0, idx - raw);
155
+ return { severity: LADDER[next], dampened: next !== idx };
156
+ }
157
+ //# sourceMappingURL=maturity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maturity.js","sourceRoot":"","sources":["../../src/engine/maturity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Finding, Rule, ScoreCard } from '../types.js';
2
+ import type { SectionDef } from './sections.js';
3
+ import type { MaturityProfile } from './maturity.js';
4
+ export interface ScoredRule {
5
+ rule: Rule;
6
+ finding: Finding;
7
+ }
8
+ /**
9
+ * Deterministic, reproducible scoring.
10
+ *
11
+ * credit_i = weight_i × CREDIT[status_i]
12
+ * section = 10 × Σcredit_i / Σweight_i (resolved applicable rules)
13
+ * overall = 100 × Σ(credit_i × sectionWeight) / Σ(weight_i × sectionWeight)
14
+ *
15
+ * Rule-level weighting (rather than averaging section scores) means a section
16
+ * with three rules cannot swing the total as hard as one with thirty.
17
+ */
18
+ export declare function score(evaluated: ScoredRule[], sections: SectionDef[], profile: MaturityProfile): ScoreCard;
19
+ //# sourceMappingURL=score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/engine/score.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAkC,MAAM,aAAa,CAAC;AAE5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;CAClB;AAkCD;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,SAAS,EAAE,UAAU,EAAE,EACvB,QAAQ,EAAE,UAAU,EAAE,EACtB,OAAO,EAAE,eAAe,GACvB,SAAS,CAgCX"}