The control surface for the agent fleet. Separate repo, separate deploy, no connection to the consumer app. Built Aug 13, 2026.
Same CartWise account you use in the app. The console can only be driven by an account on the operator list β signing in with any other account will authenticate but do nothing.
pg_cron + pg_net. Fetches cartshop.net, asserts two stable markers, writes health_checks. Two consecutive failures raise a P0_SITE_DOWN row, deduped to one per 15 min. First result: 200, 15ms, markers found.threads Β· channel_bindings Β· messages Β· runs Β· deliveries Β· feedback Β· errors Β· health_checks. Single-writer lock enforced by a unique partial index. RLS on everything, service-role only.CLAUDE_CODE_OAUTH_TOKEN stored. Claude app installed and narrowed from all repositories to Cartwise + cartwise-ops only β the real-estate repos are out of scope.cartwise, project cartwise-app, Browser JavaScript. Errors only β tracing, replay, logs and metrics all off to protect the free quota.index.html carries the loader tag, service worker moved to shell-1786716292816, old shell cache evicted. Two test events fired and both landed in Sentry: CARTWISE-APP-1 (unhandled ReferenceError) and CARTWISE-APP-2 (deliberate capture). The full path β browser error β Sentry issue β is confirmed working, not assumed.messages-append. The one way anything enters the log: Slack, this console, the in-app widget, every agent. Idempotent on (source_channel, idempotency_key) so an upstream retry is a no-op instead of a duplicate. Fails closed β returns 503 until OPS_APPEND_KEY exists, never accepts an anonymous write.slack-events. Verifies Slack's v0 HMAC signature, rejects anything older than 5 minutes, drops bot and edited messages so the agent can't answer itself. Binds each Slack thread to one spine thread, then hands off to the append API β it never writes to messages itself. Needs the URL saved on the Slack side.| P0 autonomy | Auto-rollback first. Revert to last known-good in ~90s, then a PR for the real fix. Zero unreviewed code ships. |
| Build order | Spine β console β Slack β one agent. Protected. |
| Platform | Claude on Max. No Hermes, no second orchestrator. |
| Grocery number | under $600/month as the promise Β· under $100/week stays as the proof |
| Beta terms | One month free, told to their face, then paid. No card on file, no auto-charge. |
| Dashboard | Own repo, own Pages project, own subdomain. Survives the native-mobile migration. |
OPS_APPEND_KEYProject Settings β Edge Functions β Secrets. Any long random string you generate yourself β openssl rand -hex 32 in your terminal. Same place the Slack secrets live. Until it exists the append API and Slack ingress both refuse every request, which is the correct behaviour, not a bug.https://fibnrlzjoxyllkomhbrp.supabase.co/functions/v1/slack-eventsmessage.channels and app_mention. Do this after step 2 or the challenge fails.| Work | Blocked by |
|---|---|
| CLAUDE.md in both repos β scope + never-touch, so any session knows which world it's in | nothing |
| Supabase schema β messages / threads / runs / feedback / errors, single-writer lock, RLS | nothing |
| POST /messages β one append API, idempotency, fails closed β shipped | β |
| Slack event handler β v0 signature verification, replay window, self-reply guard β shipped | β |
| Knowledge base β compiled from index.src.html + the five real questions | nothing |
| triage agent β prompt, schema, eval set, escalation rules | nothing |
| 5 smoke tests β incl. item-survives-reload, which guards the save path directly | nothing |
| Slack Event Subscriptions URL | you β step 3 |
| fixer agent β GitHub Action, guardrails, severity routing | the Sentry commit |
| Fri | Spine live Β· Slack wired both ways Β· Sentry + uptime Β· CLAUDE.md in both repos |
| SatβSun | triage running on real feedback Β· daily brief posting to Slack Β· KB drafted |
| Mon | concierge in staging β you review 20 real answers before it touches a user |
| Tue | Spine + console + Slack + triage live. fixer opening its first PR. |
Every reply: mirror β explain β act β timeline. Warm, informal, short. Three or four sentences. Names Oleg, never "our support team."
Got it β you added items at the store and they're not showing up at home.
That's an offline save. The app kept them on your phone and hasn't pushed them up yet β nothing's lost.
Open CartWise on wifi and they'll sync in about 5 seconds. Still missing after that? Tell me and I'll get you on a call with Oleg.
Got it β scanner opens but won't read anything on your iPhone.
That's a real bug, not you. I've logged it with your app version and sent it to Oleg.
He's on it, and I'll message you right here when it's fixed. Meanwhile you can add items by name from the search box.
Got it β you want the list split by store so you're not backtracking.
That's a good one and it's on the list now. I can't tell you if or when it'll get built β Oleg decides that off what everyone's asking for.
If it's blocking you, tell me how and I'll flag it higher.
blobHasContent / hadDataRef. Never edit index.html directly. Never merge its own PR.| π΄ Red flags β any hour | Site down Β· data loss Β· auth broken Β· a user reporting a charge Β· error spike Β· security |
| π‘ Everything else | Held for the 7am brief. Bugs, requests, questions, PRs waiting, cost changes |
| Signal | Pass |
|---|---|
| β Week-3 plan built unprompted | The headline. Everything else is a floor. |
| Zero data-loss events | Guard never trips; no household loses items unexplained |
| Sync integrity | No silent offline-save orphans |
| Zero P0s | Site never down, auth never broken |
| Full weekly cycle | plan β list β shop β pantry update, at least once |
| Repo | Holds | Deploys to |
|---|---|---|
Cartwise | The consumer app. index.src.html β build.mjs β index.html + sw.js | cartshop.net |
cartwise-ops private | This console, agent prompts, SOPs, edge functions | ops.cartshop.net |
ops/ folder: the app's Pages project builds from the repo root, so cartshop.net/ops/ would have been a live public URL. Separate repos make that impossible rather than something a redirect rule has to remember to prevent. It also means the fixer working on app code can never touch ops, and the native-mobile migration doesn't drag the console along with it..info/.net for if the console ever becomes its own product.CLAUDE.md stating its scope and its never-touch list. Any session that opens either repo reads it first and knows which world it's in. That's the "logic to make sure we're working in the right place" β it's a file, not a domain.POST /messages. Neither writes to the database directly, neither keeps its own history.| Now | Gated | Opens at |
|---|---|---|
| π Product & Engineering | π£ Growth & Content | β₯300 WAU or first ad dollar |
| π¬ Customer | π° Finance | first revenue or $100 ad spend |
| π Ops & Intelligence | π Trust & Compliance | payments live, >5k users, or PII past email |
| π€ Partnerships & Data | Walmart approval or 2nd retailer | |
| π₯ People & Delegation | first hire |
| Item | Comes back |
|---|---|
| π Paywall & monetization Trial mechanics, auto-renew compliance, price, payment method. Research done and saved. | Before the beta ends |
| Onboarding tutorial First week with the assistant β one week manual β import a recipe. Highest-leverage thing for the week-3 metric. | Before the families land |
| Google Calendar connector β events land in iOS Calendar | 10 min, anytime |
| Business social accounts (IG Β· TikTok Β· YT Β· FB) | Next week β Oleg |
| 2β3 weeks of content generated, ready to paste | Next week β Oleg |
| Partner email β Resend on a subdomain | Before launch |
| Realtime voice β OpenAI Platform, separate billing from ChatGPT Business | Phase 3 |
index.src.html, Oleg strikes what's wrong.