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>
This commit is contained in:
+153
@@ -0,0 +1,153 @@
|
||||
# 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`](../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.
|
||||
Reference in New Issue
Block a user