Accumulating-List Hygiene — Design
Status: Design complete (session 2026-06-05); extended 2026-06-08 with the plan-deferral descendant (§5.6), the out-of-context bookmark revision (§5.1 / §8), and the per-item aging anti-rot primitive (§4 #8). Pending final section-by-section review. Build not yet started.
Context: This is the full scope of the parked-items / bookmark-unification
thread (see current-plan.md), expanded to swallow session lessons, the Done log,
the design catalog, and the archive idea. It supersedes the scattered
fragments — the parked-items design section, the session-lessons-as-bookmarks
bookmark, and the pruned-items archive/ directory idea — which collapse into the
one system described here.
1. Purpose
The project keeps re-inventing the same mechanism — a dated list that accumulates, needs pruning, and risks bloat — for bookmarks, session lessons, architectural bookmarks, the Done log, the design catalog. Each has been hand-managed differently. This design unifies them under one type system, one base format, one set of shared primitives, and one housekeeping ledger, so every list/doc is maintained the same way and nothing grows unbounded or silently rots.
2. Type vocabulary
Four types. (The word "tier" is retired — it had been pointed at two different axes and is too overloaded to keep.)
- List — a live backlog things flow through: capture → triage → exit. Three
axes describe any List:
- Scope — which layer owns it: personal / Yggdrasil / Odin Codin' / a specific project. Determines where the store physically lives.
- State — how live an item is: hot (plan-deferral) → active → cold (backburner).
- Context-load — whether the store is routinely loaded into context (in-context) or deliberately kept out (out-of-context, a separate file).
- Target — a graduation sink: where a promoted item lands and stays active / in-context (the Done log, the design catalog, an AGENTS/CLAUDE convention).
- Archive — a prune sink: the append-only, out-of-context record where retired items go. The "never gets deleted" log.
- Scratchpad — transient work-state with a delete-when-done lifecycle (e.g.
working/hygiene.md). Not a parked item (no triage, graduation, or archive) — named here only to draw the boundary. Its hygiene is a deliberate scope-out, deferred to a bookmarked follow-on (see §10).
Core model: a List has exactly two exits — promote to a Target or prune to an Archive. Graduation can be multi-hop (bookmark → catalog → AGENTS/CLAUDE convention).
3. Base format primitive — a dated prose bullet
Every entry in every list/doc/archive inherits this parent:
- **YYYY-MM-DD** — <freeform prose content>
- Date (mandatory). All hygiene keys off dates — age-drain, the 7-day "been-a-while" trigger, review cadence. One ledger can drive every list only because every entry is dated.
- Content (freeform prose). Notes-to-self register; markdown allowed; multi-line fine.
- Deliberately NOT fielded. No
why / depends-on / statusform — same design value as the planning skill's verifiable-outcome anchor over a fixed schema. A rigid schema, if ever wanted, belongs to a domain-driven toolkit one layer up, not the base. The "why" lives inside the prose.
Optional shared kit (any descendant may opt in):
- Bold lead —
**Punchline.**opening the content; a scannable title before the elaboration. Earns its keep on longer entries. - Dated-update append —
**Update YYYY-MM-DD:** …to evolve an entry without losing the original. Archiving reuses this: an archived entry = original +**Archived YYYY-MM-DD** — reason. - Inline tags — lightweight square-brace markers riding on the prose line,
e.g.
[soon](not YAML — markdown list items can't carry frontmatter).
4. Shared primitives
The reusable pieces every descendant draws on:
- Entry format — §3.
- Ledger (
.meta/ledger.yaml) — §7. - Bloat nudge — tiered count thresholds (
<10celebrate ·10+heads-up ·15+warn ·20+firm> **Gate:**-style push) + a 7-day "been-a-while" reacclimation trigger when a count has sat in the 10+ band. - Cadence-gated review — a hygiene sub-pass that fires only when the ledger says it's due; offered (Yes/No), never forced; silent when not due.
- List lifecycle — capture → triage → exits (graduate up / archive / demote-to-cold).
- Scope-routing — per-layer ownership; each layer owns its own stores.
- Capture — the
/bookmarkingskill (§6). - Item-aging (anti-rot) (added 2026-06-08) — the per-item complement to
the count-based bloat nudge (#3). #3 is anti-bloat (keep the pile small); #8
is anti-rot (keep the pile from silently going stale). Every entry is already
date-stamped (§3), so the bookends / hygiene pass surface items left
untouched past ~14 days (uniform threshold, 2026-06-08) as an
informational signal — "these have aged; want a look?" — offered, never a
forced review (the demand-free 'tism principle applied to hygiene itself).
The action on an aged item varies by descendant (revive / promote / demote /
graduate / archive / prune); the Done log's existing age-drain (§5.4) is the
prototype. Re-touching an item (e.g. re-deferring, a
**Update YYYY-MM-DD:**) updates its date and resets the clock — alive but never pushed. Net: every live list gets anti-bloat (#3) + anti-rot (#8) baked in.- Applies to: Deferred (§5.6), active bookmarks (§5.1), backburner (§5.3), session lessons + catalog (§5.2). The Done log already has it (§5.4 drain). The Archive (§5.5, pure sink) and Scratchpads are exempt.
- Surfaced from the ledger, not by loading: for out-of-context stores the
hygiene pass stamps a small per-list aged summary (§7) so the bookends can
flag aged items without loading the store. The ~14d threshold is a first
guess — bookmarked (
yggdrasil/bookmarks.md) to revisit after real use.
5. The descendants
Each list/doc specced as a descendant of the base format (§3).
5.1 Active bookmarks
- Kit: bold lead (optional) · dated-update (yes) · tags (
soon). - Grouping: none — flat under a single
# Bookmarksheader. - Scope / load: per-layer
<repo>/bookmarks.md; out-of-context, on-demand (revised 2026-06-08). Not auto-loaded into context — read only when explicitly reached for (asking "what's in bookmarks?", working a specific topic, or opting into a ledger-flagged review). Rationale: context economy — quick sessions never pay for bookmarks they don't need. Anti-rot does not depend on loading: the bookends flag count + aged items from the ledger stamps (§7), and the human opts in to reading the file. (Revises §5.1's original "in-context" classification; same out-of-context boundary §5.3/§5.5 already use.) - Hygiene: bloat nudge counting active +
soon(kept — active bookmarks still want curation discipline, unlike the cold backburner which relaxes it; surfaced via the ledger now that the store is out-of-context); item-aging (§4 #8) surfaces stale bookmarks for revive / demote / prune; demote far-future → backburner. Cadence-gated, ledger-stamped. - Exits: graduate (task / convention / catalog) · archive · demote → backburner.
- Capture:
/bookmarking— scope-aware, default-active, optionalsoonhint. - Note:
soonis active-only (means do-next priority; meaningless elsewhere). No "resolved" tag — resolution → prune → archive.
5.2 Knowledge stores — Session lessons + Design decisions catalog
Near-twins; treat the catalog like session lessons.
- Shared: in-context · bold lead (yes) · dated-update (yes) · optional graduation marker · cadence-gated review + quantity nags, ledger-stamped · exits = graduate up (→ AGENTS/CLAUDE convention) / archive.
- Session lessons — flat; at
## Session lessons. Migration: convert per-session blocks → individual dated entries. - Catalog — keeps topic
###grouping (the only descendant with subheads); at## Design decisions catalog. Migration: add dates (currently undated). Review = staleness/graduation only; settled ≠ re-litigation.
5.3 Cold storage — Backburner
- Out-of-context, separate file
backburner.mdper scope · flat · bold lead optional · nosoontag. - Hygiene: no tight count-nag (not loaded → bloat is cheap); a ~weekly review in the hygiene pass (revive / promote / archive), ledger-stamped. The review is the hygiene.
- Fed by: demotion from active (primary) + optional direct
/bookmarking "backburner this"hint. - Exits: revive → active · graduate → target · archive. Absorbs the old architectural bookmarks as plain entries.
5.4 Completion log — Done log
- In-context · phase-grouped, two-tier · bold topic on granular entries · no dated-update · no tags.
- Hygiene (self-bounding; no review, no nags): inner phase-compaction
(closed phase → one-line summary, stays) + age-drain (granular bullets
7d → archive, but keep the 5 most-recent entries regardless of age — a tunable floor so a dormant project still shows recent context). Ledger-stamped for the drain cadence. (Age-drain, and thus the floor, is Done-log-only — every other descendant reaches the archive via review/prune, not by aging out.)
- Exits: age-drain → archive (granular bullets). Phase one-liners stay as the lightweight arc. No graduate exit — terminal for executed work.
5.5 Archive (the sink)
- Terminal sink, not a triage list. Inherits the dated prose bullet; archived
entry = original +
**Archived YYYY-MM-DD** — [reason if meaningful](aged-out Done entries need no reason; their own date tells it). - Home: per-scope
archive/directory, one file per source —archive/bookmarks.md,archive/session-lessons.md,archive/done-log.md,archive/catalog.md. A scope only gets files for the lists it actually has (the personal layer'sarchive/would just holdbookmarks.md). (Directory namedarchive/— renamed fromhistory/2026-06-08 to match the Archive type name, so the type and its home are name-aligned.) - Index —
archive/README.md(added 2026-06-08). A human-browsable manifest co-located in the directory: one line per archive file naming what it holds. Keepsarchive/self-documenting once it grows past the four list-archives, whose names self- explain only because they mirror the known lists — a strayhygiene.mdwould otherwise be off the map. Out-of-context; browsed on demand. Co-located (not in the ledger) per §7: it's human-browsable, so it co-locates with the files rather than consolidating into the machine ledger. - Standard header (added 2026-06-08). Every archive file — the four canonical and
any added later — opens with the same header shape: a
# Archive — <Source>title plus a line stating it's the append-only, out-of-context record for that source (never pruned; entries are dated prose bullets, original +**Archived YYYY-MM-DD** — reason). One shape so all archive docs read alike. - Adding a non-canonical archive file (the convention) (added 2026-06-08). When the
hygiene pass drains a source that isn't one of the four list-archives (a scratchpad
like the hygiene/drift store, or the research-reports cousin), it does three things: (1)
names the file kebab-case after its source (
hygiene.md); (2) gives it the standard header above; (3) adds its line toarchive/README.md. This small recurring upkeep is what keeps the archive findable as it accretes arbitrary sources. Also stated as an AGENTS.md house-style line, and it travels to descendent scopes when the system is reproduced there (the deferred per-layer rollout). - Grouping: chronological append (optional year subheads only if it ever gets huge).
- Context-load: out-of-context; read only on explicit request.
- Hygiene: none on content — strictly append-only, never pruned/reviewed/nagged.
(The only upkeep is creation-time: when a new archive file is first created, add its line
to
archive/README.md— see the convention below.) - Ledger: none (pure sink; sources own their drain cadence).
- Fed by: the hygiene pass, whenever it prunes/drains any live list.
- Per-source over combined: machine-read state consolidates (nothing browses it); human-browsable records separate by kind, for retrieval.
5.6 Plan-deferral — the Deferred section
(Added 2026-06-08.) Logically the hottest List — it would sit ahead of 5.1; placed last only to avoid renumbering. This is the descendant §2 pointed at ("hot (plan-deferral)") but never specced, because its home is a plan — so it belongs to the planning skill. Designed alongside that skill's §10 No-Placeholders carve-out; the two are the same artifact.
- Home / load: a dedicated
## Deferredsection inside the plan doc — the one parked-item store that's in-context, because heat ↔ context-load: the hottest items live with the active work they may promote into. - Kit: bold lead (optional) · dated-update (yes — re-deferring appends
**Update YYYY-MM-DD:**and resets the age clock) · nosoontag (the section is already the do-ish-soon end). - Notation: the base dated-prose bullet carrying a revival trigger in the prose — encouraged, never required. The trigger is forward-looking ("what brings this back"): a dependency, an external event, a judgment call, or an honest soft one ("didn't feel like it today" / "no spoons for this right now"). The skill recommends a sharper trigger when none is given but never pushes (calm house style; demand-free per the 'tism principle).
- What makes an item "tracked" (the No-Placeholders carve-out): placement in the Deferred section is the tracking — dated, in a known, reviewed place — not the trigger's quality. The planning skill's Self-Review enforces only this: every entry in the active task list is either fully spelled out or moved here. It catches the masquerade (a vague "TBD" posing as an actionable task), never the motivation for a deliberate deferral. A soft trigger is fine; an untracked TBD hiding in a task body is not.
- Hygiene: bloat nudge (an in-context List — counts toward the 10/15/20 thresholds) · item-aging (§4 #8): hard-trigger deferrals resurface by condition (did the trigger fire?), soft-trigger ones by age (~14d), both as informational offers. Cadence-gated, ledger-stamped.
- Exits: promote → active task (trigger fired / ready to detail — moves up
into the task list; heats + loads) · demote →
bookmarks.md(turns out bigger-than-this-plan or not really this plan's job — an offered, never forced "want to cool this out to bookmarks?" that cools + unloads; the pressure-valve for chronically re-deferred items) · prune → archive (decided against). - Flow position: the hot middle of
project-bookmark → plan-deferral → task— promote moves an item one notch hotter (and into context), demote one notch cooler (and out of context).
6. Capture — the /bookmarking skill evolution
Already a live, auto-invocable skill (no disable-model-invocation;
allowed-tools: [Read]). Evolve, don't replace. Capture-only — all
maintenance lives in the hygiene pass (§8), keeping the auto-firing skill lean.
- Strip the dead
/bookmarkcommand references (no such command exists). allowed-tools: [Read, Glob, Grep]— Glob to locate the scope store, Grep to dedupe-check before appending. Write/Edit stay out → the mutation still prompts.- Add scope-awareness (capture to the right layer's store).
- Add an optional backburner hint ("backburner this").
- Grow the description to carry trigger synonyms per state ("backburner this," "park for someday," "soon," …) — load-bearing for conversational invocation.
7. The ledger — .meta/ledger.yaml
One per-scope, machine-maintained (bookend-written) file consolidating all the small date-stamps/counters. Governing principle: co-locate human-maintained metadata; consolidate machine-maintained metadata — the commands keep it in sync atomically, so the usual separate-file sync-seam objection doesn't apply.
skills:
learning_new_skills: { last_run: 2026-06-01 }
lists:
active_bookmarks: { last_pruned: 2026-06-05, count_band_since: 2026-06-04, count: 18, aged_count: 3 }
backburner: { last_reviewed: 2026-05-20, count: 6, aged_count: 6 }
session_lessons: { last_reviewed: 2026-06-04 }
catalog: { last_reviewed: 2026-06-04 }
done_log: { last_drained: 2026-06-05 }
Sectioned by concern (skills vs lists). Absorbs the existing
.meta/learning-new-skills.yaml (retired into this file). The Archive needs no
entry (pure sink).
Aged-summary stamps (added 2026-06-08). For out-of-context stores, the hygiene
pass refreshes a small per-list count + aged_count (items untouched past the
~14d threshold, §4 #8) when it runs, so the bookends can surface bloat/aging
signals from the ledger alone, without loading the store. Best-effort — the
numbers are as fresh as the last hygiene pass; that's fine for an informational
nudge. In-context lists (the Deferred section) don't need the stamp — they're read
live anyway.
8. Command structure / wiring (flagged this session — own follow-on)
All the hygiene above bloats /save-progress. Proposal (2026-06-05): merge
/sweep + /consistency-check into a single /hygiene-check (name TBD)
holding all the housekeeping as distinct, cadence-gated steps, and move the
AskUserQuestion "do you want to do this" gates out of /save-progress into
it. /save-progress then offers /hygiene-check rather than embedding it;
/good-morning surfaces what it produces. This supersedes the earlier
"extract /sweep as its own sibling command" bookmark (bookends cluster) — going
further, to one consolidated hygiene command.
Steps it would hold (each cadence-gated, ledger-stamped, offered):
- active-bookmark prune + bloat-nudge
- active → backburner demotion
- backburner review
- session-lessons review + nags
- catalog review + nags
- Done-log age-drain
- consistency-check (drift between durable docs)
/good-morning bootup loading. On session start /good-morning must actively
load the list state it needs. Today it reads current-plan.md + the manifest docs,
but the manifest deliberately excludes bookmarks.md, so bookmarks are never
surfaced. Under this system it reads .meta/ledger.yaml to learn which
cadence-gated reviews are due (and flag them) and to surface the bookmark
count + a high-count flag (bloat nudge) plus any items aged past the threshold
(anti-rot, §4 #8) — all from the ledger stamps, without loading the stores
themselves (revised 2026-06-08: bookmarks are now out-of-context; the human opts
in to reading the file). It respects the context-load boundary: out-of-context
stores (bookmarks.md, backburner.md, archive/) are not loaded —
good-morning reads only their ledger stamps to flag a review or aged items as
due. This also closes the standing gap where /good-morning advertises surfacing
working/hygiene.md but has no step that reads it (bookends-cluster
bookmark).
Design this command properly as its own follow-on — it's build-wiring, not part of the list type-system.
9. Migrations (for build)
- Evolve
/bookmarking(§6). - Stand up
.meta/ledger.yaml; retire.meta/learning-new-skills.yamlinto it. - Stand up
backburner.mdper scope; move architectural bookmarks into it. - Stand up per-scope
archive/files. - Flatten
## Session lessonsblocks → dated entries. - Add dates to
## Design decisions catalog. - Wire the Done-log age-drain.
- Nuke the
## Bookmarks to fold into bookmarks.mdstaging section (live capture supersedes it). - Build/merge
/hygiene-check(§8). - Update
/good-morningto load/surface list state on bootup — bookmarks count + high-count flag, ledger-driven review-due signals, the consistency-check scratchpad — while respecting the out-of-context boundary (don't loadbackburner.md/archive/; flag from ledger stamps only). See §8.
10. Open / deferred
soonflag — notation settled as[soon](§3); only trivial build-time details remain (line placement, auto-clear on handling). Tiny convenience./hygiene-checkcommand — §8; its own follow-on design.- Anti-rot threshold (~14d, §4 #8) — a first guess; revisit after real use
(whether it nags too often or lets things rot; possibly tier by list heat).
Bookmarked in
yggdrasil/bookmarks.md(2026-06-08). - Scratchpad hygiene (deferred follow-on; bookmark "soon"). Scratchpads
aren't parked items (delete-when-done), so their cleanliness mechanism is scoped
out of this design and rides with the
/hygiene-checkbuild. Recorded lean: on resolution, delete the scratchpad — git history already preserves it, and resolved drift-checks aren't browse-worthy like completed work or retired ideas (vs. draining toarchive/). Instances: consistency-check scratchpad (already partly covered by the bookends-cluster bookmark) · research reports (dated-file cousin).
11. Decision log
- Retire "tier"; use Scope + State + context-load. It was pointed at two axes.
- Base format = freeform dated prose, not fielded. Same value as the planning verifiable-outcome anchor; rigid schemas belong to domain-driven toolkits a layer up.
- State as separate stores, not one flagged store — driven by context-economy
(cold = separate file = not loaded). The only flag is
soon. - Architectural bookmarks merged into backburner — they were just cold items; "architectural" was altitude, not a lifecycle.
- Catalog + session lessons share one hygiene profile — settled ≠ frozen; periodic staleness/graduation review, not re-litigation.
- Done log: incremental age-drain, not whole-doc rotation — rotation was described but never fired (doc at 903 lines); per-entry drain with a min-recent floor is strictly better.
- Archive: per-source files in
archive/, append-only, zero hygiene — separate human-browsable records by kind; consolidation logic applies only to machine-read state (the ledger). - Ledger: one consolidated per-scope file. The stamps are machine-written (by the bookend / hygiene commands), so one shared ledger is safe — there's no "human forgot to update it" sync seam. (The rule behind it: co-locate human-maintained metadata with its file; consolidate machine-maintained metadata — the ledger is the machine-maintained half.)
/bookmarking: evolve, capture-only — maintenance lives in the hygiene command; the skill stays lean and auto-invocable.- Tracked-deferral = the plan-deferral descendant (§5.6), homed in the plan doc (2026-06-08). What makes a deferral tracked is placement in the Deferred section, not the trigger's quality; the No-Placeholders check catches only a vague TBD masquerading as an active task, never the motivation for a deliberate deferral. Triggers are encouraged-not-required; soft ones ("didn't feel like it") are first-class.
- Bookmarks → out-of-context, on-demand (§5.1) (2026-06-08, revises the
2026-06-05 in-context call). Context economy: quick sessions never load
bookmarks. Anti-bloat (count-nudge, kept) and anti-rot (aging) both survive
via the ledger — the bookends flag from stamps; the human opts in to reading.
Also supersedes the 2026-06-03 single-doc "fold bookmarks into the plan" call
— a separate
bookmarks.mdstands, no migration needed. - Per-item aging (§4 #8) added as anti-rot across all live lists (2026-06-08). The count-nudge is anti-bloat; aging is anti-rot — surface items untouched past ~14d, informationally, never a forced review. Near-zero cost (entries already dated). The Done-log drain is the prototype; the action varies per list.
- Heat ↔ context-load alignment (2026-06-08). At the plan↔bookmark boundary, State and context-load move together: promoting heats-and-loads, demoting cools-and-unloads. The Deferred section is the one in-context parked store (hottest); bookmarks/backburner/archive are out-of-context. Demote-to-cooler is the bloat pressure-valve — offered, never forced.
- Inform-don't-demand is a load-bearing design constraint, not just tone
(2026-06-08). Triggers optional, reviews offered, the aging signal
informational, demote an offer — all flow from the autonomy/PDA + variable-spoons
accommodation now standing in
personal/CLAUDE.md→ "Design without a demand character." Captured as a 2026-06-08 session lesson. - Human-set
config:lives inside the machine ledger — a sanctioned bend of §7 (2026-06-09). §7 says consolidate machine-maintained metadata, co-locate human-maintained metadata; the tunable knobs (bloat,reacclimation_days,aging_days,cadence_days,done_log) are human-set, so by the letter they'd co-locate, not sit in the ledger. We put them there anyway, in a demarcatedconfig:section separate from the machine-writtenskills:/lists:stamps. Why: (1) the knobs are read together with the counters they govern (the bloat nudge comparescountvsbloat; aging vsaging_days), so co-locating with those counters is the natural read; (2) single-source-at-runtime — both/hygiene-checkand/good-morningread them from one file, so tuning is a one-field edit both honor, with no per-command drift. Safety (preserves §7's real concern): the hygiene restamp writes onlyskills:/lists:, neverconfig:— the machine never clobbers the human's knobs, and there's no reverse "human forgot to update" sync seam. Rejected: a separate.meta/hygiene-config.yaml— keeps §7 unbent but splits the knobs from the counters they're compared against, and adds a second file to load. Chose cohesion. Propagation: recorded as an AGENTS.md tunable-knobs pointer (plan C4) and travels to descendent scopes — a sanctioned convention, not an accident. Surfaced by the Constraint-Guardian lens (the bend was real but unlogged); this entry logs it.