fix(§22/G-15): make the branch/edit/body subsystem three-tier aware (v0.53.0)
§22 migrated the READ/catalog path to the three-tier (project/collection)
model but the WRITE/branch/body subsystem still hardcoded the default
project's default collection — resolving every meta-resident entry to the
default content repo at rfcs/<slug>.md, ignoring the entry's project (its own
content repo) and collection (a <subfolder>/rfcs/ prefix). An entry outside
the default collection rendered a blank canonical body and every edit/PR/
body-write path hit the wrong file.
- New single resolver: projects.content_repo_for_collection() +
projects.entry_location(config, cid, slug) -> (org, repo, md_path)
(collection -> project -> content_repo + subfolder; falls back to the
default repo for a legacy/unknown collection).
- Every entry write/read path resolves via it: api_branches (body GET + all
branch write paths), api_prs (pr-draft/open/merge/withdraw/review/
resolution-branch), api_graduation (graduate/claim/retire/unretire +
orchestrator + state-flip), api.py mark-reviewed + idea-PR merge/decline/
withdraw + proposal preview, api_metadata. bot.open_metadata_pr and
bot.mark_entry_reviewed gained a file_path param. refresh_meta_branches,
the webhook corpus-refresh dispatch, and the hygiene branch-delete now
span every project's content repo, not just the default.
- New additive collection-scoped body-read routes:
GET /api/projects/{pid}/collections/{cid}/rfcs/{slug}/main and
.../branches/{branch} disambiguate a slug across collections (G-5) and read
the entry's own repo. Slug-only routes kept (now collection-aware via the
cached row). Frontend getRFCMain/getBranch take optional pid+cid; RFCView
threads them (mirrors the v0.52.1 entry-detail fix).
No migration, no config change. Existing default-collection entries
unaffected. Tests: backend resolver + collection-scoped branch/body + graduate-
in-subfolder write path; frontend api unit. backend 677 / frontend 60 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -201,6 +201,37 @@ def content_repo(project_id: str) -> str | None:
|
||||
return row["content_repo"] if row and row["content_repo"] else None
|
||||
|
||||
|
||||
def content_repo_for_collection(collection_id: str) -> str | None:
|
||||
"""The content repo a collection's entries live in (§22 three-tier write
|
||||
path, G-15): collection → project → content_repo. None if the collection or
|
||||
its project is unknown/unset. The per-collection successor to
|
||||
`default_content_repo` for the WRITE path — an entry in a non-default
|
||||
project must read/write that project's repo, not the deployment default."""
|
||||
from . import collections as collections_mod
|
||||
pid = collections_mod.project_of_collection(collection_id)
|
||||
return content_repo(pid) if pid else None
|
||||
|
||||
|
||||
def entry_location(config: Config, collection_id: str, slug: str) -> tuple[str, str, str]:
|
||||
"""The git location `(gitea_org, content_repo, md_path)` of an entry, resolved
|
||||
from its collection (§22 three-tier, G-15).
|
||||
|
||||
Repo: the collection's project content_repo, falling back to the deployment
|
||||
default project's repo when the collection (or its project) is unknown — so a
|
||||
legacy/single-corpus entry still resolves to a usable location rather than an
|
||||
empty repo. Path: `<subfolder>/rfcs/<slug>.md`, or `rfcs/<slug>.md` at the
|
||||
repo root for a default (subfolder-less) collection.
|
||||
|
||||
This is the single resolver the branch/edit/body/metadata/graduation write
|
||||
paths share, replacing the hardcoded `default_content_repo` + `rfcs/<slug>.md`.
|
||||
"""
|
||||
from . import collections as collections_mod
|
||||
repo = content_repo_for_collection(collection_id) or (default_content_repo(config) or "")
|
||||
sub = collections_mod.subfolder_of(collection_id)
|
||||
rfcs_dir = f"{sub}/rfcs" if sub else "rfcs"
|
||||
return config.gitea_org, repo, f"{rfcs_dir}/{slug}.md"
|
||||
|
||||
|
||||
def project_initial_state(project_id: str) -> str:
|
||||
"""§22.4b landing state for new entries in a project's default collection
|
||||
(the per-corpus field moved down to the collection in migration 029).
|
||||
|
||||
Reference in New Issue
Block a user