Skip to main content

skill-todo

Archive completed, abandoned, and expanded tasks with CHANGE_LOG.md updates and memory harvest suggestions

Zur Installation springen

Quellinformationen

Repository
benbrastmckie/nvim
Letzte Quellaktivität
2. September 2026 um 01:58
Erkannte Sprache von SKILL.md
Englisch
Sterne
443
Forks
459

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
skill-todo
description
Archive completed, abandoned, and expanded tasks with CHANGE_LOG.md updates and memory harvest suggestions
allowed-tools
Bash, Edit, Read, Write, Grep, AskUserQuestion
context
direct
# Todo Skill Direct execution skill for archiving tasks, updating CHANGE_LOG.md, and suggesting memory harvesting. <context> <system_context>OpenCode task archival with changelog tracking and memory suggestions.</system_context> <task_context>Archive completed/abandoned/expanded tasks and track changes.</task_context> </context> <role>Direct execution skill for task archival operations with automated CHANGE_LOG updates and memory harvest suggestions.</role> <task>Parse arguments, scan for archivable tasks (completed, abandoned, expanded), update states, generate CHANGE_LOG entries, suggest memory harvesting from completed task artifacts.</task> <execution> <stage id="1" name="ParseArguments"> <action>Parse command arguments</action> <process> 1. Check for --dry-run flag 2. Set dry_run = true if present 3. Validate no other arguments expected </process> </stage> <stage id="1.5" name="ReconcileScan"> <action>Dry-run scan for status-stranded tasks whose artifact for the in-flight phase already exists on disk -- these are invisible to Stage 2's literal completed/abandoned match today and can never be archived until something promotes them</action> <process> This stage never auto-repairs status: `/todo` performs the system's most irreversible operations (moving directories, rewriting CHANGE_LOG.md), and a silent status promotion immediately before a silent archive move would compound two mutations with no visibility. Every call this stage makes is `--dry-run`; only a user-approved selection in Stage 9 ever calls the script live. 1. Generate a session ID via `common_session_id` (skill-todo does not source `command-gate-in.sh` and has no session ID of its own): ```bash source .claude/scripts/lib/common.sh todo_session_id="$(common_session_id)" ``` 2. Select the same four reconcilable statuses used by the `/task --sync` and `/orchestrate` triggers (positive-match against the four statuses `reconcile-task-status.sh` knows how to reconcile -- no `!=`/negation selector needed): ```bash reconcile_scan_targets=$(jq -r ' .active_projects[] | select(.status == "researching" or .status == "planning" or .status == "implementing" or .status == "partial") | .project_number ' specs/state.json) ``` 3. For each candidate, dry-run the script and collect any task whose output reports a would-promote line into `reconcile_candidates`, keeping each candidate's task number, current status, the artifact basename found, and the full dry-run output for display in Stage 8/9: ```bash reconcile_candidates=() for task_num in $reconcile_scan_targets; do recon_out=$(bash .claude/scripts/reconcile-task-status.sh "$task_num" "$todo_session_id" --dry-run 2>&1) if echo "$recon_out" | grep -q "Would promote"; then reconcile_candidates+=("$task_num") # associate $recon_out with $task_num (e.g. via an associative array) for Stage 9's # AskUserQuestion description text fi done ``` 4. If `reconcile_scan_targets` is empty, `reconcile_candidates` is `()` -- proceed straight to Stage 2. This stage is genuinely side-effect-free: `--dry-run` never writes `state.json` or any other file. </process> </stage> <stage id="2" name="ScanTasks"> <action>Scan for archivable tasks</action> <process> 1. Read specs/state.json 2. Identify tasks with status = "completed" 3. Identify tasks with status = "abandoned" 4. Identify tasks with status = "expanded" 5. Read specs/TODO.md and cross-reference (including entries marked [EXPANDED]) 6. Track counts: completed_count, abandoned_count, expanded_count **Subtasks-defer guard**: identical semantics to `commands/todo.md`'s Step 3 guard (see that file's "Prepare Archive List" section, which is the reference implementation this mirrors). Partition the tasks identified above into `archivable_tasks[]` (proceeds) and `deferred_expanded[]` (held back for a later `/todo` run) — an expanded parent is deferred while any task in its `subtasks[]` is still present in `active_projects` with a non-terminal status. Use a `case` statement for status classification (never `!=`): ```bash archivable_tasks=() deferred_expanded=() deferred_expanded_nums=() for task in "${candidate_tasks[@]}"; do status=$(echo "$task" | jq -r '.status') project_num=$(echo "$task" | jq -r '.project_number') case "$status" in expanded) # A missing, null, or empty subtasks array means nothing is blocking - archive normally. subtasks=$(echo "$task" | jq -c '.subtasks // []') subtask_count=$(echo "$subtasks" | jq 'length') if [ "$subtask_count" -eq 0 ]; then archivable_tasks+=("$task") continue fi blocking_count=0 for subtask_num in $(echo "$subtasks" | jq -r '.[]'); do subtask_status=$(jq -r --argjson n "$subtask_num" \ '.active_projects[] | select(.project_number == $n) | .status' \ specs/state.json) # An empty result means the subtask is already archived - not blocking. if [ -z "$subtask_status" ]; then continue fi case "$subtask_status" in completed|abandoned|expanded) # Terminal - not blocking. ;; *) # Any other status blocks. ((blocking_count++)) ;; esac done if [ "$blocking_count" -gt 0 ]; then deferred_expanded+=("$task") deferred_expanded_nums+=("$project_num") else archivable_tasks+=("$task") fi ;; *) # Non-expanded tasks pass through untouched. archivable_tasks+=("$task") ;; esac done ``` Track `deferred_expanded[]` and `deferred_count` (`= ${#deferred_expanded[@]}`). Stage 10 (`ArchiveTasks`) consumes `archivable_tasks[]` — never a freshly-recomputed status match — so a deferred parent's `active_projects` entry survives this run. </process> </stage> <stage id="2.5" name="TopicRevision"> <action>Optional: backfill topics on active tasks missing the topic field</action> <process> Detect active tasks without a topic: ```bash missing=$(jq -r '.active_projects[] | select(.status == "completed" | not) | select(.status == "abandoned" | not) | select(.status == "expanded" | not) | select(.topic == null or .topic == "") | "\(.project_number)|\(.project_name)"' specs/state.json) ``` If no tasks need backfill, skip this stage. For each task needing a topic, follow the topic assignment pattern from @.claude/context/patterns/topic-assignment-pattern.md (Mode A, per-task backfill). Use header "Topic Backfill ({i} of {total})". After each selection: ```bash bash .claude/scripts/manage-topics.sh set "$task_num" "$topic" ``` </process> </stage> <stage id="3" name="DetectOrphans"> <action>Detect orphaned directories and TODO.md orphans</action> <process> 1. Scan specs/ for directories not tracked in state files: ```bash for dir in specs/OC_[0-9]*_*/ specs/[0-9]*_*/; do [ -d "$dir" ] || continue basename_dir=$(basename "$dir") project_num=$(echo "$basename_dir" | sed 's/^OC_//' | cut -d_ -f1) in_active=$(jq -r --arg n "$project_num" \ '.active_projects[] | select(.project_number == ($n | tonumber)) | .project_number' \ specs/state.json 2>/dev/null) in_archive=$(jq -r --arg n "$project_num" \ '.completed_projects[] | select(.project_number == ($num | tonumber)) | .project_number' \ specs/archive/state.json 2>/dev/null) if [ -z "$in_active" ] && [ -z "$in_archive" ]; then orphaned_in_specs+=("$dir") fi done ``` 2. Scan specs/archive/ for orphaned directories: ```bash for dir in specs/archive/OC_[0-9]*_*/ specs/archive/[0-9]*_*/; do [ -d "$dir" ] || continue basename_dir=$(basename "$dir") project_num=$(echo "$basename_dir" | sed 's/^OC_//' | cut -d_ -f1) in_archive=$(jq -r --arg n "$project_num" \ '.completed_projects[] | select(.project_number == ($num | tonumber)) | .project_number' \ specs/archive/state.json 2>/dev/null) if [ -z "$in_archive" ]; then orphaned_in_archive+=("$dir") fi done ``` 3. Scan TODO.md for completed/abandoned tasks not tracked in state.json or archive: - Parse task headers (`### {N}.` or `### OC_{N}.`) and status lines (`[COMPLETED]`/`[ABANDONED]`) - Cross-reference each against active_projects and archive completed_projects - Collect as `todo_md_orphans[]` if: status is completed/abandoned, not in either state file, and has a directory in specs/ </process> </stage> <stage id="4" name="DetectMisplaced"> <action>Detect misplaced directories</action> <process> 1. Scan specs/ for directories tracked in archive state: ```bash for dir in specs/OC_[0-9]*_*/ specs/[0-9]*_*/; do [ -d "$dir" ] || continue basename_dir=$(basename "$dir") project_num=$(echo "$basename_dir" | sed 's/^OC_//' | cut -d_ -f1) in_active=$(jq -r --arg n "$project_num" \ '.active_projects[] | select(.project_number == ($num | tonumber)) | .project_number' \ specs/state.json 2>/dev/null) in_archive=$(jq -r --arg n "$project_num" \ '.completed_projects[] | select(.project_number == ($num | tonumber)) | .project_number' \ specs/archive/state.json 2>/dev/null) if [ -z "$in_active" ] && [ -n "$in_archive" ]; then misplaced_in_specs+=("$dir") fi done ``` </process> </stage> <stage id="5" name="ScanRoadmap"> <action>Scan for roadmap references</action> <process> 0. Do NOT auto-create `specs/ROADMAP.md` if it is absent. An absent roadmap is "no roadmap tracked" — a supported state, not a repair trigger; `roadmap-integration.sh` itself treats absence this way (exits 0, emits the `roadmap_absent` warning, does not recreate the file) and step 3 below surfaces that warning. Re-creating the file here, ahead of the script call, would silently defeat that contract and make any deliberate deletion of the roadmap never stick. 1. Partition `archivable_tasks[]` into roadmap-excluded (meta tasks, and expanded tasks — an expanded task has no `completion_summary` of its own by construction, since its subtasks carry the deliverables; do not "fix" this by requiring one) and roadmap-eligible tasks, exactly as `commands/todo.md`'s Step 3.5.1 does. 2. This stage performs no matching of its own. Invoke `roadmap-integration.sh` parse-only (no `--annotate`) against `specs/ROADMAP.md`/`specs/state.json`, capturing `roadmap_structure`, `warnings`, and `roadmap_matches` from the payload. Filter `roadmap_matches` to only the roadmap-eligible tasks from step 1 before treating any match as an annotation candidate — this filter is where meta/expanded exclusion is enforced, since the script has no `task_type` filter of its own (see the script's header "Caller contract"). 3. **Error-handling contract** (identical to `commands/todo.md`'s Step 3.5 and `commands/review.md`'s Step 2.5): a missing script, a non-zero exit, or empty output all produce the same visible warning and the same fully-defined `parseable: false` fallback — never silence. </process> </stage> <stage id="6" name="ScanMetaSuggestions"> <action>Scan meta tasks for README.md suggestions</action> <process> 1. For each archived meta task: - Check completion_data.readme_suggestions - Filter out "none" values - Track actionable suggestions by type: * Add: Insert new content * Update: Replace existing content * Remove: Delete content </process> </stage> <stage id="7" name="HarvestMemories"> <action>Collect, deduplicate, and classify memory candidates from state.json</action> <process> Note: this stage stays scoped to completed tasks and is not widened to expanded tasks — an expanded task's work product and memory candidates belong to its subtasks, which are harvested (or already were harvested) in their own right when they complete. 1. Collect candidates from state.json: - For each completed task in the archival batch: - Read `memory_candidates // []` from the task's state.json entry - Flatten into a single list, tagging each candidate with `task_number` provenance - If no candidates across all tasks, set `harvest_candidates = []` and skip to Stage 8 2. Deduplicate against existing memory-index.json: - Read `.memory/memory-index.json` (if missing or empty, skip dedup -- all candidates are CREATE) - For each candidate, compute keyword overlap against every index entry:
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen