@shrkcrft/boundaries 0.1.0-alpha.29 → 0.1.0-alpha.31

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 (229) hide show
  1. package/dist/baseline/compute-baseline.d.ts +8 -0
  2. package/dist/baseline/compute-baseline.d.ts.map +1 -1
  3. package/dist/baseline/compute-baseline.js +10 -8
  4. package/dist/baseline/diff-baseline.d.ts +28 -0
  5. package/dist/baseline/diff-baseline.d.ts.map +1 -1
  6. package/dist/baseline/diff-baseline.js +29 -0
  7. package/dist/evaluate/boundary-unit-finding.d.ts +10 -0
  8. package/dist/evaluate/boundary-unit-finding.d.ts.map +1 -0
  9. package/dist/evaluate/boundary-unit-finding.js +21 -0
  10. package/dist/evaluate/boundary-unit-kind.d.ts +7 -0
  11. package/dist/evaluate/boundary-unit-kind.d.ts.map +1 -0
  12. package/dist/evaluate/boundary-unit-kind.js +14 -0
  13. package/dist/evaluate/evaluate-boundaries.d.ts +230 -3
  14. package/dist/evaluate/evaluate-boundaries.d.ts.map +1 -1
  15. package/dist/evaluate/evaluate-boundaries.js +481 -53
  16. package/dist/evaluate/i-boundary-rule-settle-input.d.ts +27 -0
  17. package/dist/evaluate/i-boundary-rule-settle-input.d.ts.map +1 -0
  18. package/dist/evaluate/i-boundary-rule-settle-input.js +1 -0
  19. package/dist/evaluate/i-boundary-rule-settlement.d.ts +23 -0
  20. package/dist/evaluate/i-boundary-rule-settlement.d.ts.map +1 -0
  21. package/dist/evaluate/i-boundary-rule-settlement.js +1 -0
  22. package/dist/evaluate/i-boundary-unit-finding.d.ts +22 -0
  23. package/dist/evaluate/i-boundary-unit-finding.d.ts.map +1 -0
  24. package/dist/evaluate/i-boundary-unit-finding.js +1 -0
  25. package/dist/evaluate/settle-boundary-rule.d.ts +23 -0
  26. package/dist/evaluate/settle-boundary-rule.d.ts.map +1 -0
  27. package/dist/evaluate/settle-boundary-rule.js +73 -0
  28. package/dist/evaluate/with-boundary-rule-settlement.d.ts +11 -0
  29. package/dist/evaluate/with-boundary-rule-settlement.d.ts.map +1 -0
  30. package/dist/evaluate/with-boundary-rule-settlement.js +44 -0
  31. package/dist/extract/code-zones.d.ts +95 -3
  32. package/dist/extract/code-zones.d.ts.map +1 -1
  33. package/dist/extract/code-zones.js +313 -4
  34. package/dist/extract/extract-tokens.d.ts +49 -1
  35. package/dist/extract/extract-tokens.d.ts.map +1 -1
  36. package/dist/extract/extract-tokens.js +283 -25
  37. package/dist/extract/i-labeled-source.d.ts +12 -0
  38. package/dist/extract/i-labeled-source.d.ts.map +1 -0
  39. package/dist/extract/i-labeled-source.js +1 -0
  40. package/dist/extract/import-edges.d.ts +50 -0
  41. package/dist/extract/import-edges.d.ts.map +1 -0
  42. package/dist/extract/import-edges.js +170 -0
  43. package/dist/extract/inspect-source.d.ts +38 -3
  44. package/dist/extract/inspect-source.d.ts.map +1 -1
  45. package/dist/extract/inspect-source.js +56 -8
  46. package/dist/extract/parse-imports.d.ts +80 -0
  47. package/dist/extract/parse-imports.d.ts.map +1 -0
  48. package/dist/extract/parse-imports.js +254 -0
  49. package/dist/extract/scan-literals.d.ts +12 -1
  50. package/dist/extract/scan-literals.d.ts.map +1 -1
  51. package/dist/extract/scan-literals.js +15 -1
  52. package/dist/extract/source-liveness-request.d.ts +24 -0
  53. package/dist/extract/source-liveness-request.d.ts.map +1 -0
  54. package/dist/extract/source-liveness-request.js +45 -0
  55. package/dist/generated/check-provenance.d.ts +20 -2
  56. package/dist/generated/check-provenance.d.ts.map +1 -1
  57. package/dist/generated/check-provenance.js +27 -6
  58. package/dist/generated/read-regen-tree.d.ts +16 -0
  59. package/dist/generated/read-regen-tree.d.ts.map +1 -0
  60. package/dist/generated/read-regen-tree.js +61 -0
  61. package/dist/generated/scan-generated.d.ts +57 -3
  62. package/dist/generated/scan-generated.d.ts.map +1 -1
  63. package/dist/generated/scan-generated.js +111 -11
  64. package/dist/index.d.ts +51 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +54 -0
  67. package/dist/model/boundary-intended-empty-line.d.ts +10 -0
  68. package/dist/model/boundary-intended-empty-line.d.ts.map +1 -0
  69. package/dist/model/boundary-intended-empty-line.js +11 -0
  70. package/dist/model/boundary-markable-list.d.ts +15 -0
  71. package/dist/model/boundary-markable-list.d.ts.map +1 -0
  72. package/dist/model/boundary-markable-list.js +15 -0
  73. package/dist/model/boundary-rule-input-keys.d.ts +11 -0
  74. package/dist/model/boundary-rule-input-keys.d.ts.map +1 -0
  75. package/dist/model/boundary-rule-input-keys.js +29 -0
  76. package/dist/model/boundary-rule-input.d.ts +23 -0
  77. package/dist/model/boundary-rule-input.d.ts.map +1 -0
  78. package/dist/model/boundary-rule-input.js +1 -0
  79. package/dist/model/boundary-rule-key-problems.d.ts +11 -0
  80. package/dist/model/boundary-rule-key-problems.d.ts.map +1 -0
  81. package/dist/model/boundary-rule-key-problems.js +36 -0
  82. package/dist/model/boundary-rule-marker-problems.d.ts +26 -0
  83. package/dist/model/boundary-rule-marker-problems.d.ts.map +1 -0
  84. package/dist/model/boundary-rule-marker-problems.js +94 -0
  85. package/dist/model/boundary-rule-scope.d.ts +88 -0
  86. package/dist/model/boundary-rule-scope.d.ts.map +1 -0
  87. package/dist/model/boundary-rule-scope.js +175 -0
  88. package/dist/model/boundary-rule.d.ts +120 -5
  89. package/dist/model/boundary-rule.d.ts.map +1 -1
  90. package/dist/model/boundary-rule.js +148 -1
  91. package/dist/model/boundary-unit-problem-issue.d.ts +9 -0
  92. package/dist/model/boundary-unit-problem-issue.d.ts.map +1 -0
  93. package/dist/model/boundary-unit-problem-issue.js +16 -0
  94. package/dist/model/normalize-boundary-rule.d.ts +21 -0
  95. package/dist/model/normalize-boundary-rule.d.ts.map +1 -0
  96. package/dist/model/normalize-boundary-rule.js +62 -0
  97. package/dist/policy/evaluate-policy.d.ts +80 -3
  98. package/dist/policy/evaluate-policy.d.ts.map +1 -1
  99. package/dist/policy/evaluate-policy.js +152 -19
  100. package/dist/policy/i-policy-rule-liveness.d.ts +15 -0
  101. package/dist/policy/i-policy-rule-liveness.d.ts.map +1 -0
  102. package/dist/policy/i-policy-rule-liveness.js +1 -0
  103. package/dist/policy/run-policy.d.ts +1 -1
  104. package/dist/policy/run-policy.d.ts.map +1 -1
  105. package/dist/policy/run-policy.js +171 -21
  106. package/dist/registry/load-boundary-rules.d.ts +29 -1
  107. package/dist/registry/load-boundary-rules.d.ts.map +1 -1
  108. package/dist/registry/load-boundary-rules.js +38 -8
  109. package/dist/scan/glob.d.ts +90 -0
  110. package/dist/scan/glob.d.ts.map +1 -1
  111. package/dist/scan/glob.js +205 -0
  112. package/dist/scan/i-glob-unit-measure.d.ts +22 -0
  113. package/dist/scan/i-glob-unit-measure.d.ts.map +1 -0
  114. package/dist/scan/i-glob-unit-measure.js +1 -0
  115. package/dist/scan/import-pattern.d.ts +109 -0
  116. package/dist/scan/import-pattern.d.ts.map +1 -0
  117. package/dist/scan/import-pattern.js +191 -0
  118. package/dist/scan/node-builtin-package-names.d.ts +13 -0
  119. package/dist/scan/node-builtin-package-names.d.ts.map +1 -0
  120. package/dist/scan/node-builtin-package-names.js +25 -0
  121. package/dist/scan/scan-imports.d.ts +36 -3
  122. package/dist/scan/scan-imports.d.ts.map +1 -1
  123. package/dist/scan/scan-imports.js +114 -45
  124. package/dist/util/blank-run-hazard-finding.d.ts +34 -0
  125. package/dist/util/blank-run-hazard-finding.d.ts.map +1 -0
  126. package/dist/util/blank-run-hazard-finding.js +1 -0
  127. package/dist/util/blank-run-hazard.d.ts +29 -0
  128. package/dist/util/blank-run-hazard.d.ts.map +1 -0
  129. package/dist/util/blank-run-hazard.js +450 -0
  130. package/dist/util/dead-glob-units.d.ts +46 -0
  131. package/dist/util/dead-glob-units.d.ts.map +1 -0
  132. package/dist/util/dead-glob-units.js +116 -0
  133. package/dist/util/glob-list-liveness-input.d.ts +31 -0
  134. package/dist/util/glob-list-liveness-input.d.ts.map +1 -0
  135. package/dist/util/glob-list-liveness-input.js +65 -0
  136. package/dist/util/i-dead-glob-unit.d.ts +24 -0
  137. package/dist/util/i-dead-glob-unit.d.ts.map +1 -0
  138. package/dist/util/i-dead-glob-unit.js +1 -0
  139. package/dist/util/i-glob-list-units.d.ts +25 -0
  140. package/dist/util/i-glob-list-units.d.ts.map +1 -0
  141. package/dist/util/i-glob-list-units.js +1 -0
  142. package/dist/util/i-glob-liveness-list.d.ts +23 -0
  143. package/dist/util/i-glob-liveness-list.d.ts.map +1 -0
  144. package/dist/util/i-glob-liveness-list.js +1 -0
  145. package/dist/util/i-glob-liveness-request.d.ts +11 -0
  146. package/dist/util/i-glob-liveness-request.d.ts.map +1 -0
  147. package/dist/util/i-glob-liveness-request.js +1 -0
  148. package/dist/util/i-glob-negation.d.ts +13 -0
  149. package/dist/util/i-glob-negation.d.ts.map +1 -0
  150. package/dist/util/i-glob-negation.js +1 -0
  151. package/dist/util/matched-files.d.ts +22 -0
  152. package/dist/util/matched-files.d.ts.map +1 -0
  153. package/dist/util/matched-files.js +1 -0
  154. package/dist/util/negation-cause.d.ts +15 -0
  155. package/dist/util/negation-cause.d.ts.map +1 -0
  156. package/dist/util/negation-cause.js +21 -0
  157. package/dist/util/plane-scan-exclude-dirs.d.ts +17 -0
  158. package/dist/util/plane-scan-exclude-dirs.d.ts.map +1 -0
  159. package/dist/util/plane-scan-exclude-dirs.js +22 -0
  160. package/dist/util/read-glob-list-liveness.d.ts +20 -0
  161. package/dist/util/read-glob-list-liveness.d.ts.map +1 -0
  162. package/dist/util/read-glob-list-liveness.js +20 -0
  163. package/dist/util/read-scope-coverage.d.ts +90 -0
  164. package/dist/util/read-scope-coverage.d.ts.map +1 -0
  165. package/dist/util/read-scope-coverage.js +173 -0
  166. package/dist/util/read-scope.d.ts +14 -0
  167. package/dist/util/read-scope.d.ts.map +1 -0
  168. package/dist/util/read-scope.js +1 -0
  169. package/dist/util/read-selected-files.d.ts +16 -0
  170. package/dist/util/read-selected-files.d.ts.map +1 -0
  171. package/dist/util/read-selected-files.js +25 -0
  172. package/dist/util/settle-glob-lists.d.ts +12 -0
  173. package/dist/util/settle-glob-lists.d.ts.map +1 -0
  174. package/dist/util/settle-glob-lists.js +13 -0
  175. package/dist/util/unread-file-reason.d.ts +26 -0
  176. package/dist/util/unread-file-reason.d.ts.map +1 -0
  177. package/dist/util/unread-file-reason.js +26 -0
  178. package/dist/util/unread-file.d.ts +10 -0
  179. package/dist/util/unread-file.d.ts.map +1 -0
  180. package/dist/util/unread-file.js +1 -0
  181. package/dist/util/walk-files.d.ts +90 -7
  182. package/dist/util/walk-files.d.ts.map +1 -1
  183. package/dist/util/walk-files.js +206 -19
  184. package/dist/wiring/evaluate-wiring.d.ts +88 -7
  185. package/dist/wiring/evaluate-wiring.d.ts.map +1 -1
  186. package/dist/wiring/evaluate-wiring.js +276 -16
  187. package/dist/wiring/explain-wiring.d.ts +56 -14
  188. package/dist/wiring/explain-wiring.d.ts.map +1 -1
  189. package/dist/wiring/explain-wiring.js +136 -10
  190. package/dist/wiring/i-idiom-role-coverage.d.ts +24 -0
  191. package/dist/wiring/i-idiom-role-coverage.d.ts.map +1 -0
  192. package/dist/wiring/i-idiom-role-coverage.js +1 -0
  193. package/dist/wiring/i-registration-query-verdict.d.ts +38 -0
  194. package/dist/wiring/i-registration-query-verdict.d.ts.map +1 -0
  195. package/dist/wiring/i-registration-query-verdict.js +1 -0
  196. package/dist/wiring/i-registration-roles.d.ts +71 -0
  197. package/dist/wiring/i-registration-roles.d.ts.map +1 -0
  198. package/dist/wiring/i-registration-roles.js +1 -0
  199. package/dist/wiring/measure-idiom-role-coverage.d.ts +12 -0
  200. package/dist/wiring/measure-idiom-role-coverage.d.ts.map +1 -0
  201. package/dist/wiring/measure-idiom-role-coverage.js +20 -0
  202. package/dist/wiring/measure-registration-roles.d.ts +25 -0
  203. package/dist/wiring/measure-registration-roles.d.ts.map +1 -0
  204. package/dist/wiring/measure-registration-roles.js +124 -0
  205. package/dist/wiring/plan-wiring-fix.d.ts +16 -1
  206. package/dist/wiring/plan-wiring-fix.d.ts.map +1 -1
  207. package/dist/wiring/plan-wiring-fix.js +177 -4
  208. package/dist/wiring/registration-graph.d.ts +13 -1
  209. package/dist/wiring/registration-graph.d.ts.map +1 -1
  210. package/dist/wiring/registration-graph.js +22 -6
  211. package/dist/wiring/registration-query-verdict.d.ts +23 -0
  212. package/dist/wiring/registration-query-verdict.d.ts.map +1 -0
  213. package/dist/wiring/registration-query-verdict.js +118 -0
  214. package/dist/wiring/registry-query.d.ts +9 -1
  215. package/dist/wiring/registry-query.d.ts.map +1 -1
  216. package/dist/wiring/registry-query.js +17 -6
  217. package/dist/wiring/scan-wiring-files.d.ts +5 -3
  218. package/dist/wiring/scan-wiring-files.d.ts.map +1 -1
  219. package/dist/wiring/scan-wiring-files.js +55 -14
  220. package/dist/wiring/sink-imports.d.ts +95 -0
  221. package/dist/wiring/sink-imports.d.ts.map +1 -0
  222. package/dist/wiring/sink-imports.js +124 -0
  223. package/dist/wiring/trace-literal.d.ts +6 -0
  224. package/dist/wiring/trace-literal.d.ts.map +1 -1
  225. package/dist/wiring/trace-literal.js +5 -2
  226. package/dist/wiring/wiring-labeled-sources.d.ts +12 -0
  227. package/dist/wiring/wiring-labeled-sources.d.ts.map +1 -0
  228. package/dist/wiring/wiring-labeled-sources.js +20 -0
  229. package/package.json +2 -2
