archcheck 0.2.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 (251) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +536 -0
  3. package/dist/archcheck.d.ts +99 -0
  4. package/dist/archcheck.d.ts.map +1 -0
  5. package/dist/archcheck.js +339 -0
  6. package/dist/archcheck.js.map +1 -0
  7. package/dist/baseline/index.d.ts +29 -0
  8. package/dist/baseline/index.d.ts.map +1 -0
  9. package/dist/baseline/index.js +116 -0
  10. package/dist/baseline/index.js.map +1 -0
  11. package/dist/cli/args.d.ts +36 -0
  12. package/dist/cli/args.d.ts.map +1 -0
  13. package/dist/cli/args.js +233 -0
  14. package/dist/cli/args.js.map +1 -0
  15. package/dist/cli/index.d.ts +4 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +219 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/version.d.ts +2 -0
  20. package/dist/cli/version.d.ts.map +1 -0
  21. package/dist/cli/version.js +29 -0
  22. package/dist/cli/version.js.map +1 -0
  23. package/dist/contracts/banned-syntax.d.ts +48 -0
  24. package/dist/contracts/banned-syntax.d.ts.map +1 -0
  25. package/dist/contracts/banned-syntax.js +201 -0
  26. package/dist/contracts/banned-syntax.js.map +1 -0
  27. package/dist/contracts/declared-field.d.ts +39 -0
  28. package/dist/contracts/declared-field.d.ts.map +1 -0
  29. package/dist/contracts/declared-field.js +142 -0
  30. package/dist/contracts/declared-field.js.map +1 -0
  31. package/dist/contracts/encapsulation.d.ts +28 -0
  32. package/dist/contracts/encapsulation.d.ts.map +1 -0
  33. package/dist/contracts/encapsulation.js +130 -0
  34. package/dist/contracts/encapsulation.js.map +1 -0
  35. package/dist/contracts/index.d.ts +10 -0
  36. package/dist/contracts/index.d.ts.map +1 -0
  37. package/dist/contracts/index.js +9 -0
  38. package/dist/contracts/index.js.map +1 -0
  39. package/dist/contracts/judgement.d.ts +21 -0
  40. package/dist/contracts/judgement.d.ts.map +1 -0
  41. package/dist/contracts/judgement.js +109 -0
  42. package/dist/contracts/judgement.js.map +1 -0
  43. package/dist/contracts/layers.d.ts +75 -0
  44. package/dist/contracts/layers.d.ts.map +1 -0
  45. package/dist/contracts/layers.js +244 -0
  46. package/dist/contracts/layers.js.map +1 -0
  47. package/dist/contracts/naming.d.ts +21 -0
  48. package/dist/contracts/naming.d.ts.map +1 -0
  49. package/dist/contracts/naming.js +120 -0
  50. package/dist/contracts/naming.js.map +1 -0
  51. package/dist/contracts/registry.d.ts +23 -0
  52. package/dist/contracts/registry.d.ts.map +1 -0
  53. package/dist/contracts/registry.js +48 -0
  54. package/dist/contracts/registry.js.map +1 -0
  55. package/dist/contracts/required-file.d.ts +29 -0
  56. package/dist/contracts/required-file.d.ts.map +1 -0
  57. package/dist/contracts/required-file.js +131 -0
  58. package/dist/contracts/required-file.js.map +1 -0
  59. package/dist/contracts/types.d.ts +61 -0
  60. package/dist/contracts/types.d.ts.map +1 -0
  61. package/dist/contracts/types.js +2 -0
  62. package/dist/contracts/types.js.map +1 -0
  63. package/dist/coverage/index.d.ts +55 -0
  64. package/dist/coverage/index.d.ts.map +1 -0
  65. package/dist/coverage/index.js +68 -0
  66. package/dist/coverage/index.js.map +1 -0
  67. package/dist/emit/collect.d.ts +20 -0
  68. package/dist/emit/collect.d.ts.map +1 -0
  69. package/dist/emit/collect.js +17 -0
  70. package/dist/emit/collect.js.map +1 -0
  71. package/dist/emit/header.d.ts +21 -0
  72. package/dist/emit/header.d.ts.map +1 -0
  73. package/dist/emit/header.js +20 -0
  74. package/dist/emit/header.js.map +1 -0
  75. package/dist/emit/index.d.ts +57 -0
  76. package/dist/emit/index.d.ts.map +1 -0
  77. package/dist/emit/index.js +128 -0
  78. package/dist/emit/index.js.map +1 -0
  79. package/dist/emit/merge.d.ts +23 -0
  80. package/dist/emit/merge.d.ts.map +1 -0
  81. package/dist/emit/merge.js +71 -0
  82. package/dist/emit/merge.js.map +1 -0
  83. package/dist/emit/write.d.ts +20 -0
  84. package/dist/emit/write.d.ts.map +1 -0
  85. package/dist/emit/write.js +61 -0
  86. package/dist/emit/write.js.map +1 -0
  87. package/dist/exceptions/index.d.ts +46 -0
  88. package/dist/exceptions/index.d.ts.map +1 -0
  89. package/dist/exceptions/index.js +117 -0
  90. package/dist/exceptions/index.js.map +1 -0
  91. package/dist/fs/index.d.ts +12 -0
  92. package/dist/fs/index.d.ts.map +1 -0
  93. package/dist/fs/index.js +78 -0
  94. package/dist/fs/index.js.map +1 -0
  95. package/dist/graph/cache.d.ts +12 -0
  96. package/dist/graph/cache.d.ts.map +1 -0
  97. package/dist/graph/cache.js +76 -0
  98. package/dist/graph/cache.js.map +1 -0
  99. package/dist/graph/edges.d.ts +16 -0
  100. package/dist/graph/edges.d.ts.map +1 -0
  101. package/dist/graph/edges.js +161 -0
  102. package/dist/graph/edges.js.map +1 -0
  103. package/dist/graph/index.d.ts +15 -0
  104. package/dist/graph/index.d.ts.map +1 -0
  105. package/dist/graph/index.js +90 -0
  106. package/dist/graph/index.js.map +1 -0
  107. package/dist/graph/match.d.ts +12 -0
  108. package/dist/graph/match.d.ts.map +1 -0
  109. package/dist/graph/match.js +35 -0
  110. package/dist/graph/match.js.map +1 -0
  111. package/dist/graph/program.d.ts +12 -0
  112. package/dist/graph/program.d.ts.map +1 -0
  113. package/dist/graph/program.js +54 -0
  114. package/dist/graph/program.js.map +1 -0
  115. package/dist/graph/types.d.ts +55 -0
  116. package/dist/graph/types.d.ts.map +1 -0
  117. package/dist/graph/types.js +2 -0
  118. package/dist/graph/types.js.map +1 -0
  119. package/dist/index.d.ts +21 -0
  120. package/dist/index.d.ts.map +1 -0
  121. package/dist/index.js +20 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/init/index.d.ts +23 -0
  124. package/dist/init/index.d.ts.map +1 -0
  125. package/dist/init/index.js +218 -0
  126. package/dist/init/index.js.map +1 -0
  127. package/dist/normalize/identity.d.ts +4 -0
  128. package/dist/normalize/identity.d.ts.map +1 -0
  129. package/dist/normalize/identity.js +33 -0
  130. package/dist/normalize/identity.js.map +1 -0
  131. package/dist/normalize/index.d.ts +3 -0
  132. package/dist/normalize/index.d.ts.map +1 -0
  133. package/dist/normalize/index.js +3 -0
  134. package/dist/normalize/index.js.map +1 -0
  135. package/dist/normalize/normalize.d.ts +34 -0
  136. package/dist/normalize/normalize.d.ts.map +1 -0
  137. package/dist/normalize/normalize.js +91 -0
  138. package/dist/normalize/normalize.js.map +1 -0
  139. package/dist/probes/graph.d.ts +19 -0
  140. package/dist/probes/graph.d.ts.map +1 -0
  141. package/dist/probes/graph.js +181 -0
  142. package/dist/probes/graph.js.map +1 -0
  143. package/dist/probes/index.d.ts +5 -0
  144. package/dist/probes/index.d.ts.map +1 -0
  145. package/dist/probes/index.js +5 -0
  146. package/dist/probes/index.js.map +1 -0
  147. package/dist/probes/lint.d.ts +17 -0
  148. package/dist/probes/lint.d.ts.map +1 -0
  149. package/dist/probes/lint.js +121 -0
  150. package/dist/probes/lint.js.map +1 -0
  151. package/dist/probes/model/anthropic.d.ts +47 -0
  152. package/dist/probes/model/anthropic.d.ts.map +1 -0
  153. package/dist/probes/model/anthropic.js +100 -0
  154. package/dist/probes/model/anthropic.js.map +1 -0
  155. package/dist/probes/model/budget.d.ts +22 -0
  156. package/dist/probes/model/budget.d.ts.map +1 -0
  157. package/dist/probes/model/budget.js +27 -0
  158. package/dist/probes/model/budget.js.map +1 -0
  159. package/dist/probes/model/cache.d.ts +13 -0
  160. package/dist/probes/model/cache.d.ts.map +1 -0
  161. package/dist/probes/model/cache.js +74 -0
  162. package/dist/probes/model/cache.js.map +1 -0
  163. package/dist/probes/model/index.d.ts +20 -0
  164. package/dist/probes/model/index.d.ts.map +1 -0
  165. package/dist/probes/model/index.js +160 -0
  166. package/dist/probes/model/index.js.map +1 -0
  167. package/dist/probes/model/prompt.d.ts +16 -0
  168. package/dist/probes/model/prompt.d.ts.map +1 -0
  169. package/dist/probes/model/prompt.js +57 -0
  170. package/dist/probes/model/prompt.js.map +1 -0
  171. package/dist/probes/model/provider.d.ts +88 -0
  172. package/dist/probes/model/provider.d.ts.map +1 -0
  173. package/dist/probes/model/provider.js +48 -0
  174. package/dist/probes/model/provider.js.map +1 -0
  175. package/dist/probes/structure.d.ts +3 -0
  176. package/dist/probes/structure.d.ts.map +1 -0
  177. package/dist/probes/structure.js +95 -0
  178. package/dist/probes/structure.js.map +1 -0
  179. package/dist/probes/types.d.ts +46 -0
  180. package/dist/probes/types.d.ts.map +1 -0
  181. package/dist/probes/types.js +15 -0
  182. package/dist/probes/types.js.map +1 -0
  183. package/dist/registry/define.d.ts +40 -0
  184. package/dist/registry/define.d.ts.map +1 -0
  185. package/dist/registry/define.js +4 -0
  186. package/dist/registry/define.js.map +1 -0
  187. package/dist/registry/ids.d.ts +19 -0
  188. package/dist/registry/ids.d.ts.map +1 -0
  189. package/dist/registry/ids.js +86 -0
  190. package/dist/registry/ids.js.map +1 -0
  191. package/dist/registry/index.d.ts +45 -0
  192. package/dist/registry/index.d.ts.map +1 -0
  193. package/dist/registry/index.js +71 -0
  194. package/dist/registry/index.js.map +1 -0
  195. package/dist/registry/load.d.ts +14 -0
  196. package/dist/registry/load.d.ts.map +1 -0
  197. package/dist/registry/load.js +108 -0
  198. package/dist/registry/load.js.map +1 -0
  199. package/dist/registry/validate.d.ts +24 -0
  200. package/dist/registry/validate.d.ts.map +1 -0
  201. package/dist/registry/validate.js +160 -0
  202. package/dist/registry/validate.js.map +1 -0
  203. package/dist/report/index.d.ts +10 -0
  204. package/dist/report/index.d.ts.map +1 -0
  205. package/dist/report/index.js +30 -0
  206. package/dist/report/index.js.map +1 -0
  207. package/dist/report/json.d.ts +20 -0
  208. package/dist/report/json.d.ts.map +1 -0
  209. package/dist/report/json.js +34 -0
  210. package/dist/report/json.js.map +1 -0
  211. package/dist/report/sarif.d.ts +21 -0
  212. package/dist/report/sarif.d.ts.map +1 -0
  213. package/dist/report/sarif.js +138 -0
  214. package/dist/report/sarif.js.map +1 -0
  215. package/dist/report/terminal.d.ts +3 -0
  216. package/dist/report/terminal.d.ts.map +1 -0
  217. package/dist/report/terminal.js +117 -0
  218. package/dist/report/terminal.js.map +1 -0
  219. package/dist/report/types.d.ts +28 -0
  220. package/dist/report/types.d.ts.map +1 -0
  221. package/dist/report/types.js +11 -0
  222. package/dist/report/types.js.map +1 -0
  223. package/dist/report/verdict.d.ts +21 -0
  224. package/dist/report/verdict.d.ts.map +1 -0
  225. package/dist/report/verdict.js +31 -0
  226. package/dist/report/verdict.js.map +1 -0
  227. package/dist/result.d.ts +22 -0
  228. package/dist/result.d.ts.map +1 -0
  229. package/dist/result.js +19 -0
  230. package/dist/result.js.map +1 -0
  231. package/dist/types.d.ts +178 -0
  232. package/dist/types.d.ts.map +1 -0
  233. package/dist/types.js +11 -0
  234. package/dist/types.js.map +1 -0
  235. package/dist/util/compilerApi.d.ts +2 -0
  236. package/dist/util/compilerApi.d.ts.map +1 -0
  237. package/dist/util/compilerApi.js +28 -0
  238. package/dist/util/compilerApi.js.map +1 -0
  239. package/dist/util/glob.d.ts +43 -0
  240. package/dist/util/glob.d.ts.map +1 -0
  241. package/dist/util/glob.js +195 -0
  242. package/dist/util/glob.js.map +1 -0
  243. package/dist/util/paths.d.ts +6 -0
  244. package/dist/util/paths.d.ts.map +1 -0
  245. package/dist/util/paths.js +22 -0
  246. package/dist/util/paths.js.map +1 -0
  247. package/dist/version.d.ts +13 -0
  248. package/dist/version.d.ts.map +1 -0
  249. package/dist/version.js +12 -0
  250. package/dist/version.js.map +1 -0
  251. package/package.json +72 -0
