Files
rfc-app/docs/DEV.md
T
Ben Stull 779ba6db59 Slice 1: scaffolding + propose-to-super-draft vertical
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>
2026-05-24 04:31:11 -07:00

7.4 KiB
Raw Blame History

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 §§115 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.

  1. 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.
  2. 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.
  3. 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.
  4. Super-draft body editing per §9.5 + §9.6. Meta-repo edit branches as the unit of work; everything from §8 inherits.
  5. Graduation per §13. The dialog, the five-step transactional sequence, rollback, the pre-graduation history affordance.
  6. Notifications per §15. Last, because every other surface produces signals the inbox receives — notification correctness depends on the producers being in place first.
  7. The §14 chrome. Landing page polish, the /philosophy route, the persistent About link.
  8. 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.py so the webhook re-registers against the right APP_URL.

Conventions

  • Bot writes only via app/bot.py. If a module wants to call app/gitea.py's write methods directly, the spec is right and the module is wrong — the wrapper is the chokepoint that makes the §6.5 On-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.