# release-handoff process

## Index

- [1. Purpose](#1-purpose)
- [2. okstra-run wizard flow](#2-okstra-run-wizard-flow)
- [3. prepare stage](#3-prepare-stage)
- [4. entry gate](#4-entry-gate)
- [5. lead-only execution flow](#5-lead-only-execution-flow)
- [6. PR template resolution](#6-pr-template-resolution)
- [7. Deliverables](#7-deliverables)
- [8. Forbidden actions](#8-forbidden-actions)
- [9. Verified code](#9-verified-code)

## 1. Purpose

`release-handoff` is the terminal phase that pushes an already-committed implementation result with an `accepted` verdict, or hands it off as a PR. whole-task mode packages the verified task branch as-is. stage-group mode can assemble the selected stages into a collector branch and bundle them into a single PR, and the merge commit created here is produced only by `okstra handoff assemble`.

This phase has no worker dispatch. It does not use a provider or report-writer roster; the host-native Okstra lead performs git/gh inspection, user questions, the PR draft, and the final report inline.

## 2. okstra-run wizard flow

```mermaid
flowchart TD
    Start[/okstra-run/] --> Common[common task identity flow]
    Common --> Type[task-type = release-handoff]
    Type --> Plan[approved plan auto/pick]
    Plan --> Scope[handoff stage pick<br/>whole-task or eligible stages]
    Scope --> Worktree{active task worktree?}
    Worktree -->|yes| RoleCount[role-count min..max<br/>omit uses recommended; skip if min==max]
    Worktree -->|no| BaseRef[base-ref pick/text]
    BaseRef --> RoleCount
    RoleCount --> RoleModel[role-model provider/model per slot]
    RoleModel --> RoleAdd[min=0 roles via role-add only<br/>default skip]
    RoleAdd --> Extras[directive, related tasks, clarification]
    Extras --> Template[PR template override?]
    Template --> TemplateScope[save template to project/global?]
    TemplateScope --> Confirm[confirmation]
    Confirm --> Render[render-bundle]
```

`release-handoff` has no analysis-worker dispatch. Launch selection still shows any applicable role-count / role-model steps; current-session lead is this session and is listed on the confirmation summary. There is no provider roster multi-pick and no `Use defaults / Customize` fork. Dynamic verifiers are not chosen at launch. `--workers` is not a launch picker, and the runtime forces the worker list to empty. The wizard outcome's `renderArgs` includes `pr-template-path` only for release-handoff. Scope selection finishes before prepare, and the project/global save runs before `render-bundle` via the `config.set pr-template-path` action of `outcome.persistActions[]`. whole-task requires an accepted whole-task verification report, and for stage-group only the stages that were marked `verified` by an accepted single-stage verification in the Stage Lifecycle Snapshot but not yet covered by a `pr` become candidates.

Note that this phase is also a target of task worktree provisioning. The normal flow reuses the implementation/final-verification result of the same task-key. Starting a new task may create a new branch, and it is likely to be blocked at the entry gate's "implementation commit exists" condition.

## 3. prepare stage

```mermaid
sequenceDiagram
    participant W as okstra-run
    participant P as prepare_task_bundle
    participant T as PR template resolver
    participant WT as worktree registry
    participant FS as task artifacts

    W->>P: task-type=release-handoff, approved-plan, stages csv, optional pr-template-path
    P->>P: enforce stage eligibility (Stage Lifecycle Snapshot)
    P->>FS: generate release-handoff-input.md (cited verification reports)
    P->>P: force workers=[]
    P->>T: resolve PR template
    P->>WT: reuse or provision task worktree
    P->>FS: write manifests with empty roster
    P->>FS: expose PR_TEMPLATE_PATH and PR_TEMPLATE_SOURCE
    P-->>W: lead prompt for current session
```

The profile has no `Required workers:` block, and `run.py` also empties the worker override for `release-handoff`. So not going through the general TeamCreate / convergence / report-writer flow of `prompts/lead/okstra-lead-contract.md` is the intended behavior.

## 4. entry gate

```mermaid
flowchart TD
    Brief[release-handoff-input.md<br/>generated by prepare] --> Source{Source Verification Report present?}
    Source -->|no| Block[blocked<br/>route final-verification]
    Source -->|yes| Verdict{Verdict Token == accepted?}
    Verdict -->|no| Block
    Verdict -->|yes| Mode{HANDOFF_MODE}
    Mode -->|stage-group| Eligible[each selected stage<br/>verified and not in PR]
    Mode -->|whole-task| Status{git status --short clean?}
    Eligible --> Status
    Status -->|no| Dirty[blocked<br/>dirty tree]
    Status -->|yes| Branch{current branch is base branch?}
    Branch -->|yes| BaseBlock[blocked<br/>never operate on base branch]
    Branch -->|no| Commits{git log base..HEAD non-empty?}
    Commits -->|no| ImplBlock[blocked<br/>route implementation]
    Commits -->|yes| Ready[handoff questions may begin]
```

Before asking the user whether to push/PR, the lead confirms the following.

- The `## Source Verification Report` of the input document (`release-handoff-input.md`) generated by prepare contains the mode (`HANDOFF_MODE`) and the cited report table. The brief is the input of the entry phase, so it does not exist in release-handoff — the user's stage selection finishes before prepare via the wizard `handoff_stage_pick` or the CLI `--stages`.
- In whole-task mode, the cited report must be `verificationScope=whole-task` and `Verdict Token = accepted`.
- In stage-group mode, each cited single-stage report must be `Verdict Token = accepted`, and prepare / `okstra handoff assemble` re-enforce the Stage Lifecycle Snapshot-based eligibility and dependency closure.
- The working tree is clean.
- The current branch is not a base branch such as `main`, `master`, `prod`, `preprod`, `staging`, or `dev`.
- The `<base>..HEAD` commit range is non-empty.

`conditional-accept`, `blocked`, and vague-sentence verdicts are all immediate-termination targets.

## 5. lead-only execution flow

```mermaid
stateDiagram-v2
    [*] --> Gate: entry gate
    Gate --> Q1: action selection
    Q1 --> LocalCheckout: local checkout
    Q1 --> Skip: skip
    Q1 --> Q2: push + PR whole-task
    Q1 --> G2: push + PR stage-group
    state "base select + stage confirmation / okstra handoff assemble" as Assemble
    G2 --> Assemble
    Assemble --> Q3: collector branch ready
    Q2 --> Probe: choose PR base
    Probe --> Q3: no conflict
    Probe --> Conflict: conflict detected
    Conflict --> Q2: change base branch
    Conflict --> Q3: proceed anyway
    Conflict --> Cancel: cancel
    Q3 --> Push: use as-is or edit then proceed
    Q3 --> Cancel: cancel
    Push --> ReuseOrCreate: git push feature branch
    ReuseOrCreate --> FinalReport: gh pr list / gh pr create
    LocalCheckout --> FinalReport
    Skip --> FinalReport
    Cancel --> FinalReport
    FinalReport --> [*]
```

User interaction is exactly three steps.

1. Q1 action: `local checkout`, `push + PR`, `skip`
2. Q2 PR base: a branch from the profile menu such as `staging`, `preprod`, `main`, or Enter directly
3. Q3 PR title/body: `use as-is`, `edit then proceed`, `cancel`

The merge-conflict probe happens only for `push + PR`.

In stage-group mode, `local checkout` is not offered. After choosing `push + PR`, first select the PR base, confirm the already-fixed `HANDOFF_STAGES`, and then `okstra handoff assemble` creates the collector branch. After that, the conflict probe and PR title/body confirmation take the collector branch as head.

```mermaid
flowchart TD
    PushPR[push + PR selected] --> Fetch[git fetch origin chosen-base]
    Fetch --> MergeTree[git merge-tree --write-tree --merge-base<br/>origin/base HEAD origin/base]
    MergeTree --> Conflict{conflict?}
    Conflict -->|no| Draft[show PR draft]
    Conflict -->|yes| Ask[ask proceed/change base/cancel]
    Ask -->|proceed anyway| Draft
    Ask -->|change base branch| Base[return to Q2]
    Ask -->|cancel| Report[final report without push/PR]
```

The probe must not change the working tree. `git merge`, `git rebase`, and `git pull` are not part of this probe.

## 6. PR template resolution

```mermaid
flowchart TD
    Override[--pr-template-path from wizard] --> Chosen{exists?}
    Chosen -->|yes| UseOverride[use override]
    Chosen -->|no| Project[project config template]
    Project -->|exists| UseProject[use project template]
    Project -->|missing| Global[global config template]
    Global -->|exists| UseGlobal[use global template]
    Global -->|missing| Default[okstra skill default template]
```

When the user picks a template on the customize path, the okstra-run skill performs the project/global scope save before render-bundle. The runtime puts the resolved `PR_TEMPLATE_PATH` and `PR_TEMPLATE_SOURCE` into the run context, and the lead reads this file as-is, removes the HTML comments, and fills the placeholders. The section structure must not be hard-coded.

## 7. Deliverables

```mermaid
flowchart TD
    Verdict[Source Verification Report<br/>accepted token] --> Report[release-handoff final report]
    State[feature branch + clean status] --> Report
    User[Q1/Q2/Q2b/Q3 user selections] --> Report
    Commands[git/gh commands + exit codes] --> Report
    Commits[git log base..HEAD commit list] --> Report
    Probe[Merge Conflict Probe] --> Report
    PR[PR created / reused / skipped] --> Report
    Report --> Done[routing recommendation: done]
```

The final report requires at least the following.

- originating final-verification report path and quoted `accepted` verdict row
- handoff mode (`whole-task` or `stage-group`) and selected stages
- feature branch and run start `git status --short`
- record of user selections
- all executed git/gh commands and exit codes
- implementation commit list
- merge-conflict probe result
- for stage-group, the collector branch, merge commit SHA, and dependency-closure result
- PR created, reused, or skipped result
- routing recommendation `done`

## 8. Forbidden actions

```mermaid
flowchart TD
    RH[release-handoff] --> Allowed[read git/gh, fetch base, merge-tree probe,<br/>push feature branch, create/reuse PR]
    RH -. forbidden .-> Commit[git add / commit / stash]
    RH -. forbidden .-> Force[force push or +refspec]
    RH -. forbidden .-> BasePush[push directly to base branch]
    RH -. forbidden .-> NoVerify[--no-verify / -n]
    RH -. forbidden .-> Publish[release publish / deploy]
    RH -. forbidden .-> Edit[source edit]
    RH -. forbidden .-> Team[TeamCreate or Agent dispatch]
    RH -. forbidden .-> Merge[gh pr merge]
```

A failed `git push` must not be retried with weaker safeguards. When a failure such as non-fast-forward occurs, stop and take the user's instruction, and `--force`-family flags are forbidden even if the user requests them.

## 9. Verified code

- [`prompts/profiles/release-handoff.md`](../../prompts/profiles/release-handoff.md)
- [`templates/reports/release-handoff-input.template.md`](../../templates/reports/release-handoff-input.template.md)
- [`skills/okstra-run/SKILL.md`](../../skills/okstra-run/SKILL.md)
- [`scripts/okstra_ctl/wizard.py`](../../scripts/okstra_ctl/wizard.py)
- [`scripts/okstra_ctl/run.py`](../../scripts/okstra_ctl/run.py)
- [`scripts/okstra_ctl/pr_template.py`](../../scripts/okstra_ctl/pr_template.py)
- [`src/commands/lifecycle/config.mjs`](../../src/commands/lifecycle/config.mjs)
- [`scripts/okstra_ctl/worktree.py`](../../scripts/okstra_ctl/worktree.py)
