feat(phased-execution): push each phase commit after it is made

The harness now pushes the phase commit right after committing it
(PHASE_PUSH=1 default, new push_phase in lib.sh): upstream when set,
else 'git push -u <first remote> <branch>'; no remote = skip with a
notice. A push failure keeps the commit local, prints the same loud
ERROR contract as a commit failure, and stops the run — the next
phase's push sweeps the unpushed commit in. PHASE_PUSH=0 opts out with
a loud notice. SKILL.md (Commits + config table + exit codes) and the
executor prompts document the new behavior.
This commit is contained in:
2026-09-10 07:56:30 -04:00
parent f6cbb2d664
commit b88fbaec62
8 changed files with 80 additions and 22 deletions
+15 -4
View File
@@ -20,8 +20,9 @@ process** (fresh context) with bounded fixer retries. A task only moves to
final report, **and** `.agents/validate.sh` passes. When all of a phase's tasks
are done, `00_phase.md` runs as the phase's **final pass** (remaining inline
work + completion criteria + phase-level verification); moving it completes
the phase and is the `PHASE_COMMIT` commit point (one atomic commit: code +
phase files + reports — children never commit; see Commits below). This chat only dispatches
the phase and is the `PHASE_COMMIT` commit point (one atomic commit — code +
phase files + reports — pushed right after when the repo has a remote;
children never commit; see Commits below). This chat only dispatches
and relays results — do not implement task code yourself; that is what the
subprocesses are for.
@@ -65,8 +66,9 @@ Re-running `auto-phase.sh` after a failure continues where it stopped.
## After a run
Exit codes: `0` = success (or nothing to run), `1` = task/phase failed after all
attempts, `130`/`143` = interrupted (Ctrl+C / SIGTERM).
Exit codes: `0` = success (or nothing to run), `1` = task failed after all
attempts, or the phase commit/push failed, `130`/`143` = interrupted
(Ctrl+C / SIGTERM).
Failures always print a `✗ ERROR:` line with the last error output — if the
script's output looks like it ended abruptly, re-run it; the failed executor's
session is resumed automatically (retries continue the child's own session,
@@ -105,6 +107,14 @@ warning, never silently.
- Subject: `PHASE_COMMIT_SUBJECT` (default `phase: {{PHASE}}`); the
executor's final report becomes the commit body. `--no-gpg-sign` is always
passed.
- **Pushed**: with `PHASE_PUSH=1` (default) the commit is pushed right after
it is made — to the branch's upstream when one is set, otherwise
`git push -u <first remote> <branch>`. A repo with no remote skips the
push with a notice (the commit stays local). A push failure gets the same
`✗ ERROR:` contract as a commit failure: the commit is local and safe, the
run stops, and the next phase's push sweeps the unpushed commit in once
the push works. `PHASE_PUSH=0` opts out — each phase commit is left local
with a loud notice.
## Configuration (environment variables)
@@ -115,6 +125,7 @@ warning, never silently.
| `PHASE_THINKING` | session default | `--thinking` level for child executors |
| `PHASE_COMMIT` | `1` | `1` (default) = the harness commits each completed **phase** as one atomic commit (code changes + the file move + executor reports) when its `00_phase.md` final pass passes (legacy: when its file moves). `0` = opt out: the phase is left uncommitted with a loud warning. See Commits above |
| `PHASE_COMMIT_SUBJECT` | `phase: {{PHASE}}` | Commit subject template for `PHASE_COMMIT=1` (`{{PHASE}}` = the phase directory name); the executor's final report becomes the commit body |
| `PHASE_PUSH` | `1` | `1` (default) = push each phase commit right after it is made (upstream when set, else `git push -u <first remote> <branch>`); no remote = skip with a notice; a failure stops the run (the commit stays local — the next phase's push sweeps it in). `0` = leave commits local with a loud notice. See Commits above |
| `PI_TRUST` | `0` | `1` = pass `--approve` (load project `.pi/` settings/skills into children) |
| `FRESH_FIX` | `0` | `1` = fixer retries start fresh instead of resuming the failed session |
| `QUIET` | `0` | `1` = suppress live progress display (reports are still written) |