@hawkeyexl/manni 4.3.1 → 4.4.1

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 (225) hide show
  1. package/README.md +9 -1
  2. package/dist/batch-GFNLTGOH.js +36 -0
  3. package/dist/build-COYIQ25L.js +31 -0
  4. package/dist/calibrate-MDBLJKEE.js +31 -0
  5. package/dist/capture-LRML2PKV.js +32 -0
  6. package/dist/check-ASPIHA6B.js +40 -0
  7. package/dist/check-ASPIHA6B.js.map +1 -0
  8. package/dist/check-EDLBYL5N.js +27 -0
  9. package/dist/check-EDLBYL5N.js.map +1 -0
  10. package/dist/check-HYNGXYJV.js +18 -0
  11. package/dist/check-HYNGXYJV.js.map +1 -0
  12. package/dist/chunk-2B7ZNTPV.js +230 -0
  13. package/dist/chunk-2B7ZNTPV.js.map +1 -0
  14. package/dist/chunk-2H7UOFLK.js +11 -0
  15. package/dist/chunk-2H7UOFLK.js.map +1 -0
  16. package/dist/chunk-37LP5HMZ.js +1042 -0
  17. package/dist/chunk-37LP5HMZ.js.map +1 -0
  18. package/dist/chunk-3VK37OR2.js +2957 -0
  19. package/dist/chunk-3VK37OR2.js.map +1 -0
  20. package/dist/chunk-4IUC2MNL.js +2165 -0
  21. package/dist/chunk-4IUC2MNL.js.map +1 -0
  22. package/dist/{chunk-3R23C5DT.js → chunk-4TSWU2SU.js} +2 -14
  23. package/dist/chunk-4TSWU2SU.js.map +1 -0
  24. package/dist/chunk-57NEQRVO.js +10921 -0
  25. package/dist/chunk-57NEQRVO.js.map +1 -0
  26. package/dist/chunk-6JSSEWBG.js +6737 -0
  27. package/dist/chunk-6JSSEWBG.js.map +1 -0
  28. package/dist/chunk-6OYEI2VV.js +88 -0
  29. package/dist/chunk-6OYEI2VV.js.map +1 -0
  30. package/dist/chunk-77AINBYM.js +19 -0
  31. package/dist/chunk-77AINBYM.js.map +1 -0
  32. package/dist/chunk-7UKO3ASZ.js +54 -0
  33. package/dist/chunk-7UKO3ASZ.js.map +1 -0
  34. package/dist/chunk-A5ULMVHQ.js +164 -0
  35. package/dist/chunk-A5ULMVHQ.js.map +1 -0
  36. package/dist/chunk-C4SQM22E.js +299 -0
  37. package/dist/chunk-C4SQM22E.js.map +1 -0
  38. package/dist/chunk-CK7SKVHR.js +1042 -0
  39. package/dist/chunk-CK7SKVHR.js.map +1 -0
  40. package/dist/{chunk-G5CM2VGQ.js → chunk-DXNZS72W.js} +8 -94
  41. package/dist/chunk-DXNZS72W.js.map +1 -0
  42. package/dist/chunk-EPH54CAY.js +374 -0
  43. package/dist/chunk-EPH54CAY.js.map +1 -0
  44. package/dist/{chunk-KJR7OVDX.js → chunk-FBEQCK47.js} +56 -137
  45. package/dist/chunk-FBEQCK47.js.map +1 -0
  46. package/dist/{chunk-IOYXPBCL.js → chunk-G3T47CFV.js} +1 -7
  47. package/dist/{chunk-IOYXPBCL.js.map → chunk-G3T47CFV.js.map} +1 -1
  48. package/dist/chunk-GCQRPUSB.js +1287 -0
  49. package/dist/chunk-GCQRPUSB.js.map +1 -0
  50. package/dist/chunk-GLP5PSXB.js +72 -0
  51. package/dist/chunk-GLP5PSXB.js.map +1 -0
  52. package/dist/chunk-I2AH3CJJ.js +1192 -0
  53. package/dist/chunk-I2AH3CJJ.js.map +1 -0
  54. package/dist/chunk-IDV6HJCB.js +388 -0
  55. package/dist/chunk-IDV6HJCB.js.map +1 -0
  56. package/dist/chunk-IKEWBMCN.js +98 -0
  57. package/dist/chunk-IKEWBMCN.js.map +1 -0
  58. package/dist/chunk-JCDXE76J.js +52 -0
  59. package/dist/chunk-JCDXE76J.js.map +1 -0
  60. package/dist/chunk-JXLTXMJ7.js +455 -0
  61. package/dist/chunk-JXLTXMJ7.js.map +1 -0
  62. package/dist/chunk-LJ2RDH3F.js +49 -0
  63. package/dist/chunk-LJ2RDH3F.js.map +1 -0
  64. package/dist/chunk-M2JCK5F6.js +805 -0
  65. package/dist/chunk-M2JCK5F6.js.map +1 -0
  66. package/dist/chunk-M3W7J6MU.js +4398 -0
  67. package/dist/chunk-M3W7J6MU.js.map +1 -0
  68. package/dist/chunk-MMTSSTG7.js +23 -0
  69. package/dist/chunk-MMTSSTG7.js.map +1 -0
  70. package/dist/chunk-MNH7QO4Z.js +15 -0
  71. package/dist/chunk-MNH7QO4Z.js.map +1 -0
  72. package/dist/chunk-MWJLZMBL.js +934 -0
  73. package/dist/chunk-MWJLZMBL.js.map +1 -0
  74. package/dist/chunk-MYMBCTDE.js +387 -0
  75. package/dist/chunk-MYMBCTDE.js.map +1 -0
  76. package/dist/chunk-NCPWXHDO.js +683 -0
  77. package/dist/chunk-NCPWXHDO.js.map +1 -0
  78. package/dist/chunk-NLXTXE5Y.js +1661 -0
  79. package/dist/chunk-NLXTXE5Y.js.map +1 -0
  80. package/dist/{chunk-CFDUZRM2.js → chunk-NXV7WE2D.js} +32 -240
  81. package/dist/chunk-NXV7WE2D.js.map +1 -0
  82. package/dist/chunk-OWBRDNRZ.js +16 -0
  83. package/dist/chunk-OWBRDNRZ.js.map +1 -0
  84. package/dist/{chunk-KTSJ2ZHA.js → chunk-PAU352SV.js} +5 -3
  85. package/dist/{chunk-KTSJ2ZHA.js.map → chunk-PAU352SV.js.map} +1 -1
  86. package/dist/chunk-PCE7QHXJ.js +68 -0
  87. package/dist/chunk-PCE7QHXJ.js.map +1 -0
  88. package/dist/chunk-PIKOVN6W.js +1651 -0
  89. package/dist/chunk-PIKOVN6W.js.map +1 -0
  90. package/dist/chunk-PNPQTHBT.js +17 -0
  91. package/dist/chunk-PNPQTHBT.js.map +1 -0
  92. package/dist/chunk-PU6DFJMY.js +1975 -0
  93. package/dist/chunk-PU6DFJMY.js.map +1 -0
  94. package/dist/chunk-Q35YIDBV.js +1202 -0
  95. package/dist/chunk-Q35YIDBV.js.map +1 -0
  96. package/dist/{chunk-5HNHEUD5.js → chunk-QQUKGCAJ.js} +3 -3
  97. package/dist/chunk-QRWGPQKO.js +198 -0
  98. package/dist/chunk-QRWGPQKO.js.map +1 -0
  99. package/dist/{chunk-UBMMXS2Y.js → chunk-QZ6LRSNV.js} +69 -48
  100. package/dist/{chunk-UBMMXS2Y.js.map → chunk-QZ6LRSNV.js.map} +1 -1
  101. package/dist/chunk-RL5XWQOL.js +3872 -0
  102. package/dist/chunk-RL5XWQOL.js.map +1 -0
  103. package/dist/chunk-RNVYGWIC.js +30 -0
  104. package/dist/chunk-RNVYGWIC.js.map +1 -0
  105. package/dist/chunk-SE4JN5XN.js +19 -0
  106. package/dist/chunk-SE4JN5XN.js.map +1 -0
  107. package/dist/chunk-SKSDRUUK.js +622 -0
  108. package/dist/chunk-SKSDRUUK.js.map +1 -0
  109. package/dist/chunk-TIUTIOFB.js +25 -0
  110. package/dist/chunk-TIUTIOFB.js.map +1 -0
  111. package/dist/chunk-TK3FC4RF.js +3090 -0
  112. package/dist/chunk-TK3FC4RF.js.map +1 -0
  113. package/dist/chunk-TU2WUBVZ.js +2 -0
  114. package/dist/chunk-TU2WUBVZ.js.map +1 -0
  115. package/dist/chunk-TZOYZK2E.js +98 -0
  116. package/dist/chunk-TZOYZK2E.js.map +1 -0
  117. package/dist/chunk-UJCVAWP7.js +178 -0
  118. package/dist/chunk-UJCVAWP7.js.map +1 -0
  119. package/dist/chunk-UKZNLVJW.js +17 -0
  120. package/dist/chunk-UKZNLVJW.js.map +1 -0
  121. package/dist/{chunk-HAPTXWU2.js → chunk-UQISLDAV.js} +4 -4
  122. package/dist/chunk-WB3QM6PP.js +5440 -0
  123. package/dist/chunk-WB3QM6PP.js.map +1 -0
  124. package/dist/chunk-YB4IBW3M.js +96 -0
  125. package/dist/chunk-YB4IBW3M.js.map +1 -0
  126. package/dist/chunk-YEUYKR62.js +72 -0
  127. package/dist/chunk-YEUYKR62.js.map +1 -0
  128. package/dist/chunk-YJOGUXGP.js +634 -0
  129. package/dist/chunk-YJOGUXGP.js.map +1 -0
  130. package/dist/chunk-YNHZHSSM.js +41 -0
  131. package/dist/chunk-YNHZHSSM.js.map +1 -0
  132. package/dist/chunk-YTURO7SI.js +979 -0
  133. package/dist/chunk-YTURO7SI.js.map +1 -0
  134. package/dist/chunk-ZXRAE55H.js +31 -0
  135. package/dist/chunk-ZXRAE55H.js.map +1 -0
  136. package/dist/cli-3BIBYHFK.js +473 -0
  137. package/dist/cli-3BIBYHFK.js.map +1 -0
  138. package/dist/cli-673OTRGE.js +28 -0
  139. package/dist/cli-673OTRGE.js.map +1 -0
  140. package/dist/cli-6HIDIFVT.js +1203 -0
  141. package/dist/cli-6HIDIFVT.js.map +1 -0
  142. package/dist/cli-6UB5N6CU.js +232 -0
  143. package/dist/cli-6UB5N6CU.js.map +1 -0
  144. package/dist/cli-LFP5ZGYS.js +346 -0
  145. package/dist/cli-LFP5ZGYS.js.map +1 -0
  146. package/dist/cli-MN7PYMBI.js +552 -0
  147. package/dist/cli-MN7PYMBI.js.map +1 -0
  148. package/dist/cli-PYPX6O6E.js +739 -0
  149. package/dist/cli-PYPX6O6E.js.map +1 -0
  150. package/dist/cli-RPM5PELX.js +626 -0
  151. package/dist/cli-RPM5PELX.js.map +1 -0
  152. package/dist/cli-VI7VHWNZ.js +423 -0
  153. package/dist/cli-VI7VHWNZ.js.map +1 -0
  154. package/dist/cli.d.ts +12 -2
  155. package/dist/cli.js +109 -7661
  156. package/dist/cli.js.map +1 -1
  157. package/dist/docmeta.js +15 -3
  158. package/dist/docmeta.js.map +1 -1
  159. package/dist/github-6QMYOHC3.js +27 -0
  160. package/dist/github-6QMYOHC3.js.map +1 -0
  161. package/dist/github-SXPGP5DB.js +32 -0
  162. package/dist/github-SXPGP5DB.js.map +1 -0
  163. package/dist/index.d.ts +65 -3
  164. package/dist/index.js +407 -337
  165. package/dist/index.js.map +1 -1
  166. package/dist/json-7WV7KL6H.js +17 -0
  167. package/dist/json-7WV7KL6H.js.map +1 -0
  168. package/dist/json-SY7KLNC7.js +35 -0
  169. package/dist/json-SY7KLNC7.js.map +1 -0
  170. package/dist/lint-ASMJLLPA.js +28 -0
  171. package/dist/lint-ASMJLLPA.js.map +1 -0
  172. package/dist/list-KZNVTNVC.js +31 -0
  173. package/dist/list-KZNVTNVC.js.map +1 -0
  174. package/dist/list-Q57YTFUQ.js +29 -0
  175. package/dist/list-Q57YTFUQ.js.map +1 -0
  176. package/dist/page-KSGV5RD4.js +41 -0
  177. package/dist/page-KSGV5RD4.js.map +1 -0
  178. package/dist/picker-3XF36MJF.js +14 -0
  179. package/dist/picker-3XF36MJF.js.map +1 -0
  180. package/dist/pretty-A5EGTN35.js +37 -0
  181. package/dist/pretty-A5EGTN35.js.map +1 -0
  182. package/dist/pretty-CXSDXNAS.js +43 -0
  183. package/dist/pretty-CXSDXNAS.js.map +1 -0
  184. package/dist/reporters-HUY7UXFS.js +42 -0
  185. package/dist/reporters-HUY7UXFS.js.map +1 -0
  186. package/dist/reporters-K2VUKSAK.js +71 -0
  187. package/dist/reporters-K2VUKSAK.js.map +1 -0
  188. package/dist/reporters-M6LJ2IYU.js +21 -0
  189. package/dist/reporters-M6LJ2IYU.js.map +1 -0
  190. package/dist/run-3DYJNRIG.js +33 -0
  191. package/dist/run-3DYJNRIG.js.map +1 -0
  192. package/dist/term-BIQUPMOR.js +1592 -0
  193. package/dist/term-BIQUPMOR.js.map +1 -0
  194. package/dist/types-Y6TXHM7M.js +10 -0
  195. package/dist/types-Y6TXHM7M.js.map +1 -0
  196. package/dist/validate-53RKM2XG.js +16 -0
  197. package/dist/validate-53RKM2XG.js.map +1 -0
  198. package/package.json +1 -1
  199. package/plugin/manni/.claude-plugin/plugin.json +9 -0
  200. package/plugin/manni/hooks/hooks.json +69 -0
  201. package/plugin/manni/hooks/manni.mjs +157 -0
  202. package/plugin/manni/skills/check/SKILL.md +20 -0
  203. package/plugin/manni/skills/evals/SKILL.md +27 -0
  204. package/plugin/manni/skills/fix/SKILL.md +56 -0
  205. package/plugin/manni/skills/setup/SKILL.md +41 -0
  206. package/dist/batch-A5HZKYIW.js +0 -18
  207. package/dist/calibrate-S5K6QHUY.js +0 -13
  208. package/dist/capture-OZEZDABQ.js +0 -15
  209. package/dist/chunk-3R23C5DT.js.map +0 -1
  210. package/dist/chunk-CFDUZRM2.js.map +0 -1
  211. package/dist/chunk-G5CM2VGQ.js.map +0 -1
  212. package/dist/chunk-KJR7OVDX.js.map +0 -1
  213. package/dist/chunk-V4KUVE47.js +0 -27170
  214. package/dist/chunk-V4KUVE47.js.map +0 -1
  215. package/dist/chunk-ZQBTK3DO.js +0 -26518
  216. package/dist/chunk-ZQBTK3DO.js.map +0 -1
  217. package/dist/picker-6HRMETE7.js +0 -12
  218. package/plugin/tracevals/.claude-plugin/plugin.json +0 -9
  219. package/plugin/tracevals/hooks/hooks.json +0 -17
  220. /package/dist/{batch-A5HZKYIW.js.map → batch-GFNLTGOH.js.map} +0 -0
  221. /package/dist/{calibrate-S5K6QHUY.js.map → build-COYIQ25L.js.map} +0 -0
  222. /package/dist/{capture-OZEZDABQ.js.map → calibrate-MDBLJKEE.js.map} +0 -0
  223. /package/dist/{picker-6HRMETE7.js.map → capture-LRML2PKV.js.map} +0 -0
  224. /package/dist/{chunk-5HNHEUD5.js.map → chunk-QQUKGCAJ.js.map} +0 -0
  225. /package/dist/{chunk-HAPTXWU2.js.map → chunk-UQISLDAV.js.map} +0 -0
