# LWL Platform — Milestone Status

**Last updated:** 2026-05-12
**Maintainer:** Lovable agent (regenerated each turn that ships meaningful work)
**Format rule:** one milestone per `## M*` heading, one task per `- [ ]` / `- [x]` line. The roadmap docx generator parses this verbatim — keep the structure stable.

---

## M0 — App shell, auth, profiles, RLS baseline

**Acceptance:** Signup → profile created → `/v/:handle` renders empty state.
**Status:** ✅ Done

- [x] TanStack Start app shell with route tree
- [x] Lovable Cloud auth (email + Google), email confirmation required
- [x] `profiles` table with handle, display name, bio, mode
- [x] `user_roles` table + `has_role()` security-definer function
- [x] RLS deny-by-default on all 32 tables
- [x] `/v/:handle` renders for empty profile

---

## M1 — Public `/aiq` methodology + rolling AIQ on profiles

**Acceptance:** `/aiq` renders all 12 sections of `aiq-spec.md` verbatim. Score-band table shows both 0–100 and 200–1000. Council voice matrix is a real grid. Rolling AIQ visible on `/v/:handle` with sparkline.
**Status:** ✅ Done (this turn)

- [x] `/aiq` route exists
- [x] Download spec (.docx) + open canonical spec (.md) buttons
- [x] Render full aiq-spec.md verbatim (markdown → React, GFM tables)
- [x] Anchor TOC for the 12 sections
- [x] Council voice matrix renders as a real Word-like grid
- [x] Score band table shows 0–100 and 200–1000 in parallel columns
- [x] `/v/:handle` shows rolling AIQ score + band chip + "as of" timestamp
- [x] Sparkline renders from existing critique history

---

## M1.5 — Council 2.0 (deep-scan probe + sharper anchors)

**Acceptance:** Picker has a "Deep scan" tab. Scan returns 3 picked voices (each with reason + deepest question) and a 5-dimension probe of the idea. Anchor pool trimmed 25 → 15. Forbidden-copy guard committed.
**Status:** ✅ Done

- [x] Anchors trimmed 25 → 15 (3 per discipline)
- [x] `councilProbe` server fn (Gemini 2.5 Flash, structured Zod output)
- [x] Picker "Deep scan" tab with reason + deepest question per voice
- [x] 5-dim probe (desirability / feasibility / viability / defensibility / ethics)
- [x] `src/lib/copy-rules.ts` — forbidden scarcity-copy patterns
- [x] Wire deep_scan context into `chatWithCouncil` system prompt

---

## M2 — Council scoring pipeline (5 voices, 5 dims, confidence intervals)

**Acceptance:** Submitted artifact yields a stamped `scores` row with `rubric_version=2.0.0`, dim breakdowns, per-dim confidence interval.
**Status:** ⏳ In progress

- [x] Migration: `scores`, `council_runs`, `rubric_versions` tables + RLS
- [x] Critique pipeline writes real `council_runs` + per-dim `scores` (rubric v2.0.0) on every successful grade; UI surfaces a "Council v2.0.0 saved" badge with `needs_review` flag
- [ ] Edge function: pick 3 of 5 voices by declared project type
- [ ] Edge function: 5-dim scoring with per-dim confidence interval (per-voice variance)
- [ ] Project → 4-lens back-compat projection in `aiq.ts`
- [ ] Drift / low-confidence dims flagged for human review before publish

---

## M2.5 — Share & Outcomes (AIQ as a credential)

**Acceptance:** A user can share their AIQ to LinkedIn / X / copy-link from `/v/$handle` with a generated OG card. Verified outcomes (internship, college app, job, client win, press) can be tagged to a critique and surfaced on a public, opt-in `/outcomes` wall feeding the homepage proof rail.
**Status:** ⏳ Not started

- [ ] Real global counter (pitches, countries, median AIQ, top climber) wired from `critiques` + `profiles` aggregates, cached 10 min
- [ ] OG image route `/og/v/:handle.png` — score, band, radar, weakest lens
- [ ] One-click share to LinkedIn / X / copy-link from `/v/$handle` and `/dashboard`
- [ ] "Add to LinkedIn" deep-link prefilled with handle + tier
- [ ] Migration: `outcomes` table (kind, note, proof_url, critique_id, public) + RLS
- [ ] `/dashboard/outcomes/new` capture form
- [ ] Public `/outcomes` wall (opt-in, moderated) feeding homepage `OutcomesRail`
- [ ] `/v/$handle` CTAs: "Use as Common App link", "Use as Antler / YC application link"

