diff --git a/docs/conventions/topic-docs/CHANGELOG.md b/docs/conventions/topic-docs/CHANGELOG.md index 89fdf46712..b8a076da2e 100644 --- a/docs/conventions/topic-docs/CHANGELOG.md +++ b/docs/conventions/topic-docs/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog — topic-docs convention +## 2.4.3 — 2026-08-15 + +Docs-only: the prune recovery pointer no longer pretends squash-merge +preserves branch ancestry. Step 5 now prescribes the Contents API form +`?ref=` (no `^`), states that unreachable-object +retention is best-effort with no promised lifetime, and makes the +graduation targets (ADR / specs / tracker items) the load-bearing +record. Step 2's "reference the rest" pointer names that pre-prune SHA +plus those targets. (#2699) + ## 2.4.2 — 2026-08-12 Docs-only: the contract-slice lifecycle now documents how to retrieve a diff --git a/docs/conventions/topic-docs/README.md b/docs/conventions/topic-docs/README.md index 38cb6dd06b..57be0676c1 100644 --- a/docs/conventions/topic-docs/README.md +++ b/docs/conventions/topic-docs/README.md @@ -425,9 +425,10 @@ a `-.md` sidecar. pasted into the PR description inside `
` blocks (bodies cap near 64 KB — paste the contract, reference the rest). When the contract exceeds the cap, paste the summary and verification digest in - the body and **name the pruning commit** (or the PR number plus the - path) for everything else — a pointer without a followable ref is not a - preservation. + the body and **name the pre-prune commit SHA** (Contents API form in + step 5) plus where durable outcomes graduated — under squash-merge the + SHA form is best-effort; the graduation targets are the load-bearing + record. 3. Before merge, durable outcomes graduate: architectural decisions and specs through the **knowledge-vault seam** (default: history-preserving `git mv` into `docs/adr/` / `docs/specs/`; remote vault backends @@ -436,23 +437,36 @@ a `-.md` sidecar. 4. A final commit prunes the contract slice `//` (default `docs/topics/`), leaving context pointers (the PR body and the promoted-doc / tracker locations) in its place. -5. **Retrieving a pruned slice after merge.** The task branch is deleted on - merge and GitHub's three-dot PR diff drops pruned files, so - `docs/topics//…` on `main` will not resolve. The pruned content - remains reachable through the merge commit **immediately before** the - pruning commit: +5. **Retrieving a pruned slice after merge (best-effort).** Squash-merge + collapses the task branch into one new commit on `main` and carries + none of its ancestry; the head branch is deleted on merge. GitHub's + three-dot PR diff also drops pruned files, so `docs/topics//…` + on `main` will not resolve. Local `git show :` + fails from a fresh clone until that object is fetched (for example + via `git fetch origin refs/pull//head` when permitted — typically + the machine that wrote the pointer already has it). The Contents API + form `?ref=^` fails for a different reason: it is a + remote lookup, and the squash commit's parent never contained the + slice, so naming the parent of the pruning/squash commit is not a + recovery path regardless of local checkout state. + + While GitHub retains the unreachable object, the Contents API can still + resolve a **pre-prune commit SHA** (the last commit that still + contained the slice — name that SHA in the PR body before merge): ```bash - # pruning commit = the merge commit whose message prunes the slice - gh api "repos/{owner}/{repo}/contents/docs/topics//PLAN.md?ref=^" --jq .size + # pre-prune commit = last commit on the task branch that still held the slice + gh api "repos/{owner}/{repo}/contents/docs/topics//PLAN.md?ref=" --jq .size ``` - Given only a merged PR number, list its commits and take the pruning - commit from that list; use `^` as `ref`. `git fetch origin - refs/pull//head` may be denied by a consumer permission layer — the - Contents API form above works after the branch is gone. Step 2's - "reference the rest" pointer should name that pruning commit (or the PR - number plus path) so the reference is followable without archaeology. + That retention is an implementation detail with no promised lifetime — + convenience, not a recovery guarantee. The load-bearing record is + where durable outcomes graduated (ADR / specs via the vault seam, + tracker items via the work-item seam); the PR body must name those + locations. Given only a merged PR number, list its commits and take + the pre-prune SHA from that list. `git fetch origin refs/pull//head` + may be denied by a consumer permission layer — the Contents API form + above is the followable best-effort pointer after the branch is gone. 6. Enforcement: a required check that the net PR diff (`git diff --name-only base...head`) contains no path under the resolved `/**` (default `docs/topics/**`). GitHub's PR diff --git a/docs/conventions/topic-docs/examples/worked-slice.md b/docs/conventions/topic-docs/examples/worked-slice.md index b94dbe7008..ffea5ef400 100644 --- a/docs/conventions/topic-docs/examples/worked-slice.md +++ b/docs/conventions/topic-docs/examples/worked-slice.md @@ -47,9 +47,11 @@ about to disappear from the diff. 2. Two follow-ups (rate-limit tuning, mobile client migration) become tracker items through the work-items seam; the open question ("do we need per-device revocation?") files as a decision item. -3. The prune commit deletes `docs/topics/auth-token-refresh/`, and its - message plus the PR body point at: the PR description (plan + - verification), `docs/adr/0042`, and the tracker items. +3. The prune commit deletes `docs/topics/auth-token-refresh/`. The PR + body names the graduation targets (`docs/adr/0042`, the tracker + items) as the load-bearing record, and may also name the pre-prune + commit SHA for a best-effort Contents API recovery of the disposed + slice. 4. The required check confirms the net PR diff contains no `docs/topics/**` path. Merge.