phase-merge squashes a sync phase, so the feature branch loses the main ancestry and the final PR stays unmergeable #750

Open
opened 2026-10-07 23:47:12 +00:00 by claude · 8 comments
Member
  • A sync phase (from final-pr-sync-<main>.md or a rework that merges origin/main) holds a real merge commit on its sub-branch. phase-merge merges the phase PR with squash (ForgeGateway.mergeSquashAndDelete), so the feature branch gets one flat commit with no parent link to main. The final PR then shows all of main's changes as its own and the forge reports it not mergeable — the sync achieves nothing. Evidence: IW-672 phase 2 sub-branch commit eca284d0 ("Merge origin/main into IW-672-phase-02", second parent = origin/main d9e76182) squashed into 32334fcd (#748); final PR #735 then had 146 changed files and mergeable: false. Fixed by hand with a tree-identical git merge origin/main on IW-672 (635339dc). A sync phase must reach the feature branch with a merge commit (or the sync must be done on the feature branch directly).

Found during IW-672.

- [ ] A sync phase (from `final-pr-sync-<main>.md` or a rework that merges `origin/main`) holds a real merge commit on its sub-branch. `phase-merge` merges the phase PR with squash (`ForgeGateway.mergeSquashAndDelete`), so the feature branch gets one flat commit with no parent link to `main`. The final PR then shows all of main's changes as its own and the forge reports it not mergeable — the sync achieves nothing. Evidence: IW-672 phase 2 sub-branch commit `eca284d0` ("Merge origin/main into IW-672-phase-02", second parent = origin/main `d9e76182`) squashed into `32334fcd` (#748); final PR #735 then had 146 changed files and `mergeable: false`. Fixed by hand with a tree-identical `git merge origin/main` on IW-672 (`635339dc`). A sync phase must reach the feature branch with a merge commit (or the sync must be done on the feature branch directly). Found during IW-672.
Author
Member

Intake: needs-input
Workflow: diagnostic
Reason: G7 (1 [human] finding)
Analysis: project-management/issues/IW-750/analysis.md on branch IW-750

1. Should IW-750 also change phase-pr --batch and the agent merge guidance, and if so, how? (G7)

The issue names only phase-merge. The analysis also fixes phase-pr --batch, which squashes every phase PR on all forges, and the agent guidance text, which tells agents to merge with --squash. An earlier issue already decided that phase PRs use a merge commit and are not squashed. It also named the batch squash as "inconsistent", but nobody fixed it. No recorded reason for the batch squash exists.

"Phase PRs use merge commit + delete branch (--merge --delete-branch). The final PR (feature → main) may use squash." (IW-289 analysis)

Analysis sections: batch fix, guidance, guidance code.

  • a) Fix only phase-merge. Record batch and guidance as one line in FOLLOW-UPS.md. This is the smallest change, but a sync phase merged in batch mode still breaks the feature branch.
  • b) Follow the IW-289 decision. Batch always merges with a merge commit, and the guidance uses --merge and no --squash for phase PRs. Batch history is no longer flat. This needs no new git check, fake, contract test or BATS case.
  • c) Keep the analysis plan. Batch squashes ordinary phases and uses a merge commit only when the phase branch holds a merge commit, found with git rev-list --merges. This goes against IW-289 and adds the most code.

Recommended: b) — it fixes the defect on every merge path and follows the recorded decision, with less code than c).

Answer in a comment on this issue, per number, for example "1: a", or in your own words; intake reads it on its next iteration.