@@ -1,4 +1,5 @@
1
1
  import { type IWiringSource } from '@shrkcrft/core';
2
+ import type { ITsconfigPathsMap } from '../scan/tsconfig-aliases.js';
2
3
  /** A file made available to an extractor. */
3
4
  export interface IExtractFileEntry {
4
5
  /** Project-relative POSIX path. */
@@ -11,11 +12,37 @@ export interface IExtractedSite {
11
12
  readonly file: string;
12
13
  readonly line: number;
13
14
  }
15
+ /**
16
+ * Optional project context an extractor may need.
17
+ *
18
+ * Kept OUT of the source spec because it is not part of the rule — it is what
19
+ * the caller knows about the workspace. Only `import-edges` reads it today, and
20
+ * every other kind stays a pure function of (source, file contents).
21
+ */
22
+ export interface IExtractContext {
23
+ /** tsconfig `paths` map, so alias specifiers resolve as the compiler would. */
24
+ readonly tsconfigPaths?: ITsconfigPathsMap;
25
+ }
14
26
  /** Outcome of running one source: the sites, or a configuration error. */
15
27
  export interface IExtractResult {
16
28
  readonly sites: readonly IExtractedSite[];
29
+ /**
30
+ * How many characters a non-`all` `scan` zone blanked before extraction.
31
+ *
32
+ * Surfaced (not merely applied) because a zone is the one setting that can
33
+ * make a rule match LESS while still reading green: an author who sees the
34
+ * number drop can tell "my pattern was matching prose" from "my glob went
35
+ * stale". `explain` prints it.
36
+ */
37
+ readonly blankedChars?: number;
17
38
  /** Set when the SOURCE is misconfigured (never thrown — rules degrade). */
18
39
  readonly error?: string;
40
+ /**
41
+ * A diagnosis for a zero-match that is CORRECT but almost certainly not what
42
+ * the author meant. Distinct from `error`: nothing is wrong with the source,
43
+ * it just cannot mean what it looks like it means.
44
+ */
45
+ readonly hint?: string;
19
46
  }
20
47
  /**
21
48
  * Run one source's extractor over the given files.
@@ -26,5 +53,26 @@ export interface IExtractResult {
26
53
  * new extractor kind for free). Never throws — a misconfigured source returns
27
54
  * an `error` and no sites.
28
55
  */
29
- export declare function extractTokens(source: IWiringSource, files: readonly IExtractFileEntry[]): IExtractResult;
56
+ export declare function extractTokens(source: IWiringSource, files: readonly IExtractFileEntry[], context?: IExtractContext): IExtractResult;
57
+ /**
58
+ * Wall-clock cap for ONE file's `regex-capture` pass under a non-`all` scan
59
+ * zone. Checked between matches; a file that trips it contributes nothing and
60
+ * is NAMED (the source errors), so a partial token set can never read green.
61
+ */
62
+ export declare const ZONED_REGEX_FILE_BUDGET_MS = 1000;
63
+ /**
64
+ * The head regexes the anchor-based extractors run — possibly on a blanked
65
+ * buffer. One factory, so the linearity lock (`r75-blank-run-linearity`)
66
+ * times and lints the exact patterns that run, not copies of them.
67
+ */
68
+ export declare function extractorHeadPatterns(anchor: string): {
69
+ readonly arrayLiteral: RegExp;
70
+ readonly objectLiteral: RegExp;
71
+ readonly enumBody: RegExp;
72
+ readonly call: RegExp;
73
+ readonly decorator: RegExp;
74
+ readonly stringUnion: RegExp;
75
+ readonly exportDecl: RegExp;
76
+ readonly exportClause: RegExp;
77
+ };
30
78
  //# sourceMappingURL=extract-tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extract-tokens.d.ts","sourceRoot":"","sources":["../../src/extract/extract-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAC;AAUxB,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,SAAS,iBAAiB,EAAE,GAClC,cAAc,CA4DhB"}
1
+ {"version":3,"file":"extract-tokens.d.ts","sourceRoot":"","sources":["../../src/extract/extract-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AASrE,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;CAC5C;AAED,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,SAAS,iBAAiB,EAAE,EACnC,OAAO,GAAE,eAAoB,GAC5B,cAAc,CAiHhB;AA+CD;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAmN/C;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG;IACrD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAgBA"}
@@ -1,5 +1,8 @@
1
1
  import { resolveExtractorAnchor, resolveExtractorKind, validateWiringSource, } from '@shrkcrft/core';
2
2
  import { safeCompile } from "../util/safe-regex.js";
3
+ import { findBlankRunHazards } from "../util/blank-run-hazard.js";
4
+ import { blankOutsideZone } from "./code-zones.js";
5
+ import { extractImportEdges } from "./import-edges.js";
3
6
  import { elementToken, elementValue, escapeRegex, lineOf, scanBalanced, } from "./scan-literals.js";
4
7
  /**
5
8
  * Run one source's extractor over the given files.
@@ -10,41 +13,94 @@ import { elementToken, elementValue, escapeRegex, lineOf, scanBalanced, } from "
10
13
  * new extractor kind for free). Never throws — a misconfigured source returns
11
14
  * an `error` and no sites.
12
15
  */
13
- export function extractTokens(source, files) {
16
+ export function extractTokens(source, files, context = {}) {
14
17
  const error = validateWiringSource(source);
15
18
  if (error)
16
19
  return { sites: [], error };
17
20
  const kind = resolveExtractorKind(source);
18
21
  const anchor = resolveExtractorAnchor(source);
22
+ // Zone the CONTENT once, up front, instead of teaching every extractor about
23
+ // comments. Blanking preserves length and newlines, so each extractor still
24
+ // reports the true `file:line` and none of them needs zone logic of its own.
25
+ const zone = source.scan ?? 'all';
26
+ let blankedChars = 0;
27
+ // `import-edges` zones itself (round 11, 6.1a#import-edges-scan): it judges a
28
+ // statement by where its KEYWORD starts, through the one import parser.
29
+ // Pre-blanking here erased every specifier (a string) under `scan: 'code'`,
30
+ // and the rule silently extracted nothing.
31
+ const scanned = zone === 'all' || kind === 'import-edges'
32
+ ? files
33
+ : files.map((f) => {
34
+ const blanked = blankOutsideZone(f.content, zone);
35
+ blankedChars += blanked.blankedChars;
36
+ return { path: f.path, content: blanked.content };
37
+ });
19
38
  let sites;
39
+ // A user pattern run on a BLANKED buffer can backtrack O(run²) on the
40
+ // whitespace runs the zone manufactures. Lint it (the hint reaches `gates
41
+ // coverage` / `explain`), and bound each file: a file over budget is a
42
+ // named, loud skip — the rule errors, never a silent partial.
43
+ let regexHint;
20
44
  switch (kind) {
21
- case 'regex-capture':
22
- sites = byRegex(source, files);
45
+ case 'regex-capture': {
46
+ const zoned = zone !== 'all';
47
+ const hazards = zoned ? findBlankRunHazards(source.pattern) : [];
48
+ if (hazards.length > 0)
49
+ regexHint = blankRunHazardHint(zone, hazards);
50
+ const run = byRegex(source, scanned, zoned, hazards);
51
+ if (run.predicted.length + run.ran.length > 0) {
52
+ return {
53
+ sites: [],
54
+ error: zonedOverBudgetError(zone, run, hazards),
55
+ ...(regexHint ? { hint: regexHint } : {}),
56
+ ...zoneMeta(zone, blankedChars),
57
+ };
58
+ }
59
+ sites = run.sites;
23
60
  break;
61
+ }
24
62
  case 'array-members':
25
- sites = byBracketLiteral(anchor, '[', files, (el) => elementToken(el));
63
+ sites = byBracketLiteral(anchor, '[', scanned, (el) => elementToken(el));
26
64
  break;
27
65
  case 'object-keys':
28
- sites = byBracketLiteral(anchor, '{', files, (el) => source.capture === 'value' ? elementValue(el) : elementToken(el));
66
+ sites = byBracketLiteral(anchor, '{', scanned, (el) => source.capture === 'value' ? elementValue(el) : elementToken(el));
29
67
  break;
30
68
  case 'enum-members':
31
- sites = byEnumMembers(anchor, source.capture === 'value', files);
69
+ sites = byEnumMembers(anchor, source.capture === 'value', scanned);
32
70
  break;
33
71
  case 'export-names':
34
- sites = byExportNames(files);
72
+ sites = byExportNames(scanned);
35
73
  break;
36
74
  case 'call-args':
37
- sites = byCallArgs(anchor, source.argIndex ?? 0, false, files);
75
+ sites = byCallArgs(anchor, source.argIndex ?? 0, false, scanned);
38
76
  break;
39
77
  case 'decorator-args':
40
- sites = byCallArgs(anchor, source.argIndex ?? 0, true, files);
78
+ sites = byCallArgs(anchor, source.argIndex ?? 0, true, scanned);
41
79
  break;
42
80
  case 'string-union-members':
43
- sites = byStringUnion(anchor, files);
81
+ sites = byStringUnion(anchor, scanned);
44
82
  break;
45
83
  case 'json-path':
46
- sites = byJsonPath(source.jsonPath, files);
84
+ sites = byJsonPath(source.jsonPath, scanned);
85
+ break;
86
+ case 'filenames':
87
+ sites = byFilenames(source, scanned);
88
+ break;
89
+ case 'import-edges': {
90
+ const edges = extractImportEdges(source, scanned, {
91
+ ...(context.tsconfigPaths ? { tsconfigPaths: context.tsconfigPaths } : {}),
92
+ });
93
+ if (edges.error)
94
+ return { sites: [], error: edges.error };
95
+ // It zones itself, so what its zone blanked is its own figure — the
96
+ // `scan: code (N chars blanked)` note must not read 0 over a zone that
97
+ // dropped a commented-out edge.
98
+ blankedChars += edges.blankedChars ?? 0;
99
+ if (edges.hint)
100
+ return { sites: edges.sites, hint: edges.hint, ...zoneMeta(zone, blankedChars) };
101
+ sites = edges.sites;
47
102
  break;
103
+ }
48
104
  default:
49
105
  return { sites: [], error: `unknown extract kind "${String(kind)}"` };
50
106
  }
@@ -66,15 +122,187 @@ export function extractTokens(source, files) {
66
122
  });
67
123
  }
68
124
  }
69
- return { sites };
125
+ return { sites, ...zoneMeta(zone, blankedChars), ...(regexHint ? { hint: regexHint } : {}) };
126
+ }
127
+ /** The zone provenance to attach to a result — omitted entirely when unzoned. */
128
+ function zoneMeta(zone, blankedChars) {
129
+ return zone === 'all' ? {} : { blankedChars };
130
+ }
131
+ /**
132
+ * One id per FILE, derived from its path.
133
+ *
134
+ * Every other extractor reads a file's CONTENTS, so "a declared thing must have
135
+ * its sibling FILE" — a `FOO_DESCRIPTOR` const paired with `FOO_DESCRIPTOR.ts` —
136
+ * had no expression at all. Paired with a `parity` wiring rule this asserts the
137
+ * correspondence in BOTH directions: a const with no file, and a file with no
138
+ * const.
139
+ *
140
+ * The site line is 1: the id comes from the path, not from any line in it, and
141
+ * claiming a more specific location would be inventing one.
142
+ */
143
+ function byFilenames(source, files) {
144
+ const capture = source.capturePath ?? 'stem';
145
+ let re;
146
+ if (capture === 'regex') {
147
+ const compiled = safeCompile(source.pathPattern, source.pathPatternFlags);
148
+ if (!compiled.re)
149
+ return [];
150
+ re = compiled.re;
151
+ }
152
+ const sites = [];
153
+ for (const file of files) {
154
+ if (capture === 'regex') {
155
+ re.lastIndex = 0;
156
+ const m = re.exec(file.path);
157
+ if (m?.[1])
158
+ sites.push({ token: m[1], file: file.path, line: 1 });
159
+ continue;
160
+ }
161
+ const basename = file.path.slice(file.path.lastIndexOf('/') + 1);
162
+ const dot = basename.indexOf('.');
163
+ const token = capture === 'basename' || dot <= 0 ? basename : basename.slice(0, dot);
164
+ sites.push({ token, file: file.path, line: 1 });
165
+ }
166
+ return sites;
167
+ }
168
+ /**
169
+ * Wall-clock cap for ONE file's `regex-capture` pass under a non-`all` scan
170
+ * zone. Checked between matches; a file that trips it contributes nothing and
171
+ * is NAMED (the source errors), so a partial token set can never read green.
172
+ */
173
+ export const ZONED_REGEX_FILE_BUDGET_MS = 1000;
174
+ /**
175
+ * For a pattern the blank-run lint flags: a file whose PREDICTED backtracking
176
+ * work (priced by each hazard's reach, below) exceeds this is skipped BEFORE
177
+ * the regex runs. One `exec` over such a buffer cannot be interrupted (a
178
+ * 16 KB newline-crossing run already costs ~300–470 ms), so the prediction is
179
+ * what makes the cap a real bound.
180
+ */
181
+ const ZONED_HAZARD_COST_LIMIT = 2e8;
182
+ /** Blank stretches shorter than this are ordinary indentation — not worth pricing. */
183
+ const MIN_PRICED_RUN = 64;
184
+ function blankRunCosts(content) {
185
+ let run = 0;
186
+ let segment = 0;
187
+ let newlines = 0;
188
+ let runCost = 0;
189
+ let lineCost = 0;
190
+ let linesTimesRun = 0;
191
+ for (let i = 0; i <= content.length; i += 1) {
192
+ const c = i < content.length ? content.charCodeAt(i) : 0;
193
+ if (c === 0x20) {
194
+ run += 1;
195
+ segment += 1;
196
+ continue;
197
+ }
198
+ if (segment >= MIN_PRICED_RUN)
199
+ lineCost += segment * segment;
200
+ segment = 0;
201
+ if (c === 0x0a) {
202
+ run += 1;
203
+ newlines += 1;
204
+ continue;
205
+ }
206
+ if (run >= MIN_PRICED_RUN) {
207
+ runCost += run * run;
208
+ linesTimesRun += (newlines + 1) * run;
209
+ }
210
+ run = 0;
211
+ newlines = 0;
212
+ }
213
+ return { run: runCost, line: lineCost, linesTimesRun };
70
214
  }
