Start a new SiXiS project

PROJECT-ONBOARDING-V0-1 / PHASE 1 / PASTE-BASED FLOW

Draft 2953e8c5…

PROD ADMIN VIEW · READ-ONLY · WRITES STILL ON LOCAL
Resume this draft in a fresh Claude Code session
Owner: quangholio. Two ways to pick this up:
OPTION A — Bootstrap prompt (works for any operator, no slash command needed)
You are operating as the SiXiS Project Onboarding orchestrator brain (Claude) for a NON-TOMMY operator (no local SiXiS install — all substrate writes go through HTTP endpoints on dashboard.sixis.ai).

A user has initiated a new SiXiS project via the dashboard at https://dashboard.sixis.ai/new-project. They have provided this brain dump:

---
# Sweats v1 — Card 2 (GC Wallet & Ledger) Bootstrap

**Source draft:** d662c946 (Card 1, shipped 2026-05-14)
**This draft:** 2953e8c5-85df-442f-bec3-30bceca97762
**Bootstrap prompt:** `/sixis-pickup d662c946-5083-455f-837e-7399e79ad70b` followed by `Pick up this project and move to Card 2`

---

# Card 2 Handoff — for next chat session

**Prev card:** Card 1 (Foundation & Auth) — shipped + live at sweats.poker
**This card:** Card 2 — **GC Wallet & Ledger** (~1d per spec)
**Cycle:** `879ca7b7` (Sweats v1, locked spec at `~/Documents/Claude/Projects/SixiS/projects/sweats-trading-v1/SPEC.md`)

---

## What you start with (Card 1 is done)

Read these first, in order:
1. [`docs/cards/CARD_1_SPEC.md`](CARD_1_SPEC.md) — narrative spec, decisions register, threat model
2. [`docs/cards/CARD_1_MANIFEST.md`](CARD_1_MANIFEST.md) — pure inventory + verification commands
3. `supabase/migrations/0001_profiles.sql` + `0002_card1_council_deltas.sql` — applied schema

