From 9dc2b83f0efe3494349e69c49c09c73f82f0e540 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Fri, 19 Jun 2026 18:00:51 +0200 Subject: [PATCH] feat(capitalize): merge /close into /capitalize + TODO reconcile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-mode capitalize: default pre-wipe flush, --ritual adds the 3-question end-of-session reflection (now deduped, unlike legacy /close). New STEP 2B reconciles .claude/tasks/TODO.md — PASS A done-detection (only on an unambiguous task<->commit map), PASS B explicit-only capture with an anti-noise filter (never track commit/deploy/push/release/tag) and BDR routing for orientation directives. STEP 3 gate gains a separate TODO block; journal/handoff report TODO ops. /close becomes a thin alias for /capitalize --ritual (zero duplicated logic). Built via superpowers:writing-skills TDD: RED baseline (no skill) folded a push/tag parasite into the TODO, invented a subtask, and wrote with no gate; GREEN re-run on the same fixture stops at the gate, drops both dups (footer shows existing IDs), logs one learning, checks only the cleanly-done task, ignores the parasite, and routes the GraphQL directive to BDR. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01X3e8LaH2vymmxyh36h3jFU --- hooks/caveman-statusline.ps1 | 61 -------- skills/capitalize/SKILL.md | 270 ++++++++++++++++++++++++----------- skills/close/SKILL.md | 141 +++--------------- 3 files changed, 209 insertions(+), 263 deletions(-) delete mode 100644 hooks/caveman-statusline.ps1 diff --git a/hooks/caveman-statusline.ps1 b/hooks/caveman-statusline.ps1 deleted file mode 100644 index 345749a..0000000 --- a/hooks/caveman-statusline.ps1 +++ /dev/null @@ -1,61 +0,0 @@ -$ClaudeDir = if ($env:CLAUDE_CONFIG_DIR) { $env:CLAUDE_CONFIG_DIR } else { Join-Path $HOME ".claude" } -$Flag = Join-Path $ClaudeDir ".caveman-active" -if (-not (Test-Path $Flag)) { exit 0 } - -# Refuse reparse points (symlinks / junctions) and oversized files. Without -# this, a local attacker could point the flag at a secret file and have the -# statusline render its bytes (including ANSI escape sequences) to the terminal -# every keystroke. -try { - $Item = Get-Item -LiteralPath $Flag -Force -ErrorAction Stop - if ($Item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) { exit 0 } - if ($Item.Length -gt 64) { exit 0 } -} catch { - exit 0 -} - -$Mode = "" -try { - $Raw = Get-Content -LiteralPath $Flag -TotalCount 1 -ErrorAction Stop - if ($null -ne $Raw) { $Mode = ([string]$Raw).Trim() } -} catch { - exit 0 -} - -# Strip anything outside [a-z0-9-] — blocks terminal-escape and OSC hyperlink -# injection via the flag contents. Then whitelist-validate. -$Mode = $Mode.ToLowerInvariant() -$Mode = ($Mode -replace '[^a-z0-9-]', '') - -$Valid = @('off','lite','full','ultra','wenyan-lite','wenyan','wenyan-full','wenyan-ultra','commit','review','compress') -if (-not ($Valid -contains $Mode)) { exit 0 } - -$Esc = [char]27 -if ([string]::IsNullOrEmpty($Mode) -or $Mode -eq "full") { - [Console]::Write("${Esc}[38;5;172m[CAVEMAN]${Esc}[0m") -} else { - $Suffix = $Mode.ToUpperInvariant() - [Console]::Write("${Esc}[38;5;172m[CAVEMAN:$Suffix]${Esc}[0m") -} - -# Savings suffix: on by default. Opt out via CAVEMAN_STATUSLINE_SAVINGS=0. -# Reads a pre-rendered string written by caveman-stats.js. Refuses reparse -# points and strips control bytes (matches statusline.sh hardening). Until -# /caveman-stats has run at least once, the suffix file is absent and nothing -# is rendered — safe default for fresh installs. -if ($env:CAVEMAN_STATUSLINE_SAVINGS -ne "0") { - $SavingsFile = Join-Path $ClaudeDir ".caveman-statusline-suffix" - if (Test-Path $SavingsFile) { - try { - $SavingsItem = Get-Item -LiteralPath $SavingsFile -Force -ErrorAction Stop - if (-not ($SavingsItem.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -and - $SavingsItem.Length -le 64) { - $Savings = (Get-Content -LiteralPath $SavingsFile -Raw -ErrorAction Stop).TrimEnd() - $Savings = ($Savings -replace '[\x00-\x1F]', '') - if ($Savings.Length -gt 0) { - [Console]::Write(" ${Esc}[38;5;172m$Savings${Esc}[0m") - } - } - } catch {} - } -} diff --git a/skills/capitalize/SKILL.md b/skills/capitalize/SKILL.md index ef79713..65690e8 100644 --- a/skills/capitalize/SKILL.md +++ b/skills/capitalize/SKILL.md @@ -1,17 +1,19 @@ --- name: capitalize description: | - Use when about to /clear or /compact and the current conversation holds - decisions, learnings, blockers, or eval results that were never written to - `.claude/memory/`. Use to flush important uncapitalized context before it is - wiped, or when unsure whether the session's insights already reached the - registries. NOT the fresh end-of-session ritual (that is /close) and NOT + Use when about to /clear or /compact, or when closing a session, and the + conversation holds decisions, learnings, blockers, eval results, or + finished/new TODO items not yet written to `.claude/memory/` or + `.claude/tasks/TODO.md`. Plain invocation = pre-wipe flush; `--ritual` (or the + word "close"/"ritual" in the request) = end-of-session reflection mode. NOT registry curation (that is /prune-memory). Triggers: "capitalize", "capitalise", "before clear", "before compact", "save before clear", "flush memory", "don't lose this", "what's not logged yet", "avant de clear", "avant compact", "sauvegarde avant clear", - "capitalise ce qui manque". -argument-hint: (none — scans the current conversation against .claude/memory/) + "capitalise ce qui manque", "close", "end session", "session close", + "ferme la session", "checkpoint memory", "what did we learn", "retro rapide", + "fin de journée". +argument-hint: "[--ritual] (scans conversation + git + TODO against .claude/memory/; --ritual adds the 3-question reflection)" allowed-tools: - Read - Edit @@ -22,27 +24,31 @@ allowed-tools: - AskUserQuestion --- -# /capitalize — Flush uncapitalized context before a wipe +# /capitalize — Flush uncapitalized context (two modes) -Salvage the registry-worthy insights from **this conversation** that were -never written down, right before `/clear` or `/compact` destroys them. +Salvage the registry-worthy insights from **this conversation** that were never +written down — before `/clear` or `/compact` destroys them, or as a deliberate +end-of-session ritual. Also reconciles `.claude/tasks/TODO.md` against what +actually shipped. -Operates on conversation memory + git state + the existing registries. Does -NOT re-read source code. +Operates on conversation memory + git state + the existing registries + the +TODO. Does NOT re-read source code. -## What makes this different from /close +## Modes -| Situation | Skill | -|-----------|-------| -| About to `/clear` or `/compact` — salvage what the session produced but never logged | **/capitalize** (this) | -| Deliberate end-of-session ritual, fresh 3-question prompt | `/close` | -| Registries too long / noisy — curate, merge, compress | `/prune-memory` | -| Token-compress one registry file | `/caveman:compress ` | +| Mode | How triggered | Adds | +|------|---------------|------| +| **default** (pre-wipe flush) | plain `/capitalize`, "before clear", "flush memory" | auto-scan + dedup + TODO reconcile | +| **--ritual** (session-close) | `--ritual` flag, OR `$ARGUMENTS` contains "close"/"ritual", OR invoked via `/close` | everything above **+ STEP 1B** 3-question reflection | -The signature move of THIS skill is **STEP 2 — DEDUP**: every candidate is -checked against what is already in the registries, and anything already -captured is dropped silently. `/close` does not dedup; it asks fresh. Running -`/capitalize` right after a `/close` should propose (near) nothing. +Detect the mode first. Both modes share the SAME dedup (STEP 2), TODO reconcile +(STEP 2B), and approval gate (STEP 3). The signature move is **STEP 2 — DEDUP**: +every candidate is checked against what is already in the registries, and +anything already captured is dropped (its existing ID shown in the footer). +Running `/capitalize` right after a ritual should propose (near) nothing. + +This skill is NOT `/prune-memory` (registry curation — merge, compress, +mark-superseded). It only appends. ## STEP 0 — PRECHECK @@ -50,6 +56,7 @@ captured is dropped silently. `/close` does not dedup; it asks fresh. Running ls .claude/memory/decisions.md .claude/memory/learnings.md \ .claude/memory/blockers.md .claude/memory/evals.md \ .claude/memory/journal.md 2>/dev/null +ls .claude/tasks/TODO.md 2>/dev/null ``` - `.claude/memory/` missing entirely → print and STOP (do NOT create here — @@ -58,8 +65,11 @@ ls .claude/memory/decisions.md .claude/memory/learnings.md \ ⚠️ .claude/memory/ absent. Lance `/onboard` (ou `/init-project`) pour créer les registres avant de capitaliser. ``` -- Some files missing → name them, create each from +- Some registry files missing → name them, create each from `~/.claude/templates/memory/.md`, continue. +- `.claude/tasks/TODO.md` missing → the TODO reconcile volet (STEP 2B) is + **skipped**. Do NOT create it (same posture as the registries). Registries + still run. ## STEP 1 — SCAN THE CONVERSATION @@ -83,34 +93,50 @@ git status --short date +%Y-%m-%d ``` -For each candidate, draft the fields the target registry's schema expects -(read the YAML header of that file if unsure — e.g. decisions need -decision/why/alternatives; blockers need friction/real_cause/solution/status). +For each candidate, draft the fields the target registry's schema expects (read +the YAML header of that file if unsure). **Skip the trivial.** If it is reversible in under 10 min with no cross-file -impact, it is not a decision. If it is a one-shot fact, not a reusable -pattern, it is not a learning. Noise hurts the every-session re-read. +impact, it is not a decision. If it is a one-shot fact, not a reusable pattern, +it is not a learning. Noise hurts the every-session re-read. **One incident → one primary registry.** Do not fan a single event across registries. A resolved gotcha that cost time is a *learning* (the reusable pattern) — not *also* a blocker. Open a blocker only when the friction is -unresolved, or when the friction itself (not the lesson) is the durable -record. The same event written to two registries is a near-duplicate in the +unresolved, or when the friction itself (not the lesson) is the durable record. +The same event written to two registries is a near-duplicate in the every-session re-read. +## STEP 1B — RITUAL REFLECTION (only in --ritual mode) + +Default mode skips this entirely. In ritual mode, after the auto-scan, force the +end-of-session reflection — three questions that surface what the scan may have +missed: + +1. **What did you decide?** → decisions.md (BDR) +2. **What did you learn?** → learnings.md (LRN) +3. **What blocked you?** → blockers.md (BLK) + +Each answer becomes an additional candidate. It does NOT bypass dedup: every +ritual answer flows into STEP 2 exactly like an auto-scanned candidate. A +reflection answer that is already captured is **dropped, and its existing +`` is shown in the footer** — same as any other dup, never re-logged. This +is the key difference from the legacy `/close`, which wrote ritual answers fresh +with no dedup. + ## STEP 2 — DEDUP AGAINST THE REGISTRIES ★ the whole point -For every candidate from STEP 1, check whether it is already captured before -proposing it. Pull the distinctive keyword(s) of the candidate and grep the -relevant registry (Index + bodies): +For every candidate from STEP 1 (and STEP 1B), check whether it is already +captured before proposing it. Pull the distinctive keyword(s) of the candidate +and grep the relevant registry (Index + bodies): ```bash # Example: candidate is a learning about "cd -P symlink resolution" grep -niE 'symlink|cd -P|BASH_SOURCE' .claude/memory/learnings.md ``` -Also scan the journal tail for ` capitalized` lines — the session may -have already logged it earlier: +Also scan the journal tail for ` capitalized` lines — the session may have +already logged it earlier: ```bash grep -nE '(BDR|LRN|BLK|EVAL)-[0-9]+ capitalized' .claude/memory/journal.md | tail -20 @@ -124,16 +150,55 @@ Classify each candidate: flag `⚠ maybe dup of — confirm or skip`. - **NEW** — no match → propose it normally. -Dedup is semantic, not string-equality. Same root cause described two ways is -still a dup. +Dedup is **semantic, not string-equality**. The same insight reworded with +different vocabulary is still a dup — read the registry entries and reason about +meaning, do not rely on keyword grep alone. (A reworded "Tailwind classes built +by concatenation get purged at build" still matches an existing "purge strips +concatenated class names" entry.) + +## STEP 2B — TODO RECONCILE (both modes) + +Runs only if `.claude/tasks/TODO.md` exists (STEP 0). Two passes. + +**PASS A — done-detection (TODO → reality).** For each unchecked `- [ ]`, decide +whether the session actually finished it, grounding on git (`git log`, +`git diff HEAD`, `git show`) AND the conversation. Propose `[x]` ONLY when the +task ↔ commit/code map is unambiguous (task "add retry-with-backoff" ↔ a commit +that adds exactly that). +- Partial / umbrella tasks ("harden X" covering 3 things when only 1 shipped) → + leave unchecked. +- Vague tasks ("Commit", "Deploy", "test it") with no precise git evidence → + leave unchecked. Never check on assumption or on a guess. + +**PASS B — capture (conversation → TODO).** Spot explicit to-dos voiced in the +session ("il faut X", "TODO Y", "à corriger Z", new directives) that are absent +from the TODO → propose adding them as `- [ ]`. Dedup semantically against +existing items first. Capture ONLY what was explicitly stated — do not invent, +expand, or decompose a task into subtasks the user never named. + +**Anti-noise filter (PASS B).** NEVER add — or fold into an existing item — +commit / deploy / push / release / tag actions. These are systematic steps the +user performs every session, not tracked work. "push la branche + tag v0.3.0" is +noise even when phrased with action verbs. If such an item ALREADY exists in the +TODO, PASS A may check it when proven done, but PASS B never creates it nor +enriches one with session-derived push/tag/release detail. + +**Routing.** A directive that changes the project's ORIENTATION (a policy / +architecture choice, e.g. "GraphQL for all new endpoints from now on") is a +DECISION, not a task → it flows through STEP 1 into decisions.md (BDR), never +into the TODO. Don't confuse an actionable task with an architecture decision. + +**Language.** The TODO is **NOT caveman**. Tasks stay in readable, actionable +prose. Caveman is reserved for the `.claude/memory/` registries (STEP 4). ## STEP 3 — PRESENT PLAN ★ MANDATORY STOP (approval gate) -One compact screen. Pre-filled drafts, caveman-English bodies (registry rule). -Group by registry. Mark dup flags inline. +One compact screen. Pre-filled drafts — registry bodies in caveman-English, TODO +lines in plain prose. Group by registry, then a **SEPARATE TODO.md block**. Mark +dup flags inline. ``` -═══ CAPITALIZE — uncapitalized context before wipe ═══ +═══ CAPITALIZE — ═══ decisions.md ▸ NEW BDR-019 @@ -149,17 +214,28 @@ blockers.md evals.md ▸ NEW EVAL-003 <output> — <method> — <anomalies> — action: <keep|correct|deprecate> +TODO.md + ☑ check "<task>" (done @ <hash> | conversation) + + add "[ ] <new task>" (said in session, absent) + Already captured this session (dropped): LRN-023, BLK-006 +Ignored as noise: "push branch + tag v0.3.0" (systematic action) Action ? (all / pick <IDs> / edit <ID> / skip-all) ``` -If a registry has zero NEW + zero DUP → print `(rien de neuf — déjà à jour)`. +The **TODO.md block is approved / edited / skipped INDEPENDENTLY** of the +registry blocks. If a section has zero NEW + zero DUP → print +`(rien de neuf — déjà à jour)`. If a dup was dropped (incl. a ritual answer), +name its existing ID on the `Already captured` line. If the anti-noise filter +dropped a parasite, name it on the `Ignored as noise` line (no silent drops). Wait for input. Default = nothing written (journal line still goes in STEP 5). ## STEP 4 — WRITE APPROVED ENTRIES -For each approved entry, in registry order: +Registries first (in registry order), then the TODO. + +Registry entries — for each approved: 1. Read the target registry file. 2. Next sequential ID = scan existing `## <PREFIX>-NNN` body headings, take max, @@ -173,6 +249,12 @@ For each approved entry, in registry order: verbatim. Entries are ALWAYS English even if the STEP 3 prompt mirrored the user's language. +TODO — for each approved: + +- **Check**: flip the exact `- [ ]` line to `- [x]`, leaving the text unchanged. +- **Add**: append `- [ ] <task>` under the right `##` section (create a section + only if none fits). Plain readable prose, NOT caveman. + ## STEP 5 — JOURNAL LINE (always) Write one timeline line under today's `## YYYY-MM-DD` heading — even if every @@ -181,36 +263,49 @@ candidate was skipped or already captured. - Heading exists → append a bullet. - Missing → create `## YYYY-MM-DD` and write 3-5 bullets summarizing the session. -Reference any IDs written this run: `BDR-019 + LRN-026 capitalized before /clear.` +Reference any IDs written this run AND the TODO ops: +`BDR-019 + LRN-026 capitalized; checked 1 done, added 1 task.` ## STEP 6 — FINAL OUTPUT + HANDOFF ``` -CAPITALIZE COMPLETE — <YYYY-MM-DD> (pre-wipe flush) +CAPITALIZE COMPLETE — <YYYY-MM-DD> (<pre-wipe flush | session-close>) decisions.md : +<N> (BDR-019) | 0 learnings.md : +<N> (LRN-026) | 0 blockers.md : 0 — already up to date evals.md : +<N> (EVAL-003) | 0 + TODO.md : checked <N>, added <M> journal.md : +1 line under ## <date> dropped as already-captured: LRN-023, BLK-006 - -✅ Context flushed. Safe to /clear or /compact now. + ignored as noise: push/tag release ``` -The closing line matters — this skill exists to make the wipe safe, so confirm -it explicitly. +Then the mode-specific closing line: + +- **pre-wipe flush** → `✅ Context flushed. Safe to /clear or /compact now.` +- **session-close ritual** → `✅ Session closed. Next session: read .claude/memory/ at startup.` + +The closing line matters — confirm the wipe is safe (default) or the session is +checkpointed (ritual). ## Rules -- **Never invent.** Every entry grounded in this conversation or git history. - No fabricated "lessons" to fill the screen. -- **Dedup before proposing.** Re-logging an existing entry is the #1 failure - mode of this skill. When in doubt, flag as `⚠ DUP?` and let the user decide — - never silently create a near-duplicate. -- **Append-only.** Never overwrite or renumber existing entries. -- **Caveman English** bodies, always English, per CLAUDE.md memory format. -- **Journal always writes**, even on `skip-all` — timeline logging is cheap and - noise-tolerant. +- **Never invent.** Every entry grounded in this conversation or git history. No + fabricated "lessons" to fill the screen, no invented TODO subtasks. +- **Dedup before proposing.** Re-logging an existing entry is the #1 failure mode. + When in doubt, flag as `⚠ DUP?` and let the user decide. Dedup is semantic — + a reworded dup is still a dup. Applies to ritual answers too. +- **Append-only.** Never overwrite or renumber existing registry entries. +- **Caveman English** registry bodies, always English. **The TODO is plain + prose, never caveman** — caveman is registries-only. +- **TODO reconcile runs only if TODO.md exists.** Never create it (STEP 0). +- **PASS A checks only on an unambiguous task↔code/commit map.** Partial / + umbrella / vague → leave unchecked. Never on assumption. +- **PASS B captures only explicit to-dos**, deduped — never invented or + decomposed. +- **Anti-noise**: never track commit / deploy / push / release / tag. +- **Orientation directive → decisions.md (BDR)**, not the TODO. +- **Journal always writes**, even on `skip-all`. - **Skip trivial** for the 4 ID registries; journal excepted. - `.claude/memory/` missing → STOP at STEP 0, do not create the structure here. @@ -218,35 +313,48 @@ it explicitly. | Mistake | Fix | |---------|-----| -| Proposing items already in the registries | STEP 2 dedup is mandatory. Grep keywords + journal `capitalized` lines first. | -| Re-running after `/close` and re-logging the same items | Expected output after `/close` is `(rien de neuf)`. If it proposes the just-closed items, dedup failed. | +| Proposing items already in the registries | STEP 2 dedup is mandatory. Grep keywords + read entries + journal `capitalized` lines first. | +| Re-running after a ritual and re-logging the same items | Expected output after a ritual is `(rien de neuf)`. If it proposes the just-closed items, dedup failed. | +| Treating a reworded insight as new | Dedup is semantic, not lexical. Read the entry's meaning, not just its keywords. | | Renumbering or reusing an ID | IDs are stable + sequential. Max existing +1. | -| Writing prose bodies | Registries are caveman-English. Fragments, no articles/filler. | +| Writing prose registry bodies | Registries are caveman-English. Fragments, no articles/filler. (TODO stays prose.) | | Logging a trivial reversible tweak as a decision | Decision = tradeoff you'd defend, cross-file or >10 min to reverse. Else skip. | -| Fanning one incident across registries (e.g. a resolved gotcha as both LRN and BLK) | One incident → one primary registry. Reusable pattern → LRN. Unresolved friction / the friction itself → BLK. Don't write the same event twice. | -| French/English entry text | Prompt may be French; written entry is always English. | -| Creating `.claude/memory/` when absent | Not this skill's job — STOP and point to `/onboard`. | +| Fanning one incident across registries (a resolved gotcha as both LRN and BLK) | One incident → one primary registry. Reusable pattern → LRN. Unresolved friction / the friction itself → BLK. | +| Folding push / tag / release / deploy into the TODO | Anti-noise filter. Those are systematic actions, not tracked work — drop them, even phrased as tasks. | +| Checking an umbrella/partial task because "some of it shipped" | PASS A needs the WHOLE task proven done with a clear git map. Partial → leave unchecked. | +| Inventing a subtask the user never voiced | PASS B captures only explicit to-dos. No decomposition, no expansion. | +| Dumping an architecture directive as a TODO task | Route orientation/policy directives to decisions.md (BDR), not the TODO. | +| Writing a ritual answer fresh without dedup | Ritual answers go through STEP 2 like any candidate; a dup shows its existing ID. | +| French/English entry text | Prompt may be French; written registry entry is always English. | +| Creating `.claude/memory/` or `.claude/tasks/TODO.md` when absent | Not this skill's job — registries STOP and point to `/onboard`; TODO volet is skipped. | ## Red flags — STOP -- About to append an entry without having grepped the registry for it → dedup skipped. -- Proposing 6+ entries from a short conversation → over-capturing noise; keep only what you'd defend. -- Rewriting an existing entry "to update it" → append-only violation; add a new entry with `supersedes`. -- Same incident headed for two registries (LRN + BLK for one event) → pick the one primary registry. +- About to append a registry entry without having grepped + read the registry + for it → dedup skipped. +- About to treat a reworded item as new without checking meaning → semantic + dedup skipped. +- Proposing 6+ entries from a short conversation → over-capturing noise. +- Rewriting an existing entry "to update it" → append-only violation; add a new + entry with `supersedes`. +- Same incident headed for two registries (LRN + BLK for one event) → pick one. +- About to add / relabel a TODO item with push / tag / release / deploy → noise. +- About to check a `- [ ]` with no commit/code proving the WHOLE task done → stop. +- About to write a TODO item the user never explicitly asked for → stop. +- Writing the TODO in caveman → TODO is plain prose. ## TDD note (skill itself) -v1 ships without baseline pressure tests per superpowers:writing-skills Iron -Law. The STEP 3 approval gate is the human safety net (same posture as -`/prune-memory` v1). Recommended baseline before relying on it: +Baseline (RED, 2026-06-19): a no-skill agent on a pressured fixture deduped +correctly (incl. a reworded semantic dup), routed an architecture directive to +BDR, and checked a cleanly-done task — but (a) folded a "push branch + tag +release" parasite into the TODO, (b) invented a subtask the user never voiced, +(c) wrote everything with no approval stop, and (d) fanned one incident across +two registries on an earlier run (non-deterministic). This skill's mandatory +gate (STEP 3), anti-noise filter (STEP 2B), explicit-only capture, and +one-incident-one-registry rule make those deterministic. -1. **RED** — give a subagent a synthetic transcript containing 2 - already-captured insights + 1 genuinely new learning, plus a registry - snapshot. Ask it to "save what matters before /clear" WITHOUT this skill. - Document whether it re-logs the captured ones (no dedup) or misses the new one. -2. **GREEN** — invoke `/capitalize` on the same inputs. Verify STEP 2 drops the - 2 dups and proposes only the 1 new entry. -3. **REFACTOR** — log any new rationalization (e.g. "it's basically the same so - I'll just append anyway") and add a counter to Common mistakes / Red flags. - -Until done, treat as v1-untested; the approval gate gates every write. +GREEN re-run on the same fixture must: stop at the gate, drop both dups (footer +shows existing IDs), log jigsaw as ONE learning, check only the cleanly-done +task, leave the umbrella "harden" task unchecked, add only the explicit README +to-do, ignore the push/tag parasite, and route the GraphQL directive to BDR. diff --git a/skills/close/SKILL.md b/skills/close/SKILL.md index ceb88d5..111f442 100644 --- a/skills/close/SKILL.md +++ b/skills/close/SKILL.md @@ -1,13 +1,14 @@ --- name: close description: | - End-of-session ritual — capitalize the 3 registry questions: what was - decided, what was learned, what was blocked. Writes approved entries - into `.claude/memory/decisions.md`, `.claude/memory/learnings.md`, and - `.claude/memory/blockers.md`, plus a timeline line in `.claude/memory/journal.md`. - Trigger: "close", "end session", "ferme la session", "session close", + End-of-session ritual — flush what was decided, learned, and blocked into + `.claude/memory/`, reconcile `.claude/tasks/TODO.md`, and log a journal line. + Alias for `/capitalize --ritual`: same dedup + TODO-reconcile + approval-gate + pipeline, plus the explicit 3-question reflection. NOT registry curation + (that is /prune-memory). + Triggers: "close", "end session", "ferme la session", "session close", "checkpoint memory", "what did we learn", "retro rapide", "fin de journée". -argument-hint: (none — operates on the current conversation context) +argument-hint: (none — runs capitalize in ritual mode on the current conversation) allowed-tools: - Read - Edit @@ -15,124 +16,22 @@ allowed-tools: - Bash - Grep - Glob + - AskUserQuestion --- -# CLOSE — Session-Close Ritual +# /close — Session-close ritual (alias) -Capture the 3 registry-worthy outputs from the current session before losing context. Operates entirely on conversation memory + git state — does NOT re-read code. +`/close` is an alias for **`/capitalize --ritual`**. All logic lives in the +**capitalize** skill — nothing is duplicated here. -## STEP 0 — PRECHECK +Invoke the `capitalize` skill now and run it in **ritual mode**: the full +pipeline (STEP 0 precheck → STEP 1 auto-scan → STEP 2 dedup → STEP 2B TODO +reconcile → STEP 3 approval gate → STEP 4 write → STEP 5 journal → STEP 6 +handoff), PLUS STEP 1B's explicit 3-question reflection (what did you decide / +learn / block). -Verify the registry files exist: +Ritual answers are deduped like any other candidate — a dup is dropped and its +existing ID shown, not re-logged. This is the upgrade over the legacy `/close`, +which wrote ritual answers fresh with no dedup. -```bash -ls .claude/memory/decisions.md .claude/memory/learnings.md .claude/memory/blockers.md .claude/memory/journal.md 2>/dev/null -``` - -- If `.claude/memory/` is missing entirely → print: - ``` - ⚠️ .claude/memory/ absent. Lance d'abord `/onboard` (ou `/init-project` pour un nouveau repo) - pour créer la structure des registres. - ``` - STOP. -- If some files are missing → print which, create them from `~/.claude/templates/memory/<name>.md`, continue. - -## STEP 1 — GATHER SESSION CONTEXT - -Collect the raw material without re-reading code: - -```bash -git log --oneline -10 -git diff HEAD --stat -git status --short -date +%Y-%m-%d -``` - -Extract from current conversation: -- Any decision made (framework pick, refactor scope, architecture choice, naming convention). -- Any learning surfaced (surprising API behaviour, reusable pattern, gotcha, "don't do X"). -- Any blocker encountered (dead end, friction > 15 min wasted, upstream bug). - -## STEP 2 — THE 3 QUESTIONS - -Present the ritual compactly — one screen, 3 questions, pre-filled draft answers from STEP 1: - -``` -═══ SESSION-CLOSE RITUAL — 3 QUESTIONS ═══ - -1️⃣ Qu'est-ce que tu as décidé ? - Proposition BDR-XXX : - Titre : <extrait de la conversation> - Décision: <1 phrase> - Pourquoi: <1-2 phrases> - Alts rejetées: <si captable> - → (accept / edit / skip / add another) - -2️⃣ Qu'est-ce que tu as appris ? - Proposition LRN-XXX : - Pattern : <extrait abstrait> - Contexte: <où/quand> - Future : <quand s'en rappeler> - → (accept / edit / skip / add another) - -3️⃣ Sur quoi es-tu bloqué ? - Proposition BLK-XXX : - Friction : <extrait> - Cause : <si identifiée — sinon "à investiguer"> - Solution : <workaround si déjà trouvé — sinon "open"> - Statut : open | resolved | upstream - → (accept / edit / skip / add another) - -Action globale ? (all / pick <numbers> / edit / skip-all) -``` - -If nothing notable to propose for a given question → say `(rien à logger cette session)` for that question. - -## STEP 3 — WRITE APPROVED ENTRIES - -For each approved entry: - -1. Read the target registry file. -2. Append the new entry at the end (never rewrite existing entries). -3. Add a line to the Index table at the top with the new ID, date, short title, status. -4. Generate next sequential ID by scanning existing IDs (e.g., if `BDR-007` exists, next is `BDR-008`). - -## STEP 4 — JOURNAL ENTRY - -Always write one line in `.claude/memory/journal.md` under today's heading — even if all 3 questions were skipped: - -- If today's heading exists → append a new bullet under it. -- If not → create `## YYYY-MM-DD` heading and write 3-5 bullets summarising the session. - -Template: -```markdown -## YYYY-MM-DD - -- <what was done — 1 line from conversation> -- <what was decided — link to BDR-XXX if logged> -- <what was learned — link to LRN-XXX if logged> -- <what's blocked — link to BLK-XXX if logged> -- <commit hashes if any — `<hash1>..<hashN>`> -``` - -## STEP 5 — FINAL OUTPUT - -``` -CLOSE COMPLETE — session <YYYY-MM-DD> - decisions.md : +<N> entries (BDR-XXX, BDR-YYY) | 0 entries - learnings.md : +<N> entries (LRN-XXX) | 0 entries - blockers.md : +<N> entries (BLK-XXX) | 0 entries - journal.md : +1 line under ## <date> -Prochaine session : lire `.claude/memory/` au démarrage pour rappel. -``` - ---- - -## RULES - -- Never invent content. Every entry must be grounded in the current conversation or git history — no fabricated "lessons". -- Skip silently rather than log a trivial entry. Journal excepted (timeline logging is cheap, noise is fine). -- Never overwrite existing entries — append-only. -- If the user says `skip-all` → still write the journal line and exit. -- If `.claude/memory/` is missing → STOP at STEP 0, do not create it here (onboard / init-project responsibility). -- **Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The 3-question prompt may mirror the user's language; the appended entries must not. +→ Use the Skill tool to launch `capitalize` with argument `--ritual`.