fix(guard): derive target base ref for cross-repository checkouts #984

Merged
sysadmin merged 2 commits from fix/issue-983-cross-repo-base-ref into master 2026-07-31 00:05:24 -05:00
Owner

Hardcoded assumptions removed

Two independent modules each hardcoded a base ref, and they disagreed with each other:

Module Removed assumption
root_checkout_guard.py REMOTE_MASTER_REFS = ("prgs/master", "refs/remotes/prgs/master") as the silent default of resolve_remote_master_sha(). All four production callers omitted remote_refs and inherited it.
root_checkout_guard.py The literal string prgs/master baked into the operator-facing contamination message.
master_parity_gate.py refs/remotes/origin/master as the default tracking_ref.
master_parity_gate.py git remote get-url origin — a hardcoded remote name — for repository identity.

Gating assumed remote prgs; reporting assumed remote origin. At most one could be right for any repository, and for a repository using neither, both were wrong.

Both constants are retained for callers that still pass an explicit override; neither is a silent default any more.

How the authoritative target is resolved

canonical_repository_root.py is the existing authoritative repository/context resolver (#706/#973), so it was extended rather than adding a second source of repository truth.

It already probed remotes and identified the right one while resolving owner/repository — then discarded the remote name. resolve_identity_remote() now returns that name, and repository_identity_slug() becomes a thin wrapper over it, so its behaviour is unchanged.

resolve_target_base_ref() then derives, in order:

  1. Identity remote — the remote that proves repository identity, with its exact configured case preserved. Git stores remote names in case-sensitive config subsections, so MDCPS is reachable only as MDCPS; the lowercase mdcps probe candidate simply does not resolve, and the exact name arrives from git remote.
  2. Integration branch — from refs/remotes/<remote>/HEAD, which is git's own record of that remote's default branch, written by clone and remote set-head.
  3. Fallback — only when the remote publishes no such default: exactly one present master/main/dev remote-tracking ref.

No new configuration field was required, and none was added. Step 2 is authoritative repository state that already exists, which is the proof that a new field is unnecessary.

Fail-closed behaviour preserved

Derivation returns proven: false, an empty tracking_refs, and a machine-checkable reason_code when:

Condition reason_code
No remote yields a parseable identity no_identity_remote
Distinct remotes claim different repositories ambiguous_identity_remote
Several candidate branches, no recorded default ambiguous_integration_branch
No candidate branch ref at all no_integration_branch_ref

An underivable target yields sha = None — exactly what resolve_remote_master_sha() already returned when rev-parse failed — so the #749/#757 bootstrap still treats it as missing evidence, never as "no constraint". It never invents a branch, writes a ref, or falls back to another repository's commit. Derivation is strictly read-only, asserted by a test that snapshots every ref and remote before and after.

The bootstrap callers now surface the derivation reasons, so a refusal states its cause instead of only "live master tip is unknown".

One consistent target for gating and reporting

Both sides now consume the same resolver, so they cannot diverge again. assess_target_repository_parity() gains base_remote, base_branch, and tracking_ref_source; a test asserts the gate and the report agree on remote, branch, and SHA.

Repository identity is resolved independently of the base ref: a target that has never been fetched still has a provable identity, and reporting it as unidentifiable would discard real information over a missing ref that does not bear on identity.

PRGS compatibility

Unchanged. prgs/master resolves through the recorded remote HEAD to the identical SHA, and an explicit remote_refs override keeps the historical probe path verbatim. Verified live in this checkout: prgs / master -> refs/remotes/prgs/master, source remote_head_symref.

This also repairs an observable defect in this repository. refs/remotes/origin/master survives here as an orphan ref from a removed remote (git config --get remote.origin.url exits 1). The parity gate read that abandoned ref and reported:

"tracking_ref": "refs/remotes/origin/master",
"remote_tracking_head": "08c3488d7c35ba27efcd5119514aeeac37b657f7",
"repository_slug": null,
"stale": true,
"reasons": ["target repository identity could not be derived from its git remote"]

After this change, against the same checkout:

"tracking_ref": "refs/remotes/prgs/master",
"base_remote": "prgs",
"base_branch": "master",
"tracking_ref_source": "remote_head_symref",
"repository_slug": "Scaled-Tech-Consulting/Gitea-Tools",
"stale": false,
"reasons": []

Cross-repository MDCPS/dev regression coverage

tests/test_issue_983_cross_repo_base_ref.py builds hermetic git repositories on disk — no network, no fetch — and covers all ten required cases:

  1. PRGS prgs/master behaviour preserved, plus the legacy explicit-remote_refs path
  2. Remote MDCPS, branch dev -> refs/remotes/MDCPS/dev
  3. No remote named origin
  4. Exact remote-name case preserved; a lowercase caller hint still resolves MDCPS
  5. Local target equal to the resolved tip -> not stale
  6. Local target behind, and divergent, -> stale
  7. Missing target remote, and missing tracking ref -> fail closed
  8. Ambiguous branch resolution and ambiguous identity remote -> fail closed; a recorded remote HEAD resolves otherwise-ambiguous branches; an explicitly named remote disambiguates
  9. Gate and report resolve one target, and refuse the same unresolvable target
  10. Every affected production caller supplies or consumes the resolved target

Plus the orphan-origin-ref case reproducing the live symptom above, and a read-only proof that no refs or remotes are mutated.

MDCPS is never special-cased; neither is WeeklyBriefings-Meta or dev. No MDCPS or Weekly Briefings repository was touched.

Production callers traced

Five, not four. The four resolve_remote_master_sha sites named in the report, plus anti_stomp_preflight.py:551, which calls assess_root_checkout_guard directly and would have emitted the same misleading message:

  • gitea_mcp_server.py:1059 — author issue bootstrap
  • gitea_mcp_server.py:1094 — create-issue bootstrap (#749/#757)
  • gitea_mcp_server.py:1318 — namespace mutation preflight
  • gitea_mcp_server.py:2005_enforce_root_checkout_guard (#475)
  • anti_stomp_preflight.py:551 — root-checkout check, now forwarding remote_master_ref

Exact test results

Focused, in the issue worktree at 2d5d5c9:

tests/test_issue_983_cross_repo_base_ref.py        24 passed in 4.41s

Directly affected suites (16 modules):

375 passed, 130 subtests passed in 36.93s

Full suite, issue branch:

28 failed, 6191 passed, 6 skipped, 1106 subtests passed in 216.84s

Full suite, clean baseline worktree at the identical base commit 108cbfa:

28 failed, 6166 passed, 6 skipped, 1106 subtests passed in 206.88s

The two FAILED lists were captured, sorted, and diffed: byte-identical, zero introduced failures. All 28 are pre-existing at 108cbfa and do not depend on this change. The +25 passed delta is this PR's 24 new tests plus one added guard test.

Test updated with the behaviour

tests/test_root_checkout_guard.py::test_head_behind_prgs_master_blocked asserted the literal does not match prgs/master, which is exactly the string this issue removes. It is renamed to test_head_behind_tracking_base_ref_blocked and now asserts the generic wording, with a new sibling test proving a named ref is reported accurately and never as prgs/master.

One test I first wrote asserted that refs/remotes/mdcps/dev fails to resolve. It failed on macOS: a case-insensitive filesystem resolves loose refs either way, so that assertion tested the filesystem rather than this code. It was replaced with the portable guarantee — git remote names are case-sensitive config subsections on every platform (git remote get-url mdcps -> error: No such remote 'mdcps').

Closes #983

## Hardcoded assumptions removed Two independent modules each hardcoded a base ref, and they disagreed with each other: | Module | Removed assumption | |---|---| | `root_checkout_guard.py` | `REMOTE_MASTER_REFS = ("prgs/master", "refs/remotes/prgs/master")` as the **silent default** of `resolve_remote_master_sha()`. All four production callers omitted `remote_refs` and inherited it. | | `root_checkout_guard.py` | The literal string `prgs/master` baked into the operator-facing contamination message. | | `master_parity_gate.py` | `refs/remotes/origin/master` as the default `tracking_ref`. | | `master_parity_gate.py` | `git remote get-url origin` — a hardcoded remote name — for repository identity. | Gating assumed remote `prgs`; reporting assumed remote `origin`. At most one could be right for any repository, and for a repository using neither, both were wrong. Both constants are retained for callers that still pass an explicit override; neither is a silent default any more. ## How the authoritative target is resolved `canonical_repository_root.py` is the existing authoritative repository/context resolver (#706/#973), so it was extended rather than adding a second source of repository truth. It already probed remotes and identified the right one while resolving `owner/repository` — then discarded the remote name. `resolve_identity_remote()` now returns that name, and `repository_identity_slug()` becomes a thin wrapper over it, so its behaviour is unchanged. `resolve_target_base_ref()` then derives, in order: 1. **Identity remote** — the remote that proves repository identity, with its **exact configured case preserved**. Git stores remote names in case-sensitive config subsections, so `MDCPS` is reachable only as `MDCPS`; the lowercase `mdcps` probe candidate simply does not resolve, and the exact name arrives from `git remote`. 2. **Integration branch** — from `refs/remotes/<remote>/HEAD`, which is git's own record of that remote's default branch, written by `clone` and `remote set-head`. 3. **Fallback** — only when the remote publishes no such default: exactly one present `master`/`main`/`dev` remote-tracking ref. **No new configuration field was required, and none was added.** Step 2 is authoritative repository state that already exists, which is the proof that a new field is unnecessary. ## Fail-closed behaviour preserved Derivation returns `proven: false`, an **empty** `tracking_refs`, and a machine-checkable `reason_code` when: | Condition | `reason_code` | |---|---| | No remote yields a parseable identity | `no_identity_remote` | | Distinct remotes claim different repositories | `ambiguous_identity_remote` | | Several candidate branches, no recorded default | `ambiguous_integration_branch` | | No candidate branch ref at all | `no_integration_branch_ref` | An underivable target yields `sha = None` — exactly what `resolve_remote_master_sha()` already returned when `rev-parse` failed — so the #749/#757 bootstrap still treats it as **missing evidence, never as "no constraint"**. It never invents a branch, writes a ref, or falls back to another repository's commit. Derivation is strictly read-only, asserted by a test that snapshots every ref and remote before and after. The bootstrap callers now surface the derivation `reasons`, so a refusal states its cause instead of only "live master tip is unknown". ## One consistent target for gating and reporting Both sides now consume the same resolver, so they cannot diverge again. `assess_target_repository_parity()` gains `base_remote`, `base_branch`, and `tracking_ref_source`; a test asserts the gate and the report agree on remote, branch, and SHA. Repository identity is resolved **independently** of the base ref: a target that has never been fetched still has a provable identity, and reporting it as unidentifiable would discard real information over a missing ref that does not bear on identity. ## PRGS compatibility Unchanged. `prgs/master` resolves through the recorded remote HEAD to the identical SHA, and an explicit `remote_refs` override keeps the historical probe path verbatim. Verified live in this checkout: `prgs` / `master` -> `refs/remotes/prgs/master`, source `remote_head_symref`. This also repairs an **observable defect in this repository**. `refs/remotes/origin/master` survives here as an orphan ref from a removed remote (`git config --get remote.origin.url` exits 1). The parity gate read that abandoned ref and reported: ``` "tracking_ref": "refs/remotes/origin/master", "remote_tracking_head": "08c3488d7c35ba27efcd5119514aeeac37b657f7", "repository_slug": null, "stale": true, "reasons": ["target repository identity could not be derived from its git remote"] ``` After this change, against the same checkout: ``` "tracking_ref": "refs/remotes/prgs/master", "base_remote": "prgs", "base_branch": "master", "tracking_ref_source": "remote_head_symref", "repository_slug": "Scaled-Tech-Consulting/Gitea-Tools", "stale": false, "reasons": [] ``` ## Cross-repository MDCPS/dev regression coverage `tests/test_issue_983_cross_repo_base_ref.py` builds hermetic git repositories on disk — no network, no fetch — and covers all ten required cases: 1. PRGS `prgs/master` behaviour preserved, plus the legacy explicit-`remote_refs` path 2. Remote `MDCPS`, branch `dev` -> `refs/remotes/MDCPS/dev` 3. No remote named `origin` 4. Exact remote-name case preserved; a lowercase caller hint still resolves `MDCPS` 5. Local target equal to the resolved tip -> not stale 6. Local target behind, and divergent, -> stale 7. Missing target remote, and missing tracking ref -> fail closed 8. Ambiguous branch resolution and ambiguous identity remote -> fail closed; a recorded remote HEAD resolves otherwise-ambiguous branches; an explicitly named remote disambiguates 9. Gate and report resolve one target, and refuse the same unresolvable target 10. Every affected production caller supplies or consumes the resolved target Plus the orphan-`origin`-ref case reproducing the live symptom above, and a read-only proof that no refs or remotes are mutated. MDCPS is never special-cased; neither is `WeeklyBriefings-Meta` or `dev`. No MDCPS or Weekly Briefings repository was touched. ## Production callers traced Five, not four. The four `resolve_remote_master_sha` sites named in the report, plus `anti_stomp_preflight.py:551`, which calls `assess_root_checkout_guard` directly and would have emitted the same misleading message: - `gitea_mcp_server.py:1059` — author issue bootstrap - `gitea_mcp_server.py:1094` — create-issue bootstrap (#749/#757) - `gitea_mcp_server.py:1318` — namespace mutation preflight - `gitea_mcp_server.py:2005` — `_enforce_root_checkout_guard` (#475) - `anti_stomp_preflight.py:551` — root-checkout check, now forwarding `remote_master_ref` ## Exact test results Focused, in the issue worktree at `2d5d5c9`: ``` tests/test_issue_983_cross_repo_base_ref.py 24 passed in 4.41s ``` Directly affected suites (16 modules): ``` 375 passed, 130 subtests passed in 36.93s ``` Full suite, issue branch: ``` 28 failed, 6191 passed, 6 skipped, 1106 subtests passed in 216.84s ``` Full suite, clean baseline worktree at the identical base commit `108cbfa`: ``` 28 failed, 6166 passed, 6 skipped, 1106 subtests passed in 206.88s ``` The two `FAILED` lists were captured, sorted, and diffed: **byte-identical, zero introduced failures**. All 28 are pre-existing at `108cbfa` and do not depend on this change. The `+25` passed delta is this PR's 24 new tests plus one added guard test. ## Test updated with the behaviour `tests/test_root_checkout_guard.py::test_head_behind_prgs_master_blocked` asserted the literal `does not match prgs/master`, which is exactly the string this issue removes. It is renamed to `test_head_behind_tracking_base_ref_blocked` and now asserts the generic wording, with a new sibling test proving a named ref is reported accurately and never as `prgs/master`. One test I first wrote asserted that `refs/remotes/mdcps/dev` fails to resolve. It failed on macOS: a case-insensitive filesystem resolves loose refs either way, so that assertion tested the filesystem rather than this code. It was replaced with the portable guarantee — git remote names are case-sensitive config subsections on every platform (`git remote get-url mdcps` -> `error: No such remote 'mdcps'`). Closes #983
jcwalker3 added 1 commit 2026-07-30 21:35:56 -05:00
Cross-repository mutation gating assumed the tracking base ref was
prgs/master, and parity reporting independently assumed origin/master.
A namespace bound to any other repository -- for example remote MDCPS on
integration branch dev -- could not prove base equivalence, so every
gated mutation failed closed with no reachable remedy. The two modules
also disagreed with each other, so at most one could be right for any
given repository.

Derive the target instead of assuming it. canonical_repository_root
already discovered the correct remote while resolving repository
identity and then discarded its name; it now returns that name with its
exact configured case preserved, and resolve_target_base_ref() builds
refs/remotes/<remote>/<branch> from it. The integration branch comes
from refs/remotes/<remote>/HEAD -- git's own record of the remote's
default branch -- so no new configuration field is required. Only when
a remote publishes no such default does it fall back to exactly one
present integration-branch candidate.

Resolution fails closed with a machine-checkable reason_code when
identity is unprovable, when distinct remotes claim different
repositories, when several candidate branches exist with no recorded
default, or when no candidate exists. It never invents a branch, writes
a ref, or falls back to another repository's base.

Both the mutation guard and the parity report now consume that one
resolved target, so they cannot disagree again. Root-checkout
contamination names the ref it actually compared rather than a literal
prgs/master the target repository may not have.

Fixes an observable defect in this repository: refs/remotes/origin/master
survives as an orphan ref from a removed remote, so parity reported the
target stale against a dead commit while reporting its identity as
underivable.

PRGS behaviour is unchanged -- prgs/master still resolves via the
recorded remote HEAD to the same SHA, and an explicit remote_refs
override keeps the historical probe path verbatim.

Tests: 24 new hermetic regression tests covering PRGS prgs/master,
MDCPS/dev, no origin remote, exact remote-name case, equal/behind/
divergent targets, missing remote or ref, ambiguous remote and branch
resolution, gate/report agreement, and every affected production
caller. Full suite 6191 passed / 28 failed, byte-identical failure set
to the baseline at 108cbfa (zero introduced failures).

Refs #983

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #984
issue: #983
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 34009-378909a42165
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-2d5d5c9
phase: claimed
candidate_head: 2d5d5c9d17
target_branch: master
target_branch_sha: 108cbfa173
last_activity: 2026-07-31T02:54:01Z
expires_at: 2026-07-31T03:04:01Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #984 issue: #983 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 34009-378909a42165 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-2d5d5c9 phase: claimed candidate_head: 2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc target_branch: master target_branch_sha: 108cbfa173de34470d7abc022b929e6b3adc418a last_activity: 2026-07-31T02:54:01Z expires_at: 2026-07-31T03:04:01Z blocker: none
sysadmin requested changes 2026-07-30 21:59:12 -05:00
Dismissed
sysadmin left a comment
Owner

Canonical PR State

STATE: blocked
WHO_IS_NEXT: author
NEXT_ACTION: Fix B1 (stop trusting the stale refs/remotes//HEAD cache as the integration branch) and B2 (stop passing the derived identity remote back into resolve_target_base_ref, which disables the ambiguity gate), add the two missing regression fixtures, and push to fix/issue-983-cross-repo-base-ref.
NEXT_PROMPT: Continue authoring issue #983 on PR #984. Reviewer verdict at head 2d5d5c9d17 is REQUEST_CHANGES with two blocking findings. B1: resolve_target_base_ref treats refs/remotes//HEAD as authoritative, but it is a local cache written at clone time and never refreshed by fetch; on the real target /Users/jasonwalker/Development/weekly-briefings it still says refs/remotes/MDCPS/main while the upstream default is dev (git ls-remote --symref MDCPS HEAD returns refs/heads/dev), so the guard compares HEAD a37ac427c18b against MDCPS/main 9a84325a1b68 and blocks a checkout that is exactly on its integration tip. B2: master_parity_gate.py:498 passes remote=identity_remote into resolve_target_base_ref, and that function skips its ambiguity check whenever a remote is named, so DENY_AMBIGUOUS_REMOTE can never fire from the reporting path; the gate refuses an ambiguous target while the report silently names a different repository with stale=false and no reasons. Add a fixture where refs/remotes//HEAD disagrees with the checkout upstream, and a fixture asserting gate and report agree on an ambiguous target. Do not fetch and do not run git remote set-head. Then request re-review.
WHAT_HAPPENED: Independent review at the PR head. Diff, all five production call paths, and the resolver were inspected, and the resolver was executed against both the live PRGS control checkout and the real Weekly Briefings target. PRGS behaviour and the orphan-origin repair verified correct; two blocking defects found that the current test suite cannot see.
WHY: The PR replaces the hardcoded prgs/master with a derivation that is wrong for the very repository the issue was filed to unblock, and the gating/reporting consistency the issue requires is not actually achieved on ambiguous targets.
ISSUE: #983
HEAD_SHA: 2d5d5c9d17
REVIEW_STATUS: request_changes
MERGE_READY: false
BLOCKERS: B1 and B2 below; unblocked only after the integration branch is derived from a signal that is not the stale remote-HEAD cache, and after the ambiguity gate is reachable from the parity-reporting path, each with a regression test that fails on the current code.
VALIDATION: tests/test_issue_983_cross_repo_base_ref.py 24 passed; 12 affected suites 220 passed, 95 subtests passed; both blocking defects reproduced live against /Users/jasonwalker/Development/weekly-briefings and a hermetic two-remote repository.
LAST_UPDATED_BY: reviewer

Verdict

REQUEST_CHANGES at head 2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc, base master @ 108cbfa173de.

Reviewed as prgs-reviewer / sysadmin; PR author is jcwalker3, so identities differ. Runtime parity green, mutation_safe: true. Review worktree branches/review-pr984-2d5d5c9 detached at the PR head. One commit on top of master, merge-base == 108cbfa, nothing extraneous carried.

The direction of this change is right and the structural work is good. Two findings block, and the first is not a corner case — it is the Weekly Briefings target this issue exists for.

What was verified as correct

  • PRGS behaviour preserved. Against the live control checkout, resolve_target_base_ref returns prgs / master / refs/remotes/prgs/master, source remote_head_symref.
  • The orphan-origin reporting defect described in the issue is genuinely repaired. assess_target_repository_parity on this repository now returns slug Scaled-Tech-Consulting/Gitea-Tools, tracking_ref refs/remotes/prgs/master, stale: false, reasons: [], where it previously read the abandoned refs/remotes/origin/master and reported a false stale: true with a null identity.
  • No dependency on a remote named origin remains in the derivation path.
  • Remote-name case is preserved end to end; nothing folds MDCPS to mdcps.
  • No MDCPS / WeeklyBriefings / dev special-casing anywhere in the diff.
  • Derivation is read-only; no ref, branch, or remote is created or modified.
  • Every production resolve_remote_master_sha(canonical_root) call site is gone, replaced by resolve_remote_master_ref_state. The fifth caller, anti_stomp_preflight.py:551, was correctly identified and wired.
  • Tests run independently in the PR worktree: the focused suite 24 passed; twelve affected suites 220 passed with 95 subtests. No introduced failure was found.

Both findings below are green under the current suite. That is part of the problem.

B1 (blocking) — the remote-HEAD symref is a stale local cache, and the real target derives the wrong branch

Step 2 of resolve_target_base_ref treats refs/remotes/<remote>/HEAD as truth. The PR body states this explicitly:

from refs/remotes/<remote>/HEAD, which is git's own record of that remote's default branch, written by clone and remote set-head.
Step 2 is authoritative repository state that already exists, which is the proof that a new field is unnecessary.

That premise does not hold. refs/remotes/<remote>/HEAD is a local cache written once at clone time. Git never refreshes it on fetch; only an explicit git remote set-head -a updates it. When the upstream default branch changes afterwards, the cache keeps pointing at the old branch.

That is exactly the state of the repository this issue exists to unblock. Measured read-only against /Users/jasonwalker/Development/weekly-briefings:

upstream truth   git ls-remote --symref MDCPS HEAD  ->  ref: refs/heads/dev   a37ac427c18b
cached symref    refs/remotes/MDCPS/HEAD            ->  refs/remotes/MDCPS/main
refs/remotes/MDCPS/dev   = a37ac427c18bb3a93bd95c74b35171b4553a1653
refs/remotes/MDCPS/main  = 9a84325a1b68a26d2062c86870a1ca692ff647b4
local HEAD (branch dev)  = a37ac427c18bb3a93bd95c74b35171b4553a1653
branch.dev.remote/merge  = MDCPS / refs/heads/dev
@{upstream}              = MDCPS/dev

The checkout sits exactly on its integration tip. Every independent signal — the upstream's own HEAD, the checked-out branch, and that branch's configured upstream — says dev. Only the stale cache says main.

Running this PR's code against that real target:

DERIVED -> proven=true  remote=MDCPS  branch=main  tracking_ref=refs/remotes/MDCPS/main  source=remote_head_symref
GATE    -> sha=9a84325a1b68  ref=MDCPS/main
REPORT  -> tracking_ref=refs/remotes/MDCPS/main  base_branch=main
           checkout_head=a37ac427c18b  remote_tracking_head=9a84325a1b68
           stale=true  reasons=[]

Consequences:

  1. assess_root_checkout_guard compares HEAD a37ac427 against 9a84325a and blocks with "control checkout HEAD does not match refs/remotes/MDCPS/main" — for a checkout that is not behind anything.
  2. The create-issue and author bootstrap prove base equivalence against main, so they fail closed against a branch the repository does not integrate onto.
  3. The parity report emits stale: true with an empty reasons list — a bare boolean with no stated cause, the same operator-hostile shape as the original defect.

So Weekly Briefings Author work stays blocked. prgs/master is replaced by MDCPS/main; the ref is different and the refusal message is now honest about which ref it used, but it is still the wrong ref and the mutation still fails closed.

Acceptance criterion 2 — a repository using remote MDCPS and branch dev resolves refs/remotes/MDCPS/dev — is not met against the actual repository. test_mdcps_dev_resolves passes only because the fixture calls _set_remote_head(root, "MDCPS", "dev"), manufacturing the cache state the real checkout does not have. No fixture in the suite ever creates a refs/remotes/<remote>/HEAD that disagrees with the checkout's branch or its configured upstream, which is why a resolver that trusts a stale cache is fully green.

Remediation is the author's design call, but the constraints are firm: no network fetch, since the module documents that no network call is made, and no git remote set-head, since the PR's own read-only test forbids mutating refs. Signals already present locally and not currently consulted:

  • branch.<current>.remote plus branch.<current>.merge, i.e. @{upstream} — the checkout's own configured integration target. On this repository it yields MDCPS/dev correctly.
  • Alternatively, treating a cached symref that disagrees with the configured upstream as ambiguous, failing closed with a reason naming both, is acceptable. What is not acceptable is silently preferring the stale cache.

Please add a regression fixture where refs/remotes/<remote>/HEAD points at a different branch than the checkout's upstream. Without it this class of bug stays invisible.

B2 (blocking) — parity reporting bypasses the ambiguity gate, so gating and reporting still diverge

assess_target_repository_parity resolves the identity remote first, then passes it back in:

identity_remote, slug = _crr.resolve_identity_remote(canonical_root)          # master_parity_gate.py:490
base = _crr.resolve_target_base_ref(canonical_root, remote=identity_remote)   # master_parity_gate.py:498

But resolve_target_base_ref uses a caller-supplied remote as the signal that the caller has disambiguated:

if not (remote or "").strip():        # canonical_repository_root.py
    distinct = {slug for _, slug in identities}
    if len(distinct) > 1:
        ... DENY_AMBIGUOUS_REMOTE

Here the caller is not an operator naming a remote — it is the same first-wins probe. identity_remote is always non-empty whenever identity resolves, so DENY_AMBIGUOUS_REMOTE can never fire from the reporting path.

Reproduced on a hermetic repository with two remotes claiming different repositories, MDCPS to MDCPS/WeeklyBriefings-Meta and prgs to Scaled-Tech-Consulting/Gitea-Tools:

RESOLVER proven=False  reason_code=ambiguous_identity_remote
GATE     sha=None  remote=None  branch=None  reason_code=ambiguous_identity_remote
REPORT   tracking_ref=refs/remotes/prgs/master  base_remote=prgs  base_branch=master
         repository_slug=Scaled-Tech-Consulting/Gitea-Tools  stale=false  reasons=[]

The gate refuses. The report confidently names a different repository's slug and base ref, stale: false, with no reasons at all.

This contradicts the PR body's claim that both sides now consume the same resolver and cannot diverge again, and misses acceptance criteria 8 (ambiguity fails closed rather than guessing) and 9 (gating and reporting resolve the same target).

Existing coverage does not catch it: test_ambiguous_identity_remote_fails_closed at line 299 exercises the resolver directly, and test_same_resolved_target_for_gate_and_report at line 369 uses a single-remote repository. Neither crosses ambiguity with the reporting path.

The fix appears to be dropping the argument. resolve_target_base_ref(canonical_root) re-derives the identical identity remote internally and restores the ambiguity check. Verified behaviour-neutral on the live control checkout: with no remote argument and with remote="prgs" the result is identical (prgs / master / refs/remotes/prgs/master, remote_head_symref), so the orphan-origin repair and the criterion-9 test are unaffected. Please pair it with a test asserting gate and report agree on an ambiguous target.

Not blocking, for the author's judgement

  • resolve_target_base_ref returns proven: true for a symref pointing at a branch that has no corresponding tracking ref. Downstream still fails closed at rev-parse, so safety holds, but proven: true with an unresolvable tracking_ref is a misleading contract.
  • assess_target_repository_parity returns determinable: True when base-ref derivation fails. That matches the pre-existing shape for a missing tracking ref, so it is not a regression — noted only because B1 makes the path reachable far more often.

Reviewed head

2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc. Not merged. No restart and no binding change performed.

## Canonical PR State STATE: blocked WHO_IS_NEXT: author NEXT_ACTION: Fix B1 (stop trusting the stale refs/remotes/<remote>/HEAD cache as the integration branch) and B2 (stop passing the derived identity remote back into resolve_target_base_ref, which disables the ambiguity gate), add the two missing regression fixtures, and push to fix/issue-983-cross-repo-base-ref. NEXT_PROMPT: Continue authoring issue #983 on PR #984. Reviewer verdict at head 2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc is REQUEST_CHANGES with two blocking findings. B1: resolve_target_base_ref treats refs/remotes/<remote>/HEAD as authoritative, but it is a local cache written at clone time and never refreshed by fetch; on the real target /Users/jasonwalker/Development/weekly-briefings it still says refs/remotes/MDCPS/main while the upstream default is dev (git ls-remote --symref MDCPS HEAD returns refs/heads/dev), so the guard compares HEAD a37ac427c18b against MDCPS/main 9a84325a1b68 and blocks a checkout that is exactly on its integration tip. B2: master_parity_gate.py:498 passes remote=identity_remote into resolve_target_base_ref, and that function skips its ambiguity check whenever a remote is named, so DENY_AMBIGUOUS_REMOTE can never fire from the reporting path; the gate refuses an ambiguous target while the report silently names a different repository with stale=false and no reasons. Add a fixture where refs/remotes/<remote>/HEAD disagrees with the checkout upstream, and a fixture asserting gate and report agree on an ambiguous target. Do not fetch and do not run git remote set-head. Then request re-review. WHAT_HAPPENED: Independent review at the PR head. Diff, all five production call paths, and the resolver were inspected, and the resolver was executed against both the live PRGS control checkout and the real Weekly Briefings target. PRGS behaviour and the orphan-origin repair verified correct; two blocking defects found that the current test suite cannot see. WHY: The PR replaces the hardcoded prgs/master with a derivation that is wrong for the very repository the issue was filed to unblock, and the gating/reporting consistency the issue requires is not actually achieved on ambiguous targets. ISSUE: #983 HEAD_SHA: 2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc REVIEW_STATUS: request_changes MERGE_READY: false BLOCKERS: B1 and B2 below; unblocked only after the integration branch is derived from a signal that is not the stale remote-HEAD cache, and after the ambiguity gate is reachable from the parity-reporting path, each with a regression test that fails on the current code. VALIDATION: tests/test_issue_983_cross_repo_base_ref.py 24 passed; 12 affected suites 220 passed, 95 subtests passed; both blocking defects reproduced live against /Users/jasonwalker/Development/weekly-briefings and a hermetic two-remote repository. LAST_UPDATED_BY: reviewer ## Verdict REQUEST_CHANGES at head `2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc`, base `master` @ `108cbfa173de`. Reviewed as `prgs-reviewer` / `sysadmin`; PR author is `jcwalker3`, so identities differ. Runtime parity green, `mutation_safe: true`. Review worktree `branches/review-pr984-2d5d5c9` detached at the PR head. One commit on top of master, `merge-base == 108cbfa`, nothing extraneous carried. The direction of this change is right and the structural work is good. Two findings block, and the first is not a corner case — it is the Weekly Briefings target this issue exists for. ## What was verified as correct - PRGS behaviour preserved. Against the live control checkout, `resolve_target_base_ref` returns `prgs` / `master` / `refs/remotes/prgs/master`, source `remote_head_symref`. - The orphan-`origin` reporting defect described in the issue is genuinely repaired. `assess_target_repository_parity` on this repository now returns slug `Scaled-Tech-Consulting/Gitea-Tools`, `tracking_ref` `refs/remotes/prgs/master`, `stale: false`, `reasons: []`, where it previously read the abandoned `refs/remotes/origin/master` and reported a false `stale: true` with a null identity. - No dependency on a remote named `origin` remains in the derivation path. - Remote-name case is preserved end to end; nothing folds `MDCPS` to `mdcps`. - No MDCPS / WeeklyBriefings / `dev` special-casing anywhere in the diff. - Derivation is read-only; no ref, branch, or remote is created or modified. - Every production `resolve_remote_master_sha(canonical_root)` call site is gone, replaced by `resolve_remote_master_ref_state`. The fifth caller, `anti_stomp_preflight.py:551`, was correctly identified and wired. - Tests run independently in the PR worktree: the focused suite 24 passed; twelve affected suites 220 passed with 95 subtests. No introduced failure was found. Both findings below are green under the current suite. That is part of the problem. ## B1 (blocking) — the remote-HEAD symref is a stale local cache, and the real target derives the wrong branch Step 2 of `resolve_target_base_ref` treats `refs/remotes/<remote>/HEAD` as truth. The PR body states this explicitly: > from `refs/remotes/<remote>/HEAD`, which is git's own record of that remote's default branch, written by `clone` and `remote set-head`. > Step 2 is authoritative repository state that already exists, which is the proof that a new field is unnecessary. That premise does not hold. `refs/remotes/<remote>/HEAD` is a local cache written once at clone time. Git never refreshes it on fetch; only an explicit `git remote set-head -a` updates it. When the upstream default branch changes afterwards, the cache keeps pointing at the old branch. That is exactly the state of the repository this issue exists to unblock. Measured read-only against `/Users/jasonwalker/Development/weekly-briefings`: ``` upstream truth git ls-remote --symref MDCPS HEAD -> ref: refs/heads/dev a37ac427c18b cached symref refs/remotes/MDCPS/HEAD -> refs/remotes/MDCPS/main refs/remotes/MDCPS/dev = a37ac427c18bb3a93bd95c74b35171b4553a1653 refs/remotes/MDCPS/main = 9a84325a1b68a26d2062c86870a1ca692ff647b4 local HEAD (branch dev) = a37ac427c18bb3a93bd95c74b35171b4553a1653 branch.dev.remote/merge = MDCPS / refs/heads/dev @{upstream} = MDCPS/dev ``` The checkout sits exactly on its integration tip. Every independent signal — the upstream's own HEAD, the checked-out branch, and that branch's configured upstream — says `dev`. Only the stale cache says `main`. Running this PR's code against that real target: ``` DERIVED -> proven=true remote=MDCPS branch=main tracking_ref=refs/remotes/MDCPS/main source=remote_head_symref GATE -> sha=9a84325a1b68 ref=MDCPS/main REPORT -> tracking_ref=refs/remotes/MDCPS/main base_branch=main checkout_head=a37ac427c18b remote_tracking_head=9a84325a1b68 stale=true reasons=[] ``` Consequences: 1. `assess_root_checkout_guard` compares HEAD `a37ac427` against `9a84325a` and blocks with "control checkout HEAD does not match refs/remotes/MDCPS/main" — for a checkout that is not behind anything. 2. The create-issue and author bootstrap prove base equivalence against `main`, so they fail closed against a branch the repository does not integrate onto. 3. The parity report emits `stale: true` with an empty `reasons` list — a bare boolean with no stated cause, the same operator-hostile shape as the original defect. So Weekly Briefings Author work stays blocked. `prgs/master` is replaced by `MDCPS/main`; the ref is different and the refusal message is now honest about which ref it used, but it is still the wrong ref and the mutation still fails closed. Acceptance criterion 2 — a repository using remote `MDCPS` and branch `dev` resolves `refs/remotes/MDCPS/dev` — is not met against the actual repository. `test_mdcps_dev_resolves` passes only because the fixture calls `_set_remote_head(root, "MDCPS", "dev")`, manufacturing the cache state the real checkout does not have. No fixture in the suite ever creates a `refs/remotes/<remote>/HEAD` that disagrees with the checkout's branch or its configured upstream, which is why a resolver that trusts a stale cache is fully green. Remediation is the author's design call, but the constraints are firm: no network fetch, since the module documents that no network call is made, and no `git remote set-head`, since the PR's own read-only test forbids mutating refs. Signals already present locally and not currently consulted: - `branch.<current>.remote` plus `branch.<current>.merge`, i.e. `@{upstream}` — the checkout's own configured integration target. On this repository it yields `MDCPS/dev` correctly. - Alternatively, treating a cached symref that disagrees with the configured upstream as ambiguous, failing closed with a reason naming both, is acceptable. What is not acceptable is silently preferring the stale cache. Please add a regression fixture where `refs/remotes/<remote>/HEAD` points at a different branch than the checkout's upstream. Without it this class of bug stays invisible. ## B2 (blocking) — parity reporting bypasses the ambiguity gate, so gating and reporting still diverge `assess_target_repository_parity` resolves the identity remote first, then passes it back in: ```python identity_remote, slug = _crr.resolve_identity_remote(canonical_root) # master_parity_gate.py:490 base = _crr.resolve_target_base_ref(canonical_root, remote=identity_remote) # master_parity_gate.py:498 ``` But `resolve_target_base_ref` uses a caller-supplied remote as the signal that the caller has disambiguated: ```python if not (remote or "").strip(): # canonical_repository_root.py distinct = {slug for _, slug in identities} if len(distinct) > 1: ... DENY_AMBIGUOUS_REMOTE ``` Here the caller is not an operator naming a remote — it is the same first-wins probe. `identity_remote` is always non-empty whenever identity resolves, so `DENY_AMBIGUOUS_REMOTE` can never fire from the reporting path. Reproduced on a hermetic repository with two remotes claiming different repositories, `MDCPS` to `MDCPS/WeeklyBriefings-Meta` and `prgs` to `Scaled-Tech-Consulting/Gitea-Tools`: ``` RESOLVER proven=False reason_code=ambiguous_identity_remote GATE sha=None remote=None branch=None reason_code=ambiguous_identity_remote REPORT tracking_ref=refs/remotes/prgs/master base_remote=prgs base_branch=master repository_slug=Scaled-Tech-Consulting/Gitea-Tools stale=false reasons=[] ``` The gate refuses. The report confidently names a different repository's slug and base ref, `stale: false`, with no reasons at all. This contradicts the PR body's claim that both sides now consume the same resolver and cannot diverge again, and misses acceptance criteria 8 (ambiguity fails closed rather than guessing) and 9 (gating and reporting resolve the same target). Existing coverage does not catch it: `test_ambiguous_identity_remote_fails_closed` at line 299 exercises the resolver directly, and `test_same_resolved_target_for_gate_and_report` at line 369 uses a single-remote repository. Neither crosses ambiguity with the reporting path. The fix appears to be dropping the argument. `resolve_target_base_ref(canonical_root)` re-derives the identical identity remote internally and restores the ambiguity check. Verified behaviour-neutral on the live control checkout: with no remote argument and with `remote="prgs"` the result is identical (`prgs` / `master` / `refs/remotes/prgs/master`, `remote_head_symref`), so the orphan-`origin` repair and the criterion-9 test are unaffected. Please pair it with a test asserting gate and report agree on an ambiguous target. ## Not blocking, for the author's judgement - `resolve_target_base_ref` returns `proven: true` for a symref pointing at a branch that has no corresponding tracking ref. Downstream still fails closed at `rev-parse`, so safety holds, but `proven: true` with an unresolvable `tracking_ref` is a misleading contract. - `assess_target_repository_parity` returns `determinable: True` when base-ref derivation fails. That matches the pre-existing shape for a missing tracking ref, so it is not a regression — noted only because B1 makes the path reachable far more often. ## Reviewed head `2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc`. Not merged. No restart and no binding change performed.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #984
issue: #983
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 34009-378909a42165
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-2d5d5c9
phase: released
candidate_head: 2d5d5c9d17
target_branch: master
target_branch_sha: 108cbfa173
last_activity: 2026-07-31T02:59:45Z
expires_at: 2026-07-31T03:09:45Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #984 issue: #983 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 34009-378909a42165 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-2d5d5c9 phase: released candidate_head: 2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc target_branch: master target_branch_sha: 108cbfa173de34470d7abc022b929e6b3adc418a last_activity: 2026-07-31T02:59:45Z expires_at: 2026-07-31T03:09:45Z blocker: manual-release
jcwalker3 added 1 commit 2026-07-30 23:02:14 -05:00
Remediates the REQUEST_CHANGES verdict (review 658) at head 2d5d5c9d.

B1 — refs/remotes/<remote>/HEAD is a stale local cache, not authority.

The previous derivation read that symref as "git's own record of the remote
default branch". It is a cache written once at clone time; an ordinary fetch
never refreshes it, and only an explicit `git remote set-head` updates it. On
the real target this issue exists to unblock, the cache still named `main`
while the checkout tracked and sat exactly on `dev`, so the guard compared
HEAD a37ac427c18b against MDCPS/main 9a84325a1b68 and blocked a checkout that
was not behind anything.

The resolver now derives, in order:

  1. the identity remote, exact case preserved;
  2. the checkout's own configured upstream — branch.<current>.remote plus
     branch.<current>.merge — accepted only when it names that remote and its
     remote-tracking ref actually exists;
  3. otherwise exactly one present master/main/dev remote-tracking ref.

The cached symref is demoted to an observation. It is still read and reported
as cached_remote_head_branch / cached_remote_head_conflicts, and it is named in
refusal text so an operator can see the misleading signal, but it never decides
the branch and never breaks a tie between ambiguous candidates. Requiring the
tracking ref to exist also makes `proven` honest: every proven target now names
a ref that resolves.

Verified read-only against /Users/jasonwalker/Development/weekly-briefings:
MDCPS/dev, source configured_branch_upstream, cached_remote_head_conflicts
true, checkout not stale. PRGS is unchanged — prgs/master, identical SHA.

B2 — an inferred remote must not be laundered into explicit caller intent.

assess_target_repository_parity resolved the identity remote itself and passed
it back into resolve_target_base_ref, which reads a caller-supplied remote as
"the caller already disambiguated" and skips its ambiguity gate. On a target
whose remotes claim different repositories the gate refused while the report
named a different repository with stale=false and no reasons.

The parameter is renamed `explicit_remote` through the resolver and both
root_checkout_guard entry points so the two meanings cannot be confused, and
the reporting path no longer supplies one. Identity resolution for reporting
moves to the new ambiguity-aware assess_identity_remote, so an ambiguous target
now yields a null slug, no tracking ref, and the same reason_code the gate
emits. resolve_identity_remote / repository_identity_slug keep their first-wins
behaviour for the #706/#973 canonical-root validation path, which compares
against an independently trusted expected slug and needs no ambiguity verdict.

Nothing fetches, sets a remote HEAD, writes a ref, adds a remote, invents a
branch, or changes any repository's default branch. A test snapshots refs,
remotes, local config, HEAD, branch, working-tree status, and the cached symref
across every resolver entry point and asserts all are unchanged.

Tests: tests/test_issue_983_cross_repo_base_ref.py rewritten to 37 tests. The
principal MDCPS/dev fixture now reproduces the real defect — upstream dev,
cached refs/remotes/MDCPS/HEAD -> main, both refs present at different commits
— rather than manufacturing the cache state the real checkout does not have.
Added: cache-alone never proves a target, cache never breaks a tie, gate and
report agree on ambiguous remote and ambiguous branch, explicit disambiguation
stays distinct from inferred identity, no production caller passes
explicit_remote, and the read-only proof above.

Focused suite 37 passed. Nineteen affected suites 441 passed, 167 subtests
passed. Full suite 28 failed, 6204 passed, 6 skipped, 1106 subtests passed;
clean baseline at the same base commit 108cbfa 28 failed, 6166 passed, 6
skipped, 1106 subtests passed. Sorted FAILED lists are byte-identical
(sha1 092dae4bc8c4e77d14504d90690d50e0fcd2f637) — zero introduced failures.

Refs #983

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #984
issue: #983
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 52142-ac568169b8e7
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0
phase: claimed
candidate_head: 03b434a0b6
target_branch: master
target_branch_sha: 108cbfa173
last_activity: 2026-07-31T04:24:12Z
expires_at: 2026-07-31T04:34:12Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #984 issue: #983 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 52142-ac568169b8e7 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0 phase: claimed candidate_head: 03b434a0b631a197005068725176b3726a46ae89 target_branch: master target_branch_sha: 108cbfa173de34470d7abc022b929e6b3adc418a last_activity: 2026-07-31T04:24:12Z expires_at: 2026-07-31T04:34:12Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #984
issue: #983
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 52142-ac568169b8e7
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0
phase: claimed
candidate_head: 03b434a0b6
target_branch: master
target_branch_sha: 108cbfa173
last_activity: 2026-07-31T04:51:16Z
expires_at: 2026-07-31T05:01:16Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #984 issue: #983 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 52142-ac568169b8e7 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0 phase: claimed candidate_head: 03b434a0b631a197005068725176b3726a46ae89 target_branch: master target_branch_sha: 108cbfa173de34470d7abc022b929e6b3adc418a last_activity: 2026-07-31T04:51:16Z expires_at: 2026-07-31T05:01:16Z blocker: none
sysadmin approved these changes 2026-07-30 23:54:02 -05:00
sysadmin left a comment
Owner

Canonical PR State

STATE: approve-at-current-head
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR #984 into master at head 03b434a0b6 once a merger session holds the canonical merger lease; no author work remains.
NEXT_PROMPT: Continue Merger work on Gitea-Tools PR #984 (issue #983) as namespace gitea-merger, profile prgs-merger, repository Scaled-Tech-Consulting/Gitea-Tools. Invoke the canonical gitea-workflow skill first and verify runtime parity, repository binding, and merger mutation capability with fresh native calls. The reviewer verdict is an approval at head 03b434a0b6 with merge-base 108cbfa173de34470d7abc022b929e6b3adc418a; confirm approval_at_current_head is true and has_blocking_change_requests is false before acting, because the superseded REQUEST_CHANGES review 658 at head 2d5d5c9d17 remains on the record undismissed by design. Acquire the merger PR lease, merge into master, then reconcile the terminal labels and clean up the source branch fix/issue-983-cross-repo-base-ref and the review worktrees branches/review-pr984-2d5d5c9 and branches/review-pr984-03b434a0. Note that the PR description text is stale in three places and issue comment 18890 is the accurate record; do not treat the PR body as authoritative.
WHAT_HAPPENED: Independent re-review at the new head. The complete diff from base 108cbfa was read rather than only the increment since review 658, all six production call paths were traced, and the resolver, guard, and parity report were executed read-only against the live Weekly Briefings target, the live PRGS control checkout, and four hermetic repositories. B1 and B2 are both remediated and the two previously non-blocking contract notes are also addressed.
WHY: The stale clone-time remote-HEAD cache is no longer authoritative; the checkout's configured upstream now decides the integration branch, so a Weekly Briefings checkout sitting exactly on its MDCPS/dev tip derives MDCPS/dev instead of MDCPS/main. The parity report no longer hands its own inferred remote back to the resolver, so an ambiguous two-remote target now fails closed identically in gating and in reporting instead of the report naming one plausible repository.
ISSUE: #983
HEAD_SHA: 03b434a0b6
REVIEW_STATUS: approve
MERGE_READY: true
NATIVE_REVIEW_PROOF: transport=native_mcp; bound_transport=stdio; entrypoint=mcp_server; entrypoint_path=/Users/jasonwalker/Development/Gitea-Tools/gitea_mcp_server.py; mode=production; production_native_mcp_transport=true; pytest=false; pid=52142; token_fingerprint=adba475da9fda9f1
BLOCKERS: none
VALIDATION: Focused tests/test_issue_983_cross_repo_base_ref.py 37 passed; 29 affected suites 853 passed with 192 subtests passed and 6 pre-existing failures, against the same 28 suites at base 108cbfa showing 815 passed with 192 subtests passed and the identical 6 failures; full suite at the PR head 28 failed, 6204 passed, 6 skipped, 1106 subtests passed, against the full suite at base 108cbfa 28 failed, 6166 passed, 6 skipped, 1106 subtests passed, with both sorted FAILED lists byte-identical at sha1 fdebb1c202c86326d2afb0fd13df71e6790f4ad2, so zero failures were introduced and the plus-38 passed delta is this PR's own new coverage.
LAST_UPDATED_BY: reviewer

Verdict

APPROVE at head 03b434a0b631a197005068725176b3726a46ae89, base master @ 108cbfa173de.

Reviewed as prgs-reviewer / sysadmin; the PR author is jcwalker3, so identities differ. Runtime parity green, mutation_safe: true, one MCP cohort, no duplicate-cohort blocker. Review worktree branches/review-pr984-03b434a0 detached at the PR head; merge-base == 108cbfa173de, two commits on top of master, nothing extraneous carried.

Both blocking findings from review 658 are fixed, and fixed at the root rather than papered over. The remediation is the stronger of the two options I described: the cache is not merely demoted below the configured upstream, it is removed from the decision entirely and kept only as a reported observation.

B1 — resolved

refs/remotes/<remote>/HEAD is no longer a resolution step. BASE_REF_SOURCE_* names only configured_branch_upstream and unique_integration_branch_ref, and the module documents why the cache is excluded. Order is now: identity remote (ambiguity-aware) → the checkout's branch.<current>.remote + branch.<current>.merge, accepted only when it names that remote and its tracking ref exists → exactly one present master/main/dev tracking ref.

Executed read-only against the live target /Users/jasonwalker/Development/weekly-briefings, whose state is unchanged from the one that produced review 658 — cached refs/remotes/MDCPS/HEAD still names main at 9a84325a1b68, refs/remotes/MDCPS/dev is a37ac427c18b, local HEAD is on branch dev at a37ac427c18b, @{upstream} is MDCPS/dev:

DERIVED  proven=true  remote=MDCPS  branch=dev  tracking_ref=refs/remotes/MDCPS/dev
         source=configured_branch_upstream  repository_slug=MDCPS/WeeklyBriefings-Meta
         cached_remote_head_branch=main  cached_remote_head_conflicts=true
GATE     sha=a37ac427c18bb3a93bd95c74b35171b4553a1653  ref=MDCPS/dev
REPORT   tracking_ref=refs/remotes/MDCPS/dev  base_remote=MDCPS  base_branch=dev
         checkout_head=a37ac427c18b  remote_tracking_head=a37ac427c18b
         stale=false  reasons=[]

The checkout that review 658 showed being gated against MDCPS/main is now compared against MDCPS/dev and reports in-parity. Acceptance criterion 2 is met against the actual repository, not only a fixture. The stale cache is surfaced honestly as cached_remote_head_conflicts: true rather than silently obeyed.

PRGS is unchanged. Against the live control checkout: prgs / master / refs/remotes/prgs/master, slug Scaled-Tech-Consulting/Gitea-Tools, checkout_head == remote_tracking_head == 108cbfa173de, stale: false, reasons: []. The source label is now configured_branch_upstream rather than remote_head_symref, which is the intended consequence of the fix; the resolved remote, branch, ref and SHA are identical. The orphan-origin repair still holds — the running server at 108cbfa still reports tracking_ref: refs/remotes/origin/master, repository_slug: null, stale: true, and this branch fixes exactly that.

Read-only is proven, not asserted: refs, config, remotes, HEAD and --untracked-files=all status were snapshotted before and after every probe on both live repositories and compared equal. No fetch, no git remote set-head, no ref write. The Weekly Briefings repository was not modified.

The requested regression fixture exists and is genuine. _RepoCase builds remote MDCPS, checks out dev, sets upstream MDCPS/dev, and creates both dev and main tracking refs at different commits with refs/remotes/MDCPS/HEAD cached at main. test_configured_upstream_beats_stale_cached_remote_head asserts the cache still says main, asserts the two SHAs differ, and asserts dev is derived — so it fails against the previous head rather than passing vacuously. test_cached_remote_head_alone_never_proves_a_target and test_cached_remote_head_never_breaks_a_tie close the class.

B2 — resolved

master_parity_gate.assess_target_repository_parity now calls _crr.assess_identity_remote(canonical_root) and _crr.resolve_target_base_ref(canonical_root) with no remote argument, and returns early when identity is ambiguous. The parameter is renamed explicit_remote throughout resolve_target_base_ref, resolve_remote_master_sha and resolve_remote_master_ref_state, which makes the contract enforceable rather than conventional, and test_no_production_caller_supplies_an_explicit_remote holds the line. I confirmed by grep that no production module passes it.

Reproduced on a hermetic repository with MDCPSMDCPS/WeeklyBriefings-Meta and prgsScaled-Tech-Consulting/Gitea-Tools:

IDENTITY  remote=None  slug=None  ambiguous=true  reason_code=ambiguous_identity_remote
RESOLVER  proven=false reason_code=ambiguous_identity_remote
GATE      sha=None  ref=None  reason_code=ambiguous_identity_remote
REPORT    repository_slug=None  tracking_ref=None  base_remote=None
          reason_code=ambiguous_identity_remote
          reasons=["ambiguous repository identity ... remotes resolve to different
                    repositories (prgs -> ..., MDCPS -> ...) ... (fail closed)"]

Gate and report now refuse together and carry the same reason_code. The report no longer names a repository the gate refuses. Operator disambiguation still works and is correctly distinguished: explicit_remote="prgs" and explicit_remote="MDCPS" each resolve their own target with identity_explicit: true, while explicit_remote="nonexistent" cannot unlock the ambiguous target.

Two further hermetic cases behave correctly: with no configured upstream and both dev and main present, resolution fails closed with ambiguous_integration_branch even though the cache names main — the cache is explicitly refused as a tie-breaker and the refusal text says so and states the read-only remedy. With no candidate ref at all, no_integration_branch_ref. In every case gate and report agreed.

Previously non-blocking notes, both now addressed

  • proven: true with an unresolvable tracking_ref is gone. Steps 2 and 3 each require _ref_exists before returning proven, and test_every_proven_target_resolves pins it.
  • determinable: True alongside a failed base-ref derivation remains, but it is now accompanied by a populated reason_code and reasons, so the refusal states its cause. It matches the pre-existing shape and does not block.

Production callers

Six paths traced, all consistent: gitea_mcp_server.py:1059 (author bootstrap), :1094 (create-issue bootstrap, #749/#757), :1321 (namespace mutation preflight), :2011 (_enforce_root_checkout_guard, #475), anti_stomp_preflight.py:551 (root-checkout check, now receiving remote_master_ref), and gitea_mcp_server.py:19983 (assess_target_repository_parity). Every resolve_remote_master_sha(canonical_root) production call is gone. REMOTE_MASTER_REFS and DEFAULT_TARGET_TRACKING_REF survive as explicit-override constants with no production consumer, which is the documented intent.

No MDCPS, WeeklyBriefings-Meta or dev special-casing exists in the derivation path — only documentation prose and the pre-existing lowercase mdcps entry in _IDENTITY_REMOTE_CANDIDATES, which is unchanged by this diff and provably cannot supply the remote name.

Independent test results

Run by me in branches/review-pr984-03b434a0 at 03b434a0, with the base comparison in branches/baseline-980-108cbfa at 108cbfa:

focused  tests/test_issue_983_cross_repo_base_ref.py     37 passed in 9.35s
affected 29 suites @ head   6 failed, 853 passed, 192 subtests passed
         28 suites @ base   6 failed, 815 passed, 192 subtests passed   (identical 6)
full     @ head   28 failed, 6204 passed, 6 skipped, 1106 subtests passed
         @ base   28 failed, 6166 passed, 6 skipped, 1106 subtests passed
FAILED lists sorted and diffed: byte-identical, sha1 fdebb1c202c86326d2afb0fd13df71e6790f4ad2

The six affected-suite failures are root-checkout-guard and workspace-guard tests that patch resolve_remote_master_sha; they fail identically at base 108cbfa, so they are pre-existing and not caused by the call-site move. All 28 full-suite failures are pre-existing. Zero introduced failures; the +38 passed delta is this PR's own coverage.

Coverage confirmed for every required case: PRGS prgs/master; cross-repository <remote>/dev; stale cached remote HEAD; no origin remote; case-sensitive remote names; matching tip; behind and divergent; missing remote and missing ref; ambiguous remotes and ambiguous branch; gate/report consistency including on ambiguous targets; explicit versus inferred disambiguation; read-only resolver behaviour; and every affected production caller.

One record-keeping note for the merger

The PR description text is stale in three places — it still describes step 2 as refs/remotes/<remote>/HEAD, still cites source remote_head_symref for PRGS, and still cites the previous head's test counts of 24 / 375 / 6191. The author documented this in issue comment 18890 and could not edit the description from the author role under the #618 wall. Issue comment 18890 is the accurate record. This is a documentation artefact only; the code, tests and behaviour at this head are correct, so it does not block.

Reviewed head

03b434a0b631a197005068725176b3726a46ae89. Not merged. Review 658 left in place, not dismissed and not overwritten. No restart, no binding change, no credential or profile change, and no mutation of any Weekly Briefings repository.

## Canonical PR State STATE: approve-at-current-head WHO_IS_NEXT: merger NEXT_ACTION: Merge PR #984 into master at head 03b434a0b631a197005068725176b3726a46ae89 once a merger session holds the canonical merger lease; no author work remains. NEXT_PROMPT: Continue Merger work on Gitea-Tools PR #984 (issue #983) as namespace gitea-merger, profile prgs-merger, repository Scaled-Tech-Consulting/Gitea-Tools. Invoke the canonical gitea-workflow skill first and verify runtime parity, repository binding, and merger mutation capability with fresh native calls. The reviewer verdict is an approval at head 03b434a0b631a197005068725176b3726a46ae89 with merge-base 108cbfa173de34470d7abc022b929e6b3adc418a; confirm approval_at_current_head is true and has_blocking_change_requests is false before acting, because the superseded REQUEST_CHANGES review 658 at head 2d5d5c9d174ae5f7a36c57e724af298fc5cff8dc remains on the record undismissed by design. Acquire the merger PR lease, merge into master, then reconcile the terminal labels and clean up the source branch fix/issue-983-cross-repo-base-ref and the review worktrees branches/review-pr984-2d5d5c9 and branches/review-pr984-03b434a0. Note that the PR description text is stale in three places and issue comment 18890 is the accurate record; do not treat the PR body as authoritative. WHAT_HAPPENED: Independent re-review at the new head. The complete diff from base 108cbfa was read rather than only the increment since review 658, all six production call paths were traced, and the resolver, guard, and parity report were executed read-only against the live Weekly Briefings target, the live PRGS control checkout, and four hermetic repositories. B1 and B2 are both remediated and the two previously non-blocking contract notes are also addressed. WHY: The stale clone-time remote-HEAD cache is no longer authoritative; the checkout's configured upstream now decides the integration branch, so a Weekly Briefings checkout sitting exactly on its MDCPS/dev tip derives MDCPS/dev instead of MDCPS/main. The parity report no longer hands its own inferred remote back to the resolver, so an ambiguous two-remote target now fails closed identically in gating and in reporting instead of the report naming one plausible repository. ISSUE: #983 HEAD_SHA: 03b434a0b631a197005068725176b3726a46ae89 REVIEW_STATUS: approve MERGE_READY: true NATIVE_REVIEW_PROOF: transport=native_mcp; bound_transport=stdio; entrypoint=mcp_server; entrypoint_path=/Users/jasonwalker/Development/Gitea-Tools/gitea_mcp_server.py; mode=production; production_native_mcp_transport=true; pytest=false; pid=52142; token_fingerprint=adba475da9fda9f1 BLOCKERS: none VALIDATION: Focused tests/test_issue_983_cross_repo_base_ref.py 37 passed; 29 affected suites 853 passed with 192 subtests passed and 6 pre-existing failures, against the same 28 suites at base 108cbfa showing 815 passed with 192 subtests passed and the identical 6 failures; full suite at the PR head 28 failed, 6204 passed, 6 skipped, 1106 subtests passed, against the full suite at base 108cbfa 28 failed, 6166 passed, 6 skipped, 1106 subtests passed, with both sorted FAILED lists byte-identical at sha1 fdebb1c202c86326d2afb0fd13df71e6790f4ad2, so zero failures were introduced and the plus-38 passed delta is this PR's own new coverage. LAST_UPDATED_BY: reviewer ## Verdict APPROVE at head `03b434a0b631a197005068725176b3726a46ae89`, base `master` @ `108cbfa173de`. Reviewed as `prgs-reviewer` / `sysadmin`; the PR author is `jcwalker3`, so identities differ. Runtime parity green, `mutation_safe: true`, one MCP cohort, no duplicate-cohort blocker. Review worktree `branches/review-pr984-03b434a0` detached at the PR head; `merge-base == 108cbfa173de`, two commits on top of master, nothing extraneous carried. Both blocking findings from review 658 are fixed, and fixed at the root rather than papered over. The remediation is the stronger of the two options I described: the cache is not merely demoted below the configured upstream, it is removed from the decision entirely and kept only as a reported observation. ## B1 — resolved `refs/remotes/<remote>/HEAD` is no longer a resolution step. `BASE_REF_SOURCE_*` names only `configured_branch_upstream` and `unique_integration_branch_ref`, and the module documents why the cache is excluded. Order is now: identity remote (ambiguity-aware) → the checkout's `branch.<current>.remote` + `branch.<current>.merge`, accepted only when it names that remote **and** its tracking ref exists → exactly one present `master`/`main`/`dev` tracking ref. Executed read-only against the live target `/Users/jasonwalker/Development/weekly-briefings`, whose state is unchanged from the one that produced review 658 — cached `refs/remotes/MDCPS/HEAD` still names `main` at `9a84325a1b68`, `refs/remotes/MDCPS/dev` is `a37ac427c18b`, local HEAD is on branch `dev` at `a37ac427c18b`, `@{upstream}` is `MDCPS/dev`: ``` DERIVED proven=true remote=MDCPS branch=dev tracking_ref=refs/remotes/MDCPS/dev source=configured_branch_upstream repository_slug=MDCPS/WeeklyBriefings-Meta cached_remote_head_branch=main cached_remote_head_conflicts=true GATE sha=a37ac427c18bb3a93bd95c74b35171b4553a1653 ref=MDCPS/dev REPORT tracking_ref=refs/remotes/MDCPS/dev base_remote=MDCPS base_branch=dev checkout_head=a37ac427c18b remote_tracking_head=a37ac427c18b stale=false reasons=[] ``` The checkout that review 658 showed being gated against `MDCPS/main` is now compared against `MDCPS/dev` and reports in-parity. Acceptance criterion 2 is met against the actual repository, not only a fixture. The stale cache is surfaced honestly as `cached_remote_head_conflicts: true` rather than silently obeyed. PRGS is unchanged. Against the live control checkout: `prgs` / `master` / `refs/remotes/prgs/master`, slug `Scaled-Tech-Consulting/Gitea-Tools`, `checkout_head == remote_tracking_head == 108cbfa173de`, `stale: false`, `reasons: []`. The source label is now `configured_branch_upstream` rather than `remote_head_symref`, which is the intended consequence of the fix; the resolved remote, branch, ref and SHA are identical. The orphan-`origin` repair still holds — the running server at `108cbfa` still reports `tracking_ref: refs/remotes/origin/master`, `repository_slug: null`, `stale: true`, and this branch fixes exactly that. Read-only is proven, not asserted: refs, config, remotes, HEAD and `--untracked-files=all` status were snapshotted before and after every probe on both live repositories and compared equal. No fetch, no `git remote set-head`, no ref write. The Weekly Briefings repository was not modified. The requested regression fixture exists and is genuine. `_RepoCase` builds remote `MDCPS`, checks out `dev`, sets upstream `MDCPS/dev`, and creates **both** `dev` and `main` tracking refs at *different* commits with `refs/remotes/MDCPS/HEAD` cached at `main`. `test_configured_upstream_beats_stale_cached_remote_head` asserts the cache still says `main`, asserts the two SHAs differ, and asserts `dev` is derived — so it fails against the previous head rather than passing vacuously. `test_cached_remote_head_alone_never_proves_a_target` and `test_cached_remote_head_never_breaks_a_tie` close the class. ## B2 — resolved `master_parity_gate.assess_target_repository_parity` now calls `_crr.assess_identity_remote(canonical_root)` and `_crr.resolve_target_base_ref(canonical_root)` with no remote argument, and returns early when identity is ambiguous. The parameter is renamed `explicit_remote` throughout `resolve_target_base_ref`, `resolve_remote_master_sha` and `resolve_remote_master_ref_state`, which makes the contract enforceable rather than conventional, and `test_no_production_caller_supplies_an_explicit_remote` holds the line. I confirmed by grep that no production module passes it. Reproduced on a hermetic repository with `MDCPS` → `MDCPS/WeeklyBriefings-Meta` and `prgs` → `Scaled-Tech-Consulting/Gitea-Tools`: ``` IDENTITY remote=None slug=None ambiguous=true reason_code=ambiguous_identity_remote RESOLVER proven=false reason_code=ambiguous_identity_remote GATE sha=None ref=None reason_code=ambiguous_identity_remote REPORT repository_slug=None tracking_ref=None base_remote=None reason_code=ambiguous_identity_remote reasons=["ambiguous repository identity ... remotes resolve to different repositories (prgs -> ..., MDCPS -> ...) ... (fail closed)"] ``` Gate and report now refuse together and carry the *same* `reason_code`. The report no longer names a repository the gate refuses. Operator disambiguation still works and is correctly distinguished: `explicit_remote="prgs"` and `explicit_remote="MDCPS"` each resolve their own target with `identity_explicit: true`, while `explicit_remote="nonexistent"` cannot unlock the ambiguous target. Two further hermetic cases behave correctly: with no configured upstream and both `dev` and `main` present, resolution fails closed with `ambiguous_integration_branch` even though the cache names `main` — the cache is explicitly refused as a tie-breaker and the refusal text says so and states the read-only remedy. With no candidate ref at all, `no_integration_branch_ref`. In every case gate and report agreed. ## Previously non-blocking notes, both now addressed - `proven: true` with an unresolvable `tracking_ref` is gone. Steps 2 and 3 each require `_ref_exists` before returning proven, and `test_every_proven_target_resolves` pins it. - `determinable: True` alongside a failed base-ref derivation remains, but it is now accompanied by a populated `reason_code` and `reasons`, so the refusal states its cause. It matches the pre-existing shape and does not block. ## Production callers Six paths traced, all consistent: `gitea_mcp_server.py:1059` (author bootstrap), `:1094` (create-issue bootstrap, #749/#757), `:1321` (namespace mutation preflight), `:2011` (`_enforce_root_checkout_guard`, #475), `anti_stomp_preflight.py:551` (root-checkout check, now receiving `remote_master_ref`), and `gitea_mcp_server.py:19983` (`assess_target_repository_parity`). Every `resolve_remote_master_sha(canonical_root)` production call is gone. `REMOTE_MASTER_REFS` and `DEFAULT_TARGET_TRACKING_REF` survive as explicit-override constants with no production consumer, which is the documented intent. No `MDCPS`, `WeeklyBriefings-Meta` or `dev` special-casing exists in the derivation path — only documentation prose and the pre-existing lowercase `mdcps` entry in `_IDENTITY_REMOTE_CANDIDATES`, which is unchanged by this diff and provably cannot supply the remote name. ## Independent test results Run by me in `branches/review-pr984-03b434a0` at `03b434a0`, with the base comparison in `branches/baseline-980-108cbfa` at `108cbfa`: ``` focused tests/test_issue_983_cross_repo_base_ref.py 37 passed in 9.35s affected 29 suites @ head 6 failed, 853 passed, 192 subtests passed 28 suites @ base 6 failed, 815 passed, 192 subtests passed (identical 6) full @ head 28 failed, 6204 passed, 6 skipped, 1106 subtests passed @ base 28 failed, 6166 passed, 6 skipped, 1106 subtests passed FAILED lists sorted and diffed: byte-identical, sha1 fdebb1c202c86326d2afb0fd13df71e6790f4ad2 ``` The six affected-suite failures are root-checkout-guard and workspace-guard tests that patch `resolve_remote_master_sha`; they fail identically at base `108cbfa`, so they are pre-existing and not caused by the call-site move. All 28 full-suite failures are pre-existing. Zero introduced failures; the `+38` passed delta is this PR's own coverage. Coverage confirmed for every required case: PRGS `prgs/master`; cross-repository `<remote>/dev`; stale cached remote HEAD; no `origin` remote; case-sensitive remote names; matching tip; behind and divergent; missing remote and missing ref; ambiguous remotes and ambiguous branch; gate/report consistency including on ambiguous targets; explicit versus inferred disambiguation; read-only resolver behaviour; and every affected production caller. ## One record-keeping note for the merger The PR description text is stale in three places — it still describes step 2 as `refs/remotes/<remote>/HEAD`, still cites source `remote_head_symref` for PRGS, and still cites the previous head's test counts of 24 / 375 / 6191. The author documented this in issue comment 18890 and could not edit the description from the author role under the #618 wall. Issue comment 18890 is the accurate record. This is a documentation artefact only; the code, tests and behaviour at this head are correct, so it does not block. ## Reviewed head `03b434a0b631a197005068725176b3726a46ae89`. Not merged. Review 658 left in place, not dismissed and not overwritten. No restart, no binding change, no credential or profile change, and no mutation of any Weekly Briefings repository.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #984
issue: #983
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 52142-ac568169b8e7
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0
phase: released
candidate_head: 03b434a0b6
target_branch: master
target_branch_sha: 108cbfa173
last_activity: 2026-07-31T04:54:29Z
expires_at: 2026-07-31T05:04:29Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #984 issue: #983 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 52142-ac568169b8e7 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0 phase: released candidate_head: 03b434a0b631a197005068725176b3726a46ae89 target_branch: master target_branch_sha: 108cbfa173de34470d7abc022b929e6b3adc418a last_activity: 2026-07-31T04:54:29Z expires_at: 2026-07-31T05:04:29Z blocker: manual-release
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #984
issue: #983
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 91323-1e01d8c22104
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0
phase: claimed
candidate_head: 03b434a0b6
target_branch: master
target_branch_sha: 108cbfa173
last_activity: 2026-07-31T05:04:10Z
expires_at: 2026-07-31T05:14:10Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #984 issue: #983 reviewer_identity: sysadmin profile: prgs-merger session_id: 91323-1e01d8c22104 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr984-03b434a0 phase: claimed candidate_head: 03b434a0b631a197005068725176b3726a46ae89 target_branch: master target_branch_sha: 108cbfa173de34470d7abc022b929e6b3adc418a last_activity: 2026-07-31T05:04:10Z expires_at: 2026-07-31T05:14:10Z blocker: none
sysadmin merged commit 32ab839289 into master 2026-07-31 00:05:24 -05:00
Owner

Stale #332 review-decision lock cleanup (#594)

Status: APPLIED

Manual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.

## Stale #332 review-decision lock cleanup (#594) Status: **APPLIED** - actor: `sysadmin` - profile: `prgs-merger` - timestamp: `2026-07-31T05:05:28.876343+00:00` - last terminal: `approve` on PR #984 - PR state: `closed` (merged=True) - merge_commit_sha: `32ab839289e6efffa5cbfe978af30178b53d63ab` - prior live_mutations_count: `3` - prior profile_identity: `prgs-reviewer` Manual deletion of session-state files is **not** the workflow. This path only clears a lock when the referenced PR is merged/closed.
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#984