Repository navigation
Description
Problem
Part of #588 and the restoration portion of #325. It belongs to agentrepo pr (alongside #323), not agentrepo checks: restoring a local description does not watch or diagnose checks.
On origin/main at 591fd70b46a5cca7174521d72eace58039a95444, fix-pr and merge-pr carry byte-identical populate-description.sh scripts (packages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:1, packages/agents/source/skills/merge-pr/shared/scripts/populate-description.sh:1). Both rebuild PR_AGENTDESC.md from an open PR. The nonempty-draft guard is at populate-description.sh:54 (before target discovery and the metadata read), the single metadata read at :69, the direct write that can truncate a draft on decode failure at :73 and :104, and the false suffix-removal guidance at :107. No Go restoration exists: internal/agentrepo/command.go registers no pr command.
Coverage on main: no test exercises either script. tests/skills/fix-pr/scripts/test_diagnose.py no longer exists (removed when diagnosis moved to Go, #832/#959/#960); tests/skills/fix-pr/scripts/diagnose.bats covers only the diagnose wrapper's dispatch. docs/script-inventory.md:195 still names the removed file and says fix-pr has no Bats suite; this PR corrects that line.
Overlapping work, with the disposition decided here:
- Open PRs fix(fix-pr): make unattended repair paths deterministic #349 and fix(fix-pr): make unattended repair paths deterministic #696 (near-duplicates; same branch family, same 18 files) also edit
populate-description.shand addtests/skills/fix-pr/populate-description.bats. They drop the guard at:54, read metadata for a nonempty draft, and reportcurrent/hold/refreshedwith status 75 for a differing draft, to satisfy fix-pr lacks a decision rule for an existing PR_AGENTDESC.md #296. fix(fix-pr): make unattended repair paths deterministic #349 has CHANGES_REQUESTED; fix(fix-pr): make unattended repair paths deterministic #696 has no review or checks. - Disposition: this issue ports the contract on main and does not adopt that behavior. fix(fix-pr): make unattended repair paths deterministic #349 and fix(fix-pr): make unattended repair paths deterministic #696 are neither blockers nor incorporated; their populate-description changes are deferred to a Go follow-up on the new command (see Scope), and their other changes (fix-pr names the operator scripts for republishing instead of the agent-pr route #294, fix-pr asks through AskUserQuestion and has no default for a headless session #295) are independent of this issue. If one lands first, this PR rebases and its AC2/AC6 oracle becomes the landed contract; that is a scope amendment on this issue, not a native blocker.
- fix-pr lacks a decision rule for an existing PR_AGENTDESC.md #296 stays open. This PR does not close it. The follow-up closes it.
Other restoration owners, with the disposition decided here (verified against the bodies of #873, #874 and #584 and origin/main at 591fd70b46a5cca7174521d72eace58039a95444):
- feat(pr): move shared description restoration into Go #795 owns the single restoration command,
agentrepo pr populate-description, and the wrapper cutover of bothpopulate-description.shcopies (fix-pr and merge-pr). Noagentrepo merge descriptioncommand is created. - A pull request description draft is rebuilt from the published pull request in Go #873 (child 13 of Move the merge-pr, merge policy and agent-merge-pr scripts into agentrepo merge #324) specifies
agentrepo merge descriptionfor the merge-pr copy only, blocked by Ship the Go binaries as release assets installed through mise's github backend #333, keeping the closing message about suffix removal that the script does not honor (its AC2 and Non-goal). That contradicts AC9 here and duplicates this command, so A pull request description draft is rebuilt from the published pull request in Go #873 is superseded by this issue. - The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874 (child 14 of Move the merge-pr, merge policy and agent-merge-pr scripts into agentrepo merge #324) names
populate-description.shamong four scripts it routes toagentrepo merge(its Problem, AC1, AC2, AC8, Scope, Size, and A pull request description draft is rebuilt from the published pull request in Go #873 in its Dependencies). Its restoration portion is superseded by this issue; The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874 keepslint-squash-msg.sh,squash-message.shandreview.sh(and the threeagent-merge-prcounterparts). The merge-prpopulate-description.sh(62 code lines, per Move the merge-pr, merge policy and agent-merge-pr scripts into agentrepo merge #324's table) leaves The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874's 351-line count, leaving 289. - Consolidate the duplicated populate-description.sh into one shared source #584 (relocate the byte-identical
populate-description.shintopackages/agents/source/lib/) is independent and not a blocker. After this change the two copies are a dispatch shim and a frozenpopulate-description-legacy.sh, both still byte-identical across the skills, so Consolidate the duplicated populate-description.sh into one shared source #584 stays valid but shrinks to relocating those two files, and the legacy copy is deleted after the N-2 window. It is not incorporated here. Whichever lands second rebases onto the other; if Consolidate the duplicated populate-description.sh into one shared source #584 lands first this PR edits the shared source instead of the two skill sources. - Required reconciliation before build starts (issue-body edits, no code): close A pull request description draft is rebuilt from the published pull request in Go #873 as superseded by feat(pr): move shared description restoration into Go #795; narrow The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874 to drop the restoration script from its Problem, ACs, Scope, Size and Dependencies; strike child 13 in Move the merge-pr, merge policy and agent-merge-pr scripts into agentrepo merge #324's Children list and record that child 14 no longer covers
populate-description.sh. No native blocked-by results: nothing here waits on those issues.
Acceptance criteria
- AC1: When restoration is requested through either the fix-pr or merge-pr entry point, the result is the same as
agentrepo pr populate-descriptionfor the same PR and local draft state. - AC2: Given a nonempty local draft and no
--force, with GitHub access present, the draft is unchanged, the existing left-alone guidance is printed, the status is 0, and no PR metadata is read. - AC3: Given no local draft, an empty draft, or
--force, a successful restoration writes the reconstructed draft at the repository root. - AC4: An explicit number or the current branch's open PR selects the target; missing repository context, missing GitHub access or no discoverable PR produces the existing refusal and nonzero status.
- AC5: Non-functional: the reconstructed properties, title and body all come from one PR metadata read.
- AC6: Given readable PR metadata, the draft keeps the existing field order and values, title and body transformations and single trailing newline.
- AC7: Given any PR review-request state, the reconstructed frontmatter has an empty reviewers list.
- AC8: Given failed retrieval, decoding or draft writing, restoration exits 1 and leaves any existing draft byte-identical, with no partial new draft (a deliberate difference from the frozen shell).
- AC9: Successful restoration reports the draft and source PR with status 0, and its guidance does not claim a title suffix was removed (a deliberate difference from the frozen shell).
- AC10: Non-functional: restoration changes only the requested local draft: no remote write, review request or Git-state change, whatever
GH_REPO,GH_HOSTorCDPATHhold. - AC11: Non-functional: restoration gives the same outcomes on Linux, macOS and Windows.
- AC12: Both entry points only dispatch: they forward arguments, output and status unchanged to the Go command when it exists, run the unchanged frozen script throughout the N-2 window when it doesn't, never fall back after a supported run fails, and add no other shell logic.
Scope and non-goals
Moves into agentrepo pr populate-description: the draft restoration both skills duplicate, preserving the contract at the commit above (flag order [--force] [number], repository-root execution, access checks before the draft guard, field order base, draft, labels, reviewers, assignees, milestone, a blank line before the level-one title and body, CRLF to LF, outer whitespace stripped, existing title text kept). Go-path differences from the frozen shell are AC8 and AC9 only; they are documented in docs/agent-skills-migration.md.
Non-goal: the #296 classification (current/hold/refreshed, status 75), the removal of the AC2 guard, and any other behavior change. File a follow-up issue for it (Problem and numbered ACs), built on this command, list it under PR Related, and link #349/#696 and #296 from it.
Non-goals: an agentrepo merge description command (#873) and the restoration portion of #874; relocating the script source (#584); watching or diagnosing checks; description validation, review, publication or merging (#323, #324); new frontmatter properties, reviewer replay or title-suffix changes; guard or authority logic; deleting the N-2 fallback.
Approach
Capture old-script fixtures for both skills first, then add the Go command with table-driven tests against a fake gh and disposable repositories. Mirror the existing diagnose pattern: each skill's populate-description.sh becomes a dispatch shim (probe agentrepo pr populate-description --help, exec on support, otherwise run populate-description-legacy.sh, the unchanged old script). Edit the skill sources, then mise run generate-skills, mise run skill-tokens and apm install. Restoration stays explicit; it is not added to any preflight.
Dependencies
No native blocker. #333 and #544 deliver the binary to consumers; the probe-and-fallback shim lets this land first. #324 is affected only through the child reconciliation listed in Problem: #873 is superseded and #874 narrowed, so neither blocks nor is blocked by this issue. #323 is unaffected. #349, #696 and #584: see Problem.
Size
M, one PR, estimated 450 to 650 code lines counting tests and generated copies (Go command about 130, Go tests about 280, shim tests about 100, shims and generated copies about 120, from the 62 code lines of each current script and the roughly 10-line diagnose.sh shim pattern; renamed legacy scripts count as renames). Measure with git diff --stat before publishing. If it exceeds 800 code lines, split into: (1) feat(pr): add agentrepo pr populate-description (Go command and tests); (2) refactor(skills): route populate-description through the Go command (shims, generated output, docs, shim tests).
Verify plan
- Red first: command regressions for the missing subcommand, draft preservation on failure and truthful guidance fail before the port and pass after.
- AC1: the same fixtures through the Go command and both entry points, and against both pinned shell scripts; compare draft bytes, stdout, stderr and status.
- AC2: nonempty draft without force, including a nonexistent explicit number; assert unchanged bytes, guidance, status 0 and zero metadata reads; missing access still refuses first.
- AC3: missing, empty and forced-nonempty drafts, run from a nested directory; only the root draft is written.
- AC4: explicit and inferred PRs; absent repository, tool, authentication or open PR; assert refusals, statuses and an untouched draft.
- AC5: count exactly one metadata read; vary a hypothetical second response and assert every field comes from the first.
- AC6, AC7: byte-compare against baseline for draft true/false, empty and multiple labels and assignees, present and absent milestone, empty, whitespace and CRLF bodies, title whitespace and a literal
(#N)suffix, and PRs with unfinished and completed review requests (reviewers: []). - AC8: failed retrieval, malformed metadata and write failure with absent, empty, nonempty and forced drafts; assert status 1, original bytes retained and no partial file.
- AC9: assert the success message and status 0, with a suffixed title kept intact and no removal claim.
- AC10: fake
ghrejects any mutating call; compare repository content, index and refs before and after; run withGH_REPO,GH_HOSTandCDPATHset. - AC11: Go tests on the Linux, macOS and Windows jobs;
mise run check,mise run cover-go-check,mise run cover-py-check;mise run check-generated-skillsafter generate, token and apm steps. - AC12 (including no other shell logic; review the shell diff for dispatch and renames only): for both entry points test a supporting binary, no binary, a binary lacking the subcommand, and a supported run that fails; assert forwarding, fallback only on missing capability and no second run after an error.
- Delivery (D1 to D10): per the definition of done in the refinement comment; cite each AC id and its evidence in the PR.
Risks
A supported failure retried through the fallback would write twice (AC12). A forced run that fails could destroy a draft (AC8). A change reaching only one caller or only some generated copies would leave them diverged (AC1, mise run check-generated-skills). If #349 or #696 lands first the oracle shifts; rebase and amend the ACs. Undo: revert this PR and run mise run generate-skills; the frozen scripts return to their old names and behavior.
Operator authority
None
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-dev-reviews commentedon Oct 31, 2026
Refinement: NOT READY — resolve the competing existing-draft contract
Checked
origin/mainagainst remote main at591fd70b46a5cca7174521d72eace58039a95444. Both restoration scripts remain identical to the issue's pinned baseline. The overwrite guard, single metadata read, direct-write failure risk and misleading title guidance are confirmed atpackages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:54,packages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:69,packages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:104andpackages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:107.Operator authority: Nonefits this local reconstruction scope and grants no publication or merge authority. Native blocked-by is empty; the listed broader ports and distribution rollout are described as context or later retirement prerequisites, rather than landing blockers.internal/agentrepo/command.go:85does not register a PR command. Sibling diagnosis has shipped through feat(checks): diagnose failures in Go #832/test(checks): verify diagnosis report parity #959/feat(checks): route diagnosis through the Go command #960; that does not deliver restoration. Open PRs fix(fix-pr): make unattended repair paths deterministic #349 and fix(fix-pr): make unattended repair paths deterministic #696 do overlap this operation.Gaps
packages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:54, read metadata even for a nonempty draft, and reportcurrent/hold/refreshed, including status 75 for a differing draft. This directly conflicts with AC2's metadata-free status-0 guard and with the assumption that both callers share an unchanged contract. Neither PR is acknowledged in feat(pr): move shared description restoration into Go #795. Record which work is superseded, deferred or incorporated, and reconcile fix-pr lacks a decision rule for an existing PR_AGENTDESC.md #296 with AC2 and the parity oracle. If an earlier change must land first, add its issue as a native blocked-by dependency; if it is superseded or deferred, state that disposition without inventing a blocker. Keep any adopted behavioral changes in Go under Replace complex shell with tested Go, starting with gates and merging #588's freeze, and revisit size if this expands scope. The Go migration itself is not already delivered, but these competing contracts cannot both remain the intended result.The historical diagnosis-test reference is also stale on current main: #960 removed
tests/skills/fix-pr/scripts/test_diagnose.py. Refresh that evidence when revising the issue; this is not an additional readiness blocker.Split
No split required for the stated restoration-only scope. Resolve the overlap above before deciding whether adopting #296's classification behavior warrants a separate Go follow-up.
Definition of done
Checked boxes mean the issue's ACs and Verify plan cover the requirement, not that implementation or delivery has occurred.
provenance:agent-assistedto the PR.Status:comment.Round: 1 of 3
tbhb-dev-reviews commentedon Oct 31, 2026
Refinement: NOT READY — reconcile the second restoration owner and wrapper cutover
Checked
bin/request check, Go tests or any full suite. Read feat(pr): move shared description restoration into Go #795 and its newest earlier Refinement comment, parent Move watch-pr and fix-pr scripts into agentrepo checks #325, Epic Replace complex shell with tested Go, starting with gates and merging #588, siblings feat(checks): move pull request watching into Go #793/feat(checks): move pull request failure diagnosis into Go #794, transaction epics Move the pr, write-pr-description and agent-pr scripts into agentrepo pr #323/Move the merge-pr, merge policy and agent-merge-pr scripts into agentrepo merge #324, distribution work Ship the Go binaries as release assets installed through mise's github backend #333/feat(distribution): migrate consumer tool pins to release assets #544, fix-pr lacks a decision rule for an existing PR_AGENTDESC.md #296, overlapping issues Consolidate the duplicated populate-description.sh into one shared source #584/A pull request description draft is rebuilt from the published pull request in Go #873/The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874 and PRs fix(fix-pr): make unattended repair paths deterministic #349/fix(fix-pr): make unattended repair paths deterministic #696.origin/mainagainst remote main at591fd70b46a5cca7174521d72eace58039a95444. Both canonical restoration scripts are byte-identical. Access checks precede the metadata-free nonempty-draft guard atpackages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:51andpackages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:54. The single metadata read, direct-write failure exposure and false suffix guidance remain atpackages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:69,packages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:104andpackages/agents/source/skills/fix-pr/shared/scripts/populate-description.sh:107.current/hold/refreshed, including status 75. Neither delivers Go restoration. The disposition is now explicit and consistent with the verified baseline.tests/skills/fix-pr/scripts/diagnose.bats, not the removed Python test. The obsolete inventory claim remains atdocs/script-inventory.md:195, and this issue includes its correction. The previous Split advice is addressed by retaining restoration-only scope and deferring fix-pr lacks a decision rule for an existing PR_AGENTDESC.md #296 to a separate Go follow-up.internal/agentrepo/command.go:85; related-PR searches found no merged or open PR delivering it. Diagnosis PRs feat(checks): diagnose failures in Go #832/test(checks): verify diagnosis report parity #959/feat(checks): route diagnosis through the Go command #960 are merged and deliver different behavior. The compatibility dispatch pattern is visible atpackages/agents/source/skills/fix-pr/shared/scripts/diagnose.sh:5.Operator authority: Nonefits local reconstruction. Native blocked-by is empty, consistent with capability fallback and no prerequisite distribution rollout, subject to resolving ownership below.Gaps
packages/agents/source/skills/merge-pr/shared/scripts/populate-description.sh:1withagentrepo merge description, preserves the misleading closing message, and waits on Ship the Go binaries as release assets installed through mise's github backend #333. The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874 includes this same script in its wrapper cutover, routes it toagentrepo merge, and depends on A pull request description draft is rebuilt from the published pull request in Go #873. feat(pr): move shared description restoration into Go #795 owns both callers, routes them toagentrepo pr populate-description, corrects the message under AC9 and lands with fallback independently of Ship the Go binaries as release assets installed through mise's github backend #333. These deliverables overlap and specify incompatible command and guidance contracts. Amend feat(pr): move shared description restoration into Go #795's Problem, Scope and Dependencies with an explicit disposition for A pull request description draft is rebuilt from the published pull request in Go #873 and the restoration portion of The lint, populate-description, squash-message and review scripts become wrappers over agentrepo merge #874; reconcile those linked issue bodies and Move the merge-pr, merge policy and agent-merge-pr scripts into agentrepo merge #324's child ownership so there is one command and one wrapper owner. Also state whether Consolidate the duplicated populate-description.sh into one shared source #584's source consolidation is superseded or remains independently useful: it relocates the same two maintained sources this issue converts to shims. If any work must land first, record its issue as native blocked-by; otherwise defer or supersede it explicitly without manufacturing a blocker. Keep the resolution in Go under Replace complex shell with tested Go, starting with gates and merging #588 and reassess size if scope grows.Split
No implementation split is required for the stated restoration-only scope. The size contingency is reasonable. Settle #873/#874/#584 ownership before coding; retain the separately specified Go follow-up for #296.
Definition of done
Checked boxes mean the ACs and Verify plan cover the requirement, including the body's explicit adoption of D1–D10 from the previous refinement comment. They do not mean implementation or delivery has occurred.
check-leaks.shwith the repository's private-strings list, and the leak review of each post.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why.provenance:agent-assistedlabel.Status:comment names the merge commit.mise run checkis green, and so are the coverage floorsmise run cover-go-checkandmise run cover-py-check, whichcheckdoesn't run.packages/agents/source/commits whatmise run generate-skills, thenmise run skill-tokens, thenapm installrewrite, in that order, andcheck-generated-skills(part oflint) passes.docs/agent-skills-migration.mdor the adoption docs, or the PR's Verification says "No consumer impact" and why.Round: 2 of 3
tbhb-dev-reviews commentedon Oct 31, 2026
Refinement: NOT READY — finish the recorded restoration ownership reconciliation
Checked
Gaps
Split
No additional implementation split is needed for the current restoration-only scope; retain the documented over-800-line contingency and separate Go follow-up for #296. This third NOT READY exhausts the three refinement rounds: the owner must rethink the remaining ownership coordination and reconcile the records before building, rather than start a fourth unchanged refinement round or escalate a non-reserved choice to the operator.
Definition of done
Ticks mean the ACs and Verify plan cover the requirement, including the explicit adoption of D1–D10 from the refinement comment. They do not claim completed implementation, passing delivery checks or independent approval of a future head.
check-leaks.shwith the repository's private-strings list, and the leak review of each post.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why.provenance:agent-assistedlabel.Status:comment names the merge commit.mise run checkis green, and so are the coverage floorsmise run cover-go-checkandmise run cover-py-check, whichcheckdoesn't run.packages/agents/source/commits whatmise run generate-skills, thenmise run skill-tokens, thenapm installrewrite, in that order, andcheck-generated-skills(part oflint) passes.docs/agent-skills-migration.mdor the adoption docs, or the PR's Verification says "No consumer impact" and why.Round: 3 of 3