| name | graft-task-closeout |
| description | Repository-specific end-of-task closeout workflow for Graft. Use when a task slice is ending and the agent needs to decide whether to emit only a next-step startup prompt or to commit the current validated slice first and then hand off safely. This is the default slice-end path for work started through `graft-boot`. |
Graft Task Closeout
Use this skill when the current Graft slice is ending and the agent needs a concise, repeatable closeout workflow.
When a slice started through graft-boot, treat this skill as the normal required wrap-up path rather than an
optional extra.
Treat root AGENTS.md as the closeout-governance source of truth. This skill coordinates existing repository skills; it
does not replace startup, validation, or commit rules.
When To Use
Typical triggers:
close this slice
wrap up and hand off
generate the next-step startup prompt
commit current validated slice if needed and hand off
Prefer this skill over graft-commit when the main question is task closeout rather than commit creation alone.
Preconditions
- Ensure the current turn already has the startup receipt required by
AGENTS.md 4.1 Startup Governance.
- Confirm the task is actually at a closeout point:
- the current slice is complete enough to hand off, or
- the current slice is blocked and needs an honest next-step prompt
- If validation status is unclear, use
graft-validation-runner before deciding whether a commit is allowed.
- For a numbered managed worktree, do not report a completed closeout while owned changes remain uncommitted. After a
clean validated commit, invoke
graft-worktree-manager ... closeout so later release can verify the lifecycle.
Workflow
- Read the closeout rules in
AGENTS.md:
4.1 Startup Governance for required handoff prompt fields
13. Git Workflow Rules for pre-handoff commit requirements
- Classify the closeout state:
validated and owned: the current slice reached the required validation level and ownership is clear
handoff_only: the slice needs a next-step prompt but is not ready for a safe commit
blocked: ownership, validation, or scope is too ambiguous to claim closure
- Decide whether a commit is required:
- if the task ends with a real next-task handoff and the current slice reached the required validation level, prefer
committing the confirmed owned scope before handoff
- if validation is still insufficient, do not force a commit; record the exact gap
- if ownership is mixed or ambiguous, do not force a commit; keep the scope uncommitted
- Always evaluate commit eligibility using
graft-commit rules, even when the answer may be “do not commit yet”.
- If a commit is justified or explicitly requested, delegate commit execution to
graft-commit:
- keep the scope limited to the confirmed owned slice
- reuse the same ownership and validation rules instead of inventing a second commit path
- When the current checkout is an acquired numbered worktree and the closeout is validated and owned, run the manager
closeout command after the scoped commit. If ownership or validation blocks committing, report blocked or
handoff_only; do not represent the dirty worktree as a completed slice.
- Emit one explicit next-task startup prompt whenever the output hands work to a future turn. The prompt must include:
governance source
task class
recovery source
owned scope
- if recovery context matters, the parent topic and subtopic to read after startup preflight
- Report the closeout result concisely:
- whether a commit was created, and if so the scoped title and short SHA
- whether the output is a handoff prompt only
- what validation was used or what exact validation gap remains
- the
Experience capture result, following the routing and threshold rules from graft-lessons-learned when the
task produced a reusable lesson
- When the caller asks for machine-readable closeout, end the result with one fenced
```json block that matches the
closeout state and the current delegated-round budget.
Output Contract
The closeout result should stay concise and should contain:
closeout status: completed_no_handoff, committed_and_handed_off, handoff_only, recovery_handoff,
blocked, cancelled, or unsafe; exhausted_retry is not a closeout status and is recorded only as batch-wave
evidence/recovery input for the outer controller
validation: exact command run or the exact limitation
next-step startup prompt: only when a future turn is expected
experience capture: none, added, updated, promoted, or deprecated, with the lesson/doc targets when applicable
- when machine-readable closeout is requested, one fenced JSON block with:
closeout_status
continue
loop_mode
current_batch
completed_batches
pending_batches
next_batch
next_batch_prompt
next_prompt
stop_reason
validation
commit
consumed_budget
remaining_budget
scope_expanded
risk_level
recovery
Use plain language, but keep the startup prompt explicit enough that the next turn can rerun startup preflight without
guessing the inherited context.
JSON Closeout Contract
When a caller such as graft-multi-agent-loop requests machine-readable closeout, use these rules:
- keep the human-readable closeout first
- if a future turn is required, include exactly one line beginning with
Next-session startup prompt:
- append exactly one fenced
```json block as the last structured artifact
- for ordinary closeout outside
graft-multi-agent-loop, continue=true requires a non-empty next_prompt
- for
graft-multi-agent-loop in the default topic-completion-loop mode:
continue=true requires loop_mode=topic-completion-loop
continue=true requires updated completed_batches and pending_batches
continue=true requires next_batch and next_batch_prompt when batches remain
pending_batches=[] requires a final archive-readiness check before the loop may stop
continue=true requires next_prompt=null
- a terminal handoff is limited to
blocked, cancelled, unsafe, archive-ready, or explicit stop; it must
include a terminal reason resolved by the outer controller
- a
recovery_handoff is non-terminal and may emit Next-session startup prompt: only when recovery.status is
required, current_batch and pending_batches are preserved, recovery.resume_target is
RESUME_CURRENT_BATCH, and the failed batch is unsettled
- after startup preflight restores the receipt and recovery becomes eligible, the outer controller must transition
RECOVERY_COMPLETE -> RESUME_CURRENT_BATCH -> DISPATCH; it must not wait for a user re-dispatch
continue=false requires next_prompt=null unless the closeout is a terminal or recoverable handoff to a future
turn
validation.status should be one of passed, failed, or not_run
risk_level should be one of low, medium, or high
consumed_budget must describe only the current slice or delegated round
remaining_budget must reflect the budget left after the current slice or delegated round
Recommended JSON shape:
{
"closeout_status": "completed_no_handoff | committed_and_handed_off | handoff_only | recovery_handoff | blocked | cancelled | unsafe",
"continue": true,
"loop_mode": "topic-completion-loop | checkpoint-loop | null",
"current_batch": "string or null",
"completed_batches": ["..."],
"pending_batches": ["..."],
"next_batch": "string or null",
"next_batch_prompt": "string or null",
"next_prompt": "string or null",
"stop_reason": "string or null",
"validation": {
"status": "passed | failed | not_run",
"commands": ["..."],
"note": "string or null"
},
"commit": {
"created": true,
"sha": "string or null",
"title": "string or null"
},
"consumed_budget": {
"rounds": 1,
"files_changed": 3,
"commits": 0,
"runtime_minutes": 10
},
"remaining_budget": {
"rounds": 4,
"files_changed": 27,
"commits": 2,
"runtime_minutes": 80
},
"scope_expanded": false,
"risk_level": "low",
"recovery": {
"status": "none | required | context_restored | complete",
"resume_target": "RESUME_CURRENT_BATCH | null",
"current_batch_preserved": true,
"pending_batches_preserved": true,
"failed_batch_settled": false,
"retry_exhausted": false,
"repair_authority": "string or null",
"repair_eligible": false,
"required_context": {
"failed_round": "object",
"evidence": "object"
}
}
}
When this closeout is consumed by graft-multi-agent-loop, the recovery object is evidence input and the outer
controller owns the canonical decision record. Its controller record must preserve current_batch and
pending_batches during recovery and include controller_state, terminal_reason, and the complete recovery fields
shown in the loop skill. retry_exhausted=true records wave evidence only; it does not make closeout_status
terminal and does not authorize a worker or closeout helper to choose BLOCKED, ARCHIVE_READY, or a recovery
transition.
For graft-multi-agent-loop in the default topic-completion-loop mode, prefer this interpretation:
continue=true with next_prompt=null means same-session continuation
next_batch and next_batch_prompt drive the next delegated worker round
Next-session startup prompt: is emitted for terminal handoff or a structured recovery_handoff; recovery is not a
terminal state and must resume the preserved current batch after its eligibility conditions are met
Boundaries
- do not treat this skill as permission to commit unrelated changes
- do not duplicate
graft-boot; this skill assumes startup already happened in the current turn
- do not duplicate
graft-validation-runner; use it when validation scope is uncertain
- do not duplicate
graft-commit; use its rules for every commit-eligibility decision and use it directly when the
decision is to create a commit
- do not claim the next turn can skip startup preflight
Example Startup Prompt Template
You are handling a <task class> task. Governance source: root AGENTS.md. Task class: <task class>. Recovery source: <none|parent topic|parent topic + subtopic>. Owned scope: <owned scope>. First rerun startup preflight from AGENTS.md 4.1, then continue with <next step>.