diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index a6f75bf..09d072e 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "throughline", "description": "Continuous, state-aware session memory for Claude Code. Captures what you did and what is (commands, file changes, decisions, and live git/PR state), then hands it off with judgment at session wrap-up. Readable, committable artifacts; binds to Claude's native memory.", - "version": "0.6.0", + "version": "0.6.1", "author": { "name": "Dynamic Agency", "email": "support@dynamicagency.com" @@ -9,5 +9,5 @@ "homepage": "https://github.com/dynamic/throughline", "repository": "https://github.com/dynamic/throughline", "license": "MIT", - "keywords": ["memory", "handoff", "session", "context", "continuity", "compaction"] + "keywords": ["memory", "handoff", "session", "context", "continuity", "compaction", "git-state", "cross-harness", "resume", "onboarding"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 6414c84..6a51cf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,57 @@ All notable changes to throughline are documented here. Format loosely follows [Keep a Changelog](https://keepachangelog.com/); this project uses semantic versioning. +## [0.6.1] + +Docs/skill polish batch from the v0.4.0 audit (docs/AUDIT-v0.4.0.md, P2, items +#8/#10/#11). No hook behavior change - verified by the unchanged +154-assertion suite plus shellcheck under both Homebrew and an +`apt-get install shellcheck` Ubuntu container. + +### Added +- **Issue #8** - the session-log template (`throughline-handoff` Phase 3) gains + a "What we tried (including what failed)" section, with guidance to record + real evidence (the actual command/error/number), not a summary - a failed + approach is the most expensive thing for a future session to rediscover from + scratch. A **Follows** line lets a log name its predecessor in the same work + stream, so a reader can walk the decision history log-to-log without + HANDOFF.md having to carry it. +- **Issue #10** - a new README "Housekeeping" section documents what's safe to + delete (old archived buffers, a resolved `.capture-errors`) versus what + isn't (`logs/`, `HANDOFF.md`, unarchived buffers) - deliberately a + documented convention, not automated tooling, matching the plugin's + zero-infrastructure identity. The handoff skill (Phase 4) now also clears + `.capture-errors` once its contents have been surfaced in a session log, + instead of leaving it to nag on every future onboard indefinitely. + +### Changed +- **Issue #11 polish batch**: the handoff skill's Phase 4.4 no longer offers + "(or delete)" for consumed buffers - archive-only removes an unguarded + data-loss affordance. Phase 4.3's memory-binding step now cites the actual + native auto-memory layout (`MEMORY.md` as a 200-line-truncated index, one + topic file per entry under `~/.claude/projects//memory/`) and inlines + a one-line frontmatter example, so an executing model can't produce a + malformed entry. `plugin.json` keywords gained `git-state`, + `cross-harness`, `resume`, `onboarding` - the prior list under-sold the + differentiators. `tests/run.sh`'s header now states it is the single + source of truth for the current assertion count (it prints its own total), + after prose counts drifted across releases before (71/83/88/95 at + different points). + +### Fixed (found during review, before merge) +- **The memory-binding frontmatter example didn't match reality**: every + actual memory topic file (`~/.claude/projects//memory/*.md`) carries + `node_type: memory` and `originSessionId` under `metadata`, both omitted + from the template this release added - so an agent following it verbatim + would have written a schema-inconsistent entry, the exact failure the + change claimed to prevent. Verified against every real memory file in the + harness (100% carried both fields); the template now matches. +- **Em-dashes in new content**: the new Housekeeping section (README) and + session-log/Phase-4 additions (`throughline-handoff` SKILL.md) used + em-dashes, violating this user's global no-em-dash writing-style rule - + in `handoffs`, a category the rule names explicitly. Replaced with commas, + colons, periods, or spaced hyphens per the rule. + ## [0.6.0] Issue #9 from the v0.4.0 audit (docs/AUDIT-v0.4.0.md, P2): inline post-compaction diff --git a/README.md b/README.md index ed327a7..6c200b7 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,36 @@ Gitignore both for whichever data dir you use: > `!/.claude/throughline/logs/`) or set `THROUGHLINE_DATA_DIR=.agent/handoff` so the > committed artifacts sit outside the ignored tree. +## Housekeeping + +Everything throughline writes grows without automatic bound: there is no +background cleanup process, deliberately, to keep the plugin's footprint at +"pure POSIX sh + jq, zero infrastructure." What's safe to clean up by hand, +and what isn't: + +**Safe to delete:** +- `buffer/archive/*.md` older than your last `throughline-consolidate` pass - + once a consolidation has mined a log for recurring lessons, an archived raw + buffer behind it has nothing left to give. As a simple rule of thumb, an + archived buffer older than ~90 days with no open question against it is safe + to remove. +- `.capture-errors`, once its contents have been surfaced in a session log and + cleared by the handoff skill (Phase 4): it's a breadcrumb meant to be read + once, not a running log. + +**Not safe to delete:** +- `logs/`: these are the evidence trail. `throughline-consolidate` explicitly + never prunes them, and HANDOFF.md's own "Recent Session Logs" list only ever + points at the last 5, so older logs are already off the beaten path without + needing to be deleted. +- `HANDOFF.md` itself, obviously - it's the durable record. +- Any buffer still in `buffer/` (not yet archived) - it may be an in-progress or + unconsumed session; run a handoff first, which moves it to `archive/` once + distilled. + +There's no automated retention policy beyond this: clean up by hand on the +cadence above, or leave it, a growing `archive/` costs disk, not correctness. + ## Auto-handoff at wrap-up (optional reinforcement) The handoff skill is written to run proactively when the agent detects the session diff --git a/skills/throughline-handoff/SKILL.md b/skills/throughline-handoff/SKILL.md index a5e2a24..8b5c8d0 100644 --- a/skills/throughline-handoff/SKILL.md +++ b/skills/throughline-handoff/SKILL.md @@ -71,6 +71,7 @@ Create `DATA/logs/handoff-YYYY-MM-DD-HHMM.md` (local time; create `logs/` if nee ```markdown # Handoff: **Date:** **Session:** +**Follows:** [](handoff-YYYY-MM-DD-HHMM.md) ## Objective The big-picture goal of the session. @@ -79,6 +80,14 @@ The big-picture goal of the session. Distilled from the capture buffer + conversation: commands run, files changed, decisions made — with the *why*. +## What we tried (including what failed) +Approaches attempted and abandoned, with the REAL evidence: the actual command, +error text, or number that killed the approach, not a summary of it. A failed +approach is the most expensive thing for a future session to rediscover from +scratch; a summary like "tried caching, didn't work" gives a future session +nothing to avoid re-trying. Omit this section only if nothing was actually tried +and abandoned this session. + ## Progress ### Completed ### In progress ### Not started @@ -96,6 +105,11 @@ Ordered, specific — exact commands, paths, expected outcomes. Key paths, URLs, credential locations (names only). ``` +**Chain link:** if this session continues work a prior log already started (same +work stream, not just the same project), name that predecessor in the **Follows** +line above so a reader can walk the decision history log-to-log without HANDOFF.md +having to carry it. Omit the line entirely for a session that starts something new. + --- ## Phase 4: Update durable HANDOFF.md + memory binding @@ -107,12 +121,34 @@ Key paths, URLs, credential locations (names only). 3. **Memory binding (native system):** ask "did this session surface a durable fact worth pinning?" Types: a confirmed preference (`feedback`), a fact about the user/context (`user`), a project constraint/decision (`project`), a resource - pointer (`reference`). If yes, write it to the native memory dir - (`~/.claude/projects//memory/`) using the established frontmatter and - update `MEMORY.md`. This promotion is **curated** — never auto-dump the buffer - into memory. One entry per genuine insight; skip if nothing new. + pointer (`reference`). Native memory is two layers: `MEMORY.md` is an + always-loaded index (truncated past 200 lines, so every entry there must stay a + single short line), and each entry's full content lives in its own topic file + under `~/.claude/projects//memory/`, read on demand. If yes, write the + topic file with frontmatter shaped like this, then add its one-line pointer to + `MEMORY.md`: + ```markdown + --- + name: short-kebab-case-slug + description: one-line summary used to judge relevance in a future session + metadata: + node_type: memory + type: feedback # or: user, project, reference + originSessionId: + --- + ``` + This promotion is **curated**: never auto-dump the buffer into memory. One entry + per genuine insight; skip if nothing new. 4. **Consume the buffers:** move distilled `DATA/buffer/session-*.md` into - `DATA/buffer/archive/` (or delete) so they aren't re-processed next session. + `DATA/buffer/archive/` so they aren't re-processed next session. Archive only, + never delete: an archived buffer is the recovery path if a distillation later + turns out to have missed something. See "Housekeeping" in the README for when an + archived buffer is old enough to actually delete. +5. **Clear resolved breadcrumbs:** if `DATA/.capture-errors` exists and its contents + were surfaced above (as a Phase 2 "Resolved Issues" entry or in the session log), + clear the file now that it has been distilled - it exists to make a swallowed + capture failure visible exactly once, not to keep nagging on every future onboard + after it's already been read and acted on. --- diff --git a/tests/run.sh b/tests/run.sh index da14c1f..3255972 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -5,6 +5,13 @@ # and asserts on the resulting buffer / stdout. No network, no model, no deps # beyond jq + coreutils + git. Run: sh tests/run.sh (exit 0 = all passed). # +# This file is the single source of truth for the current assertion count - +# it prints its own total ("passed: N") on every run. Historical assertion +# counts have drifted in prose before (CHANGELOG/HANDOFF entries citing 71, +# 83, 88, 95... at different points, issue #11): if you cite a count in +# prose, anchor it to a specific version ("143 assertions as of v0.5.2") or +# just point here instead of hardcoding a number that will go stale. +# # Test fixtures legitimately contain literal markdown backticks and $ inside # single quotes, so SC2016 (no-expansion-in-single-quotes) is expected here. # shellcheck disable=SC2016