gooseworks 0.4.4 → 0.5.0-dev.5.1ff84a4f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +27 -10
  2. package/dist/agents/staging.d.ts +38 -0
  3. package/dist/agents/staging.d.ts.map +1 -0
  4. package/dist/agents/staging.js +309 -0
  5. package/dist/agents/staging.js.map +1 -0
  6. package/dist/auth/credentials.d.ts +1 -0
  7. package/dist/auth/credentials.d.ts.map +1 -1
  8. package/dist/auth/credentials.js +26 -8
  9. package/dist/auth/credentials.js.map +1 -1
  10. package/dist/auth/oauth-server.d.ts.map +1 -1
  11. package/dist/auth/oauth-server.js +18 -2
  12. package/dist/auth/oauth-server.js.map +1 -1
  13. package/dist/commands/doctor.d.ts.map +1 -1
  14. package/dist/commands/doctor.js +17 -8
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/formats.js +2 -2
  17. package/dist/commands/formats.js.map +1 -1
  18. package/dist/commands/graphics/publish-flow.js +1 -1
  19. package/dist/commands/graphics/publish-flow.js.map +1 -1
  20. package/dist/commands/install.d.ts.map +1 -1
  21. package/dist/commands/install.js +20 -0
  22. package/dist/commands/install.js.map +1 -1
  23. package/dist/commands/launch.d.ts +3 -0
  24. package/dist/commands/launch.d.ts.map +1 -0
  25. package/dist/commands/launch.js +35 -0
  26. package/dist/commands/launch.js.map +1 -0
  27. package/dist/commands/login.d.ts.map +1 -1
  28. package/dist/commands/login.js +7 -0
  29. package/dist/commands/login.js.map +1 -1
  30. package/dist/commands/logout.d.ts.map +1 -1
  31. package/dist/commands/logout.js +3 -1
  32. package/dist/commands/logout.js.map +1 -1
  33. package/dist/commands/skills.d.ts +16 -0
  34. package/dist/commands/skills.d.ts.map +1 -1
  35. package/dist/commands/skills.js +52 -1
  36. package/dist/commands/skills.js.map +1 -1
  37. package/dist/commands/styles.js +2 -2
  38. package/dist/commands/styles.js.map +1 -1
  39. package/dist/commands/update.d.ts.map +1 -1
  40. package/dist/commands/update.js +20 -0
  41. package/dist/commands/update.js.map +1 -1
  42. package/dist/commands/video-local.d.ts.map +1 -1
  43. package/dist/commands/video-local.js +2 -2
  44. package/dist/commands/video-local.js.map +1 -1
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +11 -3
  47. package/dist/config.js.map +1 -1
  48. package/dist/environment.d.ts +9 -0
  49. package/dist/environment.d.ts.map +1 -0
  50. package/dist/environment.js +103 -0
  51. package/dist/environment.js.map +1 -0
  52. package/dist/index.js +12 -45
  53. package/dist/index.js.map +1 -1
  54. package/dist/lib/graphics-cache.d.ts.map +1 -1
  55. package/dist/lib/graphics-cache.js +2 -2
  56. package/dist/lib/graphics-cache.js.map +1 -1
  57. package/dist/program.d.ts +2 -0
  58. package/dist/program.d.ts.map +1 -0
  59. package/dist/program.js +54 -0
  60. package/dist/program.js.map +1 -0
  61. package/dist/skills/custom-video-skill.d.ts +1 -1
  62. package/dist/skills/custom-video-skill.d.ts.map +1 -1
  63. package/dist/skills/custom-video-skill.js +1 -1
  64. package/dist/skills/custom-video-skill.js.map +1 -1
  65. package/dist/skills/installer.d.ts.map +1 -1
  66. package/dist/skills/installer.js +42 -24
  67. package/dist/skills/installer.js.map +1 -1
  68. package/dist/skills/master-skill.d.ts +12 -9
  69. package/dist/skills/master-skill.d.ts.map +1 -1
  70. package/dist/skills/master-skill.js +745 -343
  71. package/dist/skills/master-skill.js.map +1 -1
  72. package/dist/skills/releases.d.ts +1 -1
  73. package/dist/skills/releases.d.ts.map +1 -1
  74. package/dist/skills/releases.js +8 -5
  75. package/dist/skills/releases.js.map +1 -1
  76. package/dist/skills/routes.js +7 -7
  77. package/dist/skills/routes.js.map +1 -1
  78. package/dist/skills/staging-content.d.ts +3 -0
  79. package/dist/skills/staging-content.d.ts.map +1 -0
  80. package/dist/skills/staging-content.js +12 -0
  81. package/dist/skills/staging-content.js.map +1 -0
  82. package/package.json +12 -4
  83. package/skills/goose-ads/SKILL.md +363 -224
  84. package/skills/goose-product-photos/SKILL.md +84 -58
  85. package/skills/goose-video/SKILL.md +223 -14
  86. package/skills/goose-video-local/SKILL.md +195 -24
  87. package/skills/gooseworks/SKILL.md +106 -24
  88. package/skills/make-custom-video/SKILL.md +231 -10
  89. package/skills/manifest.json +7 -7
  90. package/skills/routes.json +7 -7
  91. package/dist/skills/fetcher.d.ts +0 -18
  92. package/dist/skills/fetcher.d.ts.map +0 -1
  93. package/dist/skills/fetcher.js +0 -118
  94. package/dist/skills/fetcher.js.map +0 -1
