@vibe-agent-toolkit/cli 0.2.0-rc.1 → 0.2.0-rc.3

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 (199) hide show
  1. package/dist/bin/vat +66 -15
  2. package/dist/bin/vat.js +66 -15
  3. package/dist/bin/vat.js.map +1 -1
  4. package/dist/bin.js +155 -36
  5. package/dist/bin.js.map +1 -1
  6. package/dist/command-loaders.d.ts +44 -0
  7. package/dist/command-loaders.d.ts.map +1 -0
  8. package/dist/command-loaders.js +58 -0
  9. package/dist/command-loaders.js.map +1 -0
  10. package/dist/commands/agent/index.js +1 -1
  11. package/dist/commands/agent/install.d.ts.map +1 -1
  12. package/dist/commands/agent/install.js +46 -5
  13. package/dist/commands/agent/install.js.map +1 -1
  14. package/dist/commands/audit/distributed-tree.d.ts +1 -1
  15. package/dist/commands/audit/distributed-tree.d.ts.map +1 -1
  16. package/dist/commands/audit/distributed-tree.js.map +1 -1
  17. package/dist/commands/audit/hierarchical-output.d.ts +1 -1
  18. package/dist/commands/audit/hierarchical-output.d.ts.map +1 -1
  19. package/dist/commands/audit/hierarchical-output.js +1 -1
  20. package/dist/commands/audit/hierarchical-output.js.map +1 -1
  21. package/dist/commands/audit.d.ts +22 -1
  22. package/dist/commands/audit.d.ts.map +1 -1
  23. package/dist/commands/audit.js +223 -24
  24. package/dist/commands/audit.js.map +1 -1
  25. package/dist/commands/build.d.ts +1 -1
  26. package/dist/commands/build.d.ts.map +1 -1
  27. package/dist/commands/build.js +2 -2
  28. package/dist/commands/build.js.map +1 -1
  29. package/dist/commands/cache/cache-control.d.ts +73 -0
  30. package/dist/commands/cache/cache-control.d.ts.map +1 -0
  31. package/dist/commands/cache/cache-control.js +77 -0
  32. package/dist/commands/cache/cache-control.js.map +1 -0
  33. package/dist/commands/cache/clear.d.ts +17 -3
  34. package/dist/commands/cache/clear.d.ts.map +1 -1
  35. package/dist/commands/cache/clear.js +68 -3
  36. package/dist/commands/cache/clear.js.map +1 -1
  37. package/dist/commands/cache/index.d.ts +13 -63
  38. package/dist/commands/cache/index.d.ts.map +1 -1
  39. package/dist/commands/cache/index.js +38 -79
  40. package/dist/commands/cache/index.js.map +1 -1
  41. package/dist/commands/claude/budget.d.ts +157 -0
  42. package/dist/commands/claude/budget.d.ts.map +1 -0
  43. package/dist/commands/claude/budget.js +412 -0
  44. package/dist/commands/claude/budget.js.map +1 -0
  45. package/dist/commands/claude/context.d.ts +211 -0
  46. package/dist/commands/claude/context.d.ts.map +1 -0
  47. package/dist/commands/claude/context.js +709 -0
  48. package/dist/commands/claude/context.js.map +1 -0
  49. package/dist/commands/claude/index.d.ts +13 -0
  50. package/dist/commands/claude/index.d.ts.map +1 -1
  51. package/dist/commands/claude/index.js +24 -2
  52. package/dist/commands/claude/index.js.map +1 -1
  53. package/dist/commands/claude/marketplace/git-publish.d.ts.map +1 -1
  54. package/dist/commands/claude/marketplace/git-publish.js +18 -20
  55. package/dist/commands/claude/marketplace/git-publish.js.map +1 -1
  56. package/dist/commands/claude/marketplace/validate.d.ts +1 -1
  57. package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
  58. package/dist/commands/claude/marketplace/validate.js +1 -1
  59. package/dist/commands/claude/marketplace/validate.js.map +1 -1
  60. package/dist/commands/claude/plugin/build.d.ts +16 -2
  61. package/dist/commands/claude/plugin/build.d.ts.map +1 -1
  62. package/dist/commands/claude/plugin/build.js +64 -11
  63. package/dist/commands/claude/plugin/build.js.map +1 -1
  64. package/dist/commands/claude/plugin/install.d.ts.map +1 -1
  65. package/dist/commands/claude/plugin/install.js +22 -2
  66. package/dist/commands/claude/plugin/install.js.map +1 -1
  67. package/dist/commands/claude/plugin/marketplace-json.d.ts +24 -9
  68. package/dist/commands/claude/plugin/marketplace-json.d.ts.map +1 -1
  69. package/dist/commands/claude/plugin/marketplace-json.js +10 -9
  70. package/dist/commands/claude/plugin/marketplace-json.js.map +1 -1
  71. package/dist/commands/consistency-check.d.ts.map +1 -1
  72. package/dist/commands/consistency-check.js +3 -3
  73. package/dist/commands/consistency-check.js.map +1 -1
  74. package/dist/commands/corpus/report.d.ts +1 -1
  75. package/dist/commands/corpus/report.d.ts.map +1 -1
  76. package/dist/commands/corpus/runner.js +1 -1
  77. package/dist/commands/corpus/runner.js.map +1 -1
  78. package/dist/commands/corpus/scan.d.ts.map +1 -1
  79. package/dist/commands/corpus/scan.js +17 -8
  80. package/dist/commands/corpus/scan.js.map +1 -1
  81. package/dist/commands/doctor.d.ts +36 -0
  82. package/dist/commands/doctor.d.ts.map +1 -1
  83. package/dist/commands/doctor.js +96 -0
  84. package/dist/commands/doctor.js.map +1 -1
  85. package/dist/commands/inventory.d.ts +13 -1
  86. package/dist/commands/inventory.d.ts.map +1 -1
  87. package/dist/commands/inventory.js +118 -13
  88. package/dist/commands/inventory.js.map +1 -1
  89. package/dist/commands/mcp/collections.d.ts +1 -1
  90. package/dist/commands/mcp/collections.d.ts.map +1 -1
  91. package/dist/commands/phase-utils.d.ts +1 -1
  92. package/dist/commands/phase-utils.d.ts.map +1 -1
  93. package/dist/commands/positional-args.js +1 -1
  94. package/dist/commands/positional-args.js.map +1 -1
  95. package/dist/commands/rag/index-command.d.ts +39 -0
  96. package/dist/commands/rag/index-command.d.ts.map +1 -1
  97. package/dist/commands/rag/index-command.js +28 -2
  98. package/dist/commands/rag/index-command.js.map +1 -1
  99. package/dist/commands/rag/index.d.ts.map +1 -1
  100. package/dist/commands/rag/index.js +21 -10
  101. package/dist/commands/rag/index.js.map +1 -1
  102. package/dist/commands/resources/index.d.ts.map +1 -1
  103. package/dist/commands/resources/index.js +10 -2
  104. package/dist/commands/resources/index.js.map +1 -1
  105. package/dist/commands/resources/scan.d.ts +24 -0
  106. package/dist/commands/resources/scan.d.ts.map +1 -1
  107. package/dist/commands/resources/scan.js +18 -5
  108. package/dist/commands/resources/scan.js.map +1 -1
  109. package/dist/commands/resources/validate.d.ts +1 -1
  110. package/dist/commands/resources/validate.d.ts.map +1 -1
  111. package/dist/commands/resources/validate.js +6 -3
  112. package/dist/commands/resources/validate.js.map +1 -1
  113. package/dist/commands/skill/review-checklist.d.ts.map +1 -1
  114. package/dist/commands/skill/review-checklist.js +1 -0
  115. package/dist/commands/skill/review-checklist.js.map +1 -1
  116. package/dist/commands/skill/review.js +2 -2
  117. package/dist/commands/skill/review.js.map +1 -1
  118. package/dist/commands/skill/test/configure.d.ts +19 -0
  119. package/dist/commands/skill/test/configure.d.ts.map +1 -1
  120. package/dist/commands/skill/test/configure.js +18 -3
  121. package/dist/commands/skill/test/configure.js.map +1 -1
  122. package/dist/commands/skill/test/run.d.ts +51 -4
  123. package/dist/commands/skill/test/run.d.ts.map +1 -1
  124. package/dist/commands/skill/test/run.js +112 -10
  125. package/dist/commands/skill/test/run.js.map +1 -1
  126. package/dist/commands/skills/build.d.ts +1 -1
  127. package/dist/commands/skills/build.d.ts.map +1 -1
  128. package/dist/commands/skills/build.js +72 -37
  129. package/dist/commands/skills/build.js.map +1 -1
  130. package/dist/commands/skills/package.d.ts +1 -1
  131. package/dist/commands/skills/package.d.ts.map +1 -1
  132. package/dist/commands/skills/package.js.map +1 -1
  133. package/dist/commands/skills/scope-guard.js +1 -1
  134. package/dist/commands/skills/scope-guard.js.map +1 -1
  135. package/dist/commands/skills/validate.d.ts +1 -1
  136. package/dist/commands/skills/validate.d.ts.map +1 -1
  137. package/dist/commands/skills/validate.js +37 -19
  138. package/dist/commands/skills/validate.js.map +1 -1
  139. package/dist/commands/validate.d.ts.map +1 -1
  140. package/dist/commands/validate.js +2 -1
  141. package/dist/commands/validate.js.map +1 -1
  142. package/dist/commands/verify.d.ts +2 -2
  143. package/dist/commands/verify.d.ts.map +1 -1
  144. package/dist/commands/verify.js +4 -4
  145. package/dist/commands/verify.js.map +1 -1
  146. package/dist/utils/command-error.d.ts +1 -1
  147. package/dist/utils/command-error.d.ts.map +1 -1
  148. package/dist/utils/command-error.js +1 -1
  149. package/dist/utils/command-error.js.map +1 -1
  150. package/dist/utils/config-loader.d.ts.map +1 -1
  151. package/dist/utils/config-loader.js +7 -1
  152. package/dist/utils/config-loader.js.map +1 -1
  153. package/dist/utils/context-budget-issues.d.ts +108 -0
  154. package/dist/utils/context-budget-issues.d.ts.map +1 -0
  155. package/dist/utils/context-budget-issues.js +280 -0
  156. package/dist/utils/context-budget-issues.js.map +1 -0
  157. package/dist/utils/corpus-target.d.ts +48 -0
  158. package/dist/utils/corpus-target.d.ts.map +1 -0
  159. package/dist/utils/corpus-target.js +61 -0
  160. package/dist/utils/corpus-target.js.map +1 -0
  161. package/dist/utils/issue-anchor.d.ts +2 -2
  162. package/dist/utils/issue-anchor.d.ts.map +1 -1
  163. package/dist/utils/issue-anchor.js +1 -1
  164. package/dist/utils/issue-rendering.d.ts +1 -1
  165. package/dist/utils/issue-rendering.d.ts.map +1 -1
  166. package/dist/utils/issue-rendering.js +1 -1
  167. package/dist/utils/issue-rendering.js.map +1 -1
  168. package/dist/utils/issue-severity.d.ts +1 -1
  169. package/dist/utils/issue-severity.d.ts.map +1 -1
  170. package/dist/utils/issue-severity.js +1 -1
  171. package/dist/utils/issue-severity.js.map +1 -1
  172. package/dist/utils/optional-backend.d.ts +77 -0
  173. package/dist/utils/optional-backend.d.ts.map +1 -0
  174. package/dist/utils/optional-backend.js +115 -0
  175. package/dist/utils/optional-backend.js.map +1 -0
  176. package/dist/utils/output.d.ts +17 -0
  177. package/dist/utils/output.d.ts.map +1 -1
  178. package/dist/utils/output.js +19 -0
  179. package/dist/utils/output.js.map +1 -1
  180. package/dist/utils/population-wiring.d.ts +59 -0
  181. package/dist/utils/population-wiring.d.ts.map +1 -0
  182. package/dist/utils/population-wiring.js +55 -0
  183. package/dist/utils/population-wiring.js.map +1 -0
  184. package/dist/utils/projection-store.d.ts +186 -0
  185. package/dist/utils/projection-store.d.ts.map +1 -0
  186. package/dist/utils/projection-store.js +255 -0
  187. package/dist/utils/projection-store.js.map +1 -0
  188. package/dist/utils/resource-loader.d.ts +127 -1
  189. package/dist/utils/resource-loader.d.ts.map +1 -1
  190. package/dist/utils/resource-loader.js +224 -7
  191. package/dist/utils/resource-loader.js.map +1 -1
  192. package/dist/utils/verdict-helpers.d.ts +1 -1
  193. package/dist/utils/verdict-helpers.d.ts.map +1 -1
  194. package/dist/utils/verdict-helpers.js +1 -1
  195. package/dist/utils/verdict-helpers.js.map +1 -1
  196. package/docs/agent.md +2 -2
  197. package/docs/mcp.md +2 -2
  198. package/docs/resources.md +8 -1
  199. package/package.json +15 -12
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Selecting, opening and keying the **projection store** — the cross-process
3
+ * cache that makes a second population of an unchanged tree cheap.
4
+ *
5
+ * ## Why the CLI owns this and `resources` does not
6
+ *
7
+ * `@vibe-agent-toolkit/resources` states the {@link ProjectionStore} contract
8
+ * and never picks a backend, for the same reason it states the parse contract
9
+ * and never picks a parser: it is the toolkit's most widely installed package,
10
+ * and a storage engine is a *choice*. The choice is made here, at the edge that
11
+ * already owns every other optional backend — see `optional-backend.ts`, whose
12
+ * header names a projection store as one of the shapes it exists for.
13
+ *
14
+ * So `populate()` takes a {@link PopulationCache} it is handed, and this module
15
+ * is the only place in the toolkit that knows `@vibe-agent-toolkit/projection-
16
+ * sqlite` exists.
17
+ *
18
+ * ## The key, and why it is a whole-repository tree hash
19
+ *
20
+ * A stored extent is filed under `(rootId, treeHash)`. `populate()` derives the
21
+ * root id itself so a caller cannot file one root's contents under another's;
22
+ * this module supplies the other half.
23
+ *
24
+ * {@link gitTreeSnapshot} answers it with `git write-tree` against a throwaway
25
+ * index, which covers staged edits, unstaged edits and untracked files, and
26
+ * carries **no timestamp** — byte-identical content always produces the same
27
+ * hash. 🪤 Never `git stash create`: a stash is a *commit*, so two calls over
28
+ * identical content agree only within the same wall-clock second, and every
29
+ * read would miss.
30
+ *
31
+ * ⚠️ That hash covers the whole **repository**, not the subtree the root names.
32
+ * An edit anywhere in the repository therefore cools the cache for every root
33
+ * inside it. This is conservative in the safe direction and cheap to be
34
+ * conservative about — `git write-tree` against a throwaway index is the same
35
+ * call `vibe-validate` makes on every commit.
36
+ *
37
+ * ## An opted-in cache that quietly does nothing is worse than no cache
38
+ *
39
+ * Every failure here is loud, and that is deliberate rather than harsh. A
40
+ * selector nobody honours produces a measurement arm that believes it is
41
+ * testing a cache and is testing an ordinary cold run — the "subject that
42
+ * exercises nothing looks like a clean result" failure that has already cost
43
+ * this project one whole A/B. So an uninstalled backend exits with the seam's
44
+ * standard legible error, and a tree that cannot be keyed says so on stderr
45
+ * rather than silently declining.
46
+ */
47
+ import type { PopulationCache } from '@vibe-agent-toolkit/resources';
48
+ /**
49
+ * The env var that selects a projection store for this process.
50
+ *
51
+ * An environment switch rather than a config field, for the same reason
52
+ * `VAT_INVENTORY_CRAWL` and `VAT_RESOURCES_CRAWL` are: it selects which
53
+ * INSTRUMENT runs, not what the project means, and it has to be reachable from
54
+ * the lab, which spawns the binary and controls its environment. A config field
55
+ * would put the A and B arms inside the subject's own tree, where a measurement
56
+ * edits the thing it measures.
57
+ *
58
+ * 🔑 It is read from the environment and therefore **inherited by every phase
59
+ * child**. `runPhase` passes no `env` to `spawnSync`, so `vat validate`'s
60
+ * children see the same selection their parent did.
61
+ *
62
+ * 🔑 **That inheritance now has a within-verb instance.** `vat build`'s two
63
+ * phases — `skills build` and `claude plugin build` — both reach the lane
64
+ * through `withResourcePopulationSource` (see `resource-loader.ts`), and both
65
+ * root their population at the same directory, so phase 2 reads the extent
66
+ * phase 1 wrote. Measured on `packages/vat-development-agents` with
67
+ * `VAT_CRAWL_TIMING`: with a cold store phase 1 files `builtin:filesystem`
68
+ * 39.2 ms and `projection-store:write` 10.1 ms, phase 2 files neither and its
69
+ * `resource-registry:enumerate` reads 3.6 ms against phase 1's 66.6 ms.
70
+ *
71
+ * It did NOT need the closure to emit reasons, which is what an earlier reading
72
+ * of this expected: the packaging lanes consume `resource_realizations` and let
73
+ * `walkLinkGraph` keep running on top of the registry, so the base extent alone
74
+ * answers them — the same shape `buildResourcePopulation` already had.
75
+ *
76
+ * The cross-INVOCATION win is unchanged and independent: `vat validate` and
77
+ * `vat verify` spawn a byte-identical `resources validate` child, so the second
78
+ * hits the store.
79
+ *
80
+ * ⚠️ One packaging enumeration is still on the walk: `vat claude plugin build`'s
81
+ * per-skill post-build validation, which reaches `crawlAndResolveRegistry` in
82
+ * `packaging-validator.ts` without a source — its `withResourcePopulationSource`
83
+ * bracket closes around `createProjectRegistry` and does not span the
84
+ * marketplace loop. `vat skills build` no longer does: it holds one bracket over
85
+ * the whole run, and the registry memo is keyed on the population source, so
86
+ * both of its registries source from the projection.
87
+ */
88
+ export declare const PROJECTION_STORE_ENV = "VAT_PROJECTION_STORE";
89
+ /** {@link PROJECTION_STORE_ENV}'s value that selects the SQLite backend. */
90
+ export declare const PROJECTION_STORE_SQLITE = "sqlite";
91
+ /**
92
+ * The env var that turns VAT's disk caches off for a run.
93
+ *
94
+ * Not this module's invention — `ParseCache` has read it since the parse cache
95
+ * shipped, and `vat`'s root `--no-cache` exports it from a `preAction` hook so
96
+ * the decision reaches every spawned phase. Named here rather than spelled
97
+ * inline so the projection store is visibly the same tenant as the caches the
98
+ * flag was written for.
99
+ */
100
+ export declare const CACHE_ENV = "VAT_CACHE";
101
+ /** {@link CACHE_ENV}'s one off value. Exactly `'0'`, never truthiness — see {@link projectionStoreSelected}. */
102
+ export declare const CACHE_DISABLED = "0";
103
+ /**
104
+ * Whether this process should read and write a projection store.
105
+ *
106
+ * **Off unless asked for**, which is the opposite of `vat inventory`'s crawl
107
+ * selector and matches `vat resources scan`'s. A cache changes no answer, so
108
+ * the reason to hold it back is not correctness but evidence: the win is a
109
+ * claim about cost, and a default flipped before the cost is measured on real
110
+ * corpora is a claim nobody checked.
111
+ *
112
+ * Read from the environment at each call rather than memoized at module load:
113
+ * `vitest.setup.js` deletes every `VAT_*` variable before any test module
114
+ * loads, so a module-level binding would make the switch unobservable to every
115
+ * test that sets it.
116
+ *
117
+ * ## The two switches are AND-ed, and the second one is a veto
118
+ *
119
+ * {@link PROJECTION_STORE_ENV} says *which* backend; {@link CACHE_ENV} says
120
+ * whether this run caches at all. A store selected while `VAT_CACHE=0` was
121
+ * measured writing a 9.8 MB, 18,079-row store on this repository and hitting it
122
+ * on the next run — a user who asked for no cache silently got one, and
123
+ * `vat cache`'s own help text described three caches while a fourth was being
124
+ * written beside them.
125
+ *
126
+ * 🪤 Compared against `'0'` exactly, never for truthiness, matching
127
+ * `ParseCache`'s `env['VAT_CACHE'] !== '0'`. `VAT_CACHE=1` is the value an
128
+ * operator writes to turn caching ON, and a truthiness test would read it as a
129
+ * reason to decline.
130
+ *
131
+ * @returns `true` when a store is selected
132
+ */
133
+ export declare function projectionStoreSelected(): boolean;
134
+ /** An open store, the key half it is used with, and the way to let it go. */
135
+ export interface OpenedPopulationCache {
136
+ /** Hand this to `populate()`. */
137
+ readonly cache: PopulationCache;
138
+ /**
139
+ * Close the underlying connection.
140
+ *
141
+ * Must be called. A `DatabaseSync` left open holds its file handle and, in
142
+ * WAL mode, its read transaction — see `projection-sqlite`'s note on why an
143
+ * unfinalized read statement pins a connection to a stale snapshot.
144
+ */
145
+ close(): Promise<void>;
146
+ }
147
+ /**
148
+ * Open the projection store this process selected, keyed to one tree.
149
+ *
150
+ * Returns `undefined` when no store is selected, and when the tree cannot be
151
+ * keyed — the two "carry on without a cache" answers. It does **not** return
152
+ * `undefined` for an uninstalled backend: a user who set the selector asked for
153
+ * a store, and answering that request by silently not having one is how an
154
+ * opted-in cache becomes an unmeasured one.
155
+ *
156
+ * @param options - Where the corpus is
157
+ * @param options.root - The absolute corpus root. Used to find the repository;
158
+ * the resulting hash covers that whole repository, not this subtree
159
+ * @returns The cache and its closer, or `undefined` to populate uncached
160
+ */
161
+ export declare function openPopulationCache(options: {
162
+ root: string;
163
+ }): Promise<OpenedPopulationCache | undefined>;
164
+ /**
165
+ * Run one command's work with a projection store open for its whole duration,
166
+ * and closed however it ends.
167
+ *
168
+ * A scope rather than a bare open/close pair, because the store must outlive the
169
+ * call that builds a population source and not merely the call that uses it: the
170
+ * inventory extractor MEMOIZES its population provider and may reach it well
171
+ * after the frame that supplied it has returned. A store closed at the end of
172
+ * that frame would be closed under its own consumer.
173
+ *
174
+ * It is also the `withGitSnapshotCache` bracket for the work inside it, so the
175
+ * key and the extent filed under it come from ONE git snapshot — see the note
176
+ * on the call below.
177
+ *
178
+ * @param options - Where the corpus is
179
+ * @param options.root - The absolute corpus root
180
+ * @param work - Given the cache, or `undefined` when there is none to give
181
+ * @returns Whatever `work` returned
182
+ */
183
+ export declare function withPopulationCache<T>(options: {
184
+ root: string;
185
+ }, work: (cache: PopulationCache | undefined) => Promise<T>): Promise<T>;
186
+ //# sourceMappingURL=projection-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection-store.d.ts","sourceRoot":"","sources":["../../src/utils/projection-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAKrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAEhD;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,cAAc,CAAC;AAErC,gHAAgH;AAChH,eAAO,MAAM,cAAc,MAAM,CAAC;AAelC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAGjD;AAED,6EAA6E;AAC7E,MAAM,WAAW,qBAAqB;IACpC,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC;;;;;;OAMG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IACjD,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAsB7C;AAuBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACzB,IAAI,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GACvD,OAAO,CAAC,CAAC,CAAC,CA0BZ"}
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Selecting, opening and keying the **projection store** — the cross-process
3
+ * cache that makes a second population of an unchanged tree cheap.
4
+ *
5
+ * ## Why the CLI owns this and `resources` does not
6
+ *
7
+ * `@vibe-agent-toolkit/resources` states the {@link ProjectionStore} contract
8
+ * and never picks a backend, for the same reason it states the parse contract
9
+ * and never picks a parser: it is the toolkit's most widely installed package,
10
+ * and a storage engine is a *choice*. The choice is made here, at the edge that
11
+ * already owns every other optional backend — see `optional-backend.ts`, whose
12
+ * header names a projection store as one of the shapes it exists for.
13
+ *
14
+ * So `populate()` takes a {@link PopulationCache} it is handed, and this module
15
+ * is the only place in the toolkit that knows `@vibe-agent-toolkit/projection-
16
+ * sqlite` exists.
17
+ *
18
+ * ## The key, and why it is a whole-repository tree hash
19
+ *
20
+ * A stored extent is filed under `(rootId, treeHash)`. `populate()` derives the
21
+ * root id itself so a caller cannot file one root's contents under another's;
22
+ * this module supplies the other half.
23
+ *
24
+ * {@link gitTreeSnapshot} answers it with `git write-tree` against a throwaway
25
+ * index, which covers staged edits, unstaged edits and untracked files, and
26
+ * carries **no timestamp** — byte-identical content always produces the same
27
+ * hash. 🪤 Never `git stash create`: a stash is a *commit*, so two calls over
28
+ * identical content agree only within the same wall-clock second, and every
29
+ * read would miss.
30
+ *
31
+ * ⚠️ That hash covers the whole **repository**, not the subtree the root names.
32
+ * An edit anywhere in the repository therefore cools the cache for every root
33
+ * inside it. This is conservative in the safe direction and cheap to be
34
+ * conservative about — `git write-tree` against a throwaway index is the same
35
+ * call `vibe-validate` makes on every commit.
36
+ *
37
+ * ## An opted-in cache that quietly does nothing is worse than no cache
38
+ *
39
+ * Every failure here is loud, and that is deliberate rather than harsh. A
40
+ * selector nobody honours produces a measurement arm that believes it is
41
+ * testing a cache and is testing an ordinary cold run — the "subject that
42
+ * exercises nothing looks like a clean result" failure that has already cost
43
+ * this project one whole A/B. So an uninstalled backend exits with the seam's
44
+ * standard legible error, and a tree that cannot be keyed says so on stderr
45
+ * rather than silently declining.
46
+ */
47
+ import { gitTreeSnapshot, withGitSnapshotCache } from '@vibe-agent-toolkit/utils';
48
+ import { isModuleMissing, reportMissingBackend } from './optional-backend.js';
49
+ /**
50
+ * The env var that selects a projection store for this process.
51
+ *
52
+ * An environment switch rather than a config field, for the same reason
53
+ * `VAT_INVENTORY_CRAWL` and `VAT_RESOURCES_CRAWL` are: it selects which
54
+ * INSTRUMENT runs, not what the project means, and it has to be reachable from
55
+ * the lab, which spawns the binary and controls its environment. A config field
56
+ * would put the A and B arms inside the subject's own tree, where a measurement
57
+ * edits the thing it measures.
58
+ *
59
+ * 🔑 It is read from the environment and therefore **inherited by every phase
60
+ * child**. `runPhase` passes no `env` to `spawnSync`, so `vat validate`'s
61
+ * children see the same selection their parent did.
62
+ *
63
+ * 🔑 **That inheritance now has a within-verb instance.** `vat build`'s two
64
+ * phases — `skills build` and `claude plugin build` — both reach the lane
65
+ * through `withResourcePopulationSource` (see `resource-loader.ts`), and both
66
+ * root their population at the same directory, so phase 2 reads the extent
67
+ * phase 1 wrote. Measured on `packages/vat-development-agents` with
68
+ * `VAT_CRAWL_TIMING`: with a cold store phase 1 files `builtin:filesystem`
69
+ * 39.2 ms and `projection-store:write` 10.1 ms, phase 2 files neither and its
70
+ * `resource-registry:enumerate` reads 3.6 ms against phase 1's 66.6 ms.
71
+ *
72
+ * It did NOT need the closure to emit reasons, which is what an earlier reading
73
+ * of this expected: the packaging lanes consume `resource_realizations` and let
74
+ * `walkLinkGraph` keep running on top of the registry, so the base extent alone
75
+ * answers them — the same shape `buildResourcePopulation` already had.
76
+ *
77
+ * The cross-INVOCATION win is unchanged and independent: `vat validate` and
78
+ * `vat verify` spawn a byte-identical `resources validate` child, so the second
79
+ * hits the store.
80
+ *
81
+ * ⚠️ One packaging enumeration is still on the walk: `vat claude plugin build`'s
82
+ * per-skill post-build validation, which reaches `crawlAndResolveRegistry` in
83
+ * `packaging-validator.ts` without a source — its `withResourcePopulationSource`
84
+ * bracket closes around `createProjectRegistry` and does not span the
85
+ * marketplace loop. `vat skills build` no longer does: it holds one bracket over
86
+ * the whole run, and the registry memo is keyed on the population source, so
87
+ * both of its registries source from the projection.
88
+ */
89
+ export const PROJECTION_STORE_ENV = 'VAT_PROJECTION_STORE';
90
+ /** {@link PROJECTION_STORE_ENV}'s value that selects the SQLite backend. */
91
+ export const PROJECTION_STORE_SQLITE = 'sqlite';
92
+ /**
93
+ * The env var that turns VAT's disk caches off for a run.
94
+ *
95
+ * Not this module's invention — `ParseCache` has read it since the parse cache
96
+ * shipped, and `vat`'s root `--no-cache` exports it from a `preAction` hook so
97
+ * the decision reaches every spawned phase. Named here rather than spelled
98
+ * inline so the projection store is visibly the same tenant as the caches the
99
+ * flag was written for.
100
+ */
101
+ export const CACHE_ENV = 'VAT_CACHE';
102
+ /** {@link CACHE_ENV}'s one off value. Exactly `'0'`, never truthiness — see {@link projectionStoreSelected}. */
103
+ export const CACHE_DISABLED = '0';
104
+ /**
105
+ * The backend as a user is told to install it.
106
+ *
107
+ * Named separately from the RAG backend's entry because the *reason* it ships
108
+ * apart is different, and the install message is the only place a user learns
109
+ * it: RAG carries a platform-native binary, while this one carries a Node
110
+ * version floor.
111
+ */
112
+ const PROJECTION_STORE_BACKEND = {
113
+ feature: 'The projection store',
114
+ packageName: '@vibe-agent-toolkit/projection-sqlite',
115
+ };
116
+ /**
117
+ * Whether this process should read and write a projection store.
118
+ *
119
+ * **Off unless asked for**, which is the opposite of `vat inventory`'s crawl
120
+ * selector and matches `vat resources scan`'s. A cache changes no answer, so
121
+ * the reason to hold it back is not correctness but evidence: the win is a
122
+ * claim about cost, and a default flipped before the cost is measured on real
123
+ * corpora is a claim nobody checked.
124
+ *
125
+ * Read from the environment at each call rather than memoized at module load:
126
+ * `vitest.setup.js` deletes every `VAT_*` variable before any test module
127
+ * loads, so a module-level binding would make the switch unobservable to every
128
+ * test that sets it.
129
+ *
130
+ * ## The two switches are AND-ed, and the second one is a veto
131
+ *
132
+ * {@link PROJECTION_STORE_ENV} says *which* backend; {@link CACHE_ENV} says
133
+ * whether this run caches at all. A store selected while `VAT_CACHE=0` was
134
+ * measured writing a 9.8 MB, 18,079-row store on this repository and hitting it
135
+ * on the next run — a user who asked for no cache silently got one, and
136
+ * `vat cache`'s own help text described three caches while a fourth was being
137
+ * written beside them.
138
+ *
139
+ * 🪤 Compared against `'0'` exactly, never for truthiness, matching
140
+ * `ParseCache`'s `env['VAT_CACHE'] !== '0'`. `VAT_CACHE=1` is the value an
141
+ * operator writes to turn caching ON, and a truthiness test would read it as a
142
+ * reason to decline.
143
+ *
144
+ * @returns `true` when a store is selected
145
+ */
146
+ export function projectionStoreSelected() {
147
+ if (process.env[CACHE_ENV] === CACHE_DISABLED)
148
+ return false;
149
+ return process.env[PROJECTION_STORE_ENV] === PROJECTION_STORE_SQLITE;
150
+ }
151
+ /**
152
+ * Open the projection store this process selected, keyed to one tree.
153
+ *
154
+ * Returns `undefined` when no store is selected, and when the tree cannot be
155
+ * keyed — the two "carry on without a cache" answers. It does **not** return
156
+ * `undefined` for an uninstalled backend: a user who set the selector asked for
157
+ * a store, and answering that request by silently not having one is how an
158
+ * opted-in cache becomes an unmeasured one.
159
+ *
160
+ * @param options - Where the corpus is
161
+ * @param options.root - The absolute corpus root. Used to find the repository;
162
+ * the resulting hash covers that whole repository, not this subtree
163
+ * @returns The cache and its closer, or `undefined` to populate uncached
164
+ */
165
+ export async function openPopulationCache(options) {
166
+ if (!projectionStoreSelected())
167
+ return undefined;
168
+ // Before the import, so a corpus outside a repository costs nothing and says
169
+ // why. `gitTreeSnapshot` returns null for every "git could not answer" case —
170
+ // no `git` on PATH, not a repository, a bare or unreadable one — and an empty
171
+ // snapshot of an initialized repository stays distinguishable from it.
172
+ const snapshot = gitTreeSnapshot({ cwd: options.root });
173
+ if (snapshot === null) {
174
+ process.stderr.write(`${PROJECTION_STORE_ENV} is set, but ${options.root} is not inside a readable git`
175
+ + ' repository, so there is no deterministic key to store a projection under.'
176
+ + ' Populating without a cache.\n');
177
+ return undefined;
178
+ }
179
+ const store = await loadStore();
180
+ return {
181
+ cache: { store, treeHash: snapshot.hash },
182
+ close: () => store.close(),
183
+ };
184
+ }
185
+ /**
186
+ * Load the selected backend, or report it as uninstalled and exit.
187
+ *
188
+ * 🪤 Only `ERR_MODULE_NOT_FOUND` means "not installed". A Node older than
189
+ * 22.13.0 has no `node:sqlite` at all and fails with a *different* code, which
190
+ * must propagate as itself: "install this package" would be the wrong repair
191
+ * for "upgrade Node", and diagnosing a version floor as a missing dependency
192
+ * sends a user round a loop that cannot terminate.
193
+ *
194
+ * @returns The opened store
195
+ */
196
+ async function loadStore() {
197
+ try {
198
+ const backend = await import('@vibe-agent-toolkit/projection-sqlite');
199
+ return backend.openSqliteProjectionStore();
200
+ }
201
+ catch (error) {
202
+ if (!isModuleMissing(error))
203
+ throw error;
204
+ reportMissingBackend(PROJECTION_STORE_BACKEND);
205
+ }
206
+ }
207
+ /**
208
+ * Run one command's work with a projection store open for its whole duration,
209
+ * and closed however it ends.
210
+ *
211
+ * A scope rather than a bare open/close pair, because the store must outlive the
212
+ * call that builds a population source and not merely the call that uses it: the
213
+ * inventory extractor MEMOIZES its population provider and may reach it well
214
+ * after the frame that supplied it has returned. A store closed at the end of
215
+ * that frame would be closed under its own consumer.
216
+ *
217
+ * It is also the `withGitSnapshotCache` bracket for the work inside it, so the
218
+ * key and the extent filed under it come from ONE git snapshot — see the note
219
+ * on the call below.
220
+ *
221
+ * @param options - Where the corpus is
222
+ * @param options.root - The absolute corpus root
223
+ * @param work - Given the cache, or `undefined` when there is none to give
224
+ * @returns Whatever `work` returned
225
+ */
226
+ export async function withPopulationCache(options, work) {
227
+ // ONE git snapshot for the whole scope, and this is the level that gets it:
228
+ // `openPopulationCache` below takes one to derive the store key, and the crawl
229
+ // that runs inside `work` takes another to enumerate the extent — same
230
+ // repository, sequentially, ~195 ms and ~159 ms measured on a large monorepo.
231
+ //
232
+ // The correctness half matters more than the saving. Taken separately, a
233
+ // working-tree edit landing between them makes the two snapshots DIFFERENT
234
+ // answers, and the extent from the second is then filed under the key from the
235
+ // first: a cache entry whose key does not describe its contents, written
236
+ // silently. The bracket closes that race rather than merely deduplicating.
237
+ //
238
+ // Opened here rather than around either consumer because it must enclose BOTH
239
+ // — a bracket opened deeper than one of them dedupes nothing while looking
240
+ // exactly like a bracket that works. Every CLI entry into the projection lane
241
+ // (`inventory`, `resource-loader`'s two) reaches the store through this scope,
242
+ // so this one placement covers all of them.
243
+ return withGitSnapshotCache(async () => {
244
+ const opened = await openPopulationCache(options);
245
+ if (opened === undefined)
246
+ return work(undefined);
247
+ try {
248
+ return await work(opened.cache);
249
+ }
250
+ finally {
251
+ await opened.close();
252
+ }
253
+ });
254
+ }
255
+ //# sourceMappingURL=projection-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection-store.js","sourceRoot":"","sources":["../../src/utils/projection-store.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,47 @@
1
1
  /**
2
2
  * Utilities for loading and crawling resources
3
3
  */