Intake: needs-input Workflow: diagnostic Reason: G7 (1 [human] finding) Analysis: project-management/issues/IW-750/analysis.md on branch IW-750 ### 1. Should IW-750 also change `phase-pr --batch` and the agent merge guidance, and if so, how? (G7) The issue names only `phase-merge`. The analysis also fixes `phase-pr --batch`, which squashes every phase PR on all forges, and the agent guidance text, which tells agents to merge with `--squash`. An earlier issue already decided that phase PRs use a merge commit and are not squashed. It also named the batch squash as "inconsistent", but nobody fixed it. No recorded reason for the batch squash exists. > "Phase PRs use merge commit + delete branch (`--merge --delete-branch`). The final PR (feature → main) may use squash." ([IW-289 analysis](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/project-management/issues/IW-289/analysis.md#L335-L339)) Analysis sections: [batch fix](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/project-management/issues/IW-750/analysis.md#L195-L246), [guidance](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/project-management/issues/IW-750/analysis.md#L262-L264), [guidance code](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/core/model/ProjectContext.scala#L65-L93). - **a) Fix only `phase-merge`.** Record batch and guidance as one line in FOLLOW-UPS.md. This is the smallest change, but a sync phase merged in batch mode still breaks the feature branch. - **b) Follow the IW-289 decision.** Batch always merges with a merge commit, and the guidance uses `--merge` and no `--squash` for phase PRs. Batch history is no longer flat. This needs no new git check, fake, contract test or BATS case. - **c) Keep the analysis plan.** Batch squashes ordinary phases and uses a merge commit only when the phase branch holds a merge commit, found with `git rev-list --merges`. This goes against IW-289 and adds the most code. **Recommended: b)** — it fixes the defect on every merge path and follows the recorded decision, with less code than c). Answer in a comment on this issue, per number, for example "1: a", or in your own words; intake reads it on its next iteration.
Owner

1: b

1: b
Author
Member

Seen again on IW-707. Sync phase 2 merged origin/main (merge commit 4baea0bf, parents 14429848 and 132a5cf0) on IW-707-phase-02. phase-merge squashed PR #776 into 185bec7c with one parent, so final PR #768 still reported mergeable=false and showed 181 changed files against merge base d9e76182 (29 against origin/main). Recovered by a plain merge of origin/main into IW-707 (e2c8e85f); the merged tree is identical to its first parent.

Seen again on IW-707. Sync phase 2 merged origin/main (merge commit 4baea0bf, parents 14429848 and 132a5cf0) on IW-707-phase-02. phase-merge squashed PR #776 into 185bec7c with one parent, so final PR #768 still reported mergeable=false and showed 181 changed files against merge base d9e76182 (29 against origin/main). Recovered by a plain merge of origin/main into IW-707 (e2c8e85f); the merged tree is identical to its first parent.
Author
Member

Intake: needs-input
Workflow: diagnostic
Reason: G7 (1 [human] finding; answer 1 is applied)
Analysis: project-management/issues/IW-750/analysis.md on branch IW-750

1. Should iw-cli keep the squash-merge path that no command will use after this fix, or remove it? (G7)

After this fix, phase-pr --batch merges with a merge commit, which is the choice you made in answer 1 on the issue. Then nothing in iw-cli calls mergeSquashAndDelete. Its only caller now is PhasePr.scala:650. But it is published API: it is in CommandEnv.scala:323 and in docs/api/ForgeGateway.md. Project-local commands can call it. Your rules say that I must get your approval before I remove working code.

  • a) Keep it. The analysis stays as it is. The Forgejo request body gets a closed merge-style type with the values merge and squash. The squash path stays tested, and the reproduction still shows a squash on the second POST. Cost: a code path that iw-cli does not use, and that we must maintain.
  • b) Remove it. Remove mergeSquashAndDelete from ForgeGateway, CommandEnv and LiveCommandEnv. Also remove GitHubClient.buildMergePrSquashCommand, GitLabClient.buildMergeMrSquashCommand, the FakeCommandEnv fakes, their tests and the docs/api sections. The Forgejo body then always sends Do: "merge", so it needs no style type. Cost: a breaking API change. A project-local command that calls the method stops compiling, so the release notes must say so.

Recommended: b) — YAGNI: your recorded rule (IW-289) is that phase PRs use a merge commit, so a squash path that no command calls is code we test and document for nothing. Choose a) if you know of a project-local command that calls it.

Answer in a comment on this issue, per number, for example "1: a", or in your own words; intake reads it on its next iteration.

