v0.31.0: meta-only repository topology (ROADMAP #36)
Retire the per-RFC-repo model. RFCs now live in their meta-repo entry (rfcs/<slug>.md) for their whole life; graduation is an in-place super-draft → active state flip that keeps the body in the entry — no repo creation, no body-strip, no five-step transaction, no rollback. SPEC: §1 topology rewritten (one meta/content repository, no per-RFC repos) with a deployer-facing "single content repository" framing; §2 (repo: always-null), §3 (active is in-place), §4, §9.8 (handoff frictions dissolve), and §13 fully rewritten (two-field dialog, "The flip", §13.6 RFC-0001 fold-back record). Code: graduation collapses to open+merge one frontmatter PR; branch/PR/ chat dispatch re-keyed on meta-residency (repo IS NULL) so active RFCs edit on the meta repo exactly as super-drafts do; the two "RFC has no repo" 409 guards removed; promote-to-branch slug-embeds an active RFC's auto-branch (edit-<slug>-<hex>) for shared-repo cache attribution; refresh_meta_branches + hygiene branch-resolution include meta-resident actives; the §9.8 read-only guard + pre_graduation_history scoped to legacy per-repo only; dead bot primitives + GraduateDialog repo field + blocking-PR popover removed. The repo: frontmatter field and the /blocking-prs endpoint are retained (schema stability / informational). Tests: graduation suite rewritten to the flip model; e2e + hygiene updated. Full backend suite 375 passed; frontend builds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+15
-11
@@ -603,7 +603,7 @@ def make_router(
|
||||
repo=repo,
|
||||
slug=slug,
|
||||
file_path=_file_path_for(rfc),
|
||||
is_super_draft=_is_super_draft(rfc),
|
||||
is_super_draft=_is_meta_resident(rfc),
|
||||
original_branch=original_branch,
|
||||
resolution_branch=resolution_branch,
|
||||
)
|
||||
@@ -671,32 +671,36 @@ def make_router(
|
||||
"""Used by the §10 PR-flow read and write paths. Per §17's routing-
|
||||
collapse rule, a super-draft RFC also routes here — its body-edit
|
||||
PRs are meta-repo PRs with pr_kind='meta_body_edit', but the API
|
||||
surface is identical."""
|
||||
surface is identical. Under the meta-only topology (§1) an active
|
||||
RFC is meta-resident too (repo is null) — that is normal, not an
|
||||
error, so there is no per-RFC-repo precondition."""
|
||||
row = _require_rfc(slug)
|
||||
if row["state"] not in ("active", "super-draft"):
|
||||
raise HTTPException(409, f"RFC is {row['state']}")
|
||||
if row["state"] == "active" and not row["repo"]:
|
||||
raise HTTPException(409, "RFC has no repo")
|
||||
return row
|
||||
|
||||
def _is_super_draft(rfc) -> bool:
|
||||
return rfc["state"] == "super-draft"
|
||||
def _is_meta_resident(rfc) -> bool:
|
||||
"""Meta-only topology (§1): an entry lives in the meta repo's
|
||||
`rfcs/<slug>.md` (super-draft or active-in-place) unless it carries
|
||||
a legacy per-RFC `repo:` — which nothing does after the RFC-0001
|
||||
fold-back (§13.6). Drives the body/path/repo dispatch below."""
|
||||
return not rfc["repo"]
|
||||
|
||||
def _owner_repo(rfc) -> tuple[str, str]:
|
||||
if _is_super_draft(rfc):
|
||||
if _is_meta_resident(rfc):
|
||||
return config.gitea_org, config.meta_repo
|
||||
owner, repo = rfc["repo"].split("/", 1)
|
||||
return owner, repo
|
||||
|
||||
def _file_path_for(rfc) -> str:
|
||||
if _is_super_draft(rfc):
|
||||
if _is_meta_resident(rfc):
|
||||
return f"rfcs/{rfc['slug']}.md"
|
||||
return RFC_FILE_PATH
|
||||
|
||||
def _extract_body(rfc, file_contents: str) -> str:
|
||||
"""For super-draft entries the file on disk is the full
|
||||
"""For meta-resident entries the file on disk is the full
|
||||
frontmatter+body envelope; the editable body is entry.body."""
|
||||
if not _is_super_draft(rfc):
|
||||
if not _is_meta_resident(rfc):
|
||||
return file_contents
|
||||
try:
|
||||
entry = entry_mod.parse(file_contents)
|
||||
@@ -760,7 +764,7 @@ def make_router(
|
||||
return row["original_pr_number"] if row else None
|
||||
|
||||
async def _refresh_after_pr_write(rfc) -> None:
|
||||
if _is_super_draft(rfc):
|
||||
if _is_meta_resident(rfc):
|
||||
await cache.refresh_meta_repo(config, gitea)
|
||||
await cache.refresh_meta_branches(config, gitea)
|
||||
await cache.refresh_meta_pulls(config, gitea)
|
||||
|
||||
Reference in New Issue
Block a user