4
- import { ResourceRegistry, type ProjectConfig } from '@vibe-agent-toolkit/resources';
4
+ import { ResourceRegistry, type CrawlSourceKind, type ProjectConfig, type ResourcePopulationSource } from '@vibe-agent-toolkit/resources';
5
5
  import { GitTracker } from '@vibe-agent-toolkit/utils';
6
6
  import type { Logger } from './logger.js';
7
+ /**
8
+ * Which enumerator produced a load's population.
9
+ *
10
+ * `walk` is the incumbent `crawlDirectory` route; `projection` is the
11
+ * projection lane behind {@link RESOURCES_CRAWL_ENV}.
12
+ */
13
+ export type ResourceCrawlLane = 'walk' | 'projection';
7
14
  export interface ResourceLoadResult {
8
15
  scanPath: string;
9
16
  projectRoot: string;
10
17
  config: ProjectConfig | undefined;
11
18
  registry: ResourceRegistry;
12
19
  gitTracker: GitTracker | undefined;
20
+ /**
21
+ * Which lane enumerated, as a fact about the run rather than about the
22
+ * environment that requested it.
23
+ *
24
+ * Reported so that a population can be held against another one: two scans of
25
+ * the same tree that disagree are only interpretable if each says which
26
+ * enumerator produced it. Reading the env var back instead would prove what
27
+ * was ASKED for, never what happened — a distinction that has already voided
28
+ * one whole A/B on this codebase, where both arms silently ran the incumbent.
29
+ */
30
+ lane: ResourceCrawlLane;
31
+ /**
32
+ * Which enumerator the projection lane used, or `null` when the walk ran and
33
+ * there was no extent to source.
34
+ *
35
+ * Reported for the same reason {@link ResourceCrawlLane} is, one level down.
36
+ * `lane` distinguishes the walk from the projection; it does NOT distinguish
37
+ * the projection's two enumerators, and `VAT_EXTENT_SOURCE` is exactly the
38
+ * axis a flip decision turns on. Without this, both arms of that A/B report
39
+ * `projection` and two identical populations mean either "the enumerators
40
+ * agree" or "the switch was ignored" — indistinguishable, and the second is
41
+ * reachable, because `crawlSourceFor` falls back to the walk without saying
42
+ * so when the root is not in a repository.
43
+ */
44
+ extentSource: CrawlSourceKind | null;
13
45
  }