@@ -0,0 +1,11 @@
1
+ /** Deterministic failures first, then proxies, then advisories — ordered by authority. */
2
+ export const CONFIDENCE_ORDER = ['deterministic', 'proxy', 'model'];
3
+ /**
4
+ * What a reader should see. Baselined and exempted findings are suppressed by their own mechanisms
5
+ * and counted rather than printed — but they are counted, and the count is always shown, because a
6
+ * suppression nobody can see is one nobody reviews.
7
+ */
8
+ export function visible(result, ctx) {
9
+ return result.diagnostics.filter((d) => d.severity !== 'off' && (ctx.showBaselined === true || (!d.baselined && !d.exempted)));
10
+ }
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/report/types.ts"],"names":[],"mappings":"AAsBA,0FAA0F;AAC1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,eAAe,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAE7E;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,MAAiB,EAAE,GAAc;IACvD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,aAAa,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAC7F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The verdict reporter — for a blocking hook.
3
+ *
4
+ * What this is for: a pre-commit hook or an agent's pre-write guard needs one question answered,
5
+ * "may this proceed?", plus enough detail to fix it if not. Prose is the wrong shape for that, and
6
+ * so is a full RunResult.
7
+ *
8
+ * What a caller must know: only ERROR severity blocks. A warn or an advisory finding is reported
9
+ * and does not block, because a non-deterministic or narrower-than-the-rule check that blocks is
10
+ * how a check suite loses trust (LLD §1.10).
11
+ */
12
+ import type { Diagnostic, RunResult } from '../types.js';
13
+ import type { ReportCtx, Reporter } from './types.js';
14
+ export type Verdict = {
15
+ block: boolean;
16
+ reason: string;
17
+ diagnostics: Diagnostic[];
18
+ };
19
+ export declare function verdictFor(result: RunResult, ctx?: ReportCtx): Verdict;
20
+ export declare function createVerdictReporter(): Reporter;
21
+ //# sourceMappingURL=verdict.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.d.ts","sourceRoot":"","sources":["../../src/report/verdict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtD,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAC;AAEF,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,GAAE,SAAc,GAAG,OAAO,CAqB1E;AAED,wBAAgB,qBAAqB,IAAI,QAAQ,CAOhD"}
@@ -0,0 +1,31 @@
1
+ import { visible } from './types.js';
2
+ export function verdictFor(result, ctx = {}) {
3
+ const shown = visible(result, ctx);
4
+ const blocking = shown.filter((d) => d.severity === 'error');
5
+ if (blocking.length === 0) {
6
+ const skipped = result.skipped.length;
7
+ return {
8
+ block: false,
9
+ reason: skipped > 0
10
+ ? `no blocking violations (${skipped} probe(s) did not run)`
11
+ : 'no blocking violations',
12
+ diagnostics: shown,
13
+ };
14
+ }
15
+ const first = blocking[0];
16
+ const more = blocking.length === 1 ? '' : ` (and ${blocking.length - 1} more)`;
17
+ return {
18
+ block: true,
19
+ reason: `${first?.statement ?? 'a rule was broken'} — ${first?.file ?? ''}${more}`,
20
+ diagnostics: blocking,
21
+ };
22
+ }
23
+ export function createVerdictReporter() {
24
+ return {
25
+ name: 'verdict',
26
+ async report(result, ctx) {
27
+ return `${JSON.stringify(verdictFor(result, ctx))}\n`;
28
+ },
29
+ };
30
+ }
31
+ //# sourceMappingURL=verdict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.js","sourceRoot":"","sources":["../../src/report/verdict.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAQrC,MAAM,UAAU,UAAU,CAAC,MAAiB,EAAE,MAAiB,EAAE;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACtC,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EACJ,OAAO,GAAG,CAAC;gBACT,CAAC,CAAC,2BAA2B,OAAO,wBAAwB;gBAC5D,CAAC,CAAC,wBAAwB;YAC9B,WAAW,EAAE,KAAK;SACnB,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC;IAC/E,OAAO;QACL,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,GAAG,KAAK,EAAE,SAAS,IAAI,mBAAmB,MAAM,KAAK,EAAE,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE;QAClF,WAAW,EAAE,QAAQ;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,MAAM,CAAC,MAAiB,EAAE,GAAc;YAC5C,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC;QACxD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Result for the validation paths that must not throw.
3
+ *
4
+ * What rule this enforces: a malformed manifest exits 2, never 1 — which means validation has to
5
+ * be able to *return* every problem it found rather than throwing on the first. A thrown error
6
+ * gives an agent one field name; a Result gives it all of them in one pass (LLD §1.6, plan 03).
7
+ *
8
+ * What a caller must know: `error` is a list by default, and collecting errors is the point.
9
+ * Do not reach for exceptions in validate() paths.
10
+ */
11
+ export type Result<T, E = string[]> = {
12
+ ok: true;
13
+ value: T;
14
+ } | {
15
+ ok: false;
16
+ error: E;
17
+ };
18
+ export declare function ok<T>(value: T): Result<T, never>;
19
+ export declare function err<E>(error: E): Result<never, E>;
20
+ /** Collect a list of Results into one Result, concatenating every error rather than stopping. */
21
+ export declare function allOk<T>(results: Result<T>[]): Result<T[]>;
22
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAEvF,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAEhD;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAEjD;AAED,iGAAiG;AACjG,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAQ1D"}
package/dist/result.js ADDED
@@ -0,0 +1,19 @@
1
+ export function ok(value) {
2
+ return { ok: true, value };
3
+ }
4
+ export function err(error) {
5
+ return { ok: false, error };
6
+ }
7
+ /** Collect a list of Results into one Result, concatenating every error rather than stopping. */
8
+ export function allOk(results) {
9
+ const values = [];
10
+ const errors = [];
11
+ for (const r of results) {
12
+ if (r.ok)
13
+ values.push(r.value);
14
+ else
15
+ errors.push(...r.error);
16
+ }
17
+ return errors.length > 0 ? err(errors) : ok(values);
18
+ }
19
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,KAAK,CAAI,OAAoB;IAC3C,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;;YAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * The five types. Everything else in archcheck is a function between them (LLD §2).
3
+ *
4
+ * What this is for: the shared kernel. Every layer reads these; this module reads nothing —
5
+ * not another archcheck module, and not the TypeScript SDK. That is deliberate and enforced by
6
+ * archcheck's own `kernel` layer, whose `mayImport` list is empty.
7
+ *
8
+ * What a caller must know: two fields are computed, never supplied. `identity` is the
9
+ * normaliser's job (a probe that invents one is wrong), and `schemaVersion` is stamped by
10
+ * construction. See `src/normalize/`.
11
+ */
12
+ import type { SchemaVersion } from './version.js';
13
+ /** The closed set of eight. Adding a ninth is a design decision, not a task (LLD §4). */
14
+ export type ContractKind = 'layers' | 'forbidden' | 'encapsulation' | 'naming' | 'required-file' | 'declared-field' | 'banned-syntax' | 'judgement';
15
+ export declare const CONTRACT_KINDS: readonly ContractKind[];
16
+ export type Severity = 'error' | 'warn' | 'advisory' | 'off';
17
+ /**
18
+ * Severity and confidence are orthogonal. A `model` rule can be `error` in principle — that is
19
+ * policy, not a type constraint. The default is what stops it; the type does not (plan 02).
20
+ */
21
+ export type Confidence = 'deterministic' | 'proxy' | 'model';
22
+ export type Remedy = {
23
+ /** One imperative sentence. Goes into the emitted lint message beside the statement. */
24
+ summary: string;
25
+ allowed?: string[];
26
+ autofix?: boolean;
27
+ docs?: string;
28
+ };
29
+ /** What the consumer writes, one entry per rule in `architecture.config.ts`. */
30
+ export type Rule = {
31
+ /** Immutable once committed. Renaming means a new id plus `replaces` (LLD §1.6). */
32
+ id: string;
33
+ kind: ContractKind;
34
+ /** One sentence. This is the text that ends up in the editor squiggle. */
35
+ statement: string;
36
+ severity: Severity;
37
+ confidence: Confidence;
38
+ /** Kind-specific, validated by the kind's `validate()`. Never read without validating. */
39
+ params: Record<string, unknown>;
40
+ remedy: Remedy;
41
+ /** Set when this rule supersedes a retired id. */
42
+ replaces?: string;
43
+ /** Required on an exception (plan 15). */
44
+ owner?: string;
45
+ expires?: string;
46
+ };
47
+ /** What a probe returns, before enrichment. Evidence, never prose. */
48
+ export type RawFinding = {
49
+ ruleId: string;
50
+ /** Repo-relative POSIX path. */
51
+ file: string;
52
+ line?: number;
53
+ col?: number;
54
+ endLine?: number;
55
+ /** The semantic facts: `{ from, to }` for a graph edge, `{ symbol }` for a naming miss. */
56
+ evidence: Record<string, unknown>;
57
+ /**
58
+ * Stable hash — survives line moves. Computed by the normaliser from ruleId + evidence.
59
+ * A probe leaves this empty; `normalize()` fills it.
60
+ */
61
+ identity: string;
62
+ };
63
+ /**
64
+ * What everything downstream consumes. Diagnostic *extends* RawFinding: the normaliser only
65
+ * adds, it never rewrites what a probe observed, which keeps probe output auditable against
66
+ * the diagnostic a person finally reads (plan 02).
67
+ */
68
+ export type Diagnostic = RawFinding & {
69
+ schemaVersion: SchemaVersion;
70
+ statement: string;
71
+ severity: Severity;
72
+ confidence: Confidence;
73
+ remedy: Remedy;
74
+ /**
75
+ * The probes that observed this. A list rather than the LLD's single string, because
76
+ * deduplication by identity legitimately collapses two observations of one violation —
77
+ * the graph sees the edge, lint sees the statement — and losing the second is losing
78
+ * evidence (plan 07).
79
+ */
80
+ detectedBy: string[];
81
+ /**
82
+ * How many raw findings collapsed into this one identity — normally 1. Evidence carries no
83
+ * position by design, so two empty catches in one file are literally the same evidence and the
84
+ * same hash (`computeIdentity`, src/normalize/identity.ts); this count is what keeps "one
85
+ * diagnostic" from being read as "one violation". It lives HERE and not in `evidence` precisely
86
+ * so the hash is untouched — pinned by 'counting occurrences leaves the identity hash alone' in
87
+ * src/normalize/normalize.test.ts.
88
+ *
89
+ * Optional because a required field would break every existing producer of the agent contract.
90
+ * Absent means 1; `normalize()` always sets it.
91
+ */
92
+ occurrences?: number;
93
+ /** Where those occurrences are, sorted and de-duplicated. Only the lines a probe reported. */
94
+ occurrenceLines?: number[];
95
+ /** Recorded in the baseline as pre-existing debt. Debt, not policy — see `exempted`. */
96
+ baselined: boolean;
97
+ /**
98
+ * Covered by a declared exception: owned, reasoned and expiring. Kept separate from `baselined`
99
+ * on purpose. A baseline entry is debt nobody has signed for; an exception is a deliberate
100
+ * permanent allowance somebody has. Conflating them is how debt quietly becomes policy
101
+ * (plan 14).
102
+ */
103
+ exempted: boolean;
104
+ };
105
+ /**
106
+ * One recorded pre-existing violation. KEYED by identity, never by line — but it also records how
107
+ * many occurrences that identity stood for, because one identity can cover several violations of
108
+ * one rule in one file (see `Diagnostic.occurrences`). Without the count, a single entry would
109
+ * suppress every later occurrence in that file for ever.
110
+ *
111
+ * An entry written before this field existed reads as 1, filled in by `readBaseline`
112
+ * (src/baseline/index.ts), so no existing baseline file is invalidated.
113
+ */
114
+ export type BaselineEntry = {
115
+ identity: string;
116
+ ruleId: string;
117
+ /** ISO date. For auditing how long a piece of debt has been carried. */
118
+ addedAt: string;
119
+ /** How many occurrences this identity covered when it was recorded. At least 1. */
120
+ occurrences: number;
121
+ note?: string;
122
+ };
123
+ /** A declared allowance, as the run sees it once today's date is known. */
124
+ export type ExceptionStatus = {
125
+ ruleId: string;
126
+ owner: string;
127
+ expires: string;
128
+ expired: boolean;
129
+ /** Negative once expired. */
130
+ daysLeft: number;
131
+ reason: string;
132
+ /** How many findings it actually suppressed this run. Zero means it is doing nothing. */
133
+ suppressed: number;
134
+ };
135
+ /** Emitted config, grouped by sink. One rule may produce several (LLD §1.2). */
136
+ export type FragmentTarget = 'graph' | 'lint' | 'boundaries' | 'test' | 'exports';
137
+ export type Fragment = {
138
+ target: FragmentTarget;
139
+ /** The rule that produced it — the generated header names them all. */
140
+ ruleId: string;
141
+ content: unknown;
142
+ };
143
+ export type Coverage = {
144
+ total: number;
145
+ deterministic: number;
146
+ proxy: number;
147
+ model: number;
148
+ /**
149
+ * Rules whose KIND no version of archcheck checks yet. Counted apart from the three tiers on
150
+ * purpose: the tier a rule declares is a claim by its author, and for an unimplemented kind
151
+ * archcheck knows that claim is wrong whatever the manifest says. Folding these into
152
+ * `deterministic` would inflate the one number nobody is supposed to be able to inflate.
153
+ */
154
+ unchecked: number;
155
+ };
156
+ /** A probe that did not run. Present even when empty: "clean" must be distinguishable. */
157
+ export type SkipRecord = {
158
+ probe: string;
159
+ reason: string;
160
+ };
161
+ export type RunResult = {
162
+ ok: boolean;
163
+ diagnostics: Diagnostic[];
164
+ skipped: SkipRecord[];
165
+ coverage: Coverage;
166
+ /**
167
+ * Baseline entries that no longer reproduce. The ratchet turns ONE WAY: a fixed violation that
168
+ * is still listed exits 4, because a baseline that only ever grows silently over-suppresses
169
+ * forever — the failure mode that makes baselines worthless wherever they are used badly.
170
+ */
171
+ baselineStale: BaselineEntry[];
172
+ /**
173
+ * Every declared exception, always — including the ones suppressing nothing. A silent exception
174
+ * decays into a permanent one (plan 15).
175
+ */
176
+ exceptions: ExceptionStatus[];
177
+ };
178
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ export const CONTRACT_KINDS = [
2
+ 'layers',
3
+ 'forbidden',
4
+ 'encapsulation',
5
+ 'naming',
6
+ 'required-file',
7
+ 'declared-field',
8
+ 'banned-syntax',
9
+ 'judgement',
10
+ ];
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,QAAQ;IACR,WAAW;IACX,eAAe;IACf,QAAQ;IACR,eAAe;IACf,gBAAgB;IAChB,eAAe;IACf,WAAW;CACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function missingCompilerApi(compiler: unknown): string[] | undefined;
2
+ //# sourceMappingURL=compilerApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compilerApi.d.ts","sourceRoot":"","sources":["../../src/util/compilerApi.ts"],"names":[],"mappings":"AAcA,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAa1E"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * One guard for "is the TypeScript compiler API actually here?".
3
+ *
4
+ * Why this exists: archcheck reads the compiler API that TypeScript 5.x exposes from its package
5
+ * root — `ts.sys`, `ts.createProgram`, `ts.transpileModule`. TypeScript 7 is the native port, and
6
+ * its root entry exports only `version`; the compiler API moved to a different subpath with a
7
+ * different shape. A consumer who installs `typescript@7` therefore gets an archcheck that fails
8
+ * with `Cannot read properties of undefined (reading 'readFile')`, which names nothing useful.
9
+ *
10
+ * The peer range now excludes 7, so npm warns at install time. This is the second half: a clear
11
+ * message at run time, because a peer warning is easy to miss and a lockfile can carry anything.
12
+ */
13
+ const REQUIRED = ['sys', 'createProgram', 'transpileModule', 'readConfigFile'];
14
+ export function missingCompilerApi(compiler) {
15
+ const api = compiler;
16
+ const absent = REQUIRED.filter((name) => api?.[name] === undefined);
17
+ if (absent.length === 0)
18
+ return undefined;
19
+ const version = typeof api?.version === 'string' ? api.version : 'unknown';
20
+ return [
21
+ `the installed typescript (${version}) does not expose the compiler API archcheck reads`,
22
+ ` missing: ${absent.join(', ')}`,
23
+ ' archcheck needs typescript >=5.4 and <7. TypeScript 7 is the native port, and it exposes',
24
+ ' a different API from a different subpath.',
25
+ ' → install a 6.x or 5.x release: npm install -D typescript@^5.9',
26
+ ];
27
+ }
28
+ //# sourceMappingURL=compilerApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compilerApi.js","sourceRoot":"","sources":["../../src/util/compilerApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,CAAU,CAAC;AAExF,MAAM,UAAU,kBAAkB,CAAC,QAAiB;IAClD,MAAM,GAAG,GAAG,QAA+C,CAAC;IAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;IACpE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE1C,MAAM,OAAO,GAAG,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,OAAO;QACL,6BAA6B,OAAO,oDAAoD;QACxF,cAAc,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACjC,4FAA4F;QAC5F,6CAA6C;QAC7C,kEAAkE;KACnE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The glob matcher used by every `match` and `appliesTo` in a manifest.
3
+ *
4
+ * Why ours rather than a dependency: archcheck ships with zero runtime dependencies so that
5
+ * adopting it cannot drag a transitive tree into a consumer's build. The supported surface is
6
+ * deliberately small — it is a path matcher, not a shell.
7
+ *
8
+ * What a caller must know: patterns are POSIX and repo-relative, matched against paths already
9
+ * put through `repoRelative()`. Supported:
10
+ * * any run of characters except `/`
11
+ * ** zero or more whole path segments (and `a/**` also matches `a` itself)
12
+ * ? exactly one character except `/`
13
+ * {a,b} alternation
14
+ * dir/ a trailing slash is that directory and everything under it
15
+ * !pat negation, when a pattern list is matched with `matchesAny`
16
+ */
17
+ /**
18
+ * The structural defects in a pattern — empty when it is sound. One sentence per defect, every one
19
+ * at once, each phrased to follow a field name so a caller can compose "params.appliesTo pattern
20
+ * 'x' has an empty path segment ...".
21
+ *
22
+ * Why it exists: a pattern that matches nothing is indistinguishable from a rule that is satisfied
23
+ * (AGENTS.md rule 14). `layers.match` fails loudly when it matches nothing — the files become
24
+ * unlayered — but every other glob in a manifest just stops checking, silently and forever.
25
+ *
26
+ * Why it walks the SAME segments as the compiler, through `toSegments` and `segmentToRegex`: a
27
+ * second, independent parser would drift from `patternToRegexSource` and start approving patterns
28
+ * the matcher quietly drops. So this reports only what that walk decides structurally, and it is
29
+ * deliberately silent about whether any file exists — "this matches nothing in THIS repo" needs the
30
+ * file list and is a warning, not an error.
31
+ *
32
+ * Called from the shared pass in `src/registry/validate.ts`, so every rule kind is covered without
33
+ * opting in. Pinned by the `globProblems` suite in `src/util/glob.test.ts`.
34
+ */
35
+ export declare function globProblems(pattern: string): string[];
36
+ export declare function globToRegExp(pattern: string): RegExp;
37
+ export declare function matches(pattern: string, path: string): boolean;
38
+ /**
39
+ * Match against a list. A leading `!` negates, and negations win, so a list like
40
+ * `['src/**', '!src/test-only']` reads the way a reader expects it to.
41
+ */
42
+ export declare function matchesAny(patterns: readonly string[], path: string): boolean;
43
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/util/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAiHH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAsBtD;AAID,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAU7E"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * The glob matcher used by every `match` and `appliesTo` in a manifest.
3
+ *
4
+ * Why ours rather than a dependency: archcheck ships with zero runtime dependencies so that
5
+ * adopting it cannot drag a transitive tree into a consumer's build. The supported surface is
6
+ * deliberately small — it is a path matcher, not a shell.
7
+ *
8
+ * What a caller must know: patterns are POSIX and repo-relative, matched against paths already
9
+ * put through `repoRelative()`. Supported:
10
+ * * any run of characters except `/`
11
+ * ** zero or more whole path segments (and `a/**` also matches `a` itself)
12
+ * ? exactly one character except `/`
13
+ * {a,b} alternation
14
+ * dir/ a trailing slash is that directory and everything under it
15
+ * !pat negation, when a pattern list is matched with `matchesAny`
16
+ */
17
+ const SPECIAL = /[.+^${}()|[\]\\]/g;
18
+ /**
19
+ * One path segment — no slashes. `*`, `?` and `{a,b}` only; `**` is handled a level up, where the
20
+ * pattern has already been split on `/`.
21
+ *
22
+ * ponytail: a brace group containing a slash (`{a/b,c}`) is not supported, because the split
23
+ * happens first. Nothing in this repo or its fixtures writes one. Upgrade path if that changes:
24
+ * tokenise before splitting instead of after.
25
+ *
26
+ * `problems`, when supplied, collects the structural defects this walk sees — the sink
27
+ * `globProblems` passes in so that the validator and the compiler are one walk and cannot
28
+ * disagree. Compilation is unchanged either way: nothing here reads the sink back.
29
+ */
30
+ function segmentToRegex(pattern, problems) {
31
+ let out = '';
32
+ let i = 0;
33
+ while (i < pattern.length) {
34
+ const ch = pattern[i];
35
+ if (ch === '*') {
36
+ out += '[^/]*';
37
+ i += 1;
38
+ continue;
39
+ }
40
+ if (ch === '?') {
41
+ out += '[^/]';
42
+ i += 1;
43
+ continue;
44
+ }
45
+ if (ch === '{') {
46
+ const close = pattern.indexOf('}', i);
47
+ if (close !== -1) {
48
+ const alts = pattern.slice(i + 1, close).split(',');
49
+ if (alts.some((a) => a.length === 0)) {
50
+ problems?.push(`has an empty alternative in the group '${pattern.slice(i, close + 1)}'`);
51
+ }
52
+ out += `(?:${alts.map((a) => segmentToRegex(a, problems)).join('|')})`;
53
+ i = close + 1;
54
+ continue;
55
+ }
56
+ problems?.push("has an unclosed '{'");
57
+ }
58
+ out += ch.replace(SPECIAL, '\\$&');
59
+ i += 1;
60
+ }
61
+ return out;
62
+ }
63
+ /**
64
+ * Split a pattern into the segments `patternToRegexSource` walks, with the two shapes that would
65
+ * otherwise compile to an unmatchable regex folded away first. Both folds exist because a pattern
66
+ * that matches nothing looks exactly like a rule that is satisfied (AGENTS.md rule 14).
67
+ *
68
+ * - A trailing slash is TOLERATED rather than rejected, and reads gitignore-style: the directory
69
+ * and everything under it. Tolerating it costs one line, matches what every reader of a
70
+ * manifest already expects a directory to mean, and a manifest is written by hand — rejecting
71
+ * it would need a validation seam that does not exist here yet. So the empty final segment a
72
+ * trailing slash produces becomes a globstar, which is already the spelling for "this directory
73
+ * and everything beneath it". Without this the regex required a trailing slash, and no
74
+ * `repoRelative()` path has one.
75
+ * - Consecutive globstars collapse to one. Each non-final globstar emits its own mandatory
76
+ * separator, so two in a row required a double slash, which no path has either.
77
+ *
78
+ * `src/util/glob.test.ts` pins both.
79
+ */
80
+ function toSegments(pattern) {
81
+ const raw = pattern.split('/');
82
+ if (raw.length > 1 && raw[raw.length - 1] === '')
83
+ raw[raw.length - 1] = '**';
84
+ return raw.filter((segment, index) => !(segment === '**' && raw[index - 1] === '**'));
85
+ }
86
+ /**
87
+ * The whole pattern, segment by segment. `**` is the only token that spans segments, and it has
88
+ * three distinct shapes — getting any of them wrong is silent, because a pattern that matches
89
+ * nothing looks exactly like a rule that is satisfied:
90
+ *
91
+ * - a lone globstar matches everything.
92
+ * - a globstar as the LAST segment matches its parent directory and anything beneath it.
93
+ * - a globstar in any other position matches zero or more intervening segments.
94
+ *
95
+ * The third shape at the START of a pattern was the one that was broken: it produced a regex
96
+ * requiring a leading slash, so a leading globstar followed by a filename pattern matched only
97
+ * top-level files. The model probe's file scan was the caller that found it.
98
+ *
99
+ * Repeated globstars and a trailing slash are folded away by `toSegments` before this walk, so
100
+ * every shape below sees at most one globstar in a row and no empty final segment.
101
+ */
102
+ function patternToRegexSource(pattern) {
103
+ const segments = toSegments(pattern);
104
+ let out = '';
105
+ let needsSeparator = false;
106
+ for (const [index, segment] of segments.entries()) {
107
+ const isLast = index === segments.length - 1;
108
+ if (segment === '**') {
109
+ if (isLast) {
110
+ out += out === '' ? '.*' : '(?:/.*)?';
111
+ }
112
+ else {
113
+ out += out === '' ? '(?:[^/]+/)*' : '(?:/[^/]+)*/';
114
+ needsSeparator = false;
115
+ }
116
+ continue;
117
+ }
118
+ if (needsSeparator)
119
+ out += '/';
120
+ out += segmentToRegex(segment);
121
+ needsSeparator = true;
122
+ }
123
+ return out;
124
+ }
125
+ /**
126
+ * The structural defects in a pattern — empty when it is sound. One sentence per defect, every one
127
+ * at once, each phrased to follow a field name so a caller can compose "params.appliesTo pattern
128
+ * 'x' has an empty path segment ...".
129
+ *
130
+ * Why it exists: a pattern that matches nothing is indistinguishable from a rule that is satisfied
131
+ * (AGENTS.md rule 14). `layers.match` fails loudly when it matches nothing — the files become
132
+ * unlayered — but every other glob in a manifest just stops checking, silently and forever.
133
+ *
134
+ * Why it walks the SAME segments as the compiler, through `toSegments` and `segmentToRegex`: a
135
+ * second, independent parser would drift from `patternToRegexSource` and start approving patterns
136
+ * the matcher quietly drops. So this reports only what that walk decides structurally, and it is
137
+ * deliberately silent about whether any file exists — "this matches nothing in THIS repo" needs the
138
+ * file list and is a warning, not an error.
139
+ *
140
+ * Called from the shared pass in `src/registry/validate.ts`, so every rule kind is covered without
141
+ * opting in. Pinned by the `globProblems` suite in `src/util/glob.test.ts`.
142
+ */
143
+ export function globProblems(pattern) {
144
+ // A negation is legal in every list form (`matchesAny`), and it is not part of the path.
145
+ const body = pattern.startsWith('!') ? pattern.slice(1) : pattern;
146
+ if (body.length === 0)
147
+ return ['is empty, so it matches nothing'];
148
+ const problems = [];
149
+ if (body.startsWith('/')) {
150
+ problems.push('starts with a separator, but every path it is matched against is repo-relative');
151
+ }
152
+ for (const [index, segment] of toSegments(body).entries()) {
153
+ if (segment === '') {
154
+ // Index 0 is the leading separator, already named. A trailing separator is folded to a
155
+ // globstar by `toSegments` and is legal, so any empty segment left here is a doubled one.
156
+ if (index > 0)
157
+ problems.push('has an empty path segment, from a doubled separator');
158
+ continue;
159
+ }
160
+ if (segment === '**')
161
+ continue;
162
+ segmentToRegex(segment, problems);
163
+ }
164
+ return problems;
165
+ }
166
+ const cache = new Map();
167
+ export function globToRegExp(pattern) {
168
+ const cached = cache.get(pattern);
169
+ if (cached)
170
+ return cached;
171
+ const compiled = new RegExp(`^${patternToRegexSource(pattern)}$`);
172
+ cache.set(pattern, compiled);
173
+ return compiled;
174
+ }
175
+ export function matches(pattern, path) {
176
+ return globToRegExp(pattern).test(path);
177
+ }
178
+ /**
179
+ * Match against a list. A leading `!` negates, and negations win, so a list like
180
+ * `['src/**', '!src/test-only']` reads the way a reader expects it to.
181
+ */
182
+ export function matchesAny(patterns, path) {
183
+ let hit = false;
184
+ for (const pattern of patterns) {
185
+ if (pattern.startsWith('!')) {
186
+ if (matches(pattern.slice(1), path))
187
+ return false;
188
+ }
189
+ else if (matches(pattern, path)) {
190
+ hit = true;
191
+ }
192
+ }
193
+ return hit;
194
+ }
195
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/util/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,OAAO,GAAG,mBAAmB,CAAC;AAEpC;;;;;;;;;;;GAWG;AACH,SAAS,cAAc,CAAC,OAAe,EAAE,QAAmB;IAC1D,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAW,CAAC;QAChC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,GAAG,IAAI,OAAO,CAAC;YACf,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,GAAG,IAAI,MAAM,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACtC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACpD,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;oBACrC,QAAQ,EAAE,IAAI,CAAC,0CAA0C,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC3F,CAAC;gBACD,GAAG,IAAI,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBACvE,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;gBACd,SAAS;YACX,CAAC;YACD,QAAQ,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACxC,CAAC;QACD,GAAG,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7E,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;AACxF,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,KAAK,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,MAAM,EAAE,CAAC;gBACX,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;gBACnD,cAAc,GAAG,KAAK,CAAC;YACzB,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,cAAc;YAAE,GAAG,IAAI,GAAG,CAAC;QAC/B,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,yFAAyF;IACzF,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAClE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,iCAAiC,CAAC,CAAC;IAElE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAC;IAClG,CAAC;IAED,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACnB,uFAAuF;YACvF,0FAA0F;YAC1F,IAAI,KAAK,GAAG,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;YACpF,SAAS;QACX,CAAC;QACD,IAAI,OAAO,KAAK,IAAI;YAAE,SAAS;QAC/B,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClE,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,IAAY;IACnD,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,QAA2B,EAAE,IAAY;IAClE,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;QACpD,CAAC;aAAM,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YAClC,GAAG,GAAG,IAAI,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,6 @@
1
+ /** POSIX separators, always — a generated file must be byte-identical on Windows and macOS. */
2
+ export declare function toPosix(path: string): string;
3
+ /** Repo-relative and POSIX. The canonical form for evidence, findings and generated output. */
4
+ export declare function repoRelative(root: string, path: string): string;
5
+ export declare function absoluteFrom(root: string, path: string): string;
6
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/util/paths.ts"],"names":[],"mappings":"AAUA,+FAA+F;AAC/F,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,+FAA+F;AAC/F,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/D"}