summarize-task
Close a task: capture what actually happened (often different from the plan), flip checkboxes, advance STATE.md. Produces an append-to-history artifact future sessions can read.
Anti-Pattern: "The task is done, I don't need a summary"
Without a summary, the next session has no way to know this task happened -- STATE.md wasn't updated, the slice-plan checkbox is still [ ], and the next agent will either redo the work or get confused. The summary is the closure signal. Always write it, even for one-line tasks ("CSS tweak -- shipped in one commit, no follow-up needed").
Checklist
You MUST create a TodoWrite task for each of these items:
- Run preamble -- detect active task + plan file
- HARD-GATE: active task must exist -- abort if none
- Read the plan -- show user the original scope
- Ask outcome -- what actually shipped
- Ask deviations -- what differed from plan (if anything)
- Ask follow-ups -- new tasks / decisions surfaced during execution
- Ask verification result -- did the verification command pass?
- Write
M###-S##-T##-SUMMARY.md - Flip slice-plan checkbox
[ ]→[x] - Update STATE.md -- clear
active_task, bump counts, update status line - Offer git stage -- ask if user wants git-add of touched files
- Report + return -- suggest next task or slice-close
Preamble
_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$PWD}"
cd "$_PROJECT_DIR" 2>/dev/null || true
_PROJECT_SLUG=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || basename "$(pwd)")
if [ -d "$_PROJECT_DIR/.ytstack" ]; then
_YT_DIR="$_PROJECT_DIR/.ytstack"
elif [ -d "$HOME/.ytstack/projects/$_PROJECT_SLUG" ]; then
_YT_DIR="$HOME/.ytstack/projects/$_PROJECT_SLUG"
else
_YT_DIR=""
fi
_HAS_YTSTACK=$([ -n "$_YT_DIR" ] && echo yes || echo no)
_NON_INTERACTIVE=false
if [ -n "$YTSTACK_NON_INTERACTIVE" ] || [ -n "$OPENCLAW_SESSION" ] || [ -n "$CLAUDE_AGENT_TEAM_MEMBER" ]; then
_NON_INTERACTIVE=true
fi
_CURRENT_MILESTONE=none
_ACTIVE_SLICE=none
_ACTIVE_TASK=none
if [ -f "$_YT_DIR/STATE.md" ]; then
_CURRENT_MILESTONE=$(sed -n 's/^current_milestone: *//p' "$_YT_DIR/STATE.md" | head -1)
_ACTIVE_SLICE=$(sed -n 's/^active_slice: *//p' "$_YT_DIR/STATE.md" | head -1)
_ACTIVE_TASK=$(sed -n 's/^active_task: *//p' "$_YT_DIR/STATE.md" | head -1)
fi
_PLAN_FILE="$_YT_DIR/$_CURRENT_MILESTONE-$_ACTIVE_SLICE-$_ACTIVE_TASK-PLAN.md"
_SLICE_PLAN="$_YT_DIR/$_CURRENT_MILESTONE-$_ACTIVE_SLICE-PLAN.md"
_IS_GIT=$([ -d .git ] && echo yes || echo no)
# Gather this task's commits for a durable, committed `## Commits` section.
# ytstack's commit convention prefixes task commits with `M###-S##-T##:`
# (see CLAUDE.md), so grep the log for that ref. This is the SINGLE owner of
# commit-to-task linking; the post-tool-use-bash hook only drops a draft stub
# and never maintains a commit list (issue #22 / M015).
_TASK_REF="$_CURRENT_MILESTONE-$_ACTIVE_SLICE-$_ACTIVE_TASK"
_TASK_COMMITS=""
if [ "$_IS_GIT" = yes ]; then
_TASK_COMMITS=$(git log --no-merges --pretty=format:'- `%h` -- %s' --grep "^$_TASK_REF" 2>/dev/null)
fi
echo "HAS_YTSTACK: $_HAS_YTSTACK"
echo "YTSTACK_NON_INTERACTIVE: $_NON_INTERACTIVE"
echo "CURRENT_MILESTONE: $_CURRENT_MILESTONE"
echo "ACTIVE_SLICE: $_ACTIVE_SLICE"
echo "ACTIVE_TASK: $_ACTIVE_TASK"
echo "PLAN_FILE: $_PLAN_FILE"
echo "SLICE_PLAN: $_SLICE_PLAN"
echo "IS_GIT: $_IS_GIT"
echo "TASK_COMMITS_BEGIN"
echo "${_TASK_COMMITS:-(none found for $_TASK_REF)}"
echo "TASK_COMMITS_END"
Procedure
Step 2: HARD-GATE
If any of HAS_YTSTACK / CURRENT_MILESTONE / ACTIVE_SLICE / ACTIVE_TASK is no / none:
"No active task to summarize. Check STATE.md and run the preceding skill (
plan-task/slice-milestone/plan-milestone/init-project) as needed." STOP.
If PLAN_FILE does not exist:
"STATE.md says active_task={ACTIVE_TASK} but plan file missing at {PLAN_FILE}. Repair manually before summarizing." STOP.
Step 3: Read the plan
Read {PLAN_FILE}. Extract Summary, Files, Verification. Show:
Closing {CURRENT_MILESTONE}-{ACTIVE_SLICE}-{ACTIVE_TASK}.
Original plan: {SUMMARY} Files planned: {FILE_LIST} Verification: {VERIFICATION_CMD}
Step 4: Ask outcome
Use AskUserQuestion (open-ended):
What actually shipped? 2-4 sentences. Use past tense. Say what the code does now, not what you did to it.
Good: "Signup form validates email client-side and POSTs JSON to /api/signup. Server hashes with argon2 and inserts user row. Returns 201 with session cookie. Duplicate email returns 409."
Bad: "I implemented signup" -- too vague, not useful to future sessions.
Remember as _OUTCOME.
Step 5: Ask deviations
Use AskUserQuestion (open-ended):
Did anything differ from the plan? Extra files, skipped features, refactors, new dependencies?
Enter "none" if the plan held up.
Remember as _DEVIATIONS.
Step 6: Ask follow-ups
Use AskUserQuestion (open-ended):
Anything that surfaced during execution that needs follow-up? Add them as:
- new tasks (get added to next slice or a new slice)
- decisions to lock in
DECISIONS.md- patterns worth capturing in
KNOWLEDGE.md- items to flag in
REVIEW-NOTES.mdfor end-of-cycleEnter "none" if clean.
Remember as _FOLLOWUPS.
Step 7: Ask verification result
Use AskUserQuestion (multi-choice):
Did the plan's verification step pass?
Verification was:
{VERIFICATION_CMD}A) Passed -- clean exit, expected output. (Completeness: 10/10) B) Passed with caveats -- exits 0 but something's off. (Completeness: 7/10, flag in followups) C) Failed -- task not actually done. (Completeness: 0/10, do not close)
If C: do NOT proceed. Re-execute the task until it passes, then re-run this skill.
If C: STOP. Do not write the summary.
Remember as _VERIFICATION_RESULT (value: passed / passed_with_caveats).
Step 8: Write M###-S##-T##-SUMMARY.md
---
milestone: {CURRENT_MILESTONE}
slice: {ACTIVE_SLICE}
task: {ACTIVE_TASK}
project: {PROJECT_NAME}
closed: {ISO_TIMESTAMP}
verification: {VERIFICATION_RESULT}
---
# {CURRENT_MILESTONE}-{ACTIVE_SLICE}-{ACTIVE_TASK} -- Summary
## Commits
{The commit list captured between TASK_COMMITS_BEGIN / TASK_COMMITS_END in the preamble. If it reported "(none found ...)", write: "No commits matched `{TASK_REF}:` -- task shipped uncommitted or under a non-conventional message." This section replaces the throwaway hook draft; it is the durable commit-to-task link.}
## Outcome
{OUTCOME}
## Deviations from plan
{DEVIATIONS}
## Follow-ups
{FOLLOWUPS}
## Verification
Command: `{VERIFICATION_CMD}` -- {VERIFICATION_RESULT}.
Step 9: Flip slice-plan checkbox
Edit {SLICE_PLAN}. Replace:
- [ ] {ACTIVE_TASK} -- {TASK_DESC}
with:
- [x] {ACTIVE_TASK} -- {TASK_DESC}
Also bump completed_tasks in the slice-plan's frontmatter by 1.
Step 10: Update STATE.md
If YTSTACK_NON_INTERACTIVE is false (i.e. CLAUDE_AGENT_TEAM_MEMBER is unset), edit STATE.md frontmatter:
active_task: {ACTIVE_TASK}→active_task: none- If the slice is now fully complete (all tasks
[x]): alsoactive_slice: {ACTIVE_SLICE}→active_slice: none
If YTSTACK_NON_INTERACTIVE is true (running as swarm teammate): skip frontmatter writes. Log:
[ytstack:summarize-task] skipping STATE.md active_task/active_slice write -- running as swarm teammate (CLAUDE_AGENT_TEAM_MEMBER set)
Regardless of teammate mode:
last_updated: ...→ bump to current- Status line →
**Status:** {CURRENT_MILESTONE} / {ACTIVE_SLICE} -- {N}/{TOTAL} tasks done in slice. Next task: pick from slice-plan or run/ytstack:plan-task.
If the slice is now fully complete (all tasks [x]): update status to recommend /ytstack:reassess-roadmap.
Step 11: Offer git stage
If IS_GIT=yes, use AskUserQuestion:
Task closed. Want to stage the touched files for commit?
Files from plan: {FILE_LIST}
RECOMMENDATION: A if the files match the plan. B if you touched additional files (deviation case).
A) Stage the planned files --
git add {FILE_LIST}then you commit manually with a message B) Don't stage -- I'll handle it myself C) Stage all changes --git add -A(use with caution; may include unintended files)
If A: run git add {FILE_LIST} and report git status output.
If B: skip.
If C: confirm once more (destructive-flavored), then git add -A + git status.
Step 12: Report + return
Report:
Task {ACTIVE_TASK} closed.
Summary at:
{YT_DIR}/{CURRENT_MILESTONE}-{ACTIVE_SLICE}-{ACTIVE_TASK}-SUMMARY.mdSlice-plan checkbox flipped. STATE.md:active_taskcleared.Next step:
- If slice has more tasks:
/ytstack:plan-taskfor the next one- If slice is complete:
/ytstack:reassess-roadmapto check if plan still fits reality before moving to next slice- If milestone is complete: flip milestone status in ROADMAP.md and run
/ytstack:plan-milestonefor the next
Terminal State
Valid terminal states:
- Return after summary file + slice-plan update + STATE.md update + optional git stage
- Abort on HARD-GATE failure (no active task / missing plan file)
- Abort on verification failure (C in Step 7) -- task stays open
Do NOT invoke plan-task, reassess-roadmap, or plan-milestone automatically.