Run-once
patchmill run-once advances one actionable issue through the configured
workflow. For a fresh agent-ready issue it initializes strict planning-pr-v1
state and snapshots the configured
planning review gates. That snapshot stays
immutable for the Issue run.
Preview selection without mutation:
Concurrent explicit commands
Section titled “Concurrent explicit commands”For independent issues, start separate commands from the same clone root:
Each process owns its selected issue, phase workspaces, state, artifacts, logs, and Pi sessions. Explicit selection reads only the requested issue. Other active or resumable issues do not prevent new explicit work.
If the requested issue already has an owner, Patchmill reports
issue already in progress. and returns exit code 0. The losing process
leaves the issue unchanged. This result does not require lease repair.
Without --issue, automatic selection remains serial. Automatic commands cannot
overlap explicit commands, other automatic commands, or mutating recovery
commands. Dry-run reserves no ownership.
Operator responsibilities
Section titled “Operator responsibilities”Select independent issues. Control model spending and the number of processes. Allocate CPU capacity, ports, test databases, and external services for each workspace. Patchmill does not predict conflicts between independent changes.
Use one supported Patchmill version and one clone root. The Git common directory binds the host repository, state directory, workspace root, and todo definition to one namespace. Symlinks do not create another namespace.
Before an upgrade or state migration, stop all affected processes. A changed namespace requires deliberate migration while no process owns it.
Unsupported cases include:
- Coordination across separate clones or hosts.
- Concurrent configuration changes or artifact-edit commands such as
set-plan. - Manual shared Git mutations during active Run attempts.
- Cleanup hooks that remove shared services or another issue’s resources.
- Multiple writers for the same issue.
CAUTION: Do not remove another Run attempt’s locks or use destructive cleanup as recovery. These actions can destroy owned work or permit conflicting writers.
Todos and evidence
Section titled “Todos and evidence”The default todo root remains .pi/todos inside the owned workspace. Relative
custom roots use that workspace, not the shared clone root. Absolute shared
roots use issue-scoped reads and mutations. Startup and cleanup preserve other
issues’ tasks and disable global todo garbage collection in shared roots.
Resume preserves existing todo locations, titles, tags, and completion rules. Ambiguous locations block instead of combining or moving tasks. Each new Run attempt receives separate logs and sessions, even with identical timestamps.
Comment-backed issue state
Section titled “Comment-backed issue state”When issueState.provider is comments, Run-once reads the latest trusted
Patchmill state comment instead of repository labels for workflow state such as
agent-ready, in-progress, spec-review, plan-review, and agent-done.
State changes append new comments and do not edit or delete older state
comments.
Priority labels still affect automatic issue ordering when they exist. If you cannot use priority labels, Run-once falls back to issue-number ordering among eligible issues.
Fresh planning workflow
Section titled “Fresh planning workflow”The saved gate snapshot assigns spec and plan artifacts to a phase workspace: the owned worktree and branch for one spec, plan, or implementation phase, pinned to saved remote-base evidence.
-
Patchmill fetches the target base and resolves assigned artifacts. Exactly one matching regular file under the configured directory satisfies assigned work; none creates work and multiple candidates block.
-
An agent edits, self-reviews, and commits only the requested artifact in its phase workspace.
-
If that phase has a required planning review gate, Patchmill pushes it in a non-closing planning pull request and returns
review-pendingwith exit code0. -
A human reviews and merges that exact pull request. Run ordinary recovery:
Patchmill verifies the exact saved pull request and its merge on the saved target base before advancing. Comments and labels do not unlock a fresh phase.
-
Implementation always produces an open, issue-closing pull request. Patchmill verifies its ownership marker, closing reference, repository, branches, and head OID. Publication returns
pr-createdand leaves the Issue run in progress. -
After the PR merges, rerun the same explicit command. Patchmill verifies its merge against the fetched target base and resumes finish checkpoints without another agent or PR. Only verified merge and completed finish checkpoints produce
mergedand the done label.
Gate matrix
Section titled “Gate matrix”| Spec review | Plan review | Pull request sequence |
|---|---|---|
| Off | Off | Implementation contains spec, plan, and code. |
| On | Off | Spec planning pull request, then implementation with plan and code. |
| Off | On | Plan planning pull request contains spec and plan, then implementation. |
| On | On | Spec planning pull request, plan planning pull request, then implementation. |
GitHub planning heads remain in the target repository. Forgejo may use the supported same-host head repository. Both providers use the same markers, gate rules, merge verification, and recovery behavior.
Results and output
Section titled “Results and output”Progress is written to stderr. Redirect stdout for the compact one-line JSON result:
review-pending and stopped with reason plan-only are exit-zero nonfailure
results. Patchmill no longer returns the public cleanup-pending result, even
for saved records from older releases.
After a legacy workspace refresh, the result includes quarantinePaths. This
array names the retained old checkouts. Recovery progress, final JSONL data, and
the terminal’s Quarantine paths section name the same paths. A later blocked
result also retains this field.
An open planning review takes precedence over a plan-only stop. A later invocation without the option resumes the saved phase and gate snapshot.
Failure diagnostics
Section titled “Failure diagnostics”Every reason-bearing blocked, stopped, environment, and error result keeps its
stable reason code and adds a diagnostic object. The object has a short
summary, plain-language explanation, attributed details, safe actions,
safety warnings, and retry guidance. Redirected stdout and the final JSONL
result event contain the same object; terminal output renders the same fields
as Reason, Explanation, Details, Recommended action, Safety, and Retry.
retry.kind states when another invocation can help: retry-now means the
recommended normal command can make progress now; after-action means first
complete the listed safe action; same-result means the same command will stop
again until the recorded state changes; and inspect-first means inspect and
reconcile preserved evidence before deciding whether to retry. For example,
redirected output for a dirty phase workspace includes its stable code and the
same structured diagnostic written to JSONL:
Selection rejection JSONL events also include a diagnostic beside their reason.
A final no-issue result intentionally has no aggregate reason because its
per-Issue rejection events are the source of that information.
Commands in diagnostics are limited to supported commands with a positive Issue
number: patchmill run-once --issue N, and, only for Issue run lease/fence
recovery, patchmill run lease repair --issue N. A planning-pr-v1 planning
lock is not an Issue run lease: lock diagnostics never recommend lease repair.
Recovery and operator safety
Section titled “Recovery and operator safety”For intentional resume, run patchmill run-once --issue N again. A process
exit, cancellation, crash, or open PR does not complete the Issue run. A merged
PR can close the host issue before local finish checkpoints complete. Explicit
recovery still verifies that saved PR and finishes only its owned issue.
A busy shared Git transaction returns stopped with reason repository-busy.
Retry the same explicit command after the other transaction ends. Patchmill
preserves the selected checkpoint and lifecycle labels. Independent agent work
does not hold the Git guard.
A timed-out or interrupted Git command can leave partial mutations. Preserve its state and command evidence. A dead owner PID alone cannot authorize recovery of an unverified active Git command.
A retry observes durable state, the remote, and the host before repeating an effect. It can adopt an exact pushed head or created pull request, complete a checkpointed cleanup, return the same open review, or verify a merge.
Patchmill uses ordinary Git status for verification, recovery, and cleanup.
Ignored content never blocks these operations or requires an operator label or
retry. This rule applies to every ignored path, including collapsed directories
such as .pi/ and tool output such as node_modules/.
Staged changes, tracked changes, and non-ignored untracked files remain blockers. A force-added ignored file counts as staged or committed content. Existing status and artifact-diff guards still apply. Read-only artifact verification preserves HEAD, the index, artifact files, and ignored files.
Phase removal still requires valid ownership, path identity, registration, HEAD, and publication evidence.
CAUTION: Do not store unique data in ignored files inside disposable phase
workspaces. Cleanup permanently deletes all ignored content, including .env,
.pi/, unknown files, and operator-created files.
In-place recovery preserves ignored files. Legacy refresh and reset move the old
checkout, with its ignored files, to a retained quarantine path. Patchmill never
removes quarantine paths. The replacement checkout starts without those old
ignored files. Reset reports the retained paths through its existing
quarantinePaths result.
This preservation rule does not apply to final phase cleanup. Patchmill never force-cleans a phase workspace or force-updates a conflicting branch. It does not replace a missing, ambiguous, or closed-unmerged planning pull request.
A retry can recover one committed artifact that the agent completed before its checkpoint failed. Patchmill proves ownership, ordinary cleanliness, ancestry, and a single artifact-only delta from the saved HEAD. It selects the committed artifact by issue number and configured directory, not by the retry date. The checkpoint retains the original artifact path, commit, todo root, and todos. No second artifact agent runs for that artifact. Ambiguous candidates, unrelated commits, changed HEAD, or checkpoint errors stop before later agents or publication. Normal planning review and implementation PR gates still apply.
Saved legacy cleanup-pending records resume normal cleanup without a ready
label. Patchmill does not publish new needs-info state for these records.
Existing needs-info state still blocks selection until the configured ready
state acknowledges it.
| Situation | Operator action |
|---|---|
| Open review | Review or merge the same pull request, then rerun Run-once. |
| Legacy cleanup pending | Rerun the same issue. No cleanup-specific ready label is necessary. Existing needs-info state still requires the normal ready acknowledgement. |
| Closed-unmerged, proven missing, or ambiguous review | Repair the host state manually; Patchmill does not replace the pull request. |
| Dirty or uncheckpointed phase workspace | Inspect and preserve local work before retrying. |
| Transient host failure | Repair authentication or connectivity, then retry. |
| Active lock | Wait for its owner; never remove it. |
| Stale same-host lock | Run-once automatically archives exact stale bytes under planning-pr-v1/archive/issue-locks/ and continues after a same-host dead-PID proof. The console warning identifies the archive path; JSONL warning data includes the fingerprint and archive path. Archives are retained. |
| Unverifiable, malformed, or transition-conflict lock | Coordinate with the recorded host/operator and inspect the preserved evidence before retrying; age alone proves nothing. Remote hosts, PID reuse that appears live, and infrastructure failures remain fail-closed. |
patchmill run lease repair and patchmill run reset do not authorize deleting
a planning-pr-v1 lock, state file, branch, or workspace. They retain their
legacy recovery behavior only. Mutating reset and lease repair also use
repository admission. Reset refuses planning state and published PR checkpoints.
Use ordinary explicit resume for those checkpoints.
Read-only patchmill run lease repair --issue N reserves no ownership. For a
known interrupted local repair, inspection prints exact primary and paired guard
fingerprints. The confirmed repair command verifies shutdown and archives only
those linked guards. It preserves the target lease and earlier interrupted
evidence. Inspect again before any separate lease repair.
Unknown, foreign, malformed, unlinked, or unverified repair guards remain blocked. Interrupted reconciliation guards also remain blocked. Preserve this evidence for operator inspection. No lock-bypass flag exists.
Legacy compatibility
Section titled “Legacy compatibility”set-spec, set-plan, approval labels, uploads, and --plan-only remain
available for unfinished legacy Issue runs during the compatibility window. They
are deprecated for fresh work. Use Run-once review gates for automated review
stops, or the human-invoked patchmill-plan skill for local planning without
automated implementation.
Legacy implementation also requires a PR. git.allowDirectLand: true is no
longer supported. An old direct-land checkpoint without verifiable PR evidence
blocks with migration guidance. Preserve that checkpoint instead of creating
replacement work.