@wrenai/genbi 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -0
  3. package/bin/genbi.mjs +31 -0
  4. package/dist/assets/echarts-LTFC-ysd.js +40 -0
  5. package/dist/assets/index-Bo--QMUN.js +441 -0
  6. package/dist/assets/index-Xs4q7pNo.css +1 -0
  7. package/dist/index.html +14 -0
  8. package/dist/wrenai_logo.png +0 -0
  9. package/dist/wrenai_logo_white.png +0 -0
  10. package/dist-server/harness/auth/detect.d.ts +18 -0
  11. package/dist-server/harness/auth/detect.js +37 -0
  12. package/dist-server/harness/auth/index.d.ts +4 -0
  13. package/dist-server/harness/auth/index.js +2 -0
  14. package/dist-server/harness/auth/probe.d.ts +18 -0
  15. package/dist-server/harness/auth/probe.js +52 -0
  16. package/dist-server/harness/auth/types.d.ts +42 -0
  17. package/dist-server/harness/auth/types.js +9 -0
  18. package/dist-server/harness/bundle/loader.d.ts +32 -0
  19. package/dist-server/harness/bundle/loader.js +43 -0
  20. package/dist-server/harness/bundle/schema.d.ts +199 -0
  21. package/dist-server/harness/bundle/schema.js +127 -0
  22. package/dist-server/harness/bundle/version.d.ts +10 -0
  23. package/dist-server/harness/bundle/version.js +43 -0
  24. package/dist-server/harness/capability/gate.d.ts +6 -0
  25. package/dist-server/harness/capability/gate.js +29 -0
  26. package/dist-server/harness/capability/registry.d.ts +6 -0
  27. package/dist-server/harness/capability/registry.js +17 -0
  28. package/dist-server/harness/cli-args.d.ts +123 -0
  29. package/dist-server/harness/cli-args.js +247 -0
  30. package/dist-server/harness/cli.d.ts +2 -0
  31. package/dist-server/harness/cli.js +151 -0
  32. package/dist-server/harness/compile/cache.d.ts +23 -0
  33. package/dist-server/harness/compile/cache.js +109 -0
  34. package/dist-server/harness/compile/compose-profile.d.ts +34 -0
  35. package/dist-server/harness/compile/compose-profile.js +95 -0
  36. package/dist-server/harness/compile/errors.d.ts +22 -0
  37. package/dist-server/harness/compile/errors.js +41 -0
  38. package/dist-server/harness/compile/fingerprint.d.ts +22 -0
  39. package/dist-server/harness/compile/fingerprint.js +84 -0
  40. package/dist-server/harness/compile/index.d.ts +8 -0
  41. package/dist-server/harness/compile/index.js +7 -0
  42. package/dist-server/harness/compile/pipeline.d.ts +66 -0
  43. package/dist-server/harness/compile/pipeline.js +176 -0
  44. package/dist-server/harness/compile/resolve-binary.d.ts +55 -0
  45. package/dist-server/harness/compile/resolve-binary.js +133 -0
  46. package/dist-server/harness/compile/types.d.ts +107 -0
  47. package/dist-server/harness/compile/types.js +1 -0
  48. package/dist-server/harness/compile/warble-identity.d.ts +12 -0
  49. package/dist-server/harness/compile/warble-identity.js +33 -0
  50. package/dist-server/harness/compliance/gate.d.ts +35 -0
  51. package/dist-server/harness/compliance/gate.js +48 -0
  52. package/dist-server/harness/compliance/index.d.ts +2 -0
  53. package/dist-server/harness/compliance/index.js +1 -0
  54. package/dist-server/harness/compliance/types.d.ts +16 -0
  55. package/dist-server/harness/compliance/types.js +1 -0
  56. package/dist-server/harness/events/emitter.d.ts +34 -0
  57. package/dist-server/harness/events/emitter.js +25 -0
  58. package/dist-server/harness/events/index.d.ts +4 -0
  59. package/dist-server/harness/events/index.js +2 -0
  60. package/dist-server/harness/events/sse.d.ts +20 -0
  61. package/dist-server/harness/events/sse.js +48 -0
  62. package/dist-server/harness/events/types.d.ts +131 -0
  63. package/dist-server/harness/events/types.js +1 -0
  64. package/dist-server/harness/exec/errors.d.ts +16 -0
  65. package/dist-server/harness/exec/errors.js +29 -0
  66. package/dist-server/harness/exec/index.d.ts +5 -0
  67. package/dist-server/harness/exec/index.js +2 -0
  68. package/dist-server/harness/exec/local.d.ts +32 -0
  69. package/dist-server/harness/exec/local.js +134 -0
  70. package/dist-server/harness/exec/policy.d.ts +12 -0
  71. package/dist-server/harness/exec/policy.js +1 -0
  72. package/dist-server/harness/exec/types.d.ts +63 -0
  73. package/dist-server/harness/exec/types.js +1 -0
  74. package/dist-server/harness/guardrails/index.d.ts +2 -0
  75. package/dist-server/harness/guardrails/index.js +1 -0
  76. package/dist-server/harness/guardrails/policy.d.ts +45 -0
  77. package/dist-server/harness/guardrails/policy.js +57 -0
  78. package/dist-server/harness/index.d.ts +37 -0
  79. package/dist-server/harness/index.js +19 -0
  80. package/dist-server/harness/loop/errors.d.ts +53 -0
  81. package/dist-server/harness/loop/errors.js +72 -0
  82. package/dist-server/harness/loop/executor.d.ts +123 -0
  83. package/dist-server/harness/loop/executor.js +380 -0
  84. package/dist-server/harness/loop/guard.d.ts +16 -0
  85. package/dist-server/harness/loop/guard.js +1 -0
  86. package/dist-server/harness/loop/index.d.ts +5 -0
  87. package/dist-server/harness/loop/index.js +3 -0
  88. package/dist-server/harness/native-producer/index.d.ts +109 -0
  89. package/dist-server/harness/native-producer/index.js +302 -0
  90. package/dist-server/harness/npm-package-resolve.d.ts +28 -0
  91. package/dist-server/harness/npm-package-resolve.js +47 -0
  92. package/dist-server/harness/providers/adapters/anthropic.d.ts +7 -0
  93. package/dist-server/harness/providers/adapters/anthropic.js +6 -0
  94. package/dist-server/harness/providers/adapters/mock.d.ts +4 -0
  95. package/dist-server/harness/providers/adapters/mock.js +5 -0
  96. package/dist-server/harness/providers/adapters/openai-compatible.d.ts +10 -0
  97. package/dist-server/harness/providers/adapters/openai-compatible.js +10 -0
  98. package/dist-server/harness/providers/binding.d.ts +23 -0
  99. package/dist-server/harness/providers/binding.js +13 -0
  100. package/dist-server/harness/providers/errors.d.ts +6 -0
  101. package/dist-server/harness/providers/errors.js +12 -0
  102. package/dist-server/harness/providers/index.d.ts +18 -0
  103. package/dist-server/harness/providers/index.js +22 -0
  104. package/dist-server/harness/providers/registry.d.ts +16 -0
  105. package/dist-server/harness/providers/registry.js +24 -0
  106. package/dist-server/harness/render/envelope.d.ts +145 -0
  107. package/dist-server/harness/render/envelope.js +428 -0
  108. package/dist-server/harness/render/errors.d.ts +33 -0
  109. package/dist-server/harness/render/errors.js +46 -0
  110. package/dist-server/harness/render/index.d.ts +5 -0
  111. package/dist-server/harness/render/index.js +3 -0
  112. package/dist-server/harness/render/validate.d.ts +13 -0
  113. package/dist-server/harness/render/validate.js +88 -0
  114. package/dist-server/harness/route/adapter-spec.d.ts +40 -0
  115. package/dist-server/harness/route/adapter-spec.js +61 -0
  116. package/dist-server/harness/route/agent-sdk-cli.d.ts +30 -0
  117. package/dist-server/harness/route/agent-sdk-cli.js +86 -0
  118. package/dist-server/harness/route/agent-sdk-manifest.d.ts +31 -0
  119. package/dist-server/harness/route/agent-sdk-manifest.js +56 -0
  120. package/dist-server/harness/route/artifact-content.d.ts +53 -0
  121. package/dist-server/harness/route/artifact-content.js +83 -0
  122. package/dist-server/harness/route/chat-event-mapper.d.ts +95 -0
  123. package/dist-server/harness/route/chat-event-mapper.js +164 -0
  124. package/dist-server/harness/route/codex-ask-events.d.ts +25 -0
  125. package/dist-server/harness/route/codex-ask-events.js +395 -0
  126. package/dist-server/harness/route/codex-ask.d.ts +15 -0
  127. package/dist-server/harness/route/codex-ask.js +242 -0
  128. package/dist-server/harness/route/codex-local-cli.d.ts +20 -0
  129. package/dist-server/harness/route/codex-local-cli.js +78 -0
  130. package/dist-server/harness/route/codex-local-manifest.d.ts +22 -0
  131. package/dist-server/harness/route/codex-local-manifest.js +180 -0
  132. package/dist-server/harness/route/describe.d.ts +54 -0
  133. package/dist-server/harness/route/describe.js +84 -0
  134. package/dist-server/harness/route/dispatched.d.ts +138 -0
  135. package/dist-server/harness/route/dispatched.js +339 -0
  136. package/dist-server/harness/route/in-process.d.ts +43 -0
  137. package/dist-server/harness/route/in-process.js +106 -0
  138. package/dist-server/harness/route/index.d.ts +19 -0
  139. package/dist-server/harness/route/index.js +12 -0
  140. package/dist-server/harness/route/profile-source.d.ts +37 -0
  141. package/dist-server/harness/route/profile-source.js +76 -0
  142. package/dist-server/harness/route/route.d.ts +33 -0
  143. package/dist-server/harness/route/route.js +114 -0
  144. package/dist-server/harness/route/tier-binding.d.ts +36 -0
  145. package/dist-server/harness/route/tier-binding.js +63 -0
  146. package/dist-server/harness/route/types.d.ts +286 -0
  147. package/dist-server/harness/route/types.js +1 -0
  148. package/dist-server/harness/session/errors.d.ts +4 -0
  149. package/dist-server/harness/session/errors.js +7 -0
  150. package/dist-server/harness/session/gate.d.ts +11 -0
  151. package/dist-server/harness/session/gate.js +13 -0
  152. package/dist-server/harness/session/index.d.ts +5 -0
  153. package/dist-server/harness/session/index.js +3 -0
  154. package/dist-server/harness/session/run.d.ts +60 -0
  155. package/dist-server/harness/session/run.js +333 -0
  156. package/dist-server/harness/session/types.d.ts +29 -0
  157. package/dist-server/harness/session/types.js +1 -0
  158. package/dist-server/harness/setup/codex-events.d.ts +12 -0
  159. package/dist-server/harness/setup/codex-events.js +108 -0
  160. package/dist-server/harness/setup/runner.d.ts +497 -0
  161. package/dist-server/harness/setup/runner.js +1314 -0
  162. package/dist-server/harness/tools/errors.d.ts +107 -0
  163. package/dist-server/harness/tools/errors.js +141 -0
  164. package/dist-server/harness/tools/index.d.ts +13 -0
  165. package/dist-server/harness/tools/index.js +8 -0
  166. package/dist-server/harness/tools/mcp.d.ts +26 -0
  167. package/dist-server/harness/tools/mcp.js +15 -0
  168. package/dist-server/harness/tools/native.d.ts +179 -0
  169. package/dist-server/harness/tools/native.js +322 -0
  170. package/dist-server/harness/tools/parse.d.ts +14 -0
  171. package/dist-server/harness/tools/parse.js +18 -0
  172. package/dist-server/harness/tools/resolve-wren-binary.d.ts +12 -0
  173. package/dist-server/harness/tools/resolve-wren-binary.js +21 -0
  174. package/dist-server/harness/tools/resolve.d.ts +51 -0
  175. package/dist-server/harness/tools/resolve.js +79 -0
  176. package/dist-server/harness/tools/setup-native.d.ts +84 -0
  177. package/dist-server/harness/tools/setup-native.js +353 -0
  178. package/dist-server/harness/tools/wiring.d.ts +10 -0
  179. package/dist-server/harness/tools/wiring.js +16 -0
  180. package/dist-server/providers/setup.provider.yaml +31 -0
  181. package/dist-server/providers/wren.provider.yaml +33 -0
  182. package/dist-server/server/adopt.d.ts +87 -0
  183. package/dist-server/server/adopt.js +263 -0
  184. package/dist-server/server/app.d.ts +6 -0
  185. package/dist-server/server/app.js +2521 -0
  186. package/dist-server/server/auth-choice.d.ts +16 -0
  187. package/dist-server/server/auth-choice.js +36 -0
  188. package/dist-server/server/bin.d.ts +2 -0
  189. package/dist-server/server/bin.js +601 -0
  190. package/dist-server/server/bootstrap-project-binding.d.ts +31 -0
  191. package/dist-server/server/bootstrap-project-binding.js +71 -0
  192. package/dist-server/server/clarify.d.ts +10 -0
  193. package/dist-server/server/clarify.js +17 -0
  194. package/dist-server/server/codex-setup-mcp.d.ts +2 -0
  195. package/dist-server/server/codex-setup-mcp.js +147 -0
  196. package/dist-server/server/compose.d.ts +89 -0
  197. package/dist-server/server/compose.js +271 -0
  198. package/dist-server/server/conn-config.d.ts +30 -0
  199. package/dist-server/server/conn-config.js +253 -0
  200. package/dist-server/server/context-files.d.ts +12 -0
  201. package/dist-server/server/context-files.js +117 -0
  202. package/dist-server/server/context-map.d.ts +30 -0
  203. package/dist-server/server/context-map.js +95 -0
  204. package/dist-server/server/context-source.d.ts +68 -0
  205. package/dist-server/server/context-source.js +85 -0
  206. package/dist-server/server/db.d.ts +862 -0
  207. package/dist-server/server/db.js +1839 -0
  208. package/dist-server/server/enrichment-runner.d.ts +184 -0
  209. package/dist-server/server/enrichment-runner.js +213 -0
  210. package/dist-server/server/enrichment-verify.d.ts +73 -0
  211. package/dist-server/server/enrichment-verify.js +290 -0
  212. package/dist-server/server/enrichment.d.ts +232 -0
  213. package/dist-server/server/enrichment.js +199 -0
  214. package/dist-server/server/env-detect.d.ts +8 -0
  215. package/dist-server/server/env-detect.js +17 -0
  216. package/dist-server/server/env-field-hints.d.ts +46 -0
  217. package/dist-server/server/env-field-hints.js +48 -0
  218. package/dist-server/server/fold.d.ts +133 -0
  219. package/dist-server/server/fold.js +407 -0
  220. package/dist-server/server/harness-profile-sources.d.ts +3 -0
  221. package/dist-server/server/harness-profile-sources.js +24 -0
  222. package/dist-server/server/harness.d.ts +19 -0
  223. package/dist-server/server/harness.js +439 -0
  224. package/dist-server/server/impact.d.ts +18 -0
  225. package/dist-server/server/impact.js +85 -0
  226. package/dist-server/server/interactive-terminal.d.ts +175 -0
  227. package/dist-server/server/interactive-terminal.js +336 -0
  228. package/dist-server/server/native-artifacts.d.ts +1004 -0
  229. package/dist-server/server/native-artifacts.js +564 -0
  230. package/dist-server/server/native-dispatch-registry.d.ts +42 -0
  231. package/dist-server/server/native-dispatch-registry.js +45 -0
  232. package/dist-server/server/native-producer-fence.d.ts +14 -0
  233. package/dist-server/server/native-producer-fence.js +48 -0
  234. package/dist-server/server/native-session-resume.d.ts +6 -0
  235. package/dist-server/server/native-session-resume.js +103 -0
  236. package/dist-server/server/native-session-workspace.d.ts +40 -0
  237. package/dist-server/server/native-session-workspace.js +175 -0
  238. package/dist-server/server/native-sessions.d.ts +374 -0
  239. package/dist-server/server/native-sessions.js +1517 -0
  240. package/dist-server/server/native-wren-runtime.d.ts +20 -0
  241. package/dist-server/server/native-wren-runtime.js +259 -0
  242. package/dist-server/server/node-pty-host.d.ts +31 -0
  243. package/dist-server/server/node-pty-host.js +100 -0
  244. package/dist-server/server/route-intent.d.ts +40 -0
  245. package/dist-server/server/route-intent.js +23 -0
  246. package/dist-server/server/runtime-binding.d.ts +52 -0
  247. package/dist-server/server/runtime-binding.js +258 -0
  248. package/dist-server/server/source-catalog.d.ts +84 -0
  249. package/dist-server/server/source-catalog.js +221 -0
  250. package/dist-server/server/source-driver.d.ts +35 -0
  251. package/dist-server/server/source-driver.js +124 -0
  252. package/dist-server/server/spa.d.ts +2 -0
  253. package/dist-server/server/spa.js +51 -0
  254. package/dist-server/server/subscription-model-catalog.d.ts +27 -0
  255. package/dist-server/server/subscription-model-catalog.js +203 -0
  256. package/dist-server/server/turn.d.ts +249 -0
  257. package/dist-server/server/turn.js +1074 -0
  258. package/dist-server/server/wire-types.d.ts +799 -0
  259. package/dist-server/server/wire-types.js +1 -0
  260. package/dist-server/server/wren-home.d.ts +19 -0
  261. package/dist-server/server/wren-home.js +33 -0
  262. package/dist-server/server/wren-profiles.d.ts +43 -0
  263. package/dist-server/server/wren-profiles.js +123 -0
  264. package/package.json +93 -0
  265. package/profiles/genbi-default/context/binding.yml +9 -0
  266. package/profiles/genbi-default/ir.golden.json +506 -0
  267. package/profiles/genbi-default/profile.yml +16 -0
  268. package/profiles/genbi-enrich-context/components/apply_enrichment/component.yml +42 -0
  269. package/profiles/genbi-enrich-context/components/draft_enrichment/component.yml +30 -0
  270. package/profiles/genbi-enrich-context/components/draft_enrichment/steps/draft.md +34 -0
  271. package/profiles/genbi-enrich-context/components/inspect_context/component.yml +32 -0
  272. package/profiles/genbi-enrich-context/components/inspect_context/steps/inspect.md +13 -0
  273. package/profiles/genbi-enrich-context/context/binding.yml +4 -0
  274. package/profiles/genbi-enrich-context/ir.golden.json +302 -0
  275. package/profiles/genbi-enrich-context/profile.yml +15 -0
  276. package/profiles/genbi-monitor/context/binding.yml +7 -0
  277. package/profiles/genbi-monitor/ir.golden.json +188 -0
  278. package/profiles/genbi-monitor/profile.yml +27 -0
  279. package/profiles/genbi-setup/components/build_context/component.yml +44 -0
  280. package/profiles/genbi-setup/components/build_context/steps/build.md +14 -0
  281. package/profiles/genbi-setup/components/connect_source/component.yml +51 -0
  282. package/profiles/genbi-setup/components/connect_source/steps/connect.md +23 -0
  283. package/profiles/genbi-setup/context/binding.yml +8 -0
  284. package/profiles/genbi-setup/ir.golden.json +140 -0
  285. package/profiles/genbi-setup/profile.yml +18 -0
  286. package/profiles/genbi-setup/raw/schema.json +5 -0
