Finish the 1.25.4-dated CI claim sweep #747 deliberately did not complete #869

Closed
opened 2026-08-28 18:52:25 +02:00 by timothy · 2 comments
Owner

Residue from #747 (PR #867), named there rather than implied closed. #747 re-probed the
merge-gating claims it prioritised; it was not a sweep of the corpus, and
ci.actions-credential-scoping now says so explicitly rather than implying coverage.

What is still 1.25.4-dated

1. review-verdict.yml's three comments (lines ~69, ~633, ~746). Deliberately untouched by #747:
#763 was in-progress on that file and its /statuses/{sha} paging work overlaps those lines, so
editing them would have conflicted. Line ~746 is the load-bearing one — it records the COMBINED-endpoint
behaviour for a status POSTed with a user token, which is the creator attribution the H10 allow-list
rests on (#742, #845). A second copy lives at scripts/tests/test_pr_changed_files.py:1679.

2. ci.actions-credential-scoping's own three items. The v1.25.4 scope enum
(access_token_scope.go) and the reqRepoWriter gate (routers/api/v1/api.go) were established by
READING GITEA SOURCE at the version tag — re-running them needs only a source read at v1.27.1, not a
credential. Only the write:package 403 needs a scoped PAT minted against the live instance. #747 did
none of the three.

3. --depth=1 has no merge base (ci.exemption-provenance, scripts/pr-changed-files.sh). #747
split the sentence so the 1.27.1 re-confirmation binds to the compare call only; this clause is
still 1.25.4-dated.

4. Claims deliberately left dated because the cheap probe route is gone, not because nobody looked
— re-state the reason rather than re-deriving it: push-supersession auto-cancel and the
pull_request_target overlap/serialization probes. No workflow triggers on a push to a non-main
branch and main refuses direct pushes, so the disposable scratch-branch route those measurements
used no longer exists. Both are recorded in ci.verdict-write-retarget-fence.

Method that worked in #747, worth reusing

A branch-protection or merge-path question is probeable without touching main: a scratch BASE
branch carries its own protection rule, so the whole experiment is disposable. That is what let #747
measure block_admin_merge_override after #743 had recorded it as source-attested-only on the grounds
that probing it meant merging an unreviewed PR. Derive the population with git ls-files, not from a
list of keys in an issue body.

Done-when

  • Items 1-3 each either re-probed on the current Gitea version, or re-stated as dated with a
    reason that is true today — all three re-established on 1.27.1 (PR #905)
  • The creator-attribution claim in review-verdict.yml specifically settled, since the H10
    allow-list depends on it — re-measured over 4 merged heads on both endpoints; the stated
    MECHANISM was also found wrong in review and corrected (it is CreatorID == -2, not == 0)
  • Any claim that cannot be re-probed says why, and the reason is checked rather than inherited —
    and one such reason turned out to be INVENTED (MCP cancel_run); it now states the true one
  • Adversarial review passed — 5 cold rounds, worktree-isolated, plus a cross-family Codex pass;
    final verdict CLEAN
Residue from #747 (PR #867), named there rather than implied closed. #747 re-probed the merge-gating claims it prioritised; it was **not** a sweep of the corpus, and `ci.actions-credential-scoping` now says so explicitly rather than implying coverage. ## What is still 1.25.4-dated **1. `review-verdict.yml`'s three comments (lines ~69, ~633, ~746).** Deliberately untouched by #747: #763 was in-progress on that file and its `/statuses/{sha}` paging work overlaps those lines, so editing them would have conflicted. Line ~746 is the load-bearing one — it records the COMBINED-endpoint behaviour for a status POSTed with a user token, which is the `creator` attribution the H10 allow-list rests on (#742, #845). A second copy lives at `scripts/tests/test_pr_changed_files.py:1679`. **2. `ci.actions-credential-scoping`'s own three items.** The `v1.25.4` scope enum (`access_token_scope.go`) and the `reqRepoWriter` gate (`routers/api/v1/api.go`) were established by READING GITEA SOURCE at the version tag — re-running them needs only a source read at `v1.27.1`, not a credential. Only the `write:package` 403 needs a scoped PAT minted against the live instance. #747 did none of the three. **3. `--depth=1` has no merge base** (`ci.exemption-provenance`, `scripts/pr-changed-files.sh`). #747 split the sentence so the 1.27.1 re-confirmation binds to the `compare` call only; this clause is still 1.25.4-dated. **4. Claims deliberately left dated because the cheap probe route is gone**, not because nobody looked — re-state the reason rather than re-deriving it: push-supersession auto-cancel and the `pull_request_target` overlap/serialization probes. No workflow triggers on a push to a non-`main` branch and `main` refuses direct pushes, so the disposable scratch-branch route those measurements used no longer exists. Both are recorded in `ci.verdict-write-retarget-fence`. ## Method that worked in #747, worth reusing A branch-protection or merge-path question is probeable **without touching `main`**: a scratch BASE branch carries its own protection rule, so the whole experiment is disposable. That is what let #747 measure `block_admin_merge_override` after #743 had recorded it as source-attested-only on the grounds that probing it meant merging an unreviewed PR. Derive the population with `git ls-files`, not from a list of keys in an issue body. ## Done-when - [x] Items 1-3 each either re-probed on the current Gitea version, or re-stated as dated with a reason that is true today — all three re-established on 1.27.1 (PR #905) - [x] The `creator`-attribution claim in `review-verdict.yml` specifically settled, since the H10 allow-list depends on it — re-measured over 4 merged heads on both endpoints; the stated MECHANISM was also found wrong in review and corrected (it is `CreatorID == -2`, not `== 0`) - [x] Any claim that cannot be re-probed says why, and the reason is checked rather than inherited — and one such reason turned out to be INVENTED (MCP `cancel_run`); it now states the true one - [x] Adversarial review passed — 5 cold rounds, worktree-isolated, plus a cross-family Codex pass; final verdict CLEAN
timothy added the ci-cdpriority: medium labels 2026-08-28 18:52:30 +02:00
timothy added the in-progress label 2026-09-02 00:07:32 +02:00
Author
Owner

Claiming — Claude Code session (Opus 5), bundled with #893.

Both issues are the same mechanism: a claim dated against an old Gitea version that needs re-establishing by reading the v1.27.1 source, then recorded as dated. Verified reachable at the exact tag (raw.githubusercontent.com/go-gitea/gitea/v1.27.1/... → 200) and this instance reports {"version":"1.27.1"}, so the source read and the live instance agree on the version being claimed.

Population will be derived with git ls-files, not from this issue's item list.

Claiming — Claude Code session (Opus 5), bundled with #893. Both issues are the same mechanism: a claim dated against an old Gitea version that needs re-establishing by reading the v1.27.1 source, then recorded as dated. Verified reachable at the exact tag (`raw.githubusercontent.com/go-gitea/gitea/v1.27.1/...` → 200) and this instance reports `{"version":"1.27.1"}`, so the source read and the live instance agree on the version being claimed. Population will be derived with `git ls-files`, not from this issue's item list.
Author
Owner

Closing record

Outcome: Finished the sweep #747 left incomplete. PR #905. Population derived with git ls-files17 files, 43 occurrences of 1.25.4, against the 4 items this issue's body named, which is exactly the trap the body itself warned about.

Re-established on 1.27.1: the creator-attribution claim the H10 allow-list rests on (4 merged PR heads, both endpoints); the scope enum (no status scope; 9 categories, 0 occurrences); the reqRepoWriter(unit.TypeCode) gate on POST /statuses/{sha}; the write:package 403 (live probe, read control 200 + write control 201, throwaway repo, artifacts deleted and deletion confirmed); the absence of any REST cancel route (source, which a 404 alone cannot establish); and pull_request/pull_request_target definition resolution.

Two claims were corrected, not merely re-dated:

  • --depth=1 has no merge base was filed against the wrong axis. It is a git property — a Gitea upgrade cannot change it, a git upgrade can. Re-probed on git 2.55.0.
  • enable_bypass_allowlist postdating 1.25.4 had an issue body as its only provenance. Checked in both trees: it holds. Its neighbour block_admin_merge_override does not share that history (present at 1.25.4 in all three structs), now stated so the paragraph cannot invite the inference.

Root cause: #747 prioritised the merge-gating claims and said so rather than implying coverage; the remainder simply had no owner. Underneath that, the durable cause is that a version stamp records when something was measured but not what could invalidate it — which is how the --depth=1 claim ended up carrying a Gitea version it was never sensitive to.

Decisions/conventions changed: no new keys. Updated in place: ci.actions-credential-scoping (all three items re-established), ci.batch-pushes-no-cancel-route (source-confirmed REST absence; retitled), ci.exemption-provenance (git-axis correction), ci.gate-trigger-base-resolved (definition-resolution half from source), ci.verdict-write-retarget-fence, release.main-direct-push-disabled.

Reusable knowledge:

  1. A version-stamped claim should be filed against the axis that can invalidate it. A Gitea stamp on a git property invites a re-run against the wrong system, and the re-run looks productive.
  2. Reasons decay like the claims they excuse. "Stays dated because the probe route is gone" needs re-checking as much as the measurement does — one such reason here was invented (see below) and two were merely inherited.
  3. Don't keep a copy of a set. Two attempts to track "what remains dated" — an enumerated list, then a git grep pointer — each went wrong inside the commit that wrote them: the list omitted three residuals that commit created, and the pointer missed a second spelling that commit introduced. Deleted both; each residual states its reason where it lives.
  4. The honest reason beats the tidy one. The reason first written for not re-probing MCP cancel_run ("no disposable run to spend") was false — 4 of 6 workflows carry workflow_dispatch:, and the record itself said dispatch_workflow works. The real reason was that the agent harness refused the call, and that is now what the record says.

Verification: scripts/tests 1565 passed / 3 skipped; decisions_validate.py OK; catalog regenerated (unchanged — no rule: moved); ruff lint+format clean; bash -n and YAML parse clean. Every changed line in scripts/ and .gitea/ is a comment — zero executable change, verified mechanically. Four cold review rounds (worktree-isolated) plus a cross-family Codex pass; each of the first three found real defects, all fixed.

Deferred: MCP cancel_run and the web-UI/CSRF cancel findings stay 1.25.4-dated, each with its own stated reason. The push-supersession and pull_request_target fence measurements likewise. Nothing new filed — these are decisions, not gaps.

Docs updated: docs/ci-cd.md, docs/decisions/records/ci/{actions-credential-scoping,batch-pushes-no-cancel-route,exemption-provenance,gate-trigger-base-resolved,verdict-write-retarget-fence}.md, docs/decisions/records/release/main-direct-push-disabled.md, docs/decisions/workflow-process.md, regenerated docs/decisions/README.md.

## Closing record **Outcome:** Finished the sweep #747 left incomplete. PR #905. Population derived with `git ls-files` — **17 files, 43 occurrences** of `1.25.4`, against the 4 items this issue's body named, which is exactly the trap the body itself warned about. Re-established on 1.27.1: the `creator`-attribution claim the H10 allow-list rests on (4 merged PR heads, both endpoints); the scope enum (no `status` scope; 9 categories, 0 occurrences); the `reqRepoWriter(unit.TypeCode)` gate on `POST /statuses/{sha}`; the `write:package` 403 (live probe, read control 200 + write control 201, throwaway repo, artifacts deleted and deletion confirmed); the absence of any REST cancel route (source, which a 404 alone cannot establish); and `pull_request`/`pull_request_target` definition resolution. Two claims were **corrected**, not merely re-dated: - `--depth=1` has no merge base was filed against the wrong axis. It is a **git** property — a Gitea upgrade cannot change it, a git upgrade can. Re-probed on git 2.55.0. - `enable_bypass_allowlist` postdating 1.25.4 had an issue body as its only provenance. Checked in both trees: it holds. Its neighbour `block_admin_merge_override` does **not** share that history (present at 1.25.4 in all three structs), now stated so the paragraph cannot invite the inference. **Root cause:** #747 prioritised the merge-gating claims and said so rather than implying coverage; the remainder simply had no owner. Underneath that, the durable cause is that a version stamp records *when* something was measured but not *what could invalidate it* — which is how the `--depth=1` claim ended up carrying a Gitea version it was never sensitive to. **Decisions/conventions changed:** no new keys. Updated in place: `ci.actions-credential-scoping` (all three items re-established), `ci.batch-pushes-no-cancel-route` (source-confirmed REST absence; retitled), `ci.exemption-provenance` (git-axis correction), `ci.gate-trigger-base-resolved` (definition-resolution half from source), `ci.verdict-write-retarget-fence`, `release.main-direct-push-disabled`. **Reusable knowledge:** 1. **A version-stamped claim should be filed against the axis that can invalidate it.** A Gitea stamp on a git property invites a re-run against the wrong system, and the re-run looks productive. 2. **Reasons decay like the claims they excuse.** "Stays dated because the probe route is gone" needs re-checking as much as the measurement does — one such reason here was *invented* (see below) and two were merely inherited. 3. **Don't keep a copy of a set.** Two attempts to track "what remains dated" — an enumerated list, then a `git grep` pointer — each went wrong *inside the commit that wrote them*: the list omitted three residuals that commit created, and the pointer missed a second spelling that commit introduced. Deleted both; each residual states its reason where it lives. 4. **The honest reason beats the tidy one.** The reason first written for not re-probing MCP `cancel_run` ("no disposable run to spend") was false — 4 of 6 workflows carry `workflow_dispatch:`, and the record itself said `dispatch_workflow` works. The real reason was that the agent harness refused the call, and that is now what the record says. **Verification:** `scripts/tests` 1565 passed / 3 skipped; `decisions_validate.py` OK; catalog regenerated (unchanged — no `rule:` moved); ruff lint+format clean; `bash -n` and YAML parse clean. **Every changed line in `scripts/` and `.gitea/` is a comment** — zero executable change, verified mechanically. Four cold review rounds (worktree-isolated) plus a cross-family Codex pass; each of the first three found real defects, all fixed. **Deferred:** MCP `cancel_run` and the web-UI/CSRF cancel findings stay 1.25.4-dated, each with its own stated reason. The `push`-supersession and `pull_request_target` fence measurements likewise. Nothing new filed — these are decisions, not gaps. **Docs updated:** `docs/ci-cd.md`, `docs/decisions/records/ci/{actions-credential-scoping,batch-pushes-no-cancel-route,exemption-provenance,gate-trigger-base-resolved,verdict-write-retarget-fence}.md`, `docs/decisions/records/release/main-direct-push-disabled.md`, `docs/decisions/workflow-process.md`, regenerated `docs/decisions/README.md`.
timothy removed the in-progress label 2026-09-02 22:21:11 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: timothy/ersatztv#869