ワンクリックで
retro
Periodic retro — safety review, memory maintenance, pattern extraction
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Periodic retro — safety review, memory maintenance, pattern extraction
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
The backlog — merged prioritized view of all actionable items from a task manager and backlog.md
Daily planner — time-aware plan coordinating the user's day and Claude's day, with calendar awareness and queue integration
Create Gmail drafts/sends via a local email-CLI wrapper (integration stub). Draft-by-default with a sanitizer + clobber-guard.
Session kickoff — orient from memory, state understanding, ask agenda
End-of-session wrap — update calibration, memory, backlog, lessons
Multi-persona reviewer battery (NineAngel). Auto-detects relevant personas from project signals and dispatches them in parallel. Usage: /angel [personas...] [-perf] [--full] [--all] [--loop] [--cross]
| name | retro |
| description | Periodic retro — safety review, memory maintenance, pattern extraction |
Retro procedure. Run every ~4 days. Covers safety, memory hygiene, and pattern extraction.
The memory-MAINTENANCE actions are the main point of retro. Run them FIRST, before any diagnostic checks, so they never get dropped when a session is long or interrupted. Execute the numbered sections in THIS order:
calibration.md, compress the rest into calibration-archive.md), lessons absorption (archive internalized lessons; promote pattern-shaped ones to patterns.md), MEMORY.md topic-index prune, wrap-coverage audit, per-project staleness. ACTUALLY EDIT THE FILES — don't just report on them.
1.5. §2.7 Follow-up queue — drain your personal "flag it for later" queue (see §2.7 — an example integration with a task-list API; adapt or delete if you don't keep one).Last retro / Next due / Last verified unless the §2 maintenance actions actually completed this run. If you ran out of budget and skipped them, say so explicitly and LEAVE THE DATES STALE so the next session re-triggers. A cosmetic date bump over skipped maintenance is worse than no retro — it makes the gap invisible.Why this order: a checks-first retro tends to run the cheap scans + bump the date but skip the calibration archive and lessons absorption — the substantive work. Front-loading the actions prevents that. (This is the kind of failure the §2 fail-loud guards below and the completion sentinel exist to catch mechanically, not just by discipline.)
Check each of these and report findings. (These are EXAMPLES for a Linux dev box running Node/Docker services — keep the ones that match your stack, drop the rest.)
bash <hooks-dir>/test-hooks.sh
Non-zero exit means a hook regressed. Surface the failing hook name(s) and treat as a blocker until fixed — a broken hook is silently corrupting state in real sessions, not just the test sandbox..env contents, API keys, passwords
for d in ~/Projects/*/; do echo "=== $(basename $d) ==="; git -C "$d" log --oneline -5 --diff-filter=A -- '*.env' '.env*' 2>/dev/null; done
.env files aren't world-readable. Use -L to DEREFERENCE symlinks — if your .env files are symlinks to a secrets store (a common pattern), a bare find -perm flags the symlink itself (always lrwxrwxrwx), a false positive. -L checks the real target's perms.
find -L ~/Projects -name '.env' -perm /o+r 2>/dev/null
sudo ss -tlnp | grep -v '127.0.0.1\|::1'
echo "installed: $(claude --version)" && echo "latest: $(npm view @anthropic-ai/claude-code version)"
If behind, run sudo npm install -g @anthropic-ai/claude-code@latest. Note the version jump in the report.systemctl --user list-units --state=failed
docker ps --filter "status=exited" --format "{{.Names}} exited {{.Status}}"
/ or /home over 80%
df -h / /home | tail -2
npm audit across active projects
for d in ~/Projects/*/; do [ -f "$d/package-lock.json" ] && echo "=== $(basename $d) ===" && npm audit --prefix "$d" 2>/dev/null | tail -3; done
# All listeners — including 127.0.0.1, which can shadow systemd services
ss -tlnp | grep -v 'sshd\|tailscaled\|syncthing\|systemd-resolve'
Cross-reference PIDs against known services (Docker containers, systemd units, active dev work). For loopback ports, verify each PID matches the expected unit. A manual node index.js on a service port creates a zombie that shadows the real service — check for duplicate ports. Kill anything unexplained.calibration-archive.mdlessons.md — any lessons that have been internalized (reflected in patterns.md or changed behavior) should be archivedpatterns.md (keep patterns.md at ~15 rules max)If you migrated task managers at some point, or just accumulate hand-entered
tasks between retros: sweep all lists via your task API, propose priority
prefixes and list moves for anything unprefixed/misfiled, and revisit whether
the priority-prefix tiering (see the dashboard skill) still works for you —
adjust the convention there if not.
MEMORY.md is loaded at every session start — every row costs context. Topic rows accumulate forever unless pruned. Without an explicit step here, the index grows wooly and the cheap-to-add row becomes the expensive-to-load row.
Anchor note (post two-tier-memory decision): if you've split your memory index into a hot tier (MEMORY.md: active projects + high-use topics) and a cold tier (e.g.
roster.md+topics.mdholding the full portfolio/index), the awk ranges below target the live hot-tier headers only. They prune ONLY the hot MEMORY.md file. Cold-tier coverage is a separate, harder problem (bloat tends to accumulate there once the hot tier is kept lean) — do NOT assume a clean hot-tier pass means the cold files were reviewed. If you haven't split your memory this way, ignore this note — the ranges below still apply to your single MEMORY.md.
§2 header preflight (run FIRST — abort the whole prune if it fails): before any
extraction, assert every section header the awk ranges depend on actually exists in the
live files. If any line below prints MISSING, STOP and surface it — a renamed/moved
header is the exact root cause of a silent zero-row no-op (the prune "runs," matches
nothing, and reports false-clean). Do NOT proceed to prune over an empty read.
M="<memory-dir>/MEMORY.md"
for h in '^## Key topics' '^## Memory Layout' '^## Active projects' '^## Vocabulary'; do
if grep -qE "$h" "$M"; then echo "OK $h"; else echo "MISSING $h <-- ABORT §2"; fi
done
# If you run a cold tier, its files must exist too (their internal header contract is
# a separate design decision for you to define):
for f in roster.md topics.md; do
p="<memory-dir>/$f"
[ -f "$p" ] && echo "OK $f" || echo "MISSING $f"
done
Procedure:
Find every file path referenced from MEMORY.md's Key-topics (or Topic Index) section, and check its last modification date:
MEMDIR="<memory-dir>" # adapt: your central memory dir
awk '/^## Key topics/,/^## Memory Layout/' "$MEMDIR/MEMORY.md" \
| grep -oE '\[[^]]+\]\(([^)]+\.md)\)' \
| sed -E 's/.*\(([^)]+)\)/\1/' \
| sort -u \
| while read f; do
path="$MEMDIR/$f"
if [ -f "$path" ]; then
mtime=$(stat -c %Y "$path")
age_days=$(( ( $(date +%s) - mtime ) / 86400 ))
printf "%4d days %s\n" "$age_days" "$f"
else
printf "MISSING %s\n" "$f"
fi
done | sort -rn
Fail-loud check (run after the block above): the extraction MUST yield ≥1 referenced file. Re-count independently and abort on zero rather than reading silence as "clean":
M="<memory-dir>/MEMORY.md"
n=$(awk '/^## Key topics/,/^## Memory Layout/' "$M" \
| grep -oE '\[[^]]+\]\(([^)]+\.md)\)' | sort -u | wc -l)
[ "$n" -gt 0 ] && echo "OK — $n topic refs extracted" \
|| echo "ANCHOR MISS — scanned nothing, NOT clean. The header range matched 0 rows; a header rename has re-broken §2. ABORT and fix the anchor before reporting the prune clean."
Flag for prune review (do not auto-delete):
Present candidates to the user as a numbered list with: age, file path, current MEMORY.md row text. The user decides per row: keep / archive / fold into another topic / delete. Do NOT pre-empt the decision — surface the candidates and wait.
Soft target: keep MEMORY.md under 200 lines (truncation threshold). If the current line count is >180, prune-pressure is high.
Topic Index row text discipline: each row is - [Title](file.md) — one-line hook under ~150 chars. Rows that have grown into paragraphs need to be folded back into the pointed-to file.
Consolidation pass — two checks, structural-skew first then pairwise-cluster:
(a) Structural skew check — if any single-token prefix dominates >40% of the topic index, the issue isn't pairwise merging, it's index design. Run:
awk '/^## Key topics/,/^## Memory Layout/' "$MEMDIR/MEMORY.md" \
| grep -oE '\(([^)]+\.md)\)' \
| sed -E 's/[()]//g' \
| sed -E 's/^([a-z]+)[-_].*\.md$/\1/' \
| sort | uniq -c | sort -rn | head -5
If the top prefix exceeds ~40% of rows: surface this as a structural-reorg candidate. Two reasonable shapes:
feedback-index.md cataloging all feedback-* rules with one-line summaries). MEMORY.md gets one row instead of many.feedback-*, code tasks load ref-*). Requires harness work.(b) Pairwise cluster check — only for semantically-related rows (not just prefix-matched). Run:
awk '/^## Key topics/,/^## Memory Layout/' "$MEMDIR/MEMORY.md" \
| grep -oE '\(([^)]+\.md)\)' \
| sed -E 's/[()]//g' \
| sed -E 's/^([a-z]+[-_][a-z]+[-_][a-z]+)[-_].*\.md$/\1/' \
| sort | uniq -c | sort -rn \
| awk '$1 >= 3'
A three-token prefix is stricter than two-token (avoids false positives where the third token disambiguates unrelated memories in the same domain). For each ≥3-row cluster: read the row titles, verify they're actually about the same topic before proposing a merge. If they are, propose a merged-file name and present it. If the cluster is unrelated despite the prefix match, skip.
Don't auto-merge — both checks present candidates and wait for the user's per-cluster decision.
The topic-index prune above does NOT cover the Active-projects table (the
## Active projects (in-flight) rows) — and that table is often where MEMORY.md bloat
actually accumulates, because every project's status, intent, and latest-delta tend to
get appended to its row instead of folded into the project's own memory dir. A single
project row hitting 800–1300 chars is common and is a real driver pushing MEMORY.md over
its load limit. Each project has a per-project memory dir that exists precisely to hold
this detail — the Project Index row should be a one-line pointer, not the record itself.
Procedure:
Measure the table and flag oversized rows:
awk '/^## Active projects/,/^## Vocabulary/' "$MEMDIR/MEMORY.md" \
| awk -F'|' 'NF>3 && length($0)>300 {print length($0)"\t"$2}' \
| sort -rn
echo "--- Active-projects bytes / total bytes ---"
awk '/^## Active projects/,/^## Vocabulary/' "$MEMDIR/MEMORY.md" | wc -c
wc -c "$MEMDIR/MEMORY.md"
Fail-loud check: the ## Active projects range MUST match >0 lines (the table is
never empty while any project is in-flight). Zero lines = header rename, not "no bloat":
M="$MEMDIR/MEMORY.md"
n=$(awk '/^## Active projects/,/^## Vocabulary/' "$M" | wc -l)
[ "$n" -gt 0 ] && echo "OK — Active-projects range = $n lines" \
|| echo "ANCHOR MISS — '## Active projects' matched 0 rows; ABORT, the project-index prune is reading nothing."
Note: 0 oversized rows (the length>300 filter) is a legitimate clean result once the hot tier is kept lean — that can be a signal that bloat now lives in a cold-tier file instead, not a miss. The guard above checks the RANGE matched, not that rows were over-length.
Flag for prune review (do not auto-edit): every row over ~300 chars. The target row
shape is | Project | Deploy | one-line status + intent + pointer to per-project memory |
under ~250 chars.
For each flagged row, the fix is FOLD-DOWN, not deletion: move the row's accumulated detail (status history, decision notes, latest deltas) into the project's per-project memory dir — append to or create a file there — then shorten the MEMORY.md row to a one-liner that ends with a pointer (e.g. "See per-project memory."). Verify the per-project dir exists; create the file if absent. No project loses information — it moves to where it loads on demand instead of every session.
Present candidates to the user as a numbered list (length, project, current row text, proposed shortened row + where the detail will land) and wait for per-row approval before editing. Same don't-pre-empt rule as the Topic Index prune.
If you run automated handoff pruning (e.g. a daily cron script that deletes handoffs older than a threshold, always keeping the newest per dir as a dormant-project breadcrumb, and writes a report of what it pruned), retro's job is the judgment half:
[text](handoff_X.md) → text (handoff pruned), dropping the .md suffix so the scanner stops matching. Never delete whole lines; the row's summary text usually still earns its place (prune it on its own merits via the topic-index step, not because its link died).Sessions that ended without /wrap lose calibration grades, lessons, and project deltas — the kind of drift retros exist to catch. If you run a cron-driven back-fill (the wrap-stale skill via a runner script), it handles most of this, but mtime drift, timeouts, and oversized transcripts produce gaps. An audit script can identify and bucket uncovered sessions; the retro decides what to act on.
# adapt: example audit over the last 14 days of transcripts
bash <scripts>/wrap-coverage-audit.sh 14 > /tmp/wrap-coverage.csv
echo "=== bucket counts ==="
tail -n +2 /tmp/wrap-coverage.csv | cut -d, -f1 | sort | uniq -c | sort -rn
Example buckets (sessions under ~50 KB filtered out upstream):
.wrapped sidecar exists; covered, nothing to do./wrap; covered.claude -p stdout). Common causes: claude -p exited 0 with a SKIPPED message, an auto-kickoff hook injected context that derailed the agent, an API blip mid-flight.The audit is read-only — it never modifies handoffs or sidecars. Action is per-bucket and per-session; the user decides. Delete this whole sub-step if you don't run a back-fill runner.
Spawn one Explore subagent per active project (from MEMORY.md's "Active" rows). Launch 3–5 at a time in parallel. Each agent's prompt:
"Audit the memory dir for project
<project>. Report under 80 words: (1) files not touched in 2+ weeks, (2) any obviously stale content (status lines contradicted by recentgit -C ~/Projects/<project> log --oneline -20), (3) missing files that the MEMORY.md index references but don't exist on disk. If all fresh, say 'fresh'."
Collect the reports. Flag anything stale or missing for action this retro.
Fallback if subagents are unavailable — serial diff over your per-project memory dirs:
# adapt: Claude Code stores per-project memory under dirs keyed off the cwd.
# Point this at wherever yours live and diff against a recent baseline.
for d in <memory-root>/*/memory/; do echo "=== $d ==="; git -C <memory-root-repo> diff --stat HEAD~10 -- "$d" 2>/dev/null || echo "(no git history)"; done
After the §2 maintenance actions above have ACTUALLY run, write a per-run progress sentinel recording the real sub-action deltas. §5 refuses to bump any date unless this sentinel exists and shows non-trivial work — that is the machine-checkable replacement for self-attestation (which is exactly the mode that fails: a session under time pressure reports "done" without having actually done the archiving). This same file also serves as resume-state: if a retro is interrupted and re-runs the same day, read the existing sentinel first to see which sub-actions already completed and skip redoing them.
Fill the counts from what you actually did (use 0 only when a pass genuinely had nothing to do — an all-zero sentinel does NOT satisfy the §5 gate):
mkdir -p "<state-dir>"
SENT="<state-dir>/retro-progress-$(date +%F).json"
cat > "$SENT" <<JSON
{
"date": "$(date +%F)",
"calibration": {"before": <N>, "after": <M>, "archived": <K>},
"lessons": {"promoted": <P>, "archived": <A>},
"topic_index_rows_pruned": <R>,
"project_index_rows_folded": <F>,
"wrap_coverage_buckets_reviewed": <true|false>,
"per_project_staleness_reviewed": <true|false>,
"notes": "<one line: what was substantive vs. no-op this run>"
}
JSON
echo "wrote sentinel: $SENT"; cat "$SENT"
If §2 was skipped or only ran vacuously (e.g. the anchor-miss guards fired), do NOT write a "complete" sentinel — leave it absent or set the deltas to reflect that nothing substantive happened, so §5 correctly leaves the dates stale.
If you keep a personal "flag it for the agent to look at later" channel — e.g. a dedicated list in a task-list API that you (not the agent) add items to during the week, distinct from the agent's own backlog — drain it every retro. The reference setup uses a Google Tasks list for this:
gws tasks tasks list --params '{"tasklist":"<your-tasks-list-id>","showCompleted":false}'
<your-tasks-list-id>— the list ID for your personal follow-up queue. Resolve it once viagws tasks tasklists listand hard-code it here (or in a config file) since it's stable; a script or query that references it should carry this same comment so a reader knows what the ID represents.
Emails may land in this list via a mail client's "add to tasks" feature, carrying a link back to the source message. For each open item:
gws tasks tasks patch --params '{"tasklist":"<your-tasks-list-id>","task":"<task-id>"}' --json '{"notes":"<one-line outcome + pointer>","status":"completed"}'
Known misfiling mode: a mail client's "add to tasks" feature often drops items into whichever list the task app's sidebar last had selected — if you know you flagged something and this list is empty, check your default/inbox list for it (search recent items with source links) before concluding it's missing.
If an item is urgent, raise it in-session instead — this list is the non-urgent channel; retro cadence is ~4 days.
patterns.md if warranted (merge related patterns, retire obsolete ones)Executes the meta-falsification audit prescribed by rules/quality.md (the global framework) and any per-project extensions (a project may ship its own QUALITY.md with a "Calibration logs and scoring loop" + "Meta-falsification" section). Runs against every project that ships calibration logs — the discipline travels with the framework, not with any one project.
find ~/Projects -name calibration.md -not -path '*/templates/*' -not -path '*/_archive/*' | sort -u
(Prefer find over an ls-with-globstar form — the latter depends on a shell
option that's often off by default and can silently find 0 files, no-op'ing the
whole §4 quality audit without telling you.)
Skip symlinks pointing at templates and any file inside an obvious scaffold dir (templates/, examples/, _archive/).
Fail-loud guard: the find MUST return ≥1 path if you have any projects shipping
calibration logs. If it returns zero and you expected hits, do NOT report "no calibration
files / nothing to audit" silently — abort §4 loudly: "§4a DISCOVERY MISS — scanned
nothing, NOT clean; check the find predicate against the live tree before trusting a clean
§4 report."
For each calibration.md:
_(awaiting first scenario)_ or _(awaiting first probe result)_).confirmed / refuted / partial / unresolvable.partial counts as 0.5 hit; unresolvable is excluded from the denominator.)< 0.6 or > 0.95. If no project has ≥10 resolved claims yet, report "insufficient data (need ≥10 resolved claims; current: N)". Until resolutions accrue, this is the expected state.claims.json files under projects with calibration logs (find ~/Projects -name claims.json -path '*/takes/*'). Sample 10 random could_be_wrong_if entries across them. Read each from a hostile-reader stance and judge whether it names: (1) a signal to observe, (2) a procedure to check it, (3) a threshold where applicable. Count failures. Flag if >30% (i.e., ≥4/10) fail. The retro-running assistant performs this judgment itself — do not skip it just because it's subjective; that's the point of the audit.take.md) and its scope field (in claims.json or take frontmatter). Ask: does the headline mislead a reader who only sees the headline, given the actual scope? Flag if >20% of takes do. With <5 takes total, report the count and your judgment without the percentage gate.takes/, drivers/, probes/, methodology/, docs/, decision-record files — see your QUALITY.md's "what load-bearing means here"). For each, check whether the changed content includes the discipline (confidence + could_be_wrong_if + evidence on claims; calibration-log entry where applicable). Flag if the discipline was skipped on >2 artifacts in the month.Emit as a section in the retro report. Structure:
## Quality framework health
**Calibration files discovered**: N (M with resolved claims, K scaffold-only)
### Per-project audit
- <project-path>: <resolved-count> resolved claims (<bucket breakdown or "scaffold only">)
- ...
### Meta-falsification trigger checks
- (a) Calibration drift: <result or "insufficient data (need ≥10 resolved claims; current: 0)">
- (b) Falsifier vacuity: <X/10 entries fail shape rule — UNDER/OVER threshold>
- (c) Scope abuse: <count + flag status>
- (d) Friction kill: <count + flag status>
### Action items
<any flagged triggers convert to action items here; if nothing flags, write "none">
(Skip this whole section if your projects don't ship calibration logs / claims.json takes — it's the heavyweight tier of the quality framework.)
Scan your dev-estimates log (<memory-dir>/dev_estimates.md) for entries logged since the previous retro. The log captures dev-task duration estimates quoted in chat (load-bearing for ship-vs-defer decisions) versus the actual time the work took.
Per CLAUDE.md, model training data anchors on human-developer pacing, so the model systematically overestimates. The log is the recalibration mechanism.
cat <memory-dir>/dev_estimates.md
For each complexity bucket (tweak, single-file edit, new module + tests, cross-module refactor, architecture change):
(actual / estimate) ratios over entries in this period< 0.5 (i.e., consistently 2×+ over): the bucket's calibration target in CLAUDE.md / dev_estimates.md is too high. Recommend tightening the target.> 1.5 for any bucket: UNDERestimating in that bucket — the under-bias surfaced; flag it (rare but possible if scope creep is systematically excluded from initial estimates).Add a section to the retro report:
## Dev-task estimate calibration
**Entries since last retro**: N
| Bucket | Count | Median actual/estimate | Flag |
|--------|-------|------------------------|------|
| tweak | <n> | <ratio> | <ok / over / under> |
| single-file edit | ... | | |
| ... | | | |
### Recalibration recommendations
<bullet list of bucket-specific target adjustments, or "none">
Do not edit dev_estimates.md from this audit — it's the data source. Only update CLAUDE.md's bucket-target table if action items warrant.
ALL THREE date fields are GATED by the Order-of-operations section above — none of them bump unless §2 maintenance actually completed this run. That gate is authoritative; this section is subordinate to it. The machine-checkable gate is today's progress sentinel (written by §2, see "Completion sentinel" above): if it is absent or shows no real work, LEAVE ALL DATES STALE so a stale-runner (if you have one) re-fires.
Read the sentinel first:
SENT="<state-dir>/retro-progress-$(date +%F).json"
if [ -s "$SENT" ]; then echo "=== today's sentinel ==="; cat "$SENT"; else echo "NO SENTINEL FOR TODAY — §2 did not record real work. DO NOT bump any date."; fi
Bump dates ONLY if the sentinel exists AND shows non-trivial deltas (e.g. calibration archived, lessons promoted/archived, or rows actually pruned — not an all-zero sentinel from a vacuous pass over an empty read). Then:
Last retro: and Next due: in CLAUDE.md's Session Management section.Last verified: in MEMORY.md to today's date. This field claims the index was
reviewed; the §2 maintenance + per-project staleness audit IS that review. Don't
make this bump conditional on anything beyond the gate above — once §2 genuinely
ran, don't withhold the bump for cosmetic reasons. It does NOT override the gate,
though: a fresh Last verified date suppresses any stale-runner's re-fire, so bumping
it over skipped/vacuous maintenance hides the gap. A stale value that correctly signals
"re-run me" is better than a fresh value that lies.Summarize:
Optionally ping an alert channel (<notify> — e.g. ntfy/Slack/email) on any safety blocker found, so it surfaces even if you're not at the terminal.