@@ -0,0 +1,23 @@
1
+ import type { CompileCache } from "./types.js";
2
+ /**
3
+ * The default cache root, rooted under the *current user's* home rather than a world-shared
4
+ * fixed path like `os.tmpdir()` — on a multi-user host, a predictable shared tmpdir path lets
5
+ * another local account pre-create the dir and plant a slot for a computable cache key.
6
+ * Respects `XDG_CACHE_HOME` when set, matching the XDG base-dir convention.
7
+ */
8
+ export declare function resolveDefaultCacheDir(): string;
9
+ /**
10
+ * The v1 {@link CompileCache} backend: one subdirectory per cache key under `cacheDir`, each
11
+ * holding a copy of `ir.json` and (in-process only) `bundle/bundle.json`. `get` treats a slot whose
12
+ * `ir.json` has since been deleted as a miss rather than throwing, so an external cleanup of
13
+ * `cacheDir` degrades to "just recompile" instead of a hard failure.
14
+ *
15
+ * No TTL/eviction and no crash-consistency guarantee on `set` (a process killed mid-copy can leave
16
+ * a partial slot that a later `get` may treat as a hit) — both are deferred; simple/documented per
17
+ * the task's scope guidance rather than a production-grade cache.
18
+ */
19
+ export declare function createFileSystemCompileCache(options?: {
20
+ readonly cacheDir?: string;
21
+ }): CompileCache;
22
+ /** A non-persistent {@link CompileCache} for tests/short-lived processes — no filesystem I/O. */
23
+ export declare function createInMemoryCompileCache(): CompileCache;
@@ -0,0 +1,109 @@
1
+ import { createHash } from "node:crypto";
2
+ import { chmodSync, existsSync, mkdirSync } from "node:fs";
3
+ import { cp, mkdir, stat } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ /**
7
+ * Deterministic on-disk slot name for a cache key — order-independent, one directory per (profile,
8
+ * context, mode, provider-fragment-hash, warble-identity, hub-dir). An absent `hubDir` (no
9
+ * `--hub-dir` passed, so warble's compiled-in default applied) hashes as the empty string, which is
10
+ * a distinct value from any real root rather than an alias for one.
11
+ */
12
+ function keyDigest(key) {
13
+ return createHash("sha256")
14
+ .update(`${key.profileHash}:${key.contextFingerprint}:${key.mode}:${key.providerFragmentHash}:${key.warbleIdentity}:${key.hubDir ?? ""}`)
15
+ .digest("hex");
16
+ }
17
+ /**
18
+ * The default cache root, rooted under the *current user's* home rather than a world-shared
19
+ * fixed path like `os.tmpdir()` — on a multi-user host, a predictable shared tmpdir path lets
20
+ * another local account pre-create the dir and plant a slot for a computable cache key.
21
+ * Respects `XDG_CACHE_HOME` when set, matching the XDG base-dir convention.
22
+ */
23
+ export function resolveDefaultCacheDir() {
24
+ const xdgCacheHome = process.env.XDG_CACHE_HOME;
25
+ const base = xdgCacheHome !== undefined && xdgCacheHome.trim().length > 0 ? xdgCacheHome : path.join(os.homedir(), ".cache");
26
+ return path.join(base, "wren-harness", "compile");
27
+ }
28
+ /**
29
+ * Creates the default cache dir (if missing) restricted to the owner (`0700`) so another local
30
+ * account can't read or even traverse into it. `mkdirSync`'s `mode` is subject to the process
31
+ * umask, so `chmodSync` afterwards guarantees `0700` regardless of umask or a looser pre-existing
32
+ * mode. Only applied to the *default* dir — an explicit `cacheDir` override is left exactly as
33
+ * the caller passed it (see `createFileSystemCompileCache`).
34
+ */
35
+ function createSecureDefaultCacheDir() {
36
+ const dir = resolveDefaultCacheDir();
37
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
38
+ if (process.platform !== "win32") {
39
+ chmodSync(dir, 0o700);
40
+ }
41
+ return dir;
42
+ }
43
+ /**
44
+ * Defense in depth against a planted slot (see `resolveDefaultCacheDir`'s doc comment above): if a slot directory exists but isn't
45
+ * owned by the current process's uid, treat it as untrustworthy and miss rather than trusting its
46
+ * contents. A slot that doesn't exist at all (the common miss case) is NOT a security decision —
47
+ * `stat` failing for any reason falls through to `true` so the normal `existsSync(irPath)` miss
48
+ * path below still runs. Windows has no POSIX uid model, so this is skipped there.
49
+ */
50
+ async function isOwnedByCurrentUser(slot) {
51
+ if (process.platform === "win32")
52
+ return true;
53
+ const uid = process.getuid?.();
54
+ if (uid === undefined)
55
+ return true;
56
+ try {
57
+ const stats = await stat(slot);
58
+ return stats.uid === uid;
59
+ }
60
+ catch {
61
+ return true;
62
+ }
63
+ }
64
+ /**
65
+ * The v1 {@link CompileCache} backend: one subdirectory per cache key under `cacheDir`, each
66
+ * holding a copy of `ir.json` and (in-process only) `bundle/bundle.json`. `get` treats a slot whose
67
+ * `ir.json` has since been deleted as a miss rather than throwing, so an external cleanup of
68
+ * `cacheDir` degrades to "just recompile" instead of a hard failure.
69
+ *
70
+ * No TTL/eviction and no crash-consistency guarantee on `set` (a process killed mid-copy can leave
71
+ * a partial slot that a later `get` may treat as a hit) — both are deferred; simple/documented per
72
+ * the task's scope guidance rather than a production-grade cache.
73
+ */
74
+ export function createFileSystemCompileCache(options) {
75
+ const cacheDir = options?.cacheDir ?? createSecureDefaultCacheDir();
76
+ return {
77
+ async get(key) {
78
+ const slot = path.join(cacheDir, keyDigest(key));
79
+ if (!(await isOwnedByCurrentUser(slot)))
80
+ return undefined;
81
+ const irPath = path.join(slot, "ir.json");
82
+ if (!existsSync(irPath))
83
+ return undefined;
84
+ const bundlePath = path.join(slot, "bundle", "bundle.json");
85
+ return { irPath, ...(existsSync(bundlePath) ? { bundlePath } : {}) };
86
+ },
87
+ async set(key, entry) {
88
+ const slot = path.join(cacheDir, keyDigest(key));
89
+ await mkdir(slot, { recursive: true });
90
+ await cp(entry.irPath, path.join(slot, "ir.json"));
91
+ if (entry.bundlePath !== undefined) {
92
+ await mkdir(path.join(slot, "bundle"), { recursive: true });
93
+ await cp(entry.bundlePath, path.join(slot, "bundle", "bundle.json"));
94
+ }
95
+ },
96
+ };
97
+ }
98
+ /** A non-persistent {@link CompileCache} for tests/short-lived processes — no filesystem I/O. */
99
+ export function createInMemoryCompileCache() {
100
+ const store = new Map();
101
+ return {
102
+ async get(key) {
103
+ return store.get(keyDigest(key));
104
+ },
105
+ async set(key, entry) {
106
+ store.set(keyDigest(key), entry);
107
+ },
108
+ };
109
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copies `profileSource` into `destDir`, then rewrites its context binding's `project:` field to
3
+ * point at `userProject` (absolute path) instead of the profile's own fixture binding. Returns the
4
+ * composed profile's directory (safe to pass straight to `warble compile`).
5
+ *
6
+ * The binding file to rewrite is *not* hardcoded to `context/binding.yml` — it's read from the
7
+ * copied `profile.yml`'s own `context: project: <path>` pointer (the documented Warble mechanism:
8
+ * "profile mounts context via `context: project: <path-to-binding.yml>`"), so this works for any
9
+ * profile following that shape, not just `genbi-default`. The resolved binding path is confined to
10
+ * the composed directory: a `../`-laden pointer that escapes it is a loud {@link PathTraversalError}
11
+ * (reusing the exec module's shared traversal error rather than reading/overwriting an arbitrary
12
+ * host file).
13
+ *
14
+ * Both `profile.yml` and the binding file are small, flat YAML where only a single scalar matters
15
+ * here — regex extraction/rewrite is used deliberately instead of pulling in a full YAML parser
16
+ * dependency for that. Both the pointer lookup and the `project:` rewrite assert *exactly one*
17
+ * match and loud-fail on zero or multiple (a duplicate top-level `project:` would otherwise leave a
18
+ * stale line that last-key-wins YAML parsing could silently bind to the wrong project). If a Warble
19
+ * profile ever grows a more elaborate `context:` block (e.g. multiple context sources), this needs
20
+ * revisiting.
21
+ */
22
+ export declare function composeUserProfile(options: {
23
+ readonly profileSource: string;
24
+ readonly userProject: string;
25
+ readonly destDir: string;
26
+ }): Promise<string>;
27
+ /** Extracts the single `context: project: <path>` pointer from a profile.yml's text. */
28
+ export declare function extractContextBindingPath(profileYamlText: string, sourcePath: string): string;
29
+ /**
30
+ * Replaces the single top-level `project:` line in a context-binding YAML's text, preserving
31
+ * surrounding comments. Asserts exactly one top-level `project:` — a second one would survive the
32
+ * rewrite as a stale line and could win under last-key-wins YAML parsing (silent misbind).
33
+ */
34
+ export declare function rewriteContextBindingProject(bindingText: string, newProjectPath: string, sourcePath: string): string;
@@ -0,0 +1,95 @@
1
+ import { cp, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { PathTraversalError } from "../exec/index.js";
4
+ import { InvalidProfileShapeError } from "./errors.js";
5
+ /**
6
+ * Copies `profileSource` into `destDir`, then rewrites its context binding's `project:` field to
7
+ * point at `userProject` (absolute path) instead of the profile's own fixture binding. Returns the
8
+ * composed profile's directory (safe to pass straight to `warble compile`).
9
+ *
10
+ * The binding file to rewrite is *not* hardcoded to `context/binding.yml` — it's read from the
11
+ * copied `profile.yml`'s own `context: project: <path>` pointer (the documented Warble mechanism:
12
+ * "profile mounts context via `context: project: <path-to-binding.yml>`"), so this works for any
13
+ * profile following that shape, not just `genbi-default`. The resolved binding path is confined to
14
+ * the composed directory: a `../`-laden pointer that escapes it is a loud {@link PathTraversalError}
15
+ * (reusing the exec module's shared traversal error rather than reading/overwriting an arbitrary
16
+ * host file).
17
+ *
18
+ * Both `profile.yml` and the binding file are small, flat YAML where only a single scalar matters
19
+ * here — regex extraction/rewrite is used deliberately instead of pulling in a full YAML parser
20
+ * dependency for that. Both the pointer lookup and the `project:` rewrite assert *exactly one*
21
+ * match and loud-fail on zero or multiple (a duplicate top-level `project:` would otherwise leave a
22
+ * stale line that last-key-wins YAML parsing could silently bind to the wrong project). If a Warble
23
+ * profile ever grows a more elaborate `context:` block (e.g. multiple context sources), this needs
24
+ * revisiting.
25
+ */
26
+ export async function composeUserProfile(options) {
27
+ const profileSourceAbs = path.resolve(options.profileSource);
28
+ const userProjectAbs = path.resolve(options.userProject);
29
+ const composedDir = path.join(options.destDir, "profile");
30
+ await cp(profileSourceAbs, composedDir, { recursive: true });
31
+ const profileYamlPath = path.join(composedDir, "profile.yml");
32
+ const profileYamlText = await readFile(profileYamlPath, "utf-8");
33
+ const bindingRelPath = extractContextBindingPath(profileYamlText, profileYamlPath);
34
+ const bindingPath = resolveWithinComposedDir(composedDir, bindingRelPath);
35
+ const bindingText = await readFile(bindingPath, "utf-8");
36
+ const rewritten = rewriteContextBindingProject(bindingText, userProjectAbs, bindingPath);
37
+ await writeFile(bindingPath, rewritten, "utf-8");
38
+ return composedDir;
39
+ }
40
+ /**
41
+ * Resolves `bindingRelPath` against `composedDir` and rejects anything that escapes it. Mirrors the
42
+ * containment check `harness/exec/local.ts`'s (private) `resolveWithinScope` performs, reusing its
43
+ * exported {@link PathTraversalError} — kept as a local check here so the fix stays within this
44
+ * module rather than widening the exec module's public surface.
45
+ */
46
+ function resolveWithinComposedDir(composedDir, bindingRelPath) {
47
+ const targetAbs = path.resolve(composedDir, bindingRelPath);
48
+ const relative = path.relative(composedDir, targetAbs);
49
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
50
+ throw new PathTraversalError(bindingRelPath, composedDir);
51
+ }
52
+ return targetAbs;
53
+ }
54
+ /** Extracts the single `context: project: <path>` pointer from a profile.yml's text. */
55
+ export function extractContextBindingPath(profileYamlText, sourcePath) {
56
+ const pattern = /^context:[ \t]*\r?\n[ \t]+project:[ \t]*(\S+)[ \t]*$/gm;
57
+ const matches = [...profileYamlText.matchAll(pattern)];
58
+ if (matches.length === 0) {
59
+ throw new InvalidProfileShapeError(`"${sourcePath}" has no "context:\\n project: <path>" block — cannot locate its context binding file`);
60
+ }
61
+ if (matches.length > 1) {
62
+ throw new InvalidProfileShapeError(`"${sourcePath}" has ${matches.length} "context:\\n project:" blocks — expected exactly one`);
63
+ }
64
+ const captured = matches[0]?.[1];
65
+ if (captured === undefined) {
66
+ throw new InvalidProfileShapeError(`"${sourcePath}" has a malformed "context: project:" pointer`);
67
+ }
68
+ const unquoted = stripSurroundingQuotes(captured);
69
+ if (unquoted.length === 0) {
70
+ throw new InvalidProfileShapeError(`"${sourcePath}" has an empty "context: project:" pointer`);
71
+ }
72
+ return unquoted;
73
+ }
74
+ /**
75
+ * Replaces the single top-level `project:` line in a context-binding YAML's text, preserving
76
+ * surrounding comments. Asserts exactly one top-level `project:` — a second one would survive the
77
+ * rewrite as a stale line and could win under last-key-wins YAML parsing (silent misbind).
78
+ */
79
+ export function rewriteContextBindingProject(bindingText, newProjectPath, sourcePath) {
80
+ const pattern = /^project:[ \t]*.*$/gm;
81
+ const matches = [...bindingText.matchAll(pattern)];
82
+ if (matches.length === 0) {
83
+ throw new InvalidProfileShapeError(`"${sourcePath}" has no top-level "project:" field to rewrite`);
84
+ }
85
+ if (matches.length > 1) {
86
+ throw new InvalidProfileShapeError(`"${sourcePath}" has ${matches.length} top-level "project:" fields — expected exactly one (ambiguous binding)`);
87
+ }
88
+ // Function replacement so a project path containing `$` isn't interpreted as a replacement token.
89
+ return bindingText.replace(/^project:[ \t]*.*$/m, () => `project: ${newProjectPath}`);
90
+ }
91
+ /** Strips a single matching pair of surrounding single/double quotes, if present. */
92
+ function stripSurroundingQuotes(value) {
93
+ const match = value.match(/^(['"])(.*)\1$/);
94
+ return match?.[2] ?? value;
95
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Thrown by {@link resolveWarbleBinary} (see `./resolve-binary.js`) when no `warble` binary can be
3
+ * found via any of its four resolution tiers (explicit arg, installed `@warble/cli` package,
4
+ * `PATH`, opt-in sibling repo release build). Deliberately loud — this pipeline never silently
5
+ * degrades to "skip compiling".
6
+ */
7
+ export declare class WarbleBinaryNotFoundError extends Error {
8
+ constructor(attempts: readonly string[]);
9
+ }
10
+ /** Thrown when a `warble` subprocess (compile or dispatch) exits non-zero. */
11
+ export declare class WarbleCommandFailedError extends Error {
12
+ readonly command: string;
13
+ readonly args: readonly string[];
14
+ readonly exitCode: number;
15
+ readonly stderr: string;
16
+ readonly stdout: string;
17
+ constructor(command: string, args: readonly string[], exitCode: number, stderr: string, stdout?: string);
18
+ }
19
+ /** Thrown when a Warble profile directory doesn't have the expected `profile.yml` / context-binding shape. */
20
+ export declare class InvalidProfileShapeError extends Error {
21
+ constructor(message: string);
22
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Thrown by {@link resolveWarbleBinary} (see `./resolve-binary.js`) when no `warble` binary can be
3
+ * found via any of its four resolution tiers (explicit arg, installed `@warble/cli` package,
4
+ * `PATH`, opt-in sibling repo release build). Deliberately loud — this pipeline never silently
5
+ * degrades to "skip compiling".
6
+ */
7
+ export class WarbleBinaryNotFoundError extends Error {
8
+ constructor(attempts) {
9
+ super(`could not resolve a "warble" binary:\n` +
10
+ attempts.map((attempt) => ` - ${attempt}`).join("\n") +
11
+ `\nfix: pass "warbleBin" explicitly, run "pnpm install" so "@warble/cli" is installed, or ` +
12
+ `put "warble" on PATH.`);
13
+ this.name = "WarbleBinaryNotFoundError";
14
+ }
15
+ }
16
+ /** Thrown when a `warble` subprocess (compile or dispatch) exits non-zero. */
17
+ export class WarbleCommandFailedError extends Error {
18
+ command;
19
+ args;
20
+ exitCode;
21
+ stderr;
22
+ stdout;
23
+ constructor(command, args, exitCode, stderr, stdout = "") {
24
+ // warble reports diagnostics on stderr, but capture stdout too so nothing useful is dropped.
25
+ const diagnostics = [stderr.trim(), stdout.trim()].filter((chunk) => chunk.length > 0).join("\n");
26
+ super(`"${command} ${args.join(" ")}" exited ${exitCode}:\n${diagnostics || "(no output)"}`);
27
+ this.command = command;
28
+ this.args = args;
29
+ this.exitCode = exitCode;
30
+ this.stderr = stderr;
31
+ this.stdout = stdout;
32
+ this.name = "WarbleCommandFailedError";
33
+ }
34
+ }
35
+ /** Thrown when a Warble profile directory doesn't have the expected `profile.yml` / context-binding shape. */
36
+ export class InvalidProfileShapeError extends Error {
37
+ constructor(message) {
38
+ super(message);
39
+ this.name = "InvalidProfileShapeError";
40
+ }
41
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A content fingerprint for a directory tree: every included file's relative path plus a sha256 of
3
+ * its *contents*, combined into a single sha256. This is the identity {@link CompileCache} keys on
4
+ * for both the source profile and the user's wren project.
5
+ *
6
+ * Content (not size+mtime) is hashed deliberately: mtimes are unreliable (a fresh `git checkout`
7
+ * normalizes them) and same-size edits (e.g. a column rename) collide on size — either would yield
8
+ * a false cache HIT and silently serve a stale bundle, defeating the point of binding each user to
9
+ * THEIR current semantic layer. Bulk data files are skipped (see {@link EXCLUDED_DATA_SUFFIXES}).
10
+ * Symlinks are followed (via `stat`, not the `readdir` dirent type) so a symlinked semantic-layer
11
+ * file is hashed rather than silently skipped; broken symlinks are ignored.
12
+ */
13
+ export declare function hashDirectory(rootDir: string): Promise<string>;
14
+ /**
15
+ * A content fingerprint for an ordered list of individual files (e.g. `--provider` fragment
16
+ * paths) — order-sensitive, since dispatch merges multiple provider fragments and `[a, b]` can
17
+ * compile to a different artifact than `[b, a]`. Path strings themselves are NOT part of the
18
+ * hash — only each file's content — so a fragment copied to a different path with identical
19
+ * bytes doesn't cause an unnecessary cache miss. An empty list hashes deterministically too, so
20
+ * passing `[]` (no providers) is distinguishable from any non-empty set, including the default.
21
+ */
22
+ export declare function hashFiles(filePaths: readonly string[]): Promise<string>;
@@ -0,0 +1,84 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile, readdir, stat } from "node:fs/promises";
3
+ import path from "node:path";
4
+ /** Directories never worth fingerprinting: VCS metadata, package installs, prior compiler output. */
5
+ const IGNORED_DIR_NAMES = new Set([".git", "node_modules", ".warble"]);
6
+ /**
7
+ * Bulk data files excluded from the fingerprint: their bytes are NOT compiled into the IR/bundle
8
+ * (the context binding is a *path* to a wren project; row data is read at query time, not compile
9
+ * time), so a data-only change doesn't invalidate the compiled artifact. Everything that DOES feed
10
+ * the compiled artifact — profile.yml, components, and the user project's semantic-layer defs
11
+ * (`wren_project.yml`, `mdl` under `target/`, `cubes.yml`, `relationships.yml`, `instructions.md`,
12
+ * `models/`, `views/`) — is content-hashed. When in doubt a file is included, not excluded.
13
+ */
14
+ const EXCLUDED_DATA_SUFFIXES = [".duckdb", ".duckdb.wal", ".wal", ".parquet", ".sqlite", ".db"];
15
+ /**
16
+ * A content fingerprint for a directory tree: every included file's relative path plus a sha256 of
17
+ * its *contents*, combined into a single sha256. This is the identity {@link CompileCache} keys on
18
+ * for both the source profile and the user's wren project.
19
+ *
20
+ * Content (not size+mtime) is hashed deliberately: mtimes are unreliable (a fresh `git checkout`
21
+ * normalizes them) and same-size edits (e.g. a column rename) collide on size — either would yield
22
+ * a false cache HIT and silently serve a stale bundle, defeating the point of binding each user to
23
+ * THEIR current semantic layer. Bulk data files are skipped (see {@link EXCLUDED_DATA_SUFFIXES}).
24
+ * Symlinks are followed (via `stat`, not the `readdir` dirent type) so a symlinked semantic-layer
25
+ * file is hashed rather than silently skipped; broken symlinks are ignored.
26
+ */
27
+ export async function hashDirectory(rootDir) {
28
+ const entries = [];
29
+ await walk(rootDir, rootDir, entries);
30
+ entries.sort();
31
+ const hash = createHash("sha256");
32
+ for (const entry of entries)
33
+ hash.update(entry).update("\n");
34
+ return hash.digest("hex");
35
+ }
36
+ async function walk(rootDir, dir, out) {
37
+ const dirents = await readdir(dir, { withFileTypes: true });
38
+ for (const dirent of dirents) {
39
+ const fullPath = path.join(dir, dirent.name);
40
+ // `stat` follows symlinks, so a symlink is classified by its target (not skipped the way the
41
+ // `readdir` dirent's isDirectory()/isFile() would). A broken symlink / TOCTOU race throws → skip.
42
+ let stats;
43
+ try {
44
+ stats = await stat(fullPath);
45
+ }
46
+ catch {
47
+ continue;
48
+ }
49
+ if (stats.isDirectory()) {
50
+ if (IGNORED_DIR_NAMES.has(dirent.name))
51
+ continue;
52
+ await walk(rootDir, fullPath, out);
53
+ continue;
54
+ }
55
+ if (!stats.isFile())
56
+ continue;
57
+ if (isExcludedDataFile(dirent.name))
58
+ continue;
59
+ const content = await readFile(fullPath);
60
+ const fileHash = createHash("sha256").update(content).digest("hex");
61
+ const relPath = path.relative(rootDir, fullPath);
62
+ out.push(`${relPath}:${fileHash}`);
63
+ }
64
+ }
65
+ function isExcludedDataFile(name) {
66
+ const lower = name.toLowerCase();
67
+ return EXCLUDED_DATA_SUFFIXES.some((suffix) => lower.endsWith(suffix));
68
+ }
69
+ /**
70
+ * A content fingerprint for an ordered list of individual files (e.g. `--provider` fragment
71
+ * paths) — order-sensitive, since dispatch merges multiple provider fragments and `[a, b]` can
72
+ * compile to a different artifact than `[b, a]`. Path strings themselves are NOT part of the
73
+ * hash — only each file's content — so a fragment copied to a different path with identical
74
+ * bytes doesn't cause an unnecessary cache miss. An empty list hashes deterministically too, so
75
+ * passing `[]` (no providers) is distinguishable from any non-empty set, including the default.
76
+ */
77
+ export async function hashFiles(filePaths) {
78
+ const hash = createHash("sha256");
79
+ for (const filePath of filePaths) {
80
+ const content = await readFile(path.resolve(filePath));
81
+ hash.update(createHash("sha256").update(content).digest("hex")).update("\n");
82
+ }
83
+ return hash.digest("hex");
84
+ }
@@ -0,0 +1,8 @@
1
+ export { createFileSystemCompileCache, createInMemoryCompileCache, resolveDefaultCacheDir } from "./cache.js";
2
+ export { composeUserProfile, extractContextBindingPath, rewriteContextBindingProject } from "./compose-profile.js";
3
+ export { InvalidProfileShapeError, WarbleBinaryNotFoundError, WarbleCommandFailedError, } from "./errors.js";
4
+ export { hashDirectory, hashFiles } from "./fingerprint.js";
5
+ export { compileProfile, compileRawProfile, runWarble } from "./pipeline.js";
6
+ export { resolveHubDir, resolveWarbleBinary } from "./resolve-binary.js";
7
+ export type { CompileCache, CompileCacheEntry, CompileCacheKey, CompileMode, CompileProfileOptions, CompileProfileResult, CompileRawProfileOptions, } from "./types.js";
8
+ export { getWarbleIdentity } from "./warble-identity.js";
@@ -0,0 +1,7 @@
1
+ export { createFileSystemCompileCache, createInMemoryCompileCache, resolveDefaultCacheDir } from "./cache.js";
2
+ export { composeUserProfile, extractContextBindingPath, rewriteContextBindingProject } from "./compose-profile.js";
3
+ export { InvalidProfileShapeError, WarbleBinaryNotFoundError, WarbleCommandFailedError, } from "./errors.js";
4
+ export { hashDirectory, hashFiles } from "./fingerprint.js";
5
+ export { compileProfile, compileRawProfile, runWarble } from "./pipeline.js";
6
+ export { resolveHubDir, resolveWarbleBinary } from "./resolve-binary.js";
7
+ export { getWarbleIdentity } from "./warble-identity.js";
@@ -0,0 +1,66 @@
1
+ import type { CompileProfileOptions, CompileProfileResult, CompileRawProfileOptions } from "./types.js";
2
+ /**
3
+ * This package's bundled wren capability-provider fragment (`providers/wren.provider.yaml`) — the
4
+ * default `--provider` for in-process dispatch, matching how `fixtures/genbi-default.native.bundle.json`
5
+ * was produced (see `test/e2e-wren-native.test.ts`'s comment).
6
+ */
7
+ export declare const DEFAULT_WREN_PROVIDER_PATH: string;
8
+ /**
9
+ * Compiles a Warble profile bound to a specific user's wren project (the per-user compile
10
+ * pipeline): composes a copy of `profileSource` with its context binding rebound to `userProject`
11
+ * (see `composeUserProfile`), shells out to `warble compile` for the IR, and — in `"agnostic"`
12
+ * mode — additionally `warble dispatch --target vercel` for the vercel bundle this package's
13
+ * `runAgent()` consumes.
14
+ *
15
+ * A cache hit (see below) never *executes* `warble`, but by default DOES need to resolve + read
16
+ * the binary — its content hash and the Hub root derived from its location are both cache-key
17
+ * inputs (see `warbleIdentity` and `hubDir` below), so a hit can't be trusted without knowing which
18
+ * binary is current and which component library it reads. Pass both `options.warbleIdentity` and
19
+ * `options.hubDir` explicitly to skip touching the binary at all even on a hit.
20
+ *
21
+ * Deliberately shells via plain `node:child_process` (`execFile`, no shell) rather than this
22
+ * package's `ExecutionEnv` seam (`harness/exec/`): `ExecutionEnv` gates *runtime* native-tool side
23
+ * effects against a bundle's guardrail-derived `EnforcementPolicy` (read-only / write-scope /
24
+ * egress) — there is no bundle or agent yet at this point, compiling happens before any of that
25
+ * exists, so synthesizing a policy for it would be a semantic mismatch, not a reuse. This mirrors
26
+ * the same no-shell, structured-result `execFile` convention `harness/exec/local.ts` already uses.
27
+ *
28
+ * Results are cached on (profile content hash x user-context fingerprint x mode x resolved
29
+ * provider-fragment content hash x warble binary identity x resolved Hub root) — see `./cache.js` —
30
+ * so an unchanged profile/context/providers/compiler/Hub tuple returns the previous artifact
31
+ * instead of recompiling. Folding in the provider-fragment hash, warble identity and Hub root
32
+ * (rather than just profile+context+mode) matters: otherwise a custom `options.providers` and this
33
+ * package's default fragment collide on the same key, and editing a provider fragment, rebuilding
34
+ * `warble`, or compiling against a different component library would keep serving a stale artifact
35
+ * forever, since there's no TTL/eviction.
36
+ *
37
+ * The `warble` invocations run inside a temporary scratch directory (the composed profile + raw
38
+ * compiler output). When the cache relocates the artifacts to a durable home outside that scratch
39
+ * dir — as the default persistent {@link createFileSystemCompileCache} does — the scratch dir is
40
+ * removed and the durable cache paths are returned. When the cache does NOT relocate them (e.g. a
41
+ * non-persistent in-memory cache that just stores the paths), the scratch dir is retained so the
42
+ * returned paths stay valid. Either way the returned `irPath`/`bundlePath` are always readable, and
43
+ * a caller-supplied `workDir` is never deleted.
44
+ */
45
+ export declare function compileProfile(options: CompileProfileOptions): Promise<CompileProfileResult>;
46
+ /**
47
+ * Compiles a profile's authored context without composing it against a bound
48
+ * project. The fixed context fingerprint keeps raw-profile artifacts distinct
49
+ * from every user-project-bound compile while `profileHash` still invalidates
50
+ * the entry whenever the source profile changes.
51
+ */
52
+ export declare function compileRawProfile(options: CompileRawProfileOptions): Promise<CompileProfileResult>;
53
+ /**
54
+ * Shells a `warble` subcommand (no shell interpolation — `execFile`, argv
55
+ * array only). Exported for `InProcessSetupRunner` (`harness/setup/runner.ts`),
56
+ * which dispatches the pre-committed `genbi-setup/ir.golden.json` straight to
57
+ * `warble dispatch --target vercel`, bypassing `compileProfile`'s
58
+ * `composeUserProfile` rewrite entirely (there is no user project to bind
59
+ * context against at setup time — see that runner's doc comment). Reusing
60
+ * this rather than duplicating an `execFile` wrapper keeps the two callers'
61
+ * timeout/max-buffer/error-shaping behavior identical.
62
+ */
63
+ export declare function runWarble(bin: string, args: readonly string[]): Promise<{
64
+ stdout: string;
65
+ stderr: string;
66
+ }>;