---
## M3 — Capstone rubric builder + dual-track submission view

**Acceptance:** Educator can author a rubric. Capstone submission shows school grade and AIQ side-by-side. School grade does **not** feed rolling AIQ.
**Status:** ⏳ Not started

- [ ] Migration: `rubric_criteria` table + RLS for educator role
- [ ] Migration: `capstone_submissions.school_score` jsonb column
- [ ] `/educator/rubrics` builder UI (criteria, weights, anchors)
- [ ] `/capstone/:id` dual-track view
- [ ] Confirm school grade is excluded from `aiq_rolling` recompute

---

## M4 — Sponsor console + band-gated visibility

**Acceptance:** Sponsor can filter builders by band/skills. Intro request routed via mentor with audit log entry.
**Status:** ⏳ Not started

- [ ] `/sponsor` search with band, skills, track, region filters
- [ ] Bounty visibility gated by band (Maker+ for paid, Architect+ for invite-only)
- [ ] Intro request routed through mentor with accept/decline by builder
- [ ] PII redaction enforced — no raw email exposure

---

## Changelog

- **2026-05-11** — Council 2.0 shipped: anchors trimmed 25→15, new `councilProbe` server fn, "Deep scan" picker tab with reason + deepest question per voice + 5-dim probe. `copy-rules.ts` guard added (NYU prof feedback: kill scarcity copy).
- **2026-05-11** — `/roadmap` route added (renders parsed `status.md`). Roadmap docx now also written to `public/lwl-roadmap.docx`. Header nav link added.
- **2026-05-10** — `/aiq` rebuilt to render full aiq-spec.md verbatim. Living roadmap docx generator added (`scripts/gen_roadmap_docx.mjs`). M0 + M1 marked done. First `/mnt/documents/lwl-roadmap.docx` shipped.
- **2026-05-10** — `/aiq` summary page + spec download/open buttons added.
- **2026-05-10** — AIQ v2 spec ratified at `.lovable/aiq-spec.md` (rubric_version 2.0.0). Word-doc export at `aiq-spec-v2.docx`.
- **2026-05-10** — PRD rebuilt at `.lovable/plan.md` (22 sections).
- **2026-05-11** — Launchpad polish: pitch field + tune row + council made chunky/visible (one bordered card under input). Council picker now syncs from typed pitch/URL into Deep scan (probeContext) and Auto chip surfaces the pitch it'\''s reading.

- **2026-05-11** — Homepage: removed dead Agency band + flat footer. Added "The world is scoring" global AIQ strip (pitches, countries, median, top climber) and "What an AIQ unlocks" outcomes rail (internship, college app, LinkedIn). New M2.5 milestone (Share & Outcomes) added; journey strip on /roadmap now ends with Share.
- **2026-05-11** — M1.5 closed: deep-scan probe (3 picked voices + 5-dim probe) is now plumbed from `CouncilPicker` → `CouncilChat` → `chatWithCouncil` server fn and injected as a `DEEP SCAN CONTEXT` block in the system prompt. Steve answers anchored to the probe's deepest questions, not just the critique JSON.
- **2026-05-11** — M2 kicked off: shipped scoring-pipeline schema (`rubric_versions` seeded with `2.0.0`, `council_runs`, `scores` with confidence-interval columns + `needs_review` flag). All three deny-by-default RLS, owner-only on runs/scores, public read on rubric_versions. Added `getCouncilRunForCritique` server-fn reader so UIs can detect rubric version on rated critiques.
- **2026-05-12** — M2 scoring pipeline wired end-to-end. `persistCouncilRun` server-fn writes one `council_runs` row + N `scores` rows (rubric_version=2.0.0, ±5 confidence band, `needs_review` when score<40, idempotent per critique+rubric). Critique page calls it after `saveCritique`, then re-fetches via `getCouncilRunForCritique` and surfaces a "Council v2.0.0 saved · N dims" badge in the result header (warns when any dim flagged `needs_review`).
