@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,506 @@
1
+ {
2
+ "components": [
3
+ {
4
+ "borrowed_actions": [
5
+ "introspect"
6
+ ],
7
+ "context_binding": {
8
+ "binding_mode": "runtime_selected",
9
+ "project": "../../../../examples/v5-jaffle"
10
+ },
11
+ "context_precondition": [
12
+ {
13
+ "predicate": "mdl_parseable"
14
+ }
15
+ ],
16
+ "context_requirements": [
17
+ "a wren project (semantic layer) to introspect"
18
+ ],
19
+ "description": "Survey the bound semantic model and report what can be asked of it — its models, metrics, dimensions and grain — without querying any rows. Use it to orient before analysis, or when someone asks what data is available; it answers questions *about* the model, not questions *from* the data.",
20
+ "effect": {
21
+ "outcome": {
22
+ "kind": "none"
23
+ },
24
+ "render_blocks": []
25
+ },
26
+ "eval": {
27
+ "metrics": [
28
+ "coverage"
29
+ ],
30
+ "template_ref": "eval/"
31
+ },
32
+ "eval_ref": "explore_model.eval",
33
+ "examples": [
34
+ "What's in this dataset?",
35
+ "Which metrics and dimensions are available?",
36
+ "Can I break revenue down by region?"
37
+ ],
38
+ "guardrails": [
39
+ {
40
+ "locked": true,
41
+ "name": "read_only_execution"
42
+ }
43
+ ],
44
+ "id": "explore_model",
45
+ "llm_calls": [
46
+ {
47
+ "conditional": false,
48
+ "consumes": [],
49
+ "name": "summarize_semantics",
50
+ "produces": "semantic_summary",
51
+ "prompt": "You introspect the `v5-jaffle` wren project (a semantic layer at `../../../../examples/v5-jaffle`) and return a\nstructured summary of what it contains — the map the other GenBI components build on.\n\n- Introspect the semantic layer with the `wren` CLI: run `wren context show` (and, if available,\n `wren cube list`) to read the models, columns, relationships, and metrics/cubes. This is the\n `raw_introspect_result` you consume — read it, do not assume the schema.\n- Cover the FULL set: every model, its key columns and their roles (dimension vs measure vs\n time), the relationships between models, and any defined metrics/cubes. Do not drop entries to\n keep the summary short — coverage is the point.\n- Produce `semantic_summary`: a compact structured listing of every model and metric found. Your\n FINAL message must be a single JSON object of the form\n `{\"columns\": [\"model\"], \"rows\": [[\"<model_name>\"], ...]}` listing every model in the layer\n (one row per model), so coverage can be checked deterministically. You may add a short prose\n summary after the JSON.",
52
+ "tier": "cheap",
53
+ "when": null
54
+ }
55
+ ],
56
+ "params": [],
57
+ "precondition_result": {
58
+ "checks": [
59
+ {
60
+ "outcome": "pass",
61
+ "predicate": "mdl_parseable"
62
+ }
63
+ ],
64
+ "status": "pass"
65
+ },
66
+ "prompt_fragment": "## summarize_semantics\n\nYou introspect the `v5-jaffle` wren project (a semantic layer at `../../../../examples/v5-jaffle`) and return a\nstructured summary of what it contains — the map the other GenBI components build on.\n\n- Introspect the semantic layer with the `wren` CLI: run `wren context show` (and, if available,\n `wren cube list`) to read the models, columns, relationships, and metrics/cubes. This is the\n `raw_introspect_result` you consume — read it, do not assume the schema.\n- Cover the FULL set: every model, its key columns and their roles (dimension vs measure vs\n time), the relationships between models, and any defined metrics/cubes. Do not drop entries to\n keep the summary short — coverage is the point.\n- Produce `semantic_summary`: a compact structured listing of every model and metric found. Your\n FINAL message must be a single JSON object of the form\n `{\"columns\": [\"model\"], \"rows\": [[\"<model_name>\"], ...]}` listing every model in the layer\n (one row per model), so coverage can be checked deterministically. You may add a short prose\n summary after the JSON.",
67
+ "realization_kind": "skill",
68
+ "required_capabilities": [
69
+ "semantic_introspection",
70
+ "llm:cheap"
71
+ ],
72
+ "trigger": {
73
+ "kind": "one_shot"
74
+ },
75
+ "type": "analytical",
76
+ "verb": "explore_model"
77
+ },
78
+ {
79
+ "borrowed_actions": [],
80
+ "context_binding": {
81
+ "binding_mode": "runtime_selected",
82
+ "project": "../../../../examples/v5-jaffle"
83
+ },
84
+ "context_precondition": [
85
+ {
86
+ "predicate": "mdl_parseable"
87
+ }
88
+ ],
89
+ "context_requirements": [
90
+ "a wren project (semantic layer) to query"
91
+ ],
92
+ "description": "Answer one natural-language question about the bound semantic model: resolve the intent, generate SQL against the semantic layer, run it read-only, and repair the query if it fails. Returns a result table with the definitions it relied on. Use it for a single question with a single answer, not for a multi-panel overview.",
93
+ "effect": {
94
+ "outcome": {
95
+ "kind": "none"
96
+ },
97
+ "render_blocks": [
98
+ {
99
+ "fields": {
100
+ "columns": "string[]",
101
+ "rows": "row[]"
102
+ },
103
+ "type": "table"
104
+ },
105
+ {
106
+ "fields": {
107
+ "filters": "string[]",
108
+ "source_tables": "string[]",
109
+ "sql": "string"
110
+ },
111
+ "type": "definition"
112
+ }
113
+ ]
114
+ },
115
+ "eval": {
116
+ "metrics": [
117
+ "execution_accuracy",
118
+ "tier_cost_pareto"
119
+ ],
120
+ "template_ref": "eval/"
121
+ },
122
+ "eval_ref": "answer_query.eval",
123
+ "examples": [
124
+ "What were last quarter's top 10 customers by revenue?",
125
+ "How many orders shipped late in March?",
126
+ "Compare average order value between new and returning customers."
127
+ ],
128
+ "guardrails": [
129
+ {
130
+ "locked": true,
131
+ "name": "read_only_execution"
132
+ },
133
+ {
134
+ "locked": false,
135
+ "name": "row_limit",
136
+ "threshold": 1000
137
+ },
138
+ {
139
+ "locked": false,
140
+ "name": "statement_timeout",
141
+ "threshold": 30
142
+ },
143
+ {
144
+ "locked": true,
145
+ "name": "deterministic_gate"
146
+ }
147
+ ],
148
+ "id": "answer_query",
149
+ "llm_calls": [
150
+ {
151
+ "conditional": false,
152
+ "consumes": [],
153
+ "name": "resolve_intent",
154
+ "produces": "query_intent",
155
+ "prompt": "You answer a single data question over the `v5-jaffle` wren project (a semantic layer at\n`../../../../examples/v5-jaffle`). This first step resolves the user's question into a concrete query intent.\n\n- If unsure of the schema, introspect first: `wren context show`.\n- Identify which model(s), metric(s), dimension(s), filters, grouping, and ordering the question\n implies. Resolve ambiguous business terms to concrete columns/metrics in the semantic layer.\n- Produce `query_intent`: a short, explicit statement of exactly what to compute (measures,\n grouping, filters, ordering, row limit) — enough for the next step to write SQL without\n re-reading the question.",
156
+ "tier": "cheap",
157
+ "when": null
158
+ },
159
+ {
160
+ "conditional": false,
161
+ "consumes": [
162
+ "query_intent"
163
+ ],
164
+ "name": "generate_sql",
165
+ "produces": "query_result",
166
+ "prompt": "Given the resolved `query_intent`, write and execute the query through the semantic layer.\n\n- Query ONLY through the wren CLI, which returns JSON: `wren -q -o json -s '<SQL>'`. Never\n hand-write SQL against raw tables outside the model — always go through the semantic layer.\n- Respect the guardrails: read-only only, keep within the row limit, and prefer a deterministic\n ordering when the question implies a ranking or a top-N.\n- **Verify the result set (deterministic gate — required before answering).** After the query runs,\n check it is legitimate: it actually executed (no error), it is non-empty where a value is expected,\n the types/units are sane, and the grain matches the question. Record whether it passed.\n- On success, produce `query_result` as exactly one object with this shape and no extra keys:\n ```\n {\"columns\": [\"col1\", ...], \"rows\": [[v1, ...], ...],\n \"summary\": \"<a concise prose answer grounded only in the returned rows>\",\n \"verified\": true,\n \"definition\": {\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"], \"filters\": [\"...\"]}}\n ```\n Object rows from `wren` are also valid; preserve their values exactly. Emit numbers as numbers.\n Set `verified: true` only after both execution and the deterministic result-set validation pass.\n The summary must state the useful conclusion, not merely describe the columns or claim that the\n query succeeded. `definition` is run-level provenance only; do not invent formal lineage.\n- On failure, keep the attempted SQL, execution/validation evidence, and stable non-secret error in\n `query_result` so the declared repair step can diagnose it. Never mark a failed result verified.",
167
+ "tier": "strong",
168
+ "when": null
169
+ },
170
+ {
171
+ "conditional": true,
172
+ "consumes": [
173
+ "query_result"
174
+ ],
175
+ "name": "repair_sql",
176
+ "produces": "repaired_result",
177
+ "prompt": "Repair step — runs ONLY when `query_result` came back with an execution error or an empty/obviously\nwrong result. If the previous step succeeded with a sensible result, do nothing and pass it through.\n\n- Diagnose the failure from the error text (unknown column, bad join, type mismatch, wrong grain),\n fix the SQL, and re-run it through `wren -q -o json -s '<SQL>'`. Bound your attempts — a few\n retries at most; do not loop indefinitely (retry depth is this step's concern, not the profile's).\n- **If the result still cannot be validated, REFUSE.** Do not fabricate a number. Emit\n `{\"verified\": false, \"refused\": true, \"reason\": \"<why it could not be verified>\"}` and stop.\n- Produce `repaired_result`. On success return exactly the same canonical rich result shape as\n `generate_sql`, with no extra keys:\n ```\n {\"columns\": [\"col1\", ...], \"rows\": [[v1, ...], ...],\n \"summary\": \"<a concise prose answer grounded only in the returned rows>\",\n \"verified\": true,\n \"definition\": {\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"], \"filters\": [\"...\"]}}\n ```\n Object rows from `wren` are also valid; preserve their values exactly and emit numbers as numbers.\n Set `verified: true` only when the repaired query ran and its result set passed validation. The\n summary must state the useful conclusion grounded only in those rows. The `definition` is\n run-level provenance only (the query behind this answer) — do not invent unit/owner/formal-metric\n lineage (out of scope for this run-level card).",
178
+ "tier": "strong",
179
+ "when": {
180
+ "guard": "on_failure",
181
+ "target": "generate_sql"
182
+ }
183
+ }
184
+ ],
185
+ "params": [],
186
+ "precondition_result": {
187
+ "checks": [
188
+ {
189
+ "outcome": "pass",
190
+ "predicate": "mdl_parseable"
191
+ }
192
+ ],
193
+ "status": "pass"
194
+ },
195
+ "prompt_fragment": "## resolve_intent\n\nYou answer a single data question over the `v5-jaffle` wren project (a semantic layer at\n`../../../../examples/v5-jaffle`). This first step resolves the user's question into a concrete query intent.\n\n- If unsure of the schema, introspect first: `wren context show`.\n- Identify which model(s), metric(s), dimension(s), filters, grouping, and ordering the question\n implies. Resolve ambiguous business terms to concrete columns/metrics in the semantic layer.\n- Produce `query_intent`: a short, explicit statement of exactly what to compute (measures,\n grouping, filters, ordering, row limit) — enough for the next step to write SQL without\n re-reading the question.\n\n## generate_sql\n\nGiven the resolved `query_intent`, write and execute the query through the semantic layer.\n\n- Query ONLY through the wren CLI, which returns JSON: `wren -q -o json -s '<SQL>'`. Never\n hand-write SQL against raw tables outside the model — always go through the semantic layer.\n- Respect the guardrails: read-only only, keep within the row limit, and prefer a deterministic\n ordering when the question implies a ranking or a top-N.\n- **Verify the result set (deterministic gate — required before answering).** After the query runs,\n check it is legitimate: it actually executed (no error), it is non-empty where a value is expected,\n the types/units are sane, and the grain matches the question. Record whether it passed.\n- On success, produce `query_result` as exactly one object with this shape and no extra keys:\n ```\n {\"columns\": [\"col1\", ...], \"rows\": [[v1, ...], ...],\n \"summary\": \"<a concise prose answer grounded only in the returned rows>\",\n \"verified\": true,\n \"definition\": {\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"], \"filters\": [\"...\"]}}\n ```\n Object rows from `wren` are also valid; preserve their values exactly. Emit numbers as numbers.\n Set `verified: true` only after both execution and the deterministic result-set validation pass.\n The summary must state the useful conclusion, not merely describe the columns or claim that the\n query succeeded. `definition` is run-level provenance only; do not invent formal lineage.\n- On failure, keep the attempted SQL, execution/validation evidence, and stable non-secret error in\n `query_result` so the declared repair step can diagnose it. Never mark a failed result verified.\n\n## repair_sql\n\nRepair step — runs ONLY when `query_result` came back with an execution error or an empty/obviously\nwrong result. If the previous step succeeded with a sensible result, do nothing and pass it through.\n\n- Diagnose the failure from the error text (unknown column, bad join, type mismatch, wrong grain),\n fix the SQL, and re-run it through `wren -q -o json -s '<SQL>'`. Bound your attempts — a few\n retries at most; do not loop indefinitely (retry depth is this step's concern, not the profile's).\n- **If the result still cannot be validated, REFUSE.** Do not fabricate a number. Emit\n `{\"verified\": false, \"refused\": true, \"reason\": \"<why it could not be verified>\"}` and stop.\n- Produce `repaired_result`. On success return exactly the same canonical rich result shape as\n `generate_sql`, with no extra keys:\n ```\n {\"columns\": [\"col1\", ...], \"rows\": [[v1, ...], ...],\n \"summary\": \"<a concise prose answer grounded only in the returned rows>\",\n \"verified\": true,\n \"definition\": {\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"], \"filters\": [\"...\"]}}\n ```\n Object rows from `wren` are also valid; preserve their values exactly and emit numbers as numbers.\n Set `verified: true` only when the repaired query ran and its result set passed validation. The\n summary must state the useful conclusion grounded only in those rows. The `definition` is\n run-level provenance only (the query behind this answer) — do not invent unit/owner/formal-metric\n lineage (out of scope for this run-level card).",
196
+ "realization_kind": "skill",
197
+ "required_capabilities": [
198
+ "sql_execution:read_only",
199
+ "llm:per_step_tier",
200
+ "llm:strong",
201
+ "llm:cheap"
202
+ ],
203
+ "trigger": {
204
+ "kind": "one_shot"
205
+ },
206
+ "type": "analytical",
207
+ "verb": "answer_query"
208
+ },
209
+ {
210
+ "binds": {
211
+ "topic_default": "overview"
212
+ },
213
+ "borrowed_actions": [],
214
+ "context_binding": {
215
+ "binding_mode": "runtime_selected",
216
+ "project": "../../../../examples/v5-jaffle"
217
+ },
218
+ "context_precondition": [],
219
+ "context_requirements": [
220
+ "a wren project (semantic layer) to build dashboards over"
221
+ ],
222
+ "description": "Build a multi-panel dashboard on a topic: plan which panels answer it, run each panel's query read-only, and compose them into one laid-out result of KPI cards, tables and charts. Use it when someone wants an overview of a subject from several angles rather than one specific answer.",
223
+ "effect": {
224
+ "outcome": {
225
+ "kind": "none"
226
+ },
227
+ "render_blocks": [
228
+ {
229
+ "fields": {
230
+ "delta": "number?",
231
+ "label": "string",
232
+ "unit": "string?",
233
+ "value": "number|string"
234
+ },
235
+ "type": "kpi_card"
236
+ },
237
+ {
238
+ "fields": {
239
+ "columns": "string[]",
240
+ "rows": "row[]"
241
+ },
242
+ "type": "table"
243
+ },
244
+ {
245
+ "fields": {
246
+ "chart_type": "bar|line|pie|area|scatter",
247
+ "rows": "row[]",
248
+ "series": "string[]",
249
+ "x": "string"
250
+ },
251
+ "type": "chart"
252
+ },
253
+ {
254
+ "fields": {
255
+ "filters": "string[]",
256
+ "source_tables": "string[]",
257
+ "sql": "string"
258
+ },
259
+ "type": "definition"
260
+ }
261
+ ]
262
+ },
263
+ "eval": {
264
+ "metrics": [
265
+ "panel_validity",
266
+ "relevance"
267
+ ],
268
+ "template_ref": "eval/"
269
+ },
270
+ "eval_ref": "generate_dashboard.eval",
271
+ "examples": [
272
+ "Give me a sales overview for this quarter.",
273
+ "Build a dashboard for customer retention.",
274
+ "Show me how the marketing funnel is doing."
275
+ ],
276
+ "guardrails": [
277
+ {
278
+ "locked": true,
279
+ "name": "read_only_execution"
280
+ },
281
+ {
282
+ "locked": true,
283
+ "name": "artifact_write",
284
+ "scope": "."
285
+ }
286
+ ],
287
+ "id": "generate_dashboard",
288
+ "llm_calls": [
289
+ {
290
+ "conditional": false,
291
+ "consumes": [],
292
+ "name": "plan_dashboard",
293
+ "produces": "dashboard_plan",
294
+ "prompt": "You build data dashboards over the `v5-jaffle` wren project (a semantic layer at\n`../../../../examples/v5-jaffle`).\n\nGiven the user's topic, plan the dashboard:\n\n- If the request doesn't name a fresh topic of its own — it refers back to a dashboard already in\n play (\"the dashboard,\" \"it,\" \"that dashboard\"), or is a bare \"create an artifact for it\" /\n \"build it\" follow-up — do NOT stop here to ask what dashboard or what topic. Take the topic from\n the conversation so far (whatever dashboard/topic was most recently discussed); if there is\n truly none, fall back to an overview of the project's key metrics. Either way, keep planning:\n this step always ends with a `dashboard_plan`, never a clarifying question.\n- Discover available models, columns, and cubes **at query time** using the `wren` CLI\n (`wren context show`, `wren cube list`, `wren cube describe <cube>`). Do not assume the schema —\n introspect it.\n- Decide which metrics and dimensions answer the topic, and what panels are needed\n (KPI cards for headline numbers, a chart for trends/breakdowns, a table for detail).\n- Produce `dashboard_plan`: for each panel, the panel type (kpi_card | table | chart) and the exact\n query (through the semantic layer) that populates it. Every query goes through `wren`; never\n hand-write SQL against raw tables outside the model.",
295
+ "tier": "strong",
296
+ "when": null
297
+ },
298
+ {
299
+ "conditional": false,
300
+ "consumes": [
301
+ "dashboard_plan"
302
+ ],
303
+ "name": "compose_layout",
304
+ "produces": "dashboard",
305
+ "prompt": "Given the `dashboard_plan`, run each panel's query and compose the dashboard.\n\n- Run each planned panel query with the `wren` CLI (`wren -q -o json -s '<SQL>'`) and collect the\n results — these are the `panel_results` you consume. (This inlines the query behavior; it does not\n call a separate query component.)\n- Assemble each panel into a typed render block conforming to the render contract:\n `kpi_card` for headline numbers, `chart` for trends/breakdowns, `table` for detail.\n- Produce `dashboard`: follow the \"Render output\" instructions the dispatcher appends below for the\n active render flavor — emit the `{ blocks, summary }` envelope (programmatic) or write the HTML\n (prompt). The blocks must carry real values from `panel_results`, not placeholders.\n- The rendered dashboard IS the artifact. Never ask the user what kind of artifact they want, and\n never offer alternatives — saving the plan/JSON to a file, exporting to CSV, \"something else?\",\n etc. Whatever the user called it (\"an artifact,\" \"a report,\" \"the dashboard\"), this step's only\n job is to compose it and produce `dashboard` per the render flavor above; don't stop to\n clarify format, and don't do anything else instead (no writing files outside what \"Render\n output\" already directs).",
306
+ "tier": "cheap",
307
+ "when": null
308
+ }
309
+ ],
310
+ "params": [
311
+ {
312
+ "bind": "optional",
313
+ "default": "overview",
314
+ "name": "topic_default"
315
+ }
316
+ ],
317
+ "precondition_result": {
318
+ "checks": [],
319
+ "status": "pass"
320
+ },
321
+ "prompt_fragment": "## plan_dashboard\n\nYou build data dashboards over the `v5-jaffle` wren project (a semantic layer at\n`../../../../examples/v5-jaffle`).\n\nGiven the user's topic, plan the dashboard:\n\n- If the request doesn't name a fresh topic of its own — it refers back to a dashboard already in\n play (\"the dashboard,\" \"it,\" \"that dashboard\"), or is a bare \"create an artifact for it\" /\n \"build it\" follow-up — do NOT stop here to ask what dashboard or what topic. Take the topic from\n the conversation so far (whatever dashboard/topic was most recently discussed); if there is\n truly none, fall back to an overview of the project's key metrics. Either way, keep planning:\n this step always ends with a `dashboard_plan`, never a clarifying question.\n- Discover available models, columns, and cubes **at query time** using the `wren` CLI\n (`wren context show`, `wren cube list`, `wren cube describe <cube>`). Do not assume the schema —\n introspect it.\n- Decide which metrics and dimensions answer the topic, and what panels are needed\n (KPI cards for headline numbers, a chart for trends/breakdowns, a table for detail).\n- Produce `dashboard_plan`: for each panel, the panel type (kpi_card | table | chart) and the exact\n query (through the semantic layer) that populates it. Every query goes through `wren`; never\n hand-write SQL against raw tables outside the model.\n\n## compose_layout\n\nGiven the `dashboard_plan`, run each panel's query and compose the dashboard.\n\n- Run each planned panel query with the `wren` CLI (`wren -q -o json -s '<SQL>'`) and collect the\n results — these are the `panel_results` you consume. (This inlines the query behavior; it does not\n call a separate query component.)\n- Assemble each panel into a typed render block conforming to the render contract:\n `kpi_card` for headline numbers, `chart` for trends/breakdowns, `table` for detail.\n- Produce `dashboard`: follow the \"Render output\" instructions the dispatcher appends below for the\n active render flavor — emit the `{ blocks, summary }` envelope (programmatic) or write the HTML\n (prompt). The blocks must carry real values from `panel_results`, not placeholders.\n- The rendered dashboard IS the artifact. Never ask the user what kind of artifact they want, and\n never offer alternatives — saving the plan/JSON to a file, exporting to CSV, \"something else?\",\n etc. Whatever the user called it (\"an artifact,\" \"a report,\" \"the dashboard\"), this step's only\n job is to compose it and produce `dashboard` per the render flavor above; don't stop to\n clarify format, and don't do anything else instead (no writing files outside what \"Render\n output\" already directs).",
322
+ "realization_kind": "skill",
323
+ "required_capabilities": [
324
+ "sql_execution:read_only",
325
+ "genbi_build",
326
+ "render_contract",
327
+ "artifact_write",
328
+ "llm:per_step_tier",
329
+ "llm:strong",
330
+ "llm:cheap"
331
+ ],
332
+ "trigger": {
333
+ "kind": "one_shot"
334
+ },
335
+ "type": "analytical",
336
+ "verb": "generate_dashboard"
337
+ },
338
+ {
339
+ "borrowed_actions": [],
340
+ "context_binding": {
341
+ "binding_mode": "runtime_selected",
342
+ "project": "../../../../examples/v5-jaffle"
343
+ },
344
+ "context_precondition": [],
345
+ "context_requirements": [
346
+ "a wren project with an additive metric plus a time dimension and a groupable dimension"
347
+ ],
348
+ "description": "Explain why a metric moved: decompose the change across time and the dimensions that drive it, then report the contributing drivers as a narrative. Needs an additive metric with a time dimension; the specific metric's additivity is checked at run time. Use it for causal \"why did this move\" questions, not for retrieving the number itself.",
349
+ "effect": {
350
+ "outcome": {
351
+ "kind": "none"
352
+ },
353
+ "render_blocks": [
354
+ {
355
+ "fields": {
356
+ "text": "string",
357
+ "title": "string?"
358
+ },
359
+ "type": "narrative"
360
+ }
361
+ ]
362
+ },
363
+ "eval": {
364
+ "metrics": [
365
+ "driver_correctness",
366
+ "additivity_guard"
367
+ ],
368
+ "template_ref": "eval/"
369
+ },
370
+ "eval_ref": "explain_change.eval",
371
+ "examples": [
372
+ "Why did revenue drop last month?",
373
+ "What's driving the increase in churn this quarter?",
374
+ "Which regions explain the spike in refunds?"
375
+ ],
376
+ "guardrails": [
377
+ {
378
+ "locked": true,
379
+ "name": "read_only_execution"
380
+ },
381
+ {
382
+ "locked": false,
383
+ "name": "drill_depth_limit",
384
+ "threshold": 3
385
+ },
386
+ {
387
+ "locked": true,
388
+ "name": "additivity_guard"
389
+ },
390
+ {
391
+ "locked": true,
392
+ "name": "artifact_write",
393
+ "scope": "."
394
+ }
395
+ ],
396
+ "id": "explain_change",
397
+ "llm_calls": [
398
+ {
399
+ "conditional": false,
400
+ "consumes": [],
401
+ "name": "plan_decomposition",
402
+ "produces": "decomposition_plan",
403
+ "prompt": "You explain why a metric changed over the `v5-jaffle` wren project (a semantic layer at\n`../../../../examples/v5-jaffle`), by planning how to decompose the change.\n\n- Introspect the layer as needed (`wren context show`) to find the metric, its time dimension, and\n the dimensions you can break the change down by.\n- Confirm the metric is **additive** across the dimensions you intend to decompose along (a sum of\n parts equals the whole). Nothing upstream guarantees this — you must check that the **specific**\n metric you decompose is additive. If it is a ratio/average/distinct-count or otherwise\n non-additive, note that: decomposing it can mislead.\n- Produce `decomposition_plan`: the metric, the two periods being compared, and the ordered list of\n dimensions to decompose the delta along (bounded by the drill-depth limit).",
404
+ "tier": "strong",
405
+ "when": null
406
+ },
407
+ {
408
+ "conditional": false,
409
+ "consumes": [
410
+ "decomposition_plan"
411
+ ],
412
+ "name": "synthesize_drivers",
413
+ "produces": "driver_explanation",
414
+ "prompt": "Given the `decomposition_plan`, quantify the change and synthesize the drivers into an explanation.\n\n- Run the decomposition queries through the `wren` CLI (`wren -q -o json -s '<SQL>'`): compute the\n metric for each period and the per-dimension contribution to the delta. Rank contributors by the\n size of their contribution.\n- Produce `driver_explanation` as a `narrative` render block: a short, ordered account of what drove\n the change (largest contributors first), with the actual numbers. Follow the \"Render output\"\n instructions the dispatcher appends below.\n- **Additivity caveat (required):** if the metric is not strictly additive across the decomposition\n dimensions, state plainly in the narrative that the attribution is approximate and additivity was\n not enforced. Never present a decomposition of a non-additive metric as exact — the hero output\n must not claim to run on verified reasoning it did not.",
415
+ "tier": "strong",
416
+ "when": null
417
+ }
418
+ ],
419
+ "params": [],
420
+ "precondition_result": {
421
+ "checks": [],
422
+ "status": "pass"
423
+ },
424
+ "prompt_fragment": "## plan_decomposition\n\nYou explain why a metric changed over the `v5-jaffle` wren project (a semantic layer at\n`../../../../examples/v5-jaffle`), by planning how to decompose the change.\n\n- Introspect the layer as needed (`wren context show`) to find the metric, its time dimension, and\n the dimensions you can break the change down by.\n- Confirm the metric is **additive** across the dimensions you intend to decompose along (a sum of\n parts equals the whole). Nothing upstream guarantees this — you must check that the **specific**\n metric you decompose is additive. If it is a ratio/average/distinct-count or otherwise\n non-additive, note that: decomposing it can mislead.\n- Produce `decomposition_plan`: the metric, the two periods being compared, and the ordered list of\n dimensions to decompose the delta along (bounded by the drill-depth limit).\n\n## synthesize_drivers\n\nGiven the `decomposition_plan`, quantify the change and synthesize the drivers into an explanation.\n\n- Run the decomposition queries through the `wren` CLI (`wren -q -o json -s '<SQL>'`): compute the\n metric for each period and the per-dimension contribution to the delta. Rank contributors by the\n size of their contribution.\n- Produce `driver_explanation` as a `narrative` render block: a short, ordered account of what drove\n the change (largest contributors first), with the actual numbers. Follow the \"Render output\"\n instructions the dispatcher appends below.\n- **Additivity caveat (required):** if the metric is not strictly additive across the decomposition\n dimensions, state plainly in the narrative that the attribution is approximate and additivity was\n not enforced. Never present a decomposition of a non-additive metric as exact — the hero output\n must not claim to run on verified reasoning it did not.",
425
+ "realization_kind": "skill",
426
+ "required_capabilities": [
427
+ "sql_execution:read_only",
428
+ "render_contract",
429
+ "artifact_write",
430
+ "llm:strong"
431
+ ],
432
+ "trigger": {
433
+ "kind": "one_shot"
434
+ },
435
+ "type": "analytical",
436
+ "verb": "explain_change"
437
+ }
438
+ ],
439
+ "config": {},
440
+ "context_binding": {
441
+ "binding_mode": "runtime_selected",
442
+ "project": "../../../../examples/v5-jaffle",
443
+ "resolved": {
444
+ "dimensions": [
445
+ {
446
+ "name": "customer_id",
447
+ "temporal": false
448
+ },
449
+ {
450
+ "name": "name",
451
+ "temporal": false
452
+ },
453
+ {
454
+ "name": "order_date",
455
+ "temporal": true
456
+ }
457
+ ],
458
+ "lineage": {
459
+ "consumers": {
460
+ "dashboards": 0,
461
+ "queries": 1
462
+ },
463
+ "edges": 7,
464
+ "nodes": 8,
465
+ "resolvable": true
466
+ },
467
+ "metrics": [
468
+ {
469
+ "additivity": "additive",
470
+ "declared": true,
471
+ "name": "total_revenue"
472
+ },
473
+ {
474
+ "additivity": "additive",
475
+ "declared": true,
476
+ "name": "order_count"
477
+ },
478
+ {
479
+ "declared": false,
480
+ "name": "id"
481
+ },
482
+ {
483
+ "declared": false,
484
+ "name": "id"
485
+ },
486
+ {
487
+ "declared": false,
488
+ "name": "customer_id"
489
+ },
490
+ {
491
+ "declared": false,
492
+ "name": "amount"
493
+ }
494
+ ],
495
+ "models": [
496
+ "customers",
497
+ "orders"
498
+ ],
499
+ "time_dimensions": [
500
+ "order_date"
501
+ ]
502
+ }
503
+ },
504
+ "profile": "genbi-default",
505
+ "warble_ir_version": "0.6"
506
+ }
@@ -0,0 +1,16 @@
1
+ # genbi-default — the flagship GenBI profile.
2
+ #
3
+ # Mounts the four consuming GenBI components as a single git-authoritative behavior surface, bound to
4
+ # one semantic context. The components themselves live in Warble's shared Hub component library; this
5
+ # profile mounts them by id and does not own its own component library.
6
+
7
+ profile: genbi-default
8
+
9
+ context:
10
+ project: ./context/binding.yml
11
+
12
+ components:
13
+ - use: explore_model
14
+ - use: answer_query
15
+ - use: generate_dashboard
16
+ - use: explain_change
@@ -0,0 +1,42 @@
1
+ # apply_enrichment — deterministic, sink-scoped post-approval lifecycle. This component has no
2
+ # llm_steps: the host validates the typed proposal, enforces stale/replay checks, applies one
3
+ # operation at a time, validates each MDL operation (reverting that operation on failure), then
4
+ # builds once at session end. It is intentionally a gated-tool so targets without an approval
5
+ # channel wall-hit instead of weakening the high-impact approval requirement.
6
+ id: apply_enrichment
7
+ verb: apply_enrichment
8
+ type: constitutive
9
+ realization_kind: gated-tool
10
+
11
+ binding_mode: pinned
12
+ context_requirements:
13
+ - "an existing pinned Wren project whose semantic layer parses and has a successful build proof"
14
+ context_precondition:
15
+ - { predicate: wren_project_exists }
16
+
17
+ params: []
18
+ llm_steps: []
19
+ trigger: { kind: one_shot }
20
+ guardrails:
21
+ - { name: must_dry_run, locked: true }
22
+ - { name: human_approval, locked: true }
23
+ - { name: no_silent_overwrite, locked: true }
24
+ - { name: context_write_authz, locked: true, scope: "enrichment-sinks" }
25
+ - { name: rollback_available, locked: true }
26
+ required_capabilities:
27
+ - context_write_authz
28
+ - context_validate
29
+ - context_build
30
+ - version_control
31
+ - human_approval
32
+ - enrichment_apply:deterministic
33
+ borrowed_actions: []
34
+ effect:
35
+ render_blocks: [diff, status]
36
+ outcome:
37
+ kind: mutation
38
+ target: context
39
+ change_type: context_enrichment
40
+ eval:
41
+ template_ref: eval/
42
+ metrics: [enrichment_apply_safety, compliance]
@@ -0,0 +1,30 @@
1
+ # draft_enrichment — strong-model proposal drafting over the read-only inspection result.
2
+ # The concrete payload stays executor-side; the host-facing proposal contains content digests,
3
+ # evidence ids, confidence, and sink-scoped operation identities only.
4
+ id: draft_enrichment
5
+ verb: draft_enrichment
6
+ type: analytical
7
+ realization_kind: skill
8
+
9
+ binding_mode: pinned
10
+ context_requirements:
11
+ - "an existing pinned Wren project whose semantic layer parses and has a successful build proof"
12
+ context_precondition:
13
+ - { predicate: wren_project_exists }
14
+
15
+ params: []
16
+ llm_steps:
17
+ - { name: draft, tier: strong, prompt_ref: steps/draft.md, produces: enrichment_proposal }
18
+ trigger: { kind: one_shot }
19
+ guardrails:
20
+ - { name: read_only_execution, locked: true }
21
+ required_capabilities:
22
+ - semantic_introspection
23
+ - llm:strong
24
+ borrowed_actions: []
25
+ effect:
26
+ render_blocks: [diff]
27
+ outcome: { kind: none }
28
+ eval:
29
+ template_ref: eval/
30
+ metrics: [enrichment_proposal_soundness, enrichment_sink_routing]
@@ -0,0 +1,34 @@
1
+ Turn the read-only gap inventory into concrete, minimal, append-only proposals. Do not apply them.
2
+
3
+ - Treat the pinned project revision as input, not something to infer. Return canonicalizable draft
4
+ material and evidence locators, but do not invent or claim authoritative proposal hashes or content
5
+ digests. The host validates the sink and revision, canonicalizes the payload, and computes both.
6
+ - Each proposed operation has exactly one allowed relative sink. Existing text, MDL fields, cubes,
7
+ and relationships are never overwritten.
8
+ - A cube proposal must target `cubes/<name>/metadata.yml` and use Wren's cube schema: `name`,
9
+ `base_object`, `measures`, optional `dimensions` / `time_dimensions`, and `properties`. Measures and
10
+ dimensions may reference only columns that actually exist on the chosen base object. Never invent
11
+ columns, use model-MDL keys such as `columns` / `metrics` / `relationships`, or hide a required join
12
+ inside a cube expression. If one append-only operation cannot implement the gap, emit a paused
13
+ decision explaining the missing prerequisite instead of fabricating a payload.
14
+ - For a cube, put the file body in `recommended_yaml` and follow this exact field grammar:
15
+ `measures: [{name, expression, type}]`, `dimensions: [{name, expression, type}]`, and
16
+ `time_dimensions: [{name, expression, type}]`. Use SQL aggregate expressions such as
17
+ `SUM(units_on_hand)` and Wren scalar types such as `BIGINT`, `INTEGER`, and `DATE`. Do not emit
18
+ `sql`, `model`, `columns`, `metrics`, or aggregation names such as `type: sum`.
19
+ - Grill mode emits one decision request at a time with a concrete recommended draft and accepts only
20
+ accept, edit, or skip for that operation. Skip is final for this run.
21
+ - Autopilot may mark only append-only low-risk model/column descriptions, knowledge rules, and
22
+ NL-to-SQL pairs as eligible to apply. It must pause for raw-vs-current conflicts, ambiguous sink
23
+ selection, and every new cube, view, relationship, MDL metric, or calculated column.
24
+ - Mark all inference and partial-raw evidence with confidence. Do not include raw text, credentials,
25
+ local paths, provider-session ids, or SDK internals in the host-facing proposal.
26
+ - A new cube is high impact, always requires approval, and is never autopilot-eligible.
27
+
28
+ Produce `enrichment_proposal`; approval, canonical hashes/digests, and application are deterministic
29
+ host responsibilities. Your FINAL message must be one JSON object only. Do not include prose or
30
+ Markdown fences. The top level is `{ "enrichment_proposal": { ... } }`; for Grill it contains the
31
+ supplied `project_revision`, exactly one operation with `relative_sink` and `recommended_yaml`,
32
+ confidence/evidence locators, `impact: "high"`, `requires_approval: true`,
33
+ `autopilot_eligible: false`, and one decision whose allowed responses are exactly
34
+ `["accept", "edit", "skip"]`.