@@ -0,0 +1,634 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ URI_BASE_ID,
4
+ artifactLocation,
5
+ fileUri,
6
+ normalizeRoot
7
+ } from "./chunk-GLP5PSXB.js";
8
+ import {
9
+ LintError,
10
+ matchSections,
11
+ occurrenceRange
12
+ } from "./chunk-CK7SKVHR.js";
13
+ import {
14
+ REPORT_FORMAT_LIST,
15
+ renderJunit
16
+ } from "./chunk-IDV6HJCB.js";
17
+ import {
18
+ isErrorSeverity
19
+ } from "./chunk-57NEQRVO.js";
20
+ import {
21
+ palette
22
+ } from "./chunk-RNVYGWIC.js";
23
+ import {
24
+ escapeWorkflowCommandMessage,
25
+ escapeWorkflowCommandProperty
26
+ } from "./chunk-MNH7QO4Z.js";
27
+ import {
28
+ package_default
29
+ } from "./chunk-UJCVAWP7.js";
30
+
31
+ // src/lint/core/rule-id.ts
32
+ var RULE_ID_PREFIX = "manni:lint";
33
+ var TOOL_NAME = "manni";
34
+ var STRUCTURE_JOB = "structure";
35
+ function ruleName(type) {
36
+ return type.replace(/_error$/, "").replace(/_/g, "-");
37
+ }
38
+ function ruleId(type, job = STRUCTURE_JOB) {
39
+ return `${RULE_ID_PREFIX}/${job}/${ruleName(type)}`;
40
+ }
41
+
42
+ // src/lint/reporters/junit.ts
43
+ var JUNIT_CLASSNAME = "manni.lint";
44
+ function toFieldError(finding) {
45
+ return {
46
+ schema: RULE_ID_PREFIX,
47
+ instancePath: "",
48
+ message: finding.heading != null ? `${finding.heading}: ${finding.message}` : finding.message,
49
+ keyword: `${STRUCTURE_JOB}/${ruleName(finding.type)}`,
50
+ severity: finding.severity,
51
+ line: finding.position.start.line,
52
+ col: finding.position.start.column
53
+ };
54
+ }
55
+ function toValidationResults(run) {
56
+ return run.results.filter((result) => result.skipped == null).map((result) => ({
57
+ file: result.file,
58
+ // meta's `format` is the extractor that read the file. A lint result does
59
+ // not carry the parser that produced its tree, and no reporter reached
60
+ // through here reads the field, so it names the domain rather than
61
+ // inventing a format the run never recorded.
62
+ format: "lint",
63
+ // meta's invariant, not a count: `ok` is "no error-severity finding".
64
+ // Read as "no findings at all", a file whose only finding is a warning
65
+ // renders as a `✗` through meta's own pretty reporter - which is a
66
+ // legitimate consumer, since this function is exported - while lint's
67
+ // exit code says the run passed.
68
+ ok: !result.findings.some(isErrorSeverity),
69
+ schemas: [RULE_ID_PREFIX],
70
+ errors: result.findings.map(toFieldError)
71
+ }));
72
+ }
73
+ function renderJunit2(run) {
74
+ return renderJunit(toValidationResults(run), {
75
+ classname: JUNIT_CLASSNAME
76
+ });
77
+ }
78
+
79
+ // src/lint/reporters/sarif.ts
80
+ var SARIF_VERSION = "2.1.0";
81
+ var SARIF_SCHEMA = "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json";
82
+ var INFORMATION_URI = "https://github.com/hawkeyexl/manni";
83
+ var LEVELS = {
84
+ notice: "note",
85
+ warning: "warning",
86
+ error: "error"
87
+ };
88
+ var SKIP_DESCRIPTIONS = {
89
+ "no-template": "File was not linted: no template resolved for it.",
90
+ "unsupported-format": "File was not linted: no parser handles its format.",
91
+ unreadable: "File was not linted: it could not be read."
92
+ };
93
+ function region(position) {
94
+ return {
95
+ startLine: position.start.line,
96
+ startColumn: position.start.column,
97
+ endLine: position.end.line,
98
+ endColumn: position.end.column
99
+ };
100
+ }
101
+ function location(file, root, position) {
102
+ return {
103
+ physicalLocation: {
104
+ artifactLocation: artifactLocation(file, root),
105
+ region: position ? region(position) : void 0
106
+ }
107
+ };
108
+ }
109
+ function messageText(finding) {
110
+ return finding.heading != null ? `${finding.heading}: ${finding.message}` : finding.message;
111
+ }
112
+ function words(id) {
113
+ return id.split(/[^A-Za-z0-9]+/).filter(Boolean);
114
+ }
115
+ function pascalCase(id) {
116
+ return words(id).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
117
+ }
118
+ function humanize(id) {
119
+ const text = words(id).join(" ");
120
+ return text.charAt(0).toUpperCase() + text.slice(1);
121
+ }
122
+ function buildRules(run) {
123
+ const indexOf = /* @__PURE__ */ new Map();
124
+ const order = [];
125
+ const severities = /* @__PURE__ */ new Map();
126
+ for (const result of run.results) {
127
+ for (const finding of result.findings) {
128
+ let seen = severities.get(finding.type);
129
+ if (!seen) {
130
+ seen = /* @__PURE__ */ new Set();
131
+ severities.set(finding.type, seen);
132
+ indexOf.set(finding.type, order.length);
133
+ order.push(finding.type);
134
+ }
135
+ seen.add(finding.severity);
136
+ }
137
+ }
138
+ const descriptors = order.map((type) => {
139
+ const rule = ruleName(type);
140
+ const descriptor = {
141
+ id: ruleId(type),
142
+ name: pascalCase(rule),
143
+ shortDescription: { text: humanize(rule) }
144
+ };
145
+ const [only, ...rest] = [...severities.get(type) ?? []];
146
+ if (only !== void 0 && rest.length === 0) {
147
+ descriptor.defaultConfiguration = { level: LEVELS[only] };
148
+ }
149
+ return descriptor;
150
+ });
151
+ return { descriptors, indexOf };
152
+ }
153
+ function toResult(finding, file, rules, root) {
154
+ return {
155
+ ruleId: ruleId(finding.type),
156
+ // Always populated in practice, since the index is built from these same
157
+ // findings. Omitted rather than faked if it ever is not: a wrong index
158
+ // points the alert at somebody else's rule, which is worse than none.
159
+ ruleIndex: rules.indexOf.get(finding.type),
160
+ level: LEVELS[finding.severity],
161
+ message: { text: messageText(finding) },
162
+ locations: [location(file, root, finding.position)],
163
+ properties: finding.heading != null ? { heading: finding.heading } : void 0
164
+ };
165
+ }
166
+ function buildSkips(run, root) {
167
+ const indexOf = /* @__PURE__ */ new Map();
168
+ const descriptors = [];
169
+ const notifications = [];
170
+ for (const result of run.results) {
171
+ const reason = result.skipped;
172
+ if (reason == null) continue;
173
+ let index = indexOf.get(reason);
174
+ if (index === void 0) {
175
+ index = descriptors.length;
176
+ indexOf.set(reason, index);
177
+ descriptors.push({
178
+ id: reason,
179
+ name: pascalCase(reason),
180
+ shortDescription: { text: SKIP_DESCRIPTIONS[reason] }
181
+ });
182
+ }
183
+ notifications.push({
184
+ // Declared in `tool.driver.notifications` and referenced by id *and*
185
+ // index, for the same reason results reference their rules both ways.
186
+ descriptor: { id: reason, index },
187
+ level: "note",
188
+ message: { text: skipMessage(result, reason) },
189
+ locations: [location(result.file, root)]
190
+ });
191
+ }
192
+ return { descriptors, notifications };
193
+ }
194
+ function skipMessage(result, reason) {
195
+ return result.reason ?? SKIP_DESCRIPTIONS[reason];
196
+ }
197
+ function renderSarif(run, opts = {}) {
198
+ const root = normalizeRoot(opts.root ?? process.cwd());
199
+ const rules = buildRules(run);
200
+ const skips = buildSkips(run, root);
201
+ const results = run.results.flatMap(
202
+ (result) => result.findings.map(
203
+ (finding) => toResult(finding, result.file, rules, root)
204
+ )
205
+ );
206
+ const driver = {
207
+ name: "manni-lint",
208
+ informationUri: INFORMATION_URI,
209
+ version: package_default.version,
210
+ // Emitted even when empty: results point into this array, so a consumer
211
+ // always looks here, and a stable shape is cheaper than a special case.
212
+ rules: rules.descriptors,
213
+ notifications: skips.descriptors.length > 0 ? skips.descriptors : void 0
214
+ };
215
+ const invocation = {
216
+ // Findings are the tool doing its job, not failing at it. This would only
217
+ // be false if manni lint itself could not run, and that path exits 2
218
+ // before any report is rendered.
219
+ executionSuccessful: true,
220
+ toolExecutionNotifications: skips.notifications.length > 0 ? skips.notifications : void 0
221
+ };
222
+ const log = {
223
+ $schema: SARIF_SCHEMA,
224
+ version: SARIF_VERSION,
225
+ runs: [
226
+ {
227
+ tool: { driver },
228
+ // Declared unconditionally: it is what makes every relative `uri` in
229
+ // this report mean anything, and a reader should not have to infer the
230
+ // base from whether some result happened to use it.
231
+ originalUriBaseIds: { [URI_BASE_ID]: { uri: fileUri(root) } },
232
+ invocations: [invocation],
233
+ results
234
+ }
235
+ ]
236
+ };
237
+ return JSON.stringify(log, null, 2);
238
+ }
239
+
240
+ // src/lint/reporters/alignment.ts
241
+ var LABEL_WIDTH = 22;
242
+ var ARROW = "\u2190";
243
+ var ELLIPSIS = "\u2026";
244
+ var TIMES = "\xD7";
245
+ function pad(label) {
246
+ return label.length >= LABEL_WIDTH ? `${label} ` : label.padEnd(LABEL_WIDTH + 1);
247
+ }
248
+ function titleText(title) {
249
+ return title === null ? "(no heading)" : `"${title}"`;
250
+ }
251
+ function ruleLabel(rule) {
252
+ if (rule.id !== void 0) return rule.id;
253
+ if (typeof rule.heading === "string") return rule.heading;
254
+ return "(any)";
255
+ }
256
+ function pageHeading(tree) {
257
+ const [only] = tree.sections;
258
+ if (tree.sections.length === 1 && only && only.level <= 1) {
259
+ const text2 = only.title || null;
260
+ if (text2 === null) return { text: null, note: "no heading" };
261
+ const synthesized = only.titlePosition !== null && tree.frontmatterPosition !== null && only.titlePosition.start.offset === tree.frontmatterPosition.start.offset && only.titlePosition.end.offset === tree.frontmatterPosition.end.offset;
262
+ return { text: text2, note: synthesized ? "synthesized from frontmatter" : null };
263
+ }
264
+ const raw = tree.frontmatter?.["title"];
265
+ const text = typeof raw === "string" && raw !== "" ? raw : null;
266
+ return { text, note: text === null ? "no heading" : "synthesized from frontmatter" };
267
+ }
268
+ function pageSections(tree) {
269
+ const [only] = tree.sections;
270
+ if (tree.sections.length === 1 && only && only.level <= 1) return only.sections;
271
+ return tree.sections;
272
+ }
273
+ function matchedRow(depth, run) {
274
+ const head = run[0];
275
+ if (!head) return { depth, text: `${pad("(empty run)")}${ARROW} (missing)` };
276
+ const rule = head.rule;
277
+ const first = head.section;
278
+ const last = (run[run.length - 1] ?? head).section;
279
+ const label = run.length === 1 ? ruleLabel(rule) : `${ruleLabel(rule)} ${TIMES}${run.length}`;
280
+ const coerced = run.length === 1 && head.coerced ? " (coerced)" : "";
281
+ const arrow = run.length === 1 ? `${titleText(first.title || null)}${coerced}` : `${titleText(first.title || null)} ${ELLIPSIS} ${titleText(last.title || null)}`;
282
+ return { depth, text: `${pad(label)}${ARROW} ${arrow}` };
283
+ }
284
+ function absentLabel(rule) {
285
+ return occurrenceRange(rule).min > 0 ? "(missing)" : "(none)";
286
+ }
287
+ function missingRows(depth, rule) {
288
+ if (!rule.repeat) {
289
+ return [{ depth, text: `${pad(ruleLabel(rule))}${ARROW} ${absentLabel(rule)}` }];
290
+ }
291
+ const label = absentLabel(rule);
292
+ const rows = [{ depth, text: pad(rule.id ?? "(repeat)").trimEnd() }];
293
+ for (const member of rule.repeat) {
294
+ rows.push({ depth: depth + 1, text: `${pad(ruleLabel(member))}${ARROW} ${label}` });
295
+ }
296
+ return rows;
297
+ }
298
+ function insertMissing(matched, missing) {
299
+ const out = [];
300
+ let mi = 0;
301
+ for (const entry of matched) {
302
+ while (mi < missing.length) {
303
+ const next = missing[mi];
304
+ if (!next || entry.index !== null && next.index >= entry.index) break;
305
+ out.push(...next.rows);
306
+ mi++;
307
+ }
308
+ out.push(...entry.rows);
309
+ }
310
+ while (mi < missing.length) {
311
+ const next = missing[mi];
312
+ if (!next) break;
313
+ out.push(...next.rows);
314
+ mi++;
315
+ }
316
+ return out;
317
+ }
318
+ function alignLevel(rules, sections, parent, depth) {
319
+ if (rules === void 0) return [];
320
+ const { matches } = matchSections(sections, rules, { parent });
321
+ const ruleIndex = new Map(rules.map((r, i2) => [r, i2]));
322
+ const rootOf = /* @__PURE__ */ new Map();
323
+ for (const rule of rules) {
324
+ if (rule.repeat) for (const member of rule.repeat) rootOf.set(member, rule);
325
+ else rootOf.set(rule, rule);
326
+ }
327
+ const rootOfRule = (rule) => rootOf.get(rule) ?? rule;
328
+ const matchedRoots = new Set(matches.map((m) => rootOfRule(m.rule)));
329
+ const bySection = new Map(matches.map((m) => [m.section, m]));
330
+ const matched = [];
331
+ let i = 0;
332
+ while (i < sections.length) {
333
+ const section = sections[i];
334
+ if (!section) break;
335
+ const match = bySection.get(section);
336
+ if (!match) {
337
+ matched.push({
338
+ index: null,
339
+ rows: [{ depth, text: `(unexpected) ${titleText(section.title || null)}` }]
340
+ });
341
+ i++;
342
+ continue;
343
+ }
344
+ const root = rootOfRule(match.rule);
345
+ if (root.repeat) {
346
+ const taken = [];
347
+ while (i < sections.length) {
348
+ const here = sections[i];
349
+ if (!here) break;
350
+ const next = bySection.get(here);
351
+ if (!next || rootOfRule(next.rule) !== root) break;
352
+ taken.push(next);
353
+ i++;
354
+ }
355
+ const rows2 = [{ depth, text: pad(root.id ?? "(repeat)").trimEnd() }];
356
+ let run2 = [];
357
+ const flushMember = () => {
358
+ if (run2.length === 0) return;
359
+ rows2.push(matchedRow(depth + 1, run2));
360
+ for (const m of run2) {
361
+ rows2.push(...alignLevel(m.rule.sections, m.section.sections, m.section, depth + 2));
362
+ }
363
+ run2 = [];
364
+ };
365
+ for (const m of taken) {
366
+ const first = run2[0];
367
+ if (first && first.rule !== m.rule) flushMember();
368
+ run2.push(m);
369
+ }
370
+ flushMember();
371
+ const takenMembers = new Set(taken.map((m) => m.rule));
372
+ for (const member of root.repeat) {
373
+ if (takenMembers.has(member)) continue;
374
+ rows2.push({ depth: depth + 1, text: `${pad(ruleLabel(member))}${ARROW} (missing)` });
375
+ }
376
+ matched.push({ index: ruleIndex.get(root) ?? null, rows: rows2 });
377
+ continue;
378
+ }
379
+ const run = [match];
380
+ i++;
381
+ while (i < sections.length) {
382
+ const here = sections[i];
383
+ if (!here) break;
384
+ const next = bySection.get(here);
385
+ if (!next || next.rule !== match.rule) break;
386
+ run.push(next);
387
+ i++;
388
+ }
389
+ const rows = [matchedRow(depth, run)];
390
+ for (const m of run) {
391
+ rows.push(...alignLevel(m.rule.sections, m.section.sections, m.section, depth + 1));
392
+ }
393
+ matched.push({ index: ruleIndex.get(match.rule) ?? null, rows });
394
+ }
395
+ const missing = rules.filter((rule) => !matchedRoots.has(rule)).map((rule) => {
396
+ const index = ruleIndex.get(rule);
397
+ if (index === void 0) {
398
+ throw new LintError("alignLevel: rule missing from its own index");
399
+ }
400
+ return { index, rows: missingRows(depth, rule) };
401
+ });
402
+ return insertMissing(matched, missing);
403
+ }
404
+ function explainAlignment(tree, template) {
405
+ const heading = pageHeading(tree);
406
+ const arrow = heading.text !== null ? `${titleText(heading.text)}${heading.note ? ` (${heading.note})` : ""}` : `(${heading.note ?? "no heading"})`;
407
+ const rows = [{ depth: 0, text: `${pad("(page)")}${ARROW} ${arrow}` }];
408
+ rows.push(...alignLevel(template.sections, pageSections(tree), null, 1));
409
+ return rows;
410
+ }
411
+ function formatAlignment(rows) {
412
+ return rows.map((row) => `${" ".repeat(row.depth)}${row.text}`);
413
+ }
414
+
415
+ // src/lint/reporters/index.ts
416
+ function plural(n, word) {
417
+ return `${n} ${word}${n === 1 ? "" : "s"}`;
418
+ }
419
+ function locate(finding) {
420
+ return `${finding.position.start.line}:${finding.position.start.column}`;
421
+ }
422
+ function describeFinding(finding) {
423
+ return finding.heading != null ? `${finding.heading}: ${finding.message}` : finding.message;
424
+ }
425
+ function levelPrefix(c, severity) {
426
+ if (severity === "error") return "";
427
+ return `${severity === "notice" ? c.dim("notice") : c.yellow("warning")} `;
428
+ }
429
+ function renderPretty(run, opts = {}) {
430
+ const c = palette(opts.color ?? false);
431
+ const lines = [];
432
+ let warnings = 0;
433
+ let notices = 0;
434
+ for (const result of run.results) {
435
+ if (result.skipped != null) {
436
+ const why = result.reason ?? result.skipped;
437
+ lines.push(`${c.yellow("-")} ${result.file} ${c.dim(`skipped: ${why}`)}`);
438
+ continue;
439
+ }
440
+ if (result.success && result.findings.length === 0) {
441
+ lines.push(`${c.green("\u2713")} ${result.file}`);
442
+ continue;
443
+ }
444
+ const mark = result.success ? c.yellow("\u26A0") : c.red("\u2717");
445
+ lines.push(`${mark} ${result.file}`);
446
+ for (const finding of result.findings) {
447
+ if (finding.severity === "warning") warnings++;
448
+ else if (finding.severity === "notice") notices++;
449
+ lines.push(
450
+ ` ${c.dim(locate(finding))} ${c.cyan(ruleId(finding.type))} ${levelPrefix(c, finding.severity)}${describeFinding(finding)}`
451
+ );
452
+ }
453
+ }
454
+ const { checked, passed, failed, skipped } = run.summary;
455
+ const warningsText = warnings > 0 ? `, ${plural(warnings, "warning")}` : "";
456
+ const noticesText = notices > 0 ? `, ${plural(notices, "notice")}` : "";
457
+ const summary = `${plural(checked, "file")} checked, ${passed} passed, ${failed} failed, ${skipped} skipped${warningsText}${noticesText}`;
458
+ if (lines.length > 0) lines.push("");
459
+ lines.push(failed > 0 ? c.red(summary) : c.green(summary));
460
+ return lines.join("\n");
461
+ }
462
+ function renderJson(run) {
463
+ const results = run.results.map((result) => ({
464
+ file: result.file,
465
+ success: result.success,
466
+ errors: result.findings.map((finding) => ({
467
+ type: finding.type,
468
+ // Additive, and deliberately beside `type` rather than instead of it.
469
+ // `ruleId` is the family id every other reporter files this finding
470
+ // under; `tool` names which tool produced it, the question a second
471
+ // lint job makes worth asking.
472
+ ruleId: ruleId(finding.type),
473
+ tool: TOOL_NAME,
474
+ heading: finding.heading,
475
+ message: finding.message,
476
+ position: finding.position,
477
+ // Additive too, and the reason it has to be: `success: true` beside a
478
+ // non-empty `errors` array is exactly what a warning-only file looks
479
+ // like now that `success` means "no error-severity finding" rather than
480
+ // "no findings". Without this key a consumer has no way to tell that
481
+ // apart from an error the JSON shape simply forgot to fail on.
482
+ severity: finding.severity
483
+ })),
484
+ // Additive, and the one thing this shape could not say. A skipped file is
485
+ // `{success: false, errors: []}`, which is also what a failure whose
486
+ // finding vanished looks like - so a consumer counting failures counted a
487
+ // file nothing read as a file that was read and found wanting. Null rather
488
+ // than absent, because a key that comes and goes makes "not skipped" and
489
+ // "an older manni" the same observation. The prose `reason` stays off the
490
+ // wire; it is a diagnostic for the pretty and SARIF reports.
491
+ skipped: result.skipped ?? null
492
+ }));
493
+ return JSON.stringify(results, null, 2);
494
+ }
495
+ function renderGithub(run) {
496
+ const lines = [];
497
+ for (const result of run.results) {
498
+ for (const finding of result.findings) {
499
+ const params = [
500
+ `file=${escapeWorkflowCommandProperty(result.file)}`,
501
+ `line=${finding.position.start.line}`,
502
+ `col=${finding.position.start.column}`,
503
+ `title=${escapeWorkflowCommandProperty(ruleId(finding.type))}`
504
+ ];
505
+ const message = escapeWorkflowCommandMessage(describeFinding(finding));
506
+ lines.push(`::${finding.severity} ${params.join(",")}::${message}`);
507
+ }
508
+ }
509
+ return lines.join("\n");
510
+ }
511
+ function alignmentFor(result) {
512
+ const source = result.alignment;
513
+ if (!source) return null;
514
+ return formatAlignment(explainAlignment(source.tree, source.template));
515
+ }
516
+ function renderExplain(run, opts = {}) {
517
+ const c = palette(opts.color ?? false);
518
+ const lines = [];
519
+ for (const result of run.results) {
520
+ const chosen = result.template;
521
+ lines.push(`${chosen ? c.cyan("\u25B8") : c.dim("-")} ${c.bold(result.file)}`);
522
+ const steps = result.resolution?.steps ?? [];
523
+ if (steps.length === 0) {
524
+ lines.push(` ${c.dim("(no resolution recorded)")}`);
525
+ }
526
+ for (const step of steps) {
527
+ const mark = step.ref ? c.green("\u2192") : c.dim("\xB7");
528
+ const label = step.ref ? c.bold(step.ref) : c.dim(step.detail);
529
+ const suffix = step.ref ? ` ${c.dim(step.detail)}` : "";
530
+ lines.push(` ${mark} ${step.stage.padEnd(20)} ${label}${suffix}`);
531
+ }
532
+ const alignment = chosen ? alignmentFor(result) : null;
533
+ if (alignment && alignment.length > 0) {
534
+ lines.push(` ${c.dim("alignment")}`);
535
+ for (const row of alignment) lines.push(` ${row}`);
536
+ }
537
+ const cause = result.resolution?.cause;
538
+ if (cause === "unknown-type") {
539
+ const type = result.resolution?.unknownType ?? "(none recorded)";
540
+ const near = result.resolution?.suggestions ?? [];
541
+ const known = result.resolution?.knownTypes ?? [];
542
+ const hint = near.length ? `; did you mean ${near.join(", ")}?` : known.length ? `; known doctypes: ${known.join(", ")}` : "";
543
+ lines.push(` ${c.red("\u2717")} no template serves type "${type}"${hint}`);
544
+ } else if (cause === "no-type") {
545
+ lines.push(` ${c.dim("skipped: the page declares no type")}`);
546
+ }
547
+ lines.push("");
548
+ }
549
+ const routed = run.results.filter((r) => r.template != null).length;
550
+ lines.push(
551
+ `${run.results.length} file${run.results.length === 1 ? "" : "s"}, ${routed} routed, ${run.results.length - routed} unrouted`
552
+ );
553
+ return lines.join("\n");
554
+ }
555
+ function render(run, format, opts = {}) {
556
+ switch (format) {
557
+ case "json":
558
+ return renderJson(run);
559
+ case "github":
560
+ return renderGithub(run);
561
+ case "sarif":
562
+ return renderSarif(run, opts.root === void 0 ? {} : { root: opts.root });
563
+ case "junit":
564
+ return renderJunit2(run);
565
+ case "explain":
566
+ return renderExplain(run, opts);
567
+ case "pretty":
568
+ return renderPretty(run, opts);
569
+ default: {
570
+ const unreachable = format;
571
+ throw new LintError(
572
+ `Unknown report format ${JSON.stringify(unreachable)}. Use ${REPORT_FORMAT_LIST}.`
573
+ );
574
+ }
575
+ }
576
+ }
577
+ function templateLine(c, entry) {
578
+ const title = entry.title !== "" ? ` ${c.dim("\u2014")} ${entry.title}` : "";
579
+ const types = entry.types.length > 0 ? entry.types.join(", ") : "(no types declared)";
580
+ return ` ${c.cyan(entry.id)}${title} ${c.dim(`types: ${types}`)} ${c.dim(`[${entry.source}]`)}`;
581
+ }
582
+ function renderTemplates(info, format, opts = {}) {
583
+ if (format === "json") return JSON.stringify(info, null, 2);
584
+ const c = palette(opts.color ?? false);
585
+ const lines = [c.bold("Templates:")];
586
+ if (info.templates.length === 0) {
587
+ lines.push(c.dim(" (none)"));
588
+ } else {
589
+ for (const entry of info.templates) lines.push(templateLine(c, entry));
590
+ }
591
+ return lines.join("\n");
592
+ }
593
+ function formatLine(c, entry) {
594
+ const head = ` ${c.cyan(entry.name)} ${entry.label} (${entry.extensions.join(", ")})`;
595
+ if (entry.kinds.length === 0) return head;
596
+ return `${head} ${c.dim(`kinds: ${entry.kinds.join(", ")}`)}`;
597
+ }
598
+ function renderTools(tools, format, opts = {}) {
599
+ if (format === "json") return JSON.stringify(tools, null, 2);
600
+ const c = palette(opts.color ?? false);
601
+ const lines = [c.bold("Jobs:")];
602
+ for (const entry of tools) {
603
+ const state = [
604
+ entry.configured ? "configured" : "not configured",
605
+ entry.available ? "available" : "unavailable"
606
+ ].join(", ");
607
+ const version = entry.version ?? "\u2014";
608
+ lines.push(
609
+ ` ${c.cyan(entry.job)} tool: ${c.bold(entry.tool)} ${version} [${state}]`
610
+ );
611
+ lines.push(` config: ${c.dim(entry.config)}`);
612
+ lines.push(` ${c.dim("formats:")}`);
613
+ for (const info of entry.formats) lines.push(formatLine(c, info));
614
+ }
615
+ return lines.join("\n");
616
+ }
617
+
618
+ export {
619
+ RULE_ID_PREFIX,
620
+ TOOL_NAME,
621
+ ruleName,
622
+ ruleId,
623
+ toValidationResults,
624
+ renderJunit2 as renderJunit,
625
+ renderSarif,
626
+ renderPretty,
627
+ renderJson,
628
+ renderGithub,
629
+ renderExplain,
630
+ render,
631
+ renderTemplates,
632
+ renderTools
633
+ };
634
+ //# sourceMappingURL=chunk-YJOGUXGP.js.map