@miller-tech/uap 1.221.0 → 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 (238) hide show
  1. package/README.md +19 -9
  2. package/config/exl3-profiles/qwen38-27b-exl3.env +68 -0
  3. package/config/llama-profiles/qwen38-27b-dflash2.env +6 -1
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/benchmarks/paired/adapter.d.ts +15 -0
  6. package/dist/benchmarks/paired/adapter.d.ts.map +1 -1
  7. package/dist/benchmarks/paired/adapter.js +22 -1
  8. package/dist/benchmarks/paired/adapter.js.map +1 -1
  9. package/dist/bin/cli.js +20 -24
  10. package/dist/bin/cli.js.map +1 -1
  11. package/dist/cli/deliver.d.ts +34 -0
  12. package/dist/cli/deliver.d.ts.map +1 -1
  13. package/dist/cli/deliver.js +147 -20
  14. package/dist/cli/deliver.js.map +1 -1
  15. package/dist/cli/guided-setup.d.ts.map +1 -1
  16. package/dist/cli/guided-setup.js +15 -0
  17. package/dist/cli/guided-setup.js.map +1 -1
  18. package/dist/cli/init.d.ts.map +1 -1
  19. package/dist/cli/init.js +3 -0
  20. package/dist/cli/init.js.map +1 -1
  21. package/dist/cli/plan.d.ts.map +1 -1
  22. package/dist/cli/plan.js +8 -2
  23. package/dist/cli/plan.js.map +1 -1
  24. package/dist/cli/policy.d.ts.map +1 -1
  25. package/dist/cli/policy.js +104 -2
  26. package/dist/cli/policy.js.map +1 -1
  27. package/dist/cli/quality.d.ts +11 -0
  28. package/dist/cli/quality.d.ts.map +1 -0
  29. package/dist/cli/quality.js +213 -0
  30. package/dist/cli/quality.js.map +1 -0
  31. package/dist/cli/wizard-config.d.ts.map +1 -1
  32. package/dist/cli/wizard-config.js +19 -9
  33. package/dist/cli/wizard-config.js.map +1 -1
  34. package/dist/cli/worktree.d.ts.map +1 -1
  35. package/dist/cli/worktree.js +8 -1
  36. package/dist/cli/worktree.js.map +1 -1
  37. package/dist/dashboard/savings.d.ts +1 -4
  38. package/dist/dashboard/savings.d.ts.map +1 -1
  39. package/dist/dashboard/savings.js +2 -52
  40. package/dist/dashboard/savings.js.map +1 -1
  41. package/dist/delivery/acceptance-judge.d.ts +10 -0
  42. package/dist/delivery/acceptance-judge.d.ts.map +1 -1
  43. package/dist/delivery/acceptance-judge.js +45 -3
  44. package/dist/delivery/acceptance-judge.js.map +1 -1
  45. package/dist/delivery/agentic-executor.d.ts +12 -1
  46. package/dist/delivery/agentic-executor.d.ts.map +1 -1
  47. package/dist/delivery/agentic-executor.js +25 -5
  48. package/dist/delivery/agentic-executor.js.map +1 -1
  49. package/dist/delivery/bash-sweep.d.ts +12 -0
  50. package/dist/delivery/bash-sweep.d.ts.map +1 -1
  51. package/dist/delivery/bash-sweep.js +8 -1
  52. package/dist/delivery/bash-sweep.js.map +1 -1
  53. package/dist/delivery/convergence-loop.d.ts.map +1 -1
  54. package/dist/delivery/convergence-loop.js +6 -4
  55. package/dist/delivery/convergence-loop.js.map +1 -1
  56. package/dist/delivery/execution-gate.d.ts +1 -1
  57. package/dist/delivery/execution-gate.d.ts.map +1 -1
  58. package/dist/delivery/execution-gate.js +248 -5
  59. package/dist/delivery/execution-gate.js.map +1 -1
  60. package/dist/delivery/snapshot.d.ts +16 -0
  61. package/dist/delivery/snapshot.d.ts.map +1 -1
  62. package/dist/delivery/snapshot.js +113 -2
  63. package/dist/delivery/snapshot.js.map +1 -1
  64. package/dist/delivery/user-validation.d.ts.map +1 -1
  65. package/dist/delivery/user-validation.js +55 -10
  66. package/dist/delivery/user-validation.js.map +1 -1
  67. package/dist/delivery/verifier-ladder.d.ts +24 -0
  68. package/dist/delivery/verifier-ladder.d.ts.map +1 -1
  69. package/dist/delivery/verifier-ladder.js +119 -2
  70. package/dist/delivery/verifier-ladder.js.map +1 -1
  71. package/dist/delivery/visual-gate.d.ts +24 -0
  72. package/dist/delivery/visual-gate.d.ts.map +1 -1
  73. package/dist/delivery/visual-gate.js +70 -9
  74. package/dist/delivery/visual-gate.js.map +1 -1
  75. package/dist/generators/claude-md.js +17 -4
  76. package/dist/generators/claude-md.js.map +1 -1
  77. package/dist/policies/liveness.d.ts +105 -0
  78. package/dist/policies/liveness.d.ts.map +1 -0
  79. package/dist/policies/liveness.js +251 -0
  80. package/dist/policies/liveness.js.map +1 -0
  81. package/dist/policies/policy-memory.d.ts.map +1 -1
  82. package/dist/policies/policy-memory.js +3 -4
  83. package/dist/policies/policy-memory.js.map +1 -1
  84. package/dist/quality/baseline.d.ts +29 -0
  85. package/dist/quality/baseline.d.ts.map +1 -0
  86. package/dist/quality/baseline.js +79 -0
  87. package/dist/quality/baseline.js.map +1 -0
  88. package/dist/quality/complexity.d.ts +38 -0
  89. package/dist/quality/complexity.d.ts.map +1 -0
  90. package/dist/quality/complexity.js +239 -0
  91. package/dist/quality/complexity.js.map +1 -0
  92. package/dist/quality/config.d.ts +40 -0
  93. package/dist/quality/config.d.ts.map +1 -0
  94. package/dist/quality/config.js +77 -0
  95. package/dist/quality/config.js.map +1 -0
  96. package/dist/quality/crap.d.ts +11 -0
  97. package/dist/quality/crap.d.ts.map +1 -0
  98. package/dist/quality/crap.js +54 -0
  99. package/dist/quality/crap.js.map +1 -0
  100. package/dist/quality/languages.d.ts +25 -0
  101. package/dist/quality/languages.d.ts.map +1 -0
  102. package/dist/quality/languages.js +150 -0
  103. package/dist/quality/languages.js.map +1 -0
  104. package/dist/quality/report.d.ts +38 -0
  105. package/dist/quality/report.d.ts.map +1 -0
  106. package/dist/quality/report.js +251 -0
  107. package/dist/quality/report.js.map +1 -0
  108. package/dist/quality/scanner.d.ts +32 -0
  109. package/dist/quality/scanner.d.ts.map +1 -0
  110. package/dist/quality/scanner.js +127 -0
  111. package/dist/quality/scanner.js.map +1 -0
  112. package/dist/quality/tools.d.ts +28 -0
  113. package/dist/quality/tools.d.ts.map +1 -0
  114. package/dist/quality/tools.js +189 -0
  115. package/dist/quality/tools.js.map +1 -0
  116. package/dist/types/config.d.ts +148 -0
  117. package/dist/types/config.d.ts.map +1 -1
  118. package/dist/types/config.js +35 -0
  119. package/dist/types/config.js.map +1 -1
  120. package/docs/ATTRIBUTION.md +0 -1
  121. package/docs/INDEX.md +38 -4
  122. package/docs/analysis/MARKET_POSITION.md +179 -0
  123. package/docs/architecture/OVERVIEW.md +82 -18
  124. package/docs/architecture/PROTOCOL.md +1 -1
  125. package/docs/benchmarks/PAIRED_FINDINGS.md +106 -0
  126. package/docs/benchmarks/PAIRED_HARNESS.md +16 -0
  127. package/docs/benchmarks/README.md +59 -0
  128. package/docs/design/UAP_REACTOR.md +0 -1
  129. package/docs/getting-started/INSTALLATION.md +1 -1
  130. package/docs/guides/AUTOMATIC.md +0 -14
  131. package/docs/guides/AUTOMATIC_FEATURES.md +1 -9
  132. package/docs/guides/COORDINATION.md +1 -1
  133. package/docs/guides/DELIVERY_PIPELINE.md +5 -0
  134. package/docs/guides/DEPLOY_BATCHING.md +1 -1
  135. package/docs/guides/DROIDS_AND_SKILLS.md +1 -1
  136. package/docs/guides/LOCAL_MODELS.md +6 -1
  137. package/docs/guides/MCP_ROUTER.md +1 -1
  138. package/docs/guides/MEMORY.md +1 -1
  139. package/docs/guides/MULTI_MODEL.md +1 -1
  140. package/docs/guides/ORCHESTRATOR.md +1 -1
  141. package/docs/guides/POLICIES.md +19 -3
  142. package/docs/guides/QWEN38_EXL3.md +114 -0
  143. package/docs/guides/WORKTREE_WORKFLOW.md +45 -1
  144. package/docs/integrations/MCP_ROUTER.md +1 -4
  145. package/docs/plans/deliver-hardening-plan-2026-07-13.md +173 -0
  146. package/docs/plans/deliver-hardening-review-response-2026-07-13.md +180 -0
  147. package/docs/plans/k3-uap-uplift-validation.md +216 -0
  148. package/docs/plans/qwen38-uap-retest-plan.md +196 -0
  149. package/docs/reference/API.md +1 -1
  150. package/docs/reference/CLI.md +49 -14
  151. package/docs/reference/COMPARISON.md +248 -0
  152. package/docs/reference/CONFIGURATION.md +1 -3
  153. package/docs/reference/DATABASE_SCHEMA.md +1 -1
  154. package/docs/reference/FEATURES.md +3 -3
  155. package/docs/reference/PATTERNS.md +1 -1
  156. package/docs/reference/PLATFORMS.md +1 -1
  157. package/package.json +2 -2
  158. package/scripts/maintenance/update-skills.py +0 -22
  159. package/scripts/maintenance/verify-compliance.sh +3 -3
  160. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  161. package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
  162. package/src/policies/enforcers/adr_guard.py +0 -0
  163. package/src/policies/enforcers/bearer_lockdown.py +0 -0
  164. package/src/policies/enforcers/branch_freshness.py +0 -0
  165. package/src/policies/enforcers/design_token_gate.py +0 -0
  166. package/src/policies/enforcers/enforcement_self_protect.py +70 -0
  167. package/src/policies/enforcers/expert_review_required.py +22 -0
  168. package/src/policies/enforcers/iac_plan_destruction_check.py +0 -0
  169. package/src/policies/enforcers/quality_metrics_gate.py +447 -0
  170. package/src/policies/enforcers/ship_loop_gate.py +0 -0
  171. package/src/policies/enforcers/validate_plan_on_change.py +0 -0
  172. package/src/policies/enforcers/visual_verification.py +0 -0
  173. package/src/policies/enforcers/workdir_scope.py +0 -0
  174. package/src/policies/schemas/policies/expert-review-required.md +9 -1
  175. package/src/policies/schemas/policies/quality-metrics-gate.md +74 -0
  176. package/templates/CLAUDE.template.md +1 -1
  177. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  178. package/templates/hooks/pre-tool-use-bash.sh +50 -3
  179. package/templates/hooks/pre-tool-use-edit-write.sh +31 -0
  180. package/templates/hooks/session-start.sh +15 -0
  181. package/templates/hooks/uap-policy-gate.sh +187 -5
  182. package/templates/stryker.config.json +14 -0
  183. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
  184. package/tools/agents/scripts/anthropic_proxy.py +254 -28
  185. package/tools/agents/tests/run_acceptance.py +0 -0
  186. package/tools/agents/tests/test_client_disconnect.py +0 -0
  187. package/tools/agents/tests/test_cycle_break_exploration.py +0 -0
  188. package/tools/agents/tests/test_deferral_break.py +0 -0
  189. package/tools/agents/tests/test_delivery_enforcement_all_langs.py +0 -0
  190. package/tools/agents/tests/test_delivery_enforcement_exemptions.py +0 -0
  191. package/tools/agents/tests/test_delivery_enforcement_filepath.py +0 -0
  192. package/tools/agents/tests/test_delivery_enforcement_web_and_bash.py +0 -0
  193. package/tools/agents/tests/test_delivery_enforcement_worktree.py +0 -0
  194. package/tools/agents/tests/test_delivery_enforcement_write_complexity.py +0 -0
  195. package/tools/agents/tests/test_disconnect_watcher.py +0 -0
  196. package/tools/agents/tests/test_doubling_break.py +0 -0
  197. package/tools/agents/tests/test_empty_maxtokens_recovery.py +0 -0
  198. package/tools/agents/tests/test_empty_tool_loop_break.py +0 -0
  199. package/tools/agents/tests/test_enforcement_self_protect.py +90 -0
  200. package/tools/agents/tests/test_enforcer_escape_hatches.py +0 -0
  201. package/tools/agents/tests/test_error_loop_break.py +0 -0
  202. package/tools/agents/tests/test_expert_review_pr_scope.py +13 -5
  203. package/tools/agents/tests/test_fastpath_config.py +0 -0
  204. package/tools/agents/tests/test_finalize_suppression.py +0 -0
  205. package/tools/agents/tests/test_gate_evidence.py +0 -0
  206. package/tools/agents/tests/test_gate_failclosed_indirection.py +0 -0
  207. package/tools/agents/tests/test_gate_integrity.py +0 -0
  208. package/tools/agents/tests/test_live_deliver_kill.py +0 -0
  209. package/tools/agents/tests/test_malformed_unclosed_think.py +0 -0
  210. package/tools/agents/tests/test_mandate_beats_recon.py +0 -0
  211. package/tools/agents/tests/test_mandate_deliver.py +0 -0
  212. package/tools/agents/tests/test_non_stream_resp_log.py +0 -0
  213. package/tools/agents/tests/test_output_token_ceilings.py +0 -0
  214. package/tools/agents/tests/test_overflow_truncate_count_tokens.py +0 -0
  215. package/tools/agents/tests/test_path_containment.py +0 -0
  216. package/tools/agents/tests/test_path_normalizer_hardened.py +0 -0
  217. package/tools/agents/tests/test_repeat_call_guard.py +0 -0
  218. package/tools/agents/tests/test_repeat_guard.py +0 -0
  219. package/tools/agents/tests/test_session_admission.py +0 -0
  220. package/tools/agents/tests/test_stream_heartbeat.py +0 -0
  221. package/tools/agents/tests/test_stream_thinking_deltas.py +405 -0
  222. package/tools/agents/tests/test_stuck_break_hard.py +0 -0
  223. package/tools/agents/tests/test_stuck_break_reattach.py +0 -0
  224. package/tools/agents/tests/test_turn_count_breaker_periodic.py +0 -0
  225. package/tools/agents/tests/test_upstream_chokepoint.py +0 -0
  226. package/tools/agents/tests/test_upstream_model_aliases.py +0 -0
  227. package/tools/agents/tests/test_validate_plan_gate.py +0 -0
  228. package/tools/agents/tests/test_vision_passthrough.py +0 -0
  229. package/tools/agents/tests/test_workdir_scope_enforcer.py +0 -0
  230. package/dist/cli/rtk.d.ts +0 -34
  231. package/dist/cli/rtk.d.ts.map +0 -1
  232. package/dist/cli/rtk.js +0 -401
  233. package/dist/cli/rtk.js.map +0 -1
  234. package/docs/integrations/RTK.md +0 -113
  235. package/scripts/setup/install-rtk.sh +0 -184
  236. package/src/policies/enforcers/rtk_wrap.py +0 -205
  237. package/src/policies/schemas/policies/rtk-wrap.md +0 -50
  238. package/tools/agents/tests/test_rtk_wrap.py +0 -151
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Built-in complexity fallback scanner.
3
+ *
4
+ * When lizard / rust-code-analysis are installed their numbers are used
5
+ * instead (see tools.ts). This heuristic exists so the gate is not toothless
6
+ * on machines without external tooling. It is deliberately conservative:
7
+ * function-region detection is generic (brace-balance for C-family, indent
8
+ * for Python), and decision counting follows McCabe (cc = 1 + decisions) and
9
+ * the SonarSource cognitive rules (decisions weighted by nesting depth).
10
+ *
11
+ * Accuracy note: it can disagree with lizard on exotic syntax. That is fine
12
+ * for a ratcheted gate — the baseline freezes whatever the scanner reports,
13
+ * and a project needing exact numbers installs lizard.
14
+ *
15
+ * PARITY: quality_metrics_gate.py mirrors this file decision-for-decision.
16
+ * Change one, change both, and extend the parity corpus in
17
+ * test/quality/quality-gate-enforcer.test.ts.
18
+ */
19
+ import { stripNoise } from './languages.js';
20
+ /** Count non-empty lines of comment-stripped content. */
21
+ export function countLoc(stripped) {
22
+ let n = 0;
23
+ for (const line of stripped.split('\n'))
24
+ if (line.trim())
25
+ n++;
26
+ return n;
27
+ }
28
+ /** Boolean/ternary ops get a flat +1 cognitive (no nesting bump). */
29
+ const BOOL_OPS = new Set(['&&', '||', '?', 'and', 'or']);
30
+ function countDecisions(segment, facts, initialDepth = 0) {
31
+ let cyclomatic = 1;
32
+ let cognitive = 0;
33
+ // Region segments include the function's own opening brace; callers pass
34
+ // initialDepth = -1 there so nesting depth counts from INSIDE the function
35
+ // (SonarSource convention), not from the header line.
36
+ let depth = initialDepth;
37
+ // Normalize modern TS before tokenizing: `??` counts as ONE decision (a
38
+ // coalescing branch), `?.` counts as none (optional chaining is a guard,
39
+ // not a branch SonarSource-style). Without this `a?.b ?? c` reads as three
40
+ // phantom decisions. Keep in lockstep with quality_metrics_gate.py.
41
+ const normalized = segment.replace(/\?\?/g, ' ? ').replace(/\?\./g, '.');
42
+ // Word + operator scan in source order so cognitive nesting weighting works.
43
+ const tokenRe = /[A-Za-z_][A-Za-z0-9_]*|&&|\|\||[?{}]/g;
44
+ let m;
45
+ while ((m = tokenRe.exec(normalized)) !== null) {
46
+ const tok = m[0];
47
+ if (tok === '{') {
48
+ depth++;
49
+ continue;
50
+ }
51
+ if (tok === '}') {
52
+ depth = Math.max(0, depth - 1);
53
+ continue;
54
+ }
55
+ const isDecision = facts.decisionWords.includes(tok) || facts.decisionOps.includes(tok);
56
+ if (isDecision) {
57
+ cyclomatic++;
58
+ // SonarSource cognitive: +1 for the decision, +1 per nesting level.
59
+ // Binary boolean ops add 1 flat (no nesting bump). Keep BOOL_OPS in
60
+ // lockstep with quality_metrics_gate.py (_BOOL_OPS).
61
+ cognitive += BOOL_OPS.has(tok) ? 1 : 1 + Math.max(0, depth);
62
+ }
63
+ }
64
+ return { cyclomatic, cognitive };
65
+ }
66
+ /**
67
+ * Function-header detection, tried in order per line. Deliberately simple:
68
+ * keyword forms first (including generators `function*`), then arrow
69
+ * functions assigned to consts (pervasive in modern TS — missing them dumps
70
+ * their bodies into the <module> score), then a method-style fallback that
71
+ * rejects control-flow keywords. Built from strings (not regex literals) so
72
+ * this module's own <module> score does not count the patterns' `?`s —
73
+ * string contents are stripped before scanning.
74
+ */
75
+ const RE_FUNC_KW = new RegExp('\\b(?:export\\s+)?(?:default\\s+)?(?:async\\s+)?function\\s*\\*?\\s*([A-Za-z_$][\\w$]*)\\s*\\(');
76
+ const RE_NAMED_KW = new RegExp('\\b(?:def|fn|func|fun)\\s+([A-Za-z_]\\w*)\\s*\\(');
77
+ const RE_ARROW = new RegExp('^\\s*(?:export\\s+)?(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*(?::\\s*[^=]+?)?=' +
78
+ '\\s*(?:async\\s+)?(?:\\([^)]*\\)|[A-Za-z_$][\\w$]*)\\s*=>\\s*\\{');
79
+ const RE_METHOD = new RegExp('^\\s*(?:(?:public|private|protected|static|final|abstract|override|readonly|async|inline|virtual' +
80
+ '|constexpr|pub|unsafe|extern|internal|sealed|partial|suspend|open|export|default|get|set)\\s+)*' +
81
+ '([A-Za-z_$][\\w$]*)\\s*\\([^;{}]*\\)\\s*(?::\\s*[^{;]+?)?\\s*\\{');
82
+ const CONTROL_WORDS = new Set([
83
+ 'if', 'for', 'while', 'switch', 'catch', 'return', 'do', 'else', 'case',
84
+ 'with', 'synchronized', 'lock', 'using', 'foreach', 'when', 'unless', 'until',
85
+ ]);
86
+ /** Name of the function declared on this line, or null. */
87
+ export function functionHeader(line) {
88
+ let m = RE_FUNC_KW.exec(line) ?? RE_NAMED_KW.exec(line) ?? RE_ARROW.exec(line);
89
+ if (m)
90
+ return m[1];
91
+ m = RE_METHOD.exec(line);
92
+ if (m && !CONTROL_WORDS.has(m[1]))
93
+ return m[1];
94
+ return null;
95
+ }
96
+ function braceDelta(line) {
97
+ let n = 0;
98
+ for (let i = 0; i < line.length; i++) {
99
+ if (line[i] === '{')
100
+ n++;
101
+ else if (line[i] === '}')
102
+ n--;
103
+ }
104
+ return n;
105
+ }
106
+ function scoreRegion(seg, facts, name, line, initialDepth) {
107
+ const d = countDecisions(seg, facts, initialDepth);
108
+ return { name, line, cyclomatic: d.cyclomatic, cognitive: d.cognitive, nloc: countLoc(seg) };
109
+ }
110
+ /** Module-level decisions score as a pseudo-function, so module-level
111
+ * tangles are still gated (and stay in TS/Python signature parity). */
112
+ function moduleMetric(modLines, facts) {
113
+ const seg = modLines.join('\n');
114
+ const d = countDecisions(seg, facts);
115
+ if (d.cyclomatic <= 1)
116
+ return null;
117
+ return { name: '<module>', line: 1, cyclomatic: d.cyclomatic, cognitive: d.cognitive, nloc: countLoc(seg) };
118
+ }
119
+ /** Python-style: a region starts at `def name(` and ends at the first
120
+ * subsequent line whose indent <= the def's indent. */
121
+ function analyzeIndentRegions(lines, loc, facts) {
122
+ const functions = [];
123
+ const modBuf = [];
124
+ let open = null;
125
+ let buf = [];
126
+ const flush = () => {
127
+ if (!open)
128
+ return;
129
+ functions.push(scoreRegion(buf.join('\n'), facts, open.name, open.startLine, 0));
130
+ open = null;
131
+ buf = [];
132
+ };
133
+ for (let i = 0; i < lines.length; i++) {
134
+ const line = lines[i];
135
+ const dm = /^(\s*)(?:async\s+)?def\s+([A-Za-z_][\w]*)\s*\(/.exec(line);
136
+ if (dm) {
137
+ flush();
138
+ open = { name: dm[2], startLine: i + 1, indent: dm[1].length };
139
+ buf.push(line);
140
+ continue;
141
+ }
142
+ if (!open) {
143
+ modBuf.push(line);
144
+ continue;
145
+ }
146
+ const indent = /^(\s*)/.exec(line)?.[1].length ?? 0;
147
+ if (line.trim() && indent <= open.indent) {
148
+ flush();
149
+ modBuf.push(line); // the dedent line itself is module-level
150
+ continue;
151
+ }
152
+ buf.push(line);
153
+ }
154
+ flush();
155
+ const mod = moduleMetric(modBuf, facts);
156
+ if (mod)
157
+ functions.push(mod);
158
+ return { functions, loc };
159
+ }
160
+ /** Classify a detected header line: open a region for it, or score it
161
+ * in place (one-line functions) and stay at module level. */
162
+ function startBraceRegion(name, line, lineNo, depth, delta, facts, functions) {
163
+ if (delta > 0) {
164
+ return { region: { name, startLine: lineNo, startDepth: depth + delta, entered: true }, depth: depth + delta };
165
+ }
166
+ if (!line.includes('{')) {
167
+ // Multi-line signature — the opening brace is on a later line. Open the
168
+ // region now, anticipating the body one level above current depth (TS
169
+ // overload signatures collapse into their implementation; fine for a
170
+ // heuristic).
171
+ return { region: { name, startLine: lineNo, startDepth: depth + 1, entered: false }, depth };
172
+ }
173
+ // One-line function (`function f() { ... }` on one line): the brace
174
+ // balance never dips below startDepth, so without this branch the region
175
+ // stays open and swallows the REST OF THE FILE into this function's
176
+ // metrics. Score the header line alone.
177
+ functions.push(scoreRegion(line, facts, name, lineNo, 0));
178
+ return { region: null, depth: Math.max(0, depth + delta) };
179
+ }
180
+ /** Brace languages: find candidate headers, then brace-balance the region. */
181
+ function analyzeBraceRegions(lines, loc, facts) {
182
+ const functions = [];
183
+ const fileBuf = [];
184
+ let depth = 0;
185
+ let open = null;
186
+ let buf = [];
187
+ const closeRegion = () => {
188
+ if (!open)
189
+ return;
190
+ functions.push(scoreRegion(buf.join('\n'), facts, open.name, open.startLine, -1));
191
+ open = null;
192
+ buf = [];
193
+ };
194
+ for (let i = 0; i < lines.length; i++) {
195
+ const line = lines[i];
196
+ if (open) {
197
+ buf.push(line);
198
+ const d = braceDelta(line);
199
+ depth += d;
200
+ if (!open.entered) {
201
+ if (d > 0)
202
+ open.entered = true;
203
+ continue; // never close-check before the body opens
204
+ }
205
+ if (depth < open.startDepth)
206
+ closeRegion();
207
+ continue;
208
+ }
209
+ const name = functionHeader(line);
210
+ const delta = braceDelta(line);
211
+ if (!name) {
212
+ fileBuf.push(line);
213
+ depth = Math.max(0, depth + delta);
214
+ continue;
215
+ }
216
+ const started = startBraceRegion(name, line, i + 1, depth, delta, facts, functions);
217
+ if (started.region) {
218
+ open = started.region;
219
+ buf = [line];
220
+ }
221
+ depth = started.depth;
222
+ }
223
+ // Unbalanced braces — score what we saw rather than dropping it.
224
+ closeRegion();
225
+ const mod = moduleMetric(fileBuf, facts);
226
+ if (mod)
227
+ functions.push(mod);
228
+ return { functions, loc };
229
+ }
230
+ /** Split source into function-ish regions and score each. */
231
+ export function analyzeComplexity(content, facts) {
232
+ const stripped = stripNoise(content, facts.commentStyle);
233
+ const lines = stripped.split('\n');
234
+ const loc = countLoc(stripped);
235
+ return facts.indentBased
236
+ ? analyzeIndentRegions(lines, loc, facts)
237
+ : analyzeBraceRegions(lines, loc, facts);
238
+ }
239
+ //# sourceMappingURL=complexity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.js","sourceRoot":"","sources":["../../src/quality/complexity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export interface QualityThresholds {
2
+ /** Max cyclomatic complexity per function. */
3
+ maxCyclomatic: number;
4
+ /** Max cognitive complexity per function. */
5
+ maxCognitive: number;
6
+ /** Max Halstead difficulty per function (requires rust-code-analysis). */
7
+ maxHalsteadDifficulty: number;
8
+ /** Max non-blank, non-comment lines per file. */
9
+ maxLocPerFile: number;
10
+ /** Min line-coverage percent per file (0-100). */
11
+ minCoveragePct: number;
12
+ /** Max CRAP score per function: cc^2 * (1-cov)^3 + cc. */
13
+ maxCrap: number;
14
+ /** Max surviving mutants (changed-files incremental run). */
15
+ maxSurvivingMutants: number;
16
+ /** Max duplicated-block findings (jscpd clones over the token floor). */
17
+ maxDuplicateBlocks: number;
18
+ /** Max dead-code findings (knip / vulture / compiler dead_code). */
19
+ maxDeadCode: number;
20
+ /** Max explicit any/unknown type usages (TS: any/unknown, Py: typing.Any). */
21
+ maxAnyTypes: number;
22
+ }
23
+ export interface QualityConfig {
24
+ version: 1;
25
+ thresholds: QualityThresholds;
26
+ /** Glob-ish directory prefixes to exclude from scanning. */
27
+ excludeDirs: string[];
28
+ /** File extensions considered source (others are ignored). */
29
+ sourceExts: string[];
30
+ }
31
+ export declare const DEFAULT_THRESHOLDS: QualityThresholds;
32
+ export declare const DEFAULT_SOURCE_EXTS: string[];
33
+ export declare const DEFAULT_EXCLUDE_DIRS: string[];
34
+ export declare function configPath(root: string): string;
35
+ export declare function defaultConfig(): QualityConfig;
36
+ /** Load the config, or null when the gate is inactive (no config file). */
37
+ export declare function loadQualityConfig(root: string): QualityConfig | null;
38
+ /** Write the default config (uap quality init). */
39
+ export declare function writeDefaultConfig(root: string): string;
40
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/quality/config.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,iBAAiB,CAAC;IAC9B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,eAAO,MAAM,kBAAkB,EAAE,iBAWhC,CAAC;AAEF,eAAO,MAAM,mBAAmB,UAI/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,UAIhC,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,aAAa,IAAI,aAAa,CAO7C;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAiBpE;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Quality-metrics gate configuration.
3
+ *
4
+ * Lives at `.uap/quality-metrics.json` (committed, per project). The gate is
5
+ * INACTIVE (fails open) when the file is absent — quality policing is opt-in
6
+ * per project via `uap quality init`, exactly like the design-token gate is
7
+ * inactive without a DESIGN.md.
8
+ *
9
+ * Every threshold mirrors the policing targets:
10
+ * cyclomatic < 22 · cognitive < 22 · halstead difficulty < 80
11
+ * LOC/file < 500 · coverage 100% · CRAP < 25 · surviving mutants 0
12
+ * dead code 0 · redundant (duplicate) code 0 · explicit any/unknown 0
13
+ */
14
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
15
+ import { join } from 'path';
16
+ export const DEFAULT_THRESHOLDS = {
17
+ maxCyclomatic: 22,
18
+ maxCognitive: 22,
19
+ maxHalsteadDifficulty: 80,
20
+ maxLocPerFile: 500,
21
+ minCoveragePct: 100,
22
+ maxCrap: 25,
23
+ maxSurvivingMutants: 0,
24
+ maxDuplicateBlocks: 0,
25
+ maxDeadCode: 0,
26
+ maxAnyTypes: 0,
27
+ };
28
+ export const DEFAULT_SOURCE_EXTS = [
29
+ '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
30
+ '.py', '.java', '.cs', '.cpp', '.cc', '.cxx', '.c', '.h', '.hpp',
31
+ '.rs', '.go', '.rb', '.php', '.swift', '.kt', '.scala',
32
+ ];
33
+ export const DEFAULT_EXCLUDE_DIRS = [
34
+ 'node_modules', 'dist', 'build', 'out', 'target', 'coverage',
35
+ '.git', '.worktrees', 'vendor', '__pycache__', '.venv', 'venv',
36
+ 'benchmarks', 'benchmark-results', 'third_party', 'generated',
37
+ ];
38
+ export function configPath(root) {
39
+ return join(root, '.uap', 'quality-metrics.json');
40
+ }
41
+ export function defaultConfig() {
42
+ return {
43
+ version: 1,
44
+ thresholds: { ...DEFAULT_THRESHOLDS },
45
+ excludeDirs: [...DEFAULT_EXCLUDE_DIRS],
46
+ sourceExts: [...DEFAULT_SOURCE_EXTS],
47
+ };
48
+ }
49
+ /** Load the config, or null when the gate is inactive (no config file). */
50
+ export function loadQualityConfig(root) {
51
+ const p = configPath(root);
52
+ if (!existsSync(p))
53
+ return null;
54
+ try {
55
+ const raw = JSON.parse(readFileSync(p, 'utf-8'));
56
+ const d = defaultConfig();
57
+ return {
58
+ version: 1,
59
+ thresholds: { ...d.thresholds, ...(raw.thresholds ?? {}) },
60
+ excludeDirs: raw.excludeDirs ?? d.excludeDirs,
61
+ sourceExts: raw.sourceExts ?? d.sourceExts,
62
+ };
63
+ }
64
+ catch {
65
+ // A corrupt config must not silently disable policing, but crashing the
66
+ // gate is worse — fail open and let `uap quality check` surface the error.
67
+ return null;
68
+ }
69
+ }
70
+ /** Write the default config (uap quality init). */
71
+ export function writeDefaultConfig(root) {
72
+ const p = configPath(root);
73
+ mkdirSync(join(root, '.uap'), { recursive: true });
74
+ writeFileSync(p, JSON.stringify(defaultConfig(), null, 2) + '\n');
75
+ return p;
76
+ }
77
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/quality/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare function crapScore(cyclomatic: number, coverageFraction: number): number;
2
+ /**
3
+ * Parse per-file line-coverage fractions from a vitest/istanbul
4
+ * coverage-summary.json (`<root>/coverage/coverage-summary.json`).
5
+ * Returns null when absent — coverage metrics are then skipped (fail-open
6
+ * with a logged warning), matching the missing-tool policy.
7
+ */
8
+ export declare function loadCoverageSummary(root: string): Map<string, number> | null;
9
+ /** Resolve the coverage fraction for a scanned file, tolerating path shape. */
10
+ export declare function coverageFor(coverage: Map<string, number>, root: string, file: string): number | null;
11
+ //# sourceMappingURL=crap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crap.d.ts","sourceRoot":"","sources":["../../src/quality/crap.ts"],"names":[],"mappings":"AAaA,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAG9E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAkB5E;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASpG"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * CRAP (Change Risk Anti-Patterns) score: cc^2 * (1 - cov)^3 + cc
3
+ * where cc is cyclomatic complexity and cov is the line-coverage fraction.
4
+ *
5
+ * Function-level coverage is not reliably available from every provider, so
6
+ * the gate computes CRAP per function using the FILE's line-coverage fraction
7
+ * — an approximation documented in the policy. A file with 0% coverage makes
8
+ * CRAP = cc^2 + cc, so untested complex functions blow past the threshold
9
+ * fast, which is exactly the pressure the metric exists to apply.
10
+ */
11
+ import { existsSync, readFileSync } from 'fs';
12
+ import { join } from 'path';
13
+ export function crapScore(cyclomatic, coverageFraction) {
14
+ const c = Math.min(1, Math.max(0, coverageFraction));
15
+ return cyclomatic * cyclomatic * Math.pow(1 - c, 3) + cyclomatic;
16
+ }
17
+ /**
18
+ * Parse per-file line-coverage fractions from a vitest/istanbul
19
+ * coverage-summary.json (`<root>/coverage/coverage-summary.json`).
20
+ * Returns null when absent — coverage metrics are then skipped (fail-open
21
+ * with a logged warning), matching the missing-tool policy.
22
+ */
23
+ export function loadCoverageSummary(root) {
24
+ const p = join(root, 'coverage', 'coverage-summary.json');
25
+ if (!existsSync(p))
26
+ return null;
27
+ try {
28
+ const raw = JSON.parse(readFileSync(p, 'utf-8'));
29
+ const out = new Map();
30
+ for (const [file, data] of Object.entries(raw)) {
31
+ if (file === 'total')
32
+ continue;
33
+ const pct = data?.lines?.pct;
34
+ if (typeof pct === 'number')
35
+ out.set(file, pct / 100);
36
+ }
37
+ return out;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /** Resolve the coverage fraction for a scanned file, tolerating path shape. */
44
+ export function coverageFor(coverage, root, file) {
45
+ const norm = file.replace(/\\/g, '/');
46
+ for (const [covFile, pct] of coverage) {
47
+ const cf = covFile.replace(/\\/g, '/');
48
+ if (cf === norm || cf === join(root, norm).replace(/\\/g, '/') || cf.endsWith(`/${norm}`)) {
49
+ return pct;
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ //# sourceMappingURL=crap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crap.js","sourceRoot":"","sources":["../../src/quality/crap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,gBAAwB;IACpE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACrD,OAAO,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,uBAAuB,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAG9C,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,IAAI,IAAI,KAAK,OAAO;gBAAE,SAAS;YAC/B,MAAM,GAAG,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC;YAC7B,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,QAA6B,EAAE,IAAY,EAAE,IAAY;IACnF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtC,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACvC,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YAC1F,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Language detection + lexical facts for the built-in scanner.
3
+ *
4
+ * The scanner is a *fallback*: when lizard / rust-code-analysis are installed
5
+ * their (authoritative) numbers win. Without them the gate still needs teeth,
6
+ * so we approximate with a generic brace/indent model driven by the facts
7
+ * below. Heuristic by design — documented as such in the policy.
8
+ */
9
+ export type CommentStyle = 'c' | 'hash';
10
+ export interface LanguageFacts {
11
+ name: string;
12
+ commentStyle: CommentStyle;
13
+ /** True for indent-delimited languages (python): no braces delimit blocks. */
14
+ indentBased: boolean;
15
+ /**
16
+ * Decision keywords counted for cyclomatic complexity. Word-boundary matched
17
+ * against code with strings/comments stripped.
18
+ */
19
+ decisionWords: string[];
20
+ /** Operator decision tokens (counted like keywords): `&&`, `||`, `?` etc. */
21
+ decisionOps: string[];
22
+ }
23
+ export declare function languageForFile(path: string): LanguageFacts | null;
24
+ export declare function stripNoise(content: string, style: CommentStyle): string;
25
+ //# sourceMappingURL=languages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"languages.d.ts","sourceRoot":"","sources":["../../src/quality/languages.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,YAAY,GAAG,GAAG,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,CAAC;IAC3B,8EAA8E;IAC9E,WAAW,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAmED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAKlE;AAqDD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAiBvE"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Language detection + lexical facts for the built-in scanner.
3
+ *
4
+ * The scanner is a *fallback*: when lizard / rust-code-analysis are installed
5
+ * their (authoritative) numbers win. Without them the gate still needs teeth,
6
+ * so we approximate with a generic brace/indent model driven by the facts
7
+ * below. Heuristic by design — documented as such in the policy.
8
+ */
9
+ const C_FAMILY = {
10
+ commentStyle: 'c',
11
+ indentBased: false,
12
+ decisionWords: ['if', 'for', 'while', 'case', 'catch', 'elif'],
13
+ decisionOps: ['&&', '||', '?'],
14
+ };
15
+ const FACTS = {
16
+ typescript: { name: 'typescript', ...C_FAMILY },
17
+ javascript: { name: 'javascript', ...C_FAMILY },
18
+ java: { name: 'java', ...C_FAMILY },
19
+ csharp: { name: 'csharp', ...C_FAMILY },
20
+ cpp: { name: 'cpp', ...C_FAMILY },
21
+ c: { name: 'c', ...C_FAMILY },
22
+ go: {
23
+ name: 'go',
24
+ commentStyle: 'c',
25
+ indentBased: false,
26
+ decisionWords: ['if', 'for', 'case', 'select'],
27
+ decisionOps: ['&&', '||'],
28
+ },
29
+ rust: {
30
+ name: 'rust',
31
+ commentStyle: 'c',
32
+ indentBased: false,
33
+ decisionWords: ['if', 'for', 'while', 'loop', 'match', 'catch'],
34
+ decisionOps: ['&&', '||', '?'],
35
+ },
36
+ python: {
37
+ name: 'python',
38
+ commentStyle: 'hash',
39
+ indentBased: true,
40
+ decisionWords: ['if', 'elif', 'for', 'while', 'except', 'with', 'assert'],
41
+ decisionOps: ['and', 'or'],
42
+ },
43
+ ruby: {
44
+ name: 'ruby',
45
+ commentStyle: 'hash',
46
+ indentBased: false,
47
+ decisionWords: ['if', 'elsif', 'unless', 'while', 'until', 'when', 'rescue'],
48
+ decisionOps: ['&&', '||'],
49
+ },
50
+ php: { name: 'php', ...C_FAMILY },
51
+ swift: { name: 'swift', ...C_FAMILY },
52
+ kotlin: { name: 'kotlin', ...C_FAMILY },
53
+ scala: { name: 'scala', ...C_FAMILY },
54
+ };
55
+ const EXT_MAP = {
56
+ '.ts': 'typescript', '.tsx': 'typescript', '.mts': 'typescript', '.cts': 'typescript',
57
+ '.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript',
58
+ '.py': 'python',
59
+ '.java': 'java',
60
+ '.cs': 'csharp',
61
+ '.cpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp', '.hpp': 'cpp', '.hxx': 'cpp',
62
+ '.c': 'c', '.h': 'c',
63
+ '.rs': 'rust',
64
+ '.go': 'go',
65
+ '.rb': 'ruby',
66
+ '.php': 'php',
67
+ '.swift': 'swift',
68
+ '.kt': 'kotlin', '.kts': 'kotlin',
69
+ '.scala': 'scala',
70
+ };
71
+ export function languageForFile(path) {
72
+ const m = /\.[^./\\]+$/.exec(path);
73
+ if (!m)
74
+ return null;
75
+ const key = EXT_MAP[m[0].toLowerCase()];
76
+ return key ? FACTS[key] : null;
77
+ }
78
+ const QUOTE_OF = { sq: "'", dq: '"', tpl: '`' };
79
+ function codeStep(ch, next, style, out, i) {
80
+ if (ch === '/' && next === '/')
81
+ return { next: i + 2, state: 'line' };
82
+ if (ch === '/' && next === '*')
83
+ return { next: i + 2, state: 'block' };
84
+ if (style === 'hash' && ch === '#')
85
+ return { next: i + 1, state: 'line' };
86
+ if (ch === "'") {
87
+ out.push(' ');
88
+ return { next: i + 1, state: 'sq' };
89
+ }
90
+ if (ch === '"') {
91
+ out.push(' ');
92
+ return { next: i + 1, state: 'dq' };
93
+ }
94
+ if (ch === '`') {
95
+ out.push(' ');
96
+ return { next: i + 1, state: 'tpl' };
97
+ }
98
+ out.push(ch);
99
+ return { next: i + 1, state: 'code' };
100
+ }
101
+ function lineStep(ch, out, i) {
102
+ if (ch === '\n') {
103
+ out.push('\n');
104
+ return { next: i + 1, state: 'code' };
105
+ }
106
+ return { next: i + 1, state: 'line' };
107
+ }
108
+ function blockStep(ch, next, out, i) {
109
+ if (ch === '*' && next === '/')
110
+ return { next: i + 2, state: 'code' };
111
+ if (ch === '\n')
112
+ out.push('\n'); // keep line numbers stable
113
+ return { next: i + 1, state: 'block' };
114
+ }
115
+ function stringStep(ch, state, out, i) {
116
+ if (ch === '\\')
117
+ return { next: i + 2, state };
118
+ if (ch === QUOTE_OF[state])
119
+ return { next: i + 1, state: 'code' };
120
+ if (ch === '\n') {
121
+ out.push('\n');
122
+ // Unterminated single/double-quoted string ends at the newline; template
123
+ // literals span lines.
124
+ return { next: i + 1, state: state === 'tpl' ? 'tpl' : 'code' };
125
+ }
126
+ return { next: i + 1, state };
127
+ }
128
+ export function stripNoise(content, style) {
129
+ const out = [];
130
+ let state = 'code';
131
+ let i = 0;
132
+ const n = content.length;
133
+ while (i < n) {
134
+ const ch = content[i];
135
+ const next = i + 1 < n ? content[i + 1] : '';
136
+ let step;
137
+ if (state === 'code')
138
+ step = codeStep(ch, next, style, out, i);
139
+ else if (state === 'line')
140
+ step = lineStep(ch, out, i);
141
+ else if (state === 'block')
142
+ step = blockStep(ch, next, out, i);
143
+ else
144
+ step = stringStep(ch, state, out, i);
145
+ i = step.next;
146
+ state = step.state;
147
+ }
148
+ return out.join('');
149
+ }
150
+ //# sourceMappingURL=languages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"languages.js","sourceRoot":"","sources":["../../src/quality/languages.ts"],"names":[],"mappings":"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"}