@@ -11,7 +11,7 @@ description: >
11
11
  references a product to photograph. Unlike goose-ads (ad creative) this produces clean PRODUCT
12
12
  photos that can then feed the ad workflow.
13
13
  category: ads
14
- version: 0.2.0
14
+ version: 0.3.0
15
15
  author: GooseWorks
16
16
  tags: [gooseworks, ads, product-photos, photoshoot, product, ecommerce, studio, lifestyle, on-model]
17
17
  ---
@@ -19,13 +19,16 @@ tags: [gooseworks, ads, product-photos, photoshoot, product, ecommerce, studio,
19
19
  # GooseWorks Product Photos — branded product photography
20
20
 
21
21
  The GooseWorks Product Photos skill. You **pick a brand + product and submit one generation**;
22
- the **backend** runs the whole pipeline (compose the shot prompt → generate on `gpt_image_2` →
23
- judge for product fidelity → auto-retry a few times for free) and stores the results. You do NOT
22
+ the **backend** runs the whole pipeline (compose the shot prompt → generate → judge for product
23
+ fidelity → auto-retry a few times for free) and stores the results. You do NOT
24
24
  generate images, call a model, or manage files — this is the exact same workflow the Product
25
25
  Photos studio uses, so the skill and the app can never drift. The point is to **enrich a brand's
26
26
  usable product imagery** — approved photos join the brand kit and can then feed the ad workflow
27
27
  (`goose-ads`).
28
28
 
29
+ It shoots a **physical catalog product** (apparel, beauty, consumer goods). A software
30
+ screenshot or an app mockup is not a product photo: that is an image edit, not this skill.
31
+
29
32
  ## How to talk to the customer (applies to every message you send them)
30
33
 
31
34
  The customer is a marketer or founder, not an engineer. Everything in this skill about tools,
@@ -78,19 +81,31 @@ and approval before spending. Hosted installed snapshots use the existing Skills
78
81
  Skill content and a host's cached MCP tool schemas are separate: refreshing one does not refresh
79
82
  the other. Check the actual advertised tools before using new fields.
80
83
 
81
- ## Prerequisite — the GooseWorks MCP server is REQUIRED
84
+ ## Prerequisite — the GooseWorks connector tools
85
+
86
+ Everything below runs through the GooseWorks connector's tools, by the names this skill uses.
87
+ Match on the tool name: a coding agent may show a server prefix (for example
88
+ `mcp__gooseworks__photos_generate`), a chat app may not.
89
+
90
+ If a tool named here is missing, the GooseWorks connection or its tool list is stale: ask the
91
+ user to reconnect or refresh GooseWorks in their app's connector settings. Installing or
92
+ updating the `gooseworks` CLI never fixes a missing connector tool, so never send a chat-app
93
+ user to a terminal for it. Only a terminal coding agent (Claude Code, Codex, Cursor) that has no
94
+ GooseWorks tools at all connects them, in that terminal, with `gooseworks install --mcp` plus
95
+ `--claude`, `--codex` or `--cursor`, then a restart.
82
96
 
83
- Everything goes through the `mcp__gooseworks__*` tools. If they are not available, **stop and
84
- tell the user to run `gooseworks install --claude --mcp`** (and restart Claude Code). There is no
85
- HTTP/file fallback.
97
+ Older notes or skill copies may name tools the connector no longer lists. Use the tool this skill
98
+ names instead; `catalog_fetch { type: "skill", slug: "gooseworks-guide" }` maps every old name.
86
99
 
87
100
  ## Start from the brand context — don't re-ask what it already answers
88
101
 
89
102
  If the `gooseworks` router handed you brand context, USE IT. If you were invoked directly, call
90
- `brand_read` yourself first. It answers most of the setup questions below, so **do not ask
91
- the user for them**:
103
+ `brand_read { brand_id, sections: ["summary","kit","products","learnings"] }` yourself first, then
104
+ `knowledge_search { brand_id, query: "<the shoot, in the user's words>" }` for saved rules and past
105
+ feedback (an archived photo's reason is saved as a `dont` rule). They answer most of the setup
106
+ questions below, so **do not ask the user for them**:
92
107
 
93
- - **Which product?** — the context's `products[]` are the real catalog entries. Offer them; never
108
+ - **Which product?** — the context's `products` are the real catalog entries. Offer them; never
94
109
  invent a product or ask the user to describe one you can already see.
95
110
  - **What does it look like / what is it made of?** — grounded in the product's stored images and
96
111
  description. Never guess a material, colorway, or silhouette.
@@ -102,79 +117,90 @@ the user for them**:
102
117
  Ask only for the genuinely open choices: the shot `category`, how many photos, quality, and
103
118
  whether a human model is wanted (which needs explicit consent — see the rules).
104
119
 
105
- ## Identity & credits
120
+ ## Credits — state the total, then get a yes
106
121
 
107
- - One agent-scoped token authenticates the tools; they resolve your org automatically. Never
108
- print the token. (You may pass an optional `target` to operate on a specific agent/org, exactly
109
- as the other GooseWorks tools; omit it to use your pinned scope.)
110
- - **Credits are handled by the backend.** `generate_product_photos` reserves the estimated cost up
111
- front and bills only the photos that pass the judge — **automatic retries are free**, and a photo
112
- the judge can't get right (`flagged`) is shown but **never billed**. Call
113
- `estimate_product_photos` first to quote the cost; `get_ad_credits` shows the balance.
122
+ - One token authenticates the tools and resolves your org; never print it. Omit `target`.
123
+ - **Quote first.** Call `photos_generate` with the exact arguments you will submit plus
124
+ `dry_run: true`. It reserves nothing and returns `creditsPerOutput` and `totalCredits`. Pass
125
+ `count` and `quality` explicitly in both calls so the quote matches the run.
126
+ - **Nothing paid runs without the user's explicit yes in this chat, given after you state that
127
+ credit total.** Then submit the same call without `dry_run`.
128
+ - The submit reserves the quoted credits and bills only the photos that pass the judge:
129
+ **automatic retries are free**, and a photo the judge can't get right (`flagged`) is shown but
130
+ **never billed**. The balance is `credits.available_credits` from `account_whoami`. If the
131
+ wallet is short, say so plainly with the total and the balance, and stop.
114
132
 
115
133
  ## The tools
116
134
 
117
135
  **Pick the brand + product**
118
- - `list_ad_brands` — the user's ad brands (get a `brand_id`; also carries `slug`).
119
- - `list_brand_products { brand_id, search?, page?, page_size? }` — the brand's imported products.
120
- Pick a `product_id` to shoot. `search` matches name / type / variant / SKU.
121
- - `import_product { brand_id, kind, url, product_name? }` — import a product if it isn't in the
122
- catalog yet. `kind` is `product_url` (a single product page), `shopify_store` (a store URL →
123
- imports the catalog), or `image_url` (a direct image; requires `product_name`). Returns an import
124
- row with an `id`; if its `status` isn't `complete`, poll `get_product_import` until it is, then
125
- `list_brand_products` to find the new product. (File uploads aren't available over MCP — use a URL.)
126
- - `get_product_import { import_id }` — poll an import until `status` is `complete` or `failed`.
136
+ - `brand_read` with no `brand_id` — the user's brands (each row's `id` is the `brand_id`).
137
+ - `brand_read { brand_id, sections: ["products"], products_query: "<name>" }` — the brand's
138
+ imported products in `products.items`; a product's `id` is the `product_id` to shoot.
139
+ `products_query` matches name / type / variant / SKU / description.
140
+ - Import a product that isn't in the catalog yet (free):
141
+ `brand_update { brand_id, patch: { products: [{ import_url, import_kind, name? }] } }`.
142
+ `import_kind` is `product_url` (a single product page), `shopify_store` (a store URL → imports
143
+ the catalog), or `image_url` (a direct image; also needs `name`). It returns `jobs[]`: poll
144
+ `job_get { job_id, kind: "product_import" }` until it finishes, then read the products again.
145
+ To add a photo the user attached to an existing product:
146
+ `media_upload { brand_id, scope: "product", scope_id: <product_id>, kind: "reference", source: { type: "bytes", filename, content_base64 } }`.
127
147
 
128
148
  **Generate**
129
- - `estimate_product_photos { count, quality? }` — cost preview (per-photo + total credits). `count`
130
- is 1, 2, 4, or 8; `quality` is `low` | `medium` | `high` (default `medium`). Reserves nothing.
131
- - `generate_product_photos { brand_id, product_id, variant_id?, category, controls?, prompt?,
132
- count?, quality?, reference_image_urls?, attestation_accepted? }` — **the one call that makes
133
- photos.** `category` is `apparel` | `beauty` | `cpg` (seeds sensible scene/framing defaults).
134
- Omit `controls` to use the category preset; pass `prompt` as free-text steering **added on top of**
135
- the settings (it doesn't replace them). Returns a generation with an `id` **immediately** — poll
136
- `get_product_photo_generation` until done, then read each `outputs[].final_image_url`.
149
+ - `photos_generate { brand_id, product_id, variant_id?, category, controls?, prompt?, count,
150
+ quality, reference_image_urls?, attestation_accepted?, dry_run? }` — **the one call that makes
151
+ photos** (and, with `dry_run: true`, its free quote). `category` is `apparel` | `beauty` |
152
+ `cpg` (seeds sensible scene/framing defaults). `count` is 1, 2, 4, or 8; `quality` is
153
+ `low` | `medium` | `high`. Omit `controls` to use the category preset; pass `prompt` as
154
+ free-text steering **added on top of** the settings (it doesn't replace them). Returns the
155
+ generation with its `id` **immediately**.
137
156
  **If you request a human model** (`controls.model.presence` is not `none`) you MUST pass
138
157
  `attestation_accepted: true` to confirm the user has the rights for model imagery.
139
- - `get_product_photo_generation { generation_id }` — poll until `status` is `complete`,
140
- `partial_failure`, or `failed`. Each `outputs[]` entry has its own `status` and, once ready, a
158
+ - `photos_read { brand_id, generation_id }` — poll until `status` is `complete`,
159
+ `partial_failure`, or `failed` (`job_get { job_id: <generation id>, kind: "photo_generation" }`
160
+ works too). Each `outputs[]` entry has its own `id`, `status` and, once ready, a
141
161
  `final_image_url`. A `flagged` output is the best attempt but wasn't billed.
142
162
 
143
163
  **Use the results**
144
- - `list_product_photos { brand_id, archived? }` — the brand's generated photos (`archived: false`
145
- = active, `true` = archived).
146
- - `approve_product_photo { output_id }` — approve a photo: links it to the product and makes it
147
- available in the **brand kit**, so `goose-ads` can use it. **Photos are not used anywhere until
148
- approved.**
149
- - `archive_product_photo { output_id, reason? }` — archive a photo; archived photos are **excluded**
150
- from ad generation.
164
+ - `photos_read { brand_id, archived?, product_id?, status? }` — the brand's generated photos
165
+ (`archived: false` = active, `true` = archived).
166
+ - `photos_update { brand_id, output_id, action: "approve" }` — approve a photo: links it to the
167
+ product and makes it available in the **brand kit**, so `goose-ads` can use it. **Photos are
168
+ not used anywhere until approved.**
169
+ - `photos_update { brand_id, output_id, action: "archive", reason? }` — archive a photo; archived
170
+ photos are **excluded** from ad generation, and the reason is saved as a `dont` rule.
151
171
 
152
172
  ## Workflow — shoot a product
153
173
 
154
- 1. **Load the brand context** (`brand_read`, or reuse what the router passed you) and
155
- **resolve the brand + product.** `list_ad_brands` → `brand_id`. `list_brand_products` → pick a
156
- `product_id` from the catalog you already know about. If the product genuinely isn't there,
157
- `import_product` (poll `get_product_import`).
158
- 2. **Quote the cost.** `estimate_product_photos { count, quality }` → tell the user credits.
159
- 3. **Generate.** `generate_product_photos { brand_id, product_id, category, count, quality, prompt? }`.
160
- Build `prompt` from the brand's voice/positioning you already have — don't interview the user for it.
161
- Returns a generation `id` right away.
162
- 4. **Poll.** `get_product_photo_generation { generation_id }` until terminal; hand back each
174
+ 1. **Load the brand context** (`brand_read` + `knowledge_search`, or reuse what the router passed
175
+ you) and **resolve the brand + product.** Pick a `product_id` from the catalog you already
176
+ know about. If the product genuinely isn't there, import it and poll the import.
177
+ 2. **Quote the cost.** `photos_generate` with `dry_run: true` and the exact `brand_id`,
178
+ `product_id`, `category`, `count` and `quality` → tell the user the credit total and wait
179
+ for their explicit yes.
180
+ 3. **Generate.** The same `photos_generate` call without `dry_run` (add `prompt` built from the
181
+ brand's voice/positioning you already have — don't interview the user for it). Returns a
182
+ generation `id` right away.
183
+ 4. **Poll.** `photos_read { brand_id, generation_id }` every ~20-30s until terminal; show each
163
184
  `final_image_url`.
164
- 5. **Approve the keepers.** Show the results and let the user pick; `approve_product_photo` the ones
165
- they'd publish (that's what puts them in the brand kit for ads), `archive_product_photo` the rest.
185
+ 5. **Approve the keepers.** Show the results and let the user pick; `photos_update` with
186
+ `action: "approve"` the ones they'd publish (that's what puts them in the brand kit for ads),
187
+ `action: "archive"` the rest.
166
188
 
167
189
  ## Rules
168
190
 
191
+ - **Connector tools only** — a missing tool means the GooseWorks connection is stale: ask the
192
+ user to reconnect or refresh GooseWorks. Never send a chat-app user to a terminal or a CLI
193
+ install.
169
194
  - **Never invent product facts.** The backend grounds the shot on the product's real images; don't
170
195
  describe a product you can't see.
171
196
  - **Use the brand context instead of interviewing the user.** Product, audience, voice, positioning,
172
197
  logo/colors/fonts all come from `brand_read` / the brand kit. Ask only for the shot
173
198
  category, count, quality, and model consent.
174
- - **Ask before spending.** Quote the estimate and confirm `count` / `quality` before
175
- `generate_product_photos` — it reserves credits.
199
+ - **Ask before spending.** State the dry-run credit total and get the user's explicit yes before
200
+ the real `photos_generate` — it reserves credits.
176
201
  - **Poll, don't re-submit.** A generation that's still `running` is not stuck; re-submitting
177
- double-bills. Only a `failed` generation should be retried.
202
+ double-bills. A `failed` generation may still hold `flagged` photos (shown, never billed):
203
+ show those first, and run again only after a new quote and the user's yes.
178
204
  - **Model imagery needs consent.** Only set a human model when the user asks, and pass
179
205
  `attestation_accepted: true`.
180
206
  - **Approval is the hand-off to ads.** Remind the user that only **approved** photos reach the brand
@@ -7,7 +7,7 @@ description: >
7
7
  goose-video-local; a chat host hands the same project to the GooseWorks coworker. Review
8
8
  one complete template plan and total credits before production. Custom videos retain two authenticated review gates in this chat.
9
9
  category: ads
10
- version: 3.0.0
10
+ version: 3.0.5
11
11
  author: GooseWorks
12
12
  tags: [gooseworks, ads, video, local-render, coworker, chat]
13
13
  ---
@@ -78,9 +78,210 @@ and `available_here`, never a guess from the host's name. Template-remix review
78
78
  chat. Custom videos use separate authenticated script and ingredient approvals in this same chat.
79
79
  Studio is an optional review surface.
80
80
 
81
- ## Custom videos: route before formats
81
+ ## Prepare the video workflow and brand before creative work
82
82
 
83
- For an original brief without a reference template, an Instagram reel/post URL or a direct video URL to study, fetch `catalog_fetch { type: "skill", slug: "make-custom-video" }` and follow it in this same session. It creates format:"custom", custom_mode:"generate" with the brief and optional reference_url. Growth executes in its managed sandbox; connected agents use their shell. Script and actual ingredients are reviewed and separately approved in the same chat before paid production; Studio is optional. Do not force a template choice or import the reference as a finished video.
83
+ **Installed entry files are bootstrap instructions.** For new work started from an installed
84
+ file or an old chat, fetch `catalog_fetch { type: "skill", slug: "goose-video" }` on the selected
85
+ connection and read its returned content and dependencies before continuing. Use the already
86
+ fetched body when this entry came from that connection in this run; do not recursively fetch
87
+ the same entry. A CLI freshness warning does not block using the current connected package.
88
+ Keep the fetched package and hashes in a new run folder; do not replace edited installed files.
89
+ If current instructions cannot be loaded, resolve the connection before format suggestions,
90
+ script writing or production. Do not continue from an old installed workflow or session notes.
91
+
92
+ **Follow the connector's full-guide requirement when available.** Fetch
93
+ `catalog_fetch { type: "skill", slug: "gooseworks-guide" }` when the connector requires it.
94
+ The only older-server exception is below; it never removes brand preparation or approvals.
95
+
96
+ | Returned guide/workflow state on the selected connection | Required action |
97
+ | --- | --- |
98
+ | Guide returns `not_found`, and this same connection already returned the complete current matching video entry with its required dependencies | Continue with that authoritative entry's workflow, full brand preparation and existing approvals. |
99
+ | Guide has another error, no response, or incomplete content; or the matching entry/dependencies are missing, incomplete or from another connection | Stop before creative work, project writes or paid calls; resolve a compatible connection on this same environment. |
100
+
101
+ A missing custom entry or required custom tool/schema remains unavailable: never substitute
102
+ a template or an import to bypass it. Never hide other fetch errors or continue from cached
103
+ instructions merely because the guide was not found.
104
+
105
+ **For an existing project or batch, read `video_project_read` first.** Determine its actual
106
+ route and saved review state before fetching a recipe or doing local work. Resume an approved
107
+ run with its recorded packages, brand inputs, script and ingredients; do not silently replace
108
+ them with today's release or brand rules. Follow returned preparation requirements and use
109
+ the existing affected review/approval flow for an intentional change. Reads, free drafts,
110
+ imports and existing-job retrieval do not grant permission for new paid production.
111
+
112
+ **For every new plan, resolve the brand and call**
113
+ `brand_read { brand_id, sections: ["summary", "kit", "products", "learnings"] }` **before**
114
+ suggesting formats, mining video angles, writing any script, creating a production plan or
115
+ handing the work to another agent. Use `brand_get_context` with those same four sections only
116
+ when advertised. Reuse a complete read from this run on the same connection and brand.
117
+ Onboarding completion, a summary-only response and earlier session notes do not supply the
118
+ kit, selected product facts or saved rules. If the full read is unavailable, resolve it before
119
+ creative work. Use known kit facts while research is incomplete; do not restart research
120
+ solely because its status is pending. Never invent a product fact or accept a campaign to
121
+ bypass preparation. Then search the Brand Brain (next section) before suggesting formats,
122
+ choosing an angle or asking the user for a brand fact.
123
+
124
+ Carry that context through custom/template/idea routing and delegation. Before writing, make
125
+ the workflow's brand-rules file from those sources: pronunciations, required spoken copy,
126
+ prohibited claims, real logo, font, palette and the selected product's supported facts.
127
+ Entries prefixed `Video preference:` and visual/pacing instructions are creative direction,
128
+ not spoken lines. Use the kit's audience, offer and voice as defaults without an interview.
129
+ The rules file mirrors context; it is not proof of a read or permission to spend. Keep the
130
+ route's existing script, ingredient and budget approvals, including its allowed previews.
131
+
132
+ **Use the server's brand bundle when the selected API returns it.** Project create/read may
133
+ return top-level
134
+ `brand_context`: `{ version: 1, brand_id, digest, loaded_at, sections, brand, kit, products,
135
+ learnings }`. Its sections cover summary, kit, products and learnings.
136
+
137
+ | Returned brand/project response on the selected connection | Required action |
138
+ | --- | --- |
139
+ | A complete authoritative version-1 `brand_context` is returned | Binding is required: use its contents for the plan/rules and include `script_drafts.brand_context_digest = brand_context.digest` with each new/changed script save. |
140
+ | An older API returns the actual four brand sections but no `brand_context` in either the brand read or project response | Prepare from those full sections, write the brand rules and follow the selected connection's existing approval flow and advertised fields. Do not fabricate a receipt or send nonexistent bundle/digest fields. |
141
+
142
+ An incomplete/malformed bundle or missing brand section is a preparation failure, never the
143
+ older-API exception. Once this connection returns an authoritative bundle, use its binding
144
+ contract. `script_drafts.video_brand_context` is server-owned: do not author, replace or forge
145
+ it, and do not invent a read receipt or hash local brand facts into one. Keep the full bundle
146
+ out of client review payloads. If managed generation returns HTTP 409
147
+ `video_brand_context_required`, reload the project and bind the plan to its returned bundle
148
+ through the normal review flow before retrying. That refusal never permits the older-API
149
+ fallback, skipping sections or retrying paid calls blindly. Unchanged approved legacy resumes
150
+ retain their package, context and approvals; an upgrade alone needs no extra approval.
151
+
152
+ **To apply a deliberate brand correction to a new or revised plan**, make a fresh, unfiltered
153
+ `brand_read` of those four sections. When it returns the authoritative bundle, use its
154
+ returned `brand_context.digest` in the complete revised `script_drafts` through the existing
155
+ `video_project_upsert` `patch.script` save; the server verifies the current brand and replaces
156
+ its snapshot with the saved plan. On an older API with no bundle contract, apply the actual
157
+ four-section correction and save the revised draft through its existing flow without inventing
158
+ digest fields. If a connection that already returned a bundle cannot supply the fresh bundle,
159
+ resolve that failure before rebinding. Review and approve the affected script, ingredients and
160
+ budget through the normal flow. Never refresh an ongoing approved run automatically; its
161
+ recorded package and brand inputs stay pinned until an intentional change.
162
+
163
+ ## Search the Brand Brain, then propose — before any creative choice or question
164
+
165
+ The Brand Kit is a summary. The brand's saved knowledge (its Brain) holds what the Kit does not:
166
+ rules from past feedback, approved and rejected creatives, customer evidence, approved claims,
167
+ reports and documents. **After `brand_read`, and before you choose an angle, claim, hook,
168
+ product emphasis, format or source ad — and before you ask the user for any brand fact — call
169
+ `knowledge_search { brand_id, query }`** when it is registered. It is free and read-only: no
170
+ approval, no announcement to the customer and no questionnaire.
171
+
172
+ 1. **Search for this task, not the whole Brain.** Run one short query (under 500 characters) in
173
+ the user's own words plus the product (for example "ads for <product>: what worked, what to
174
+ avoid") and one with
175
+ `source_types: ["evidence", "claim", "learning", "creative", "document"]` for proof and past
176
+ creative results. Add a query only for a specific open question. Reuse results from this run.
177
+ 2. **Keep these states distinct** and record which one each query returned:
178
+
179
+ | Result | Means | Do |
180
+ | --- | --- | --- |
181
+ | `status: "ok"` with matches | Saved knowledge exists | Use it; keep each fact's citation in your working brief |
182
+ | `status: "empty"` | Nothing saved matches this query | Say "no saved evidence for <topic>", never "the brand has no proof" |
183
+ | `refresh_required` | The results shown are current; some changed sources were left out | Use them; search again shortly for anything missing |
184
+ | `building` | The index is not ready | Retry once shortly, then continue with the gap stated |
185
+ | An error, or the tool is not registered | Retrieval failed or is unavailable | Retry an error once, then continue from `brand_read` and treat evidence as unchecked |
186
+ | An empty Kit field | Only that field is blank | Not a search result: still search before asking |
187
+
188
+ 3. **Let the findings change the plan.** A `dont`/`must` learning or a rejected creative rules
189
+ options out; an approved or well-rated past creative is a proven angle to lead with; a report
190
+ shows what worked. Claim-grade proof is a result with `approved_ad_claim: true` or the kit's
191
+ `approvedClaims` within their stated applicability; the kit's `proofPoints` are what the
192
+ backend allows an ad to state, used as written. Other Kit text, documents and performance
193
+ numbers are context, never public claims. Never invent an offer, price or result. Judge
194
+ relevance and skip results about another product or business.
195
+ 4. **Propose; don't interview.** Lead with one recommended direction (angle, product, source or
196
+ format) and a one-line reason naming what you found, with up to two alternatives. When several
197
+ directions fit (two audiences, products or campaigns), pick the one the evidence favours, such
198
+ as an active campaign or approved past creatives, and name the other as an alternative instead
199
+ of asking. Ask only for a decision the brand read and the search cannot settle, or for spend
200
+ approval. Never ask the user for a fact the Brain already answered.
201
+ Keep directions already chosen (the user's words, a project's creative brief, handed-off
202
+ defaults, approved plans): search only to fill empty fields and to apply saved rules. When a
203
+ returned card or picker presents the choice, your recommendation is its one acknowledgement
204
+ line and the saved plan's defaults, not a separate list.
205
+ 5. **Carry an evidence brief** into the routed skill, writer or plan: findings with citations,
206
+ the state of each query, what it ruled out and the open gaps. Tell the customer the findings
207
+ in plain words; the citations stay in the brief.
208
+
209
+ On an approved resume, keep the saved brief and evidence; search again only for a new decision.
210
+
211
+ ## Custom videos: check formats first
212
+
213
+ First check the catalog: when the brief names or implies a listed format (for example a street interview, testimonial, podcast or chat video), show that format and its fit through the format flow below, including its support status. Go custom only when no format fits and the customer chooses custom after hearing why; custom keeps that format's hard constraints. For an original brief without a reference template, an Instagram reel/post URL or a direct video URL to study, fetch `catalog_fetch { type: "skill", slug: "make-custom-video" }` and follow it in this same session. It creates format:"custom", custom_mode:"generate" with the brief and optional reference_url. Growth executes in its managed sandbox; connected agents use their shell. Script and actual ingredients are reviewed and separately approved in the same chat before paid production; Studio is optional. Do not force a template that does not fit or that the customer declined, and do not import the reference as a finished video.
214
+
215
+ ## Run the format's route check before proposing it
216
+
217
+ A catalog row says what a format is best for and ranks it for the brand. It does not say whether
218
+ the format can make the setup the customer asked for (how many people, mic only, no product).
219
+ Some renderers declare a route selector that decides that; today that is the street interview
220
+ (`render-street-interview`). Before you propose, script or create a street-interview project,
221
+ template or custom, check the request against its routes:
222
+
223
+ | Street route | On screen | Needs | Makes |
224
+ | --- | --- | --- | --- |
225
+ | Guessing (`product-guess`) | Interviewer and up to four people | A physical product to hand over, photographed on its own | A finished video |
226
+ | Conversation (`mic-only`, `product-sample`, `concept-challenge`) | Interviewer and one person | No product photo, phone, screen or UI | A script and prompt preview only, no finished video yet |
227
+ | Street testimonial (its own format) | One person talking to camera, no interviewer | The creator still its recipe prescribes | A finished video, when the catalog lists it |
228
+
229
+ Neither interview route takes a photo of a person: people are described in text, so never
230
+ propose putting a founder's or creator's face in one. Keep the customer's named setup: never
231
+ change the interaction, mode or number of people just to make a check pass.
232
+
233
+ - **Without a shell** (a chat host), decide from this table. Do not fetch the renderer: its
234
+ package is far too large for a chat.
235
+ - **With a shell** (the customer's computer or the coworker sandbox), also run its free
236
+ selector, which makes no paid call. If the fetch or the run fails, decide from the table.
237
+ 1. Fetch the renderer to a file, not into the conversation: its inline package is over a
238
+ million characters. Either save the JSON from `gooseworks fetch render-street-interview > <file.json>`,
239
+ then write each `scripts` entry as
240
+ `/tmp/gooseworks-scripts/render-street-interview/scripts/<name>` and each `files` entry at
241
+ `/tmp/gooseworks-scripts/render-street-interview/<path>`. Or call
242
+ `catalog_fetch { type: "skill", slug: "render-street-interview", delivery: "archive" }`,
243
+ extract the ZIP, check each file against its `manifest.json` hashes and copy the contents of its
244
+ `agent-config/skills/render-street-interview/` folder into
245
+ `/tmp/gooseworks-scripts/render-street-interview/`. Either way the selector reads
246
+ `references/street-reference-library.json` from that folder.
247
+ 2. Write a brief JSON. `mode` and `interaction_type` go in pairs: `product-guess` with
248
+ `product-guess`, or `conversation` with `mic-only`, `product-sample` or `concept-challenge`.
249
+ `offering_type` is exactly `physical`, `service` or `digital` (software, SaaS and apps are
250
+ `digital`). `participants` is a whole number: people interviewed on screen, not counting
251
+ the interviewer. Leave it out when the customer named no count; the selector then uses the
252
+ route's usual cast. When the customer named no interaction, run each mode that could fit.
253
+ 3. Run `python3 /tmp/gooseworks-scripts/render-street-interview/scripts/prepare_script_context.py --brief <brief.json> --out <context.json>`.
254
+ Read `status` and `brief_gaps` in the output file, not the exit code: it exits 2 for every
255
+ status except `ready-for-writing`. A Python traceback is not a verdict: the brief or the
256
+ saved files are wrong (for example the reference library in the wrong folder). Fix them and
257
+ run it again.
258
+ 4. A run with any `brief_gaps` has not checked the route. Fix every gap and run it again.
259
+
260
+ **An unsupported setup is a stop.** `unsupported-route`, or a request the table rules out,
261
+ means this setup can't be made. Tell the customer plainly, in one line, for example: "A
262
+ three-person mic-only street interview isn't something we can make yet: that version takes one
263
+ person, and the three-person version needs a physical product to hand over." Then offer the
264
+ closest supported options in plain words, each with how it differs. With a shell, these are the
265
+ selector's `alternatives`. Without one, take them from the table:
266
+
267
+ - when only the number of people was the problem, the same setup within its limit: guessing
268
+ (a physical product only) with up to four people, a finished video; or a conversation with
269
+ one person, a script preview only;
270
+ - for something people can't hold (software, a service), a one-person conversation instead
271
+ of guessing;
272
+ - one person talking to camera with no interviewer, if the catalog lists that format;
273
+ - a custom video, untested, that keeps the street format's limits.
274
+
275
+ Never use route names or the script's wording. Do not create the project or write a script for
276
+ it. Go custom only if the customer picks it; a custom video keeps the street format's hard
277
+ constraints, which make-custom-video lists.
278
+
279
+ **A supported setup.** With empty `brief_gaps`, any other status means the route exists.
280
+ `needs-reference` means no observed reference ad matched yet: it does not block proposing the
281
+ format; carry it into the handoff so the script step resolves or reports it before script
282
+ approval. Carry the route too: which one, how many people, finished video or preview only, and
283
+ no person photos. A preview-only route makes a script and prompt preview, not a finished video:
284
+ say so before the customer chooses it.
84
285
 
85
286
  ## Route first: is this a new video?
86
287
 
@@ -90,9 +291,10 @@ Hand off to **`goose-video-local`** now, and stop following this skill, for:
90
291
  - the app's copy-for-Claude command (it names `goose-video-local`);
91
292
  - "remix this video ad template" for a specific app template.
92
293
 
93
- Use `goose-video-local` if it is installed; otherwise load it with
294
+ Load the current `goose-video-local` entry with
94
295
  `catalog_fetch { type: "skill", slug: "goose-video-local" }` on the GooseWorks MCP (older clients:
95
- `fetch_skill("goose-video-local")`). It reads the project first and says what to do with it.
296
+ `fetch_skill("goose-video-local")`), unless already fetched on this connection in this run.
297
+ It reads the project first and retains an approved run's recorded recipe packages.
96
298
 
