Drop "prototype/carryover" framing now that v1 is shipped

SPEC, DEV docs, and code comments still talked about the codebase as
a rewrite-in-progress against an external prototype. With v1 shipped
the framing reads oddly — it implies code is provisional when it's
the production thing. Recast §18 as "the technical stack," strip
"carryover from the prototype" comments across backend (api.py,
chat.py, providers.py) and frontend (DiffView, PromptBar,
SelectionTooltip, modelStyles), and rework SPEC §1 / §18 to introduce
OHM up front rather than as a follow-on to a prototype reference.

Also:
- RUNBOOK: bump Python prereq to 3.11+ to match the production VM
  (was 3.13).
- Remove IMPLEMENTATION-PROMPT.md — the original implementation brief
  is no longer load-bearing.
- Add deploy/DEPLOY-NEW-SESSION-PROMPT.md as the durable
  deploy-handoff prompt for new sessions.
This commit is contained in:
Ben Stull
2026-05-25 10:32:46 -07:00
parent 7c3b8fc133
commit ee6e3491e7
12 changed files with 411 additions and 155 deletions
+37 -40
View File
@@ -1,24 +1,23 @@
# RFC App — Specification
This app hosts the **Open Human Model (OHM)**, the corpus of RFCs the
Wiggleverse framework produces. Each RFC defines one word; the first
defines *human*. OHM is English-first by design: the markdown bodies
are canonical, and the OpenXML APIs and UX surfaces a downstream
system needs to actually let humans and machines interact are derived
from that English source, not authored alongside it. The framework's
*why* lives in [`PHILOSOPHY.md`](./PHILOSOPHY.md); this document is
the binding *what* for the app that hosts OHM.
This is the agreed-upon model for the Wiggleverse RFC Contributor app —
the host for the **Open Human Model (OHM)**, the corpus of RFCs the
framework produces. Each RFC defines one word; the first defines
*human*. OHM is English-first by design: the markdown bodies are
canonical, and the OpenXML APIs and UX surfaces a downstream system
needs to actually let humans and machines interact are derived from
that English source, not authored alongside it. The framework's *why*
lives in [`PHILOSOPHY.md`](./PHILOSOPHY.md); this document is the
binding *what* for the app that hosts OHM.
This is the agreed-upon model for the rewrite of the Wiggleverse RFC Contributor app.
It captures the structural decisions made before any UX work on the main document
pane, per-RFC conversations, revisions, and PRs. Those areas are deliberately
out of scope here and will be designed in a follow-up session that takes this
spec plus the existing prototype as context.
spec as context.
The technical stack is unchanged from the prototype: FastAPI with SSE streaming
on the backend, React + Vite + Tiptap (ProseMirror) on the frontend, Gitea as
the Git host, multiple LLM providers (Anthropic, Google, OpenAI / GitHub
Copilot). The code base is a clean rewrite; the existing app is reference only.
The technical stack: FastAPI with SSE streaming on the backend, React + Vite +
Tiptap (ProseMirror) on the frontend, Gitea as the Git host, multiple LLM
providers (Anthropic, Google, OpenAI / GitHub Copilot).
---
@@ -112,9 +111,9 @@ conflict-free even with concurrent proposers.
Integer `RFC-NNNN` IDs are assigned at graduation time as `max(existing
integer IDs) + 1`. Super-drafts have no integer ID; their stable identifier
is the slug. This avoids the race condition the prototype has (where two
concurrent submissions can try to claim the same number) and means
proposing an idea costs nothing in identifier space.
is the slug. This avoids the race condition where two concurrent
submissions could try to claim the same number, and means proposing
an idea costs nothing in identifier space.
---
@@ -265,8 +264,8 @@ and exact columns are illustrative; the implementing session can adjust.
PRs per §10.6.
- `changes` — structured proposed edits to a branch's document. Each
change is either AI-proposed (from a `<change>` block in an assistant
message, per the protocol carried over from the prototype, §18) or
manually authored (typed directly into the editor). Columns: `id`,
message, per the §18 protocol) or manually authored (typed directly
into the editor). Columns: `id`,
`rfc_slug`, `branch_name`, `thread_id` (nullable; null for direct
manual edits not tied to a thread), `source_message_id` (nullable;
set for AI-proposed changes), `kind` (`ai` | `manual`), `state`
@@ -278,7 +277,7 @@ and exact columns are illustrative; the implementing session can adjust.
contributor acts on the stale card), `acted_by`, `acted_at`,
`commit_sha` (nullable; the bot commit that materialized the
acceptance, see §8.6). The `<change>` / `<original>` / `<proposed>`
/ `<reason>` parsing protocol is unchanged from the prototype.
/ `<reason>` parsing protocol is specified in §18.
- `pr_seen` — per-user, per-PR seen-cursor for the "what changed since
my last visit" mechanism in §10.3. Columns: `id`, `user_id`, `rfc_slug`,
`pr_number`, `last_seen_commit_sha`, `last_seen_message_id`, `seen_at`.
@@ -448,8 +447,8 @@ universe when the field is absent). Where a deterministic single
model must be chosen and the contributor has not picked one — the
§10.2 PR-draft, the §9.1 tag suggestions, the §8.13 "Ask Claude to
propose a fix" invocation from an empty thread — that's the model
used. Per-message picker grain inside a chat thread (the §18
prototype carryover) is preserved: each message can name a different
used. Per-message picker grain inside a chat thread (per §18) is
preserved: each message can name a different
model from the resolved list, and the picker's currently-selected
entry persists across messages within a session.
@@ -632,7 +631,7 @@ between branches.
### 8.1 Layout
The RFC view inherits the three-column shape from the prototype:
The RFC view uses a three-column shape:
- **Left column** — the RFC catalog from §7, unchanged.
- **Center column** — a thin breadcrumb strip at the top showing the
@@ -662,8 +661,8 @@ that branch's thread.
### 8.3 Discuss vs. contribute mode (branch-scoped)
The prototype's discuss-vs-contribute distinction survives, but is
scoped to the current branch rather than global.
The discuss-vs-contribute distinction is scoped to the current
branch rather than global.
- **Discuss mode** is the default on any branch (including main).
The editor is read-only. The chat is enabled (subject to §6's
@@ -856,7 +855,7 @@ DiffView is the durable artifact for inspecting accepted changes in
context.
DiffView is the read-only render surface invoked via a toolbar
toggle, carried over from the prototype per §8.15. It reads from the
toggle (§8.15). It reads from the
`changes` table for the branch, reconstructs the markup for every
accepted change in branch history, and renders the result in-place
where the editor was. Hovering any marked span surfaces a tooltip
@@ -944,8 +943,8 @@ the scroll-to-editor binding. Resolved and stale threads stay in the
data; the chat feed's filter affordances surface or hide them on
demand.
The chat's model picker (the §18 prototype carryover) draws its
option list from the resolved per-RFC set per §6.6 — the
The chat's model picker (§18) draws its option list from the
resolved per-RFC set per §6.6 — the
intersection of the entry's optional `models:` frontmatter (or the
operator universe when absent) with the operator's currently
provisioned providers. An RFC whose resolved list is empty surfaces
@@ -1032,9 +1031,9 @@ surface — under the data model, every AI proposal is a first-class
artifact from the moment it lands, on whatever branch the
conversation produced it on.
### 8.15 Carryovers and implementation-deferred details
### 8.15 Branch-scoped affordances and implementation-deferred details
These prototype affordances carry over with branch-scoped behavior:
These affordances are scoped to the current branch:
the selection tooltip (elaborated in §8.12 as the range-thread
entry point); the review-mode toggle and `DiffView` for inspecting
accepted changes in context (§8.10); the discuss-mode banner
@@ -2376,10 +2375,10 @@ specified* and what is intentionally out of scope for v1.
renders, the Tiptap editor configuration, how the editor handles
rich markdown, headings, links, code blocks.
- **The per-RFC and per-branch chat UX.** Threading model, AI
participation, the discuss-vs-contribute mode distinction from the
prototype, the selection tooltip, the prompt bar, the model picker
chrome (its option-list source is settled in §6.6 / §8.12; the
visual treatment and per-thread persistence remain).
participation, the discuss-vs-contribute mode distinction, the
selection tooltip, the prompt bar, the model picker chrome (its
option-list source is settled in §6.6 / §8.12; the visual treatment
and per-thread persistence remain).
- **The revision flow.** How proposed changes from AI or contributors
appear, the change-card panel, accept/decline/edit, tracked
insertions/deletions in the editor.
@@ -2609,8 +2608,8 @@ The follow-up session will refine this. A minimal starting set:
- `POST /api/webhooks/email-bounce` — bounce and complaint receiver
per §15.4; sets the recipient's global email opt-out.
Plus all the chat / streaming / model-picker endpoints inherited from
the prototype, scoped to per-RFC and per-branch threads.
Plus all the chat / streaming / model-picker endpoints, scoped to
per-RFC and per-branch threads.
The `branches/<branch>/...` endpoint family covers both per-RFC-repo
branches and meta-repo edit branches; per §9.5, the routing collapses
@@ -2621,11 +2620,9 @@ right Gitea repo; the API surface is the same.
---
## 18. Carryover from the prototype
## 18. Technical stack
These are confirmed unchanged from the existing app and should be
preserved as-is in the rewrite unless a downstream decision changes
them:
The stack the app is built on:
- FastAPI + SSE for streaming chat.
- React + Vite + Tiptap (ProseMirror) for the editor.