Skip to content

feat: close out issues when their devloop PR merges - #2

Merged
RjBiermann merged 1 commit into
masterfrom
forge-owns-checkouts
Sep 12, 2026
Merged

RjBiermann merged 1 commit into
masterfrom
forge-owns-checkouts

Conversation

@RjBiermann

Copy link
Copy Markdown
Owner

What

A human-merged devloop PR (devloop/issue-N branch) now completes its issue's lifecycle: devloop posts a devloop PR merged #P ledger entry and closes the issue. Today nothing listens to merge events — merged issues linger open and become re-buildable ghosts on the next sweep.

Why it's not a guardrail breach

close_issue stays human-only for everything else. This path gets the same carve-out /retry's close_pr got: the human's merge IS the judgment that the work is done — devloop executes that act, never judges its own work. The handler fires only from a real forge merge event, never agent output.

Changes

  • ledger.py: MERGED marker + merged() producer — deliberately outside MARKERS, so count() never mistakes a merge for an attempt
  • forge/base.py: complete_issue() with carve-out docstring; GitHub adapter: gh issue close
  • core.py: handle_merge() — deterministic devloop/issue-N → issue mapping, no-op on any other branch or malformed number
  • cli.py: devloop merged — reads $GITHUB_EVENT_PATH, silent exit off-CI (zero token spend)
  • deploy/github-actions.yml: pull_request: types: [closed] trigger, YAML-gated to merged == true + devloop/ head branch so unrelated merges cost nothing
  • Docs: CONTEXT.md Closeout term, README guardrail paragraph, CHANGELOG

Verification

$ python3 tests/test_devloop.py
all checks passed

New test: test_merged_pr_completes_issue — merge → ledger + close; non-devloop branch → no-op; malformed branch → no-op; close_issue still raises for other callers; merge marker not counted as an attempt.

A human-merged devloop PR now completes its issue's lifecycle: ledger
completion entry (not counted as an attempt) + issue close. Same
carve-out as /retry's close_pr — the merge IS the human's verdict;
devloop executes it, never judges its own work.

- ledger: MERGED marker + merged() producer, outside MARKERS
- forge: complete_issue() (base docstring cites the precedent), gh impl
- core: handle_merge() — devloop/issue-N branch mapping, no-op otherwise
- cli: devloop merged (GITHUB_EVENT_PATH, silent no-op off-CI)
- workflow template: pull_request closed trigger, YAML-gated to merged
  devloop branches
- tests, CONTEXT.md (Closeout), README guardrail note, CHANGELOG
@RjBiermann
RjBiermann merged commit c6ee2e1 into master Sep 12, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant