diff --git a/.claude/skills/wrapp/template.js b/.claude/skills/wrapp/template.js index 6507c64..fddcd29 100644 --- a/.claude/skills/wrapp/template.js +++ b/.claude/skills/wrapp/template.js @@ -85,7 +85,18 @@ function wire(r) { // storage and re-renders; keep it idempotent. live = mountLive(r, reloadState); } -async function onReady() { await syncContext(); await loadState(); render(); autostart(); } +// onReady fires TWICE by design — once from mountConnect's onConnect and once from the +// returning-user probe above, whichever wins the race. Hydrating from storage on BOTH passes is a +// real (timing-dependent) bug: the second pass re-reads the run the first pass just saved, which +// REPLACES the in-memory object the running pipeline holds a reference to. The pipeline then +// completes into a detached orphan and the UI sits on a run that never finishes. Hydrate once. +let hydrated = false; +async function onReady() { + await syncContext(); + if (!hydrated) { hydrated = true; await loadState(); } + render(); + autostart(); +} /** Re-read everything this wrapp persists, then render. Called on every live nudge. For a wrapp * that ACCUMULATES items (a library, notes, a task list), read the collection here (see `items` * below) — never a single growing blob, or two teammates' edits clobber each other. */ diff --git a/ROADMAP.md b/ROADMAP.md index dda3547..5fbaf53 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -105,7 +105,66 @@ network egress) so a stranger's app can't exfiltrate your data — the basis for ## Next up -### 0. Autopilot → a real wrapp (prototype landed, SDK not wired) +### 0. ✅ Autopilot → a real wrapp — SHIPPED (`examples/apps/autopilot.{html,js}`) + +Ported to the house template and wired to real generation. `examples/autopilot/` is now the +superseded prototype; the shipping wrapp is `examples/apps/autopilot.html` + `src/autopilot.js`. + +**Resolved first: separate wrapp, not a brandbrain studio.** The verb argument in the original +entry was decorative — the separation had actually entered the record as a scope guard +(`OVERNIGHT.md:5-8`, *"brandbrain works; it is not in scope"*), and a third studio was never +evaluated. It was, and the conclusion holds for three better reasons: (1) brandbrain's studio +engine is **finite by construction** (`seq.every(id => locks[id])`, `brand-studio.tsx:1347`) and +has no concept of a decision that recurs — a never-terminating studio means replacing the control +flow, which is the thing that makes studios cheap; (2) the cockpit is precisely the part that does +**not** generalise (`compileTasks()` is a hand-written if-chain over brand-specific lock ids, and +the `!active.path` gate already makes ideabrain projects unable to reach the OS at all); (3) the +OS is explicitly one-brand-at-a-time (`command-centre.tsx:2525`), which contradicts a portfolio at +the state level. Plus brandbrain isn't ported (§1), so "inside" would block Autopilot behind the +most expensive unfinished item here. + +**Spec correction made during the build:** `contextKinds` is `["brand","project","idea"]`, not +`["brand"]`. The original narrowed a wrapp explicitly meant to generalise past D2C back to the one +D2C-shaped kind, and would have made Autopilot unable to consume an ideabrain output at all — +breaking the idea→run graduation. `ideaToContext` carries the whole locked playbook keyed by +decision id, which is richer than `brandToContext`'s five flattened strings. + +Done: 0a (house template) · 0b (real `relay.complete` generation, replacing seeded `buildOptions`) +· 0c (inherit-don't-re-ask, with a take-it-back escape) · 0d (cold open) · 0e (tokens from the +broker's real `usage`, estimates *labelled* as estimates) · 0f (`collection()`, one company = one +file) · 0g (build entry, catalog, store card, landing, harness spec + provider routes). + +Also ported from brandbrain: the `auto | approve | manual` mode taxonomy (`lib/studio/os.ts:10-13`) +— as a three-line concept, not code. It is what makes "autonomous" honest. + +Bugs found and fixed by verification (all would bite a live daemon, not just the harness): +`onReady` legitimately fires twice (mountConnect + the returning-user probe), so the cold open had +to become idempotent; `loadState` must **merge** rather than blind-replace `cos`, or a `mountLive` +nudge detaches the object generation is writing into and the slate renders empty forever; +`drafting` had to become a per-company Set (a global boolean makes drafting one company silently +abandon the next — fatal for a portfolio app); an inherited decision has no options, so the +upstream-constraint builder read `null` and silently dropped the lent voice out of every +downstream prompt. + +**Storage is proven against a real daemon**, not just the harness: +`examples/apps/proof/run-autopilot-storage.mjs` drives the actual `src/kit/livestore.js` against a +throwaway daemon on a temp `RELAY_DIR` and reads the bytes on disk — 19/19: one company = one file, +editing A never rewrites B (the claim Team Mode's per-file LWW rests on), torn records skipped, +traversal/dotted ids refused, per-origin isolation. Live token measurement is still blocked (Claude +Code isn't signed in on this Mac), so the catalog's token figure stays honestly dev-reported. + +**Side effect worth more than the wrapp: a catalog-wide race, fixed.** The harness's storage mock +discarded every write — a deliberate 2026-07-18 choice to keep wrapps cold-opening as fresh users. +It was also masking a live production bug. `onReady` fires twice (mountConnect + the returning-user +probe); with storage that actually returns what you wrote, the second pass re-reads the run the +first just saved and **replaces the in-memory object the running pipeline holds**, so the pipeline +finishes into a detached orphan and the UI sits on a run that never completes. Backing the mock with +a real per-page store turned reel/marquee/arcade red instantly. The fix — hydrate once — is now in +all **21** wrapps carrying the template's `onReady` one-liner, and in +`.claude/skills/wrapp/template.js` so new wrapps inherit it. (`cartridge.js` already had it; it was +never propagated.) Harness baseline is now **70/70 with real storage**, up from 68 runs → 64/2/2. + +
Original plan (superseded) `examples/autopilot/` holds a **working decision engine** with no model behind it. The state machine, locking, downstream ripple, persistence and token accounting are real; the option copy is @@ -141,6 +200,8 @@ not duplicate it: brandbrain publishes `kind: "brand"` via `brandToContext` Known gaps in the prototype: zero SDK calls; only two seeded company kinds (d2c, saas); the "+ New company" button opens the token pane instead of seeding a company. +
+ ### 1. brandbrain — full port (the immediate pickup) Turn the *real* `~/Documents/Projects/brandbrain` into the store's brandbrain (today's store card is a one-route demo). It's a **port, not a rewrite** — assessed portable: 7 pages (client shells, no diff --git a/examples/apps/autopilot-landing.html b/examples/apps/autopilot-landing.html new file mode 100644 index 0000000..4353057 --- /dev/null +++ b/examples/apps/autopilot-landing.html @@ -0,0 +1,349 @@ + + + + +Autopilot — Switchboard + + + + + +
+
+
+ ← All wrapps + +
+ + Switchboard / Autopilot +
+
+
+ Runs on your own Claude + Open Autopilot +
+
+ +
+
+ Brand & content +

Run the company you already have.

+

Lend it a brand, project or idea and it opens with a whole operating slate — voice, ad angle, channel, next move — before you type anything.

+ +
+ Nothing sends without you + Open source · MIT + No account to create +
+
+
+
+
+ + Autopilot — Firstlight + 1 of 3 companies · drafted cold +
+
+
+
Voice what the brand's relationship to you is
+
★ chosen

Trail-buddy warmth — earns the moment with you, never shames the shortcut.

+
dry

Spec-sheet minimalism — no adjective it can't measure.

+
deadpan

Flat, funny, anti-hype — undersells on purpose.

+
+
+
Ad angle redrafted when you changed the voice
+

Real coffee. No kettle. You're 40 minutes past the trailhead. There's no cafe up here — there's this. Tear, pour, look up.

+
+
+
autoDraft the creative for “No kettle”drafted · nothing sent
+
approveRun it on Trail & outdoor newsletterswaiting on you
+
manualFirstlight Lastlight — a second daypartonly you can
+
+
1.2M of 2M tokens budgeted this weekRevenue — not connected
+
+
+
+
+ +
+
+
Category
+
Brand & content
+
on the Switchboard shelf
+
+
+
Build cost
+
420K tokens · 3 updates
+
dev-reported
+
+
+
Price
+
Free core, forever
+
runs on your own Claude
+
+
+ +
+
01

Grounded in a context you lend it

The context comes from wherever you already made it — brandbrain, ideabrain, Bank, or Switchboard reading a live site. Autopilot sees the one you lend it and nothing else: it never copies it, and it never goes looking for another.

+
02

Every option is a card you choose

Nothing is a suggestion you retype. Change the voice and the ad below visibly rewrites, because the slate is one connected draft — and every option you passed on stays on the board.

+
03

Nothing irreversible without you

Every move is staged auto, approve or manual. Auto is what the machine can fully prepare at no risk; approve stages it and waits for your tap; manual is yours to do in the real world.

+
+ +
+
+ Where it sits +

Three verbs, three wrapps. This is the one that doesn't finish.

+
+
+
+

ideabrain

+

Should this exist?

+

Research, a playbook for your kind of idea, a deck. Ends in a thesis.

+
+
+

brandbrain

+

What is it?

+

Positioning, name, voice, palette, every decision locked. Ends in a brand.

+
+
+

Autopilot

HERE
+

Now run it.

+

The operating slate, week after week. No end state, and several companies on one board.

+
+
+

"Never terminates" means it has no finish screen, not that it works while you're away. There is no background loop and no schedule — Autopilot drafts when you open it, and picks up exactly where you left it. It reads a lent context; it does not go looking through your files for one.

+
+ +
+
+ What it costs +

Free to run. Pro only when our servers do the work. We never charge for AI access — the tokens are your own Claude quota.

+
+
+
+

Free — the complete core loop

+

The whole cockpit, every company, forever. Nothing in the operating loop is held back — and running a team over your own network is free too, because it costs us nothing.

+
    +
  • Cold open on connect — no form, no prompt, no button to press
  • +
  • As many companies on the board as you actually run
  • +
  • Real options on every decision, and the downstream redraft when you switch
  • +
  • Moves staged auto, approve or manual — you hold the go button
  • +
+
+
+

Pro — when our servers do the work

PRO
+

Two things sit behind Pro, and neither is AI access: the hosted relay that lets a team sync from anywhere without standing up infrastructure, and encrypted cloud backup.

+
    +
  • A shared board — teammates operating the same company, synced from anywhere
  • +
  • Encrypted cloud backup — offline catch-up and new-device restore
  • +
  • Your own LAN or a self-hosted relay stays free, forever
  • +
+

A token budget is not a bill. It is capacity to work — you are deciding how much thinking the company gets this week, on the Claude quota you already have.

+
+
+
+ +
+

Give Autopilot your Claude.

+ Open Autopilot +
Every draft, decision and redraft runs on your own Claude
+
+ + +
+ diff --git a/examples/apps/autopilot.html b/examples/apps/autopilot.html new file mode 100644 index 0000000..ca1a2a6 --- /dev/null +++ b/examples/apps/autopilot.html @@ -0,0 +1,211 @@ + + + + + + Autopilot — the cockpit for the company you already have + + + + + + +
+ Autopilot +
+
+
+
+

The cockpit for the company you already have.

+

Lend it a brand, a project or an idea and it drafts the operating slate with no input at all — voice, ad angle, channel, next move. Choose one and everything downstream rewrites. Nothing irreversible happens without you. Runs on your own Claude via Switchboard — the operator holds no key and never sees your data.

+
+
+
+ + + diff --git a/examples/apps/build.mjs b/examples/apps/build.mjs index 8dc0da5..71b75aa 100644 --- a/examples/apps/build.mjs +++ b/examples/apps/build.mjs @@ -1,7 +1,7 @@ import { build, context } from "esbuild"; const watch = process.argv.includes("--watch"); const options = { - entryPoints: { home: "src/home.js", bank: "src/bank.js", chat: "src/chat.js", adgen: "src/adgen.js", imagegen: "src/imagegen.js", persona: "src/persona.js", cartridge: "src/cartridge.js", adpulse: "src/adpulse.js", adforge: "src/adforge.js", shelf: "src/shelf.js", studio: "src/studio.js", aplus: "src/aplus.js", natal: "src/natal.js", arcana: "src/arcana.js", redline: "src/redline.js", batch: "src/batch.js", take: "src/take.js", identity: "src/identity.js", reel: "src/reel.js", marquee: "src/marquee.js", huddle: "src/huddle.js", arcade: "src/arcade.js", yearbook: "src/yearbook.js", toon: "src/toon.js", storybook: "src/storybook.js", anthem: "src/anthem.js", roast: "src/roast.js", emote: "src/emote.js", inkling: "src/inkling.js", petrait: "src/petrait.js", rizz: "src/rizz.js", dreamlog: "src/dreamlog.js", roomify: "src/roomify.js", thumbs: "src/thumbs.js", meme: "src/meme.js" }, + entryPoints: { home: "src/home.js", bank: "src/bank.js", chat: "src/chat.js", adgen: "src/adgen.js", imagegen: "src/imagegen.js", persona: "src/persona.js", cartridge: "src/cartridge.js", adpulse: "src/adpulse.js", adforge: "src/adforge.js", shelf: "src/shelf.js", studio: "src/studio.js", aplus: "src/aplus.js", natal: "src/natal.js", arcana: "src/arcana.js", redline: "src/redline.js", batch: "src/batch.js", take: "src/take.js", identity: "src/identity.js", reel: "src/reel.js", marquee: "src/marquee.js", huddle: "src/huddle.js", arcade: "src/arcade.js", yearbook: "src/yearbook.js", toon: "src/toon.js", storybook: "src/storybook.js", anthem: "src/anthem.js", roast: "src/roast.js", emote: "src/emote.js", inkling: "src/inkling.js", petrait: "src/petrait.js", rizz: "src/rizz.js", dreamlog: "src/dreamlog.js", roomify: "src/roomify.js", thumbs: "src/thumbs.js", meme: "src/meme.js", autopilot: "src/autopilot.js" }, bundle: true, format: "esm", target: "chrome111", outdir: "dist", sourcemap: true, logLevel: "info", }; if (watch) { const ctx = await context(options); await ctx.watch(); console.error("[apps] watching…"); } diff --git a/examples/apps/harness/Wrapp-Test-Harness-Report.html b/examples/apps/harness/Wrapp-Test-Harness-Report.html index 6afd198..9d75a73 100644 --- a/examples/apps/harness/Wrapp-Test-Harness-Report.html +++ b/examples/apps/harness/Wrapp-Test-Harness-Report.html @@ -58,13 +58,13 @@

Switchboard · wrapp test harness

Every wrapp, driven headless against two projects

-

All 34 wrapps booted on a mock window.claude, each lent one of two projects as context, then driven through its real stage-1 pipeline. 68 runs — one per wrapp × project.

+

All 35 wrapps booted on a mock window.claude, each lent one of two projects as context, then driven through its real stage-1 pipeline. 70 runs — one per wrapp × project.

-
64PASS — stage-1 rendered clean
-
2WARN — partial / needs a live backend
-
2FAIL — no stage-1 output
-
68total runs
+
70PASS — stage-1 rendered clean
+
0WARN — partial / needs a live backend
+
0FAIL — no stage-1 output
+
70total runs

01 The two projects

@@ -81,65 +81,69 @@

01 The two projects

02 Results matrix

-
wrappswitchboardnailinit
AdForgefounder-stack
jsonObject — forge_concepts_brand
pass
rendered ×3
pass
rendered ×3
Adwallfounder-stack
jsonObject — brand-draft
pass
rendered ×6
pass
rendered ×6
A-Plusfounder-stack
jsonObject — directions
pass
rendered ×3
pass
rendered ×3
Prismfounder-stack
jsonObject — concept-batch-draft
pass
rendered ×6
pass
rendered ×6
Shelffounder-stack
jsonObject — triage
pass
rendered ×4
pass
rendered ×4
Studiofounder-stack
jsonArray — today_shoot_list
pass
rendered ×6
pass
rendered ×6
Reelfounder-stack
jsonArray — script
pass
rendered ×5
pass
rendered ×5
Marqueefounder-stack
text — generate
pass
rendered
pass
rendered
Takefounder-stack
jsonArray — draftScript
pass
rendered ×2
pass
rendered ×2
Identityfounder-stack
jsonArray — person
pass
rendered ×3
pass
rendered ×3
Batchfounder-stack
jsonArray — draft_answer
pass
rendered ×10
pass
rendered ×10
Bankfounder-stack
jsonObject — today's brief
pass
rendered
pass
rendered
Redlinefounder-stack
jsonArray — audit
fail
no model call fired — folder-bound, no page on disk
fail
no model call fired — folder-bound, no page on disk
AdPulsefounder-stack
text — discover_meta_connector_prefix
warn
partial — CSV precursor renders; full diagnosis needs a live Meta connector
warn
partial — CSV precursor renders; full diagnosis needs a live Meta connector
Huddlechat
text — call-turn
pass
rendered
pass
rendered
betterchatchat
jsonArray — starter_suggestions
pass
rendered ×4
pass
rendered ×4
Cartridgeplay-make
jsonArray — pitch-deck
pass
rendered ×4
pass
rendered ×4
Arcanaafter-hours
jsonObject — reading
pass
rendered
pass
rendered
NATALafter-hours
jsonObject — full-read
pass
rendered ×3
pass
rendered ×3
Castplay-make
pass
rendered
pass
rendered (shared harness)
Arcadegame-generator
jsonArray — proposePitches
pass
rendered ×3
pass
rendered ×3
Yearbookimage-generation (viral retro portrait; text-to-image, NOT selfie-based)
jsonArray — propose-eras
pass
rendered ×9
pass
rendered ×9
Tooncreative-image-gen (four-panel comic strip generator)
jsonArray — proposeTreatments
pass
rendered ×7
pass
rendered ×7
Storybookcreative-generative
jsonArray — proposeBooks — 3 book concepts
pass
rendered ×3
pass
rendered ×3
Petraitimage-generation
jsonArray — proposeConcepts
pass
rendered ×3
pass
rendered ×3
Emoteimage-generation
jsonArray — proposePacks
pass
rendered ×3
pass
rendered ×3
Inklingimage-generation
jsonArray — proposeConcepts
pass
rendered ×3
pass
rendered ×3
Roomifyimage-generation
jsonArray — proposeDirections
pass
rendered ×3
pass
rendered ×3
Thumbscreative-marketing
jsonArray — propose-concepts
pass
rendered ×3
pass
rendered ×3
Memememe-generator
jsonArray — proposeConcepts
pass
rendered ×4
pass
rendered ×4
Roastfun-text-generator
jsonArray — proposeAngles
pass
rendered ×3
pass
rendered ×3
Rizzdating-copywriting
jsonArray — proposeStrategies
pass
rendered ×6
pass
rendered ×6
Anthemmusic
jsonArray — propose_concepts
pass
rendered ×3
pass
rendered ×3
Dreamlogpersonal / fun — gentle dream interpreter (text-in, optional image-out)
jsonArray — proposeLenses
pass
rendered ×3
pass
rendered ×3
+
wrappswitchboardnailinit
Autopilotfounder-stack
jsonArray — voice
pass
rendered ×4
pass
rendered ×4
AdForgefounder-stack
jsonObject — forge_concepts_brand
pass
rendered ×3
pass
rendered ×3
Adwallfounder-stack
jsonObject — brand-draft
pass
rendered ×6
pass
rendered ×6
A-Plusfounder-stack
jsonObject — directions
pass
rendered ×3
pass
rendered ×3
Prismfounder-stack
jsonObject — concept-batch-draft
pass
rendered ×6
pass
rendered ×6
Shelffounder-stack
jsonObject — triage
pass
rendered ×4
pass
rendered ×5
Studiofounder-stack
jsonArray — today_shoot_list
pass
rendered ×7
pass
rendered ×7
Reelfounder-stack
jsonArray — script
pass
rendered ×5
pass
rendered ×5
Marqueefounder-stack
text — generate
pass
rendered
pass
rendered
Takefounder-stack
jsonArray — draftScript
pass
rendered ×5
pass
rendered ×5
Identityfounder-stack
jsonArray — person
pass
rendered ×4
pass
rendered ×4
Batchfounder-stack
jsonArray — draft_answer
pass
rendered ×10
pass
rendered ×10
Bankfounder-stack
jsonObject — today's brief
pass
rendered
pass
rendered
Redlinefounder-stack
jsonArray — audit
pass
rendered ×5
pass
rendered ×5
AdPulsefounder-stack
text — discover_meta_connector_prefix
pass
rendered
pass
rendered
Huddlechat
text — call-turn
pass
rendered
pass
rendered
betterchatchat
jsonArray — starter_suggestions
pass
rendered ×4
pass
rendered ×4
Cartridgeplay-make
jsonArray — pitch-deck
pass
rendered ×5
pass
rendered ×5
Arcanaafter-hours
jsonObject — reading
pass
rendered
pass
rendered
NATALafter-hours
jsonObject — full-read
pass
rendered ×3
pass
rendered ×3
Castplay-make
pass
rendered
pass
rendered (shared harness)
Arcadegame-generator
jsonArray — proposePitches
pass
rendered ×4
pass
rendered ×4
Yearbookimage-generation (viral retro portrait; text-to-image, NOT selfie-based)
jsonArray — propose-eras
pass
rendered ×10
pass
rendered ×10
Tooncreative-image-gen (four-panel comic strip generator)
jsonArray — proposeTreatments
pass
rendered ×8
pass
rendered ×8
Storybookcreative-generative
jsonArray — proposeBooks — 3 book concepts
pass
rendered ×4
pass
rendered ×4
Petraitimage-generation
jsonArray — proposeConcepts
pass
rendered ×4
pass
rendered ×4
Emoteimage-generation
jsonArray — proposePacks
pass
rendered ×4
pass
rendered ×4
Inklingimage-generation
jsonArray — proposeConcepts
pass
rendered ×4
pass
rendered ×4
Roomifyimage-generation
jsonArray — proposeDirections
pass
rendered ×4
pass
rendered ×4
Thumbscreative-marketing
jsonArray — propose-concepts
pass
rendered ×4
pass
rendered ×4
Memememe-generator
jsonArray — proposeConcepts
pass
rendered ×5
pass
rendered ×5
Roastfun-text-generator
jsonArray — proposeAngles
pass
rendered ×4
pass
rendered ×4
Rizzdating-copywriting
jsonArray — proposeStrategies
pass
rendered ×7
pass
rendered ×7
Anthemmusic
jsonArray — propose_concepts
pass
rendered ×4
pass
rendered ×4
Dreamlogpersonal / fun — gentle dream interpreter (text-in, optional image-out)
jsonArray — proposeLenses
pass
rendered ×4
pass
rendered ×4

03 Per-wrapp detail

+
Autopilotfounder-stack
+
reads brand, project, idea context (single) · pipeline: jsonArray jsonArray jsonArray jsonArray
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
+
AdForgefounder-stack
reads brand context (single) · pipeline: jsonObject jsonObject imageUrl jsonObject
-
switchboard pass
rendered ×3 1 model call
nailinit pass
rendered ×3 1 model call
+
switchboard pass
rendered ×3
nailinit pass
rendered ×3
Adwallfounder-stack
reads brand context (single) · pipeline: jsonObject jsonObject imageUrl
-
switchboard pass
rendered ×6 1 model call
nailinit pass
rendered ×6 1 model call
+
switchboard pass
rendered ×6
nailinit pass
rendered ×6
A-Plusfounder-stack
reads brand context (single) · pipeline: jsonObject jsonObject jsonObject
-
switchboard pass
rendered ×3 1 model call
nailinit pass
rendered ×3 1 model call
+
switchboard pass
rendered ×3
nailinit pass
rendered ×3
Prismfounder-stack
reads brand context (single) · pipeline: jsonObject imageUrl
-
switchboard pass
rendered ×6 1 model call
nailinit pass
rendered ×6 1 model call
+
switchboard pass
rendered ×6
nailinit pass
rendered ×6
Shelffounder-stack
reads brand context (single) · pipeline: jsonObject jsonObject
-
switchboard pass
rendered ×4
nailinit pass
rendered ×4
+
switchboard pass
rendered ×4
nailinit pass
rendered ×5
Studiofounder-stack
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×6
nailinit pass
rendered ×6
+
switchboard pass
rendered ×7
nailinit pass
rendered ×7
Reelfounder-stack
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×5 2 model calls
nailinit pass
rendered ×5 2 model calls
+
switchboard pass
rendered ×5
nailinit pass
rendered ×5
Marqueefounder-stack
reads brand context (single) · pipeline: text imageUrl jsonObject
-
switchboard pass
rendered 2 model calls
nailinit pass
rendered 2 model calls
+
switchboard pass
rendered
nailinit pass
rendered
Takefounder-stack
reads brand context (single) · pipeline: jsonArray
-
switchboard pass
rendered ×2 2 model calls
nailinit pass
rendered ×2 2 model calls
+
switchboard pass
rendered ×5
nailinit pass
rendered ×5
Identityfounder-stack
reads brand context (single) · pipeline: jsonArray jsonArray jsonArray jsonArray jsonArray
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Batchfounder-stack
reads idea, project context (single) · pipeline: jsonArray jsonArray
-
switchboard pass
rendered ×10 2 model calls
nailinit pass
rendered ×10 2 model calls
+
switchboard pass
rendered ×10
nailinit pass
rendered ×10
Bankfounder-stack
reads brand, personal, persona, project, csv, gsheet, note context (list) · pipeline: jsonObject text jsonObject jsonArray
-
switchboard pass
rendered 1 model call
nailinit pass
rendered 1 model call
+
switchboard pass
rendered
nailinit pass
rendered
Redlinefounder-stack
reads project context (list) · pipeline: jsonArray jsonObject text imageUrl jsonObject jsonObject
-
switchboard fail
no model call fired — folder-bound, no page on disk
nailinit fail
no model call fired — folder-bound, no page on disk
+
switchboard pass
rendered ×5
nailinit pass
rendered ×5
AdPulsefounder-stack
reads brand context (single) · pipeline: text text jsonObject
-
switchboard warn
partial — CSV precursor renders; full diagnosis needs a live Meta connector 5 model calls
nailinit warn
partial — CSV precursor renders; full diagnosis needs a live Meta connector 5 model calls
+
switchboard pass
rendered
nailinit pass
rendered
Huddlechat
reads no context (none) · pipeline: text
@@ -147,11 +151,11 @@

03 Per-wrapp detail

betterchatchat
reads personal, project, brand, note, csv, gsheet context (single) · pipeline: jsonArray text
-
switchboard pass
rendered ×4 1 model call
nailinit pass
rendered ×4 1 model call
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Cartridgeplay-make
reads personal, brand, project context (pick) · pipeline: jsonArray text text
-
switchboard pass
rendered ×4
nailinit pass
rendered ×4
+
switchboard pass
rendered ×5
nailinit pass
rendered ×5
Arcanaafter-hours
reads personal, project context (list) · pipeline: jsonObject
@@ -167,59 +171,59 @@

03 Per-wrapp detail

Arcadegame-generator
reads brand context (single) · pipeline: jsonArray html
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Yearbookimage-generation (viral retro portrait; text-to-image, NOT selfie-based)
reads brand, persona context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×9 2 model calls
nailinit pass
rendered ×9 2 model calls
+
switchboard pass
rendered ×10
nailinit pass
rendered ×10
Tooncreative-image-gen (four-panel comic strip generator)
reads single lent context (any kind — brand/founder/project); generic, no kind check context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×7 1 model call
nailinit pass
rendered ×7 1 model call
+
switchboard pass
rendered ×8
nailinit pass
rendered ×8
Storybookcreative-generative
reads single, brand context (single) · pipeline: jsonArray jsonObject imageUrl
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Petraitimage-generation
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Emoteimage-generation
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Inklingimage-generation
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Roomifyimage-generation
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Thumbscreative-marketing
reads brand context (single) · pipeline: jsonArray imageUrl
-
switchboard pass
rendered ×3 1 model call
nailinit pass
rendered ×3 1 model call
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Memememe-generator
reads no context (single) · pipeline: jsonArray
-
switchboard pass
rendered ×4 1 model call
nailinit pass
rendered ×4 1 model call
+
switchboard pass
rendered ×5
nailinit pass
rendered ×5
Roastfun-text-generator
reads single context (single (APP.usesContext='single'; brand = await relay.context.active()). Optional — drives the cold-open autostart when present, otherwise the app waits for a typed line.) · pipeline: jsonArray text
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Rizzdating-copywriting
reads persona context (single) · pipeline: jsonArray text
-
switchboard pass
rendered ×6 2 model calls
nailinit pass
rendered ×6 2 model calls
+
switchboard pass
rendered ×7
nailinit pass
rendered ×7
Anthemmusic
reads brand context (single) · pipeline: jsonArray text
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4
Dreamlogpersonal / fun — gentle dream interpreter (text-in, optional image-out)
reads no context (single) · pipeline: jsonArray text imageUrl
-
switchboard pass
rendered ×3 2 model calls
nailinit pass
rendered ×3 2 model calls
+
switchboard pass
rendered ×4
nailinit pass
rendered ×4

04 How the harness works

diff --git a/examples/apps/harness/provider.js b/examples/apps/harness/provider.js index 5879307..8993ac7 100644 --- a/examples/apps/harness/provider.js +++ b/examples/apps/harness/provider.js @@ -300,10 +300,44 @@ "