Brings the §1 bot wrapper, the §4 cache (webhook + reconciler), the §5 schema (six numbered migrations), Gitea OAuth + §6 user provisioning, the §7 catalog left pane, and the propose-to-merge vertical: propose modal opens an idea PR against the meta repo, an owner merges from the pending-idea view, the cache picks it up via webhook or reconciler sweep, and the catalog renders the new super-draft. Per §1 the bot is the only Git writer; every commit, branch creation, and PR merge carries the §6.5 On-behalf-of: trailer and an `actions` audit row. Per §4 the cache is never written from a user action — it's webhook+reconciler only. Covered by `backend/tests/test_propose_vertical.py` against an in-process Gitea simulator. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.4 KiB
Build notes
The slicing plan for the v1 build, the current state of the codebase, and the next slice's brief.
The slicing plan
Eight slices carry §§1–15 of SPEC.md end-to-end. The
build does not extend the spec; spec corrections during the build are
rare and surgical and live in the appropriate numbered section per
§19.3's working agreement.
- Repository scaffolding + propose-to-super-draft vertical. The chokepoint that every Git operation flows through (§1 bot wrapper), the §4 cache machinery (webhook + reconciler), the §5 schema, Gitea OAuth + user provisioning, the minimal §7 catalog, and one end-to-end vertical: propose → idea PR → merge → super-draft view.
- The active-RFC view per §8 in full. Editor, branch creation,
per-branch chat with AI participation (the §18
<change>protocol), the change-card panel, accept/decline/edit, manual-edit flushes, sub-threads, flags, DiffView. - The PR flow per §10. Open, review surface (diff + compressed chat), the §10.3 seen-cursor, §10.4 review threads, merge, post-merge, §10.9 conflict resolution.
- Super-draft body editing per §9.5 + §9.6. Meta-repo edit branches as the unit of work; everything from §8 inherits.
- Graduation per §13. The dialog, the five-step transactional sequence, rollback, the pre-graduation history affordance.
- Notifications per §15. Last, because every other surface produces signals the inbox receives — notification correctness depends on the producers being in place first.
- The §14 chrome. Landing page polish, the
/philosophyroute, the persistent About link. - Hardening. End-to-end tests, dev/prod deployment shape, the §12 30/90 branch-hygiene timers.
State of the codebase
Slice 1 — shipped
The repository scaffolding (backend/, frontend/, scripts/,
docs/), the §5 schema as numbered migrations under
backend/migrations/, the §1 bot wrapper (app/bot.py) that is the
single chokepoint every Git write flows through, Gitea OAuth and the
§6.1 user-provisioning row in users, the §4.1 webhook receiver and
the §4.1 periodic reconciler (both writing to the cache; user actions
never do), the §7 left pane (catalog list, search, sort, state-filter
chips, pending-ideas disclosure), and one end-to-end vertical: propose
→ idea PR opens → owner merges → super-draft appears in the catalog →
super-draft view renders the body.
The §17 endpoints exercised so far:
| Method | Path | § |
|---|---|---|
| GET | /api/auth/me |
§6 |
| GET | /api/rfcs |
§7, §17 |
| GET | /api/rfcs/{slug} |
§17 |
| GET | /api/proposals |
§17 |
| GET | /api/proposals/{pr_number} |
§17 |
| POST | /api/rfcs/propose |
§9.1 |
| POST | /api/proposals/{pr_number}/merge |
§9.3 |
| POST | /api/proposals/{pr_number}/decline |
§9.3 |
| POST | /api/proposals/{pr_number}/withdraw |
§9.3 |
| POST | /api/webhooks/gitea |
§4.1 |
| GET | /auth/login / /auth/callback / /auth/logout |
§18 |
What's deferred from slice 1
These were on the §9.1 spec but pushed to Slice 2 because they belong with surfaces that haven't been built yet:
- The propose modal's AI-suggested tags (§9.1) — the AI surface lands with Slice 2's chat wiring. The tag chip input works manually in the meantime.
- The propose modal's AI-drafted PR description (§9.2) — same reason. The PR description is the pitch text for now.
- The decline ceremony's two-step composer-then-preview dialog (§9.3) — the single-step required-comment input is in place; the preview-and-confirm beat is the kind of UX polish that the §19.2 topic "pending-idea view's interaction design (remainder)" should pick up alongside the merge-confirmation ceremony.
- The §9.3 pre-merge chat thread on a pending-idea view and the migration of those threads to the super-draft on merge — depends on Slice 2's chat infrastructure.
These are deferred in the build's working sense — surfaces exist in the spec, but they share infrastructure that's wired in a later slice and would otherwise have to be wired twice.
Environment notes
- Python 3.13. Earlier 3.11+ should also work; 3.13 is what the build session ran on.
- Node 20+ for the frontend.
- Local Gitea on port 3000. Anything that exposes the Gitea v1
REST API works. If you tunnel Gitea elsewhere (e.g. a container,
a Codespace), re-run
scripts/seed_meta_repo.pyso the webhook re-registers against the rightAPP_URL.
Conventions
- Bot writes only via
app/bot.py. If a module wants to callapp/gitea.py's write methods directly, the spec is right and the module is wrong — the wrapper is the chokepoint that makes the §6.5On-behalf-of:trailer and the §6 authorization both consistent. - Cache writes only from
app/cache.py. User actions trigger Git operations via the bot; the cache learns about them when the webhook arrives (or the next reconciler sweep), and never before. This invariant is what makes §4's "Git is truth" claim hold operationally. - Spec corrections during the build are rare and surgical. When running code reveals the spec was wrong at a structural level (per §19.3's working agreement), the correction lands in the appropriate numbered section with a brief note explaining what running code revealed. Spec extensions during the build are not in scope — they accumulate in §19.2.
- §16 stays deferred. Body full-text search, per-RFC model picker, funder role, persistent accepted-change markup, slug renames — these are not shipped in any slice. They earn their own topic sessions when use surfaces evidence they matter.
Next slice
Slice 2: the active-RFC view per §8.
The active-RFC view inherits the three-column shape (§8.1), opens
on main in discuss mode by default (§8.2), supports the §8.3
discuss-vs-contribute mode flip on non-main branches, hosts §8.4's
per-branch chat with AI participation (§18's <change> protocol
parsing into changes rows per §8.6), the §8.8 change-card panel
with §8.9's accept / decline / edit-before-accept resolution, the
§8.10 tracked-change markup and DiffView toggle, the §8.11 manual-
edit flushes, the §8.12 range and paragraph sub-threads, the §8.13
flag affordance, and the §8.14 discuss-mode buffer.
The carryover assets that belong to Slice 2 are in the prototype
under /Users/benstull/projects/wiggleverse/rfc-app-prototype/:
frontend/src/components/Editor.jsx,ChatPanel.jsx,ChangePanel.jsx,PromptBar.jsx,SelectionTooltip.jsx,DiffView.jsx,ModelPicker.jsx— Tiptap config, the<change>parser, the selection-quote machinery, the model-picker UX.backend/providers.py,backend/chat.py— the multi-provider abstraction and the SSE-streaming chat layer.
These are §18 carryovers; reuse the working code rather than
rewriting. The prototype's data model and permission shape do
not carry; this codebase's threads, thread_messages, changes,
changes.thread_id, the §6 four-role model, and the per-branch
chat thread are the canonical shape for Slice 2 to wire against.