feat: phases + tasks — per-task execution with phase directories
- A phase is now a directory: 00_phase.md (overview + task index) plus small, quick NN_task.md task files; complete/ mirrors todo/ - Task is the unit of execution: run-task.sh (one unit), run-phase.sh (phase to completion incl. 00_phase.md final pass), auto-phase.sh (all units in order); validate.sh gate runs after every task - PHASE_COMMIT commits at phase boundaries (00_phase.md / legacy file moves) - Legacy flat todo/NN_name.md files still execute as a single unit; new migrate-phases-to-tasks.sh converts them to the directory layout - phase-status.sh reports per-task state and the next unit - New task-template.md; phase templates now carry a Tasks index
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# migrate-phases-to-tasks.sh — convert the flat phase-file layout to the
|
||||
# phase-directory + task-file layout.
|
||||
#
|
||||
# Each numeric-prefixed flat phase file in {todo,complete}/ is wrapped into a
|
||||
# directory of the same name with the file renamed to 00_phase.md:
|
||||
#
|
||||
# todo/03_api.md → todo/03_api/00_phase.md
|
||||
# complete/01_init.md → complete/01_init/00_phase.md
|
||||
#
|
||||
# The harness still executes wrapped phases: their inline task lists are
|
||||
# picked up by the phase's 00_phase.md final pass, so this is safe
|
||||
# mid-pipeline. Splitting a wrapped todo phase into real task files is the
|
||||
# phase-authoring skill's job, not this script's. Already-migrated phases are
|
||||
# left alone; a flat file colliding with an existing same-name directory is
|
||||
# reported and skipped.
|
||||
#
|
||||
# Usage: bash migrate-phases-to-tasks.sh [project-root]
|
||||
# project-root defaults to the nearest ancestor containing
|
||||
# .agent/phases/todo or agent/phases/todo (older projects).
|
||||
set -euo pipefail
|
||||
|
||||
root="${1:-}"
|
||||
if [[ -n "$root" ]]; then
|
||||
[[ -d "$root" ]] || { echo "✗ ERROR: $root is not a directory" >&2; exit 1; }
|
||||
else
|
||||
root="$(pwd)"
|
||||
while :; do
|
||||
if [[ -d "$root/.agent/phases/todo" || -d "$root/agent/phases/todo" ]]; then break; fi
|
||||
[[ "$root" == "/" ]] && { echo "✗ ERROR: no phases/todo found at or above $(pwd)" >&2; exit 1; }
|
||||
root="$(dirname "$root")"
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -d "$root/.agent/phases" ]]; then
|
||||
phases="$root/.agent/phases"
|
||||
elif [[ -d "$root/agent/phases" ]]; then
|
||||
phases="$root/agent/phases"
|
||||
else
|
||||
echo "✗ ERROR: no phases directory under $root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "project root: $root"
|
||||
echo "phases: $phases"
|
||||
echo
|
||||
|
||||
moved=0 skipped=0
|
||||
for d in todo complete; do
|
||||
[[ -d "$phases/$d" ]] || continue
|
||||
for f in "$phases/$d"/*.md; do
|
||||
[[ -e "$f" ]] || continue
|
||||
base="$(basename "$f" .md)"
|
||||
[[ "$base" =~ ^[0-9] ]] || continue
|
||||
if [[ -d "$phases/$d/$base" ]]; then
|
||||
echo "⚠ skip: $d/$base.md — directory $d/$base/ already exists (conflict)" >&2
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
mkdir -p "$phases/$d/$base"
|
||||
mv -f "$f" "$phases/$d/$base/00_phase.md"
|
||||
echo " $d/$base.md → $d/$base/00_phase.md"
|
||||
moved=$((moved + 1))
|
||||
done
|
||||
done
|
||||
|
||||
echo
|
||||
echo "migrated: $moved phase file(s) → 00_phase.md directory layout; skipped: $skipped"
|
||||
if (( moved > 0 )); then
|
||||
echo "wrapped todo phases now run as a single final pass; use the phase-authoring"
|
||||
echo "skill to split their inline task lists into real task files."
|
||||
fi
|
||||
Reference in New Issue
Block a user