Skip to content
Merged
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
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ the installation block without making remote writes. Keep its markers intact.
`src/scheduler.ts` owns interval jobs; `src/state.ts` owns persistence and locks.
- `src/executor.ts` owns analysis, base selection, worktrees, session execution,
verification, and pushing. `src/analysis.ts` and `src/branch.ts` validate model
decisions. `src/github.ts` implements GitHub calls; `src/approval.ts` evaluates
decisions. `src/pr-description.ts` extracts final public reports and renders and
reconciles managed PR descriptions. `src/github.ts` implements GitHub calls; `src/approval.ts` evaluates
approval candidates.
- `src/runtime.ts`, `src/worker.ts`, and `src/bridge.ts` implement worker hooks,
runtime installation, and communication with the owner. `src/prompt.ts` loads
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ include the full version, for example `## 0.7.0-beta.1`.

### Fixed

- Use the successful session's final completion report as the PR description instead
of its initial acknowledgement. Persist reports across restarts, retain the
original summary plus the latest follow-up, distinguish dispatcher checks from
agent-reported tests, and preserve manual notes outside the managed section.

- Reconcile timed-out or interrupted sessions completed manually after a blocked
task or service restart. Verify and publish through the dispatcher, then process
queued issue feedback on the same branch and PR, including legacy checkpoints.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ installations are not removed by `npm uninstall --global`.
`resume` commands from the target repository. Closing a PR closes its bot tabs
while retaining session history. Authorized issue comments can continue work
on an open PR without another mention, after the current round publishes.
- **PR descriptions:** the successful session's final summary appears in the PR,
with dispatcher checks listed separately. Follow-ups keep the original report
and replace **Latest update**. Keep manual notes outside the managed HTML markers.
See [PR descriptions](docs/runtime.md#pr-descriptions).
- **Recovery:** completing a stopped bot session manually is detected by the
dispatcher, which verifies and publishes before processing queued comments.
Use `/restartworkflow` in the owner project's TUI or
Expand Down
34 changes: 33 additions & 1 deletion docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ OpenCode service must be running for polling to work.
| `stateDirectory` | Shared location for queues, locks, and worktrees. Keep it consistent across components and restarts. |
| `repositories` | Repositories with existing local checkouts, default base branches, allowed authors, and checks. A natural-language request can override the base before work starts. |
| `allowedAuthors` | GitHub users authorized to request work and approve merging. Merging also requires repository write access. |
| `checks` | Arrays of executable arguments, e.g. `[["npm", "test"]]`. `[]` skips automated tests and reports that in the PR. No implicit shell. |
| `checks` | Arrays of executable arguments, e.g. `[["npm", "test"]]`. `[]` skips dispatcher test commands; the PR distinguishes this from agent-reported tests. No implicit shell. |
| `routes` | Maps full mentions to agents and models available in OpenCode. |
| `routes[tag].capabilities` | Main model capabilities: `text`, `vision`, `audio`; omitted means text only. |
| `routes[tag].mediaModel` | `{ model: { providerID, id }, capabilities: ["text", "vision"] }` for the media helper. |
Expand Down Expand Up @@ -232,3 +232,35 @@ See [runtime management](runtime.md#manage-tasks-from-bot) for the UI and limits
While a closure is pending, the dispatcher does not start another worker pass.
An unrelated already-running task can finish; scanning continues for other tasks.
The monitor reports task maintenance until closure completes.


## PR description recovery

Task state stores `completion` (final public text or an explicit unavailable
reason, session, round, then verified commit and checks), `initialCompletion`,
and `publishedBody` (the last acknowledged managed section). New rounds clear
only the current completion. Older verifying/publishing tasks recover missing
summaries from their saved sessions; this does not rerun the model. Missing or
empty successful reports are marked unavailable, while transient reads retry.
Already completed or closed tasks are not bulk rewritten on upgrade.

Publication reads the PR at the verified head and only replaces the managed HTML
marker region. Notes outside it are preserved. An exact known legacy body can be
replaced; unknown unmarked text is retained with the new section appended, since
it might contain manual edits. A later legacy round may not have enough saved
information to identify its old acknowledgement exactly.

An edited/removed managed section, changed PR head, closed follow-up PR, or oversized
body blocks at `publishing`. Preserve your notes outside the markers and restore
the previous managed section from `publishedBody` in the task checkpoint (or PR
edit history), then use the normal workflow retry. Do not delete the queue or
restart implementation just to retry a description update. If a PATCH succeeded
but its response was lost, matching desired content is accepted without another
write. Body and head are reread before PATCH; edits after that final read cannot
be atomically excluded by this implementation.

Each rendered report is limited to 22,000 UTF-8 bytes with an explicit truncation
notice; full saved text remains in task state and the session. Dispatcher check
text is limited to 8,000 bytes. The complete description, including retained
notes and signature, must fit within the automation limit of 60,000 bytes or
publication blocks without dropping notes. Titles are not regenerated on updates.
8 changes: 6 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ loads a generic scheduler, a GitHub dispatcher, and a terminal UI component.
3. Publish a signed acknowledgement, resolve the base branch, and pin that choice.
4. Create or reuse the task worktree and checkpoint the session identity before
prompting the executor. The executor must not publish directly.
5. Validate session success, verify changes, then push and create or reconcile the
PR. Generate its title only if creating a PR without an already-saved title.
5. Validate session success and save the final public completion report. Verify
changes, bind the report to the verified commit, then push and create or reconcile
the PR with that report and separate dispatcher checks. Generate its title only
if creating a PR without an already-saved title.
6. After publication, process queued authorized issue comments as new rounds on
the same worktree and branch, with a new main session and the existing open PR.
Keep the original PR report and update its Latest update section after pushing;
preserve manual notes outside the managed description.
7. Merge only after eligible approval of the published head, repository permission
checks, and GitHub merge readiness checks. Post a signed acknowledgement.

Expand Down
71 changes: 52 additions & 19 deletions docs/bot-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ flowchart TD
Stopped -->|Manual continuation succeeds and probe passes| R
Stopped -->|Explicit restartworkflow| Recover[Persist recovery intent, rejoin the same session]
Recover --> R
R -->|Validated success, no unresolved question| V[verifying: configured checks and commit]
R -->|Validated success, no unresolved question| Report[Persist final public assistant summary with session and round]
Report --> V[verifying: configured checks and commit]
V --> P[publishing: reconcile or create PR, push when required]
V -->|Failed check or Git consistency guard| VB[verifying / blocked]
VB -->|Operator retries saved stage| V
Expand Down Expand Up @@ -311,6 +312,7 @@ sequenceDiagram
else Wait completes
D->>S: Read context and final outcome
alt Valid task marker, admitted recovery marker if required, and successful final assistant
D->>D: Save final public assistant text with session and round
D->>D: Clear recovery state and advance to verifying
else Unsuccessful final outcome or assistant
D->>D: Save session-stop block for later reconciliation
Expand Down Expand Up @@ -415,7 +417,8 @@ Source: [runtime.ts — inspect_media](../src/runtime.ts).

```mermaid
flowchart TD
Start[Validated session success or retry of verifying phase] --> Identity[Require saved workspace and base, exact managed root, branch and shared repository]
Start[Validated session success or retry of verifying phase] --> Report[Reuse saved completion summary or recover from saved session]
Report --> Identity[Require saved workspace and base, exact managed root, branch and shared repository]
Identity --> Base[Require baseSha ancestor of HEAD and no unresolved conflicts]
Base --> Checks[Run configured checks sequentially, or none if list empty]
Checks -->|Configured check fails| Block[blocked at saved phase, retain work]
Expand All @@ -426,22 +429,28 @@ flowchart TD
Identity -->|Explicit consistency guard fails| Block
Base -->|Unresolved conflicts| Block
Validate -->|Explicit consistency guard fails| Block
Validate -->|Pass| Save[Persist checks and exact commit SHA, phase publishing]
Retry[Retry saved publishing phase] --> Find
Save --> Find[Find branch PR including closed PRs]
Validate -->|Pass| Save[Persist summary, checks and exact commit SHA, phase publishing]
Retry[Retry saved publishing phase] --> Body
Save --> Body[Recover missing legacy summary, save original report and render body]
Body --> Find[Find branch PR including closed PRs]
Find --> Follow{Follow-up round?}
Follow -->|Yes| Open{Existing PR open?}
Open -->|No| Block
Open -->|Yes| Push[Validate origin, workspace, saved HEAD and clean tree, push exact SHA]
Follow -->|No| Exists{PR already exists?}
Exists -->|Yes| Done[Record PR and publication time, pr_opened / done]
Exists -->|Yes| Closed{PR closed?}
Closed -->|Yes| Done[Record PR and publication time, pr_opened / done]
Closed -->|No| Description
Exists -->|No| Title[Generate title only if no saved prTitle]
Title --> Issue{Issue still open?}
Issue -->|No| Block
Issue -->|Yes| PushNew[Validate origin and workspace, push exact verified SHA]
PushNew --> Create[Create or reconcile signed PR against pinned base]
Create --> Done
Push --> Done
Create --> Description[Read open PR at verified SHA, reconcile managed description]
Push --> Description
Description -->|Edited managed block, changed head or oversized body| Block
Description -->|Unchanged or update succeeds| Acknowledge[Persist published body checkpoint]
Acknowledge --> Done
Failure[Other command, model or transport error] --> Policy[Keep current phase and apply retry policy in section 8]
Close[Operator closes task before publishing starts] --> Drain[Finish in-flight local operation, reject next checkpoint]
Drain --> Preserve[Do not publish, preserve existing local changes]
Expand All @@ -455,23 +464,45 @@ pushed branch does not by itself make a task complete.

The configured checks are command argument arrays. A failing configured check
produces `blocked`. With no configured checks, only Git consistency checks run;
the PR explicitly states that automated tests were not run. Commit hooks changing
the PR explicitly says the dispatcher did not independently rerun agent-reported
tests. Commit hooks changing
the recorded tree, a dirty worktree after commit, or no diff from the base block
publication. Other command failures use the general error policy below.

The PR body contains the analysis, `Closes #N`, checks, session ID, and verified
commit SHA. Push uses `COMMIT:refs/heads/TASK_BRANCH` without force. The first
publication reconciles an existing branch PR by recording it without another
push; follow-ups require an open PR and push the new verified commit. Follow-ups
do not regenerate the existing PR title or body.
The PR body uses the final public text of the successful assistant response,
with its Markdown preserved, rather than the pre-work analysis acknowledgement.
The executor saves it with the session and round before verification; verification
adds the checks and exact commit to the same snapshot. No extra model call rewrites
the report. Reasoning, tools, and failed or unfinished responses are excluded.
Missing legacy snapshots are read from the saved session; a missing session or
empty response produces an explicit summary-unavailable notice, never analysis
as a fallback. Transport errors retain the stage for retry.

The body keeps the original report and replaces one **Latest update** section on
follow-ups. Dispatcher checks appear separately from agent-reported tests, followed
by `Closes #N`, session, round and verified commit. Push uses
`COMMIT:refs/heads/TASK_BRANCH` without force. The first publication reconciles an
existing branch PR without another push; follow-ups require an open PR and push
the new verified commit before updating its description. The title is retained.
An already closed first-round PR is recorded without editing its description.

A stable HTML marker pair encloses the bot-managed description. Notes outside
it are preserved; an edited or removed managed section blocks publication rather
than overwriting it. The last acknowledged body is checkpointed, so a lost update
response can be reconciled without duplicate sections. Exact legacy descriptions
can be replaced; otherwise unmarked content is retained and the managed section
appended. GitHub is reread before writing to detect concurrent edits, although
there is no atomic compare-and-swap across that read and write. See
[publication recovery and limits](advanced.md#pr-description-recovery) for details.

Signed comments use stable `opencode2` markers; reconciliation looks for a marker
posted by the authenticated account. This covers analysis acknowledgements,
questions, and merge acknowledgements after a lost response.

Sources: [executor.ts — GitWorkspace.verify, push, title](../src/executor.ts),
[dispatcher.ts — publishing](../src/dispatcher.ts),
[github.ts — ensureComment, ensurePull](../src/github.ts).
[github.ts — ensureComment, ensurePull, updatePullBody](../src/github.ts),
[pr-description.ts — extraction, rendering and reconciliation](../src/pr-description.ts).

## 7. Feedback, merge approval, and tab closure

Expand All @@ -482,7 +513,8 @@ flowchart TD
Keep --> Recovery[Session recovery and publication must finish first]
Recovery --> Done
Done -->|Yes| Round[Next worker pass starts one new round on saved branch and worktree]
Round --> Guard[Require open issue, open original PR and authorized feedback, then analyze again]
Round --> Snapshot[Retain original report and published body, reset current completion]
Snapshot --> Guard[Require open issue, open original PR and authorized feedback, then analyze again]
Idle[Worker has no eligible execution task] --> Eligible{Auto-merge enabled and done task eligible?}
Eligible -->|No| Later[Wait for a later worker pass]
Eligible -->|Yes| Since{publishedAt exists?}
Expand Down Expand Up @@ -549,7 +581,8 @@ or a request failure records `mergeError`; error retries also respect GitHub tim
An already-merged response can reconcile a previously lost merge response.

Follow-up rounds reset analysis, question, current session, session-stop/recovery
state, checks, and commit; they retain the branch, worktree, pinned base, and previous session reference.
state, current completion summary, checks, and commit; they retain the original
report, last published body, branch, worktree, pinned base, and previous session reference.
Preparation reuses the saved worktree path rather than deriving a new path from
the branch name. A renamed branch can therefore retain its original directory.
Preparation, verification, and push all check the managed path, exact Git root,
Expand Down Expand Up @@ -595,7 +628,7 @@ An error normally preserves the phase so retry continues from its checkpoint.
| `ready` | Eligible for worker selection when due. |
| `waiting` | Awaiting an issue answer; no implementation or publication while unresolved. |
| `retry_wait` | Transient failure; automatic retry after `nextAt`. |
| `blocked` | Explicit `Blocked` error or GitHub HTTP 401, 404, or 422; requires inspection/retry, except a stopped session completed manually is reconciled automatically. |
| `blocked` | Explicit `Blocked` or PR-description conflict, or GitHub HTTP 401, 404, or 422; requires inspection/retry, except a stopped session completed manually is reconciled automatically. |
| `failed` | Other errors reached `maxAttempts`; operator recovery/retry required unless the checkpoint also qualifies as a stopped-session recovery candidate. |
| `done` | PR publication/reconciliation completed; feedback and merge monitoring remain possible. |
| `closing` | Operator requested end of tracking; interrupt sessions and drain in-flight work, retaining errors for retry. |
Expand All @@ -606,7 +639,7 @@ flowchart TD
Work[Execute saved phase] --> Result{Result?}
Result -->|WaitingForAnswer| Wait[waiting, or ready if answer already arrived]
Result -->|SessionStopped| Stop[running / blocked, sessionStopped true]
Result -->|Other Blocked or GitHub 401, 404, 422| Block[blocked at saved phase]
Result -->|Other Blocked, description conflict or GitHub 401, 404, 422| Block[blocked at saved phase]
Result -->|Other failure below attempt limit| Retry[retry_wait at saved phase]
Retry -->|nextAt elapsed| Work
Result -->|Other failure at limit| Fail[failed at saved phase]
Expand Down
22 changes: 22 additions & 0 deletions docs/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,28 @@ owner location and updated plugin are available there. Live worker/scan diagnost
reset when the owner is recreated; task checkpoints and scheduler history remain
durable as before.

## PR descriptions

The PR contains the agent's final completion summary from the successful session,
with Markdown preserved, followed by dispatcher verification, the issue reference,
session, round and verified commit. The initial issue acknowledgement is not a
completion report. Agent-reported tests remain in the summary; the dispatcher
lists only checks it actually ran. With no configured test command it explicitly
states that agent-reported tests were not independently rerun.

Follow-up rounds keep the original summary and replace a single **Latest update**
section after the new commit is pushed. The PR title stays unchanged. Reports are
saved before publication so a restart or lost GitHub response can reuse them.
If a legacy session is missing or has no successful final text, the description
states that its summary is unavailable.

Put manual PR notes outside the `opencode2:pr-body` HTML markers (visible when
editing the description). Edits inside that section or removal of the markers
block further description updates to protect your changes. Inspect the task error,
resolve the conflict and retry publication; see
[description recovery](advanced.md#pr-description-recovery). Installing an update
does not automatically rewrite already completed or closed PRs.

## Interrupted sessions and workflow recovery

If you manually continue a timed-out or interrupted bot session in the TUI,
Expand Down
6 changes: 6 additions & 0 deletions prompts/bot.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ repository inspection in the implementation session.

## Final report

The dispatcher copies the final public text of a successfully completed session
into the PR description with Markdown preserved. Write a review-ready report of
completed work, not an acknowledgement or a promise to begin. On follow-ups, report
what changed in this round; the original report remains in the PR and this report
becomes its Latest update. Do not include private reasoning or raw tool transcripts.

Finish an implementation session with a concise English summary covering:

- The behavior delivered.
Expand Down
Loading