71
- /** Capture-group-1 of a pattern, per file. */
72
- function byRegex(source, files) {
215
+ /** Price every flagged hazard by its OWN reach; the file costs what its worst hazard costs. */
216
+ function predictedHazardCost(hazards, costs) {
217
+ let worst = { cost: 0, measure: 'Σ run²' };
218
+ for (const h of hazards) {
219
+ const priced = !h.crossesNewline
220
+ ? { cost: costs.line, measure: 'Σ line-run²' }
221
+ : h.shape === 'leading' && h.fromLineStart
222
+ ? { cost: costs.linesTimesRun, measure: 'Σ lines×run' }
223
+ : { cost: costs.run, measure: 'Σ run²' };
224
+ if (priced.cost > worst.cost)
225
+ worst = priced;
226
+ }
227
+ return worst;
228
+ }
229
+ /**
230
+ * The remedy for each hazard shape present. A LEADING quantifier is fixed by
231
+ * a literal anchor — never by another quantifier: a leading `[ \t]*` is still
232
+ * tried at every offset of a blanked line.
233
+ */
234
+ function hazardRemedy(hazards) {
235
+ const remedies = [];
236
+ if (hazards.some((h) => h.shape === 'leading')) {
237
+ remedies.push('anchor the alternative on a literal — begin it with the token the whitespace precedes ' +
238
+ '(`foo[ \\t]*\\(`, not `[ \\t]*foo\\(`), since a leading whitespace quantifier of any class is tried at every offset');
239
+ }
240
+ if (hazards.some((h) => h.shape === 'adjacent')) {
241
+ remedies.push('collapse the touching whitespace quantifiers into one');
242
+ }
243
+ return remedies.join('; ');
244
+ }
245
+ /** The hint a hazardous user pattern earns under a zone — surfaced through `gates coverage` / `explain`. */
246
+ function blankRunHazardHint(zone, hazards) {
247
+ const h = hazards[0];
248
+ const reach = hazards.every((x) => !x.crossesNewline)
249
+ ? ' It stops at each newline, so only a very long blanked line is costly.'
250
+ : '';
251
+ return (`pattern backtracking hazard under scan: '${zone}': ${h.message}. Blanked comments and strings become ` +
252
+ `long whitespace runs; ${hazardRemedy(hazards)} (or scan: 'all').${reach}`);
253
+ }
254
+ function namedFiles(files) {
255
+ return files.slice(0, 5).join(', ') + (files.length > 5 ? `, … (+${files.length - 5} more)` : '');
256
+ }
257
+ function formatCost(n) {
258
+ return n.toExponential(1).replace('e+', 'e');
259
+ }
260
+ /**
261
+ * The error for files a zoned `regex-capture` could not judge — loud, named,
262
+ * never a silent partial. The two causes are worded apart: a PREDICTED skip
263
+ * never ran the regex (so it spent nothing), a STOPPED file ran past the cap.
264
+ */
265
+ function zonedOverBudgetError(zone, run, hazards) {
266
+ const parts = [];
267
+ if (run.predicted.length > 0) {
268
+ const worst = run.predicted.reduce((a, b) => (b.cost > a.cost ? b : a));
269
+ parts.push(`predicted over budget, so the regex was never run (${worst.measure} = ${formatCost(worst.cost)} > ` +
270
+ `${formatCost(ZONED_HAZARD_COST_LIMIT)}): ${namedFiles(run.predicted.map((p) => p.path))}`);
271
+ }
272
+ if (run.ran.length > 0) {
273
+ parts.push(`ran past the ${ZONED_REGEX_FILE_BUDGET_MS} ms per-file cap and was stopped: ${namedFiles(run.ran)}`);
274
+ }
275
+ const total = run.predicted.length + run.ran.length;
276
+ const why = hazards.length > 0 ? ` — ${hazards[0].message}` : '';
277
+ const fix = hazards.length > 0 ? hazardRemedy(hazards) : 'simplify the pattern';
278
+ return (`regex-capture under scan: '${zone}' skipped ${total} file(s): over budget — ${parts.join('; ')}${why}. ` +
279
+ `${fix.charAt(0).toUpperCase()}${fix.slice(1)}, or use scan: 'all'.`);
280
+ }
281
+ /**
282
+ * Capture-group-1 of a pattern, per file. Under a zone (`zoned`), each file is
283
+ * bounded: a FLAGGED pattern skips a file whose predicted work — each hazard
284
+ * priced by its own reach, so a line-bounded one pays per line — is over the
285
+ * limit, and any pattern stops a file that runs past the per-file budget.
286
+ * Both are named, never a quietly smaller token set.
287
+ */
288
+ function byRegex(source, files, zoned, hazards) {
73
289
  const { re } = safeCompile(source.pattern, source.flags);
74
290
  if (!re)
75
- return [];
291
+ return { sites: [], predicted: [], ran: [] };
76
292
  const sites = [];
293
+ const predicted = [];
294
+ const ran = [];
77
295
  for (const f of files) {
296
+ if (zoned && hazards.length > 0) {
297
+ const p = predictedHazardCost(hazards, blankRunCosts(f.content));
298
+ if (p.cost > ZONED_HAZARD_COST_LIMIT) {
299
+ predicted.push({ path: f.path, ...p });
300
+ continue;
301
+ }
302
+ }
303
+ const startedAt = Date.now();
304
+ const fileSites = [];
305
+ let over = false;
78
306
  re.lastIndex = 0;
79
307
  let m;
80
308
  while ((m = re.exec(f.content)) !== null) {
@@ -82,12 +310,42 @@ function byRegex(source, files) {
82
310
  if (m.index === re.lastIndex)
83
311
  re.lastIndex += 1;
84
312
  const token = m[1];
85
- if (token === undefined || token === '')
86
- continue;
87
- sites.push({ token, file: f.path, line: lineOf(f.content, m.index) });
313
+ if (token !== undefined && token !== '') {
314
+ fileSites.push({ token, file: f.path, line: lineOf(f.content, m.index) });
315
+ }
316
+ if (zoned && Date.now() - startedAt > ZONED_REGEX_FILE_BUDGET_MS) {
317
+ over = true;
318
+ break;
319
+ }
320
+ }
321
+ if (over) {
322
+ ran.push(f.path);
323
+ continue;
88
324
  }
325
+ sites.push(...fileSites);
89
326
  }
90
- return sites;
327
+ return { sites, predicted, ran };
328
+ }
329
+ /**
330
+ * The head regexes the anchor-based extractors run — possibly on a blanked
331
+ * buffer. One factory, so the linearity lock (`r75-blank-run-linearity`)
332
+ * times and lints the exact patterns that run, not copies of them.
333
+ */
334
+ export function extractorHeadPatterns(anchor) {
335
+ const a = escapeRegex(anchor);
336
+ const literalHead = (open) => new RegExp(`(?<![\\w$])${a}\\s*(?::[^=\\n]*)?[:=]\\s*(?:[A-Za-z_$][\\w$.]*\\s*\\(\\s*)?\\${open}`, 'g');
337
+ return {
338
+ arrayLiteral: literalHead('['),
339
+ objectLiteral: literalHead('{'),
340
+ enumBody: new RegExp(`\\benum\\s+${a}\\s*\\{`, 'g'),
341
+ call: new RegExp(`(?<![\\w$.@])${a}\\s*\\(`, 'g'),
342
+ decorator: new RegExp(`@${a}\\s*\\(`, 'g'),
343
+ // Collapsed from `\s*(?:<[^>]*>)?\s*=`: two whitespace quantifiers with
344
+ // only an optional group between them re-partition a blank run.
345
+ stringUnion: new RegExp(`\\btype\\s+${a}\\s*(?:<[^>]*>\\s*)?=`, 'g'),
346
+ exportDecl: EXPORT_DECL,
347
+ exportClause: EXPORT_CLAUSE,
348
+ };
91
349
  }
92
350
  /**
93
351
  * Elements of every `<anchor> = <open> … ` / `<anchor>: <open> … ` literal.
@@ -99,7 +357,8 @@ function byRegex(source, files) {
99
357
  */
100
358
  function byBracketLiteral(anchor, open, files, tokenOf) {
101
359
  const sites = [];
102
- const head = new RegExp(`(?<![\\w$])${escapeRegex(anchor)}\\s*(?::[^=\\n]*)?[:=]\\s*(?:[A-Za-z_$][\\w$.]*\\s*\\(\\s*)?\\${open}`, 'g');
360
+ const heads = extractorHeadPatterns(anchor);
361
+ const head = open === '[' ? heads.arrayLiteral : heads.objectLiteral;
103
362
  for (const f of files) {
104
363
  head.lastIndex = 0;
105
364
  let m;
@@ -122,7 +381,7 @@ function byBracketLiteral(anchor, open, files, tokenOf) {
122
381
  /** Members of `enum <anchor> { … }` — the member name, or its assigned value. */
123
382
  function byEnumMembers(anchor, wantValue, files) {
124
383
  const sites = [];
125
- const head = new RegExp(`\\benum\\s+${escapeRegex(anchor)}\\s*\\{`, 'g');
384
+ const head = extractorHeadPatterns(anchor).enumBody;
126
385
  for (const f of files) {
127
386
  head.lastIndex = 0;
128
387
  let m;
@@ -173,9 +432,8 @@ function byExportNames(files) {
173
432
  /** Argument `argIndex` of every `anchor(…)` call — or `@anchor(…)` decorator. */
174
433
  function byCallArgs(anchor, argIndex, decorator, files) {
175
434
  const sites = [];
176
- const head = decorator
177
- ? new RegExp(`@${escapeRegex(anchor)}\\s*\\(`, 'g')
178
- : new RegExp(`(?<![\\w$.@])${escapeRegex(anchor)}\\s*\\(`, 'g');
435
+ const heads = extractorHeadPatterns(anchor);
436
+ const head = decorator ? heads.decorator : heads.call;
179
437
  for (const f of files) {
180
438
  head.lastIndex = 0;
181
439
  let m;
@@ -199,7 +457,7 @@ function byCallArgs(anchor, argIndex, decorator, files) {
199
457
  /** The string literals of `type <anchor> = 'a' | 'b' | 'c'`. */
200
458
  function byStringUnion(anchor, files) {
201
459
  const sites = [];
202
- const head = new RegExp(`\\btype\\s+${escapeRegex(anchor)}\\s*(?:<[^>]*>)?\\s*=`, 'g');
460
+ const head = extractorHeadPatterns(anchor).stringUnion;
203
461
  const member = /['"`]([^'"`]+)['"`]/g;
204
462
  for (const f of files) {
205
463
  head.lastIndex = 0;
@@ -0,0 +1,12 @@
1
+ import type { IWiringSource } from '@shrkcrft/core';
2
+ /**
3
+ * One extraction source of a gate rule, named by the side it plays —
4
+ * `declared`, `registered[1]`, `chain[0]`, `source`, `consumer`, a role, or
5
+ * `compute.source`. The label qualifies the source's marker lists
6
+ * (`declared.files`) and prefixes its units in a multi-source report.
7
+ */
8
+ export interface ILabeledSource {
9
+ readonly label: string;
10
+ readonly source: IWiringSource;
11
+ }
12
+ //# sourceMappingURL=i-labeled-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i-labeled-source.d.ts","sourceRoot":"","sources":["../../src/extract/i-labeled-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import type { IWiringSource } from '@shrkcrft/core';
2
+ import { type ITsconfigPathsMap } from '../scan/tsconfig-aliases.js';
3
+ import type { IExtractFileEntry, IExtractedSite } from './extract-tokens.js';
4
+ /**
5
+ * The `import-edges` extractor — the dependency graph as a rule input.
6
+ *
7
+ * Every other extractor reads file CONTENTS: a regex, an array literal, an enum
8
+ * body, an export list. None of them can see which file imports what, so an
9
+ * entire class of invariant — alias-resolved dependency direction — was
10
+ * inexpressible as a rule, and repos hand-rolled scripts for it (adoption
11
+ * ledgers, orphan scans, deprecation ratchets).
12
+ *
13
+ * This emits that missing fact as an id set, so every existing plane gets it for
14
+ * free: a `baseline` over the set is an adoption ledger (a LOST edge is a silent
15
+ * de-adoption); `direction: 'no-shrink'` over the importer set is a deprecation
16
+ * ratchet; a `wiring` rule whose registered side is "symbols with ≥1 importer"
17
+ * finds dead generated code a byte-drift gate cannot see.
18
+ *
19
+ * **On freshness.** It reads the files the caller already walked, resolving
20
+ * specifiers on the spot — there is no persisted graph index behind it and
21
+ * therefore no staleness question to get wrong. That is deliberate: a rule
22
+ * answering from a stale graph would be a confident false green, the exact
23
+ * failure this engine exists to prevent.
24
+ *
25
+ * **Honest scope.** It resolves what the text says plus tsconfig path aliases —
26
+ * the same resolution `check boundaries` uses. It does not follow a re-export
27
+ * chain to attribute a symbol to its original module: a barrel is reported as
28
+ * the module the consumer actually names. That is a lexer's honest answer, and
29
+ * `to.files` matches the resolved target when you need the real path.
30
+ */
31
+ /** What an emitted id represents. */
32
+ export type ImportEdgeEmit = 'edge' | 'symbol' | 'from';
33
+ /** Context a caller supplies so alias specifiers resolve. */
34
+ export interface IImportEdgeContext {
35
+ readonly tsconfigPaths?: ITsconfigPathsMap;
36
+ }
37
+ /**
38
+ * Extract the import edges a source selects.
39
+ *
40
+ * `files` is the CONSUMER glob (the `from` side): it reuses the field every
41
+ * other extractor uses, so `--changed-only` footprinting, the shared walk, and
42
+ * `$use` all work on it unchanged.
43
+ */
44
+ export declare function extractImportEdges(source: IWiringSource, files: readonly IExtractFileEntry[], context?: IImportEdgeContext): {
45
+ sites: IExtractedSite[];
46
+ error?: string;
47
+ hint?: string;
48
+ blankedChars?: number;
49
+ };
50
+ //# sourceMappingURL=import-edges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-edges.d.ts","sourceRoot":"","sources":["../../src/extract/import-edges.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7F,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,qCAAqC;AACrC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAmFxD,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,SAAS,iBAAiB,EAAE,EACnC,OAAO,GAAE,kBAAuB,GAC/B;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CA4FnF"}