diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ced8f3..6076c5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ Please choose versions by [Semantic Versioning](http://semver.org/). * MINOR version when you add functionality in a backwards-compatible manner, and * PATCH version when you make backwards-compatible bug fixes. +## Unreleased + +- feat(command): add `/vault-cli:plan-goal` slash command — goal-side planning gate mirroring `plan-task`; validates the required decision sections (`# Success Criteria` / `# Definition of Done` / `# Non-goals`) and that every `# Tasks` wikilink resolves to an existing task file (skipping inline-code spans), runs `goal-auditor`, leaves the goal at `phase: planning`, and hands off to `execute-goal` (never flips phase itself) +- feat(command): add `/vault-cli:execute-goal` slash command — goal-side execution gate + task-drain driver mirroring `execute-task`; re-runs plan-goal's hard checks, flips `phase: planning → execution` on a clean plan, then recommends the next open task (first `# Tasks` wikilink whose task file is not `completed`/`aborted`) one at a time until the goal drains, then points to `verify-goal` → `complete-goal`. Recommends only — never runs the task + ## v0.100.0 - feat(domain): add `GoalPhase` string-enum type with four canonical values (`todo`/`planning`/`execution`/`done`), mirroring `TaskPhase` but with no aliases — foundation for goal phase validation in a later prompt diff --git a/README.md b/README.md index 295149a..dedd4a0 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,8 @@ claude plugin update vault-cli@vault-cli | `/vault-cli:execute-task` | Hard gate `phase: planning → execution` — re-runs plan-task's 4 hard non-negotiables, on pass flips phase + prints first unchecked subtask + DoD reminder. Idempotent on `phase: execution` | | `/vault-cli:verify-goal` | Quick goal validation (status, subtasks) | | `/vault-cli:audit-goal` | Full goal audit against Goal Writing Guide | +| `/vault-cli:plan-goal` | Validate required sections + that every `# Tasks` wikilink resolves to an existing task file, via goal-auditor; conversationally fill gaps; leaves `phase: planning` and hands off to `/execute-goal` (never flips phase itself) | +| `/vault-cli:execute-goal` | Gate `phase: planning → execution` — re-runs plan-goal's 3 hard checks, on pass flips phase + recommends the next open task one at a time until the goal drains, then points to `/verify-goal` → `/complete-goal`. Recommends only, never runs the task | | `/vault-cli:verify-theme` | Quick theme validation (structure, sections) | | `/vault-cli:audit-theme` | Full theme audit against Theme Writing Guide | | `/vault-cli:audit-objective` | Full objective audit against Objective Writing Guide | diff --git a/commands/execute-goal.md b/commands/execute-goal.md new file mode 100644 index 0000000..0007bf5 --- /dev/null +++ b/commands/execute-goal.md @@ -0,0 +1,153 @@ +--- +description: Gate planning → execution for a goal. Re-runs plan-goal's hard checks; on pass flips phase and recommends the next open task (one at a time) until the goal drains. Recommends only — never runs the task. +argument-hint: " (or detects from conversation)" +allowed-tools: [Read, Edit, Glob, Bash, AskUserQuestion, Task] +--- + +The **hard gate** between a goal's planning and execution, and the driver that walks its tasks one at a time. Refuses to flip `phase: planning → execution` unless plan-goal's 3 hard checks pass. Idempotent on `phase: execution` — re-run it to surface the next open task. It **recommends** the next task; the normal task lifecycle (`/vault-cli:work-on-task` → `plan-task` → `execute-task` → `complete-task`) does the work in between. + +This command **must stay inline** — it analyzes the parent conversation when no argument is given; a sub-agent cannot see the conversation. + +## When to use + +After `/vault-cli:plan-goal` (or any time the goal plan is genuinely complete) to formally enter execution and get pointed at the first task. Re-run after finishing a task to get the next one, until the goal drains. + +```bash +/vault-cli:execute-goal # detects from conversation +/vault-cli:execute-goal "Some Goal Name" +/vault-cli:execute-goal 23\ Goals/Some\ Goal.md +``` + +## Process + +### 1. Resolve goal path + +**With argument:** exact path if path-like, else `Glob` `/**.md` (vault-cli config respected). Multiple matches → list and STOP. Zero → STOP. + +**Without argument — detect from conversation** (same priority order as `/plan-goal`): + +1. Most recent `/create-goal` / `/launch-goal` / `/plan-goal` / `/work-on-goal` output — scan the parent conversation for the resolved goal name. +2. Most recent `[[Goal Name]]` wikilink referenced as a goal subject. +3. Most recently modified file in `/`. + +Multiple matches → ask via `AskUserQuestion`. Zero → `❌ No goal detected. Pass a goal identifier or name.` STOP. + +Print `Detected goal: ` on first line so owner can interrupt before any state mutation. + +### 2. Read status + phase + +```bash +vault-cli goal get "" status --output json +vault-cli goal get "" phase --output json +``` + +### 3. Refusal cases (no mutation, exit non-zero) + +Refuse and STOP if any apply: + +- `status: completed` OR `status: aborted` → `❌ Goal closed (status: ). Run reopen if you need to continue work.` +- `phase: done` → `❌ Goal phase is done. Run reopen if work needs to resume.` +- `phase: todo` OR `phase` empty AND `status: in_progress` → `❌ Planning gate not run. Run /vault-cli:plan-goal first.` (planning is non-skippable) + +### 4. Status entry contract (mutate, then continue) + +If `status` is in `next` / `backlog` / `hold` → flip to `in_progress`: +```bash +vault-cli goal set "" status in_progress +``` +Print: `ℹ️ Status: → in_progress (resume from )` + +If `status` is already `in_progress` → continue, no mutation. + +### 5. Run plan-goal's 3 hard checks (re-check planning) + +Copy the *Hard* checks from `/vault-cli:plan-goal` § 5 — DO NOT factor into a shared helper yet (keeps both commands self-contained; lift to a `vault-cli goal verify-plan` CLI verb if a third caller appears). Read `~/.claude/plugins/marketplaces/vault-cli/docs/goal-writing.md` as the canonical rule source. + +Check (in order, collect ALL failures — don't short-circuit): + +1. **Required sections present** — each of `# Success Criteria`, `# Definition of Done`, `# Non-goals` exists as a heading. Report each missing section by name. +2. **Success Criteria binary** — `# Success Criteria` has ≥ 2 binary checkboxes (`- [ ]` / `- [x]`). +3. **Every `# Tasks` wikilink resolves** — each `[[Task Title]]` in the `# Tasks` section resolves to an existing `/.md` (skip `[[...]]` inside inline-code spans; strip `|alias` display text). Report each unresolved task by name. + +### 6. Phase transition or refusal + +**If ANY hard check failed AND `phase: planning`:** + +Print: +``` +❌ Plan not ready. Run /vault-cli:plan-goal first. + +Failed checks: +- : +... +``` +STOP. Do NOT flip phase. + +**If all hard checks pass AND `phase: planning`:** + +```bash +vault-cli goal set "" phase execution +``` +Print: `✅ Phase: planning → execution` + +Continue to step 7. + +**If `phase: execution`:** no flip, no check (already past the gate). Continue to step 7 idempotently. Print: `ℹ️ Already in execution — surfacing the next task.` + +### 7. Recommend the next open task (or signal drain-complete) — final output + +Walk the `# Tasks` section's wikilinks **in listed order**. For each `[[Task Title]]` (inline-code spans skipped, `|alias` stripped), resolve to `/.md` and read its status: + +```bash +vault-cli task get "" status --output json +``` + +- **No task wikilinks at all** under `# Tasks` → `⚠ No tasks listed under # Tasks — nothing to execute. Run /vault-cli:plan-goal to add at least one.` (do NOT report a false "drained"). STOP. +- **A wikilink that no longer resolves** to an existing task file (e.g. the task was renamed/deleted after the goal entered execution — the resolution check in step 5 only runs on the `planning` path) → `⚠ Task file missing: [[]] — re-run /vault-cli:plan-goal to repair the # Tasks list.` Report it and skip that entry rather than erroring mid-walk; continue evaluating the rest. +- **Next open task** = the first *resolving* task whose status is NOT `completed` and NOT `aborted`. Recommend exactly that one: + + ``` + 🎯 Next task: [[<Task Title>]] (status: <status>) + + → Run /vault-cli:work-on-task "<Task Title>" to start it. + ``` + + Recommend **one** task only — not the whole list. `execute-goal` never runs the task; the operator drives it through the task lifecycle, then re-runs `/vault-cli:execute-goal` for the next one. + +- **All tasks complete** (every `# Tasks` wikilink resolves to a task with status `completed`, none `aborted` pending) → the goal has drained: + + ``` + ✅ All tasks complete — the goal has drained. + + → Run /vault-cli:verify-goal to confirm the Success Criteria, then /vault-cli:complete-goal to close it. + ``` + +- **Only aborted tasks remain** (no open task, but ≥1 `aborted`) → print `⚠ Remaining tasks are aborted: <names>. Re-plan (/vault-cli:plan-goal) or complete the goal if the aborted work is intentionally dropped.` + +## Notes + +- **Recommends, never runs.** `execute-goal` surfaces the next task and stops. The task lifecycle (`work-on-task` → `plan-task` → `execute-task` → `complete-task`) does the actual work — keeping the operator in the loop between tasks (per the goal's design; no autonomous drain). +- **Idempotent re-entry.** Safe to re-run on `phase: execution` — no mutation, just re-computes the next open task from live task statuses. This is how you walk the goal: finish a task, re-run `execute-goal`, get the next. +- **Task completion is derived, not stored on the goal.** The goal's `# Tasks` list is wikilinks, not checkboxes; "done" is read from each linked task file's `status: completed`. This keeps a single source of truth (the task file) and means the goal auto-reflects task progress with no manual ticking. +- **Hard checks duplicated, not shared.** The 3 plan-goal checks are re-implemented inline rather than factored into a shared verb. Keeps both commands self-contained; revisit if a third caller needs the same logic. +- **Planning is non-skippable.** A goal in `status: in_progress, phase: todo` (or empty phase) is refused with a pointer to `/plan-goal`. Blocks, unlike `/work-on-goal`'s informational nudge. +- **Reads `~/.claude/plugins/marketplaces/vault-cli/docs/goal-writing.md`** as the canonical rule source for the 3 hard checks — same source `/plan-goal` and `goal-auditor` use. + +## Integration + +Goal lifecycle: + +1. `/vault-cli:create-goal` / `/vault-cli:launch-goal` — capture / frame +2. `/vault-cli:work-on-goal` — orient (pick a task, get guides) +3. `/vault-cli:plan-goal` — sharpen (3 hard gates); never flips phase +4. **`/vault-cli:execute-goal`** — the gate; flips planning → execution + recommends the next open task, one at a time — this command +5. Work each task via the task lifecycle (`/vault-cli:work-on-task` → `plan-task` → `execute-task` → `complete-task`), then re-run `/vault-cli:execute-goal` for the next +6. `/vault-cli:verify-goal` → `/vault-cli:complete-goal` — confirm Success Criteria + close the goal once all tasks drain + +Output ends with one of: +- `🎯 Next task: [[<Title>]] → Run /vault-cli:work-on-task "<Title>".` (gate passed, task remaining) +- `✅ All tasks complete — the goal has drained. → /vault-cli:verify-goal → /vault-cli:complete-goal.` (drained) +- `❌ Plan not ready. Run /vault-cli:plan-goal first.` (hard checks failed) +- `❌ Planning gate not run. Run /vault-cli:plan-goal first.` (phase: todo) +- `❌ Goal closed (...).` (status/phase terminal) +- `❌ No goal detected. Pass a goal identifier or name.` (input error) diff --git a/commands/plan-goal.md b/commands/plan-goal.md new file mode 100644 index 0000000..b694211 --- /dev/null +++ b/commands/plan-goal.md @@ -0,0 +1,127 @@ +--- +description: Validate that a goal is well-formed — required sections present and every # Tasks wikilink resolves to an existing task file; conversationally fill gaps; leaves the goal at phase=planning and hands off to execute-goal (never flips phase itself). +argument-hint: "<goal-file-path-or-name> (or detects from conversation)" +allowed-tools: [Task, Read, Edit, Glob, Bash, AskUserQuestion] +--- + +Drive a goal to *execution-ready* through conversation. Checks that the goal has the required decision sections (`# Success Criteria`, `# Definition of Done`, `# Non-goals`) and that every task named in `# Tasks` actually exists as a file. Runs `goal-auditor` for findings, asks targeted questions, applies answers, loops until ready. Leaves the goal at `phase: planning` and points to `/vault-cli:execute-goal` to begin draining tasks — **plan-goal never flips the phase itself**; `execute-goal` owns the `planning → execution` transition. + +This command **must stay inline** — it analyzes the parent conversation when no argument is given; a sub-agent cannot see the conversation. + +## When to use + +Right after `/vault-cli:create-goal` or `/vault-cli:launch-goal` (capture/framing → plan strict), or any time a goal feels incomplete before you start working its tasks. The goal-side mirror of `/vault-cli:plan-task`. + +```bash +/vault-cli:plan-goal # detects from conversation (e.g. just after /launch-goal) +/vault-cli:plan-goal "Some Goal Name" +/vault-cli:plan-goal 23\ Goals/Some\ Goal.md +``` + +## Process + +### 1. Resolve goal path + +**With argument:** exact path if path-like, else `Glob` `<goals_dir>/*<arg>*.md` (vault-cli config respected). Multiple matches → list and STOP. Zero → STOP. + +**Without argument — detect from conversation** (in priority order): + +1. **Most recent `/create-goal` or `/launch-goal` output** — scan the parent conversation for `/vault-cli:create-goal "<name>"` / `/vault-cli:launch-goal "<name>"` (with or without slash) or its result line (`✅ Goal: <name>` / file-path output). If found and unambiguous, use that name. +2. **Most recent `[[Goal Name]]` wikilink** referenced in the conversation as a goal subject (not a generic mention in prose). Match against `<goals_dir>/`. +3. **Most recently modified file in `<goals_dir>/`** — final fallback. + +Resolve the detected name via `Glob` same as the with-argument path. Multiple matches → list candidates and ask owner via `AskUserQuestion` (single-question, short options). Zero → `❌ No goal detected. Pass a goal identifier or name.` STOP. + +When detection succeeds without explicit argument, print the resolved goal name on first line of output (`Detected goal: <name>`) so the owner can interrupt if wrong before any state mutation. + +### 2. Read status + phase + +```bash +vault-cli goal get "<name>" status --output json +vault-cli goal get "<name>" phase --output json +``` + +### 3. Entry contract — flip if needed + +The goal is to land at `status: in_progress, phase: planning` for fresh goals; respect a deliberate post-planning phase setting. + +- `status` in `next`/`todo`/`backlog` → flip status AND phase together: `vault-cli goal set "<name>" status in_progress` + `vault-cli goal set "<name>" phase planning` (if phase is empty/`todo`/`planning`). Skip the phase flip if phase is `execution` / `done` (treat as deliberate — sharpen but don't move phase backward). +- `status` already `in_progress` and `phase` is `todo`/empty → `vault-cli goal set "<name>" phase planning` +- `status` already `in_progress` and `phase` is past planning → continue without flip; step 7 will skip the phase transition. + +### 4. Run goal-auditor + +``` +Task tool with: + subagent_type: 'vault-cli:goal-auditor' + prompt: 'Audit <resolved-path>. Return: score (1-10), Critical Issues, Goal Scope Fit findings, Task-Goal Alignment, top 5 Recommendations.' +``` + +### 5. Check the non-negotiables + +Three checks beyond the auditor's general scoring — all hard (any failure → mandatory question in step 6, can't exit on auditor score alone). + +**Hard:** + +- **Required sections present** — each of `# Success Criteria`, `# Definition of Done`, `# Non-goals` exists as a heading. Report each missing section **by name**. +- **Success Criteria binary** — `# Success Criteria` section has ≥ 2 binary checkboxes (`- [ ]` / `- [x]`). +- **Every `# Tasks` wikilink resolves** — extract each `[[Task Title]]` from the `# Tasks` section and confirm a file `<tasks_dir>/<Task Title>.md` exists (vault-cli config `tasks_dir`; use `Glob`). Report each **unresolved task by name**. Two rules on extraction: + 1. **Skip inline-code spans** — a `[[wikilink]]` inside backticks (e.g. a literal example in prose) is NOT a task reference; exclude it. Only bare `[[...]]` in the `# Tasks` list counts. + 2. **Strip display aliases** — `[[Real Title|shown]]` resolves against `Real Title`. + + An unresolved wikilink is the goal-side equivalent of a missing subtask: the goal names work that has no home yet. The owner creates it (`/vault-cli:create-task "<title>"` or clicking the wikilink in Obsidian) before the goal is execution-ready. + +Any hard check failing → mandatory question in step 6; can't exit on auditor score alone. + +### 6. Surface gaps + fix loop + +Translate findings (auditor + non-negotiable checks) into questions. Rules: + +- Max 3 questions per turn +- Each question is short (one sentence) + tight options (single yes/no OR 2-4 numbered options) +- Lead with `(Recommended)` per global UX +- Quote the offending line/section so owner sees what triggered the question +- Use `AskUserQuestion` for the actual ask + +For a **missing section**, offer to scaffold it (from the goal template / `goal-writing.md` shape) or point the owner to fill it. For an **unresolved task wikilink**, offer: create the task now (`/vault-cli:create-task "<title>"`), remove the wikilink, or leave it (blocks execution-ready). Apply each answer via `Edit`. Re-run the auditor after each batch. Print delta `Score: X → Y`. Loop until score ≥ 8 AND all three hard non-negotiables pass OR owner says "good enough." + +### 7. Exit — hand off to execute-goal (no phase flip) + +**plan-goal never flips the phase.** It validates and reports; `/vault-cli:execute-goal` owns the `planning → execution` transition. This keeps each lifecycle command to one job and makes "start draining the tasks" a deliberate operator action. + +**Phase is `planning` AND score ≥ 8 AND hard non-negotiables pass:** + +Print: `✅ Plan ready. Score: X/10. Phase stays: planning. → Run /vault-cli:execute-goal to begin working the tasks.` + +**Phase is already past planning (execution / done):** + +Print: `✅ Goal sharpened. Score: X/10. Phase unchanged (was <phase>).` + +**Owner abort OR score < 8 after loop OR a hard check still failing:** + +Print: `⚠ Goal improved to X/10. Phase unchanged. Remaining: <bullets>. Re-run /vault-cli:plan-goal when ready.` + +## Notes + +- **Scope is focused on what blocks safe execution.** Plan-goal enforces three planning-gate checks (required sections present, SC binary, every task wikilink resolves) because each prevents a specific failure mode: an under-specified goal, unmeasurable success, and phantom tasks the goal names but never created. Other heuristics (SMART criteria, evidence shape, theme linkage, outcome-shaped title) stay in `goal-auditor` and `goal-writing.md` as canonical rules — surfaced via the auditor in step 4, not promoted to dedicated gates. Letting the auditor enforce general structure while plan-goal enforces the three named gates keeps the command short and the gates legible. +- **The task-wikilink gate is the signature goal check.** A goal is "planned" when the path from now to its Success Criteria is laid out as real, existing tasks. A `# Tasks` list pointing at files that don't exist is the goal-level equivalent of a task with no subtasks — the plan looks complete but there's nothing to execute. +- **No phase flip.** plan-goal never transitions phase; it validates and hands off to `/vault-cli:execute-goal`, which owns the `planning → execution` flip. Entry-contract flips (`next` → `in_progress` + `planning`) still happen in step 3. +- **Conversational on purpose.** Owner is the judge of substance. Plan-goal never silently rewrites; every change comes from an explicit answer. +- **Mechanical fixes stay in `/audit-goal`.** This command is for substance (sections, measurable SCs, real tasks), not formatting. + +## Integration + +Goal lifecycle: + +1. `/vault-cli:create-goal` / `/vault-cli:launch-goal` — capture / frame +2. `/vault-cli:work-on-goal` — orient (pick a task, get guides) +3. **`/vault-cli:plan-goal`** — sharpen (3 hard gates); never flips `planning → execution` — this command +4. `/vault-cli:execute-goal` — gate planning → execution; flips phase + recommends the next task +5. Work the tasks via the task lifecycle (`/vault-cli:work-on-task` → `plan-task` → `execute-task` → `complete-task`) +6. `/vault-cli:complete-goal` — close the goal when all tasks + success criteria are done + +Output ends with one of: +- `✅ Plan ready. Score: X/10. Phase stays: planning. → Run /vault-cli:execute-goal.` (planning success) +- `✅ Goal sharpened. Score: X/10. Phase unchanged (was <phase>).` (non-planning success) +- `⚠ Goal improved to X/10. Phase unchanged. Remaining: <bullets>. Re-run when ready.` (partial) +- `❌ No goal detected. Pass a goal identifier or name.` (input error)