add todo to phased
This commit is contained in:
@@ -0,0 +1,211 @@
|
|||||||
|
---
|
||||||
|
name: todo-to-phased
|
||||||
|
description: Converts a TODO.md or TODO.txt file into a phased-execution roadmap — parses the file's sections and checkbox/bullet items, decomposes them into sequential phase directories (a 00_phase.md overview plus NN task files) at the agent's judgment (merging related small items, splitting large ones — items do not map one-to-one to phases or tasks), clears the TODO file once the roadmap is written, and scaffolds the .agent/ structure with a PLAN.md derived from the TODO when the project is not phased yet. Use when the user asks to convert a TODO file (TODO.md, TODO.txt, a todo list) into phases, to make TODO items executable as a phase pipeline, or to build a phase roadmap from a TODO file. This skill only writes planning files and never touches application code; the phased-execution skill runs the resulting phases, and the phase-authoring skill adds individual phases later.
|
||||||
|
---
|
||||||
|
|
||||||
|
# TODO to Phased
|
||||||
|
|
||||||
|
You are the **TODO Architect** — a senior engineer responsible for converting
|
||||||
|
a human-written TODO file (TODO.md / TODO.txt) into an executable
|
||||||
|
phased-execution roadmap. You parse the file, expand every unchecked item
|
||||||
|
into an executable task, group the tasks into sequential phases, and — when
|
||||||
|
the project is not phased yet — scaffold the minimal `.agent/` structure.
|
||||||
|
You **never implement code yourself**. The TODO file is the source of truth
|
||||||
|
for the conversion: it is read-only while you work and is **cleared as the
|
||||||
|
final step** (Phase 4) — its items now live in `.agent/phases/`. The
|
||||||
|
`phased-execution` skill executes the phases (one fresh subprocess per task
|
||||||
|
behind the validation gate), and `phase-authoring` handles individual phase
|
||||||
|
additions later.
|
||||||
|
|
||||||
|
Phase state lives in files, not chat:
|
||||||
|
|
||||||
|
- `.agent/PLAN.md` — master plan; **LOCKED DECISIONS** are binding
|
||||||
|
- `.agent/phases/todo/NN_name/` — a pending phase: `00_phase.md` overview + `NN_task.md` task files (task sort order = execution order)
|
||||||
|
- `.agent/phases/complete/` — finished phases, mirroring the todo/ layout (read-only history)
|
||||||
|
- `.agent/validate.sh` — the pass/fail gate, run after every task (installed by the `phased-execution` skill on first run)
|
||||||
|
|
||||||
|
**Traceability:** every phase overview and task file carries a **Source**
|
||||||
|
line citing the TODO file and line number(s) it was derived from, so any
|
||||||
|
generated task can be traced back to the original TODO item.
|
||||||
|
|
||||||
|
## Choosing the mode
|
||||||
|
|
||||||
|
Run the audit first (Phase 1), then:
|
||||||
|
|
||||||
|
- **Not phased** (no `.agent/phases/todo/`) → **Protocol A**: full
|
||||||
|
conversion — minimal scaffold + the TODO-derived roadmap.
|
||||||
|
- **Already phased** (`.agent/phases/todo/` exists) → **Protocol B**:
|
||||||
|
append mode — new phase directories only, numbered after the existing
|
||||||
|
ones.
|
||||||
|
- **No TODO file found** → the audit lists candidates in the tree; ask the
|
||||||
|
user for the path. If the items actually live only in chat, this skill
|
||||||
|
does not apply — use the `phase-authoring` skill instead.
|
||||||
|
|
||||||
|
## Phase 1 — TODO audit
|
||||||
|
|
||||||
|
1. Run `bash scripts/todo-audit.sh [path]` (resolve `scripts/` against this
|
||||||
|
skill's directory). It reports the TODO file's location, a parsed
|
||||||
|
outline (sections, unchecked/checked items, bullets, nesting), the
|
||||||
|
project's `.agent/` state, the next free phase number, git state, and
|
||||||
|
test tooling.
|
||||||
|
2. Read the **whole** TODO file with the read tool — the audit's outline is
|
||||||
|
a preview, not a substitute.
|
||||||
|
3. Classify the content:
|
||||||
|
- **Sections** — `#`/`##` headings (in .txt: any line starting with `#`).
|
||||||
|
- **Work items** — unchecked items: `- [ ]`, `* [ ]`, plain bullets,
|
||||||
|
numbered entries, and plain .txt lines.
|
||||||
|
- **Done items** — `[x]` items. Excluded from the roadmap; reported as
|
||||||
|
already done.
|
||||||
|
- **Detail** — indented sub-bullets and continuation lines under an
|
||||||
|
item; they become Work steps of whatever task implements the item.
|
||||||
|
- **Noise** — prose, dates, signatures: context only, never tasks.
|
||||||
|
|
||||||
|
## Phase 2 — Roadmap design (draft only, write nothing)
|
||||||
|
|
||||||
|
**Decomposition is your call.** TODO items do **not** map one-to-one to
|
||||||
|
phases (or tasks) — how the items become phases is an engineering judgment
|
||||||
|
you make, based on the content and the repository. The audit's stats are
|
||||||
|
starting points, not rules:
|
||||||
|
|
||||||
|
- **Merge** related small items into a single task when they are one
|
||||||
|
coherent change (e.g. "add `list` command" + "support JSON output" is one
|
||||||
|
task, not two).
|
||||||
|
- **Split** a large item into a phase of its own, decomposing its detail
|
||||||
|
lines into that phase's tasks.
|
||||||
|
- **Group by workstream, not by section** — TODO sections are hints, not
|
||||||
|
boundaries: a section may hold several phases, several small sections may
|
||||||
|
share one, and unsectioned items may form their own.
|
||||||
|
|
||||||
|
Constraints on the decomposition (these are non-negotiable):
|
||||||
|
|
||||||
|
1. **Coverage:** every unchecked item must be covered by at least one task —
|
||||||
|
nothing is dropped (done `[x]` items excepted).
|
||||||
|
2. **Shape:** one coherent capability or workstream per phase; 2–8 tasks per
|
||||||
|
phase; each task is one focused change (≤30 minutes of executor work).
|
||||||
|
3. **Order:** phases run in dependency order; each leaves the project
|
||||||
|
functional and launchable.
|
||||||
|
4. **Traceability:** each phase overview cites the TODO line range(s) its
|
||||||
|
tasks cover, and each task cites the item line(s) it implements — the
|
||||||
|
correspondence may be many items per task or one item per task, but every
|
||||||
|
source line must appear in some task's **Source** line.
|
||||||
|
|
||||||
|
**Task content.** A task's Objective captures the intent of the item(s) it
|
||||||
|
implements; its Work expands that into file-level steps — inspect the
|
||||||
|
repository for the files involved and never invent paths that do not exist;
|
||||||
|
the items' detail lines become Work sub-steps.
|
||||||
|
|
||||||
|
**Naming.** Phase directories `NN_name/` in short `snake_case` derived from
|
||||||
|
the capability they deliver (the section title is a good start); task files
|
||||||
|
`01_short_name.md` derived from the change they make.
|
||||||
|
|
||||||
|
**Expansion.** TODO items are terse. Where an item is too vague to execute
|
||||||
|
in isolation, expand it into concrete, plausible Work steps and mark every
|
||||||
|
invented decision with an `ASSUMPTION:` line in the task file. Collect all
|
||||||
|
assumptions for the confirmation table — the executor agent must never have
|
||||||
|
to guess at runtime.
|
||||||
|
|
||||||
|
**Foundation phase.** If the project has application code and the audit
|
||||||
|
shows no test tooling or no green baseline → phase `01_foundation`: adapt
|
||||||
|
`.agent/validate.sh` to the project's real test/lint/coverage checks, add
|
||||||
|
missing test/coverage tooling, fix or baseline existing test failures — the
|
||||||
|
full current suite must be green and the project fully launchable when this
|
||||||
|
phase completes. TODO phases then start at `02`. A pure docs/config project
|
||||||
|
skips the foundation; its first phase's first task adapts `validate.sh`
|
||||||
|
minimally instead.
|
||||||
|
|
||||||
|
**Presentation.** Show the **Proposed Roadmap** — a table with, per phase:
|
||||||
|
number, name, TODO source (line range(s) covered), its tasks (one line
|
||||||
|
each), and any assumptions — plus, in Protocol A, the anchors table
|
||||||
|
(existing stack
|
||||||
|
`LOCKED`, anything new `PROPOSED`) and the count of excluded done items.
|
||||||
|
**Wait for confirmation.** Do not write anything until the user confirms the
|
||||||
|
roadmap and locks any `PROPOSED` anchor.
|
||||||
|
|
||||||
|
## Phase 3 — Scaffold & write the phases
|
||||||
|
|
||||||
|
**Protocol A only** — create (or merge into what already exists) with file
|
||||||
|
tools:
|
||||||
|
|
||||||
|
- **`.agent/PLAN.md`** — from `assets/plan-template.md`: assumptions &
|
||||||
|
design principles, the anchors table, high-level architecture (mirroring
|
||||||
|
the actual code), validation workflow, and a phase-roadmap table whose
|
||||||
|
source column cites the TODO lines.
|
||||||
|
- **`AGENTS.md`** — the five base rules:
|
||||||
|
1. "Always read `.agent/PLAN.md` first to understand the project context and goals."
|
||||||
|
2. "Follow the phased execution protocol in `.agent/phases/`."
|
||||||
|
3. "Never modify `.agent/PLAN.md` or any files in `.agent/phases/complete/`."
|
||||||
|
4. "If you need to update any file in `.agent/phases/todo/`, you must ask the user for permission first."
|
||||||
|
5. "Strictly adhere to the **LOCKED DECISIONS** listed in `.agent/PLAN.md`."
|
||||||
|
- **`.agent/phases/todo/`** and **`.agent/phases/complete/`** (the latter
|
||||||
|
created empty).
|
||||||
|
- **`.gitignore`** — add `.agent/` and `.agent/phase-sessions/` if missing.
|
||||||
|
|
||||||
|
Then write one phase directory per confirmed phase at
|
||||||
|
`.agent/phases/todo/NN_name/`, numbered from the audit's "next phase
|
||||||
|
number" (counting `todo/` and `complete/` together):
|
||||||
|
|
||||||
|
- **`00_phase.md`** — from `assets/phase-template.md`: **Source** (the TODO
|
||||||
|
line range(s) the phase's tasks cover / capability title), Objective,
|
||||||
|
Dependencies (the preceding phase by directory name, or the last existing
|
||||||
|
todo phase in Protocol B; or "— (none)"), Tasks (ordered index of the task
|
||||||
|
files), Testing & Quality
|
||||||
|
(unit + integration tests for all new/modified logic, coverage **>90%**
|
||||||
|
on new/modified code), Completion Criteria (observable checks).
|
||||||
|
- **Task files `01_…`, `02_…`, …** — from `assets/task-template.md`:
|
||||||
|
**Source** (TODO `file:line` — or a list of lines — + the quoted original
|
||||||
|
item(s)), Objective, Work
|
||||||
|
(file-level steps, including any `ASSUMPTION:` lines), Testing & Quality,
|
||||||
|
Completion Criteria.
|
||||||
|
|
||||||
|
**Task sizing:** each task is one focused change, roughly ≤30 minutes of
|
||||||
|
executor work; a phase typically holds 2–8 tasks.
|
||||||
|
|
||||||
|
**Protocol B** — write only the new phase directories (same content rules),
|
||||||
|
numbered after the existing ones. Do not touch `.agent/PLAN.md`,
|
||||||
|
`AGENTS.md`, or existing phases; note in the final summary that `PLAN.md`'s
|
||||||
|
roadmap table does not list these appended phases.
|
||||||
|
|
||||||
|
## Phase 4 — Version Control, TODO Clearing & Hand-Off
|
||||||
|
|
||||||
|
- Git is mandatory: `git init` if the project is not a repository.
|
||||||
|
- **Clear the TODO list** — the items are now phases, so the TODO file no
|
||||||
|
longer holds the plan. Replace its entire item list with a one-line
|
||||||
|
pointer (e.g. `Phased on YYYY-MM-DD — items now live in
|
||||||
|
.agent/phases/todo/`); never delete the file itself.
|
||||||
|
- Commit the conversion — `AGENTS.md`, the cleared TODO file, and any other
|
||||||
|
modified non-`.agent/` files (the `.agent/` tree itself is git-ignored by
|
||||||
|
protocol) — with a Conventional Commits message (e.g. `chore(agent): phase
|
||||||
|
roadmap from TODO.md, NN phases`), always with `--no-gpg-sign`.
|
||||||
|
|
||||||
|
Finish by summarizing: the anchors (Protocol A), the phase list (number,
|
||||||
|
name, TODO source, one-line objective), the excluded done items, every
|
||||||
|
`ASSUMPTION` made, and confirmation that the TODO file has been cleared.
|
||||||
|
Then hand off:
|
||||||
|
|
||||||
|
- **Execute:** the `phased-execution` skill — `run-task.sh` for a single
|
||||||
|
task, `run-phase.sh` for a phase, `auto-phase.sh` for the full pipeline.
|
||||||
|
- **Extend:** the `phase-authoring` skill for individual additional phases.
|
||||||
|
|
||||||
|
## Strict Operational Rules
|
||||||
|
|
||||||
|
- The conversion writes **planning files**: `.agent/**`, `AGENTS.md`, and
|
||||||
|
`.gitignore`. **Never modify application code.** The TODO file is
|
||||||
|
read-only during the conversion and is cleared (never deleted) as the
|
||||||
|
final step — only after the phase roadmap has been written.
|
||||||
|
- Never overwrite existing `.agent/` content — merge into it. Never modify
|
||||||
|
anything in `.agent/phases/complete/`.
|
||||||
|
- In Protocol B, never modify `.agent/PLAN.md` or `AGENTS.md`.
|
||||||
|
- Do not create `.agent/validate.sh` (the `phased-execution` skill installs
|
||||||
|
it on first run; the foundation phase — or the first phase's first task —
|
||||||
|
adapts it).
|
||||||
|
- Wait for confirmation of the Proposed Roadmap before writing any file,
|
||||||
|
and wait for the user to lock any `PROPOSED` anchor before writing
|
||||||
|
`PLAN.md`.
|
||||||
|
- Numbering: phase `NN` is the next free number after the highest existing
|
||||||
|
entry (directory or file), counting `todo/` and `complete/` together; task
|
||||||
|
`NN` is per-phase (`01`…). Never reuse or collide a number.
|
||||||
|
- **Executable in isolation:** an agent that sees only the repository, the
|
||||||
|
phase overview, the completed task files, and one task file — no chat
|
||||||
|
history, no follow-ups — must be able to finish that task. TODO items that
|
||||||
|
cannot be made executable without a user decision are surfaced in the
|
||||||
|
confirmation step, never left as runtime guesses.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Phase {{NN}} — {{Short Title}}
|
||||||
|
|
||||||
|
**Source:** `{{TODO file}} L{{range(s) the phase's tasks cover, e.g. 34–38, 41}} — "{{capability / section title}}"`
|
||||||
|
**Story:** `{{.agent/user_stories/<story>.md or "n/a"}}`
|
||||||
|
**Context:** `{{PLAN.md sections / files this phase builds on}}`
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
{{1–3 sentences: what this phase delivers}}
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- `{{NN_name}}` ({{complete|todo}}) — {{what is needed from it}}
|
||||||
|
{{or "— (none)"}}
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
1. `01_{{short_name}}.md` — {{one-line summary}}
|
||||||
|
2. `02_{{short_name}}.md` — {{one-line summary}}
|
||||||
|
|
||||||
|
## Testing & Quality
|
||||||
|
- Unit/integration: {{tests required for all new logic — name the behaviors to cover}}
|
||||||
|
- Coverage: **>90%** on new/modified code
|
||||||
|
{{project additions, e.g. a dedicated Playwright E2E suite run in isolation by this phase's final pass}}
|
||||||
|
|
||||||
|
## Completion Criteria
|
||||||
|
- [ ] {{observable check: command to run / endpoint to hit / artifact to exist}}
|
||||||
|
- [ ] test suite green, coverage >90%
|
||||||
|
- [ ] no behavior change in completed phases
|
||||||
|
{{project additions, e.g. a commit command per AGENTS.md conventions}}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# {{Project Name}} — Master Plan
|
||||||
|
|
||||||
|
> Master design document for a phased-execution project. The phase roadmap
|
||||||
|
> below was derived from `{{TODO file}}` on {{date}}; each phase overview and
|
||||||
|
> task file cites its source lines in that file. The **LOCKED DECISIONS**
|
||||||
|
> below are binding: no phase may introduce technology outside them without
|
||||||
|
> explicit user permission.
|
||||||
|
|
||||||
|
## Assumptions & Design Principles
|
||||||
|
- {{...}}
|
||||||
|
|
||||||
|
## Architectural Anchors
|
||||||
|
| COMPONENT | DECISION | RATIONALE | STATUS |
|
||||||
|
|-----------|----------|-----------|--------|
|
||||||
|
| {{component}} | {{decision — inherited from the existing codebase}} | {{why}} | LOCKED |
|
||||||
|
| {{component}} | {{decision awaiting ratification}} | {{why}} | PROPOSED |
|
||||||
|
|
||||||
|
## High-Level Architecture
|
||||||
|
{{Component breakdown and data flow, mirroring the actual code.}}
|
||||||
|
|
||||||
|
## Data Model
|
||||||
|
{{Existing schemas, state transitions, and persistence details.}}
|
||||||
|
|
||||||
|
## Validation / Verification Workflow
|
||||||
|
{{Multi-step logic ensuring high-confidence outputs (unit → integration →
|
||||||
|
contract/E2E → coverage floor).}}
|
||||||
|
|
||||||
|
## Phase Roadmap
|
||||||
|
| # | Phase | TODO source | Objective (one line) |
|
||||||
|
|---|-------|-------------|----------------------|
|
||||||
|
| 01 | {{NN_name}} | — | foundation: adapt validate.sh, green test baseline (where applicable) |
|
||||||
|
| 02 | {{NN_name}} | `{{TODO file}} L{{a}}–L{{b}}` | {{...}} |
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Task {{NN}} — {{Short Title}}
|
||||||
|
|
||||||
|
**Phase:** `{{NN_phase}}` · **Source:** `{{TODO file}}:{{line(s), e.g. 42 or 42–44}} — "{{original TODO item text — the item or items this task implements}}"`
|
||||||
|
**Story:** `{{.agent/user_stories/<story>.md or "n/a"}}`
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
{{1–2 sentences: what this task delivers}}
|
||||||
|
|
||||||
|
## Work
|
||||||
|
1. `{{path/to/file}}` — {{specific change, file-level detail}}
|
||||||
|
2. `{{path/to/file}}` — {{specific change}}
|
||||||
|
{{for every decision the TODO item left open: "- ASSUMPTION: {{what was left open and the choice made}}"}}
|
||||||
|
|
||||||
|
## Testing & Quality
|
||||||
|
- Unit/integration: {{tests required for this task's logic}}
|
||||||
|
- Coverage: **>90%** on this task's new/modified code
|
||||||
|
|
||||||
|
## Completion Criteria
|
||||||
|
- [ ] {{observable check: command to run / endpoint to hit / artifact to exist}}
|
||||||
|
- [ ] full test suite green
|
||||||
|
- [ ] no behavior change in completed work
|
||||||
Executable
+241
@@ -0,0 +1,241 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# todo-audit.sh — TODO file & phased-readiness probe for the TODO Architect.
|
||||||
|
#
|
||||||
|
# Locates a TODO.md / TODO.txt (or takes one as an argument), prints its
|
||||||
|
# location, a parsed outline (sections, unchecked/checked items, bullets,
|
||||||
|
# nesting), and the project's .agent/ state, next free phase number
|
||||||
|
# (counting .agent/phases/todo/ and complete/ together, zero-padded to 2
|
||||||
|
# digits), git state, and test tooling.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bash todo-audit.sh [path/to/TODO.(md|txt)]
|
||||||
|
# bash todo-audit.sh # auto-detect in cwd and git root
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
# --- locate the TODO file ------------------------------------------------------
|
||||||
|
todo=""
|
||||||
|
if [[ $# -ge 1 ]]; then
|
||||||
|
[[ -f "$1" ]] || { echo "✗ ERROR: not a file: $1" >&2; exit 1; }
|
||||||
|
todo="$1"
|
||||||
|
else
|
||||||
|
# search the git root first, then cwd and its ancestors (up to the git
|
||||||
|
# root, or 3 levels when not in a repo)
|
||||||
|
dirs=()
|
||||||
|
gr="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
||||||
|
if [[ -n "$gr" ]]; then
|
||||||
|
dirs+=("$gr")
|
||||||
|
d="$(pwd)"
|
||||||
|
while [[ "$d" != "$gr" && "$d" != "/" ]]; do
|
||||||
|
dirs+=("$d")
|
||||||
|
d="$(dirname "$d")"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
d="$(pwd)"
|
||||||
|
for _ in 0 1 2 3; do
|
||||||
|
[[ "$d" == "/" ]] && break
|
||||||
|
dirs+=("$d")
|
||||||
|
d="$(dirname "$d")"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
for r in "${dirs[@]}"; do
|
||||||
|
[[ -d "$r" ]] || continue
|
||||||
|
for f in "$r"/*; do
|
||||||
|
[[ -f "$f" ]] || continue
|
||||||
|
b="$(basename "$f" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
case "$b" in
|
||||||
|
todo.md|todo.txt) todo="$f"; break 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$todo" ]]; then
|
||||||
|
echo "no TODO.md / TODO.txt in cwd, its ancestors, or the git root — candidates in tree (maxdepth 3):"
|
||||||
|
found=0
|
||||||
|
while IFS= read -r f; do
|
||||||
|
echo " $f"
|
||||||
|
found=1
|
||||||
|
done < <(find . -maxdepth 3 \( -name .git -o -name node_modules -o -name .venv \) -prune -o -type f -iname 'todo.*' -print 2>/dev/null)
|
||||||
|
(( found )) || echo " (none found — pass the file path as an argument)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# project root: git toplevel of the TODO file's directory, else that directory
|
||||||
|
tdir="$(cd "$(dirname "$todo")" && pwd)"
|
||||||
|
gr2="$(git -C "$tdir" rev-parse --show-toplevel 2>/dev/null || true)"
|
||||||
|
if [[ -n "$gr2" ]]; then root="$gr2"; else root="$tdir"; fi
|
||||||
|
|
||||||
|
ext="markdown"
|
||||||
|
[[ "$todo" == *.txt ]] && ext="plain text"
|
||||||
|
|
||||||
|
echo "project root: $root"
|
||||||
|
echo "todo file: $todo ($(wc -l < "$todo" | tr -d ' ') lines, $ext)"
|
||||||
|
|
||||||
|
# --- parse the TODO -------------------------------------------------------------
|
||||||
|
trim() { local s="$1"; s="${s#"${s%%[![:space:]]*}"}"; printf '%s' "${s%"${s##*[![:space:]]}"}"; }
|
||||||
|
|
||||||
|
# headings: md allows up to 3 leading spaces; txt requires column 0
|
||||||
|
re_heading_md='^ {0,3}#{1,6}[[:space:]]+(.*)$'
|
||||||
|
re_heading_txt='^#{1,6}[[:space:]]+(.*)$'
|
||||||
|
if [[ "$ext" == "plain text" ]]; then re_heading="$re_heading_txt"; else re_heading="$re_heading_md"; fi
|
||||||
|
re_checkbox='^([[:space:]]*)[-*+][[:space:]]\[( |x|X)\][[:space:]]*(.*)$'
|
||||||
|
re_bullet='^([[:space:]]*)[-*+][[:space:]]+(.*)$'
|
||||||
|
re_numbered='^([[:space:]]*)[0-9]+[.)][[:space:]]+(.*)$'
|
||||||
|
|
||||||
|
ln=0 sections=0 top_items=0 nested_items=0 checked=0 detail=0 maxdepth=0
|
||||||
|
outline=()
|
||||||
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||||
|
ln=$((ln + 1))
|
||||||
|
line="${line%$'\r'}"
|
||||||
|
[[ -z "${line//[[:space:]]/}" ]] && continue
|
||||||
|
|
||||||
|
if [[ "$line" =~ $re_heading ]]; then
|
||||||
|
sections=$((sections + 1))
|
||||||
|
outline+=("L$ln: # $(trim "${BASH_REMATCH[1]}")")
|
||||||
|
elif [[ "$line" =~ $re_checkbox ]]; then
|
||||||
|
d=$(( ${#BASH_REMATCH[1]} / 2 ))
|
||||||
|
(( d > maxdepth )) && maxdepth=$d
|
||||||
|
case "${BASH_REMATCH[2]}" in
|
||||||
|
x|X) checked=$((checked + 1)); m="[x]" ;;
|
||||||
|
*) (( d > 0 )) && nested_items=$((nested_items + 1)) || top_items=$((top_items + 1)); m="[ ]" ;;
|
||||||
|
esac
|
||||||
|
outline+=("L$ln: $m $(trim "${BASH_REMATCH[3]}")")
|
||||||
|
elif [[ "$line" =~ $re_bullet ]]; then
|
||||||
|
d=$(( ${#BASH_REMATCH[1]} / 2 ))
|
||||||
|
(( d > maxdepth )) && maxdepth=$d
|
||||||
|
(( d > 0 )) && nested_items=$((nested_items + 1)) || top_items=$((top_items + 1))
|
||||||
|
outline+=("L$ln: - $(trim "${BASH_REMATCH[2]}")")
|
||||||
|
elif [[ "$line" =~ $re_numbered ]]; then
|
||||||
|
d=$(( ${#BASH_REMATCH[1]} / 2 ))
|
||||||
|
(( d > maxdepth )) && maxdepth=$d
|
||||||
|
(( d > 0 )) && nested_items=$((nested_items + 1)) || top_items=$((top_items + 1))
|
||||||
|
outline+=("L$ln: n. $(trim "${BASH_REMATCH[2]}")")
|
||||||
|
elif [[ "$ext" == "plain text" ]]; then
|
||||||
|
top_items=$((top_items + 1))
|
||||||
|
outline+=("L$ln: · $(trim "$line")")
|
||||||
|
else
|
||||||
|
detail=$((detail + 1))
|
||||||
|
if [[ "$line" =~ ^[[:space:]]{2,} ]]; then
|
||||||
|
outline+=("L$ln: (detail) $(trim "$line")")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$todo"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "todo stats:"
|
||||||
|
echo " sections: $sections"
|
||||||
|
printf ' top-level work items (-> tasks): %s\n' "$top_items"
|
||||||
|
printf ' nested sub-items (-> task work steps): %s\n' "$nested_items"
|
||||||
|
printf ' done items [x] (excluded): %s\n' "$checked"
|
||||||
|
echo " detail/prose lines: $detail"
|
||||||
|
echo " max nesting depth: $maxdepth"
|
||||||
|
|
||||||
|
echo
|
||||||
|
if (( ${#outline[@]} > 150 )); then
|
||||||
|
echo "todo outline (first 150 of ${#outline[@]} structural lines):"
|
||||||
|
printf '%s\n' "${outline[@]:0:150}"
|
||||||
|
else
|
||||||
|
echo "todo outline (${#outline[@]} structural lines):"
|
||||||
|
printf '%s\n' ${outline[@]+"${outline[@]}"}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- .agent state -----------------------------------------------------------------
|
||||||
|
echo
|
||||||
|
echo ".agent state:"
|
||||||
|
a=0
|
||||||
|
if [[ -f "$root/.agent/PLAN.md" ]]; then
|
||||||
|
echo " .agent/PLAN.md: present"
|
||||||
|
a=1
|
||||||
|
fi
|
||||||
|
if [[ -f "$root/AGENTS.md" ]]; then
|
||||||
|
echo " AGENTS.md: present"
|
||||||
|
a=1
|
||||||
|
fi
|
||||||
|
if [[ -f "$root/.agent/validate.sh" ]]; then
|
||||||
|
echo " .agent/validate.sh: present"
|
||||||
|
a=1
|
||||||
|
fi
|
||||||
|
todo_dir="$root/.agent/phases/todo"
|
||||||
|
complete_dir="$root/.agent/phases/complete"
|
||||||
|
list_phases() {
|
||||||
|
local dir="$1" entry n t any=0
|
||||||
|
for entry in "$dir"/*; do
|
||||||
|
if [[ ! -e "$entry" ]]; then continue; fi
|
||||||
|
n="$(basename "$entry")"
|
||||||
|
if [[ "$n" =~ ^[0-9] ]]; then
|
||||||
|
if [[ -d "$entry" ]]; then
|
||||||
|
t="$(ls -1 "$entry" 2>/dev/null | grep -cE '\.md$' || true)"
|
||||||
|
echo " $n/ ($t file(s): 00_phase.md + tasks)"
|
||||||
|
else
|
||||||
|
echo " $n (legacy single-file phase)"
|
||||||
|
fi
|
||||||
|
any=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if (( ! any )); then echo " (empty)"; fi
|
||||||
|
}
|
||||||
|
if [[ -d "$todo_dir" ]]; then
|
||||||
|
echo " .agent/phases/todo:"
|
||||||
|
list_phases "$todo_dir"
|
||||||
|
a=1
|
||||||
|
fi
|
||||||
|
if [[ -d "$complete_dir" ]]; then
|
||||||
|
echo " .agent/phases/complete:"
|
||||||
|
list_phases "$complete_dir"
|
||||||
|
a=1
|
||||||
|
fi
|
||||||
|
if (( ! a )); then echo " (no .agent/ artifacts — Protocol A full conversion needed)"; fi
|
||||||
|
|
||||||
|
max=0
|
||||||
|
for d in "$todo_dir" "$complete_dir"; do
|
||||||
|
[[ -d "$d" ]] || continue
|
||||||
|
for entry in "$d"/*; do
|
||||||
|
if [[ ! -e "$entry" ]]; then continue; fi
|
||||||
|
n="$(basename "$entry" .md)"
|
||||||
|
if [[ "$n" =~ ^([0-9]+) ]]; then
|
||||||
|
n=$((10#${BASH_REMATCH[1]}))
|
||||||
|
if (( n > max )); then max=$n; fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
echo " next phase number: $(printf '%02d' $((max + 1)))"
|
||||||
|
|
||||||
|
# --- version control ----------------------------------------------------------------
|
||||||
|
echo
|
||||||
|
echo "version control:"
|
||||||
|
if [[ -d "$root/.git" ]]; then
|
||||||
|
branch="$(git -C "$root" branch --show-current 2>/dev/null || echo unknown)"
|
||||||
|
dirty="$(git -C "$root" status --porcelain 2>/dev/null | wc -l | tr -d ' ')"
|
||||||
|
echo " git repository (branch: ${branch:-detached}, uncommitted changes: ${dirty})"
|
||||||
|
else
|
||||||
|
echo " (not a git repository — the conversion must git init)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- test tooling --------------------------------------------------------------------
|
||||||
|
echo
|
||||||
|
echo "test tooling:"
|
||||||
|
t=0
|
||||||
|
if [[ -f "$root/pytest.ini" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -q '\[tool\.pytest' "$root/pyproject.toml"; }; then
|
||||||
|
echo " pytest configured"
|
||||||
|
t=1
|
||||||
|
fi
|
||||||
|
if [[ -f "$root/conftest.py" ]] || [[ -d "$root/tests" ]]; then
|
||||||
|
echo " tests/ or conftest.py present"
|
||||||
|
t=1
|
||||||
|
fi
|
||||||
|
n_py="$(find "$root" \( -name 'test_*.py' -o -name '*_test.py' \) -not -path '*/.git/*' -not -path '*/node_modules/*' -not -path '*/.venv/*' -not -path '*/venv/*' 2>/dev/null | wc -l | tr -d ' ')"
|
||||||
|
if (( n_py > 0 )); then echo " $n_py python test file(s)"; t=1; fi
|
||||||
|
if [[ -f "$root/package.json" ]] && grep -q '"test"' "$root/package.json"; then
|
||||||
|
echo " npm test script"
|
||||||
|
t=1
|
||||||
|
fi
|
||||||
|
if [[ -f "$root/ruff.toml" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -q '\[tool\.ruff\]' "$root/pyproject.toml"; }; then
|
||||||
|
echo " ruff configured"
|
||||||
|
t=1
|
||||||
|
fi
|
||||||
|
if [[ -f "$root/.coveragerc" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -qE '\[tool\.(coverage|pytest-cov)\]' "$root/pyproject.toml"; }; then
|
||||||
|
echo " coverage configured"
|
||||||
|
t=1
|
||||||
|
fi
|
||||||
|
if (( ! t )); then echo " (none detected — a 01_foundation phase must establish a test baseline)"; fi
|
||||||
Reference in New Issue
Block a user