Intake: needs-input Workflow: diagnostic Reason: G7 (1 [human] finding; answer 1 is applied) Analysis: project-management/issues/IW-750/analysis.md on branch IW-750 ### 1. Should iw-cli keep the squash-merge path that no command will use after this fix, or remove it? (G7) After this fix, `phase-pr --batch` merges with a merge commit, which is the choice you made in answer 1 on the issue. Then nothing in iw-cli calls `mergeSquashAndDelete`. Its only caller now is [PhasePr.scala:650](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/core/commands/PhasePr.scala#L650-L650). But it is published API: it is in [CommandEnv.scala:323](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/core/commands/CommandEnv.scala#L323-L330) and in [docs/api/ForgeGateway.md](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/docs/api/ForgeGateway.md#L35-L61). Project-local commands can call it. Your rules say that I must get your approval before I remove working code. - **a) Keep it.** The analysis stays as it is. The Forgejo request body gets a closed merge-style type with the values `merge` and `squash`. The squash path stays tested, and the reproduction still shows a squash on the second POST. Cost: a code path that iw-cli does not use, and that we must maintain. - **b) Remove it.** Remove `mergeSquashAndDelete` from `ForgeGateway`, `CommandEnv` and `LiveCommandEnv`. Also remove [GitHubClient.buildMergePrSquashCommand](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/core/adapters/GitHubClient.scala#L871-L871), [GitLabClient.buildMergeMrSquashCommand](https://code.iterative.works/iterative-works/iw-cli/src/branch/IW-750/core/adapters/GitLabClient.scala#L764-L764), the `FakeCommandEnv` fakes, their tests and the `docs/api` sections. The Forgejo body then always sends `Do: "merge"`, so it needs no style type. Cost: a breaking API change. A project-local command that calls the method stops compiling, so the release notes must say so. **Recommended: b)** — YAGNI: your recorded rule (IW-289) is that phase PRs use a merge commit, so a squash path that no command calls is code we test and document for nothing. Choose a) if you know of a project-local command that calls it. Answer in a comment on this issue, per number, for example "1: a", or in your own words; intake reads it on its next iteration.
Owner
  1. b
1. b
Author
Member

Intake: agent-ready
Workflow: diagnostic
Reason: all gates passed
Analysis: project-management/issues/IW-750/analysis.md on branch IW-750

Intake: agent-ready Workflow: diagnostic Reason: all gates passed Analysis: project-management/issues/IW-750/analysis.md on branch IW-750
mph referenced this issue from a commit 2026-10-15 13:44:33 +00:00
Author
Member

Implement: needs-human
Reason: batch-implement exit 1 — the kanon plugin command did not compile against this branch's iw-cli core, so no phase ran

batch-implement.log was not written. The plugin's lib/batch/ForgeCatchUp.scala expects CommandEnv.tracker.fetchPullRequestForBranch to return Either[String, …]. Since #778 / #780, iw-cli main returns Either[TrackerError, …]. The branch is current with main. This is not specific to this issue: every iw-cli new item fails the same way until the kanon plugin follows the TrackerError change.

[error] /home/mph/.local/share/iw/plugins/kanon/lib/batch/ForgeCatchUp.scala:143:7
[error] Found:    Either[iw.core.model.TrackerError, Option[batch.ForgeState]]
[error] Required: Either[String, Option[batch.ForgeState]]
Compilation failed
Implement: needs-human Reason: batch-implement exit 1 — the kanon plugin command did not compile against this branch's iw-cli core, so no phase ran `batch-implement.log` was not written. The plugin's `lib/batch/ForgeCatchUp.scala` expects `CommandEnv.tracker.fetchPullRequestForBranch` to return `Either[String, …]`. Since #778 / #780, iw-cli `main` returns `Either[TrackerError, …]`. The branch is current with `main`. This is not specific to this issue: every iw-cli `new` item fails the same way until the kanon plugin follows the `TrackerError` change. ``` [error] /home/mph/.local/share/iw/plugins/kanon/lib/batch/ForgeCatchUp.scala:143:7 [error] Found: Either[iw.core.model.TrackerError, Option[batch.ForgeState]] [error] Required: Either[String, Option[batch.ForgeState]] Compilation failed ```
Author
Member

Release: the implement loop failed this issue for a reason outside it. The kanon plugin did not compile against iw-cli main, because the tracker port now returns TrackerError (iw-cli #778). The plugin fix is dev-docs #484, and iw-cli 0.22.1 carries the core change. The issue goes back to the implement loop.

Release: the implement loop failed this issue for a reason outside it. The kanon plugin did not compile against iw-cli main, because the tracker port now returns TrackerError (iw-cli #778). The plugin fix is dev-docs #484, and iw-cli 0.22.1 carries the core change. The issue goes back to the implement loop.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
iterative-works/iw-cli#750
No description provided.