Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions tests/unit/test_crane_workflow_prompt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pathlib import Path


WORKFLOW_PROMPT = Path(__file__).parents[2] / "workflows" / "crane.md"


def test_accepted_iteration_summary_contract_is_documented():
prompt = WORKFLOW_PROMPT.read_text()

assert "Accepted Iteration Summary" in prompt
assert "single shared source summary" in prompt

for surface in [
"PR body",
"PR comment",
"migration issue comment",
"repo-memory iteration history",
]:
assert surface in prompt

assert "add-comment" in prompt
assert "push-to-pull-request-branch" in prompt
24 changes: 20 additions & 4 deletions workflows/crane.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,22 @@ This Step 0 produces the plan and ships it as commit #1 on the migration branch
2. Parse the JSON output. The required field is `migration_score`. Optional fields (`progress`, `parity_passing`, `parity_total`, `source_tests_passing`, `target_tests_passing`, `perf_ratio`) are logged in iteration history.
3. Compare `migration_score` against `best_metric` from the state file.

### Accepted Iteration Summary

For every accepted iteration, construct a single shared source summary before updating any output surface. Reuse this same summary, with the same facts, in the PR body, an explicit PR comment, the migration issue comment, and the repo-memory iteration history.

Include these fields when available:
- Iteration number and accepted status.
- Current milestone or focus.
- Concise change summary, up to three compact bullets.
- Commit short SHA linked to the commit URL.
- Workflow run URL.
- Migration score, best score, and signed delta.
- Progress or parity counts such as `parity_passing` / `parity_total`.
- CI fix-attempt count when greater than zero.

Keep the summary compact (roughly ten bullets or 1000 characters max) and link to full evidence instead of pasting full diffs or long logs. For existing PR updates, use `push-to-pull-request-branch`, then also emit an `add-comment` safe output containing this summary. Do not rely on the generic push comment as the only reviewer-facing update.

### Step 5: Accept or Reject

Verification is necessary but **not sufficient** for acceptance. The agent's sandbox cannot reliably install many project toolchains, so a "score improved" signal from the sandbox can mask broken commits CI would catch. Acceptance must therefore be gated on **CI green** for the pushed HEAD commit. If CI fails, attempt to fix-and-retry within the same iteration rather than reverting.
Expand Down Expand Up @@ -507,17 +523,17 @@ If `status == "failure"`, **fix and retry — do not revert, do not accept**:
1. The commit(s) are already on the long-running branch. No further pushing needed.
2. If a draft PR does not already exist for this branch, create one — specify `branch: crane/{migration-name}` explicitly:
- Title: `[Crane: {migration-name}]`
- Body: summary of the migration (source → target, strategy), link to the migration issue, current best score and progress, AI disclosure: `🤖 *This PR is maintained by Crane. Each accepted iteration adds a commit to this branch.*`
If a draft PR already exists, use `push-to-pull-request-branch` (never `create-pull-request`). Update the PR body with the latest score and a summary of the most recent accepted iteration. Add a comment to the PR summarizing the iteration: what milestone was advanced, old score, new score, fix-attempt count if `> 0`, and a link to the actions run.
- Body: summary of the migration (source → target, strategy), link to the migration issue, current best score and progress, the shared Accepted Iteration Summary, AI disclosure: `🤖 *This PR is maintained by Crane. Each accepted iteration adds a commit to this branch.*`
If a draft PR already exists, use `push-to-pull-request-branch` (never `create-pull-request`). Update the PR body with the latest score and the shared Accepted Iteration Summary, then emit an explicit `add-comment` safe output to add the same contentful summary to the PR.
3. Ensure the migration issue exists (see [Migration Issue](#migration-issue) below) — for file-based migrations with no migration issue yet (`selected_issue` is null in `/tmp/gh-aw/crane.json`), create one and record its number in the state file's `Issue` field.
4. Update the state file `{migration-name}.md` in the repo-memory folder:
- **⚙️ Machine State** table: reset `consecutive_errors` to 0, set `best_metric` (the new `migration_score`), increment `iteration_count`, set `last_run` to current UTC, append `"accepted"` to `recent_statuses` (keep last 10), set `paused` to false.
- If this migration was listed in `stale_completed_state`, also set `Completed: false` and `Completed Reason: —` before checking the halting condition. Do not carry a stale completion marker forward unless the current accepted iteration completes again.
- **🪜 Milestones**: update the relevant milestone's status — typically `done` if the milestone was fully completed, otherwise leave `in-progress` and update its notes. If the milestone is done, the next milestone in the list becomes the new **🎯 Current Focus**.
- Prepend an entry to **📊 Iteration History** with status ✅, score, **signed delta**, PR link, fix-attempt count if `> 0`, and a one-line summary of what milestone was advanced and how.
- Prepend the shared Accepted Iteration Summary to **📊 Iteration History**.
- Update **📚 Lessons Learned** if this iteration revealed something new (e.g. a bridging trick, a parity surprise, a perf trap).
- Update **🔭 Future Work** if this iteration opened new threads.
5. **Update the migration issue**: edit the status comment and post a per-iteration comment.
5. **Update the migration issue**: edit the status comment and post a per-iteration comment using the shared Accepted Iteration Summary.
6. **Check halting condition** (see [Halting Condition](#halting-condition)): if `target-metric` is set, compare the new `best_metric` from this accepted iteration against it. For `higher` direction, the target is reached when `best_metric >= target-metric`. Reaching the target metric does **not** complete the migration in this run. It creates a completion candidate: set `Completion Candidate: true`, set `Completion Gate: pr-head-checks`, set `Completion Gate Status: pending`, keep `Completed: false`, keep `Completed Reason: —`, and leave the `crane-migration` label on the issue. Completion is finalized only by a later run after the pushed PR head's deterministic checks are observed green.

**If the score did not improve**:
Expand Down