Live state:
- Supabase project: `vaqevyigkgfbjivwofgr` (us-west-2 pooler). DSN in `.env.local` as `SUPABASE_DB_URL`
- Vercel deployed, env vars set: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`
- GitHub: `gh auth login` as `sweatspoker` is the active account on this laptop — `git push origin main` works
- `requireVerifiedUser()` guard at `src/lib/auth/require-user.ts` is the canonical gate for any new post-auth route. Use it.

---

## Card 2 scope (from SPEC.md)

**GC Wallet & Ledger** — per the handoff-doc economics:
- $1 = 10 GC purchase rate (Stripe later — Card 3)
- 100 GC = $1 redemption rate (Card 14)
- Append-only ledger as source of truth; balance is a DERIVED view, never a column on `profiles`
- All GC math must be server-side; no client-side balance trust
- Every GC movement gets a ledger entry with `actor`, `reason`, `idempotency_key`, `prev_balance`, `new_balance`

**Out of scope for Card 2** (per SPEC.md critical-path order):
- Stripe purchase flow → Card 3 (gated on Card 1a + 1b)
- IPO mechanic → Card 5 (gated on attorney signoff — Gate A)
- Order book → Card 7
- Settlement payout → Card 9
- Redemption catalog → Card 14

---

## Council convergence Card 1 surfaced (load-bearing for Card 2)

All 3 voter brains (GPT, DeepSeek, Claude.ai) converged on these for any GC-movement work:
- **GC columns do NOT belong on `profiles`** — keep `profiles` identity-only
- Use a dedicated schema (`ledger.*` or similar) with stricter RLS than `profiles`
- Recommended downstream tables: `accounts`, `ledger_entries`, `orders`, `trades`, `settlements`, `admin_actions`, `idempotency_keys`
- `user_id` from `auth.users` is and stays the immutable join key
- Optimistic concurrency: include `version INTEGER` on any row that gets updated under contention
- Every SECURITY DEFINER function MUST declare `set search_path = public, pg_temp` (Postgres footgun)
- DB-level invariants for any state that drives compliance — don't rely solely on application code

---

## Protocol going forward (established this session — DON'T skip)

1. **Fire council cross-poll EARLY in Card 2** — at the architectural decision points, not after the build. Card 1 surfaced a real security bug only because the council was polled. Tommy will be most strict about GC-movement scrutiny.
2. **Per-brain relay matrix** (memory: `reference_council_architecture_v2.md`):
   - DeepSeek → API via `deepseek_api_v0_1/sixis/deepseek_client.py`, browser fallback at chat.deepseek.com (Expert mode)
   - GPT → ChatGPT desktop app, chat in **sweats.poker** project folder
   - Claude.ai → Chrome MCP, chat in **Sweats.Poker** project folder
   - Gemini → judge + reviewer, NOT voter
3. **At Card 2 closeout:**
   - Have Claude.ai produce `CARD_2_SPEC.docx` + `CARD_2_MANIFEST.docx` as artifacts (Tommy downloads)
   - Save `CARD_2_SPEC.md` + `CARD_2_MANIFEST.md` to `docs/cards/`
   - **MANDATORY: run Gemini reviewer pass on the final state** (`~/.npm-global/bin/gemini --skip-trust --output-format text` piping bundle on stdin + reviewer-role prompt via `-p`). Independent audit, separate from voter cross-poll. Fold real findings; verify against working production (Gemini false-positives on Next 16 + new Supabase key naming).
   - Commit + push
   - Write `CARD_3_HANDOFF.md` so next session picks up
4. **Cross-poll on GC-touching code is mandatory**, not optional. "Doubt is the cross-poll trigger" + GC is the riskiest surface.
5. **No client-side trust** for anything that affects balance or movements. SECURITY DEFINER RPC is the only legitimate writer pattern (same as `submit_age_gate`).

---

## REQUIRED early in Card 2 (council-ratified at Card 1 closeout, poll `0411a731`)

These are not deferrable to "later in Card 2" — they are forcing conditions BEFORE ledger writes can land safely:

1. **Profile-row invariant — defensive lazy-create AND monitoring hook.** On first authed read of `profiles` (in `loadProfile()` or equivalent), if no row exists for `auth.uid()`, INSERT one (with `ON CONFLICT (user_id) DO NOTHING` for idempotency). This masks the symptom of `handle_new_user` trigger failure. ALSO add a monitoring/alert hook that detects silent trigger failures — orphan `auth.users` rows without a `profiles` row should page someone. Lazy-create alone hides the cause; monitoring surfaces it. Claude.ai's exact framing: "lazy-create masks the symptom but doesn't surface the cause."

2. **Audit sibling authed write paths for the `requireVerifiedUser` guard.** Card 1's reviewer finding F3 fixed `/profile/save`. Claude.ai flagged: if Card 2 introduces avatar upload / preferences / wallet preferences / any authed write path, each one needs the same `age_verified` check or it becomes whack-a-mole. Add to your Card 2 checklist: enumerate every authed POST/PATCH route Card 2 introduces and confirm each calls `requireVerifiedUser()` (or equivalent guard) before mutating.

---

## Open follow-ups carried from Card 1 (revisit during/after Card 2)

These are NOT Card 2 scope, but ledger/wallet work may touch them:

| Item | Owner | Why it matters for Card 2 |
|---|---|---|
| CSRF tokens on POST routes | Pre-public-push | Wallet ops are state-changing POSTs — design with CSRF in mind |
| Zod validation on inputs | Pre-public-push | GC amounts especially — validate aggressively |
| `audit_events` emission | Card 1a (co-requisite with Card 2 if interleaved) | Every ledger write should log an audit event |
| Geo-jurisdiction check | Pre-public-push | Real-money pathway needs this before redemption |
| `.env.example` | Pre-public-push | — |
| Automated test suite | Pre-public-push | Ledger math correctness is the highest-leverage test target |

---

## Don't-repeat-this-time gotchas

- **Next.js 16 + Turbopack** still has flaky server-action POSTs in dev — use plain route handlers (`/app/.../route.ts`) for any form target. Pattern established in Card 1.
- **Substrate cycle `879ca7b7` is in local SQLite but NOT in Supabase events FK** — `sixis log-brain-response --cycle-id 879c...` will fail FK. Capture brain responses as `/tmp/*` files instead (worked for Card 1) until substrate sync is fixed.
- **Sweats Supabase Postgres DB password** is in `.env.local` as `SUPABASE_DB_URL` (gitignored). If `.env.local` got blown away, ask Tommy once. Don't loop on region detection — pooler host is `aws-1-us-west-2.pooler.supabase.com:6543`.
- **Vercel CLI** is authed as the wrong account (`tommysixis-2777`). For env-var changes use the dashboard via Chrome MCP (worked at Card 1 closeout). Don't try `vercel link`.
- **Repo-local git author** is `Sweats <valuebet.app@gmail.com>` (per `.git/config`). Don't override.

---

## Suggested opening move for Card 2 chat

```
cd ~/Desktop/sweats-poker && git log --oneline -5
cat docs/cards/CARD_2_HANDOFF.md
cat docs/cards/CARD_1_MANIFEST.md
# Then sketch the ledger schema, draft a council cross-poll question on the schema shape,
# fire it, fold convergence, build, smoke-test, closeout per protocol.
```

End of handoff.


---

## Reference docs in repo (read these first)

- `docs/cards/CARD_1_SPEC.md` — narrative spec, decisions, threat model from Card 1
- `docs/cards/CARD_1_MANIFEST.md` — pure inventory of what shipped + verification commands
- `~/Documents/Claude/Projects/SixiS/projects/sweats-trading-v1/SPEC.md` — full Sweats v1 locked spec sheet (all 16 cards)

---

## CURRENT STACK & DEPLOY STATE (auto-injected from substrate)

**Hosting:**
- `dashboard.sixis.ai` → Vercel static export (`ui/`)
- `dashboard.sixis.ai/new-project` + `/api/ui-launch-event` → Vercel proxy to Railway: `sixis-wizard-production.up.railway.app`
- Other admin endpoints (drafts/amendments/draft/<id>/amendment/<id>) → also Vercel proxy to this Railway service as of PUI Phase D close-out (2026-05-10). Honor-system admin gate via ?owner= URL param. Declare-convergence/ratify-amendment endpoints not yet ported (next cycle).

**Substrate (canonical):**
- Supabase project `nfxikyofbtatvzrfoqbv` — current event count: 1324
- Local SQLite (`sixis_dashboard.db`) is an archive after Phase B replay caught up (2026-05-07). Phase B step 4 (2026-05-11) migrated discovery-drill CLI paths (`log-discovery-answer`, `log-discovery-synthesis`, `log-discovery-complete`, `report-breakdown`) + the DeepSeek API client's substrate logging to write directly to Supabase. Remaining SQLite-writing CLI paths sync up via the post-invoke mirror.
- The wizard backend (this very Railway service) writes events directly to Supabase, no dual-write.

**Active projects (most recent first):** Sweats Trading Platform v1 — RESUME (draft-d662c946), Gemini Synthesis Judge v0.1 (gemini-synthesis-judge-v0-1), Active Attention Engine (active-attention-engine)

**Last shipped change:** Built gcloud ADC + venv + gsc_pull.py demand-brief tool; tested end-to-end; scheduled task updated to pull GSC before Batch 3.

**Council relay discipline — CORRECTED MATRIX (ratified by Tommy 2026-05-11T02:14, Universal Shell amendment in flight):**
- `cross-poll` defaults `--auto-relay ON`. The orchestrator (Claude Code session) drives all brains directly. API/CLI is the PRIMARY path for the two non-browser brains; browser control is FOR THE TWO REMAINING BROWSER-ONLY BRAINS ONLY:
  - **DeepSeek (voter)** → API via `deepseek_api_v0_1/sixis/deepseek_client.py` (`call_deepseek`). Browser fallback at chat.deepseek.com (Expert/DeepThink mode) ONLY when the API client returns `ok=False` with `fallback=browser`.
  - **Gemini (judge + reviewer)** → CLI/API via `gemini-synthesis-judge-v0-1/` (and `gemini-cli-judge-wrapper-v0-1/`). No browser path needed.
  - **GPT (voter)** → ChatGPT desktop app via computer-use MCP. New chat created INSIDE the "SiXiS" project folder (per per-project chat-thread rule).
  - **Claude.ai (voter)** → claude.ai via Claude-in-Chrome MCP. New chat created INSIDE the SiXiS project folder.
- Tommy is NOT a packet-routing relay node. Pipeline: prompt DeepSeek first via API (longest reasoning), kick off GPT + Claude.ai in browser windows while DeepSeek streams, capture all three responses in any order they arrive.

**Ratification cadence (extended convergence rule, ratified 2026-05-07):**
- Genuine multi-brain convergence at any tier (1/2/3) = automatic ratification — orchestrator proceeds without explicit Tommy ask.
- "Doubt is the cross-poll trigger" — when orchestrator has uncertainty, fire a cross-poll, don't decide unilaterally and don't ask Tommy.
- Sovereign-only matters (red-line risks, irreversible data destruction, money movement, account creation) still always escalate.

**Discoveries fold into scope (rule established 2026-05-07):** anything surfaced during this drill that's adjacent and relevant folds INTO the project's scope by default — don't punt to followups unless folding shifts the tier.


Wizard IDs (use these in the curl POSTs below — DO NOT change them):
- draft_id: 2953e8c5-85df-442f-bec3-30bceca97762
- cycle_id: 37245c60-914e-443b-bede-66a36fe09099
- owner: ask the user which operator they're acting as (e.g. "quangholio") and use that value verbatim — DO NOT default to "tommy"

## Your job

Per FORCED_RULE_PO_01 (Conversational Discovery Drill), drill the user ONE QUESTION AT A TIME.

The internal checklist below is YOUR scaffolding — NOT an interrogation script for the user. Pick the most upstream open question, ask it, listen, let the answer pivot/collapse/deepen the queue.

Internal checklist:
- intent (the frozen Z1 statement of what they want to build)
- scope (in scope vs explicitly out of scope)
- consumers (who/what uses this)
- constraints (technical, time, resources, external commitments)
- success criteria (how they know it shipped well)
- failure modes (what could break, how they'd detect)
- reversibility / tier classification (Tier 1/2/3)
- required artifacts / deliverables
- known unknowns

Do NOT batch questions. Do NOT pre-load 5+ at once. Per FORCED_RULE_PO_01 this is a hard rule from the project's own Cycle Zero.

## Substrate logging (HTTP, no local CLI required)

After EACH user answer, log it to substrate via curl:
```
curl -sS -X POST https://dashboard.sixis.ai/api/log-discovery-answer \
  -H "Content-Type: application/json" \
  -d '{"draft_id": "2953e8c5-85df-442f-bec3-30bceca97762", "cycle_id": "37245c60-914e-443b-bede-66a36fe09099", "question": "<the question you asked>", "answer": "<their answer>", "owner": "<operator>"}'
```

When you reach pollable sufficiency (the council can disagree productively without first asking what the project is), summarize the sharpened intent and ask the user to confirm. Then log the synthesis:
```
curl -sS -X POST https://dashboard.sixis.ai/api/log-discovery-synthesis \
  -H "Content-Type: application/json" \
  -d '{"draft_id": "2953e8c5-85df-442f-bec3-30bceca97762", "cycle_id": "37245c60-914e-443b-bede-66a36fe09099", "synthesis_text": "<your sharpened-intent summary>", "owner": "<operator>"}'
```

After the user confirms the synthesis, mark discovery complete:
```
curl -sS -X POST https://dashboard.sixis.ai/api/log-discovery-complete \
  -H "Content-Type: application/json" \
  -d '{"draft_id": "2953e8c5-85df-442f-bec3-30bceca97762", "cycle_id": "37245c60-914e-443b-bede-66a36fe09099", "owner": "<operator>"}'
```

Then propose firing the council cross-poll. (Council cross-poll endpoints are not yet HTTP-exposed; for now, the user will need to surface to Tommy/admin to fire R1+R2. This is a known gap — see draft f8b196a0 next phase.)

## Error handling

If anything crashes, the user reports a wizard issue, or you encounter a malformed/unworkable state mid-drill, log a breakdown:
```
curl -sS -X POST https://dashboard.sixis.ai/api/report-breakdown \
  -H "Content-Type: application/json" \
  -d '{"draft_id": "2953e8c5-85df-442f-bec3-30bceca97762", "cycle_id": "37245c60-914e-443b-bede-66a36fe09099", "description": "<what went wrong>", "severity": "blocking", "owner": "<operator>"}'
```

The user can also report breakdowns from the dashboard "⚠ Report friction" button (bottom-right corner of any wizard page).

## Verifying writes landed

Each curl returns JSON like `{"ok": true, "event_id": "..."}` on success or `{"error": "..."}` on failure. ALWAYS check the response. If a write fails, surface the error to the user immediately and DO NOT proceed to the next question — the substrate must reflect every Q&A for the council to deliberate from.

You can verify substrate state any time by fetching:
```
curl -sS https://dashboard.sixis.ai/draft/2953e8c5-85df-442f-bec3-30bceca97762?owner=<operator>
```
Returns the live event timeline rendered as HTML; grep for "discovery_answer_logged" / "discovery_synthesis_logged" / "wizard_step_completed" to confirm.
Paste into any fresh Claude Code chat — Claude runs the discovery drill on the brain dump.
OPTION B — Slash-command shortcut (Tommy's setup only — needs ~/.claude/commands/sixis-pickup.md installed)
/sixis-pickup 2953e8c5-85df-442f-bec3-30bceca97762
Brain dump (raw)
Original input from /new-project. Stored as raw evidence per FORCED_RULE_PO_02; never edited in place.
# Sweats v1 — Card 2 (GC Wallet & Ledger) Bootstrap

**Source draft:** d662c946 (Card 1, shipped 2026-05-14)
**This draft:** 2953e8c5-85df-442f-bec3-30bceca97762
**Bootstrap prompt:** `/sixis-pickup d662c946-5083-455f-837e-7399e79ad70b` followed by `Pick up this project and move to Card 2`

---

# Card 2 Handoff — for next chat session

**Prev card:** Card 1 (Foundation & Auth) — shipped + live at sweats.poker
**This card:** Card 2 — **GC Wallet & Ledger** (~1d per spec)
**Cycle:** `879ca7b7` (Sweats v1, locked spec at `~/Documents/Claude/Projects/SixiS/projects/sweats-trading-v1/SPEC.md`)

---

## What you start with (Card 1 is done)

Read these first, in order:
1. [`docs/cards/CARD_1_SPEC.md`](CARD_1_SPEC.md) — narrative spec, decisions register, threat model
2. [`docs/cards/CARD_1_MANIFEST.md`](CARD_1_MANIFEST.md) — pure inventory + verification commands
3. `supabase/migrations/0001_profiles.sql` + `0002_card1_council_deltas.sql` — applied schema

Live state:
- Supabase project: `vaqevyigkgfbjivwofgr` (us-west-2 pooler). DSN in `.env.local` as `SUPABASE_DB_URL`
- Vercel deployed, env vars set: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`
- GitHub: `gh auth login` as `sweatspoker` is the active account on this laptop — `git push origin main` works
- `requireVerifiedUser()` guard at `src/lib/auth/require-user.ts` is the canonical gate for any new post-auth route. Use it.

---

## Card 2 scope (from SPEC.md)

**GC Wallet & Ledger** — per the handoff-doc economics:
- $1 = 10 GC purchase rate (Stripe later — Card 3)
- 100 GC = $1 redemption rate (Card 14)
- Append-only ledger as source of truth; balance is a DERIVED view, never a column on `profiles`
- All GC math must be server-side; no client-side balance trust
- Every GC movement gets a ledger entry with `actor`, `reason`, `idempotency_key`, `prev_balance`, `new_balance`

**Out of scope for Card 2** (per SPEC.md critical-path order):
- Stripe purchase flow → Card 3 (gated on Card 1a + 1b)
- IPO mechanic → Card 5 (gated on attorney signoff — Gate A)
- Order book → Card 7
- Settlement payout → Card 9
- Redemption catalog → Card 14

---

## Council convergence Card 1 surfaced (load-bearing for Card 2)

All 3 voter brains (GPT, DeepSeek, Claude.ai) converged on these for any GC-movement work:
- **GC columns do NOT belong on `profiles`** — keep `profiles` identity-only
- Use a dedicated schema (`ledger.*` or similar) with stricter RLS than `profiles`
- Recommended downstream tables: `accounts`, `ledger_entries`, `orders`, `trades`, `settlements`, `admin_actions`, `idempotency_keys`
- `user_id` from `auth.users` is and stays the immutable join key
- Optimistic concurrency: include `version INTEGER` on any row that gets updated under contention
- Every SECURITY DEFINER function MUST declare `set search_path = public, pg_temp` (Postgres footgun)
- DB-level invariants for any state that drives compliance — don't rely solely on application code

---

## Protocol going forward (established this session — DON'T skip)

1. **Fire council cross-poll EARLY in Card 2** — at the architectural decision points, not after the build. Card 1 surfaced a real security bug only because the council was polled. Tommy will be most strict about GC-movement scrutiny.
2. **Per-brain relay matrix** (memory: `reference_council_architecture_v2.md`):
   - DeepSeek → API via `deepseek_api_v0_1/sixis/deepseek_client.py`, browser fallback at chat.deepseek.com (Expert mode)
   - GPT → ChatGPT desktop app, chat in **sweats.poker** project folder
   - Claude.ai → Chrome MCP, chat in **Sweats.Poker** project folder
   - Gemini → judge + reviewer, NOT voter
3. **At Card 2 closeout:**
   - Have Claude.ai produce `CARD_2_SPEC.docx` + `CARD_2_MANIFEST.docx` as artifacts (Tommy downloads)
   - Save `CARD_2_SPEC.md` + `CARD_2_MANIFEST.md` to `docs/cards/`
   - **MANDATORY: run Gemini reviewer pass on the final state** (`~/.npm-global/bin/gemini --skip-trust --output-format text` piping bundle on stdin + reviewer-role prompt via `-p`). Independent audit, separate from voter cross-poll. Fold real findings; verify against working production (Gemini false-positives on Next 16 + new Supabase key naming).
   - Commit + push
   - Write `CARD_3_HANDOFF.md` so next session picks up
4. **Cross-poll on GC-touching code is mandatory**, not optional. "Doubt is the cross-poll trigger" + GC is the riskiest surface.
5. **No client-side trust** for anything that affects balance or movements. SECURITY DEFINER RPC is the only legitimate writer pattern (same as `submit_age_gate`).

---

## REQUIRED early in Card 2 (council-ratified at Card 1 closeout, poll `0411a731`)

These are not deferrable to "later in Card 2" — they are forcing conditions BEFORE ledger writes can land safely:

1. **Profile-row invariant — defensive lazy-create AND monitoring hook.** On first authed read of `profiles` (in `loadProfile()` or equivalent), if no row exists for `auth.uid()`, INSERT one (with `ON CONFLICT (user_id) DO NOTHING` for idempotency). This masks the symptom of `handle_new_user` trigger failure. ALSO add a monitoring/alert hook that detects silent trigger failures — orphan `auth.users` rows without a `profiles` row should page someone. Lazy-create alone hides the cause; monitoring surfaces it. Claude.ai's exact framing: "lazy-create masks the symptom but doesn't surface the cause."

2. **Audit sibling authed write paths for the `requireVerifiedUser` guard.** Card 1's reviewer finding F3 fixed `/profile/save`. Claude.ai flagged: if Card 2 introduces avatar upload / preferences / wallet preferences / any authed write path, each one needs the same `age_verified` check or it becomes whack-a-mole. Add to your Card 2 checklist: enumerate every authed POST/PATCH route Card 2 introduces and confirm each calls `requireVerifiedUser()` (or equivalent guard) before mutating.

---

## Open follow-ups carried from Card 1 (revisit during/after Card 2)

These are NOT Card 2 scope, but ledger/wallet work may touch them:

| Item | Owner | Why it matters for Card 2 |
|---|---|---|
| CSRF tokens on POST routes | Pre-public-push | Wallet ops are state-changing POSTs — design with CSRF in mind |
| Zod validation on inputs | Pre-public-push | GC amounts especially — validate aggressively |
| `audit_events` emission | Card 1a (co-requisite with Card 2 if interleaved) | Every ledger write should log an audit event |
| Geo-jurisdiction check | Pre-public-push | Real-money pathway needs this before redemption |
| `.env.example` | Pre-public-push | — |
| Automated test suite | Pre-public-push | Ledger math correctness is the highest-leverage test target |

---

## Don't-repeat-this-time gotchas

- **Next.js 16 + Turbopack** still has flaky server-action POSTs in dev — use plain route handlers (`/app/.../route.ts`) for any form target. Pattern established in Card 1.
- **Substrate cycle `879ca7b7` is in local SQLite but NOT in Supabase events FK** — `sixis log-brain-response --cycle-id 879c...` will fail FK. Capture brain responses as `/tmp/*` files instead (worked for Card 1) until substrate sync is fixed.
- **Sweats Supabase Postgres DB password** is in `.env.local` as `SUPABASE_DB_URL` (gitignored). If `.env.local` got blown away, ask Tommy once. Don't loop on region detection — pooler host is `aws-1-us-west-2.pooler.supabase.com:6543`.
- **Vercel CLI** is authed as the wrong account (`tommysixis-2777`). For env-var changes use the dashboard via Chrome MCP (worked at Card 1 closeout). Don't try `vercel link`.
- **Repo-local git author** is `Sweats <valuebet.app@gmail.com>` (per `.git/config`). Don't override.

---

## Suggested opening move for Card 2 chat

```
cd ~/Desktop/sweats-poker && git log --oneline -5
cat docs/cards/CARD_2_HANDOFF.md
cat docs/cards/CARD_1_MANIFEST.md
# Then sketch the ledger schema, draft a council cross-poll question on the schema shape,
# fire it, fold convergence, build, smoke-test, closeout per protocol.
```

End of handoff.


---

## Reference docs in repo (read these first)

- `docs/cards/CARD_1_SPEC.md` — narrative spec, decisions, threat model from Card 1
- `docs/cards/CARD_1_MANIFEST.md` — pure inventory of what shipped + verification commands
- `~/Documents/Claude/Projects/SixiS/projects/sweats-trading-v1/SPEC.md` — full Sweats v1 locked spec sheet (all 16 cards)
Event timeline (2)
Every event tagged with this draft_id, in chronological order.
project_draft_started claude · 2026-05-15 02:16:37.914458+00:00
Sweats v1 Card 2 draft started (draft_id=2953e8c5-85df-442f-bec3-30bceca97762). Bootstraps next chat session for GC Wallet & Ledger work. Parent: Sweats v1 cycle 879ca7b7, Card 1 shipped.
draft_saved claude · 2026-05-15 02:16:37.914458+00:00
You saved the brain-dump for draft 2953e8c5-85df-442f-bec3-30bceca97762: "# Sweats v1 — Card 2 (GC Wallet & Ledger) Bootstrap **Source draft:** d662c946 (Card 1, shipped 2026-05-14) **This draft:** 2953e8c5-85df-442f-bec3-30bceca97762 **Bootstrap prompt:** `/sixis-pickup d662c946-5083-455f-837e-7399e79ad70b` followed by `Pick up this project and move to Car…