@homie-rocks/studio 0.51.5 → 0.51.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/apps/APPS.md +41 -0
- package/bin/homie-studio.mjs +1 -1
- package/functions/FUNCTIONS.md +2 -2
- package/guides/app/NEEDS.md +160 -0
- package/guides/app/SKILL.md +45 -3
- package/guides/office/SKILL.md +27 -1
- package/guides/servers/SKILL.md +27 -1
- package/guides/shop/SKILL.md +38 -15
- package/lib/app-needs.mjs +93 -19
- package/lib/app-ready.mjs +21 -0
- package/lib/check.mjs +16 -7
- package/lib/cloudflare.mjs +4 -4
- package/lib/codex.mjs +7 -5
- package/lib/mcp-tools.mjs +1 -1
- package/lib/needs-headless.mjs +34 -0
- package/lib/shop-links.mjs +91 -27
- package/lib/shop-mcp.mjs +37 -10
- package/lib/stripe-connect.mjs +4 -4
- package/lib/template-history.json +84 -0
- package/lib/worker-config.mjs +3 -0
- package/package.json +1 -1
- package/shop/SHOP.md +82 -15
- package/worker/app-records.mjs +1 -0
- package/worker/build-id.mjs +1 -1
- package/worker/event-resources.mjs +9 -3
- package/worker/local-test.mjs +4 -0
- package/worker/mcp-events.mjs +2 -2
- package/worker/mcp-tools.mjs +31 -4
- package/worker/mcp.mjs +1 -1
- package/worker/shop-links.mjs +1 -1
- package/worker/shop-rules.mjs +3 -0
- package/worker/shop.mjs +53 -5
- package/worker/version.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -17,6 +17,39 @@ To bring a studio up to date, tell Claude: "Upgrade my studio to the newest Homi
|
|
|
17
17
|
`npx -y @homie-rocks/studio@latest upgrade`, which shows what's new since the version your studio pins (from this
|
|
18
18
|
file) and what the upgrade would change, and changes nothing until you agree.
|
|
19
19
|
|
|
20
|
+
## [0.51.7] - 2026-10-14
|
|
21
|
+
|
|
22
|
+
**Plugin 0.51.7**
|
|
23
|
+
|
|
24
|
+
Finish setting up your shop through Stripe's official plugin, and see what your studio's scheduled work is doing.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **Finish shop setup with fewer calls:** Products, prices and payment links are set up together where possible, and setup remembers completed changes instead of repeatedly searching your Stripe account. Verified shop settings are saved and installed on deploy; checkout explains when private webhook setup is the remaining step.
|
|
29
|
+
- **Clear, private webhook setup:** The guided flow explains when you need one separate Stripe CLI browser approval. The installer passes the signing secret privately to Wrangler. You do not need to supply an API key, and payments stay with Stripe.
|
|
30
|
+
- **See your studio's work:** Owners and studio-wide staff can inspect function run history, errors and the next scheduled run through their authenticated studio connection. Record actions use your highest declared role by default and tell you which role was used.
|
|
31
|
+
- **Reliable handover:** Deploy distinguishes claiming your studio from listing it in the directory. Screenshots used as evidence that owner needs are met are copied into the studio so they remain available with its Codex handover.
|
|
32
|
+
|
|
33
|
+
## [0.51.6] - 2026-10-14
|
|
34
|
+
|
|
35
|
+
**Plugin 0.51.6**
|
|
36
|
+
|
|
37
|
+
Keep each customer's exact basket through payment, and check that your studio meets its needs across screens, AI jobs and handover.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **Check the whole service:** Owner needs can call studio MCP tools as customer, staff or owner, assert returned results and saved records, invoke declared scheduled functions locally, read event feeds and MCP Events, check webhook delivery, and verify handover files. Checks keep role permissions and test-record isolation. Headless-only plans run without Chrome; missing tools, permissions, effects and text explain why a need is not met.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **Exact rounds and baskets:** Opt-in keyless saved baskets keep the phone's exact items and quantities. One custom-amount Payment Link carries the saved total; signed payments are checked against the saved basket and report full payment or a shortfall for staff. Short payments grant no automatic entitlements. The Worker needs no Stripe API key, and existing adjustable Stripe menus keep their behavior.
|
|
46
|
+
- **Clear acceptance and evidence:** Passing assertions mark a need met even when captures are absent or fail. Capture diagnostics identify the surface, explain the failure and show how to collect evidence with `--shots`.
|
|
47
|
+
- **Reliable changing controls:** Click, fill and select actions retry detached elements within a bounded wait. The app skill, packaged guides and Codex template explain how updating controls in place preserves a held press across delayed refreshes.
|
|
48
|
+
|
|
49
|
+
### Upgrade notes
|
|
50
|
+
|
|
51
|
+
- Saved baskets are opt-in through `shop.json.basket` and require Stripe with tax-inclusive menu prices. Automatic tax and Managed Payments are refused for basket mode. Staff can use the reported basket total, actual payment and settlement status to collect a shortfall.
|
|
52
|
+
|
|
20
53
|
## [0.51.5] - 2026-10-14
|
|
21
54
|
|
|
22
55
|
**Plugin 0.51.5**
|
package/apps/APPS.md
CHANGED
|
@@ -181,3 +181,44 @@ The phone remains its own surface; assert its confirmed gift after checkout. The
|
|
|
181
181
|
checker brings each page forward before reading or capturing it. Use the real
|
|
182
182
|
provider's controls, never a test-only app action. App sharing defaults to the top
|
|
183
183
|
right, clear of bottom tabs; `screen.share` remains an author-controlled override.
|
|
184
|
+
|
|
185
|
+
## Every owner need is executable
|
|
186
|
+
|
|
187
|
+
The Codex `needs` block supports existing UI steps plus named-role MCP calls,
|
|
188
|
+
returned-result assertions, simulated schedule ticks, record/results reads,
|
|
189
|
+
event feed/MCP Events/webhook checks and handover file contents. See the packaged
|
|
190
|
+
[needs format and examples](../guides/app/NEEDS.md). Passing assertions are **met**;
|
|
191
|
+
captures are additional evidence. Missing captures name their surface, reason and
|
|
192
|
+
how to rerun with `--shots .checks`. Detached action elements are re-queried for a
|
|
193
|
+
bounded ten seconds; ambiguous post-dispatch failures are not replayed.
|
|
194
|
+
|
|
195
|
+
Keep buttons connected during delayed refreshes: create the button once and set
|
|
196
|
+
`button.textContent = label` when data arrives. Never replace a held button with
|
|
197
|
+
`innerHTML` or `replaceWith`; that can cancel navigation between pointer down and
|
|
198
|
+
up. The needs guide has a short complete example and explains outcome assertions.
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
## Selling and operational checks over MCP
|
|
202
|
+
|
|
203
|
+
Use Stripe's official plugin and the shop skill's batched `stripe_shop_plan` flow.
|
|
204
|
+
Retain write responses, verify, then deploy the compact public links. Until the
|
|
205
|
+
private `stripe_webhook` step completes, checkout names that one remaining step.
|
|
206
|
+
The AI starts the tool; the owner approves Stripe CLI once if needed. No secrets
|
|
207
|
+
or API keys pass through chat. Deploy distinguishes **claimed, not listed** from
|
|
208
|
+
an actual directory listing; publishing is a separate action.
|
|
209
|
+
|
|
210
|
+
On the existing signed-in studio connector (`<site>/mcp/auth`), call
|
|
211
|
+
`studio_function_runs` with optional `name`, `errors`, `before` for actual attempts,
|
|
212
|
+
redacted errors and next due times. Owners and studio-wide `staff` grants can read
|
|
213
|
+
this operational history; per-app staff grants do not expose other apps' runs.
|
|
214
|
+
Do not start `functions runs --url` in a headless shell with no CLI OAuth session:
|
|
215
|
+
that is a different client and would need its own initial browser approval.
|
|
216
|
+
|
|
217
|
+
`app_records` without `role` selects the highest available declared role: signed-in
|
|
218
|
+
roles first, then the largest permission set, with role name as a stable tie-break.
|
|
219
|
+
Each response reports `role`; an explicit role stays explicit. Inspect `app_schema`
|
|
220
|
+
and pass a role when deliberately testing the customer experience.
|
|
221
|
+
|
|
222
|
+
`check --shots` may capture outside the studio, but persistent needs evidence copies
|
|
223
|
+
those pictures into `.studio/checks` and stores studio-relative paths. Keep that
|
|
224
|
+
folder with the Codex evidence. Deploy can render it without outside-path warnings.
|
package/bin/homie-studio.mjs
CHANGED
|
@@ -514,7 +514,7 @@ function print(result) {
|
|
|
514
514
|
// (lib/deploy-state.mjs): the hash `build` printed and the one the live site's manifest answers with.
|
|
515
515
|
...result.games.map((g) => ` ${g.id}: ${g.open ?? g.play}${g.hash ? ` [${deployWords(g)}]` : ''}${g.wall ? ` wall: ${g.wall}` : ''}`), ...(result.removed?.length ? [` no longer on the site: ${result.removed.join(', ')}`] : []), ...(result.notes ?? []).map((n) => ` Note: ${n}`), ...(result.songs ?? []).map((m) => ` song ${m.slug}: ${m.page}`), ...(result.videos ?? []).map((m) => ` video ${m.slug}: ${m.page}`),
|
|
516
516
|
...(result.media?.moved ?? []).map((m) => ` moved to R2 (checked by SHA-256): ${m.path}, still at ${m.url}`), ...(result.media?.failed ?? []).map((m) => ` not moved to R2: ${m.path}: ${m.why}`), '', `Cloudflare: Worker ${result.worker}, D1 ${result.d1}, Durable Objects Table + Lobby${result.r2 ? `, R2 ${result.r2}` : ' (no storage: none needed; `homie-studio storage add` adds it for large media)'}.`,
|
|
517
|
-
result.claim ?
|
|
517
|
+
result.claim ? `The site is ${result.listing??'claimed, not listed'}: list the games with the Homie MCP tool studio_publish, or: npx --no-install homie-studio publish` : 'No directory claim. Listing is the studio’s choice: set homie.directory to true or a directory URL before deploying to request one.',
|
|
518
518
|
...(result.standalone?.length ? ['', ...result.standalone] : []));
|
|
519
519
|
break;
|
|
520
520
|
case 'deploy plan':
|
package/functions/FUNCTIONS.md
CHANGED
|
@@ -87,8 +87,8 @@ homie-studio functions runs --before 101
|
|
|
87
87
|
The command uses the studio's deployed address unless `--url` overrides it. It
|
|
88
88
|
uses the existing owner OAuth connection (one initial browser approval; no office
|
|
89
89
|
key). After approval, checks need no browser. An AI connected to `<site>/mcp` calls
|
|
90
|
-
the owner-
|
|
91
|
-
`before`. Anonymous callers and staff cannot read it.
|
|
90
|
+
the owner/studio-staff `studio_function_runs` tool with optional `name`, `errors` and
|
|
91
|
+
`before`. Anonymous callers and per-app staff cannot read it. A studio-wide `staff` grant can read it; revocation takes effect on the next call. Reuse the authenticated connector at `/mcp/auth`; a headless CLI with no saved OAuth session requires a separate initial browser approval.
|
|
92
92
|
|
|
93
93
|
Results include function, event ID, trigger, started/finished UTC times, outcome,
|
|
94
94
|
error message and attempt. Failed attempts survive successful retries; history
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Check every owner need
|
|
2
|
+
|
|
3
|
+
The JSON array in the app's `CODEX.md` fenced `needs` block is the acceptance
|
|
4
|
+
source. Keep every owner statement, including AI jobs, reminders, results and
|
|
5
|
+
handover. Each need has a unique `id`, `statement`, optional `role` and `steps`,
|
|
6
|
+
and nonempty `assertions`. An unavailable capability stays as a need with an
|
|
7
|
+
empty assertion list and a prose explanation; check reports it not met.
|
|
8
|
+
|
|
9
|
+
Run `homie-studio check <app> --url http://localhost:8787 --shots .checks` with
|
|
10
|
+
`homie-studio dev` running in the same studio. Headless-only needs require no
|
|
11
|
+
Chrome. UI steps and headless steps can be combined in one need and run in order.
|
|
12
|
+
Each need starts with its own saved results; records are shared across needs in
|
|
13
|
+
the run. The default isolated record scope is shared by browsers, MCP calls and
|
|
14
|
+
scheduled effects. `--no-isolate` explicitly uses existing records. Isolation is
|
|
15
|
+
for app records, not a sandbox for external email/SMS/payment calls: use the
|
|
16
|
+
service's test connection for those jobs.
|
|
17
|
+
|
|
18
|
+
## Passing assertions and capture evidence
|
|
19
|
+
|
|
20
|
+
Passing assertions mean **met**, with or without screenshots. A missing capture
|
|
21
|
+
never changes that verdict. For every UI surface without a capture, the result
|
|
22
|
+
names the surface, why it was unavailable (including the browser's error), and
|
|
23
|
+
tells you to rerun with `--shots .checks`. Fix the reported disk/browser error
|
|
24
|
+
first. Successful captures are listed in the saved needs report. Inspect them
|
|
25
|
+
against the owner's scene: automation proves the assertions, not visual quality.
|
|
26
|
+
Headless needs have no screenshots to collect.
|
|
27
|
+
|
|
28
|
+
Click, fill and select actions re-query their selector for up to ten seconds when
|
|
29
|
+
the browser reports a detached/stale element. A permanently unstable control
|
|
30
|
+
reports its surface and selector. Other action failures are not replayed: a
|
|
31
|
+
navigation error after dispatch does not prove that a purchase did not happen.
|
|
32
|
+
|
|
33
|
+
## Customer and staff AI calls and returned results
|
|
34
|
+
|
|
35
|
+
Headless actions require an explicit `role`, inherited from the need or overridden
|
|
36
|
+
on a headless step/assertion. Use an app's declared role, or `owner` for owner-only
|
|
37
|
+
operations. The dev-only signed identity enforces real MCP audiences and record
|
|
38
|
+
capabilities; a customer is not silently promoted to owner. Production OAuth
|
|
39
|
+
approval is unchanged. Missing dev credentials, tools or role permissions produce
|
|
40
|
+
plain not-met reasons.
|
|
41
|
+
|
|
42
|
+
```needs
|
|
43
|
+
[
|
|
44
|
+
{"id":"ai-book","statement":"A customer's AI books in one call","role":"customer",
|
|
45
|
+
"steps":[{"mcp":{"tool":"book","arguments":{"name":"Ada"}},"save":"booking"}],
|
|
46
|
+
"assertions":[{"result":"booking","contains":{"ok":true}}]},
|
|
47
|
+
{"id":"open-roles","statement":"Staff AI can ask which roles are still open","role":"staff",
|
|
48
|
+
"steps":[{"mcp":{"tool":"open_roles"},"save":"open"}],
|
|
49
|
+
"assertions":[{"result":"open","path":"roles","contains":["cook"]}]}
|
|
50
|
+
]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use actual tool names, arguments and returned fields from this studio. `save`
|
|
54
|
+
names the returned result; duplicate names fail. `result` reads it. `path` selects
|
|
55
|
+
dot-separated object keys or array indexes, such as `records.0.data.name`.
|
|
56
|
+
`equals` compares the full selected JSON value; `contains` matches a subset of
|
|
57
|
+
object fields, each expected array entry against an actual entry, or a substring.
|
|
58
|
+
`text` checks a string for one substring or every string in an array. Use `{"$result":"booking.id"}` anywhere in a subsequent step or assertion
|
|
59
|
+
to refer to a saved value, without string interpolation. A missing
|
|
60
|
+
result/path, wrong value or malformed assertion stays not met, naming the failed
|
|
61
|
+
condition. Standard studio tool envelopes are unwrapped to their `data` value;
|
|
62
|
+
other tools retain their structured content or MCP result.
|
|
63
|
+
|
|
64
|
+
## Schedules, records and results
|
|
65
|
+
|
|
66
|
+
A `schedule` step invokes a named declared scheduled function through the local
|
|
67
|
+
MCP dispatcher, with a simulated timestamp in epoch milliseconds. It runs the
|
|
68
|
+
handler headless and reports handler failures. This is a simulated tick, not
|
|
69
|
+
proof that a deployed cron fired or an external message reached a person. Assert
|
|
70
|
+
the actual resulting record or queue entry; do not just assert the trigger's ID.
|
|
71
|
+
The handler still needs a declared role with the relevant record capabilities.
|
|
72
|
+
|
|
73
|
+
```needs
|
|
74
|
+
[
|
|
75
|
+
{"id":"remind","statement":"Daily reminders queue for booked guests","role":"owner",
|
|
76
|
+
"steps":[{"schedule":{"name":"reminders","at":1800000000000}}],
|
|
77
|
+
"assertions":[{"role":"staff","records":{"collection":"reminders"},
|
|
78
|
+
"contains":{"records":[{"data":{"name":"Ada","state":"queued"}}]}}]},
|
|
79
|
+
{"id":"results","statement":"Staff can read the completed result","role":"staff",
|
|
80
|
+
"assertions":[{"records":{"collection":"results","id":"one"},
|
|
81
|
+
"contains":{"data":{"status":"complete"}}}]}
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`records` uses the real `app_records` read tool, bound to this app, the named role
|
|
86
|
+
and this check's isolation scope. Supply collection and optional ID as accepted by that tool. Use its actual response shape (a single record versus
|
|
87
|
+
a list). Create fixtures with steps before asserting them; fresh runs start empty.
|
|
88
|
+
|
|
89
|
+
## Owner AI events and webhook handoff
|
|
90
|
+
|
|
91
|
+
Call `studio_events_read` to prove the feed contains the event, or use MCP Events
|
|
92
|
+
`events/poll` with an explicit cursor to prove event retrieval. `events/list`
|
|
93
|
+
checks discovery. `resources/read` also works and preserves its MCP `contents`
|
|
94
|
+
array. These prove the studio exposes an event to the named role; they do not
|
|
95
|
+
claim an external AI held a live connection or acted on it.
|
|
96
|
+
|
|
97
|
+
```needs
|
|
98
|
+
[
|
|
99
|
+
{"id":"owner-feed","statement":"The owner's AI can read new bookings","role":"owner",
|
|
100
|
+
"steps":[{"mcp":{"tool":"book","arguments":{"name":"Ada"}},"role":"customer"}],
|
|
101
|
+
"assertions":[{"mcp":{"tool":"studio_events_read","arguments":{"feed":"bookings"}},
|
|
102
|
+
"contains":{"events":[{"type":"record.changed","data":{"data":{"name":"Ada"}}}]}}]},
|
|
103
|
+
{"id":"mcp-events","statement":"Owner AI retrieves booking events through MCP Events","role":"owner",
|
|
104
|
+
"assertions":[{"mcp":{"method":"events/poll","params":{"name":"bookings","cursor":"v1:bookings:0"}},
|
|
105
|
+
"contains":{"events":[{"name":"bookings"}]}}]},
|
|
106
|
+
{"id":"webhook","statement":"The declared owner webhook accepts a signed test event","role":"owner",
|
|
107
|
+
"steps":[{"mcp":{"tool":"studio_events_webhook_test","arguments":{"feed":"bookings"}},"save":"delivery"}],
|
|
108
|
+
"assertions":[{"mcp":{"tool":"studio_events_webhook_status","arguments":{"feed":"bookings"}},
|
|
109
|
+
"waitMs":5000,"contains":{"deliveries":[{"event":{"$result":"delivery.id"},"state":"complete"}]}}]}
|
|
110
|
+
]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Declare the feed/audience and webhook first using the existing functions guide.
|
|
114
|
+
The webhook test sends an explicitly synthetic event to the declared receiver;
|
|
115
|
+
match the saved delivery ID to avoid mistaking an older delivery for this test.
|
|
116
|
+
Use `studio_events_webhook_status` for subsequent attempts and errors.
|
|
117
|
+
A status assertion proves the receiver's acknowledgement, not its downstream
|
|
118
|
+
email/SMS or AI work. Read-only MCP/records assertions make one call by default. For asynchronous
|
|
119
|
+
effects, set `waitMs` (0–10000) to re-read until the expected value appears.
|
|
120
|
+
Tool/permission errors fail immediately. Saved results are immutable and are
|
|
121
|
+
never retried. Never put a mutating tool in an assertion; use a step once and
|
|
122
|
+
assert its saved result or durable effect. Unknown methods/tools and denied feeds
|
|
123
|
+
fail explicitly. Secrets do not belong in the needs block.
|
|
124
|
+
|
|
125
|
+
## Handover files
|
|
126
|
+
|
|
127
|
+
```needs
|
|
128
|
+
[
|
|
129
|
+
{"id":"handover","statement":"The owner has AI connection and reminder instructions",
|
|
130
|
+
"assertions":[{"file":"HANDOVER.md","text":["/mcp","Reminders run daily"]}]}
|
|
131
|
+
]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`file` is relative to the studio root. The file must exist and be readable; `text`
|
|
135
|
+
checks all requested contents. Without `text` it proves only existence/readability.
|
|
136
|
+
Use this for handover instructions and exported text results; use `records` for
|
|
137
|
+
live structured results. Missing files and missing text name the exact failure.
|
|
138
|
+
|
|
139
|
+
## Keep controls connected during delayed refreshes
|
|
140
|
+
|
|
141
|
+
Never replace a button under a press. A delayed fetch can finish between pointer
|
|
142
|
+
down and pointer up; replacing the node cancels its click/navigation and loses
|
|
143
|
+
focus. Create interactive nodes once, key repeated items by stable record IDs,
|
|
144
|
+
and update text/attributes in place. Keep pending/disabled state deliberate.
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
const choose = document.createElement('button');
|
|
148
|
+
choose.textContent = 'Choose crew';
|
|
149
|
+
choose.addEventListener('click', () => selectRole('crew'));
|
|
150
|
+
controls.append(choose);
|
|
151
|
+
async function refresh() {
|
|
152
|
+
const { open } = await loadRoles();
|
|
153
|
+
choose.textContent = `Choose crew (${open} places)`;
|
|
154
|
+
// Keep this same button connected; do not replace controls.innerHTML here.
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The runner can retry a detected stale handle before dispatch; it cannot infer
|
|
159
|
+
that an app silently cancelled a press after dispatch. Both stable DOM updates
|
|
160
|
+
and an assertion on the navigation's outcome are necessary.
|
package/guides/app/SKILL.md
CHANGED
|
@@ -100,7 +100,7 @@ The Codex's `needs` fenced block is a JSON array, one entry per need from the re
|
|
|
100
100
|
|
|
101
101
|
Steps support `fill`, `select`, `click: true` and `reload: true`; surfaces are `wall`, `phone`, `phone-two`, `tablet`, `kiosk` and `staff` (a tablet viewport). Set a need’s `role` to the declared role to prove. Each assertion names its surface; only the named screens are required. Assertions use a visible selector with optional contained text, or an observed effect. An honestly unavailable capability remains in the block with no assertions and a plain explanation in the prose; check reports it not met. Do not delete, weaken or replace a need to get green. Static needs such as accurate prices may have no action steps. Use semantic attributes on real visible scene elements for testability, never hidden QA-only counters.
|
|
102
102
|
|
|
103
|
-
Run build and the shared-action check, then the needs step runs on those real browsers. Save captures with `--shots .checks`. The result contains each statement, met/partly/not, the assertion result and captures of
|
|
103
|
+
Run build and the shared-action check, then the needs step runs on those real browsers. Save captures with `--shots .checks`. The result contains each statement, met/partly/not, the assertion result and available captures of named surfaces; `.studio/checks/<id>-needs.json` drives the Codex's Needs status. Redraw `codex <id>` after checking. Passing a selector assertion is evidence, not a visual judgement: read every capture and perform the full flows as owner and customer using the playtest skill. If the picture fails the words, it is not done even with green assertions.
|
|
104
104
|
|
|
105
105
|
For staff flows, sign in through the existing local owner link and prove the transition in real Chrome. Keep evidence in the Codex alongside the automated flows. Confirm unauthorized writes are refused and records remain after all screens close. Never call an untested privileged path passed. Before final handover, show the need table with evidence and explicit remaining gaps. If the starter or a board of boxes is still visible, return to the scene design and build it.
|
|
106
106
|
|
|
@@ -252,8 +252,8 @@ a notification or a person heard audio. Observations reset before each need.
|
|
|
252
252
|
After reloads and rebuilt frames, check waits for online state, completed arrival,
|
|
253
253
|
a hidden loading cover and two frames before assertions/captures. Timeout evidence
|
|
254
254
|
names the surface and selector/effect it awaited. Dialogs are automatically accepted
|
|
255
|
-
and reported. Read retries recover detached frames
|
|
256
|
-
|
|
255
|
+
and reported. Read retries recover detached frames. Click/fill/select retry detached elements by
|
|
256
|
+
re-querying for up to ten seconds; other dispatched action failures are not replayed. `dev` rebuilds root HTML, CSS and JS as well as source and map
|
|
257
257
|
changes. Unavailable sandbox Web Storage uses frame-local memory; use app records
|
|
258
258
|
or `net.prefs` for persistence across reloads.
|
|
259
259
|
|
|
@@ -312,3 +312,45 @@ Issues and grant Notifications Write and Workers Observability Write. Cloudflare
|
|
|
312
312
|
posts signed events to the client's webhook so new or recurring reliability
|
|
313
313
|
problems reach the AI without polling; Homie hosts nothing for this. See
|
|
314
314
|
[Cloudflare's announcement](https://developers.cloudflare.com/changelog/post/2026-10-13-cloudflare-mcp-events/).
|
|
315
|
+
|
|
316
|
+
## Every need has a check
|
|
317
|
+
|
|
318
|
+
Read [NEEDS.md](NEEDS.md) for the complete executable format and examples for UI,
|
|
319
|
+
customer/staff MCP tools, owner event feeds and MCP Events, webhook delivery,
|
|
320
|
+
simulated scheduled functions, records/results and handover files. Keep existing
|
|
321
|
+
UI steps. Headless steps use an explicit named role and the local dev credential;
|
|
322
|
+
assertions check actual returned values and effects. Missing capabilities stay
|
|
323
|
+
not met with their reason. Passing assertions are met even without captures;
|
|
324
|
+
missing evidence names each surface, its error and the `--shots .checks` remedy.
|
|
325
|
+
|
|
326
|
+
Keep interactive DOM nodes connected across delayed refreshes. Update a button's
|
|
327
|
+
text and attributes in place; never replace a button under a press. The short
|
|
328
|
+
example in NEEDS.md preserves its click listener and focus. A stale-element retry
|
|
329
|
+
helps a replaced handle before dispatch; it cannot recover a silently cancelled
|
|
330
|
+
press. Assert the resulting navigation as well as the button's presence.
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
## Selling and operational checks over MCP
|
|
334
|
+
|
|
335
|
+
Use Stripe's official plugin and the shop skill's batched `stripe_shop_plan` flow.
|
|
336
|
+
Retain write responses, verify, then deploy the compact public links. Until the
|
|
337
|
+
private `stripe_webhook` step completes, checkout names that one remaining step.
|
|
338
|
+
The AI starts the tool; the owner approves Stripe CLI once if needed. No secrets
|
|
339
|
+
or API keys pass through chat. Deploy distinguishes **claimed, not listed** from
|
|
340
|
+
an actual directory listing; publishing is a separate action.
|
|
341
|
+
|
|
342
|
+
On the existing signed-in studio connector (`<site>/mcp/auth`), call
|
|
343
|
+
`studio_function_runs` with optional `name`, `errors`, `before` for actual attempts,
|
|
344
|
+
redacted errors and next due times. Owners and studio-wide `staff` grants can read
|
|
345
|
+
this operational history; per-app staff grants do not expose other apps' runs.
|
|
346
|
+
Do not start `functions runs --url` in a headless shell with no CLI OAuth session:
|
|
347
|
+
that is a different client and would need its own initial browser approval.
|
|
348
|
+
|
|
349
|
+
`app_records` without `role` selects the highest available declared role: signed-in
|
|
350
|
+
roles first, then the largest permission set, with role name as a stable tie-break.
|
|
351
|
+
Each response reports `role`; an explicit role stays explicit. Inspect `app_schema`
|
|
352
|
+
and pass a role when deliberately testing the customer experience.
|
|
353
|
+
|
|
354
|
+
`check --shots` may capture outside the studio, but persistent needs evidence copies
|
|
355
|
+
those pictures into `.studio/checks` and stores studio-relative paths. Keep that
|
|
356
|
+
folder with the Codex evidence. Deploy can render it without outside-path warnings.
|
package/guides/office/SKILL.md
CHANGED
|
@@ -118,7 +118,7 @@ build/deploy; the Worker dispatches due functions without an office browser.
|
|
|
118
118
|
Build and redeploy after upgrading; custom crons are kept. Check the deploy plan's
|
|
119
119
|
cron line. Do not add a default cron to a studio with no declared need.
|
|
120
120
|
|
|
121
|
-
To inspect runs from the owner's AI, call the owner
|
|
121
|
+
To inspect runs from the owner's AI, call the owner or studio-staff MCP tool
|
|
122
122
|
`studio_function_runs` (optional `name`, `errors`, `before`), or run
|
|
123
123
|
`homie-studio functions runs [<name>] [--errors] [--url <studio-site>]`.
|
|
124
124
|
Use the existing owner OAuth connection; never request an office key. Results
|
|
@@ -180,3 +180,29 @@ Issues and grant Notifications Write and Workers Observability Write. Cloudflare
|
|
|
180
180
|
posts signed events to the client's webhook so new or recurring reliability
|
|
181
181
|
problems reach the AI without polling; Homie hosts nothing for this. See
|
|
182
182
|
[Cloudflare's announcement](https://developers.cloudflare.com/changelog/post/2026-10-13-cloudflare-mcp-events/).
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
## Selling and operational checks over MCP
|
|
186
|
+
|
|
187
|
+
Use Stripe's official plugin and the shop skill's batched `stripe_shop_plan` flow.
|
|
188
|
+
Retain write responses, verify, then deploy the compact public links. Until the
|
|
189
|
+
private `stripe_webhook` step completes, checkout names that one remaining step.
|
|
190
|
+
The AI starts the tool; the owner approves Stripe CLI once if needed. No secrets
|
|
191
|
+
or API keys pass through chat. Deploy distinguishes **claimed, not listed** from
|
|
192
|
+
an actual directory listing; publishing is a separate action.
|
|
193
|
+
|
|
194
|
+
On the existing signed-in studio connector (`<site>/mcp/auth`), call
|
|
195
|
+
`studio_function_runs` with optional `name`, `errors`, `before` for actual attempts,
|
|
196
|
+
redacted errors and next due times. Owners and studio-wide `staff` grants can read
|
|
197
|
+
this operational history; per-app staff grants do not expose other apps' runs.
|
|
198
|
+
Do not start `functions runs --url` in a headless shell with no CLI OAuth session:
|
|
199
|
+
that is a different client and would need its own initial browser approval.
|
|
200
|
+
|
|
201
|
+
`app_records` without `role` selects the highest available declared role: signed-in
|
|
202
|
+
roles first, then the largest permission set, with role name as a stable tie-break.
|
|
203
|
+
Each response reports `role`; an explicit role stays explicit. Inspect `app_schema`
|
|
204
|
+
and pass a role when deliberately testing the customer experience.
|
|
205
|
+
|
|
206
|
+
`check --shots` may capture outside the studio, but persistent needs evidence copies
|
|
207
|
+
those pictures into `.studio/checks` and stores studio-relative paths. Keep that
|
|
208
|
+
folder with the Codex evidence. Deploy can render it without outside-path warnings.
|
package/guides/servers/SKILL.md
CHANGED
|
@@ -130,7 +130,7 @@ build/deploy; the Worker dispatches due functions without an office browser.
|
|
|
130
130
|
Build and redeploy after upgrading; custom crons are kept. Check the deploy plan's
|
|
131
131
|
cron line. Do not add a default cron to a studio with no declared need.
|
|
132
132
|
|
|
133
|
-
To inspect runs from the owner's AI, call the owner
|
|
133
|
+
To inspect runs from the owner's AI, call the owner or studio-staff MCP tool
|
|
134
134
|
`studio_function_runs` (optional `name`, `errors`, `before`), or run
|
|
135
135
|
`homie-studio functions runs [<name>] [--errors] [--url <studio-site>]`.
|
|
136
136
|
Use the existing owner OAuth connection; never request an office key. Results
|
|
@@ -181,3 +181,29 @@ Issues and grant Notifications Write and Workers Observability Write. Cloudflare
|
|
|
181
181
|
posts signed events to the client's webhook so new or recurring reliability
|
|
182
182
|
problems reach the AI without polling; Homie hosts nothing for this. See
|
|
183
183
|
[Cloudflare's announcement](https://developers.cloudflare.com/changelog/post/2026-10-13-cloudflare-mcp-events/).
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
## Selling and operational checks over MCP
|
|
187
|
+
|
|
188
|
+
Use Stripe's official plugin and the shop skill's batched `stripe_shop_plan` flow.
|
|
189
|
+
Retain write responses, verify, then deploy the compact public links. Until the
|
|
190
|
+
private `stripe_webhook` step completes, checkout names that one remaining step.
|
|
191
|
+
The AI starts the tool; the owner approves Stripe CLI once if needed. No secrets
|
|
192
|
+
or API keys pass through chat. Deploy distinguishes **claimed, not listed** from
|
|
193
|
+
an actual directory listing; publishing is a separate action.
|
|
194
|
+
|
|
195
|
+
On the existing signed-in studio connector (`<site>/mcp/auth`), call
|
|
196
|
+
`studio_function_runs` with optional `name`, `errors`, `before` for actual attempts,
|
|
197
|
+
redacted errors and next due times. Owners and studio-wide `staff` grants can read
|
|
198
|
+
this operational history; per-app staff grants do not expose other apps' runs.
|
|
199
|
+
Do not start `functions runs --url` in a headless shell with no CLI OAuth session:
|
|
200
|
+
that is a different client and would need its own initial browser approval.
|
|
201
|
+
|
|
202
|
+
`app_records` without `role` selects the highest available declared role: signed-in
|
|
203
|
+
roles first, then the largest permission set, with role name as a stable tie-break.
|
|
204
|
+
Each response reports `role`; an explicit role stays explicit. Inspect `app_schema`
|
|
205
|
+
and pass a role when deliberately testing the customer experience.
|
|
206
|
+
|
|
207
|
+
`check --shots` may capture outside the studio, but persistent needs evidence copies
|
|
208
|
+
those pictures into `.studio/checks` and stores studio-relative paths. Keep that
|
|
209
|
+
folder with the Codex evidence. Deploy can render it without outside-path warnings.
|
package/guides/shop/SKILL.md
CHANGED
|
@@ -42,20 +42,30 @@ calling it; tool argument shapes can change. See https://docs.stripe.com/mcp.
|
|
|
42
42
|
read `/v1/account` to record its account ID. Live mode only after the owner requests it.
|
|
43
43
|
2. Call Homie's `stripe_shop_plan` with `account`, `mode: "test"`, `slots` and
|
|
44
44
|
`observations: []`. CLI equivalent: `homie-studio shop plan --have plan-input.json`.
|
|
45
|
-
That JSON file contains the same fields.
|
|
46
|
-
method,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
That JSON file contains the same fields. `operations` contains every independent
|
|
46
|
+
operation currently ready, with method, path, parameters and create idempotency key.
|
|
47
|
+
Execute the batch through Stripe's official plugin, then replan for dependent work.
|
|
48
|
+
`next` remains the first operation for older clients.
|
|
49
|
+
3. Append `{ "method": "POST", "path": "…", "params": {…}, "body": <Stripe response> }`
|
|
50
|
+
for **writes as well as reads**. Keep this setup's observations across batches.
|
|
51
|
+
Product creation includes its default Price; link creation expands line items.
|
|
52
|
+
Product and Price Search use studio/origin metadata. Existing links are fetched by
|
|
53
|
+
IDs from the verified configuration; Stripe has no Payment Link metadata search.
|
|
54
|
+
Keep `.studio/stripe-mcp.json` when moving the studio to another computer. Without
|
|
55
|
+
it, repeat creates use their idempotency keys; outside Stripe's idempotency retention
|
|
56
|
+
window, recover the studio's existing link IDs before setup to avoid duplicates.
|
|
57
|
+
Follow search `next_page` cursors. Search is eventually consistent: write responses
|
|
58
|
+
are the immediate evidence. On an uncertain write, retry its exact idempotency key;
|
|
59
|
+
never discard successful responses or invent IDs. Start a new read set when checking
|
|
60
|
+
later external edits, changing accounts, or changing mode.
|
|
61
|
+
4. Call `stripe_shop_plan` with `verify: true` using those observations (CLI
|
|
62
|
+
`homie-studio shop verify --have plan-input.json`). Verification checks real fields,
|
|
63
|
+
line items, menus, slot limits and portal settings. It saves compact public Worker
|
|
64
|
+
configuration and provenance to `.studio/stripe-mcp.json`, never API response history.
|
|
65
|
+
Deploy installs those links. Checkout then reports only `webhook-secret` missing;
|
|
66
|
+
it cannot open until signed payment events can confirm orders. Changing shop.json,
|
|
67
|
+
the slot manifest or origin requires verification again. Local test configuration
|
|
68
|
+
goes to `.dev.vars`.
|
|
59
69
|
5. For a deployed HTTPS studio, run `stripe_webhook` (CLI `homie-studio shop webhook`).
|
|
60
70
|
Follow `studio_job`. This uses Stripe CLI only for private webhook installation,
|
|
61
71
|
checks the same account as the MCP, and installs the signing secret and verified
|
|
@@ -63,7 +73,7 @@ calling it; tool argument shapes can change. See https://docs.stripe.com/mcp.
|
|
|
63
73
|
studio profile is not already connected. MCP approval cannot be reused or exported.
|
|
64
74
|
Cloudflare authorization and an existing deployment are prerequisites.
|
|
65
75
|
6. After installation, perform the returned `retire` operations through Stripe MCP to
|
|
66
|
-
archive replaced catalog objects
|
|
76
|
+
archive replaced catalog objects. Use fresh scoped reads for later drift checks. Test a sandbox
|
|
67
77
|
purchase and its signed event, order grant, booking capacity or recurring invoice;
|
|
68
78
|
a browser return is never proof. Stripe CLI `trigger` can send a test event, and
|
|
69
79
|
`events resend <event> --webhook-endpoint <endpoint>` retries a delivery. Check the
|
|
@@ -72,6 +82,19 @@ calling it; tool argument shapes can change. See https://docs.stripe.com/mcp.
|
|
|
72
82
|
|
|
73
83
|
Never create a webhook through model-visible Stripe MCP: its response exposes the signing secret.
|
|
74
84
|
|
|
85
|
+
**Why the separate approval (checked 2026-10-14).** Stripe's
|
|
86
|
+
[event destination API](https://docs.stripe.com/api/v2/core/event-destinations/create)
|
|
87
|
+
also returns its signing secret only in the private create response when explicitly
|
|
88
|
+
included. Thin events still require signature verification and authenticated retrieval
|
|
89
|
+
of event details; they do not supply a secret handoff to Wrangler. The
|
|
90
|
+
[official MCP](https://docs.stripe.com/mcp) documents no credential or secret transfer
|
|
91
|
+
to a studio Worker. Therefore the AI starts `stripe_webhook`, the owner clicks
|
|
92
|
+
Approve once in Stripe's CLI browser page if needed, and the tool completes endpoint
|
|
93
|
+
creation and Wrangler secret installation privately. MCP approval and CLI approval
|
|
94
|
+
are separate. No API key is requested, no secret enters chat, and Homie is never in
|
|
95
|
+
the money path. A connected studio CLI profile needs no further approval.
|
|
96
|
+
|
|
97
|
+
|
|
75
98
|
The owner never handles an API key or signing secret. No Homie backend handles payments.
|
|
76
99
|
The Worker needs only public link configuration and the signing secret; buyers pay
|
|
77
100
|
Stripe directly even when the AI and the owner's computer are offline. The old
|