ship 2026-05-28: bb Apps subsystem (Phases 1–3 + follow-ups)#56
Merged
Conversation
…s + status app + bb app CLI Per-thread Apps system foundation (no frontend yet): apps/<id>/ layout (manifest.json + served assets/ + file-based data/ + logo.*), daemon-owned asset serving + data/ watcher, server routes (entry/assets/icon/data CRUD/ message + WS relay on thread:<id>:app:<id>:data), injected window.bb bridge (capability-gated, advisory for v1), default seeded `status` app, and bb app new|list|open|rm. STATUS remains in place; teardown is Phase 3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ch + app tabs Frontend for the Apps system (additive; STATUS UI left intact for Phase 3): - App tab kind + pinned `status` app tab in the secondary panel - "+" launcher listing the thread's apps with resolved icons - Unified app + file search (Apps + Files sections) - App tab content branches on entry kind: HTML → iframe + injected window.bb, Markdown → static react-markdown - Live data updates via window.bb.data.onChange (with replay/unsubscribe lifecycle guard), shared markdown asset URL transform, centralized STATUS_APP_ID Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the legacy STATUS system end to end (no backwards compat) and makes the Apps system the only path: - Delete STATUS server routes/injection/status-data/status-version, the WS hub status method, the daemon status commands (HOST_DAEMON_PROTOCOL_VERSION→26), the frontend manager-status surface + useThreadStatusVersion, and all STATUS-specific tests. - Rewrite manager/thread system prompts + instructions to the apps model (apps/status, data/state.json, window.bb, bb app CLI). - bb-guide-status-state → bb-guide-app (bb guide app); fold bb guide styling into it; regenerate templates. New managers seed only the `status` app. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Guide for migrating an existing manager/thread off the removed STATUS surface (STATUS.html/.md/STATUS folder + STATUS-data) to a `status` app: target layout, manifest, state consolidation into data/state.json, the bbStatusState→window.bb and bbThreadTell→window.bb.message API mapping, agent/maintainer direct-fs writes, and cleanup. Points to `bb guide app` for the full reference. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… on unmatched Replace `/api/v1/threads/:id/apps/:appId/assets/*` with the canonical flat `/api/v1/threads/:id/apps/:appId/*` wildcard → filesystem `apps/<appId>/assets/<*>`. The `assets/` directory is an internal storage detail; URLs no longer expose it. Nested paths preserved. Add an `/api/v1/*` JSON-404 guard so unmatched API URLs return JSON 404 instead of falling through to the bb SPA shell HTML. Improve the fresh-manager missing-manifest path to return `app_not_provisioned` with a rebuild hint (root cause was stale binaries, not a real seeding bug). Update default status template HTML, file-content-urls, migration guide, bb guide app, tests, and regenerated templates to flat URLs only. No back-compat alias kept — apps system isn't shipped yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
seedManagerThreadStorage previously early-returned after copying from
a user-authored manager template, skipping the bundled apps/status
fallback entirely. Fresh managers with any user template on disk would
404 on apps/status because the bundled manifest never got seeded.
Now the bundled set (apps/status/{manifest.json, assets/index.html,
data/state.json}) is always overlaid on top of any user-template copy,
regardless of which template is active. User-authored files still win
because they are copied first and the bundled overlay uses
writeFile(..., flag: "wx") which refuses to overwrite. Missing
non-default templates still warn but no longer skip the seed.
Tests refactored around expectBundledStatusAppSeeded() helper; added
"user-authored files win over the bundled overlay at the same path"
case asserting both behaviors.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full-width button below the search input in the secondary-panel New
Tab. Clicking it prefills the thread composer's draft via
usePromptDraftStorage.setDraft (text + clears attachments — full
replacement, not just text), focuses the composer with the [NAME]
placeholder selected, and dismisses the New Tab panel.
Replacing a non-empty draft prompts a browser confirm; cancel
preserves the existing draft (text + attachments), accept replaces
both. Reuses the existing prompt-draft store; no parallel state.
Plumbs a stable textareaId from ThreadDetailPromptArea through
FollowUpPromptBox so the button can focus the composer reliably.
Prefill template references `bb guide app`, the apps/<id>/
{manifest.json, assets/index.html, data/state.json} layout, and the
window.bb.data / window.bb.message browser APIs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Visual: bigger app rows with rounded tile-style icon container, name
+ id caption, uppercase tracking-wider section headers ("APPS",
"FILES"), token-driven hover/active/focus states that work in dark
mode. Create App moves from a full-width outline button below the
search to a dotted "+ Create App" tile at the end of the Apps list,
mirroring app rows with a "Describe an idea, the manager builds it"
hint line. The Apps section now always renders so the tile is
reachable immediately on open.
Prompt: prefilled template drops the [NAME] / [DESCRIBE…] placeholders
in favor of an end-of-text cursor landing. All apps-system context
lives at the top (manifest layout, window.bb usage), with a single
line pointing at `bb app new` for default styling, and a trailing
`What I want:` blank line where the user starts typing. Composer
cursor parks at end of text — no placeholder hunt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The blank template now scaffolds a bb-native HTML surface instead of a barebones one-line demo. New apps get the bb default styling head verbatim from `bb guide styling` (Google Fonts links for Inter + Fira Code, the full `:root` oklch token block, dark-mode overrides, body / .panel defaults), with scaffold-only classes (header chip, title, timestamp slot, section title, task-list rows, pills) layered strictly after the guide block. Visual structure mirrors the status task-list dashboard at a stripped-down plain-HTML scale, with a placeholder line — "Ask your agent to customize the status app how you please." — inviting the user to ask their agent to build on top. Name interpolation goes through a shared escapeHtmlText helper now extracted into @bb/domain and reused from the previous module-local copies in apps/desktop (local-view, log-viewer). XSS test covers `<script>`, `&`, `"`, and `'` in the app name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three small visual fixes to the secondary-panel New Tab launcher: 1. Unified the icon containers across Pet / Status / Create App tiles via shared LAUNCHER_TILE_ICON_CLASS constants. All three now share a size-9 raised frame with a size-5 glyph; the only intentional variant is the dashed inner border on Create App. The frame stays constant, only the asset varies. 2. Hide redundant id captions when the app id matches a slugified display name. `pet` / `status` captions disappear; when the id genuinely differs from the name, the caption renders in font-mono so it visibly reads as a developer identifier. 3. Drop the duplicate `title` tooltip on Create App (body hint stays) and the dead `disabled` prop on CreateAppTile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The default status app shipped to fresh managers was hard-coded to a
PR/worker-review workflow (PULL REQUESTS + WORKERS + "Message the
manager" sections, a `pr` landing-mode chip). That assumed one
specific routine; a brand-new bb user has neither. Replace with a
bb-styled generic starting-point dashboard that matches the
`bb app new --template blank` output and invites customization:
"Ask your agent to customize the status app how you please."
Mechanism: extract buildBlankAppIndexHtml({ name }) into a new
apps/server/src/services/threads/blank-app-scaffold.ts. Both
`bb app new --template blank` and `--template status` paths plus the
bundled manager-template overlay now generate index.html through one
generator (only the manifest icon differs). Delete the static
default-template/apps/status/{assets/index.html, data/state.json}
that pinned the old PR-review content.
User-authored manager templates still win over the bundled seed via
the existing flag:"wx" overlay semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A single invalid app manifest in a thread's apps/ directory used to fail the entire GET /api/v1/threads/<id>/apps list response with 422, taking down the whole secondary-panel launcher. The list route now shares a single readAppManifest parse step with the detail and serve routes; zod validation failures on an individual manifest log a structured warning (appId, manifestPath, summarized issue list at WARN level, full issues at debug) and that app is skipped in the list response. Detail and serve routes still surface the failure as a new invalid_manifest 422 error code (added to @bb/server-contract errors) with a one-line message — full zod issues stay in the server log, not on the wire. Tests cover: partial-success list (valid + invalid → 200 with only the valid summary + logger warned); detail returns invalid_manifest 422; serve returns invalid_manifest 422 (not the SPA shell fallthrough). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4e69ce1 to
49ae445
Compare
useCallback dep list had `promptDraft.getCurrent` / `promptDraft.setDraft` broken out; react-hooks/exhaustive-deps wants `promptDraft` itself. Replaced both with the parent object. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this ships
The bb Apps subsystem (three phases + follow-ups) lands on
main. A thread now exposes one or more apps in its secondary panel instead of the legacy STATUS surface. The bundledstatusapp replacesSTATUS.html+STATUS-data/. Includes a newbb appCLI, a bb-styled blank scaffold (now also the default for fresh managers), a Create App… tile that prefills the composer, the migration guide for old threads, and hardening so a single malformed manifest can't take down the whole launcher.Architecture report (local, not in repo):
/Users/sawyerhood/.bb/thread-storage/thr_mpi7fmdbse/reports/apps-system-architecture.md.Commits in this batch (12)
8defe97bwindow.bbbridge injection, bundledstatusapp,bb appCLI. STATUS still in place.03568757statustab, "+" New Tab launcher with unified apps + files search, HTML-vs-Markdown entry branching. STATUS UI intact.f3e7c92aHOST_DAEMON_PROTOCOL_VERSION→ 26. Prompt/guide rewrite:bb-guide-status-state→bb-guide-app(withbb guide stylingfolded in).3b414eefdocs/migrating-status-to-apps.md.220c7346/assets/*URL segment (no back-compat alias), added/api/v1/*JSON-404 guard, distinguishedapp_not_provisionedfromENOENT.251921fbseedManagerThreadStorageno longer early-returns after a user-template copy; bundledapps/statusis always overlaid (user files win viaflag:"wx").5af2941cusePromptDraftStorage.f7ff5581b5967795bb app new --template blankscaffolds a bb-styled HTML surface (Inter + Fira Code + oklch tokens + dark mode +.panel) with the placeholder "Ask your agent to customize the status app how you please." SharedescapeHtmlTexthelper extracted into@bb/domain.08bf1c862c9d2866buildBlankAppIndexHtml({ name })inblank-app-scaffold.ts.bb app new --template blank,--template status, AND the bundled manager-template overlay all go through the same generator now.4e69ce19invalid_manifest422 error code.QA checklist
Apps core
+→ New Tab launcher renders: search input, APPS section header, app rows, Create App tile at end.size-9frame; only the asset inside varies).pet/statusid captions hidden under app names; would re-appear if id ≠ slugified name.Default status (NEW look)
.panelwith placeholder "Ask your agent to customize the status app how you please.", "Example tasks" sample section with two row shapes. NOT the old PRs / Workers / "Message the manager" UI.task_*.jsonshape is supported but intentionally drifted from the bundledstate.jsondefault).Manager-template overlay
~/.bb/manager-templates/<name>/template ALSO getsapps/status/overlaid — add a custom file to your template dir, make a fresh manager, confirm BOTH the custom file ANDapps/status/are present.URL contract
curl -i http://127.0.0.1:38886/api/v1/threads/<id>/apps/status/index.html→ 200.app_not_provisionedJSON error (not rawENOENT).GET /api/v1/threads/<id>/apps/pet/iconserveslogo.svgwhen present.Apps list resilience (NEW)
apps/broken/manifest.jsonwith"icon": "NotAnIcon").GET /threads/<id>/apps→ 200, returns the valid apps, skips the broken one. Check server logs for the structured WARN.GET /threads/<id>/apps/broken/index.html→ 422 with{ code: "invalid_manifest", message: "..." }(NOT bb SPA shell, NOT raw 500).invalid_manifest422.window.bbbridgewindow.bb.appId+window.bb.data+window.bb.messagepresent (gated bycapabilitiesin manifest).entry: "index.md", e.g. the Markdown Test I just dropped atapps/mdtest/):window.bbis NOT injected. Open/api/v1/threads/<id>/apps/mdtest/index.md(or the Markdown Test tab) and verify headings / code blocks / tables / task lists / nested blockquotes / footnotes /<details>all render.window.bb.data.onChange("", cb)replays existing matches once on subscribe, then streams.window.bb.data.write(path, value)persists and broadcasts to other open viewers.apps/<id>/data/state.json(atomic temp+rename) ALSO broadcasts — open the app, write the file from a shell, watch the UI update.window.bb.message("text")posts a message to the parent thread.bb appCLIbb app list --selfshows the seededstatusapp.bb app new "Foo" --id foo --template blank --selfscaffolds an app; serves at the flat URL; renders bb tokens + dark mode; placeholder"Ask your agent to customize the status app how you please."visible.bb app new '<script>alert(1)</script>' --id xss --template blank --self— open the served URL; verify<script>does NOT execute (escaped as<script>).bb app new "Bar" --id bar --template status --selfscaffolds the status-template variant (now identical to blank, just withicon: ListTodoin the manifest).bb app open foo --selfprints the URL.bb app rm foo --self --yesremoves the app from disk.New Tab launcher / Create App… tile
What I want:).setDraftvs oldsetText).Legacy STATUS gone
GET /api/v1/threads/<id>/status/...→ 404 (route removed).GET /api/v1/threads/<id>/status-data→ 404 (route removed).window.bbStatusState/window.bbThreadTellNOT present in any served app.STATUS.html/STATUS.md/STATUS-data/files in existing thread storages are simply ignored.Migration guide
docs/migrating-status-to-apps.mdreads cleanly and is accurate after the post-ship corrections (flat URL contract,assetsDir: ""Vite hint, etc.).Protocol / desktop
Quality / regressions
pnpm exec turbo run typecheck— green across the board.pnpm exec turbo run test— green across the board (or any remaining failures are pre-existing sandbox-permission flakes, not regressions).Notes
PREFERENCES.md,sawyer-nextauto-merges on review APPROVE; this PR is merged tomainwith Rebase and merge (one commit per worker-batch).🤖 Co-authored by Claude Opus 4.7 + bb manager
thr_mpi7fmdbse.