97
299
  When they ask **what** to make ("give me video ad ideas", "what angles should I use?", "what's
98
300
  working for my competitors?"), fetch **`ad-angle-miner`** (`catalog_fetch { type: "skill", slug: "ad-angle-miner" }`,
@@ -147,8 +349,9 @@ review set; do not add a separate approval round.
147
349
  ## Save durable brand answers, then verify them
148
350
 
149
351
  Read the selected brand with `brand_read { brand_id, sections: ["summary", "kit", "products", "learnings", "onboarding"] }`
150
- (fallback: `brand_get_context` with the same sections). Keep founder answers, user corrections,
151
- research and your own hypotheses distinct. Reuse matching saved answers; ask only about gaps.
352
+ (older clients: `brand_get_context` with the same sections, only when that tool is advertised).
353
+ Keep founder answers, user corrections, research and your own hypotheses distinct. Reuse
354
+ matching saved answers; ask only about gaps.
152
355
 
153
356
  When the user asks to remember a rule, answers a brand interview, or explicitly corrects a
154
357
  standing fact, save that answer in the same turn. The capture request authorizes those answers;
@@ -272,14 +475,15 @@ bypass setup. Keep the original request.
272
475
  ### 2. Keep the goal and propose defaults
273
476
 
274
477
  Never ask what the ad is for before showing formats. Keep the customer's exact direction.
275
- Otherwise propose defaults from the verified kit's products, audience, offer and voice. Show
276
- those defaults in the saved plan so any can be changed. Never invent proof or product facts.
478
+ Otherwise propose defaults from the verified kit's products, audience, offer and voice and the
479
+ Brain search's evidence brief (proven angles, saved rules, approved claims). Show those defaults
480
+ in the saved plan so any can be changed. Never invent proof or product facts.
277
481
  Idea requests still follow ad-angle-miner with the video output.
278
482
 
279
483
  ### 3. Show the picker or its text fallback
280
484
 
281
485
  Call `video_catalog_list { kind: "formats", brand_id }`. On the customer's computer, when you
282
- can actually execute shell commands, include `client: { shell: true }`; in a chat host omit
486
+ can actually execute shell commands, you MUST choose local execution and include `client: { shell: true }`; in a chat host omit
283
487
  that claim. Inside a coworker sandbox follow its reported capabilities, never claim to be the
284
488
  customer's computer. Respect requested limit and next_cursor for more item pages; the card may
285
489
  contain a full picker independently of the item page.
@@ -291,6 +495,9 @@ contain a full picker independently of the item page.
291
495
  Write "no demo yet" when absent. Never put links only in a question control.
292
496
  - A format whose card contradicts what they asked for is never Suggested. Never offer
293
497
  available_here:false as an executable choice. Relay not_available_here in one short line.
498
+ - `suggested` ranks a row for the brand; it never means the row makes the setup they named.
499
+ Never tell the customer a row is "exactly" what they asked for beyond what its card says. A
500
+ street interview still needs the route check above first.
294
501
  - Missing required assets are missing; unknown suitability is “needs review.” Inspect the
295
502
  selected format's candidates before spending. Never promise an unverified asset is ready.
296
503
  - Template formats use **one plan, one approval with the total in credits**, not approval for
@@ -302,7 +509,7 @@ contain a full picker independently of the item page.
302
509
  Never tell a chat host it needs Claude Code to start. Browser-only formats remain unavailable
303
510
  here; give computer setup guidance only if asked how to make one.
304
511
  - **Local shell:** run `gooseworks doctor --no-browser` for common setup (auth/MCP, Node 18+,
305
- ffmpeg with libx264 + libass, ffprobe). Then fetch the selected template and its capabilities,
512
+ ffmpeg with libx264 (libass only for an ASS caption route), ffprobe). Then fetch the selected template and its capabilities,
306
513
  and install documented dependencies in its fetched folder. Do not guess a renderer from a
