diff --git a/CHANGELOG.md b/CHANGELOG.md index 14fd8f7..10c3966 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Please choose versions by [Semantic Versioning](http://semver.org/). ## Unreleased - fix: `/vault-cli:post-compact` now reads the anchor task's parent goal from the task file's own `goals:` frontmatter instead of trusting the checkpoint's `Goal:` line. That line is prose written at checkpoint time and validated against nothing, and a wrong goal name still returns a valid status — so the anchor check passed while the goal was misattributed for a whole session, including its success-criteria counts in every closer panel. +- fix: session-close offers "leave it open" as an anchor-task resolution — a task gated on a scheduled event is neither finished nor abandoned, and the previous complete/defer/hold menu had no correct option for it ## v0.126.0 diff --git a/commands/session-close.md b/commands/session-close.md index 321bc9b..0ed62bd 100644 --- a/commands/session-close.md +++ b/commands/session-close.md @@ -215,7 +215,7 @@ Interpret: - `STATUS_EXIT == 0` and parsed `value` field: - `status: completed` → ✅ silent OK - - `status: in_progress` → ⚠ **HARD flag**, *unless the created-this-session exclusion above applies* (check that first — it is the only exception, and it is decided before this bullet) — the session anchored on this task but never completed it. This is a blocker on the clean verdict, not a soft warning: it forces Phase 9 into mode 3 (outstanding) and must be the item named in the closer's `approve:` line. There is no "no action needed" / "correct, standing trigger" / "deliberate" annotation that downgrades an `in_progress` anchor task to clean — a task that is designed never to complete still blocks the clean close until the operator explicitly resolves it (complete / defer / hold / abort). Observed 2026-08-30: a standing-trigger anchor task stayed `in_progress` by design, session-close flagged it as outstanding but named a worktree-cleanup item as the `approve:` item instead, and the session closed `⚪ DONE` with the anchor unfinished. The task is the gate; no other item stands in for it. + - `status: in_progress` → ⚠ **HARD flag**, *unless the created-this-session exclusion above applies* (check that first — it is the only exception, and it is decided before this bullet) — the session anchored on this task but never completed it. This is a blocker on the clean verdict, not a soft warning: it forces Phase 9 into mode 3 (outstanding) and must be the item named in the closer's `approve:` line. There is no "no action needed" / "correct, standing trigger" / "deliberate" annotation that downgrades an `in_progress` anchor task to clean — a task that is designed never to complete still blocks the clean close until the operator explicitly resolves it (complete / defer / hold / abort, or explicitly chooses to leave it open). Note the difference: choosing to leave it open is a *resolution the operator makes*, stated in the output — it keeps the mode-3 verdict rather than clearing it, which is precisely what an "annotation" would wrongly do. Observed 2026-08-30: a standing-trigger anchor task stayed `in_progress` by design, session-close flagged it as outstanding but named a worktree-cleanup item as the `approve:` item instead, and the session closed `⚪ DONE` with the anchor unfinished. The task is the gate; no other item stands in for it. - created this session AND not anchored (see the exclusion above) → ✅ silent OK (follow-up filed for a later session, never this session's anchor) - `status: hold` / `status: aborted` → ✅ silent OK (deliberate non-completion, owner already decided) - `status: next` / `status: backlog` → ✅ silent OK (touched as a side-reference, not as an active anchor) @@ -224,9 +224,18 @@ Interpret: For each `in_progress` task that was **not** excluded above, surface in Phase 9 as outstanding: ``` -N. Task [[]] still in_progress — `/vault-cli:complete-task "<title>"` to finish, `/vault-cli:defer-task "<title>" <date>` to push out, or set status hold/aborted if abandoning +N. Task [[<title>]] still in_progress — `/vault-cli:complete-task "<title>"` to finish, `/vault-cli:defer-task "<title>" <date>` to push out, set status hold/aborted if abandoning, or **leave it open and say so plainly** ``` +**"Leave it open" is a real resolution, and often the only correct one.** A task gated on a scheduled event — a soak window, a deferred re-measure, a dated follow-up — is neither finished nor abandoned, and forcing a status flip to clear the flag records something false. Two of the three other options are actively wrong for it: + +- `hold` is for blocks with **no** resume date. Setting it on a task that resumes on a known date misstates the reason it is not moving. +- `defer` may be the operator's choice, but this command must not propose it — it is banned as a suggestion. + +So the flag stays (Phase 4.5 is still a hard block, and mode 3 still applies), the `approve:` line offers leaving it open, and the reason is stated in the output. What is forbidden is closing **silently** with an unresolved anchor, not closing with an anchor that is deliberately still open. + +Observed 2026-09-06: an anchor task was gated on a 48h verification window with a watcher already armed. The template offered only complete / defer / hold, so `hold` was proposed — contradicting the vault's own status semantics (*"never set `hold` for a task with a scheduled `defer_date`… reserve `hold` only for blocks with no scheduled resume date"*). The operator caught it with one word: *"why … hold?"* + For each task whose status lookup FAILED, surface in Phase 9 as outstanding: ``` @@ -251,7 +260,7 @@ Interpretation is identical to the task branch above — `completed` / `hold` / For each `in_progress` goal, surface in Phase 9 as outstanding — except the anchor goal of a goal-anchored session (Phase 1's `GOAL_ANCHORED`): see the goal-anchored exemption below. ``` -N. Goal [[<title>]] still in_progress — `/vault-cli:complete-goal "<title>"` to close, `/vault-cli:defer-goal "<title>" <date>` to push out, or set status hold/aborted if abandoning +N. Goal [[<title>]] still in_progress — `/vault-cli:complete-goal "<title>"` to close, `/vault-cli:defer-goal "<title>" <date>` to push out, set status hold/aborted if abandoning, or **leave it open and say so plainly** ``` For each goal whose status lookup FAILED: @@ -547,7 +556,7 @@ Omit any line with zero entries. If nothing was touched (e.g. talk-only session) **Verdict — three modes:** -**Mode gate (Phase 4.5 is a hard block, not a suggestion):** if any touched task is `in_progress`, modes 1 and 2 (the clean verdicts) are **forbidden** — the verdict MUST be mode 3 (outstanding), with that task as an outstanding item. An `in_progress` anchor task can never be annotated away ("no action needed", "standing trigger", "deliberate") into a clean verdict; the operator must resolve it (complete / defer / hold / abort) before the session can be suggested as closeable. Modes 1 and 2 are reachable only when every touched task is `completed`, `hold`, `aborted`, `next`, or `backlog`. +**Mode gate (Phase 4.5 is a hard block, not a suggestion):** if any touched task is `in_progress`, modes 1 and 2 (the clean verdicts) are **forbidden** — the verdict MUST be mode 3 (outstanding), with that task as an outstanding item. An `in_progress` anchor task can never be annotated away ("no action needed", "standing trigger", "deliberate") into a clean verdict; the operator must resolve it (complete / defer / hold / abort, or explicitly choose to leave it open) before the session can be suggested as closeable. Leaving it open is a resolution, not an annotation — the verdict stays mode 3 and the task stays on the list. Modes 1 and 2 are reachable only when every touched task is `completed`, `hold`, `aborted`, `next`, or `backlog`. **Goal-anchored sessions are exempt from the goal half of the gate.** The Phase 4.5 block above is about touched *tasks* — that stands unchanged. But an anchor goal left `in_progress` with open tasks does NOT force mode 3: it is the goal session's designed steady state, exempted in Phase 4.5. A goal-anchored session reaches the clean verdicts on the same task conditions as any session; the open goal is then reflected in the closer panel (below), never as an outstanding item — the one exception is a DRAINED anchor goal (all tasks terminal), which Phase 4.5 lists normally as outstanding (drained goals go through mode 3, not this path). @@ -609,7 +618,7 @@ Append below the verdict. This command is terminal; without a fixed closer the t ⏰ Next: /vault-cli:work-on-task "<next open task>" — <N> open task(s) remain under the goal ``` -**Outstanding items (mode 3):** `🔵 READY`, with `👤 You: approve:` naming exactly ONE item from the numbered list. **When an `in_progress` touched task is on the list, that task IS the item to name** — the `approve:` line must offer its resolution (`/vault-cli:complete-task "<title>"`, `/vault-cli:defer-task "<title>" <date>`, or set status hold/aborted), never a different item (a worktree cleanup, uncommitted files, a daemon). Naming any other item while the anchor task sits `in_progress` repeats the 2026-08-30 defect: the session closed `⚪ DONE` with the anchor unfinished. The task is the gate; no other item stands in for it. +**Outstanding items (mode 3):** `🔵 READY`, with `👤 You: approve:` naming exactly ONE item from the numbered list. **When an `in_progress` touched task is on the list, that task IS the item to name** — the `approve:` line must offer its resolution (`/vault-cli:complete-task "<title>"`, `/vault-cli:defer-task "<title>" <date>`, set status hold/aborted, or **leave it open and say so plainly**), never a different item (a worktree cleanup, uncommitted files, a daemon). Naming any other item while the anchor task sits `in_progress` repeats the 2026-08-30 defect: the session closed `⚪ DONE` with the anchor unfinished. The task is the gate; no other item stands in for it. **Never name a specific next task — in a task-anchored session.** For task sessions, never name a specific next task and never recommend `/vault-cli:next-task`: next-session anchor selection belongs to the orchestrator (or to the user opening a fresh session), not to this command. Same rationale as `sync-progress.md` Phase 6 — closing one task's session is the routine bookend between two task sessions, so the global "no end-of-day suggestions" rule does not apply here.