Accumulating-List Hygiene + Bookend Worktrees Plan
Goal: Build the accumulating-list-hygiene system for Yggdrasil and wire the session-bookend worktree lifecycle, as one cohesive build.
Approach: Three phases on a dependency chain. Phase A stands up the
independent stores and migrations (ledger, backburner, history archive, in-plan list
migrations, the /bookmarking evolution) — none of which touch the bookends.
Phase B builds the /hygiene-check command that operates those stores. Phase C
is the convergence: the combined /good-morning + /save-progress rewrites that fold
in both the list-hygiene surfacing and the bookend worktree lifecycle, since both
builds rewrite those same two commands.
Design source: working/2026-06-05-list-hygiene-design.md
(primary) + the bookend-worktree design in
working/current-plan.md → "Bookends — the active build (2026-06-08)"
and "Git working-tree discipline — design-complete (2026-06-04)".
Scope: Yggdrasil only. The personal layer (bookmarks-only) and odin-codin
(skeleton, no lists) are out of scope — personal-layer rollout is parked in ## Deferred.
Execution: isolation & resumption
Isolation. This plan is git-backed Yggdrasil work, so execute it on its own session
branch under .worktrees/ (off main), merging back when the work checks out — never
editing main directly without consent. This plan builds the bookend worktree lifecycle
in Phase C, so until that lands the isolation is set up by hand, in two steps in order:
- Step 0 — gitignore first (before any worktree exists): ensure
.worktrees/is in.gitignoreand committed, so the bootstrap worktree never shows as untracked or gets committed into itself. (Normally a C1 concern, but it MUST precede the manual bootstrap — see C1, which just confirms it's committed.) - Step 1 — create the worktree:
git worktree add .worktrees/session-2026-06-09 -b session-2026-06-09 HEAD(substitute today's date), then do all work inside it.
Resumption (the build spans /clear'd sessions). A fresh Claude reopening this plan
mid-build learns "where am I" from disk state, not memory: every task's Confirm-by is
an idempotent disk check, so a task is already done if its Confirm-by already passes,
and re-running it is a no-op. To resume: walk from the top, skip any task whose
Confirm-by already holds, do the first that doesn't. A phase is complete when all its
tasks' Confirm-bys pass. The ## Progress checklist below is a quick where-am-I index,
but a convenience layer only: a checked box claims the Confirm-by passed, yet the
Confirm-by stays ground truth — re-verify on resume, since a box can drift from reality
(e.g. work reverted in a discarded worktree). This is why every Confirm-by is written as a
disk-state check, not "did I do it."
Phases & progress
- Phase A — Independent migrations: A1–A7 (ledger, archive, backburner, in-plan
migrations,
/bookmarking, the## Deferredsection). - Phase B — The
/hygiene-checkcommand: B1–B4. - Phase C — The convergence: C1–C5 (
/good-morning+/save-progressrewrites + worktree lifecycle + puppet fix + docs + final verification).
Progress checklist — a quick where-am-I index. A checked box claims the task's Confirm-by passed, but the Confirm-by stays ground truth (re-verify on resume — a box can drift if work was reverted/discarded). Check boxes as you go; commit them with the work.
- A1 — Stand up
backburner.md+ migrate architectural bookmarks - A2 — Stand up the
archive/directory (+ README, verbatim header) - A3 — Stand up
.meta/ledger.yaml(config + stamps; graduate notes; honest seed) - A4 — Flatten session lessons into dated entries (by pattern)
- A5 — Date the catalog + delete the staging section
- A6 — Evolve the
/bookmarkingskill - A7 — Stand up
## Deferredincurrent-plan.md(canonical Yggdrasil-wide store) - B1 —
/hygiene-checkskeleton + active-list curation steps - B2 — Knowledge-store review steps
- B3 — Done-log hygiene step (+ one-time normalization)
- B4 — Consistency-check step + retire
/consistency-check - C1 —
/good-morningrewrite (worktree lifecycle + ledger surfacing) - C2 —
/save-progressrewrite (disposition + pin + offer/hygiene-check) - C3 — Puppet fix (decouple bootstrap from
/good-morning) - C4 — Consolidated AGENTS.md / durable-docs update
- C5 — Final verification pass (walk all Confirm-bys; reconcile the boxes)
Phase A — Independent migrations
Order note: A3 (ledger) runs after A1 and A2, so it can seed counts from stores that already exist. The others are order-independent.
Task A1: Stand up backburner.md + migrate architectural bookmarks
Touches: new backburner.md (Yggdrasil repo root); the ## Architectural bookmarks
section in current-plan.md.
Create backburner.md as the per-scope cold-storage store (design §5.3:
out-of-context, flat, optional bold lead, no soon tag). Open it with a short
header naming it as Yggdrasil's backburner — cold/backburner items, reviewed on cadence,
not loaded into context. Then move every entry from current-plan.md's
## Architectural bookmarks section (the five items: Agent teams · Self-hosted web UI /
Hermes-style harness · LSB social-license conversation · Public release of Yggdrasil/Odin
Codin' · creating-workflow-skills as the first "create things" skill) into it as dated
prose bullets (- **YYYY-MM-DD** — …). Date each from git blame of its line (when it
was added); if not readily determinable, stamp 2026-06-08 (the migration date). Preserve
each item's full text. Finally, remove the ## Architectural bookmarks section from
current-plan.md.
Done when: backburner.md exists holding all five architectural items as dated
entries, and the ## Architectural bookmarks section is gone from current-plan.md.
Confirm by: open backburner.md (five entries, all dated, text intact); grep
current-plan.md for "Architectural bookmarks" (no section heading remains); eyeball that
no item's content was dropped.
Task A2: Stand up the archive/ directory
Touches: new archive/ directory at Yggdrasil repo root, with four source files —
archive/bookmarks.md, archive/session-lessons.md, archive/done-log.md,
archive/catalog.md — plus the index archive/README.md.
Create the archive/ directory and the four per-source archive files (design §5.5: the
append-only, out-of-context prune sinks — one file per source kind). Give each the
standard archive header — this verbatim template (copy it literally so every archive
file across every scope reads identically; <Source> / <source> are the only
substitutions):
# Archive — <Source>
Append-only, out-of-context record of retired <source> items. Never pruned, reviewed, or
nagged. Entries are dated prose bullets, each the original + `**Archived YYYY-MM-DD** — reason`.
Bodies start empty — nothing has been pruned yet; these are the sinks Phase B's hygiene
steps drain into. Also create archive/README.md, the index (design §5.5), seeded with
one line per file describing what it holds (the four above). This verbatim header + the
README line are the template the "adding a non-canonical archive file" convention copies
when Phase B later adds archive/hygiene.md, and when descendent scopes stand up
their own archive/.
Done when: archive/ holds the four source files (each with the standard header, empty
body) and archive/README.md listing all four.
Confirm by: list archive/ (four source files + README); open each source file
(standard header, no entries yet); open README.md (four described entries).
Task A3: Stand up .meta/ledger.yaml
Touches: new .meta/ledger.yaml; retire .meta/learning-new-skills.yaml (leaving
.meta/workflow.yaml untouched — it's the layer-identity manifest, not a hygiene stamp,
so the ledger deliberately does not absorb it); the ## Session lessons section in
current-plan.md (to receive the retired notes — see below).
Create .meta/ledger.yaml as the per-scope ledger (design §7), sectioned into config:
(human-set, tunable knobs), skills:, and lists: (both machine-written stamps). Carry
the existing last_run value out of .meta/learning-new-skills.yaml into
skills.learning_new_skills.last_run. Before deleting it, graduate its notes: block
(first-run findings: disable-model-invocation, the Stop-hook prompt-eval pattern,
terminalSequence for Windows notifications, the skill-creator 500-line threshold) into the
## Session lessons list as a dated 2026-05-27 entry — they're session-lesson-shaped and
mostly already echoed there, so merge rather than duplicate (A4 then flattens them with
the rest). Then delete .meta/learning-new-skills.yaml (last_run absorbed, notes
graduated — nothing lost). Seed the lists: section with one entry per existing Yggdrasil list —
active_bookmarks, backburner, session_lessons, catalog, done_log — using the
stamp shape from §7. Concrete seeding:
config:(the tunable hygiene knobs, read at runtime by/hygiene-checkand/good-morning— see B1):bloat: { heads_up: 10, warn: 15, firm: 20 }·reacclimation_days: 7·aging_days: 14·cadence_days: { backburner: 7, session_lessons: 7, catalog: 7, done_drain: 7 }·done_log: { drain_age_days: 7, min_recent: 5 }. Seed each value with an inline YAML comment marking it a tunable first-guess, so the provenance lives in the file the future tuner opens — e.g.aging_days: 14 # first guess 2026-06-09; tunable, see bookmarks. (Theaging_daysvalue is what theaged_countseeds below key off; Phase B's ledger-restamp must preserve thisconfig:section — see B1.)active_bookmarks:count= the live count of entries inbookmarks.md, computed now — do not copy the design's example18; it's ~39 today, already in the20+band.aged_count= entries older thanconfig.aging_days.last_pruned= today. Forcount_band_sincewe genuinely can't reconstruct when the pile crossed 10+, so set it to today as an init — but B1 must treat an init-stampedcount_band_sincewhose count is already in the20+band as immediately reacclimation-eligible, so the seed date doesn't suppress the "been a while" nudge (Skeptic-lens finding).backburner:count: 5(from A1);aged_countper the same ~14d rule;last_reviewed: 2026-06-08.session_lessons,catalog:last_reviewed: 2026-06-08.done_log:last_drained: 2026-06-08.
Done when: .meta/ledger.yaml exists with all three sections populated (config
seeded with the tunable knobs; skills/lists stamped), the prior last_run is preserved
under skills.learning_new_skills, and .meta/learning-new-skills.yaml is deleted.
Confirm by: open ledger.yaml (all three sections; config values carry their
inline-comment provenance); git status shows .meta/learning-new-skills.yaml deleted and
.meta/workflow.yaml untouched; confirm the carried last_run matches the old file's value,
the retired notes: now appear as a 2026-05-27 session-lessons entry, and
active_bookmarks.count is the live count (~39), not the example 18.
Task A4: Flatten session lessons into dated entries
Touches: all ## Session lessons (from … session) blocks in current-plan.md —
match them by pattern, not the frozen list of dates. The build spans days, so a block
like (from 2026-06-09 session) may accrete after this plan was written; flatten whatever
exists at run time, plus the 2026-05-27 notes A3 graduates in.
Convert the per-session blocks into a single ## Session lessons section holding
individual dated prose bullets (design §5.2: flat, bold lead yes, dated-update yes). For
every lesson bullet under each dated block, prefix it with that block's session date in
the base format (- **YYYY-MM-DD** — …) and move it under the one ## Session lessons
header, preserving chronological order and each lesson's full text (including its existing
bold lead). Remove the now-empty per-session block sub-headers. No lesson content is
dropped — this is a reshape, not a prune.
Done when: current-plan.md has one flat ## Session lessons section of dated
entries, every prior lesson present, and all per-session block headers are gone (however
many there were).
Confirm by: grep for any remaining (from … session) header — none should match
(this catches a block that accreted after planning, which a naive before/after count would
miss); confirm a single ## Session lessons header remains; spot-read a few entries for
intact text + correct dates.
Task A5: Date the catalog + delete the staging section
Touches: the ## Design decisions catalog section and the empty
## Bookmarks to fold into bookmarks.md section, both in current-plan.md.
Add a date to each catalog entry (design §5.2: the catalog keeps its ### topic
grouping — the only descendant with subheads — so date at the ###-topic level). Derive
each date from the decision date stated in the entry's own text where present (many read
"reframed 2026-05-29," "sharpened 2026-06-03," etc.); otherwise from git blame; otherwise
stamp 2026-06-08 with no false precision. Date every ### entry present at run time
(including any added since this plan was written). Keep the topic grouping and all content
intact — this adds dates only, it does not re-litigate settled entries. Separately, delete the
## Bookmarks to fold into bookmarks.md staging section (it's empty and live capture via
/bookmarking supersedes it).
Done when: every catalog topic entry carries a date, the topic grouping is unchanged,
and the staging section is gone.
Confirm by: scan the catalog for any undated ### entry (none); grep current-plan.md
for "Bookmarks to fold into" (absent); confirm no catalog content changed beyond added
dates.
Task A6: Evolve the /bookmarking skill
Touches: skills/bookmarking/SKILL.md.
Evolve /bookmarking per design §6 — capture-only (all maintenance lives in
/hygiene-check, built in Phase B), keeping the auto-firing skill lean:
- Set
allowed-tools: [Read, Glob, Grep](Glob to locate the scope's store, Grep to dedupe-check before appending; Write/Edit stay out so the mutation still prompts). - Add scope-awareness: capture to the right layer's store (Yggdrasil →
bookmarks.md; personal →personal/bookmarks.md; an adopted project → its store), detected from context rather than hardcoded. - Add an optional backburner hint — "backburner this" / "park for someday" captures
straight to
backburner.mdinstead of active bookmarks. - Strip any dead
/bookmarkcommand references (no such command exists). - Grow the description to carry trigger synonyms ("backburner this," "park for someday," "soon," …) so conversational invocation fires reliably.
Done when: skills/bookmarking/SKILL.md reflects all of the above and remains
capture-only (no pruning/triage logic added).
Confirm by: read the skill — frontmatter shows [Read, Glob, Grep]; description carries
the trigger synonyms; scope-awareness and the backburner hint are described; no /bookmark
references remain; no maintenance logic crept in.
Task A7: Stand up the ## Deferred section in current-plan.md
Touches: current-plan.md (new ## Deferred section).
The §5.6 Deferred section is the in-context hot parked-item store, and good-morning (C1)
surfaces ripe deferrals from it — but current-plan.md has no ## Deferred section yet
(only specific sub-plans like this one do). Stand one up as the canonical Yggdrasil-wide
Deferred store that C1 scans. Create the ## Deferred section in the §5.6 shape (dated
prose bullets with optional revival triggers); seed it with any clearly-deferred items easy
to lift in, otherwise leave it lightly populated. Broad consolidation of the scattered
"Open:" bits across current-plan.md's design sections is NOT in scope here — that's a later
cleanup; this task just establishes the canonical section so C1 has a real place to read.
(Two-level note, self-contained: sub-plans like this list-hygiene plan keep their own
## Deferred for plan-scoped deferrals; those merge up to current-plan.md's section — or to
bookmarks.md — when the sub-plan resolves. Whether good-morning ALSO scans the active
sub-plan's Deferred mid-build is a deliberately-deferred v2 question; v1 = good-morning
scans current-plan.md's section only.)
Done when: current-plan.md has a ## Deferred section in the §5.6 dated-bullet shape.
Confirm by: grep current-plan.md for ## Deferred (heading exists); the section
follows the dated-prose-bullet format.
Phase B — the /hygiene-check command
/hygiene-check is the standalone command that operates the stores Phase A stood up
(design §8). It merges what would have been /sweep with /consistency-check into one
command holding each housekeeping concern as a distinct, cadence-gated, offered step. The
bookends don't embed it — /save-progress offers it and /good-morning surfaces
what it produced (that wiring is Phase C).
The shared step pattern — every step below follows this:
- Cadence-gate — read the step's
last_*stamp from.meta/ledger.yamland its interval fromconfig.cadence_days; the step is due only if elapsed time ≥ the interval. If not due, stay silent and skip — no prompt. - Offer — if due, present an
AskUserQuestionYes/No to run it (these are the gates that used to live inline in/save-progress). Decline = skip, no change. - Act — do the step's work (review / prune / drain / nudge).
- Drain — pruned/retired items append to their
archive/<source>.md(with the standard header + a README line per the §5.5 convention if the file is new), never deleted outright. - Restamp — update the ledger: the step's
last_*date, plus a refreshedcount+aged_countfor the touched store (so/good-morningsurfaces bloat/aging from stamps without loading the store). The restamp writes onlyskills:/lists:— it never touches the human-setconfig:section.
Frontmatter: disable-model-invocation: true, allowed-tools: [Read, Glob, Grep] (reads
pre-approved; the Yes/No offers authorize each mutation — whether to also pre-approve the
store writes, to avoid a second prompt after the offer, is a build-time refinement).
Task B1: /hygiene-check skeleton + active-list curation steps
Touches: new commands/hygiene-check.md; reads/writes .meta/ledger.yaml,
bookmarks.md, backburner.md, archive/.
Create commands/hygiene-check.md with the frontmatter and the shared step pattern above
as the command's spine (this task establishes the machinery B2–B4 reuse), then implement
the three active-list steps:
- Bookmark prune + bloat-nudge. Count
bookmarks.mdentries; compare againstconfig.bloat(<10celebrate ·10+heads-up ·15+warn ·20+firm> **Gate:**-style push to prune — softening of this 20+ vocabulary is parked in## Deferred). If the count has sat in the 10+ band sincecount_band_sincefor ≥config.reacclimation_days, add the "been a while" reacclimation note — and treat an init-stampedcount_band_sincewhose count is already in the20+band as immediately eligible (the seed date must not suppress the nudge; per A3). Offer a prune pass — review entries, retire resolved/dead ones toarchive/bookmarks.md. Restampactive_bookmarks(count,aged_count,last_pruned,count_band_since). - Active → backburner demotion. Offer moving cold / far-future active bookmarks to
backburner.md— the pressure valve for chronically-deferred items. Restamp both stores' counts. - Backburner review. Cadence-gated on
config.cadence_days.backburner. Offer a walk ofbackburner.md: revive → active bookmark · promote → a Target · archive. (Backburner is bookmark-lineage — cold bookmarks — so its archive exit drains toarchive/bookmarks.md, not a separatearchive/backburner.md. Settled design call.) Restampbackburner.last_reviewed+ counts.
Done when: commands/hygiene-check.md exists with the shared pattern + the three
active-list steps; a run cadence-gates each, offers via AskUserQuestion, drains accepted
prunes to archive/, and restamps the ledger without touching config.
Confirm by: invoke /hygiene-check against the current stores — a not-due step stays
silent; a due step prompts; accepting a bookmark prune drains to archive/bookmarks.md and
updates the active_bookmarks stamps while config is untouched. Present the before/after
ledger diff.
Task B2: Knowledge-store review steps
Touches: commands/hygiene-check.md; the ## Session lessons + ## Design decisions catalog sections in current-plan.md; archive/session-lessons.md, archive/catalog.md.
Add two more steps (each following the shared pattern):
- Session-lessons review + nags. Cadence-gated on
config.cadence_days.session_lessons. Offer a staleness/graduation pass over the flat## Session lessonslist (from A4): graduate a proven lesson up to an AGENTS/CLAUDE convention, or archive a stale one toarchive/session-lessons.md. Quantity nag if the list runs long. Restampsession_lessons.last_reviewed+ count/aged. - Catalog review + nags. Cadence-gated on
config.cadence_days.catalog. Offer a staleness/graduation pass over## Design decisions catalog(dated in A5) — staleness and graduation only; settled ≠ re-litigation (§5.2). Archive superseded entries toarchive/catalog.md. Restampcatalog.last_reviewed.
Done when: both steps run end-to-end under the shared pattern.
Confirm by: trigger each with its cadence elapsed — the offer fires, a graduation moves
an entry to the right Target, an archive drains to the right archive/ file, the ledger
restamps.
Task B3: Done-log hygiene step
Touches: commands/hygiene-check.md; the ### Done / Done-log section in
current-plan.md; archive/done-log.md.
Add the Done-log step (self-bounding — no review, no nags, per §5.4):
- One-time normalization (setup — runs once, NOT cadence-gated; the two recurring steps
below are the cadence-gated hygiene). Reshape the existing
### Donesection into the §5.4 two-tier shape — closed phases collapsed to one-line summaries, active-phase work as individual dated granular bullets. The current section is close, so this is light. Where an entry is too terse or truncated to reshape confidently, leave it as-is and flag it passively (a brief(couldn't confidently reshape — left in place)marker) rather than blocking to interrogate the user mid-step. They can fill any in later if they choose; the step never stalls waiting on a human (no-demand). Once done, this normalization is a no-op. - Phase-compaction (recurring): collapse each newly-closed phase's granular bullets into a one-line summary that stays in place (the lightweight arc).
- Age-drain (recurring): move granular Done bullets older than
config.done_log.drain_age_daystoarchive/done-log.md, but keep theconfig.done_log.min_recentmost-recent regardless of age (the floor so a dormant project still shows recent context). - Cadence-gated on
config.cadence_days.done_drain; restampdone_log.last_drained.
Done when: the ### Done section is normalized to the two-tier shape, and the step
thereafter compacts closed phases and drains aged granular bullets (respecting the
min-recent floor) to archive/done-log.md, restamping last_drained.
Confirm by: run it against the Done log — bullets older than the drain age (beyond the
most-recent floor) moved to archive/done-log.md, the newest kept, closed phases compacted,
done_log.last_drained updated.
Task B4: Consistency-check step + retire /consistency-check
Touches: commands/hygiene-check.md; working/hygiene.md (the scratchpad);
new archive/hygiene.md; delete commands/consistency-check.md; AGENTS.md
(the one-line commands-row delete).
Port the existing /consistency-check drift-detection logic (from
commands/consistency-check.md) in as a /hygiene-check step. It is event-driven — run
after durable-doc changes, not time-cadence-gated — so it gets no cadence_days
entry; offer it when the session has touched durable docs (or on request). It writes
outstanding drift to working/hygiene.md (the hygiene/drift scratchpad — renamed from
consistency-check.md to the more generic hygiene.md, since it's now /hygiene-check's
output, not a standalone command's; rename the existing file as part of this task).
- Scratchpad drain — the first use of the §5.5 "non-canonical archive file" convention.
When resolved runs accumulate, append them to
archive/hygiene.md— creating that file with the standard archive header and adding itsarchive/README.mdline per the convention — then remove the resolved runs from the working scratchpad. - One-off: drain the existing resolved runs currently in
working/hygiene.mdintoarchive/hygiene.md, leaving only genuinely-open items in the scratchpad. - Retire
/consistency-check: deletecommands/consistency-check.md(its logic now lives in the step) and do the one-line AGENTS.md commands-row delete here (remove/consistency-checkfrom the commands table), so AGENTS.md never advertises a command that no longer exists. (Only this factual row-delete moves up to B4; the richer AGENTS.md house-style additions still land in C4.)
Done when: the consistency-check step runs within /hygiene-check (event-driven, writes
the scratchpad); resolved runs (including the existing backlog) drain to
archive/hygiene.md, created per the convention; commands/consistency-check.md
is deleted and AGENTS.md's commands row no longer lists it.
Confirm by: run the step (drift lands in working/hygiene.md); confirm the
existing resolved runs moved to archive/hygiene.md; confirm archive/README.md
gained the hygiene.md line and the file carries the standard header; confirm
commands/consistency-check.md is gone and AGENTS.md's commands row shows no
/consistency-check.
Phase C — the convergence
Where the two designs merge: both the list-hygiene surfacing and the bookend worktree
lifecycle land in the same two command rewrites. Full worktree mechanics live in the
bookend design (current-plan.md → "Bookends — the active build (2026-06-08)" and "Git
working-tree discipline — design-complete") — the tasks below name the behaviors and pull
the fine step-by-step from there rather than re-deriving it. Order note: C3 (puppet)
depends on C1 (its trigger is good-morning gaining worktree creation).
Task C1: /good-morning rewrite — the full startup sequence
Touches: commands/good-morning.md; .gitignore; reads .meta/ledger.yaml,
current-plan.md, working/hygiene.md.
Prerequisite: .worktrees/ in .gitignore and committed — done at Execution Step 0;
this task just confirms it's committed as a permanent entry (good-morning creates
worktrees there on every run).
Rewrite good-morning into the startup sequence below — it composes the original orient-and-stand-ready behavior with the new worktree lifecycle + ledger surfacing. State it as git-by-default + worktree-always (not the planning skill's softer "or at least a branch" floor). The character shifts from "only reads and orients" → "reads, orients, and sets up / cleans the workspace" — but it still does not execute the plan's work. (This is the onboarding/bootstrap/startup chokepoint — the full sequence lives here.)
1. Parse & capture (entry). Parse the invocation: briefing preference + any loose note. Safe-capture a loose note first — if the user sat down to drop an idea, bookmark it immediately so it never rides only in conversation.
2. Locate & resume the session worktree (precedes orient — the pinned handoff can live on
the session branch). git worktree list to detect session-* worktrees (branch-prefix
detection; reserve xrepo-* and native worktree-* as not session-resumes — no active
cross-repo logic, deferred). If a kept session-* exists, resume it (cd in) — that's
where last session's pinned handoff lives if it was "kept." More than one → disambiguate
via AskUserQuestion listing each with a derived per-session summary (from recent commits
/ the branch checkpoint) + last-commit date, plus "start fresh." If none exists, the handoff
is on main and you create fresh in step 4.
3. Orient. Read current-plan.md from the resumed location (the freshest pinned
handoff), in full. Explore what it points to — references, the active skill(s), source paths.
Skim durable docs from the manifest if the session will touch architecture.
4. Finish workspace setup. Now that you've oriented: worktree-always — if step 2 found
none, create a session-YYYY-MM-DD worktree under .worktrees/ branched from local HEAD
(so worktree.baseRef is moot, no-remote-safe); "start fresh" while today's name exists →
collision suffix (-2, -3). Necessity-only cleanup (offered, not silent): reuse a
same-day empty silently; nuke an empty stale-dated worktree (clean, no commits beyond
base) and tell the user; clear a broken/half-made one. cd settled into the worktree;
target absolute worktree paths thereafter (raw git doesn't auto-relocate).
5. Surface — all from ledger stamps + in-context; never load the out-of-context stores
(bookmarks.md / backburner.md / archive/):
- Ledger (
.meta/ledger.yaml): bookmark count + high-count flag (bloat bands fromconfig.bloat), items aged pastconfig.aging_days, and which cadence-gated reviews are due. working/hygiene.mdopen items, if any (the hygiene/drift scratchpad — closes the standing bug where good-morning advertised surfacing it but had no step that read it).- Ripe deferrals from
current-plan.md's## Deferred(in-context, so reading it is fine): hard-trigger fired (by condition) or soft-trigger aged pastconfig.aging_days(by age) — an informational offer to pick it up, never forced (§5.6). (A7 stands up that section; v1 scanscurrent-plan.md's only — sub-plan Deferred scanning is a deferred v2.) - Active-build progress: if a sub-plan is in flight (a plan with unchecked
## Progressboxes), surface "you're at Task X of plan Y; next is …" — making good-morning the resume point for a/clear'd mid-build.
6. Brief & stand ready. Offer the briefing (unless declined on entry). State where you're picking up + the immediate next step; stand ready. No work execution.
Done when: good-morning runs the full sequence — locate/resume (or create) the session
worktree with disambiguation + necessity-cleanup, orient from the freshest handoff, surface
the four signal classes (ledger flags · working/hygiene.md open items · ripe deferrals ·
active-build progress) while respecting the out-of-context boundary, and stop at orientation
without executing the plan's work; .worktrees/ is gitignored.
Confirm by: run /good-morning in a clean repo — it creates .worktrees/session-<today>
off main, orients, surfaces the four signal classes, and stops (git status clean —
worktree ignored). Re-run with a kept session worktree → resumes it and reads the handoff from
there; with two → disambiguation w/ summaries; with a stale empty → nuke + notify.
Task C2: /save-progress rewrite — disposition + pin + offer /hygiene-check
Touches: commands/save-progress.md.
Pin + disposition (the bookend half — full mechanics in the design's §(b)/(c)):
- Pin the handoff (checkpoint write+commit) — self-housekeeping, auto-commit, no
prompt — written once, to wherever
/good-morningreads next (keep→branch, merge→main, discard→breadcrumb onmain). - Disposition menu —
AskUserQuestionmerge / keep / discard, always gated (deliberately outside the auto-commit exception), recommended option pre-pointed by the drafted checkpoint's "Next step" shape (verification read off it, not asked cold). All git viagit -C/ absolute paths, nevercd:- merge = merge the session branch into
main, re-confirm it still checks out on the combined state, remove the worktree, delete the branch. - keep = leave branch + worktree, frictionless; next
/good-morningresumes. - discard = "Are you sure?"
AskUserQuestion→ write a fresh "abandoned X" breadcrumb tomain'scurrent-plan.md, remove the worktree, force-delete the branch (recoverable via reflog + breadcrumb).
- merge = merge the session branch into
- Preserve save-progress's existing step 1(a) in-flight-design materialization guardrail through the rewrite.
Offer /hygiene-check (the list-hygiene half — design §8): shed the inline sweep;
instead offer /hygiene-check (the AskUserQuestion gates moved there). save-progress
offers it, never embeds it.
Done when: save-progress pins the checkpoint (auto), offers the gated merge/keep/discard
disposition (pre-pointed by the checkpoint), offers /hygiene-check, and preserves step
1(a); the old inline sweep is gone.
Confirm by: run /save-progress in a session worktree — the pin auto-commits to the
right place; the disposition menu appears with the recommended option pre-pointed; merge
cleanly combines + re-confirms + removes the worktree; keep leaves it; discard
confirms + breadcrumbs; /hygiene-check is offered (not embedded); step 1(a) still fires.
Task C3: Puppet fix — decouple its bootstrap from /good-morning
Touches: commands/puppet.md. (Depends on C1.)
Per the [priority] bookmark, now due: puppet step 2 currently reads
commands/good-morning.md as text and follows it — which, after C1, would make puppet
inherit worktree-creation + a Yggdrasil pin, violating its own read-only gate ("No Yggdrasil
checkpoint on the way in") and spinning a worktree during a read-only foreign adoption.
Replace the delegate-to-good-morning bootstrap with an inline minimal bootstrap keeping only what puppet needs (Brad wants the full Yggdrasil context bootstrap kept so puppet sessions ride the real toolkit and get logged):
- Load
working/current-plan.md(Yggdrasil's plan, for context/logging). - Skip the briefing; orient and stand ready.
- Explicitly NO worktree creation and NO pin/checkpoint.
- Do not inherit good-morning's ledger-surfacing/worktree machinery — puppet is a read-only foreign adoption.
Done when: puppet step 2 does its own inline bootstrap (load plan, skip briefing, orient
— no worktree, no pin) and no longer reads/follows commands/good-morning.md.
Confirm by: read puppet.md — step 2 is self-contained, references no good-morning
delegation, creates no worktree and no pin; the read-only gate and "No Yggdrasil checkpoint"
gate remain intact.
Task C4: Consolidated AGENTS.md / durable-docs update
Touches: AGENTS.md; .meta/durable-docs.md (confirmed to exist — reconcile it);
personal/CLAUDE.md (the commit-convention cross-ref).
Land the house-style / convention entries this build accumulated (collected here to avoid scattering them across earlier tasks):
- Archive-file convention (§5.5): kebab-name after source · standard header ·
archive/README.mdline, whenever a non-canonical archive file is added (travels to descendent scopes). ledger.configpointer: "the hygiene knobs — bloat / aging / cadence — are tunable in.meta/ledger.yaml→config."- Disposition-is-prompted (Loose End 3): worktree disposition (merge/keep/discard) is always human-gated, outside the self-housekeeping auto-commit exception.
- "commit" git-op-vs-convention house-style (the deferred bookmark): bare "commit" = the
git op; lean on pin / disposition in worktree mechanics; write "the commit
convention" when meaning the convention. Cross-ref
personal/CLAUDE.md's commit convention. - Bloat-nudge concept reference (thresholds live in
ledger.config). - Commands-row: confirm
/consistency-checkis already gone (deleted in B4) and add/hygiene-checkto the commands table. - Worktree naming/location convention (
session-*/ reservedxrepo-*,.worktrees/, git-by-default) if not already captured.
Done when: AGENTS.md carries all the above; the commands row shows /hygiene-check and
no /consistency-check; durable-docs references reconciled.
Confirm by: read AGENTS.md (each convention present; commands row correct); then run
/hygiene-check's consistency-check step — it flags no new drift against the durable
docs (closing the loop: the build's own docs are now self-consistent).
Task C5: Final verification pass
Touches: all build artifacts (read-only verification); the ## Progress checklist.
The closing sign-off that the build is actually complete and coherent — catches a checkbox that lies and any cross-task inconsistency the per-task Confirm-bys miss individually:
- Walk every task's Confirm-by against disk (A1–A7, B1–B4, C1–C4). Each must pass; a box
that's checked but whose Confirm-by fails is the exact failure this catches — re-open that
task. Reconcile the
## Progressboxes to the real results. - Re-run the Self-Review consistency check on the built artifacts (not the plan text):
the
config.*keys the commands read exist in the ledger; thearchive/files the steps drain to exist with the standard header;/hygiene-checkand/good-morningreference the sameworking/hygiene.mdand ledger fields; no dangling cross-reference between commands, ledger, and stores. - Plan-scoped cousin of the Phase-12 full-stack capstone; candidate to graduate into the planning skill as a standard closing step (captured in the planning-skill-improvements bookmark).
Done when: every task's Confirm-by passes against disk, every ## Progress box is honest,
and the cross-artifact consistency check is clean.
Confirm by: the walk yields a clean bill — no failing Confirm-by, no mismatched checkbox,
no dangling cross-reference; if anything fails, it names the task to re-open.
Deferred
- 2026-06-08
[priority]— Roll the hygiene system out to the personal layer. Stand up the personal layer's mini version: apersonal/.meta/ledger.yamland bookmark hygiene forpersonal/bookmarks.md(no session-lessons/catalog/done-log there — it has none). Trigger: once this plan is written and worked through — it should be quick and easy on the back of the Yggdrasil build, which is why it's[priority]rather than open-ended. Pairs with the bookmarked "uniform repo-maintenance routine across all layer-repos" thread. - 2026-06-09 — Cross-repo (
xrepo-*) worktree disposition — deferred to the uniform per-layer maintenance thread. Decision (Phase C scoping): this plan fully handles same-reposession-*worktrees; it reserves thexrepo-*prefix in the naming/detection scheme (so detection stays forward-correct —session-*are ours-to-resume,xrepo-*and nativeworktree-*are not) but builds no active cross-repo detection or disposition.- Why deferred: nothing in the current or planned system actually creates
xrepo-*worktrees yet — cross-repo edits today land directly on the other repos'mainbranches (as this session'spersonal//odin-codin/branch-renames did). So any cross-repo detection/warning logic would be inert until a reach-in mechanism exists. And the genuinely-hard part — disposing of worktrees across N repos at session end — is a design effort of its own: the parked "uniform repo-maintenance routine across all layer-repos" thread (bookmarks.md), which sprang from this same Loose End 2. - Intended usage in the hypothetical future world (recorded so the design isn't lost): a
session has a primary repo with its
session-*worktree; when work must touch another layer-repo, instead of editing that repo'smaindirectly, the system creates anxrepo-*worktree in it — isolating the reach-in the same way the primary work is isolated. The prefix distinguishes "a reach-in worktree created from another repo's session" from "this repo's own primary session," because the two carry different disposition semantics. At session end, disposition becomes multi-repo:/save-progress(or the uniform-maintenance routine) walks each touched repo and offers merge/keep/discard per repo, not just the primary's. The pre-reach-in warning is the safety net: a later/good-morningthat detects an unclosedxrepo-*worktree in some repo warns "repo X has an unclosed Claude-managed worktree — load it asmainand close it out first," nudging the user to handle that repo in its own primary session rather than leaving orphaned cross-repo state. - Trigger: taken up with the uniform per-layer maintenance routine thread. Cross-ref:
bookmarks.md(uniform-maintenance routine) + the bookend design's Loose End 2.
- Why deferred: nothing in the current or planned system actually creates
- 2026-06-09 —
/hygiene-checkUX: prompt-grouping + softer 20+ nudge (lens-audit follow-on). Two calm-house-style refinements surfaced by the lens audit, parked together because both make the hygiene UX gentler:- Prompt-grouping. On a day many cadences are due,
/hygiene-checkcan fire up to ~7 sequential Yes/No gates — each "offered," but the aggregate carries a demand character (worst on the low-spoon "been away" return). Idea: open with a single roll-up — "N things are due: all / pick one / none" — with a first-class "just one thing" path, so the default low-spoon route is one decision, not seven. (Brad: "maybe I'll nest some into groups" — not now.) - Softer 20+ nudge. The
20+band uses> **Gate:**-style pressure-language (design §4 #3 + B1) — the one spot the calm/no-demand house style slips, pointed at the lowest-stakes pile. Soften to salient-but-calm: keep it visually prominent, drop the gate/blocking vocabulary. - Trigger: when Brad wants to tune the hygiene UX (soft — no spoons pressure). Source: lens audit, User-Advocate findings.
- Prompt-grouping. On a day many cadences are due,