307
514
  format name. For each Node renderer using default Playwright Chromium, run
308
515
  `gooseworks doctor --renderer-script "/absolute/path/to/the/fetched/scripts/record.js"` with
@@ -318,7 +525,8 @@ contain a full picker independently of the item page.
318
525
  ### 5. Create the project and hand it off, in this session
319
526
 
320
527
  1. `video_project_upsert { brand_id, name, format: <template_id> }` with no brief (a brief creates
321
- a concept batch). Include client:{shell:true} only for real local execution. Default
528
+ a concept batch). A street interview is created only after its route check found a supported
529
+ setup. Include client:{shell:true} only for real local execution. Default
322
530
  creation_intent:"format" keeps the style with this brand's content; source_remix requires an
323
531
  explicit choice to use source content.
324
532
  If they already chose a campaign/concept, include its verified campaign_id and optional
@@ -326,9 +534,10 @@ contain a full picker independently of the item page.
326
534
  to it. Omit unknown IDs and never infer a link or create a campaign solely to file a video.
327
535
  2. **Verified local shell or coworker sandbox:** load
328
536
  `catalog_fetch { type: "skill", slug: "goose-video-local" }` and follow it on the same project_id.
329
- Carry the customer's words, verified defaults, campaign and selected angle into its brief.
537
+ Carry the customer's words, verified defaults, campaign, selected angle and a street
538
+ interview's route check result into its brief.
330
539
  3. **Chat host:** `goose_run_task { brand_id, project_id, message }` with the request, selected
331
- format and defaults. Keep task_id. Continue questions/edits with the same task and project.
540
+ format, defaults and a street interview's route check result. Keep task_id. Continue questions/edits with the same task and project.
332
541
  A saved free draft is not a started worker or a complete plan. Follow actual saved state.
333
542
  4. When follow.card_follows is true, the card follows progress: do not re-read it in a loop.
334
543
  Read again on a customer reply, card action or requested update. A failure or missing saved