feat(wren): GenBI app build & deploy — semantic layer → shareable web app#2348
Conversation
…poser
Slice 01 of the GenBI app build & deploy feature. `wren genbi build <name>
--prompt …` is a pure prompt composer: it prints an authoritative build
instruction (wasm wiring know-how + live project context + the user's
verbatim prompt) to stdout and writes nothing to disk. The agent authors
the app from scratch into apps/<name>/ following the instruction.
- BuildInstructionComposer: pure function; pinned wren-core-wasm version,
CDN-load directive, model/column inventory, snapshot data guidance,
register/verify final steps
- --prompt / --prompt-file / stdin ('-') prompt inputs
- implicit `context build` when target/mdl.json is missing
- behavior tests via CliRunner + scripts/genbi-e2e.sh (installs local CLI
and asserts real CLI behavior end-to-end)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Slice 02 of the GenBI app build & deploy feature. A Wren project can hold multiple GenBI apps, tracked in .wren/apps.yml — the deterministic input contract for deploy. The index is machine-written via `wren genbi register` (never hand-rolled YAML), mirroring the profiles.yml registry pattern. - AppIndex module: load/save/register/remove, status state machine (scaffolded → built → deployed), no secrets ever stored - register requires the app dir to exist on disk; idempotent updates - list shows data mode / status / deploy URL; remove keeps files on disk - behavior tests via CliRunner + e2e harness slice-02 section Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…preview Slice 03 of the GenBI app build & deploy feature. `verify` is the quality gate before deploy: structural checks (index.html present, mdl.json parses and is non-empty, snapshot apps bundle a *.parquet/*.duckdb data asset) with clear failure reasons; success flips index status scaffolded → built. `open` serves a registered app on localhost for visual preview. A browser-based wasm smoke query is deliberately deferred — the verifier stays deterministic and CI-safe. - AppVerifier returns structured pass/fail; status never flips on failure - e2e: incomplete app rejected, completed app passes, `open` curl smoke Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…fy gate Slice 04 of the GenBI app build & deploy feature. One command from a verified app on disk to a shareable Vercel URL. - TokenResolver: 3-tier discovery (env var → merged .env files → project .env); tokens are never accepted as CLI flags and never persisted - DeployProvider protocol + provider registry; Vercel adapter uploads via the v13 REST API (inline base64 files, Authorization header only) - deploy runs verify as preflight and aborts before any upload on failure - preview by default, --prod for production; per-app deploy state (provider, project/org id, last URL, environment) persisted in the index - mocked-transport tests assert request construction (endpoint, auth header, file set, target) and that no secret reaches apps.yml - e2e: token-missing, unknown-provider, and verify-abort error paths Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Slice 05 of the GenBI app build & deploy feature. Second DeployProvider adapter, proving the abstraction: no changes to the deploy command, TokenResolver, or index logic — just a new adapter in the registry. - Cloudflare Pages Direct Upload (ensure project, then create deployment) - CLOUDFLARE_API_TOKEN via the shared 3-tier resolver; account_id from persisted link state or CLOUDFLARE_ACCOUNT_ID with an actionable error - 403 responses surface a Pages:Edit scope hint - mocked-transport tests assert account-scoped endpoint, bearer header, persisted account_id/url; e2e covers token/account-id error paths Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Slice 06 of the GenBI app build & deploy feature. Live mode becomes usable end-to-end while a credential-leaking app can never reach a public URL. - composer live block: endpoint-only connection config, CORS requirement surfaced, hard rule — credentials MUST NEVER be inlined - AppVerifier scans text files for inlined secrets (connection-string passwords, AWS access keys, password/secret/token assignments) and fails with the offending file; runs for every data mode since all GenBI apps ship to public static hosts - live apps don't require a bundled data asset; deploy inherits the gate via its verify preflight - e2e: clean live app passes, secret-bearing app blocked at verify and at deploy Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d & deploy Slice 07 of the GenBI app build & deploy feature. The companion skill that ties the flow together: a user asks for a dashboard in natural language and the agent drives build → author → register → verify → deploy to a URL. - SKILL.md mirrors the skills/ + cli split: the CLI owns the authoritative build instruction and all deterministic state; the skill encodes the workflow, app-name/data-mode resolution, fix-and-re-verify loop, and safety boundaries (no inlined secrets, no tokens on argv, confirm --prod, never hand-edit .wren/apps.yml) - registered in skills/index.json - e2e: validates every quick-ref command against the real CLI and runs the full documented walkthrough to a verified app Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sync the 0.9.0 line from main, whose headline change (#2329) moves the agent skills out of skills/wren-*/ and serves them from the CLI (`wren skills get <name>`), leaving skills/wren/ as the only external discovery stub. Conflict resolution + architecture alignment: - skills/index.json: take main's version (only the `wren` discovery stub; guard test requires names == ["wren"]). - core/wren/src/wren/cli.py: auto-merged — genbi sub-app registration kept alongside main's new docs/ask/cube/utils/skills sub-apps. - Migrate the worktree's wren-genbi-app skill into the CLI-served model: skills/wren-genbi-app/SKILL.md -> core/wren/src/wren/skills_content/genbi-app/SKILL.md (frontmatter name genbi-app, drop version field per served-skill convention). - skills/wren/SKILL.md: list `wren skills get genbi-app` in the stub. - test_skills_cli.py: add genbi-app to ALL_SKILLS. - genbi-e2e.sh: verify the guide via `wren skills get genbi-app` instead of the removed skills/ path. - uv.lock: editable wren version reconciled 0.8.0 -> 0.9.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR introduces the complete GenBI feature for building and deploying LLM-generated web applications from Wren semantic layers. It adds a ChangesGenBI Build & Deployment Feature
Sequence Diagram(s) sequenceDiagram
participant User
participant GenbiCLI
participant Verifier
participant Provider
participant AppIndex
User->>GenbiCLI: wren genbi deploy <name> --provider <p> --prod?
GenbiCLI->>Verifier: verify_app(app_dir, data_mode)
Verifier-->>GenbiCLI: VerifyResult (passed/fail)
GenbiCLI->>Provider: deploy(build_dir, app_name, token, prod, link)
Provider-->>GenbiCLI: Deployment(url, environment, ids)
GenbiCLI->>AppIndex: update_app(name, deployment metadata)
GenbiCLI-->>User: prints deployed URL or error
🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/wren/scripts/genbi-e2e.sh`:
- Around line 161-169: The test currently background-launches the server via the
genbi "open" command and then blindly sleeps 2s (see the genbi open ... &
snippet and OPEN_PID, WORK/open.out, URL variables); replace that sleep with a
bounded readiness loop that repeatedly extracts the URL from WORK/open.out (same
grep used to set URL) and attempts a lightweight HTTP probe (curl -sf) until
success or a configurable timeout (e.g., 30s) with a short sleep interval (e.g.,
0.5–1s) between attempts; on timeout, kill OPEN_PID and fail the test, and on
success continue as before. Ensure you update references to URL after each grep
attempt inside the loop so the probe uses the freshly discovered port.
In `@core/wren/src/wren/genbi/cli.py`:
- Around line 42-63: User-supplied app names can contain path traversal (e.g.,
"../") and are being path-joined directly in
build/register/verify/open_app/deploy, allowing escapes from the project's apps
directory; replace those joins by calling a central resolver (e.g.,
_resolve_app_dir(project_path, name)) that constructs project_apps =
project_path / "apps", resolves the resulting path, verifies it is a child of
project_apps (path.resolve().startswith(project_apps.resolve())), and raises a
typer.BadParameter (or ValueError caught and re-raised as typer.BadParameter)
for invalid or empty names; update build, register, verify, open_app, and deploy
to use _resolve_app_dir(project_path, name) instead of direct joins and ensure
all callers handle the raised error appropriately.
In `@core/wren/src/wren/genbi/index.py`:
- Around line 28-36: load_index currently assumes the YAML file is a mapping and
will crash on malformed `.wren/apps.yml`; wrap the yaml.safe_load call in a
try/except that catches yaml.YAMLError (and other parsing exceptions) and
validate that the returned data is a dict before calling setdefault; if parsing
fails or data is not a mapping, raise a clear, user-actionable ValueError (or a
custom error) that mentions the offending path (use index_path(project_path))
and advises the file is malformed, otherwise proceed to set default
"schema_version" and "apps" and return the dict; keep references to load_index,
index_path, and INDEX_SCHEMA_VERSION when implementing this.
In `@core/wren/src/wren/genbi/providers/cloudflare.py`:
- Around line 92-97: The code currently fabricates a deployment URL with
f"https://{app_name}.pages.dev" when result["url"] is missing; stop this by
removing the fallback and propagate the missing URL instead (e.g., set url =
result.get("url") or None) so upstream can detect/fail on missing data; update
the Deployment construction in the same block (the usage of url, environment,
account_id) and ensure any callers of Deployment (or code that expects a
non-empty url) handle a None/empty url rather than relying on a fabricated
pages.dev address.
- Around line 34-38: The dict comprehension that reads file bytes from build_dir
must skip symlinks and ensure resolved paths stay inside build_dir to prevent
exfiltration; update the comprehension/filter around rglob("*") to only include
entries where p.is_file() and not p.is_symlink() and where p.resolve() is under
build_dir (e.g., use p.resolve().is_relative_to(build_dir) or fall back to a
safe prefix compare of str(p.resolve()) against str(build_dir.resolve()) +
os.sep), then call p.read_bytes() only for those validated paths so
base64.b64encode(...) never reads files outside build_dir.
In `@core/wren/src/wren/genbi/providers/vercel.py`:
- Around line 70-73: The code currently defaults raw_url = data.get("url", "")
which leads to producing "https://" when the URL is missing; update the provider
code that constructs raw_url (the variable raw_url in vercel.py) to validate
presence and format of data["url"] before returning the Deployment: if
data.get("url") is missing or empty, raise an explicit error (e.g.,
ValueError/RuntimeError) or return a clear failure instead of defaulting to "",
and only build the Deployment(url=...) with the https:// prefix when raw_url is
non-empty and does not already start with "http"; ensure this check happens
right before the Deployment(...) call so the code never persists or returns
"https://".
- Around line 30-37: The file-collection loop in vercel.py allows symlink
traversal because path.is_file() and path.read_bytes() follow symlinks; prevent
exfiltration by skipping symlinks or verifying resolved targets are inside the
build_dir. In the for path in sorted(build_dir.rglob("*")) loop (the block that
appends to files), add a check to skip path if path.is_symlink() (or resolve the
path and ensure path.resolve().relative_to(build_dir.resolve()) succeeds inside
a try/except) before calling read_bytes(), so only regular files under build_dir
are read and encoded.
In `@core/wren/src/wren/genbi/verify.py`:
- Around line 68-100: verify_app currently ignores unknown data_mode values; add
an explicit validation of the data_mode parameter (in the verify_app function)
against the supported set (at minimum the existing "snapshot" mode) and treat
any other value as a verification failure: append a clear failure like
"unsupported data_mode: {data_mode}" to failures and return VerifyResult(False,
failures) early. Ensure you reference the same VerifyResult return type and
place the check after the app_dir existence checks (before the existing if
data_mode == "snapshot": block) so unsupported modes are rejected
deterministically.
In `@core/wren/src/wren/skills_content/genbi-app/SKILL.md`:
- Around line 51-55: The sentence in SKILL.md that currently says the build
"writes nothing to disk" conflicts with earlier text that the tool may
implicitly compile target/mdl.json; update the wording to scope the side-effect
(e.g., state that the command performs no writes to the app/index or app bundle
but may implicitly generate/compile target/mdl.json when missing). Edit the
paragraph around the long-prompt instructions to explicitly mention the implicit
target/mdl.json compilation behavior and clarify that only that metadata file
may be created, while no application bundle/app index files are written.
In `@core/wren/tests/unit/test_genbi_deploy.py`:
- Around line 54-57: The test assumes no external dotenv/profile fallbacks but
only deletes the VERCEL_TOKEN env var; make it hermetic by also isolating
filesystem and disabling dotenv/profile loaders: in
test_token_absent_returns_none (and the other affected tests) unset VERCEL_TOKEN
via monkeypatch.delenv, then set HOME and XDG_CONFIG_HOME to tmp_path with
monkeypatch.setenv(str(tmp_path)), and monkeypatch any dotenv/profile loader to
a no-op (e.g., monkeypatch.setattr("dotenv.load_dotenv", lambda *a, **k: False,
raising=False)) so resolve_token is forced to consult only the controlled
environment; apply the same pattern around resolve_token calls in the other test
blocks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1643c895-5504-4554-bdeb-7f3a91c5e17c
⛔ Files ignored due to path filters (1)
core/wren/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (19)
core/wren/scripts/genbi-e2e.shcore/wren/src/wren/cli.pycore/wren/src/wren/genbi/__init__.pycore/wren/src/wren/genbi/cli.pycore/wren/src/wren/genbi/composer.pycore/wren/src/wren/genbi/index.pycore/wren/src/wren/genbi/providers/__init__.pycore/wren/src/wren/genbi/providers/base.pycore/wren/src/wren/genbi/providers/cloudflare.pycore/wren/src/wren/genbi/providers/vercel.pycore/wren/src/wren/genbi/tokens.pycore/wren/src/wren/genbi/verify.pycore/wren/src/wren/skills_content/genbi-app/SKILL.mdcore/wren/tests/unit/test_genbi_build.pycore/wren/tests/unit/test_genbi_deploy.pycore/wren/tests/unit/test_genbi_index.pycore/wren/tests/unit/test_genbi_verify.pycore/wren/tests/unit/test_skills_cli.pyskills/wren/SKILL.md
…t handoff Adjustments to make the GenBI workflow agent-drivable from natural language: - Rename the served skill genbi-app → genbi (`wren skills get genbi`): skills_content/genbi-app/ → genbi/, frontmatter name, ALL_SKILLS, discovery-stub guide line, and the e2e walkthrough. - Discovery stub (skills/wren/SKILL.md + index.json): add genbi/dashboard/ app/deploy trigger words (incl. zh) to the `description` so an agent loads the wren skill on "build a dashboard / 把語意層變成 app" intents, and lists `wren skills get genbi`. - genbi guide: document the Vercel Deployment Protection 401 trap (default-on Vercel Authentication; disable at Settings → Deployment Protection) and tell the agent to verify the deployed URL actually loads before calling it shareable. - genbi guide: add a "Snapshot data export" section with a DuckDB→parquet recipe and clarify the data-origin handoff — SaaS data comes via the dlt-connector skill (its .duckdb output is the snapshot source). - dlt-connector guide: bidirectional handoff — point to `wren skills get genbi` as the next step to share the loaded data as an app. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Not wired into CI (wren-ci.yml runs pytest only), so it provided no automated protection — only ad-hoc value when run by hand. The genbi unit tests (test_genbi_*.py) cover the logic; dropping the unmaintained manual e2e walkthrough rather than letting it rot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
♻️ Duplicate comments (1)
core/wren/src/wren/skills_content/genbi/SKILL.md (1)
51-55:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winThe disk-write statement still contradicts earlier text.
Lines 26-27 state that
wren genbi build"compiles it implicitly" whentarget/mdl.jsonis missing, but lines 54-55 claim it "writes nothing to disk." This past review concern remains unaddressed.📝 Suggested clarification
-For long or multi-line prompts use `--prompt-file <file>` or pipe to -`--prompt -`. The command prints the authoritative build instruction — -wasm wiring (pinned version, CDN load), the project's model/column inventory, -data-mode guidance, acceptance criteria, and the target folder. It writes -nothing to disk. +For long or multi-line prompts use `--prompt-file <file>` or pipe to +`--prompt -`. The command prints the authoritative build instruction — +wasm wiring (pinned version, CDN load), the project's model/column inventory, +data-mode guidance, acceptance criteria, and the target folder. It does not +write app files or `.wren/apps.yml` (it may compile `target/mdl.json` if missing).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/wren/src/wren/skills_content/genbi/SKILL.md` around lines 51 - 55, The documentation contradicts itself: the section describing "wren genbi build" must be clarified so it consistently states whether the command writes files when it "compiles it implicitly" due to a missing target/mdl.json; update SKILL.md to either (A) state that "wren genbi build" will perform an implicit compile and write the compiled artifacts (e.g., target/mdl.json and wasm wiring) to disk, or (B) state that it only compiles in-memory and prints the authoritative build instruction to stdout without writing any files; ensure the phrasing around "wren genbi build", "target/mdl.json", and the sentence "It writes nothing to disk." is made consistent and unambiguous.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@core/wren/src/wren/skills_content/genbi/SKILL.md`:
- Around line 51-55: The documentation contradicts itself: the section
describing "wren genbi build" must be clarified so it consistently states
whether the command writes files when it "compiles it implicitly" due to a
missing target/mdl.json; update SKILL.md to either (A) state that "wren genbi
build" will perform an implicit compile and write the compiled artifacts (e.g.,
target/mdl.json and wasm wiring) to disk, or (B) state that it only compiles
in-memory and prints the authoritative build instruction to stdout without
writing any files; ensure the phrasing around "wren genbi build",
"target/mdl.json", and the sentence "It writes nothing to disk." is made
consistent and unambiguous.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f98e824d-9653-4d2c-a321-16bd7ec114ca
📒 Files selected for processing (6)
core/wren/scripts/genbi-e2e.shcore/wren/src/wren/skills_content/dlt-connector/SKILL.mdcore/wren/src/wren/skills_content/genbi/SKILL.mdcore/wren/tests/unit/test_skills_cli.pyskills/index.jsonskills/wren/SKILL.md
✅ Files skipped from review due to trivial changes (1)
- skills/index.json
🚧 Files skipped from review as they are similar to previous changes (2)
- core/wren/tests/unit/test_skills_cli.py
- core/wren/scripts/genbi-e2e.sh
… silent failures Resolve CodeRabbit findings on #2348 (each with a regression test): - cli.py: validate app names as slugs via _resolve_app_dir() and route build/register/verify/open/deploy through it, so a crafted name ("../../etc") can't escape <project>/apps/. - vercel.py / cloudflare.py: skip symlinks and entries resolving outside build_dir when collecting files — a stray symlink must never exfiltrate on-disk files to a public static host. - vercel.py / cloudflare.py: raise DeployError instead of fabricating a URL ("https://", "{app}.pages.dev") when the provider response omits one — never report an unverifiable link as a successful deploy. - index.py: load_index() raises MalformedIndexError (with the path) on invalid/non-mapping .wren/apps.yml instead of crashing opaquely. - verify.py: fail closed on an unknown data_mode (a typo like "snapsho" no longer silently skips the snapshot data-asset check). - genbi SKILL.md + build docstring: fix the "writes nothing to disk" self-contradiction (build compiles target/mdl.json if missing). - test_genbi_deploy.py: autouse fixture neutralizes tier-2 ~/.wren/.env loading so token tests are hermetic (previously failed / could trigger a real provider call when a real VERCEL_TOKEN was present). The stale comment on the (now-removed) genbi-e2e.sh sleep loop is moot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The previous adapter POSTed {"branch", "files": {path: base64}} as JSON to the
Pages deployments endpoint — a shape Cloudflare never accepts (→ 400). Pages
has no single inline-upload REST endpoint like Vercel; Direct Upload is a
multi-step, partially-undocumented protocol (manifest → upload token →
multipart asset upload → completion token → create deployment). Cloudflare's
own guidance is to use `wrangler pages deploy`, so shell out to it:
- Detect `wrangler` (or `npx wrangler`); clear DeployError if absent.
- `wrangler pages project create` (tolerate "already exists"), then
`wrangler pages deploy . --project-name <n> --branch <main|preview>`,
run with cwd=app_dir so a stray wrangler.toml can't be picked up.
- Token + account id travel via the subprocess env, never argv.
- Parse the *.pages.dev URL from wrangler output; DeployError if none
(never fabricate a URL).
Rewrites the Cloudflare tests to mock the subprocess (the old tests mocked
the JSON transport and asserted our wrong shape — green but never exercised
the real protocol). Vercel is unchanged. Skill deploy section notes the
wrangler requirement.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review — GenBI app build & deployVerdict: Approve with one security follow-up. Clean CLI↔agent split, deterministic state owned by the CLI, and strong behavior-test coverage across build/index/verify/deploy. The prior review round already hardened path traversal, symlink exfiltration, URL fabrication, malformed-index handling, and fail-closed verify — each with a regression test. One gap below is worth fixing before Scope & CI
🟠 Medium — secret-leak gate has a suffix blind spot (reproduced)
Meanwhile Recommendation: invert to default-deny — scan every file except a small set of known-binary/data suffixes ( 🟡 Low — don't oversell the gateThe patterns are deliberately narrow (good for false positives) but miss GCP service-account JSON ( Nits
Done well
The Medium finding is the only thing I'd want addressed before merge, given security is the headline feature. |
goldmedal
left a comment
There was a problem hiding this comment.
We should also write the doc for the genBi command.
…, en-only - verify: invert the secret scan to DEFAULT-DENY. Previously an allowlist of web suffixes (.html/.js/.json/.css/.txt/.md) meant .env, .ts/.tsx/.jsx/.vue, .yaml/.toml were never scanned — exactly the files most likely to carry an inlined credential, and they all ship to the public host. Now scan every file except known binary/data formats (.parquet/.duckdb/.wasm/images/fonts…). - verify: a `.env*` file fails the gate on presence alone (independent of the narrow content patterns; `wrangler pages deploy .` would otherwise ship it). - vercel: belt-and-suspenders — never include `.env*` in the uploaded file set. - Soften the "verify catches secrets" wording in composer + SKILL to best-effort defense-in-depth (not a guarantee); the rule is never inline. - docs: add a `wren genbi` section to docs/core/reference/cli.md (build/ register/list/remove/verify/open/deploy, tokens, wrangler, Vercel protection). - Drop all Chinese trigger strings from skills/wren/SKILL.md and the genbi guide — English-only descriptions. Regression tests: non-weblike files (.ts/.yaml) are scanned, .env fails by presence, binary data assets aren't scanned (no false positives). goldmedal nits left as-is (per review): test files not lint-gated (pre-existing), open/remove don't route through _resolve_app_dir (no traversal risk — index keys / already-validated dir). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- reference/skills.md: add a `genbi` row to the Available skills table and a full `## genbi` section (CLI↔agent split, workflow, data modes, deploy notes incl. wrangler + Vercel protection, dlt handoff) — it was the only served skill missing from the enumeration. - core/wren/README.md: add an optional "Build a shareable GenBI app" quick-start step alongside cube/memory. - docs/core/guides/genbi.md: new how-to guide with the conversational flow, data export recipe, verify/secret-gate caveats, and the Vercel 401 trap; linked from the docs index. Docs only — no code change. (cli.md genbi reference landed in a prior commit.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… copy Reframe the GenBI-specific wording to "context layer" (positioning), across the genbi docs/skill/CLI text: skills.md (table + section), cli.md, the genbi guide, core/wren/README.md step 7, the genbi SKILL.md, the wren discovery stub's genbi clause, and the genbi composer/CLI help text. Leaves unrelated pre-existing uses untouched — the "semantic SQL layer" product tagline and "semantic layer" in the onboarding/usage skill sections. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up note: update the project-structure docThe default-deny secret-scan fix looks good (verified: the GenBI introduces two new project-local artifacts — Not a blocker — (Unrelated, pre-existing: |
Address goldmedal's follow-up: the canonical "what lives in the project vs. ~/.wren/" reference didn't mention the two project-local artifacts GenBI adds. Add a "Project layout" tree section that includes `apps/<name>/` (the generated app) and `.wren/apps.yml` (the app index, beside `.wren/memory/`), keeping the structure overview in sync with the directories this PR adds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Adds a GenBI app build & deploy pipeline to the
wrenCLI: turn a Wren project's semantic layer into a shareable, browser-side GenBI web app and deploy it to the user's Vercel or Cloudflare account — from a natural-language request to a public URL in one conversation.Design: CLI ↔ agent split
.wren/apps.ymlis only ever written by the CLI, never hand-edited.New CLI surface (
wren genbi)wren genbi build <name> --prompt "…" [--data-mode snapshot|live]wren-core-wasmversion, the project's model/column inventory, data-mode guidance, acceptance criteria, target folder). Writes nothing to disk.wren genbi register / list / removewren genbi verify <name>wren genbi open <name>wren genbi deploy <name> --provider vercel|cloudflare [--prod]Data modes
Security
verifyfails the app if credentials are inlined into app files, anddeployrefuses to ship it (the deploy target is a public static host).VERCEL_TOKEN/CLOUDFLARE_API_TOKEN(andCLOUDFLARE_ACCOUNT_ID) are discovered from the environment or.env, never passed as flags.--prodis explicit.Skill
Ships a
genbi-appagent workflow guide. Per main's new model (skills served from the CLI, withskills/wren/as the only external discovery stub), the guide lives atcore/wren/src/wren/skills_content/genbi-app/SKILL.mdand is served viawren skills get genbi-app— no separateskills/directory, no version drift.Tests
core/wren/tests/unit/test_genbi_*.py).core/wren/scripts/genbi-e2e.sh.genbi-appadded to the bundled set.Notes
This branch also merges
main(0.9.0) and aligns the GenBI skill with main's "skills served from the CLI" architecture (#2329).🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
wren genbicommand suite: build (composes agent instructions), register/list/remove, verify, open (local HTTP preview), and deploy to Vercel or Cloudflare. Token lookup supports env/project .env fallbacks.Bug Fixes / Safety
Documentation
Tests
Screen.Recording.2026-06-10.at.9.05.10.AM.mov
Screen.Recording.2026-06-10.at.9.06.39.AM.mov