Founder-requested onboarding review by grok (grok-4.6-build), run via ~/.claude/scripts/ask-model.sh a day after codex's review. Read-only: cloned the repo, read docs/ARCHITECTURE.md, all migrations, src/lib, functions/api, all three standalone Workers, and the last ~30 commits, then ran PP_LIBRARY=/tmp/sw-empty-library npm test -- --no-bail (preflight PASS, 21/21 gates; 31 live PDFs staged from public R2). Unlike codex's run — which compared main against the still-unmerged release branch and recommended holding release before merging — grok reviewed main directly at ca40a91a026b986975fb1022c20cc565da724c4a (Merge PR #93, release → main, 2026-09-05 21:57:32 -0400, Ben Wilson), i.e. after that merge had already happened. It does not use a "hold release" framing (there was no longer a release to hold); instead it ranks findings P0/P1/P2 against the merged main.
Headline: independently reaches the same top P0 as codex — the single shared migrations/ directory can apply the wrong migrations to the wrong D1 database — and adds a second P0 that codex treated as documentation debt rather than a release blocker: docs/ARCHITECTURE.md is materially out of date against the current main (wrong wrangler.toml claims, wrong inventory counts, wrong print-flow description, wrong worker-deployment claims). Grok's read on codex's other three P0s is more measured: it surfaces the removed-adult/lead-authority issue too, but files it as P1 (finding #5, "Unstamped session + 0008 membership ⇒ lead powers"), not P0, and frames the household-access problem primarily as a lockout (P1 finding #3: a removed home adult can lose reachable access to a household they still belong to) rather than as codex's privilege-escalation framing. Grok did not independently surface codex's P0-3 (privacy-copy-vs-stored-child-data mismatch) as a standalone headline finding — its closest analog is P1 finding #6, which flags that the privacy page promises deletion by an undeployed retention sweeper, and that the sweeper's own delete-then-log-R2-failure logic is buggy.
Correction (Ray, verified 2026-09-06 07:5x ET against live Cloudflare state): grok had no Cloudflare account access (read-only repo clone only) and repeatedly calls things "undeployed" that are in fact live in production — most importantly sw-retention-sweeper (deployed 2026-09-02, cron 20 4 * * * UTC, verified via GET /workers/scripts just now) and sw-daily-playset (deployed, actively sending; this session sent a real household email through it minutes before this review ran). Every "undeployed" claim below is grok inferring from repo contents alone and should be read as "I found the code for this but have no way to confirm it's live" — not as a verified gap. The migrations_dir (P0) and docs/ARCHITECTURE.md staleness (P0) findings are code-level facts grok could actually verify and stand as reported.
Note on garbling: the raw model output had severe streaming-concatenation corruption — not just in a short preamble, but through roughly the first 75% of the 101KB response (interleaved/duplicated word fragments consistent with overlapping "thinking" traces, plus what appear to be grok's own intermediate scratch notes on individual files/workers). The clean, coherent, well-structured report below is the final ~25% of the raw text, beginning at the line # Scribble Works — fresh-eyes onboarding review. Everything before that point was discarded as unusable; nothing from the garbled section was paraphrased back in.
Scribble Works — fresh-eyes onboarding review
Repo: https://github.com/RayDataCo/scribble-works
Branch: main @ ca40a91a026b986975fb1022c20cc565da724c4a
Head: Merge PR #93 (release → main), 2026-09-05 21:57:32 -0400, Ben Wilson
Method: clone, read, run tests. No edits, no push, no PR. Working tree still clean after npm test.
Tests: PP_LIBRARY=/tmp/sw-empty-library npm test -- --no-bail → preflight PASS, 21/21 gates. Same empty-library convention as CI. Individual suites I captured: customize 404/404, auth 281/281, accounts 243/243, account-api 160/160, playset-curate 174/174, daily-playset 124/124, shopper 92/92, maze 53/53, ugc 52/52, downloads 33/33, playset-storage 10/10. Build staged 31 live PDFs from public R2.
This is a small, well-tested product that has been shipping faster than its present-tense docs can keep up. The security instincts in the last 72 hours (PR #95, PDF proxy, session identity) are real. The operational landmines are also real.
System mental model
Runtime topology
Four runtimes, not one:
| Runtime | What | Data |
|---|---|---|
| Astro static Pages | Home, browse, 31 game pages, planner/shopper, account, legal. No server state. | localStorage tray |
Pages Functions /api/* |
Auth, household APIs, tray sync, customize, art, planner, PDF proxy, downloads, client-error beacon | D1 ACCOUNTS + UGC, KV CUSTOMIZE/DOWNLOADS/SHOPPER, AI Gateway, Resend, Turnstile |
sw-feedback-intake Worker |
Email Routing feedback@ + Twilio POST /sms |
Same UGC D1, private R2 sw-feedback, KV pointer feedback:inbox |
sw-daily-playset Worker |
Hourly cron :30 UTC; POST /run behind X-Run-Token |
Production accounts D1 (read households/children/plans, write deliveries); Resend; public R2 PDF fetch |
sw-retention-sweeper Worker |
Daily cron 04:20 UTC |
Deletes expired UGC/feedback + expired/used magic links + expired/revoked sessions |
Two of those workers are written and tested, not deployed (workers/daily-playset/wrangler.toml:3-5, workers/retention-sweeper/wrangler.toml:3-6). Privacy copy already talks as if the sweeper runs.
Deliberate split: Pages Functions have no R2 binding. Binding paper-playground broke every Pages deploy on 2026-09-01 (wrangler.toml:31-34). Game PDFs are fetched server-side by functions/api/pdf/[slug].js from the public R2 URL. Generated art lives in KV (art:<sha256>, 7-day TTL). Worker R2 is fine; only Pages+R2 is cursed.
Preview vs production: Preview has its own accounts D1 (ce79745e-…); production accounts is 8132dd91-…. KV namespaces and UGC D1 are shared. Preview has no CF_AIG_TOKEN and no RESEND_API_KEY on purpose — generative endpoints answer 200 "unchanged", sign-in mail is the guarded echo path. A green preview smoke is not proof the model rail works.
wrangler.toml is now live config (pages_build_output_dir = "dist" at line 56). Top-level = preview (Cloudflare convention). [[env.production]] = production. Secrets stay out of the file.
Data model
Two D1 databases, one mixed migrations/ folder. That last fact is the sharpest ops issue in the tree.
scribble-works-ugc (a349fa50-…)
| Table | Migration | Role |
|---|---|---|
customizations |
0001 | Validated customize answers. No name. household_hash = sha256(CUSTOMIZE_SALT + ip). retain_until +90d. Promoted rows kept. |
feedback, feedback_contacts |
0002 | Privacy split: hash on the message, raw address only on the contact row. +180d. |
counters |
0004 | Atomic monthly spend caps (UPDATE … SET n = n+1 WHERE n < ? RETURNING n) |
client_errors |
0008_client_errors.sql | Eight-field browser failures. No retain_until. |
scribble-works-accounts (8132dd91-… prod / ce79745e-… preview)
| Table | Migration | Role |
|---|---|---|
households, identities, magic_links, sessions, household_state |
0003 | v1 auth. Tokens stored as sha256(SESSION_SECRET + raw) only. |
adults, adult_identities, household_events, children, consents, consent_events, household_waitlist, household_deletions, classrooms, seats |
0005 | v2 household. Classrooms/seats reserved, no writes. |
household_plans, deliveries |
0006 | Plus plan + one-email-per-household-per-local-day |
session_adults |
0007 | Which adult this session acts as |
session_identities |
0008_session_identities.sql | Which verified identity created the session |
Relationships that matter:
- Home household =
identities.household_id(never rewritten after first sign-in). - Current household =
sessions.household_id(switch updates this). - Actor =
session_adults→adults(role lead/adult). - Membership = an active
adultsrow whose email matches the session identity.identities.household_idis not authorization (src/lib/accounts/store.js:446-458). - Children are household-owned profiles. No login. Full
YYYY-MM-DDbirth date. Cap 8, enforced in the INSERT. - Consents outlive the child row (no
REFERENCES). Sweeper does not read them yet.
Trust / generation ladder
Two ladders live in the repo. Do not conflate them.
README "LOCKED roadmap" (README.md:15): 1 catalog-local → 2 website JIT → 3 MCP → 4 scheduled → (5 turnkey, out of scope). MCP is not in this repo. Scheduled exists as undeployed sw-daily-playset.
What the product actually ships (customize spec stages):
| Stage | What | Network / cost |
|---|---|---|
| Catalog | Browse, tray, recommended playsets | none |
| Age-only customize | Maze/generated slots resized in the browser (source: "code") |
none |
| Planner | Pick 6 from catalog | Anthropic via gateway; anonymous; Turnstile |
| Stage 1 | Rewrite words | Claude; account required; name never in the prompt |
| Stage 3 / 3b | Scene picture / ≤2 icons | Grok Imagine → optional FLUX → mandatory Claude vision evaluator |
| Daily playset | Curate in code, package PDF, email | No model (ruling #20); plus households only; undeployed |
Customize family: well-formed requests never 5xx. Gates return 200 "unchanged" / art: null. That is fail-closed on spend, fail-open on the parent's page.
Planner is the exception: not behind guardSession / GENERATIVE_REQUIRES_ACCOUNT (functions/api/shopper.js:183-190). Abuse blast radius is a model call, not a generated artefact.
Hard constraints (verified in code)
These are the ones I would treat as non-negotiable unless a founder ruling overturns them.
- Raw tokens never persist.
src/lib/auth/tokens.js:5-7. Hash only near D1. Same for invite HMAC (src/lib/accounts/invites.js:5-6). - Cookie is
__Host-sw_session. Secure, HttpOnly, SameSite=Lax, Path=/, no Domain (tokens.js:12,139-141). - No raw IP in stores. Pepper is
SESSION_SECRET, neverCUSTOMIZE_SALT(src/lib/auth/limits.js:3-5). - Child's name-box never reaches the model, KV, or UGC.
engine.js:130;ugc/log.js:14-16,89throwsNameInLogError. A name inside the sentence is not detected (privacy.astro:23-25,107-111). - Answers / geometry / SVG are code-owned. Model never writes them (
recompute.js:1,engine.js:44-47). Client apply istextContent, neverinnerHTML(apply.js:3). - Art evaluator is mandatory. No verdict, no picture (
art-rail.js:136-137). - Gateway: no provider keys from Functions;
cf-aig-collect-log: false. Customize also sendscf-aig-skip-cache: true. Planner does not skip cache (shopper.js:121-123). GENERATIVE_REQUIRES_ACCOUNTunset = required. Only literal"false"opens it (guard.js:20-34). Session gate runs before kill switch.- Monthly ceilings are atomic D1. A D1 error must not fall back to KV (
counter.js:29-32). Daily/burst stay on racy KV on purpose. - Auth/household writes fail closed; customize/shopper/feedback fail open to the parent. Opposite postures, both intentional (
auth/store.js:5-8vscustomize.js:54-56vsfeedback-intake/src/store.js:2-3). - GET must not consume a magic link. Callback is inert; only POST confirm burns it.
nextcomes off the row, never the query string (tokens.js:114-116,confirm.js:100-101). - Same-origin on mutations for account, state PUT, confirm, signout, accept-invite. Origin checked before session (
functions/_lib/account.js:31-33). - No
pack:/pack_page:.validate-taxonomy.mjsfails the build (README.md:4-8). - No R2 binding on Pages.
wrangler.toml:31-34. - Twilio
/smsfail-closed unlessTWILIO_ALLOW_UNSIGNED(local only) (feedback-intake/wrangler.toml:52-57). - Lead-only membership/children/consent. Enforced in
store.jsbefore the first INSERT (store.js:10-13).planis never in a parent SET (plans.js:6). - Accounts migrations never hit UGC. Stated in every 0003/0005/0006/0007/0008_session SQL header and
wrangler-accounts-preview.toml:3-7. The sharedmigrations/directory does not enforce this. - PRs target
release, nevermain.docs/PRE-PR-CHECKLIST.md:114. - Playset is 6 games + 1 parent page.
src/config/terms.ts:18-19. - Browser PDF traffic stays same-origin. Direct R2 only after our proxy 5xx (
package.js:197-199).
Code quality findings
Ranked by blast radius. Concrete, with what I would do.
P0 — will hurt someone if you touch the wrong command
1. One migrations/ directory, two databases, two files named 0008_*.sql.
migrations/0008_client_errors.sql is UGC-only. migrations/0008_session_identities.sql is accounts-only. Root wrangler.toml:266-270 and workers/feedback-intake/wrangler.toml:33 both set migrations_dir at that mixed folder for UGC. wrangler-accounts-preview.toml:21 points accounts-preview at the same folder.
wrangler d1 migrations apply scribble-works-ugc --remote will see 0003/0005/0006/0007/0008_session_identities. The SQL comments say "NEVER apply this to UGC." Comments are not a lock.
Fix: split migrations/ugc/ and migrations/accounts/. Renumber client_errors to 0009 or 0005 on the UGC timeline. Add a preflight gate that fails if any accounts-only file is reachable from a UGC migrations_dir.
2. docs/ARCHITECTURE.md is not present tense.
The file's own rule (ARCHITECTURE.md:7-9): when it disagrees with the notes, this file is wrong. It currently disagrees with the code on:
| Claim | Reality |
|---|---|
wrangler.toml is 100% commentary / has no pages_build_output_dir (417-418, 535-536) |
pages_build_output_dir = "dist" at line 56; bindings are live |
No public/_headers (538-540) |
CSP/HSTS/XFO exist; postbuild hashes inline scripts |
"no purge job exists" (43, 549-550) |
workers/retention-sweeper/ exists (undeployed) |
| Inventory: 25 games, 35 pages, only one Worker | 31 live games; daily-playset + sweeper exist |
| Print flow A: browser → R2 | Browser → /api/pdf/<slug> → Function → R2 |
Feedback workers_dev = true |
Toml is now false |
| §3E "no UI, no endpoint" for accounts v2 | Full /api/account/* + Kids/Adults/Households UI |
If you follow ARCHITECTURE on the next Pages deploy you will either (a) think dashboard still wins, or (b) panic-remove pages_build_output_dir and drop every binding that only lives in the file. The header of wrangler.toml:18-25 is the real rule: first deploy with this file takes bindings from the file, not the dashboard.
Same-file contradiction: wrangler.toml:253-255 still says wrangler ignores the file because there is no pages_build_output_dir.
Fix: rewrite §1 inventory, §3A print flow, §4 deploy, §7 debts against ca40a91. Stop treating ARCHITECTURE as optional when a PR changes topology.
P1 — authz / privacy / undeployed promises
3. Magic-link always opens home. Removal from home locks other memberships.
Confirm upserts the home household (confirm.js:80). After removeAdult from home, openAccount 403s not_a_member before switch (functions/_lib/account.js:54-56). A remaining membership in household B is unreachable unless a B session is still live. Tests treat this as intended (test-account-api.mjs around the lockout case). The 2026-09-05 multi-household ruling does not.
Fix: confirm should land in an active membership (last-used, or a picker). At minimum, /api/me + a "you still belong here" switch that does not require a live session in the target.
4. Generative endpoints still treat a zombie session as signed-in.
/api/state was hardened in PR #95 to call resolveActor (state.js:39-44). customize.js:225, customize-art.js, customize-icons.js only guardSession. A session whose identity is no longer an active adult in sessions.household_id can still spend the model budget. /api/me also skips membership (functions/api/me.js).
Fix: one requireMember(session) used by every cookie-gated Function, not just household APIs.
5. Unstamped session + 0008 membership ⇒ lead powers.
resolveActor (store.js:430-463): if session_adults misses, 0008 only proves membership. Actor then becomes the earliest active lead (461-463). Confirm's adult stamp is best-effort (confirm.js:94-98). If 0007 is not applied, or stampSessionAdult misses (second-household + home-only adult_identities), a non-lead can pass requireLead.
Fix: once session_identities exists, refuse household_fallback for mutations. No stamp, no write.
6. Privacy page promises deletion the sweeper does not yet perform — and the sweeper has a real bug.
privacy.astro:245,284 says rows are deleted after 90/180 days, citing sweep.js. Toml: NOT DEPLOYED. Until it is, that sentence is false.
Worse, the deployed-when-ready code does not match its own comment:
// The photos go FIRST. If the row survives a failed R2 delete the next run
// retries it; ...
...
return { deleted: await deleteByIds(db, 'feedback', 'id', rows.map((r) => r.id), opts), photos };
R2 failure is logged; the row is still deleted. Orphaned photos, and the next run cannot see the keys. Test asserts photos === 0, not "row kept."
Sweeper also never touches household_deletions, consents, client_errors, or KV art:*. 0005 documented those as "the sweeper's convention."
Fix: do not ship the privacy sentence until the Worker is on. Gate row-delete on successful R2 deletes. Add household_deletions + a retain_until on client_errors.
7. sw-daily-playset with workers_dev = true and /run dry:false that ignores the kill switch.
workers/daily-playset/wrangler.toml:19-22,43-45. POST /run with a leaked DAILY_PLAYSET_RUN_TOKEN emails any household, cron disabled or not (deliver.js / index.js:43-45). Unauthenticated GET /health reports whether secrets are set. Send happens before the deliveries insert (README:120) — double-send race.
Also: Worker mails households.email only. Second-household adults do not get the playset (open question in the notes; still true).
Fix: workers_dev = false before any real send; cron-only or IP-allow /run; insert-then-send (or a pending status); document the contact-address limitation on /account.
P2 — product holes and maintainability
8. Kids UI is not lead-aware. Non-leads see add/edit/remove; server 403s; errorText has no not_lead branch (account-kids.js). Adults UI hides controls when can_manage is false. Drift.
9. Waitlist / consent / household-delete are store-only. addChild returns waitlist: true; there is no /api/account waitlist route. ARCHITECTURE §3E still describes a UI prompt that does not exist.
10. Invite email_taken copy is a lie. Multi-household shipped. Fail HTML still says "Joining a second household from one address is not something we do yet" (accept-invite.js:74-76). The remaining email_taken path is the pre-identity households.email shape only.
11. Cookie Max-Age is not rolled. rollSession extends D1 expires_at (session.js:27-29). sessionCookie() is only set at confirm/accept. Browser drops the cookie 30 days after mint even if D1 was rolled.
12. GET /api/me?full=1 is a SameSite=Lax navigation. A clicked cross-site link can leak the unmasked address to the page. Masked default is fine; full=1 should be POST or require a header the browser will not send cross-site.
13. /api/customize-icons?debug=1 is on for any signed-in caller. Truncated gateway error strings (customize-icons.js:162-165). Fine for a preview secret; not for production.
14. Planner monthly cap is global and anonymous. Daily customize gate is per-IP (CGNAT shares 3/day; rotating IP bypasses). Shopper comment claims an "IP daily cap" (shopper.js:188) — there isn't one, only 10/h + 1400/month. GENERATIVE_ENABLED does not kill the planner.
15. client_errors has no retention, no origin check, no rate limit. Privacy-minimal, unbounded. Fail-open 204 (client-errors.js:34-54). Fine for a weekend; not for a public POST.
16. Notes order is unspecified in practice. README + PRE-PR: newest first, prepend. notes-index.mjs + file header: newest last. The file currently has 2026-09-05 work at both ends. Agents will keep doing both.
17. PRE-PR / README still say npm test is 13 gates. It is 21. CI smoke job (smoke:header-account, smoke:account-kids) is not in npm test.
18. Pack PDF links are still direct R2 (src/pages/packs/[id].astro), unlike every game/tray/customize link. Frozen archive, but it punches a hole in the "browser PDF traffic stays on our origin" invariant.
19. npm audit: 2 high / 1 low. Astro XSS in define:vars (<6.1.6), sharp/libvips (transitive), esbuild Windows-only. Astro is the one I would actually bump; this site uses inline scripts + CSP hashes so the practical risk is bounded but not zero.
Open questions (cannot resolve from the repo)
These are the ones I would ask before taking a production-touching task:
- Which migrations are actually applied where? Every 0005–0008 file says "applied to NO remote database by this PR." Daily-playset README says "0005 is already there" on production accounts (
workers/daily-playset/README.md:97). Those cannot both be true. Preview vs prod vs UGC all need ad1 migrations list. - Has anyone deployed Pages with
pages_build_output_diractive? If dashboard and toml have drifted, the next deploy drops the extras. - Are
sw-daily-playsetandsw-retention-sweeperdeployed at all? Code says no. Privacy copy says the sweeper's effect is current. - AI Gateway
collect_logsdefault. ARCHITECTURE says the gateway default is on; every request sendscf-aig-collect-log: false. Spec assumes the gateway retains nothing. Per-request vs dashboard — which wins, and is the dashboard still on? - xAI training toggle on the BYOK key. Privacy page assumes Enterprise no-train. Notes say a consumer Grok plan would make that sentence wrong (
IMPLEMENTATION-NOTES.md:2759-2760). - Email Routing rules (hello@, feedback@, catch-all) — agent token had no permission; still verify.
- Twilio webhook URL now that
workers_dev = false. Feedback README still prints a workers.dev/smsURL. - Turnstile widget domains — ARCHITECTURE lists
feat-accounts-v1.scribble-works.pages.dev. Isrelease.scribble-works.pages.devon the widget? - Founder decisions left open in the notes: a B-only adult can never found their own household; daily playset does not fan out to second-household adults;
deliveries.reasoncolumn vs log-only; Italian as a customize language; designed HTML parent-page in the Worker. - Live
PUBLIC_TURNSTILE_SITE_KEYat build time. Omit it and/accountships without a widget (ARCHITECTURE.md:407-408). Is production's last build using the real key?
Pushback
I will not just validate the local conventions.
The shared migrations directory is a bad abstraction, not a clever one. Isolating accounts-preview so UGC is "one typo away" (wrangler-accounts-preview.toml:3-7) while leaving the reverse path wide open is how you get a households table on the UGC database at 11pm. Two directories is boring and correct. Duplicate 0008 prefixes in the same folder is the tell that two people (or two agents) landed migrations without a coordinator.
Shipping code before the matching migration, then feature-detecting sqlite_master on every request, does not scale. It is a reasonable trick for 0005 on a Friday. It is now the production posture for children, plans, adults, session stamps, and client_errors. The running system and the schema are allowed to disagree, and the UI hides the disagreement. That will produce "it works on preview" bugs that are actually "0007 never landed on prod."
ARCHITECTURE as "present tense" is the right rule and it is not being followed. Four days of PRs (#83–#95) added two workers, a PDF proxy, CSP, live wrangler bindings, multi-household, and a session-identity model. The inventory table still describes 2026-09-02. An onboarding agent that trusts docs/ will ship against a topology that no longer exists. Either update it in the same PR that changes topology (PRE-PR already says this, line 109) or stop claiming it is the source of truth.
Privacy copy that cites an undeployed sweeper is the wrong kind of honesty. The rest of privacy.astro is unusually careful (name-box vs sentence, Grok never sees the ask, gateway header). "Individual rows are deleted after 90 days" is the one sentence a regulator would test. Undeployed + a sweeper that deletes the row even when R2 fails is worse than saying "we intend to delete."
workers_dev = true on a Worker that can email children's names is the opposite of the feedback-intake lesson. You already burned that once (audit B H1). Daily-playset repeats it "so the runbook curl works." Use wrangler tail + a custom route.
Anonymous planner + global monthly ceiling is the actual spend-abuse surface, not customize. Customize requires an account and 3/IP/day. Planner is Turnstile + 1400/month shared by the whole internet, and it does not honor GENERATIVE_ENABLED. The written rationale ("the answer is a set of games we already own") is fair for content risk and weak for bill risk.
IMPLEMENTATION-NOTES as a 4k-line append-only log with a generated index that disagrees about top vs bottom will keep eating review time. The proposed split (notes = history, docs/ = now) is correct. Enforce it: PRE-PR should fail if ARCHITECTURE's inventory table doesn't mention a Worker that exists under workers/.
What I would not push back on: __Host- cookies, enumeration-safe auth request, inert GET callback, mandatory art evaluator, atomic D1 ceilings, origin-before-session, name-box redaction asserted by throw, "never 5xx the parent" on generative, tests that pin CHECK lists and "no v3 writer." That layer is better than most production code at this size.
Recent velocity (last ~30 commits)
Almost all of it is 2026-09-02 → 2026-09-05. Two authors: Ray (implementation) and Ben Wilson (merge-to-main).
Themes, in order of weight:
- Accounts becoming a product: v2 household schema → Kids + plan UI → adult invites → multi-household switch → session identity hardening (PR #95).
- Daily playset: migration 0006 + Worker + packaged 7-page PDF email (v2).
- Studio going live: Get Dressed, Bedtime Routine, Clever Crossing, Dots and Boxes, plus audit-E print fixes. Catalog is 31 live games, all slot-marked.
- Platform hardening: CSP, atomic counters, planner no-log header, PDF proxy, client-error beacon, retention sweeper (undeployed).
- Release flow: feature branches off
release; founder shipsrelease→main.
This is a studio that can land a new game, a schema, and an authz model in the same day. The cost is documentation skew and two 0008 files. For delegated work I would assume: code + tests are ahead of docs/ARCHITECTURE.md; IMPLEMENTATION-NOTES.md is the real changelog; remote schema may lag the code; preview does not prove the model rail.
How I will operate on this repo
- Branch from
origin/release, PR torelease. PP_LIBRARYempty dir (orci-fetch-printables) beforenpm test. Never point it at the founder vault from a sandbox.- Touching a prompt/schema/engine → live smoke with
CF_AIG_TOKEN, not a preview deploy. - Touching a game → render gate + look at the PNG.
- Any D1 change: say which database, never
d1 migrations applyfrom a config whosemigrations_dircan see the other database's files — until that is split. - If current-state behavior changes, patch
docs/ARCHITECTURE.mdin the same PR. Prepend or append notes, but not both; I will follow the file-as-it-is (newest work currently exists at both ends) and call out the conflict.
I have not assumed the charter in the private vault; everything above was read out of this clone.
Run metadata
Extracted from .grok-review-raw-2026-09-06.json (deleted after this note was filed):
- Model: grok-4.6-build
- Input tokens: 1,247,712
- Cache-read input tokens: 3,637,888
- Output tokens: 73,597
- Reasoning tokens: 37,053
- Total tokens: 4,959,197
- Total cost: $0.8085115