@wrenai/genbi 0.0.4 → 0.0.5
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.
- package/README.md +64 -2
- package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
- package/dist/assets/index-A_Wrq7Ey.css +1 -0
- package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
- package/dist/index.html +2 -2
- package/dist-server/harness/bundle/schema.d.ts +38 -0
- package/dist-server/harness/bundle/schema.js +18 -10
- package/dist-server/harness/bundle/version.js +1 -1
- package/dist-server/harness/cli-args.d.ts +10 -2
- package/dist-server/harness/cli-args.js +24 -8
- package/dist-server/harness/cli.js +75 -9
- package/dist-server/harness/compile/cache.js +4 -4
- package/dist-server/harness/compile/compose-profile.d.ts +51 -14
- package/dist-server/harness/compile/compose-profile.js +85 -19
- package/dist-server/harness/compile/context-loader.d.ts +56 -0
- package/dist-server/harness/compile/context-loader.js +237 -0
- package/dist-server/harness/compile/errors.d.ts +19 -0
- package/dist-server/harness/compile/errors.js +35 -0
- package/dist-server/harness/compile/index.d.ts +4 -3
- package/dist-server/harness/compile/index.js +4 -3
- package/dist-server/harness/compile/pipeline.d.ts +15 -7
- package/dist-server/harness/compile/pipeline.js +62 -14
- package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
- package/dist-server/harness/compile/resolve-binary.js +3 -3
- package/dist-server/harness/compile/types.d.ts +29 -0
- package/dist-server/harness/compile/warble-identity.d.ts +11 -0
- package/dist-server/harness/compile/warble-identity.js +13 -0
- package/dist-server/harness/components/ai-step.d.ts +4 -0
- package/dist-server/harness/components/ai-step.js +40 -0
- package/dist-server/harness/components/broker.d.ts +60 -0
- package/dist-server/harness/components/broker.js +117 -0
- package/dist-server/harness/components/capability-card.d.ts +98 -0
- package/dist-server/harness/components/capability-card.js +169 -0
- package/dist-server/harness/components/context.d.ts +2 -0
- package/dist-server/harness/components/context.js +30 -0
- package/dist-server/harness/components/display.d.ts +6 -0
- package/dist-server/harness/components/display.js +29 -0
- package/dist-server/harness/components/egress-judge.d.ts +12 -0
- package/dist-server/harness/components/egress-judge.js +27 -0
- package/dist-server/harness/components/egress.d.ts +142 -0
- package/dist-server/harness/components/egress.js +469 -0
- package/dist-server/harness/components/in-process.d.ts +7 -0
- package/dist-server/harness/components/in-process.js +245 -0
- package/dist-server/harness/components/normalize.d.ts +35 -0
- package/dist-server/harness/components/normalize.js +245 -0
- package/dist-server/harness/components/plan.d.ts +31 -0
- package/dist-server/harness/components/plan.js +184 -0
- package/dist-server/harness/components/report.d.ts +207 -0
- package/dist-server/harness/components/report.js +309 -0
- package/dist-server/harness/components/runner.d.ts +193 -0
- package/dist-server/harness/components/runner.js +492 -0
- package/dist-server/harness/components/semantic-guards.d.ts +20 -0
- package/dist-server/harness/components/semantic-guards.js +42 -0
- package/dist-server/harness/components/terminal-json.d.ts +18 -0
- package/dist-server/harness/components/terminal-json.js +82 -0
- package/dist-server/harness/components/usage.d.ts +14 -0
- package/dist-server/harness/components/usage.js +19 -0
- package/dist-server/harness/components/wren-access.d.ts +29 -0
- package/dist-server/harness/components/wren-access.js +233 -0
- package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
- package/dist-server/harness/components/zone-dry-run.js +107 -0
- package/dist-server/harness/components/zone-gate.d.ts +76 -0
- package/dist-server/harness/components/zone-gate.js +144 -0
- package/dist-server/harness/events/index.d.ts +1 -1
- package/dist-server/harness/events/types.d.ts +52 -0
- package/dist-server/harness/index.d.ts +9 -2
- package/dist-server/harness/index.js +5 -1
- package/dist-server/harness/loop/executor.d.ts +1 -0
- package/dist-server/harness/loop/executor.js +37 -15
- package/dist-server/harness/npm-package-resolve.d.ts +2 -0
- package/dist-server/harness/npm-package-resolve.js +16 -4
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
- package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
- package/dist-server/harness/providers/adapters/openai.js +6 -0
- package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
- package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
- package/dist-server/harness/providers/binding.d.ts +45 -4
- package/dist-server/harness/providers/binding.js +44 -8
- package/dist-server/harness/providers/index.d.ts +9 -3
- package/dist-server/harness/providers/index.js +10 -3
- package/dist-server/harness/providers/zone.d.ts +96 -0
- package/dist-server/harness/providers/zone.js +112 -0
- package/dist-server/harness/render/answering-query.d.ts +29 -0
- package/dist-server/harness/render/answering-query.js +62 -0
- package/dist-server/harness/render/envelope.d.ts +6 -0
- package/dist-server/harness/render/envelope.js +10 -3
- package/dist-server/harness/route/adapter-spec.d.ts +8 -9
- package/dist-server/harness/route/adapter-spec.js +13 -14
- package/dist-server/harness/route/codex-ask-events.js +2 -1
- package/dist-server/harness/route/codex-ask.d.ts +4 -0
- package/dist-server/harness/route/codex-ask.js +69 -30
- package/dist-server/harness/route/codex-host-query.d.ts +52 -0
- package/dist-server/harness/route/codex-host-query.js +191 -0
- package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
- package/dist-server/harness/route/codex-local-manifest.js +96 -15
- package/dist-server/harness/route/codex-wren-proxy.d.ts +33 -0
- package/dist-server/harness/route/codex-wren-proxy.js +227 -0
- package/dist-server/harness/route/describe.js +45 -6
- package/dist-server/harness/route/in-process.d.ts +22 -1
- package/dist-server/harness/route/in-process.js +54 -4
- package/dist-server/harness/route/route.js +5 -2
- package/dist-server/harness/route/types.d.ts +30 -1
- package/dist-server/harness/session/run.js +30 -10
- package/dist-server/harness/setup/runner.d.ts +2 -0
- package/dist-server/harness/setup/runner.js +38 -17
- package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
- package/dist-server/harness/setup/yaml-scalar.js +62 -0
- package/dist-server/server/adopt.js +1 -17
- package/dist-server/server/app.d.ts +1 -0
- package/dist-server/server/app.js +163 -14
- package/dist-server/server/auth-choice.d.ts +13 -1
- package/dist-server/server/auth-choice.js +66 -1
- package/dist-server/server/bin.js +177 -25
- package/dist-server/server/codex-local-grounding.d.ts +18 -0
- package/dist-server/server/codex-local-grounding.js +92 -0
- package/dist-server/server/codex-native-session.d.ts +25 -0
- package/dist-server/server/codex-native-session.js +1 -0
- package/dist-server/server/codex-runtime-composition.d.ts +34 -0
- package/dist-server/server/codex-runtime-composition.js +250 -0
- package/dist-server/server/codex-structured-ask.d.ts +23 -0
- package/dist-server/server/codex-structured-ask.js +102 -0
- package/dist-server/server/conn-config.js +4 -16
- package/dist-server/server/conversation-socket.d.ts +16 -0
- package/dist-server/server/conversation-socket.js +65 -0
- package/dist-server/server/db.d.ts +46 -0
- package/dist-server/server/db.js +88 -9
- package/dist-server/server/env-detect.d.ts +6 -0
- package/dist-server/server/env-detect.js +7 -0
- package/dist-server/server/fold.d.ts +22 -4
- package/dist-server/server/fold.js +37 -5
- package/dist-server/server/harness.d.ts +2 -2
- package/dist-server/server/harness.js +33 -7
- package/dist-server/server/interactive-terminal.d.ts +10 -6
- package/dist-server/server/interactive-terminal.js +33 -8
- package/dist-server/server/managed-wren-runtime.d.ts +116 -0
- package/dist-server/server/managed-wren-runtime.js +670 -0
- package/dist-server/server/native-artifacts.d.ts +23 -7
- package/dist-server/server/native-artifacts.js +43 -12
- package/dist-server/server/native-component-context.d.ts +19 -0
- package/dist-server/server/native-component-context.js +76 -0
- package/dist-server/server/native-component-preparation.d.ts +20 -0
- package/dist-server/server/native-component-preparation.js +129 -0
- package/dist-server/server/native-component-runtime.d.ts +36 -0
- package/dist-server/server/native-component-runtime.js +92 -0
- package/dist-server/server/native-components.d.ts +84 -0
- package/dist-server/server/native-components.js +160 -0
- package/dist-server/server/native-dispatch-process.d.ts +8 -0
- package/dist-server/server/native-dispatch-process.js +65 -0
- package/dist-server/server/native-runtime-spec.d.ts +89 -0
- package/dist-server/server/native-runtime-spec.js +169 -0
- package/dist-server/server/native-sessions.d.ts +172 -19
- package/dist-server/server/native-sessions.js +839 -244
- package/dist-server/server/native-shutdown.d.ts +6 -0
- package/dist-server/server/native-shutdown.js +28 -0
- package/dist-server/server/native-wren-home.d.ts +18 -0
- package/dist-server/server/native-wren-home.js +262 -0
- package/dist-server/server/node-pty-host.d.ts +2 -1
- package/dist-server/server/node-pty-host.js +3 -2
- package/dist-server/server/profile-registry.d.ts +139 -0
- package/dist-server/server/profile-registry.js +620 -0
- package/dist-server/server/runtime-binding.d.ts +4 -1
- package/dist-server/server/runtime-binding.js +50 -2
- package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
- package/dist-server/server/runtime-host/claude-component-step.js +186 -0
- package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
- package/dist-server/server/runtime-host/codex-app-server.js +239 -0
- package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
- package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
- package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
- package/dist-server/server/runtime-host/codex-component-step.js +308 -0
- package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
- package/dist-server/server/runtime-host/codex-conversation.js +295 -0
- package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
- package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
- package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
- package/dist-server/server/runtime-host/codex-events.js +66 -0
- package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-policy.js +151 -0
- package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
- package/dist-server/server/runtime-host/codex-process.js +96 -0
- package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
- package/dist-server/server/runtime-host/codex-rpc.js +182 -0
- package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
- package/dist-server/server/runtime-host/codex-session.js +492 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
- package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
- package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
- package/dist-server/server/runtime-host/codex-terminal.js +120 -0
- package/dist-server/server/runtime-host/index.d.ts +5 -0
- package/dist-server/server/runtime-host/index.js +3 -0
- package/dist-server/server/runtime-host/local.d.ts +29 -0
- package/dist-server/server/runtime-host/local.js +90 -0
- package/dist-server/server/runtime-host/policy.d.ts +8 -0
- package/dist-server/server/runtime-host/policy.js +78 -0
- package/dist-server/server/runtime-host/types.d.ts +52 -0
- package/dist-server/server/runtime-host/types.js +62 -0
- package/dist-server/server/structured-query-evidence.d.ts +7 -0
- package/dist-server/server/structured-query-evidence.js +47 -0
- package/dist-server/server/structured-runtime.d.ts +52 -0
- package/dist-server/server/structured-runtime.js +130 -0
- package/dist-server/server/structured-scope.d.ts +4 -0
- package/dist-server/server/structured-scope.js +12 -0
- package/dist-server/server/turn.d.ts +6 -1
- package/dist-server/server/turn.js +82 -25
- package/dist-server/server/wire-types.d.ts +67 -3
- package/dist-server/server/wren-profiles.js +1 -1
- package/managed-wren/README.md +60 -0
- package/managed-wren/dependency-wheels.json +282 -0
- package/managed-wren/manifest.json +373 -0
- package/managed-wren/release-inputs.json +45 -0
- package/managed-wren/runtime-tree.cjs +115 -0
- package/managed-wren/source-inputs.json +40 -0
- package/package.json +15 -6
- package/profiles/genbi-default/context/binding.yml +17 -7
- package/profiles/genbi-default/context/context.json +146 -0
- package/profiles/genbi-default/ir.golden.json +39 -43
- package/profiles/genbi-default/profile.yml +31 -0
- package/profiles/genbi-enrich-context/context/binding.yml +14 -3
- package/profiles/genbi-enrich-context/context/context.json +146 -0
- package/profiles/genbi-enrich-context/ir.golden.json +4 -5
- package/profiles/genbi-monitor/context/binding.yml +13 -5
- package/profiles/genbi-monitor/context/context.json +146 -0
- package/profiles/genbi-monitor/ir.golden.json +13 -7
- package/profiles/genbi-report/context/binding.yml +19 -0
- package/profiles/genbi-report/context/context.json +223 -0
- package/profiles/genbi-report/ir.golden.json +328 -0
- package/profiles/genbi-report/profile.yml +38 -0
- package/profiles/genbi-setup/ir.golden.json +3 -1
- package/dist/assets/index-Xs4q7pNo.css +0 -1
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
# Coarse context binding: the whole v5-jaffle semantic layer
|
|
2
|
-
# builds a real MdlContext over the bound project and evaluates context_precondition predicates
|
|
3
|
-
# against it — it does introspect MDL. The binding stays "coarse" in a different sense: it names the
|
|
4
|
-
# whole project, not a specific metric/grain.
|
|
1
|
+
# Coarse context binding: the whole v5-jaffle semantic layer, bound as a PREPARED document.
|
|
5
2
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
3
|
+
# `kind: prepared` means Warble does not read the semantic layer itself — it reads the JSON document
|
|
4
|
+
# `document:` names, which WrenAI's own `wren-context-loader` generator produced from the project.
|
|
5
|
+
# Warble therefore needs no knowledge of MDL, and the projection Wren hands it is the one Wren
|
|
6
|
+
# controls. The binding stays "coarse" in the original sense: it names the whole project, not a
|
|
7
|
+
# specific metric/grain.
|
|
8
|
+
#
|
|
9
|
+
# `project:` is the layer's IDENTITY, not a path Warble reads, and never the document's path — it is
|
|
10
|
+
# what the compiled prompts call the project the agent is working on. `document:` is the separate
|
|
11
|
+
# field carrying the file. Both resolve relative to this Warble project's own root (the profile
|
|
12
|
+
# directory), not relative to this file.
|
|
13
|
+
#
|
|
14
|
+
# The host rewrites this `project:` line to the user's own wren project at bind time and regenerates
|
|
15
|
+
# `document:`'s file in place; the committed values pin this repo's own v5 example so the profile
|
|
16
|
+
# compiles standalone for CI/dev. See MAINTAINING.md for how to regenerate the committed document.
|
|
17
|
+
kind: prepared
|
|
9
18
|
project: ../../../../examples/v5-jaffle
|
|
19
|
+
document: context/context.json
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
{
|
|
2
|
+
"context_version": 2,
|
|
3
|
+
"parseable": true,
|
|
4
|
+
"metrics": [
|
|
5
|
+
{
|
|
6
|
+
"name": "total_revenue",
|
|
7
|
+
"owner": "order_metrics",
|
|
8
|
+
"declared": true,
|
|
9
|
+
"additivity": "additive"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "order_count",
|
|
13
|
+
"owner": "order_metrics",
|
|
14
|
+
"declared": true,
|
|
15
|
+
"additivity": "additive"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "id",
|
|
19
|
+
"owner": "customers",
|
|
20
|
+
"declared": false,
|
|
21
|
+
"additivity": null
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "id",
|
|
25
|
+
"owner": "orders",
|
|
26
|
+
"declared": false,
|
|
27
|
+
"additivity": null
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "customer_id",
|
|
31
|
+
"owner": "orders",
|
|
32
|
+
"declared": false,
|
|
33
|
+
"additivity": null
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "amount",
|
|
37
|
+
"owner": "orders",
|
|
38
|
+
"declared": false,
|
|
39
|
+
"additivity": null
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"dimensions": [
|
|
43
|
+
{
|
|
44
|
+
"name": "customer_id",
|
|
45
|
+
"owner": "order_metrics",
|
|
46
|
+
"is_temporal": false
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "name",
|
|
50
|
+
"owner": "customers",
|
|
51
|
+
"is_temporal": false
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "order_date",
|
|
55
|
+
"owner": "orders",
|
|
56
|
+
"is_temporal": true
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"models": [
|
|
60
|
+
{
|
|
61
|
+
"name": "customers",
|
|
62
|
+
"has_timestamp": false,
|
|
63
|
+
"columns": [
|
|
64
|
+
"id",
|
|
65
|
+
"name"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "orders",
|
|
70
|
+
"has_timestamp": true,
|
|
71
|
+
"columns": [
|
|
72
|
+
"id",
|
|
73
|
+
"customer_id",
|
|
74
|
+
"order_date",
|
|
75
|
+
"amount"
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"lineage": {
|
|
80
|
+
"nodes": [
|
|
81
|
+
{
|
|
82
|
+
"id": "model:customers",
|
|
83
|
+
"kind": "model"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "model:orders",
|
|
87
|
+
"kind": "model"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "rel:orders_customer",
|
|
91
|
+
"kind": "relationship"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "cube:order_metrics",
|
|
95
|
+
"kind": "cube"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"id": "metric:order_metrics.total_revenue",
|
|
99
|
+
"kind": "metric"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "metric:order_metrics.order_count",
|
|
103
|
+
"kind": "metric"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "dim:order_metrics.customer_id",
|
|
107
|
+
"kind": "dimension"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "query:total-revenue",
|
|
111
|
+
"kind": "query"
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"edges": [
|
|
115
|
+
{
|
|
116
|
+
"from": "model:orders",
|
|
117
|
+
"to": "rel:orders_customer"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"from": "model:customers",
|
|
121
|
+
"to": "rel:orders_customer"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"from": "model:orders",
|
|
125
|
+
"to": "cube:order_metrics"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"from": "cube:order_metrics",
|
|
129
|
+
"to": "metric:order_metrics.total_revenue"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"from": "cube:order_metrics",
|
|
133
|
+
"to": "metric:order_metrics.order_count"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"from": "cube:order_metrics",
|
|
137
|
+
"to": "dim:order_metrics.customer_id"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"from": "model:orders",
|
|
141
|
+
"to": "query:total-revenue"
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
"lineage_diagnostics": []
|
|
146
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"borrowed_actions": [
|
|
5
5
|
"introspect"
|
|
6
6
|
],
|
|
7
|
+
"brief": "Data access in this deployment goes through the `wren` CLI. Introspect the semantic layer\nwith `wren context show` (and, where available, `wren cube list`) to read models, columns,\nrelationships, and metrics/cubes — do not assume the schema.",
|
|
7
8
|
"context_binding": {
|
|
8
9
|
"binding_mode": "runtime_selected",
|
|
9
10
|
"project": "../../../../examples/v5-jaffle"
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
}
|
|
15
16
|
],
|
|
16
17
|
"context_requirements": [
|
|
17
|
-
"a
|
|
18
|
+
"a bound semantic context (semantic layer) to introspect"
|
|
18
19
|
],
|
|
19
20
|
"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
21
|
"effect": {
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
},
|
|
24
25
|
"render_blocks": []
|
|
25
26
|
},
|
|
27
|
+
"entrypoint": true,
|
|
26
28
|
"eval": {
|
|
27
29
|
"metrics": [
|
|
28
30
|
"coverage"
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
"consumes": [],
|
|
49
51
|
"name": "summarize_semantics",
|
|
50
52
|
"produces": "semantic_summary",
|
|
51
|
-
"prompt": "You introspect the `v5-jaffle`
|
|
53
|
+
"prompt": "You introspect the bound semantic context `v5-jaffle` (a semantic layer at `../../../../examples/v5-jaffle`)\nand return a structured summary of what it contains — the map the other GenBI components build on.\n\n- Introspect the semantic layer using the bound introspection capability to read the models,\n columns, relationships, and metrics/cubes. This is the `raw_introspect_result` you consume — read\n 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
54
|
"tier": "cheap",
|
|
53
55
|
"when": null
|
|
54
56
|
}
|
|
@@ -63,7 +65,7 @@
|
|
|
63
65
|
],
|
|
64
66
|
"status": "pass"
|
|
65
67
|
},
|
|
66
|
-
"prompt_fragment": "## summarize_semantics\n\nYou introspect the `v5-jaffle`
|
|
68
|
+
"prompt_fragment": "## summarize_semantics\n\nYou introspect the bound semantic context `v5-jaffle` (a semantic layer at `../../../../examples/v5-jaffle`)\nand return a structured summary of what it contains — the map the other GenBI components build on.\n\n- Introspect the semantic layer using the bound introspection capability to read the models,\n columns, relationships, and metrics/cubes. This is the `raw_introspect_result` you consume — read\n 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
69
|
"realization_kind": "skill",
|
|
68
70
|
"required_capabilities": [
|
|
69
71
|
"semantic_introspection",
|
|
@@ -77,6 +79,7 @@
|
|
|
77
79
|
},
|
|
78
80
|
{
|
|
79
81
|
"borrowed_actions": [],
|
|
82
|
+
"brief": "Data access in this deployment goes through the `wren` CLI. If you need to introspect the\nschema, run `wren context show`. Query the semantic layer with `wren -q -o json -s '<SQL>'`,\nwhich returns JSON; object-shaped rows are also valid — preserve their values exactly. Never\nhand-write SQL against raw tables outside the model.\nFor time-series questions, use the requested date range. If none is given, use the full\navailable data range and disclose that choice; never silently pick a recent N-week window.\nDistinguish calendar-relative dates from a window anchored on the latest data date. Preserve\nexplicit calendar-relative requests even if the data is old; do not silently re-anchor them.\nExplain exact date bounds, the date column, week start, timezone if known, and partial periods.\nUse semantic metric definitions where available. Otherwise state the chosen interpretation:\ndistinct ordering customers, first-order customers and cumulative customers are different.\nDo not present synonymous counts as different metrics. Do not invent registration dates or\nmetric meanings absent from context. Name the answer SQL in the terminal definition so that\nlater date-bound checks cannot replace the answering table.",
|
|
80
83
|
"context_binding": {
|
|
81
84
|
"binding_mode": "runtime_selected",
|
|
82
85
|
"project": "../../../../examples/v5-jaffle"
|
|
@@ -87,31 +90,16 @@
|
|
|
87
90
|
}
|
|
88
91
|
],
|
|
89
92
|
"context_requirements": [
|
|
90
|
-
"a
|
|
93
|
+
"a bound semantic context (semantic layer) to query"
|
|
91
94
|
],
|
|
92
95
|
"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
96
|
"effect": {
|
|
94
97
|
"outcome": {
|
|
95
98
|
"kind": "none"
|
|
96
99
|
},
|
|
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
|
-
]
|
|
100
|
+
"render_blocks": []
|
|
114
101
|
},
|
|
102
|
+
"entrypoint": true,
|
|
115
103
|
"eval": {
|
|
116
104
|
"metrics": [
|
|
117
105
|
"execution_accuracy",
|
|
@@ -148,11 +136,14 @@
|
|
|
148
136
|
"id": "answer_query",
|
|
149
137
|
"llm_calls": [
|
|
150
138
|
{
|
|
139
|
+
"capabilities": [
|
|
140
|
+
"llm:cheap"
|
|
141
|
+
],
|
|
151
142
|
"conditional": false,
|
|
152
143
|
"consumes": [],
|
|
153
144
|
"name": "resolve_intent",
|
|
154
145
|
"produces": "query_intent",
|
|
155
|
-
"prompt": "You answer a single data question over the `v5-jaffle`
|
|
146
|
+
"prompt": "You answer a single data question over the bound semantic context `v5-jaffle` (a semantic\nlayer at `../../../../examples/v5-jaffle`). This first step resolves the user's question into a concrete query intent.\n\n- Do not call any tool in this step: it declares no data capability. Resolve the question from the\n semantic context you were given; the next step writes and runs the query.\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
147
|
"tier": "cheap",
|
|
157
148
|
"when": null
|
|
158
149
|
},
|
|
@@ -163,7 +154,7 @@
|
|
|
163
154
|
],
|
|
164
155
|
"name": "generate_sql",
|
|
165
156
|
"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
|
|
157
|
+
"prompt": "Given the resolved `query_intent`, write and execute the query through the semantic layer.\n\n- Query ONLY through the bound query capability, which returns structured (JSON) results. 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\": {\"query_id\": \"<the query_id the tool result returned>\"}}\n ```\n Object-shaped rows 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- When the tool result carries a `query_id`, never copy SQL, filters or source tables into\n `definition`: cite `{\"query_id\": …}` only. When it carries none, cite\n `{\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"]}` and nothing else. No shape of\n `definition` has a `filters` key.\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- Your final message is `query_result` as JSON and nothing else: no heading, no sentence before or\n after it, no Markdown fence, no reasoning tags. Every string closed and every bracket matched; it\n must parse as JSON.",
|
|
167
158
|
"tier": "strong",
|
|
168
159
|
"when": null
|
|
169
160
|
},
|
|
@@ -174,7 +165,7 @@
|
|
|
174
165
|
],
|
|
175
166
|
"name": "repair_sql",
|
|
176
167
|
"produces": "repaired_result",
|
|
177
|
-
"prompt": "Repair step — runs ONLY when `query_result` came back with an execution error or an empty/obviously
|
|
168
|
+
"prompt": "Repair step — runs ONLY in one of these cases:\n\n- When `query_result` is `{\"status\": \"error\", \"code\": \"step_failed\", \"reason\":\n \"terminal_unparseable: …\", \"text\": …}`, the previous answer is in `text`; when `query_result`\n is otherwise not valid JSON (prose around it, an unterminated string, a stray reasoning tag),\n the previous answer is that raw text. Re-emit that SAME answer as one JSON object in the canonical\n shape below, citing its query by its `query_id` (or, when its tool result carried none,\n `{\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"]}`).\n Run no new query, and put nothing else in the message.\n- `query_result` came back with an execution error or an empty/obviously wrong result.\n\nIf the previous step succeeded with a valid JSON, sensible result, do nothing and pass it through.\n\n- For an execution failure (the second case above): diagnose the failure from the error text (unknown column, bad join, type mismatch, wrong grain),\n fix the SQL, and re-run it through the bound query capability. 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\": {\"query_id\": \"<the query_id the tool result returned>\"}}\n ```\n Object-shaped rows 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).\n When the tool result carries a `query_id`, never copy SQL, filters or source tables into\n `definition`: cite `{\"query_id\": …}` only. When it carries none, cite\n `{\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"]}` and nothing else. No shape of\n `definition` has a `filters` key.\n Your final message is the JSON object (or the refusal object) and nothing else: no heading, no\n sentence before or after it, no Markdown fence, no reasoning tags. Every string closed and every\n bracket matched; it must parse as JSON.",
|
|
178
169
|
"tier": "strong",
|
|
179
170
|
"when": {
|
|
180
171
|
"guard": "on_failure",
|
|
@@ -192,7 +183,7 @@
|
|
|
192
183
|
],
|
|
193
184
|
"status": "pass"
|
|
194
185
|
},
|
|
195
|
-
"prompt_fragment": "## resolve_intent\n\nYou answer a single data question over the `v5-jaffle`
|
|
186
|
+
"prompt_fragment": "## resolve_intent\n\nYou answer a single data question over the bound semantic context `v5-jaffle` (a semantic\nlayer at `../../../../examples/v5-jaffle`). This first step resolves the user's question into a concrete query intent.\n\n- Do not call any tool in this step: it declares no data capability. Resolve the question from the\n semantic context you were given; the next step writes and runs the query.\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 bound query capability, which returns structured (JSON) results. 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\": {\"query_id\": \"<the query_id the tool result returned>\"}}\n ```\n Object-shaped rows 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- When the tool result carries a `query_id`, never copy SQL, filters or source tables into\n `definition`: cite `{\"query_id\": …}` only. When it carries none, cite\n `{\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"]}` and nothing else. No shape of\n `definition` has a `filters` key.\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- Your final message is `query_result` as JSON and nothing else: no heading, no sentence before or\n after it, no Markdown fence, no reasoning tags. Every string closed and every bracket matched; it\n must parse as JSON.\n\n## repair_sql\n\nRepair step — runs ONLY in one of these cases:\n\n- When `query_result` is `{\"status\": \"error\", \"code\": \"step_failed\", \"reason\":\n \"terminal_unparseable: …\", \"text\": …}`, the previous answer is in `text`; when `query_result`\n is otherwise not valid JSON (prose around it, an unterminated string, a stray reasoning tag),\n the previous answer is that raw text. Re-emit that SAME answer as one JSON object in the canonical\n shape below, citing its query by its `query_id` (or, when its tool result carried none,\n `{\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"]}`).\n Run no new query, and put nothing else in the message.\n- `query_result` came back with an execution error or an empty/obviously wrong result.\n\nIf the previous step succeeded with a valid JSON, sensible result, do nothing and pass it through.\n\n- For an execution failure (the second case above): diagnose the failure from the error text (unknown column, bad join, type mismatch, wrong grain),\n fix the SQL, and re-run it through the bound query capability. 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\": {\"query_id\": \"<the query_id the tool result returned>\"}}\n ```\n Object-shaped rows 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).\n When the tool result carries a `query_id`, never copy SQL, filters or source tables into\n `definition`: cite `{\"query_id\": …}` only. When it carries none, cite\n `{\"sql\": \"<the exact SQL you ran>\", \"source_tables\": [\"...\"]}` and nothing else. No shape of\n `definition` has a `filters` key.\n Your final message is the JSON object (or the refusal object) and nothing else: no heading, no\n sentence before or after it, no Markdown fence, no reasoning tags. Every string closed and every\n bracket matched; it must parse as JSON.",
|
|
196
187
|
"realization_kind": "skill",
|
|
197
188
|
"required_capabilities": [
|
|
198
189
|
"sql_execution:read_only",
|
|
@@ -211,15 +202,16 @@
|
|
|
211
202
|
"topic_default": "overview"
|
|
212
203
|
},
|
|
213
204
|
"borrowed_actions": [],
|
|
205
|
+
"brief": "Data access in this deployment goes through the `wren` CLI. Discover the schema at query\ntime with `wren context show`, `wren cube list`, and `wren cube describe <cube>` — do not\nassume it. Run each panel query with `wren -q -o json -s '<SQL>'`; every query goes through\n`wren`, never hand-written SQL against raw tables outside the model.",
|
|
214
206
|
"context_binding": {
|
|
215
207
|
"binding_mode": "runtime_selected",
|
|
216
208
|
"project": "../../../../examples/v5-jaffle"
|
|
217
209
|
},
|
|
218
210
|
"context_precondition": [],
|
|
219
211
|
"context_requirements": [
|
|
220
|
-
"a
|
|
212
|
+
"a bound semantic context (semantic layer) to build dashboards over"
|
|
221
213
|
],
|
|
222
|
-
"description": "Build a multi-panel dashboard on a topic: plan which
|
|
214
|
+
"description": "Build a multi-panel dashboard on a topic: plan which panel questions answer it, obtain a verified result for each panel through the profile's bound answer behavior, 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
215
|
"effect": {
|
|
224
216
|
"outcome": {
|
|
225
217
|
"kind": "none"
|
|
@@ -252,7 +244,7 @@
|
|
|
252
244
|
},
|
|
253
245
|
{
|
|
254
246
|
"fields": {
|
|
255
|
-
"filters": "string[]",
|
|
247
|
+
"filters": "string[]?",
|
|
256
248
|
"source_tables": "string[]",
|
|
257
249
|
"sql": "string"
|
|
258
250
|
},
|
|
@@ -260,6 +252,7 @@
|
|
|
260
252
|
}
|
|
261
253
|
]
|
|
262
254
|
},
|
|
255
|
+
"entrypoint": true,
|
|
263
256
|
"eval": {
|
|
264
257
|
"metrics": [
|
|
265
258
|
"panel_validity",
|
|
@@ -291,18 +284,24 @@
|
|
|
291
284
|
"consumes": [],
|
|
292
285
|
"name": "plan_dashboard",
|
|
293
286
|
"produces": "dashboard_plan",
|
|
294
|
-
"prompt": "You build data dashboards over the `v5-jaffle`
|
|
287
|
+
"prompt": "You build data dashboards over the bound semantic context `v5-jaffle` (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- Decide which business questions 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, give its title, panel type (kpi_card | table | chart),\n and one self-contained natural-language data question whose verified answer will populate it.\n Do not inspect the schema, write a query, or invent data in this step; the bound answer behavior\n resolves each panel question against its own semantic context and query authority.",
|
|
295
288
|
"tier": "strong",
|
|
296
289
|
"when": null
|
|
297
290
|
},
|
|
298
291
|
{
|
|
292
|
+
"component_calls": [
|
|
293
|
+
{
|
|
294
|
+
"alias": "answer",
|
|
295
|
+
"component": "answer_query"
|
|
296
|
+
}
|
|
297
|
+
],
|
|
299
298
|
"conditional": false,
|
|
300
299
|
"consumes": [
|
|
301
300
|
"dashboard_plan"
|
|
302
301
|
],
|
|
303
302
|
"name": "compose_layout",
|
|
304
303
|
"produces": "dashboard",
|
|
305
|
-
"prompt": "Given the `dashboard_plan`,
|
|
304
|
+
"prompt": "Given the `dashboard_plan`, obtain each panel's verified answer and compose the dashboard.\n\n- For every planned panel, call the logical `answer` alias once with a concise request to answer\n that panel's natural-language data question. Include the panel title and type in the optional\n structured input. Call the same alias again for every additional panel; do not combine unrelated\n panels into one request merely to avoid repeated calls.\n- Accept a panel result only when the call returns `status: \"ok\"`, `output.kind: \"value\"`, and a\n value containing `verified: true`, `columns`, `rows`, `summary`, and `definition`. Refuse the\n dashboard rather than using a refused, failed, unverified, malformed, or placeholder result.\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. Panels reach\n this step with SQL provenance; a host that issues `query_id`s resolves them first. Derive the\n dashboard's definition block from the accepted panel definitions: copy `sql` and `source_tables`\n when the panel carries them, include `filters` only if the panel carries them, and never invent\n provenance.\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 the accepted 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
305
|
"tier": "cheap",
|
|
307
306
|
"when": null
|
|
308
307
|
}
|
|
@@ -318,16 +317,15 @@
|
|
|
318
317
|
"checks": [],
|
|
319
318
|
"status": "pass"
|
|
320
319
|
},
|
|
321
|
-
"prompt_fragment": "## plan_dashboard\n\nYou build data dashboards over the `v5-jaffle`
|
|
320
|
+
"prompt_fragment": "## plan_dashboard\n\nYou build data dashboards over the bound semantic context `v5-jaffle` (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- Decide which business questions 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, give its title, panel type (kpi_card | table | chart),\n and one self-contained natural-language data question whose verified answer will populate it.\n Do not inspect the schema, write a query, or invent data in this step; the bound answer behavior\n resolves each panel question against its own semantic context and query authority.\n\n## compose_layout\n\nGiven the `dashboard_plan`, obtain each panel's verified answer and compose the dashboard.\n\n- For every planned panel, call the logical `answer` alias once with a concise request to answer\n that panel's natural-language data question. Include the panel title and type in the optional\n structured input. Call the same alias again for every additional panel; do not combine unrelated\n panels into one request merely to avoid repeated calls.\n- Accept a panel result only when the call returns `status: \"ok\"`, `output.kind: \"value\"`, and a\n value containing `verified: true`, `columns`, `rows`, `summary`, and `definition`. Refuse the\n dashboard rather than using a refused, failed, unverified, malformed, or placeholder result.\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. Panels reach\n this step with SQL provenance; a host that issues `query_id`s resolves them first. Derive the\n dashboard's definition block from the accepted panel definitions: copy `sql` and `source_tables`\n when the panel carries them, include `filters` only if the panel carries them, and never invent\n provenance.\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 the accepted 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
321
|
"realization_kind": "skill",
|
|
323
322
|
"required_capabilities": [
|
|
324
|
-
"sql_execution:read_only",
|
|
325
|
-
"genbi_build",
|
|
326
323
|
"render_contract",
|
|
327
324
|
"artifact_write",
|
|
328
325
|
"llm:per_step_tier",
|
|
329
326
|
"llm:strong",
|
|
330
|
-
"llm:cheap"
|
|
327
|
+
"llm:cheap",
|
|
328
|
+
"component_invocation"
|
|
331
329
|
],
|
|
332
330
|
"trigger": {
|
|
333
331
|
"kind": "one_shot"
|
|
@@ -337,13 +335,14 @@
|
|
|
337
335
|
},
|
|
338
336
|
{
|
|
339
337
|
"borrowed_actions": [],
|
|
338
|
+
"brief": "Data access in this deployment goes through the `wren` CLI. Introspect the layer as needed\nwith `wren context show`. Run the decomposition queries with `wren -q -o json -s '<SQL>'`.",
|
|
340
339
|
"context_binding": {
|
|
341
340
|
"binding_mode": "runtime_selected",
|
|
342
341
|
"project": "../../../../examples/v5-jaffle"
|
|
343
342
|
},
|
|
344
343
|
"context_precondition": [],
|
|
345
344
|
"context_requirements": [
|
|
346
|
-
"a
|
|
345
|
+
"a bound semantic context with an additive metric plus a time dimension and a groupable dimension"
|
|
347
346
|
],
|
|
348
347
|
"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
348
|
"effect": {
|
|
@@ -360,6 +359,7 @@
|
|
|
360
359
|
}
|
|
361
360
|
]
|
|
362
361
|
},
|
|
362
|
+
"entrypoint": true,
|
|
363
363
|
"eval": {
|
|
364
364
|
"metrics": [
|
|
365
365
|
"driver_correctness",
|
|
@@ -400,7 +400,7 @@
|
|
|
400
400
|
"consumes": [],
|
|
401
401
|
"name": "plan_decomposition",
|
|
402
402
|
"produces": "decomposition_plan",
|
|
403
|
-
"prompt": "You explain why a metric changed over the `v5-jaffle`
|
|
403
|
+
"prompt": "You explain why a metric changed over the bound semantic context `v5-jaffle` (a semantic\nlayer at `../../../../examples/v5-jaffle`), by planning how to decompose the change.\n\n- Introspect the layer as needed, using the bound introspection capability, to find the metric, its\n time dimension, and 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
404
|
"tier": "strong",
|
|
405
405
|
"when": null
|
|
406
406
|
},
|
|
@@ -411,7 +411,7 @@
|
|
|
411
411
|
],
|
|
412
412
|
"name": "synthesize_drivers",
|
|
413
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
|
|
414
|
+
"prompt": "Given the `decomposition_plan`, quantify the change and synthesize the drivers into an explanation.\n\n- Run the decomposition queries through the bound query capability: compute the metric for each\n period and the per-dimension contribution to the delta. Rank contributors by the size of their\n 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
415
|
"tier": "strong",
|
|
416
416
|
"when": null
|
|
417
417
|
}
|
|
@@ -421,7 +421,7 @@
|
|
|
421
421
|
"checks": [],
|
|
422
422
|
"status": "pass"
|
|
423
423
|
},
|
|
424
|
-
"prompt_fragment": "## plan_decomposition\n\nYou explain why a metric changed over the `v5-jaffle`
|
|
424
|
+
"prompt_fragment": "## plan_decomposition\n\nYou explain why a metric changed over the bound semantic context `v5-jaffle` (a semantic\nlayer at `../../../../examples/v5-jaffle`), by planning how to decompose the change.\n\n- Introspect the layer as needed, using the bound introspection capability, to find the metric, its\n time dimension, and 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 bound query capability: compute the metric for each\n period and the per-dimension contribution to the delta. Rank contributors by the size of their\n 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
425
|
"realization_kind": "skill",
|
|
426
426
|
"required_capabilities": [
|
|
427
427
|
"sql_execution:read_only",
|
|
@@ -456,10 +456,6 @@
|
|
|
456
456
|
}
|
|
457
457
|
],
|
|
458
458
|
"lineage": {
|
|
459
|
-
"consumers": {
|
|
460
|
-
"dashboards": 0,
|
|
461
|
-
"queries": 1
|
|
462
|
-
},
|
|
463
459
|
"edges": 7,
|
|
464
460
|
"nodes": 8,
|
|
465
461
|
"resolvable": true
|
|
@@ -502,5 +498,5 @@
|
|
|
502
498
|
}
|
|
503
499
|
},
|
|
504
500
|
"profile": "genbi-default",
|
|
505
|
-
"warble_ir_version": "0.
|
|
501
|
+
"warble_ir_version": "0.9"
|
|
506
502
|
}
|
|
@@ -10,7 +10,38 @@ context:
|
|
|
10
10
|
project: ./context/binding.yml
|
|
11
11
|
|
|
12
12
|
components:
|
|
13
|
+
# Each mount's `brief` carries this binding's concrete data-access framing — the wren CLI
|
|
14
|
+
# invocations the underlying Hub component prompts used to name directly before they were
|
|
15
|
+
# neutralized. It replaces the component's own `brief` wholesale and is assembled into every
|
|
16
|
+
# step's system prompt for that component (see Warble's docs/spec/authoring.md, "brief").
|
|
13
17
|
- use: explore_model
|
|
18
|
+
brief: |
|
|
19
|
+
Data access in this deployment goes through the `wren` CLI. Introspect the semantic layer
|
|
20
|
+
with `wren context show` (and, where available, `wren cube list`) to read models, columns,
|
|
21
|
+
relationships, and metrics/cubes — do not assume the schema.
|
|
14
22
|
- use: answer_query
|
|
23
|
+
brief: |
|
|
24
|
+
Data access in this deployment goes through the `wren` CLI. If you need to introspect the
|
|
25
|
+
schema, run `wren context show`. Query the semantic layer with `wren -q -o json -s '<SQL>'`,
|
|
26
|
+
which returns JSON; object-shaped rows are also valid — preserve their values exactly. Never
|
|
27
|
+
hand-write SQL against raw tables outside the model.
|
|
28
|
+
For time-series questions, use the requested date range. If none is given, use the full
|
|
29
|
+
available data range and disclose that choice; never silently pick a recent N-week window.
|
|
30
|
+
Distinguish calendar-relative dates from a window anchored on the latest data date. Preserve
|
|
31
|
+
explicit calendar-relative requests even if the data is old; do not silently re-anchor them.
|
|
32
|
+
Explain exact date bounds, the date column, week start, timezone if known, and partial periods.
|
|
33
|
+
Use semantic metric definitions where available. Otherwise state the chosen interpretation:
|
|
34
|
+
distinct ordering customers, first-order customers and cumulative customers are different.
|
|
35
|
+
Do not present synonymous counts as different metrics. Do not invent registration dates or
|
|
36
|
+
metric meanings absent from context. Name the answer SQL in the terminal definition so that
|
|
37
|
+
later date-bound checks cannot replace the answering table.
|
|
15
38
|
- use: generate_dashboard
|
|
39
|
+
brief: |
|
|
40
|
+
Data access in this deployment goes through the `wren` CLI. Discover the schema at query
|
|
41
|
+
time with `wren context show`, `wren cube list`, and `wren cube describe <cube>` — do not
|
|
42
|
+
assume it. Run each panel query with `wren -q -o json -s '<SQL>'`; every query goes through
|
|
43
|
+
`wren`, never hand-written SQL against raw tables outside the model.
|
|
16
44
|
- use: explain_change
|
|
45
|
+
brief: |
|
|
46
|
+
Data access in this deployment goes through the `wren` CLI. Introspect the layer as needed
|
|
47
|
+
with `wren context show`. Run the decomposition queries with `wren -q -o json -s '<SQL>'`.
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
# A pinned, existing semantic project
|
|
2
|
-
#
|
|
3
|
-
#
|
|
1
|
+
# A pinned, existing semantic project, bound as a PREPARED document: `kind: prepared` means Warble
|
|
2
|
+
# reads the JSON document `document:` names — produced by WrenAI's own `wren-context-loader`
|
|
3
|
+
# generator — rather than introspecting the project's MDL itself.
|
|
4
|
+
#
|
|
5
|
+
# `project:` is the layer's IDENTITY, never the document's path; `document:` carries the file. Both
|
|
6
|
+
# resolve relative to this Warble project's own root (the profile directory), not relative to this
|
|
7
|
+
# file.
|
|
8
|
+
#
|
|
9
|
+
# Runtime hosts replace this fixture binding with the project selected at bind time (rewriting
|
|
10
|
+
# `project:` and regenerating `document:`'s file in place) and must present a successful
|
|
11
|
+
# context-build proof before starting a run. See MAINTAINING.md for how to regenerate the committed
|
|
12
|
+
# document.
|
|
13
|
+
kind: prepared
|
|
4
14
|
project: ../../../../examples/v5-jaffle
|
|
15
|
+
document: context/context.json
|