You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(source-control): map upkeep can adopt a fork PR that shares the upkeep branch name #9937
The map-upkeep flow (/testing:refresh-feature-map on main, ported to /app-control:map refresh in #9934) finds its existing upkeep PR with /source-control:pull-request list --head "<branch>". That lookup filters on the head branch name only: gh pr list --help says Filter by head branch ("<owner>:<branch>" syntax not supported), and read-pr.sh's LIST_FIELDS returns no isCrossRepository or headRepositoryOwner. On a public repository, a fork PR whose head branch has the upkeep branch's name is therefore taken as the upkeep PR. An unattended pass then pushes to origin, opens no PR, and reports the fork PR's URL as the upkeep PR.
Fix
list returns isCrossRepository and headRepositoryOwner.
The upkeep flow counts a match only when isCrossRepository is false. A same-named fork PR records blocked and is reported.
Evidence: plugins/testing/skills/refresh-feature-map/SKILL.md:177; plugins/source-control/skills/pull-request/scripts/read-pr.sh:40,96-99. Found by the security review of #9934 (finding 1). It exists on main, so it is deferred from that PR.
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Low
Uncertainty: Known
Flags: none
Blocked by: none
Decision recorded. The owner answered in the Refinement and Issue Triage sessions (2026-10-25), deciding the open items below on the facts:
[quote truncated; the full decision is at the link] #9937 (comment)
The decision settles the open questions: the bug still stands in /app-control:map refresh, the fix is the one in the body, and it is not a security stop. The work is to add isCrossRepository and headRepositoryOwner to read-pr.sh list, have the refresh flow count a match only when isCrossRepository is false (a same-named fork PR makes the outcome blocked and is named in the report), and add a test for the two fields.
Released for re-triage under the owner's 2026-10-24 rule: an issue stops for a person only for an intent or vision question, a security call, a host or attended run, or spend outside prepaid credit. The hold label came off and intake triage runs again now; it re-applies a hold, with a numbered question, when one of those applies.
To hold this issue again, add needs-human (or status: needs-decision) and say why in a comment.
Decision recorded. The owner answered in the Refinement and Issue Triage sessions (2026-10-25), deciding the open items below on the facts:
go with whatever the facts/data/metrics + /discovery:research says and ensure we're aligned with SOLID, DRY/SSOT principles
I should only ever be in the loop ONLY when necessary (intent/vision changed, something came up during implementation that impacts trajectory/alignment, OR a high security risk) - I've covered this all before
No owner ledger (.work/*/interview-checklist.md, .work/gh-monitor-owner-decisions/) names this issue.
The body's evidence paths moved: plugins/testing/skills/refresh-feature-map is gone from origin/main, and the upkeep flow now lives in /app-control:map refresh. The bug stands there.
Is the bug still on main?
Decided: Yes. plugins/app-control/skills/map/reference/refresh.md:214-215 finds the upkeep PR with /source-control:pull-request list --head "<branch>". read-pr.sh lists with LIST_FIELDS=number,url,state,isDraft,title,headRefName,baseRefName,mergeCommit (plugins/source-control/skills/pull-request/scripts/read-pr.sh:40) and filters on the branch name only (:94-104). gh pr list documents --head as "Filter by head branch (":" syntax not supported)" and offers isCrossRepository and headRepositoryOwner as JSON fields (https://cli.github.com/manual/gh_pr_list, read 2026-10-26).
Which fix?
Decided: The body's fix as written. list adds isCrossRepository and headRepositoryOwner to its fields; the upkeep flow counts a match only when isCrossRepository is false, and a same-named fork PR makes the outcome blocked with that PR named in the report. Basis: the same rule already guards the pr-unblock dispatchers, which skip any PR that is not "a ready same-repository PR" (.github/scripts/pr-unblock/fix-docs-dispatch.mjs:101-103).
Is this an owner security stop?
Decided: No. The harm is a wrong PR reported and a push to the repository's own upkeep branch; no token, grant or gate widens. The fix only tightens. Basis: refresh.md:214-219.
Acceptance criteria:
/source-control:pull-request list returns isCrossRepository and headRepositoryOwner for each PR.
/app-control:map refresh treats a listed PR as the upkeep PR only when isCrossRepository is false; a same-named fork PR makes the outcome blocked and the report names it.
A test of read-pr.sh list asserts both fields are in the output.
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.
Intended outcome:/source-control:pull-request list returns isCrossRepository and headRepositoryOwner, and /app-control:map refresh adopts a listed PR only when it is same-repository, recording a same-named fork PR as blocked.
Acceptance criteria
plugins/source-control/skills/pull-request/scripts/read-pr.sh LIST_FIELDS (line 40) includes isCrossRepository and headRepositoryOwner, and read-pr.sh list output carries both for each PR.
plugins/source-control/skills/pull-request/scripts/read-pr.test.sh has a list case that asserts both fields appear in the output, and the test script passes.
plugins/app-control/skills/map/reference/refresh.md step 4 (lines 214-219) says a listed PR counts as the upkeep PR only when isCrossRepository is false.
refresh.md says a same-named PR with isCrossRepository true makes the outcome blocked, and the report names that PR.
refresh.md does not push to the branch or report the fork PR URL as the upkeep PR in the fork case.
Any other doc in plugins/source-control/skills/pull-request that lists the list fields is updated to match.
plugins/source-control/skills/pull-request/scripts/read-pr.sh:40: LIST_FIELDS=number,url,state,isDraft,title,headRefName,baseRefName,mergeCommit, with no isCrossRepository or headRepositoryOwner
plugins/source-control/skills/pull-request/scripts/read-pr.sh:99: gh pr list is called with --json "$LIST_FIELDS"
plugins/app-control/skills/map/reference/refresh.md:214-219: upkeep PR lookup uses pull-request list --head and treats any match as the upkeep PR
plugins/source-control/skills/pull-request/scripts/read-pr.test.sh: exists, the place for the new list-fields test
issue comment 2026-10-26T20:08:28Z: owner decision confirming the bug, the fix and the three acceptance criteria
Automated refinement by the lanes App. Intake triages the issue again with it.
Activity
github-actions commentedon Oct 25, 2026
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Low
Uncertainty: Known
Flags: none
Blocked by: none
The decision settles the open questions: the bug still stands in
/app-control:map refresh, the fix is the one in the body, and it is not a security stop. The work is to addisCrossRepositoryandheadRepositoryOwnertoread-pr.sh list, have the refresh flow count a match only whenisCrossRepositoryis false (a same-named fork PR makes the outcome blocked and is named in the report), and add a test for the two fields.Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 25, 2026
The latest triage verdict holds nothing: the issue is at
status: ready.kyle-sexton commentedon Oct 26, 2026
Released for re-triage under the owner's 2026-10-24 rule: an issue stops for a person only for an intent or vision question, a security call, a host or attended run, or spend outside prepaid credit. The hold label came off and intake triage runs again now; it re-applies a hold, with a numbered question, when one of those applies.
To hold this issue again, add
needs-human(orstatus: needs-decision) and say why in a comment.1 remaining item
kyle-sexton commentedon Oct 26, 2026
Decision recorded. The owner answered in the Refinement and Issue Triage sessions (2026-10-25), deciding the open items below on the facts:
No owner ledger (
.work/*/interview-checklist.md,.work/gh-monitor-owner-decisions/) names this issue.The body's evidence paths moved:
plugins/testing/skills/refresh-feature-mapis gone from origin/main, and the upkeep flow now lives in/app-control:map refresh. The bug stands there.Decided: Yes.
plugins/app-control/skills/map/reference/refresh.md:214-215finds the upkeep PR with/source-control:pull-request list --head "<branch>".read-pr.shlists withLIST_FIELDS=number,url,state,isDraft,title,headRefName,baseRefName,mergeCommit(plugins/source-control/skills/pull-request/scripts/read-pr.sh:40) and filters on the branch name only (:94-104).gh pr listdocuments--headas "Filter by head branch (":" syntax not supported)" and offersisCrossRepositoryandheadRepositoryOwneras JSON fields (https://cli.github.com/manual/gh_pr_list, read 2026-10-26).Decided: The body's fix as written.
listaddsisCrossRepositoryandheadRepositoryOwnerto its fields; the upkeep flow counts a match only whenisCrossRepositoryis false, and a same-named fork PR makes the outcome blocked with that PR named in the report. Basis: the same rule already guards the pr-unblock dispatchers, which skip any PR that is not "a ready same-repository PR" (.github/scripts/pr-unblock/fix-docs-dispatch.mjs:101-103).Decided: No. The harm is a wrong PR reported and a push to the repository's own upkeep branch; no token, grant or gate widens. The fix only tightens. Basis:
refresh.md:214-219.Acceptance criteria:
/source-control:pull-request listreturnsisCrossRepositoryandheadRepositoryOwnerfor each PR./app-control:map refreshtreats a listed PR as the upkeep PR only whenisCrossRepositoryis false; a same-named fork PR makes the outcome blocked and the report names it.read-pr.sh listasserts both fields are in the output.melodic-automation-lanes commentedon Oct 26, 2026
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.
Intended outcome:
/source-control:pull-request listreturnsisCrossRepositoryandheadRepositoryOwner, and/app-control:map refreshadopts a listed PR only when it is same-repository, recording a same-named fork PR as blocked.Acceptance criteria
read-pr.sh listoutput carries both for each PR.Related work
Sources read
Automated refinement by the lanes App. Intake triages the issue again with it.