14
46
  /**
15
47
  * Scope resource include patterns to a subdirectory of the crawl base.
@@ -23,6 +55,100 @@ export interface ResourceLoadResult {
23
55
  * `docs/**\/*.md` still matches `docs/a.md`.
24
56
  */
25
57
  export declare function scopeIncludeToSubtree(include: readonly string[], relDir: string): string[];
58
+ /**
59
+ * The env var that selects the crawler behind every resources-crawling verb —
60
+ * `vat resources scan`/`validate`, `vat rag index`, the pipeline oracles, and
61
+ * (via {@link withResourcePopulationSource}) the packaging verbs
62
+ * `vat skills build`/`validate` and `vat claude plugin build`, which is what
63
+ * puts `vat build` on the lane at all.
64
+ *
65
+ * An environment switch rather than a config field, for the same reason
66
+ * `VAT_INVENTORY_CRAWL` is one: it selects which INSTRUMENT runs, not what
67
+ * the project means, and it has to be reachable from the lab, which spawns the
68
+ * binary and controls its environment. A config field would put the A and B arms
69
+ * inside the subject's own tree, where a measurement edits the thing it measures.
70
+ */
71
+ export declare const RESOURCES_CRAWL_ENV = "VAT_RESOURCES_CRAWL";
72
+ /** {@link RESOURCES_CRAWL_ENV}'s value that selects the projection lane. */
73
+ export declare const RESOURCES_CRAWL_PROJECTION = "projection";
74
+ /**
75
+ * {@link RESOURCES_CRAWL_ENV}'s value that opts BACK to the incumbent walk.
76
+ *
77
+ * The projection lane is the default now, so this is the escape hatch rather
78
+ * than the selector. Any other value — including the historical `projection` —
79
+ * leaves the projection lane selected, so existing scripts and lab arms that
80
+ * name it explicitly keep working and keep MEANING the same thing.
81
+ */
82
+ export declare const RESOURCES_CRAWL_WALK = "walk";
83
+ /**
84
+ * Whether this process should source the resources population from a projection.
85
+ *
86
+ * **Defaults to the projection lane.** Both lanes now enumerate
87
+ * `tracked ∪ (untracked ∧ ¬ignored)` — `ResourceRegistry.crawl` passes
88
+ * `includeUntracked: true` per `docs/architecture/resource-scanning-and-caching.md`
89
+ * §2.1 — so the population question they answer is the same one.
90
+ *
91
+ * ⚠️⚠️ **ONE DISAGREEMENT SURVIVES, AND IT DROPS FINDINGS: SYMLINKS.** The
92
+ * `filesystem` extent crawls with `followSymlinks: false` and records no link's
93
+ * own path, and `GitCrawlSource` skips mode `120000` deliberately to match it —
94
+ * so BOTH projection extents omit a committed symlink that the incumbent walk
95
+ * includes. For an out-of-tree target those bytes have no other path into the
96
+ * population, which means **a broken symlink the walk reports as
97
+ * `LINK_BROKEN_FILE` is not reported on this lane.** That is a real loss, it is
98
+ * known, and it is the cost this default was accepted at; closing it is its own
99
+ * change (teaching an extent to admit `120000` entries as their own paths).
100
+ * {@link RESOURCES_CRAWL_WALK} is the one-value escape hatch meanwhile.
101
+ *
102
+ * Read from the environment at each call rather than memoized at module load:
103
+ * `vitest.setup.js` deletes every `VAT_*` variable before any test module loads,
104
+ * so a module-level binding would make the switch unobservable to every test
105
+ * that sets it.
106
+ *
107
+ * @returns `true` when the projection lane is selected
108
+ */
109
+ export declare function resourcesProjectionCrawlSelected(): boolean;
110
+ /**
111
+ * Run one command's work with the projection-backed population source it
112
+ * selected, and the store that answers it open for the whole call.
113
+ *
114
+ * The lane-selection seam for every command that builds its OWN registry rather
115
+ * than going through {@link loadResourcesWithConfig} — `vat skills build` and
116
+ * `vat claude plugin build` (via `createProjectRegistry`) and
117
+ * `vat skills validate` (via its shared-context registry). Those three are what
118
+ * put `vat build` on the projection lane at all: before this, that verb reached
119
+ * a projection store on NO phase.
120
+ *
121
+ * Same selector, same store, same ignore oracle as the resource loader —
122
+ * deliberately, and not merely for tidiness. A second way to decide the lane is
123
+ * a second thing to keep in step, and a packaging lane that answered the
124
+ * selector differently from the validation lane would make a whole-run A/B
125
+ * uninterpretable: half the phases on one population, half on the other, and
126
+ * nothing in the output saying so.
127
+ *
128
+ * ⚠️ The tracker is **not optional dressing**. With no `GitTracker` every
129
+ * realization row reads `gitignored: false`, so the population would admit the
130
+ * ignored half of a git tree — generated markdown, caches, vendored corpora —
131
+ * and the packaging run would start bundling and validating files the project
132
+ * told git to forget. One is built here when the caller has none, rooted at the
133
+ * same root the population is enumerated from.
134
+ *
135
+ * @param options - Where the corpus is, and what to reuse
136
+ * @param options.root - The absolute corpus root, which is also the basis every
137
+ * enumerated path is returned against
138
+ * @param options.gitTracker - An already-initialized tracker to reuse. Omit to
139
+ * have one built, which costs a `git ls-files` spawn — and only when the lane
140
+ * is actually selected
141
+ * @param options.observeExtentSource - Called with the enumerator that ran, once
142
+ * per enumerated root. 🪤 NOT a cache-hit marker: on a hit no enumerator runs
143
+ * and this still reports the one this process selected
144
+ * @param work - Given the source, or `undefined` when the walk stays selected
145
+ * @returns Whatever `work` returned
146
+ */
147
+ export declare function withResourcePopulationSource<T>(options: {
148
+ root: string;
149
+ gitTracker?: GitTracker | undefined;
150
+ observeExtentSource?: ((kind: CrawlSourceKind) => void) | undefined;
151
+ }, work: (populationSource: ResourcePopulationSource | undefined) => Promise<T>): Promise<T>;
26
152
  /**
27
153
  * Load resources from a path with config support
28
154
  *
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.d.ts","sourceRoot":"","sources":["../../src/utils/resource-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAEL,gBAAgB,EAEhB,KAAK,aAAa,EAEnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAA4B,MAAM,2BAA2B,CAAC;AAGjF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1F;AAkED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAuD7B"}
1
+ {"version":3,"file":"resource-loader.d.ts","sourceRoot":"","sources":["../../src/utils/resource-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAIL,gBAAgB,EAEhB,KAAK,eAAe,EAEpB,KAAK,aAAa,EAClB,KAAK,wBAAwB,EAE9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAA6C,MAAM,2BAA2B,CAAC;AAGlG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,YAAY,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC;;;;;;;;;OASG;IACH,IAAI,EAAE,iBAAiB,CAAC;IACxB;;;;;;;;;;;;OAYG;IACH,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1F;AA+CD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD,4EAA4E;AAC5E,eAAO,MAAM,0BAA0B,eAAe,CAAC;AAEvD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gCAAgC,IAAI,OAAO,CAE1D;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,EAClD,OAAO,EAAE;IACP,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,mBAAmB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACrE,EACD,IAAI,EAAE,CAAC,gBAAgB,EAAE,wBAAwB,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3E,OAAO,CAAC,CAAC,CAAC,CAoBZ;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CA8G7B"}