feat(capitalize): merge /close into /capitalize + TODO reconcile
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) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X3e8LaH2vymmxyh36h3jFU
This commit is contained in:
parent
a4e0425581
commit
9dc2b83f0e
@ -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 {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,17 +1,19 @@
|
|||||||
---
|
---
|
||||||
name: capitalize
|
name: capitalize
|
||||||
description: |
|
description: |
|
||||||
Use when about to /clear or /compact and the current conversation holds
|
Use when about to /clear or /compact, or when closing a session, and the
|
||||||
decisions, learnings, blockers, or eval results that were never written to
|
conversation holds decisions, learnings, blockers, eval results, or
|
||||||
`.claude/memory/`. Use to flush important uncapitalized context before it is
|
finished/new TODO items not yet written to `.claude/memory/` or
|
||||||
wiped, or when unsure whether the session's insights already reached the
|
`.claude/tasks/TODO.md`. Plain invocation = pre-wipe flush; `--ritual` (or the
|
||||||
registries. NOT the fresh end-of-session ritual (that is /close) and NOT
|
word "close"/"ritual" in the request) = end-of-session reflection mode. NOT
|
||||||
registry curation (that is /prune-memory).
|
registry curation (that is /prune-memory).
|
||||||
Triggers: "capitalize", "capitalise", "before clear", "before compact",
|
Triggers: "capitalize", "capitalise", "before clear", "before compact",
|
||||||
"save before clear", "flush memory", "don't lose this", "what's not logged
|
"save before clear", "flush memory", "don't lose this", "what's not logged
|
||||||
yet", "avant de clear", "avant compact", "sauvegarde avant clear",
|
yet", "avant de clear", "avant compact", "sauvegarde avant clear",
|
||||||
"capitalise ce qui manque".
|
"capitalise ce qui manque", "close", "end session", "session close",
|
||||||
argument-hint: (none — scans the current conversation against .claude/memory/)
|
"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:
|
allowed-tools:
|
||||||
- Read
|
- Read
|
||||||
- Edit
|
- Edit
|
||||||
@ -22,27 +24,31 @@ allowed-tools:
|
|||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /capitalize — Flush uncapitalized context before a wipe
|
# /capitalize — Flush uncapitalized context (two modes)
|
||||||
|
|
||||||
Salvage the registry-worthy insights from **this conversation** that were
|
Salvage the registry-worthy insights from **this conversation** that were never
|
||||||
never written down, right before `/clear` or `/compact` destroys them.
|
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
|
Operates on conversation memory + git state + the existing registries + the
|
||||||
NOT re-read source code.
|
TODO. Does NOT re-read source code.
|
||||||
|
|
||||||
## What makes this different from /close
|
## Modes
|
||||||
|
|
||||||
| Situation | Skill |
|
| Mode | How triggered | Adds |
|
||||||
|-----------|-------|
|
|------|---------------|------|
|
||||||
| About to `/clear` or `/compact` — salvage what the session produced but never logged | **/capitalize** (this) |
|
| **default** (pre-wipe flush) | plain `/capitalize`, "before clear", "flush memory" | auto-scan + dedup + TODO reconcile |
|
||||||
| Deliberate end-of-session ritual, fresh 3-question prompt | `/close` |
|
| **--ritual** (session-close) | `--ritual` flag, OR `$ARGUMENTS` contains "close"/"ritual", OR invoked via `/close` | everything above **+ STEP 1B** 3-question reflection |
|
||||||
| Registries too long / noisy — curate, merge, compress | `/prune-memory` |
|
|
||||||
| Token-compress one registry file | `/caveman:compress <file>` |
|
|
||||||
|
|
||||||
The signature move of THIS skill is **STEP 2 — DEDUP**: every candidate is
|
Detect the mode first. Both modes share the SAME dedup (STEP 2), TODO reconcile
|
||||||
checked against what is already in the registries, and anything already
|
(STEP 2B), and approval gate (STEP 3). The signature move is **STEP 2 — DEDUP**:
|
||||||
captured is dropped silently. `/close` does not dedup; it asks fresh. Running
|
every candidate is checked against what is already in the registries, and
|
||||||
`/capitalize` right after a `/close` should propose (near) nothing.
|
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
|
## 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 \
|
ls .claude/memory/decisions.md .claude/memory/learnings.md \
|
||||||
.claude/memory/blockers.md .claude/memory/evals.md \
|
.claude/memory/blockers.md .claude/memory/evals.md \
|
||||||
.claude/memory/journal.md 2>/dev/null
|
.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 —
|
- `.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
|
⚠️ .claude/memory/ absent. Lance `/onboard` (ou `/init-project`) pour créer
|
||||||
les registres avant de capitaliser.
|
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/<name>.md`, continue.
|
`~/.claude/templates/memory/<name>.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
|
## STEP 1 — SCAN THE CONVERSATION
|
||||||
|
|
||||||
@ -83,34 +93,50 @@ git status --short
|
|||||||
date +%Y-%m-%d
|
date +%Y-%m-%d
|
||||||
```
|
```
|
||||||
|
|
||||||
For each candidate, draft the fields the target registry's schema expects
|
For each candidate, draft the fields the target registry's schema expects (read
|
||||||
(read the YAML header of that file if unsure — e.g. decisions need
|
the YAML header of that file if unsure).
|
||||||
decision/why/alternatives; blockers need friction/real_cause/solution/status).
|
|
||||||
|
|
||||||
**Skip the trivial.** If it is reversible in under 10 min with no cross-file
|
**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
|
impact, it is not a decision. If it is a one-shot fact, not a reusable pattern,
|
||||||
pattern, it is not a learning. Noise hurts the every-session re-read.
|
it is not a learning. Noise hurts the every-session re-read.
|
||||||
|
|
||||||
**One incident → one primary registry.** Do not fan a single event across
|
**One incident → one primary registry.** Do not fan a single event across
|
||||||
registries. A resolved gotcha that cost time is a *learning* (the reusable
|
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
|
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
|
unresolved, or when the friction itself (not the lesson) is the durable record.
|
||||||
record. The same event written to two registries is a near-duplicate in the
|
The same event written to two registries is a near-duplicate in the
|
||||||
every-session re-read.
|
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
|
||||||
|
`<ID>` 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
|
## STEP 2 — DEDUP AGAINST THE REGISTRIES ★ the whole point
|
||||||
|
|
||||||
For every candidate from STEP 1, check whether it is already captured before
|
For every candidate from STEP 1 (and STEP 1B), check whether it is already
|
||||||
proposing it. Pull the distinctive keyword(s) of the candidate and grep the
|
captured before proposing it. Pull the distinctive keyword(s) of the candidate
|
||||||
relevant registry (Index + bodies):
|
and grep the relevant registry (Index + bodies):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Example: candidate is a learning about "cd -P symlink resolution"
|
# Example: candidate is a learning about "cd -P symlink resolution"
|
||||||
grep -niE 'symlink|cd -P|BASH_SOURCE' .claude/memory/learnings.md
|
grep -niE 'symlink|cd -P|BASH_SOURCE' .claude/memory/learnings.md
|
||||||
```
|
```
|
||||||
|
|
||||||
Also scan the journal tail for `<ID> capitalized` lines — the session may
|
Also scan the journal tail for `<ID> capitalized` lines — the session may have
|
||||||
have already logged it earlier:
|
already logged it earlier:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
grep -nE '(BDR|LRN|BLK|EVAL)-[0-9]+ capitalized' .claude/memory/journal.md | tail -20
|
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 <ID> — confirm or skip`.
|
flag `⚠ maybe dup of <ID> — confirm or skip`.
|
||||||
- **NEW** — no match → propose it normally.
|
- **NEW** — no match → propose it normally.
|
||||||
|
|
||||||
Dedup is semantic, not string-equality. Same root cause described two ways is
|
Dedup is **semantic, not string-equality**. The same insight reworded with
|
||||||
still a dup.
|
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)
|
## STEP 3 — PRESENT PLAN ★ MANDATORY STOP (approval gate)
|
||||||
|
|
||||||
One compact screen. Pre-filled drafts, caveman-English bodies (registry rule).
|
One compact screen. Pre-filled drafts — registry bodies in caveman-English, TODO
|
||||||
Group by registry. Mark dup flags inline.
|
lines in plain prose. Group by registry, then a **SEPARATE TODO.md block**. Mark
|
||||||
|
dup flags inline.
|
||||||
|
|
||||||
```
|
```
|
||||||
═══ CAPITALIZE — uncapitalized context before wipe ═══
|
═══ CAPITALIZE — <pre-wipe flush | session-close ritual> ═══
|
||||||
|
|
||||||
decisions.md
|
decisions.md
|
||||||
▸ NEW BDR-019 <title>
|
▸ NEW BDR-019 <title>
|
||||||
@ -149,17 +214,28 @@ blockers.md
|
|||||||
evals.md
|
evals.md
|
||||||
▸ NEW EVAL-003 <output> — <method> — <anomalies> — action: <keep|correct|deprecate>
|
▸ 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
|
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)
|
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).
|
Wait for input. Default = nothing written (journal line still goes in STEP 5).
|
||||||
|
|
||||||
## STEP 4 — WRITE APPROVED ENTRIES
|
## 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.
|
1. Read the target registry file.
|
||||||
2. Next sequential ID = scan existing `## <PREFIX>-NNN` body headings, take max,
|
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
|
verbatim. Entries are ALWAYS English even if the STEP 3 prompt mirrored the
|
||||||
user's language.
|
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)
|
## STEP 5 — JOURNAL LINE (always)
|
||||||
|
|
||||||
Write one timeline line under today's `## YYYY-MM-DD` heading — even if every
|
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.
|
- Heading exists → append a bullet.
|
||||||
- Missing → create `## YYYY-MM-DD` and write 3-5 bullets summarizing the session.
|
- 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
|
## 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
|
decisions.md : +<N> (BDR-019) | 0
|
||||||
learnings.md : +<N> (LRN-026) | 0
|
learnings.md : +<N> (LRN-026) | 0
|
||||||
blockers.md : 0 — already up to date
|
blockers.md : 0 — already up to date
|
||||||
evals.md : +<N> (EVAL-003) | 0
|
evals.md : +<N> (EVAL-003) | 0
|
||||||
|
TODO.md : checked <N>, added <M>
|
||||||
journal.md : +1 line under ## <date>
|
journal.md : +1 line under ## <date>
|
||||||
dropped as already-captured: LRN-023, BLK-006
|
dropped as already-captured: LRN-023, BLK-006
|
||||||
|
ignored as noise: push/tag release
|
||||||
✅ Context flushed. Safe to /clear or /compact now.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The closing line matters — this skill exists to make the wipe safe, so confirm
|
Then the mode-specific closing line:
|
||||||
it explicitly.
|
|
||||||
|
- **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
|
## Rules
|
||||||
|
|
||||||
- **Never invent.** Every entry grounded in this conversation or git history.
|
- **Never invent.** Every entry grounded in this conversation or git history. No
|
||||||
No fabricated "lessons" to fill the screen.
|
fabricated "lessons" to fill the screen, no invented TODO subtasks.
|
||||||
- **Dedup before proposing.** Re-logging an existing entry is the #1 failure
|
- **Dedup before proposing.** Re-logging an existing entry is the #1 failure mode.
|
||||||
mode of this skill. When in doubt, flag as `⚠ DUP?` and let the user decide —
|
When in doubt, flag as `⚠ DUP?` and let the user decide. Dedup is semantic —
|
||||||
never silently create a near-duplicate.
|
a reworded dup is still a dup. Applies to ritual answers too.
|
||||||
- **Append-only.** Never overwrite or renumber existing entries.
|
- **Append-only.** Never overwrite or renumber existing registry entries.
|
||||||
- **Caveman English** bodies, always English, per CLAUDE.md memory format.
|
- **Caveman English** registry bodies, always English. **The TODO is plain
|
||||||
- **Journal always writes**, even on `skip-all` — timeline logging is cheap and
|
prose, never caveman** — caveman is registries-only.
|
||||||
noise-tolerant.
|
- **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.
|
- **Skip trivial** for the 4 ID registries; journal excepted.
|
||||||
- `.claude/memory/` missing → STOP at STEP 0, do not create the structure here.
|
- `.claude/memory/` missing → STOP at STEP 0, do not create the structure here.
|
||||||
|
|
||||||
@ -218,35 +313,48 @@ it explicitly.
|
|||||||
|
|
||||||
| Mistake | Fix |
|
| Mistake | Fix |
|
||||||
|---------|-----|
|
|---------|-----|
|
||||||
| Proposing items already in the registries | STEP 2 dedup is mandatory. Grep keywords + journal `capitalized` lines first. |
|
| Proposing items already in the registries | STEP 2 dedup is mandatory. Grep keywords + read entries + 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
||||||
| French/English entry text | Prompt may be French; written entry is always English. |
|
| Folding push / tag / release / deploy into the TODO | Anti-noise filter. Those are systematic actions, not tracked work — drop them, even phrased as tasks. |
|
||||||
| Creating `.claude/memory/` when absent | Not this skill's job — STOP and point to `/onboard`. |
|
| 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
|
## Red flags — STOP
|
||||||
|
|
||||||
- About to append an entry without having grepped the registry for it → dedup skipped.
|
- About to append a registry entry without having grepped + read the registry
|
||||||
- Proposing 6+ entries from a short conversation → over-capturing noise; keep only what you'd defend.
|
for it → dedup skipped.
|
||||||
- Rewriting an existing entry "to update it" → append-only violation; add a new entry with `supersedes`.
|
- About to treat a reworded item as new without checking meaning → semantic
|
||||||
- Same incident headed for two registries (LRN + BLK for one event) → pick the one primary registry.
|
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)
|
## TDD note (skill itself)
|
||||||
|
|
||||||
v1 ships without baseline pressure tests per superpowers:writing-skills Iron
|
Baseline (RED, 2026-06-19): a no-skill agent on a pressured fixture deduped
|
||||||
Law. The STEP 3 approval gate is the human safety net (same posture as
|
correctly (incl. a reworded semantic dup), routed an architecture directive to
|
||||||
`/prune-memory` v1). Recommended baseline before relying on it:
|
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
|
GREEN re-run on the same fixture must: stop at the gate, drop both dups (footer
|
||||||
already-captured insights + 1 genuinely new learning, plus a registry
|
shows existing IDs), log jigsaw as ONE learning, check only the cleanly-done
|
||||||
snapshot. Ask it to "save what matters before /clear" WITHOUT this skill.
|
task, leave the umbrella "harden" task unchecked, add only the explicit README
|
||||||
Document whether it re-logs the captured ones (no dedup) or misses the new one.
|
to-do, ignore the push/tag parasite, and route the GraphQL directive to BDR.
|
||||||
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.
|
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
---
|
---
|
||||||
name: close
|
name: close
|
||||||
description: |
|
description: |
|
||||||
End-of-session ritual — capitalize the 3 registry questions: what was
|
End-of-session ritual — flush what was decided, learned, and blocked into
|
||||||
decided, what was learned, what was blocked. Writes approved entries
|
`.claude/memory/`, reconcile `.claude/tasks/TODO.md`, and log a journal line.
|
||||||
into `.claude/memory/decisions.md`, `.claude/memory/learnings.md`, and
|
Alias for `/capitalize --ritual`: same dedup + TODO-reconcile + approval-gate
|
||||||
`.claude/memory/blockers.md`, plus a timeline line in `.claude/memory/journal.md`.
|
pipeline, plus the explicit 3-question reflection. NOT registry curation
|
||||||
Trigger: "close", "end session", "ferme la session", "session close",
|
(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".
|
"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:
|
allowed-tools:
|
||||||
- Read
|
- Read
|
||||||
- Edit
|
- Edit
|
||||||
@ -15,124 +16,22 @@ allowed-tools:
|
|||||||
- Bash
|
- Bash
|
||||||
- Grep
|
- Grep
|
||||||
- Glob
|
- 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
|
→ Use the Skill tool to launch `capitalize` with argument `--ritual`.
|
||||||
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.
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user