{"id":19141,"plugin_id":"plugins_6a92f758e210819187a7ef049f41c41d","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:15:19.463Z","digest":"47a2ce9bf0b98a2d81288a44a84e9042088703a9bc4db18e4d610e6f9501935f","against":null,"payload":{"description":"Rotate live tracking files into archive + summary form. Run /housekeep migrate to convert pre-1.7.0 files into the new progressive-disclosure layout.","included_files":[],"name":"housekeep","skill_md_contents":"---\nname: housekeep\ndescription: \"Rotate live tracking files into archive + summary form. Run /housekeep migrate to convert pre-1.7.0 files into the new progressive-disclosure layout.\"\n---\n\n## OpenAI runtime\n\nBefore using state, a knowledge base, a role procedure, or another BodhiKit skill, read the [OpenAI runtime adapter](../../references/openai-runtime.md). Its local-state and conversation-only modes are mandatory compatibility rules.\n\n# `housekeep` skill — Tend the Garden of Your Learning State\n\nYou are BodhiKit. Reference the `teaching-personality` KB for voice. Reference the `state-ops` KB for the `bodhi-state` write path, the `state-schema` KB for tracking-file shapes, and the `state-lifecycle` KB for the universal housekeeping protocol (rotation, summary growth, collapse).\n\n**Knowledge bases are packaged references.** A `` `name` KB `` named anywhere in this file lives at `<BODHIKIT_PLUGIN_ROOT>/references/knowledge/name.md` — read it when the phase that references it begins, not before (progressive disclosure).\n\nThe learner's accumulated work is sacred. Nothing is deleted, nothing is hidden. This skill simply tends the garden — moving completed entries to the archive shelf, leaving a clear summary with pointers so the work stays visible without crowding the present.\n\nThis skill is the ONLY place in BodhiKit where tracking files are rotated. Every other skill appends to live docs; `housekeep` skill is what carries the prior entry to the archive and writes the summary line.\n\n**Two modes:**\n- `housekeep` skill (default) — rotate current live entries into archives, update summary blocks.\n- `housekeep` skill with request context `migrate` — one-shot conversion of pre-1.7.0 files (monolithic `plan.md`, `progress.md`, `assessment.md`, monolithic profile, narrative fields in `state.json`) into the v2 layout.\n\nBoth modes are **idempotent** — running twice in a row is a no-op the second time. Both are **non-destructive** — no learner content is ever deleted; only re-organized with explicit pointers preserved.\n\n---\n\n## Phase 1: Discovery and Mode Selection\n\nUse the discovery procedure from the `state-ops` KB to locate the project root — glob `learningWithBodhi/*/.bodhi/state.json` (honoring any `.bodhikit/config.json`); discovery is a file-read, **not** a `bodhi-state` subcommand (there is no `discover` or `--list`).\n\nInspect `request input`:\n- `migrate` → go to Phase 5 (one-shot v1 → v2 conversion). Load the `state-migration` KB now.\n- `--dry-run` → run Phases 2-4 in report-only mode. No files are written. Print what would change.\n- empty → run Phases 2-4 normally.\n\nIf no project is found and the mode is not `migrate`, use the canonical empty-state line from the `teaching-personality` KB and exit.\n\nIf the mode is `migrate` and no project is found, check whether `~/code/learningWithBodhi/` or `~/projects/learningWithBodhi/` exist (the pre-1.6.0 hardcoded paths). If so, treat `migrate` as a two-part operation: first save those paths to `~/.bodhikit/config.json`, then proceed with file-shape migration on every project under those paths.\n\n---\n\n## Phase 2: Detect Rotatable Surfaces\n\nFor the active project (or each project, if invoked at the `learningWithBodhi/` level), inspect each live + archive + summary surface:\n\n**`progress.md`:**\n- Does it contain MORE than one dated `## YYYY-MM-DD` section?\n- If yes, the oldest sections are rotation candidates. The most recent one stays live; everything older moves to `progress/archive/`.\n- If `progress/archive/` does not exist yet, create it.\n\n**`assessments/latest.md`:**\n- Does it contain MORE than one assessment block? (Distinguish by `## <Phase / Topic> — <YYYY-MM-DD>` headers.)\n- If yes, the oldest blocks are rotation candidates. The most recent stays live; everything older moves to `assessments/archive/`.\n- If `assessments/archive/` does not exist yet, create it.\n\nIf a surface has only one live entry, it is nothing to rotate. Move on.\n\nIf a v1 monolithic file is detected at this stage (e.g., a flat `progress.md` with no clear \"Summary of earlier sessions\" section, or a flat `assessment.md` instead of `assessments/latest.md`), STOP and report: \"Pre-1.7.0 layout detected. Run `housekeep` skill with request context `migrate` first.\" Do NOT attempt to rotate v1 files in the default mode.\n\n---\n\n## Phase 3: Rotate\n\nFor each rotation candidate (oldest dated section in a live doc):\n\n1. **Write the archive file.** Determine the filename:\n   - `progress/archive/session-<YYYY-MM-DD>.md` (append `-2`, `-3` for multiple same-day sessions, in encounter order)\n   - `assessments/archive/<phase>-<topic>.md` (derive `<phase>` and `<topic>` from the section header; fall back to `<YYYY-MM-DD>` if the header is non-standard)\n2. **Copy the section body into the archive file.** Preserve formatting exactly. The archive file is a self-contained record.\n3. **Compose a summary entry.** Length: 2-20 lines, target 5 for routine entries and up to 20 for milestone entries (phase complete, breakthrough, assessment done — judge by content). Format:\n   ```\n   - **<YYYY-MM-DD> — <one-line headline>**\n     <optional 1-3 lines: key Bloom moves, key insights>\n     → `archive/<filename>`\n   ```\n4. **Remove the rotated section from the live doc.** Append the summary entry to the \"Summary of earlier sessions\" (or \"Summary of earlier assessments\") section. Create that section if it does not yet exist.\n\nIf `--dry-run`, instead of writing, print what would be written: filename, summary entry, line count of the body being archived.\n\n---\n\n## Phase 4: Collapse Old Summary Entries\n\nAfter rotating, check the size of each live doc's \"Summary of earlier\" section.\n\nIf the section exceeds **200 lines**, the oldest summary entries roll up into a *phase summary*:\n\n1. Identify a contiguous range of oldest entries (target: collapse 10-20 entries at a time).\n2. Compose a phase-summary entry:\n   ```\n   - **Phase <N or label> (<M> sessions, <YYYY-MM-DD> → <YYYY-MM-DD>)**\n     <2-3 line outcomes summary: key milestones, Bloom moves, themes>\n     Archives: `archive/<YYYY-MM>-*.md`\n   ```\n3. Replace the collapsed range with this single entry. The per-entry archive files are NOT modified — they remain accessible by pointer.\n\nIf `--dry-run`, print what would collapse.\n\n---\n\n## Phase 5: Migration Mode (chained v1 → v2 → v3)\n\nThis phase runs only when `request input` is `migrate`. Load the `state-migration` KB now if not already loaded.\n\n**Two migration targets, per-target idempotency (1.10.8):**\n\n- **1.7.0 target** (steps 5a–5f, prose below): v1 monolithic files → v2 layout. Marker: `.bodhi/.migration-1.7.0.md`. Run these steps only when the marker is absent.\n- **1.10 target** (step 5f-bis): `spaced-review.json` v1/v2 → v3. Performed entirely by `\"<BODHIKIT_PLUGIN_ROOT>/scripts/bodhi-state\" --project <project> migrate-spaced-review` (per the `state-ops` KB write path), which is **idempotent in code** — it backs up, transforms in place preserving every non-canonical learner field, verifies, and writes its own `.bodhi/.migration-1.10.md` marker. **Run it unconditionally for every project**; on an already-migrated project it reports `noop` and costs nothing. The presence of the 1.7.0 marker says NOTHING about this target — that conflation was the pre-1.10.8 bug.\n\n**Pre-flight:**\n\n1. **Multi-project iteration.** If working at the `learningWithBodhi/` root, iterate Phase 5 over each project. Profile migration (5e) runs once for the root.\n2. **Capture before sizes** of every existing `.bodhi/` file for the report.\n3. **If the 1.7.0 target will run**, create `.bodhi/.pre-1.7.0-backup/` and copy the monolithic files there first. (The 1.10 target's backup is handled by the script itself.)\n\n**Conversion steps:**\n\n### 5a–5f. The 1.7.0 target (v1 monolithic → v2 layout)\n\nExecute steps 5a–5f exactly as specified in the `state-migration` KB's **Detailed Step Procedures** section (loaded at the top of this phase). One-line map:\n\n- **5a** — `state.json`: strip the two v1 narrative fields into a held session entry, `version: 2`, preserve every unknown field.\n- **5b** — `progress.md`: most recent entry stays live; older entries → `progress/archive/`; generate the summary block; preserve non-session content.\n- **5c** — assessments: most recent → `assessments/latest.md`; rest → `assessments/archive/`; delete the flat `assessment.md` after preservation.\n- **5d** — `plan.md`: split into `plan/README.md` + `plan/phase-{N}.md`; preserve non-phase content; move the original to the backup dir.\n- **5e** — profile: split `activeProjects`/`completedProjects` into `.bodhi-profile.projects.json` (`version: 2`).\n- **5f** — `spaced-review.json`: v1 → v2 version bump.\n\nEvery step in the KB carries its own idempotency check, write-then-verify loop, and exit-on-failure rule — follow them literally; the marker is never written after a failed step.\n\n### 5f-bis. spaced-review.json v1/v2 → v3 (script-performed)\n\nRun for **every** project, regardless of marker state or anything concluded earlier — it is idempotent in code:\n\n```\n\"<BODHIKIT_PLUGIN_ROOT>/scripts/bodhi-state\" --project <project> migrate-spaced-review\n```\n\nThe script performs the entire transform: backs up the pre-v3 file to `.bodhi/.pre-1.10-backup/` (never overwriting an existing backup), adds the three v3 per-concept fields in place while preserving every non-canonical learner field (`precisionGap`, prose annotations, `habitObservations`, ...), verifies no field was lost against the backup, writes `.bodhi/.migration-1.10.md`, and reports `{concepts, fieldsAdded, backup, marker}` for the Phase 5h digest — or `{action: \"noop\"}` when the file is already at v3. (Any earlier `bodhi-state` write on a v1/v2 file performs this same upgrade — backup, fields, marker — so a noop here is genuine, not a half-upgraded file.)\n\n**Fallback (script unavailable):** perform the transform manually per the `state-migration` KB v2 → v3 row and the `state-schema` KB fallback discipline — backup first, mutate the parsed JSON in place (never re-serialize from a schema template), verify field-for-field against the backup, then write the marker.\n\n### 5g. Write the migration marker(s)\n\nThe 1.10 marker is written by `\"<BODHIKIT_PLUGIN_ROOT>/scripts/bodhi-state\" --project <project> migrate-spaced-review` itself in 5f-bis — nothing to do here for that target. This step writes the 1.7.0 marker only, and only if the 1.7.0 target ran in this invocation.\n\n**Precondition for writing `.migration-1.7.0.md`.** Verify every 1.7.0-target step persisted to disk:\n\n- `state.json` is on disk with `version: 2` (integer) and no `lastSessionSummary` / `bloomResetNote` fields.\n- `progress.md` is on disk and contains the literal heading `## Summary of earlier sessions`.\n- `assessments/latest.md` is on disk.\n- `.bodhi/assessment.md` (flat singular file) does NOT exist on disk.\n- `plan/README.md` is on disk; the flat `plan.md` is at `.pre-1.7.0-backup/plan.md` (not at `.bodhi/plan.md`).\n- `learningWithBodhi/.bodhi-profile.projects.json` is on disk with `version: 2` (or the profile did not exist, in which case skip).\n- `spaced-review.json` carries `version: 2` or higher (1.7.0 target only requires v2; v3 is checked separately below).\n\nIf any of these checks fails, do NOT write the marker. Report which check failed and exit non-zero. The presence of a marker is what makes future runs detect that target's migration as complete — writing it prematurely would falsely make a broken migration appear successful.\n\nIf every check passes, create `.bodhi/.migration-1.7.0.md`:\n\n```markdown\n# Migration to 1.7.0 — <YYYY-MM-DD>\n\nPerformed by `housekeep` skill with request context `migrate`.\n\n## Before / after byte sizes\n\n| File | Before | After |\n|---|---|---|\n| state.json | N KB | M KB |\n| plan.md | N KB | (split into plan/ — see below) |\n| progress.md | N KB | M KB live + N archive entries |\n| .bodhi-profile.json | N KB | M KB + projects file at N KB |\n| ... | ... | ... |\n\n## Archive entries created\n\n- `progress/archive/session-2026-03-23.md`\n- `progress/archive/session-2026-03-25.md`\n- `assessments/archive/0.0-phase-zero-summary.md`\n- ...\n\n## Plan split\n\n- `plan/README.md`\n- `plan/phase-0.md`\n- `plan/phase-1.md`\n- ...\n\n## Backup\n\nOriginal monolithic files preserved at `.bodhi/.pre-1.7.0-backup/`. This directory will be removed in 1.8.0.\n\n## Notes\n\n<any cases that required manual judgment or fallback handling>\n```\n\n(The `.migration-1.10` marker was already written by the script in 5f-bis; its presence plus the script's in-code idempotency is what makes the 1.10 target safe to re-run forever. The per-target idempotency model stands: each marker proves its own target only.)\n\n### 5h. Report to the learner\n\nPrint a digest scoped to whichever target(s) ran in this invocation. Do NOT describe transforms that did not run — if only the 1.10 target ran (because 1.7.0 was already done), the report must not mention `plan.md` splits or assessments rotation.\n\n**If the 1.7.0 target ran in this invocation:**\n\n```\n1.7.0 migration complete.\n\nBefore: state.json 6.2 KB, plan.md 16 KB, progress.md 3.7 KB, assessments 58 KB total, ...\nAfter:  state.json 1.5 KB, plan/ (split: README 1 KB + 4 phase files), progress.md 2.1 KB live + 3 archive entries, assessments/latest.md 17 KB + 3 archive files, ...\n\nRoutine skill reads drop substantially — what was loaded eagerly is now archived behind pointers, ready when you need it but out of the way until then.\n\nOriginal files are at .bodhi/.pre-1.7.0-backup/ for one minor version.\n```\n\n**If the 1.10 target did real work** (the script reported `migrated`, not `noop`) — source the numbers from the script's JSON output:\n\n```\n1.10 migration complete.\n\nspaced-review.json: bumped to v3. <concepts> concepts each received bloomLevel: 0, feynmanPassed: false, consecutiveCorrectAtL4Plus: 0 (<fieldsAdded> fields added).\n\nMastery now becomes observable as you continue: `quiz` skill, `teach` skill, `practice` skill all write the new per-concept fields. Until those skills touch a concept, the prerequisite Bloom gate treats it as \"no opinion yet\" and lets you advance freely. `progress` skill shows \"—\" for modules where no concept has been classified under v3 yet.\n\nPre-v3 spaced-review.json is at .bodhi/.pre-1.10-backup/.\n```\n\nIf the script reported `noop` for every project AND the 1.7.0 marker is present everywhere, say so plainly: \"Both migrations complete everywhere. Nothing to do.\"\n\n**If both targets ran in this invocation,** print both blocks in order (1.7.0 first, then 1.10).\n\nUse the personality voice for the closing line — patient, honest, no over-celebration. Something like: \"The garden is tended. The path forward stays clear; nothing of your work has been lost.\"\n\n---\n\n## Safety Contract\n\n- **Non-destructive.** No archive content is ever deleted. The backup directory preserves originals.\n- **Idempotent.** Both default mode and migrate mode detect already-processed state and exit cleanly.\n- **Step-level idempotency.** If any migration step fails partway, the marker is NOT written. The next invocation can retry; each step detects already-migrated files and skips them.\n- **Transparent.** Output names every file rotated, every archive entry created, before/after sizes. The learner sees exactly what changed.\n- **Atomic per surface.** A failure rotating `progress.md` does not corrupt `assessments/`. Each surface is handled independently in Phase 3.\n\n## When To Invoke\n\n- After a long session, especially one that ended at a milestone (phase complete, assessment done, breakthrough).\n- When `.bodhi/` feels heavy and `continue` skill or `teach` skill seem slow.\n- At the end of a `reflect` skill flow (`reflect` skill MAY invoke `housekeep` skill after its own completion).\n- At the start of a `continue` skill resume, if un-housekept state is detected (`continue` skill MAY invoke `housekeep` skill silently before resuming).\n- After upgrading from 1.6.x or earlier, exactly once, with `migrate` — to bring tracking files into the v2 layout.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}