aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-11 17:09:24 -0500
committerCraig Jennings <c@cjennings.net>2026-06-11 17:09:24 -0500
commit45194e5e5cb73dd4fc583c4d8ac753034c57d1ba (patch)
tree120d319fb6dc912d4bb06f501e33f9926fcc2738
parentd52e73aa4b9a2db8f830ae833e83479e3763ab8f (diff)
downloadrulesets-45194e5e5cb73dd4fc583c4d8ac753034c57d1ba.tar.gz
rulesets-45194e5e5cb73dd4fc583c4d8ac753034c57d1ba.zip
chore: process home consolidation handoffs and file follow-ups
-rw-r--r--.ai/notes.org2
-rw-r--r--inbox/PROCESSED-2026-06-11-1703-from-home-consolidation-handoff-rulesets.org46
-rw-r--r--inbox/PROCESSED-2026-06-11-1703-from-home-project-consolidation-spec.org350
-rw-r--r--inbox/PROCESSED-2026-06-11-1705-from-home-addendum-to-today-s-consolidation.org5
-rw-r--r--todo.org10
5 files changed, 412 insertions, 1 deletions
diff --git a/.ai/notes.org b/.ai/notes.org
index abb03af..eabeb04 100644
--- a/.ai/notes.org
+++ b/.ai/notes.org
@@ -79,6 +79,6 @@ Format:
Markers maintained by workflows to record when they last ran. Read by other workflows that gate their behavior on freshness.
:LAST_AUDIT: 2026-05-28
-:LAST_INBOX_PROCESS: 2026-06-11
+:LAST_INBOX_PROCESS: 2026-06-11 (evening: home consolidation handoffs x3)
Format: one =:MARKER: YYYY-MM-DD= line per workflow. Workflows overwrite their own marker on completion.
diff --git a/inbox/PROCESSED-2026-06-11-1703-from-home-consolidation-handoff-rulesets.org b/inbox/PROCESSED-2026-06-11-1703-from-home-consolidation-handoff-rulesets.org
new file mode 100644
index 0000000..f0a86b7
--- /dev/null
+++ b/inbox/PROCESSED-2026-06-11-1703-from-home-consolidation-handoff-rulesets.org
@@ -0,0 +1,46 @@
+#+TITLE: Home is consolidating all personal ~/projects AI projects into itself — heads-up + okay requested
+#+DATE: 2026-06-11
+
+* What's happening
+
+Craig approved and started a migration that folds every AI-managed project under ~/projects (except work) into the home project as area subdirectories, with full git history preserved via git filter-repo + merge. End state: ~/projects holds home and work only; ~/code stays the place for standalone code projects. One todo.org, one priority scheme, one .ai session for all personal project management.
+
+The spec rode along in this same inbox drop (from-home file with "project-consolidation-spec" in the name). It went through a full spec-review cycle (Codex, two passes: Not ready → Ready) and carries the per-fold manifest contract, a two-mode restore runbook, and a layered rollback story (snapper snapshot, untouched server bares, pre-fold tags, retired dirs, 30-day cooling-off).
+
+* How far we've gone (as of 2026-06-11 ~17:00 CDT)
+
+- Phase 0 done: git-filter-repo verified, snapper snapshot 5621, memory-dir tar in ~/backups/, pre-consolidation tag pushed.
+- Phase 1 done: philosophy folded (pilot). Mode-B rollback drill passed in a disposable clone — the fold is provably removable using only its manifest.
+- Phase 2 done: clipper folded (dress rehearsal). First todo.org import with :MIGRATED_FROM: markers and a fold-time triage; first live-link fix (a dirvish bookmark in ~/.emacs.d).
+- Both sources retired to ~/projects/.retired/ (not deleted). Server bares untouched.
+- Manifests at home:docs/consolidation-manifest-{philosophy,clipper}.org; live inventory gate at docs/consolidation-manifest-inventory.org.
+
+* Learnings and adjustments so far
+
+- A manifest can't embed its own redistribution commit's sha (amend changes it). The manifest row now reads "the commit introducing this manifest"; only the merge sha is recorded literally.
+- git clone --no-local is the right clone shape for filter-repo's fresh-clone safety check; --force is banned from the runbook.
+- The fold-merge branch is read from the source (fb-photo-scraper sits on master, not main — assume nothing).
+- Staged freeze instead of full shutdown: the live inventory gate is regenerated per project immediately before its fold, so Craig can keep using not-yet-folded projects until their turn.
+- Imported [#D] tasks fall outside the task-review staleness pool (it tracks A-C only) — by design, but worth knowing when verifying an import.
+- Source todo.org "Reference" sections (non-task content) merge into the area's notes.org, not into home's todo.org.
+
+* What we'd like rulesets to think about
+
+- Edge cases we may not have seen: anything in the templates, workflows, or scripts that assumes one .ai per project under ~/projects (cross-agent-comms discovery, inbox-send target resolution, the ai launcher's project scan, broadcast).
+- Future-project plans: whether new personal "projects" should now start as areas inside home rather than standalone ~/projects entries, and whether the templates should say so.
+- Any rulesets docs or workflows that name the folding projects as handoff/broadcast targets (finances, jr-estate, etc.) — they'll need updating in our Phase 7 ecosystem pass; a list from your side would help us not miss any.
+- The knowledge-base work-root denylist (~/projects/work) is unaffected.
+
+* Ask: confirmed okay to continue
+
+Reply to home's inbox with a confirmed okay (or concerns) for folding the remaining projects. The remaining list, in planned order:
+
+1. jr-estate (Phase 3 — 704M history, 18-task triage, first memory merge)
+2. danneel (Phase 4 — 613M history, 10-task triage)
+3. finances (Phase 5 — 251M history, 43-task triage)
+4. documents, elibrary, health, kit (Phase 6 folds, together)
+5. website + little-elisper — relocate to ~/code as standalone AI projects (Phase 6)
+6. fb-photo-scraper — delete (unmodified upstream clone; origin recorded in spec D2)
+7. Phase 7 ecosystem pass: link sweep, velox migration, rulesets-reference updates, KB node, cooling clock.
+
+We hold the remaining folds until your reply lands.
diff --git a/inbox/PROCESSED-2026-06-11-1703-from-home-project-consolidation-spec.org b/inbox/PROCESSED-2026-06-11-1703-from-home-project-consolidation-spec.org
new file mode 100644
index 0000000..b557012
--- /dev/null
+++ b/inbox/PROCESSED-2026-06-11-1703-from-home-project-consolidation-spec.org
@@ -0,0 +1,350 @@
+#+TITLE: Project Consolidation — Fold ~/projects AI Projects into Home — Spec
+#+AUTHOR: Craig Jennings
+#+DATE: 2026-06-11
+
+* Metadata
+| Status | Ready — Codex spec-review confirmed 2026-06-11 |
+| Owner | Craig Jennings |
+| Reviewer | Codex (spec-review, 2026-06-11) |
+| Related | [[file:../todo.org::*Project consolidation into home][todo.org task]] |
+
+* Summary
+
+Fold every AI-managed project under =~/projects/= (except =work=) into the =home= project as area subdirectories, with full git history preserved, so all personal tasks live in one =todo.org= and can be prioritized against each other. The end state: =~/projects/= holds =home= and =work=; =~/code/= holds standalone code projects. Every step is reversible — originals are snapshotted, server bare repos stay untouched until a cooling-off period ends, and a written restore procedure covers both single-project and full rollback.
+
+* Problem / Context
+
+Craig manages 12 AI projects under =~/projects/= beside =home= and =work=. Each has its own =.ai/= session machinery, =todo.org=, inbox, memory dir, and git repo on cjennings.net. That isolation was the design — but the life-management projects (finances, jr-estate, danneel, health, kit, clipper, documents…) are all facets of one life, and their tasks compete for the same hours. Today there is no single surface where a [#A] in jr-estate can be weighed against a [#A] in finances; each project's priorities are graded against siblings only. Sessions fragment the same way: a morning touching finances, danneel, and home means three separate session launches, three inboxes, three memory stores, and cross-project handoff files between them.
+
+The forces: (1) one prioritization surface requires one task file (or at least one repo); (2) these projects are critical — legal disputes, estate settlement, finances — so the migration must be provably reversible; (3) per-project git histories carry evidentiary and reference value (especially danneel and jr-estate) and must survive queryably; (4) the =.ai/= ecosystem (sessions, memories, inboxes, workflows) has per-project state that must merge without loss; (5) other machines (velox at minimum) hold clones whose remotes must not break silently.
+
+Survey of the candidates (2026-06-11):
+
+| Project | What it is | .git | Sessions | Open tasks | Memories | Inbox |
+|------------------+---------------------------------------------+-------+----------+------------+----------+-------|
+| clipper | 19 Clipper St SF rental property | 23M | 6 | 1 | 0 | 0 |
+| danneel | 4319 Danneel construction dispute (legal) | 613M | 45 | 10 | 0 | 0 |
+| documents | Disaster-prep document vault | 61M | 7 | 8 | 0 | 2 |
+| elibrary | Ebook + music library management | 2.4M | 6 | 0 | 2 | 3 |
+| fb-photo-scraper | Third-party FB gallery scraper (clone) | 3.4M | 0 | 0 | 0 | 0 |
+| finances | Personal finance (Craig + Christine) | 251M | 24 | 43 | 1 | 4 |
+| health | Personal health management | 5.9M | 27 | 8 | 1 | 3 |
+| jr-estate | JR estate settlement (legal, trust, taxes) | 704M | 44 | 18 | 7 | 2 |
+| kit | Keep In Touch — relationship management | 17M | 20 | 20 | 3 | 4 |
+| little-elisper | The Little LISPer worked in elisp (study) | 4.7M | 2 | 0 | 0 | 0 |
+| philosophy | Philosophy study + discussion notes | 30M | 5 | 0 | 0 | 0 |
+| website | Personal Hugo site (deployed from homelab) | 8.6M | 10 | 11 | 0 | 3 |
+
+All have origin on cjennings.net except fb-photo-scraper (GitHub clone). All =.ai/= dirs are tracked (personal-project model). No project has a live =session-context.org=. Several have small dirty trees (elibrary 2, finances 1, health 1, kit 4, little-elisper 1 files) that must be resolved pre-fold.
+
+* Goals and Non-Goals
+
+** Goals
+- One repo, one =todo.org=, one priority scheme, one =.ai/= session for all personal (non-work) project management.
+- Full git history of every folded project preserved and queryable in place (=git log <area>/= works).
+- All =.ai/= state merged without loss: session archives, memories, inboxes, someday-maybe, project workflows/scripts.
+- A written, tested restore path for any single project and for the whole migration.
+- =~/code/= becomes the only home for standalone code projects.
+
+** Non-Goals
+- No restructuring of home's existing content (homelab docs, assets, music reconciliation dirs stay where they are; re-nesting them under an =infra/= area is vNext).
+- No change to the =work= project in any way.
+- No task content rewriting beyond re-grading priorities to the unified scheme — bodies, links, and histories move as-is.
+- No server-side bare-repo deletion during the migration (archival is a separate, later, post-cooling step).
+- No renaming of the =home= project.
+
+** Scope tiers
+- v1: fold the nine life-management projects (clipper, danneel, documents, elibrary, finances, health, jr-estate, kit, philosophy); relocate the code-shaped three (website, little-elisper, fb-photo-scraper) per Decision 2; ecosystem updates (emacs agenda, rulesets references, velox).
+- Out of scope: work; any =~/code/= project; home's internal restructure.
+- vNext: server bare-repo archival after cooling-off; optional =infra/= re-nesting of homelab content; per-area README normalization.
+
+* Design
+
+** End-state layout
+
+Each folded project becomes a top-level area directory in home, preserving its internal structure:
+
+#+begin_example
+~/projects/home/
+ clipper/ danneel/ documents/ elibrary/
+ finances/ health/ jr-estate/ kit/ philosophy/
+ assets/ docs/ homelab-inventory/ inbox/ scripts/ (existing home content, unchanged)
+ todo.org (unified)
+ .ai/ (single session machinery)
+#+end_example
+
+This matches the established area pattern (work's =deepsat/assets/=, the working-files convention's =<area>/assets/=). Each area keeps its own =assets/=, =docs/=, internal org files, and a per-area =.gitignore= carrying its old ignore patterns (git honors nested ignores; prefixing patterns into the root ignore is error-prone).
+
+** Git history — filter-repo then merge
+
+For each source project, on a throwaway clone (never the original). =--no-local= forces a real transport-style clone instead of hardlinked/shared objects — the conservative shape git-filter-repo's manual recommends, and what makes the clone a genuine fresh-clone safety check. =branch= is the source's actual default branch (fb-photo-scraper is on =master=; assume nothing):
+
+#+begin_example
+branch=$(git -C ~/projects/<name> symbolic-ref --short HEAD)
+git clone --no-local ~/projects/<name> /tmp/fold-<name>
+cd /tmp/fold-<name>
+git filter-repo --to-subdirectory-filter <name>
+cd ~/projects/home
+git remote add fold-<name> /tmp/fold-<name>
+git fetch fold-<name>
+git merge --allow-unrelated-histories -m "feat(<name>): fold <name> project into home" "fold-<name>/$branch"
+git remote remove fold-<name>
+#+end_example
+
+=git filter-repo --force= is not part of this runbook. If filter-repo refuses to run, the fresh-clone safety check failed — stop, write down why, and fix the clone rather than overriding.
+
+=filter-repo= rewrites every historical path under =<name>/=, so after the merge =git log <name>/somefile= shows the file's full history with original commit messages, authors, and dates. The original repo and its server bare are never touched — the rewrite happens on the temp clone only.
+
+The merged home =.git= grows to roughly 1.8G (dominated by danneel 613M + jr-estate 704M + finances 251M). Acceptable for a private single-user server; noted as a clone-time cost.
+
+** The .ai/ and task merge (per project, after the git merge)
+
+The git merge lands the project's files under =<name>/=, including its old =.ai/= and =todo.org=. A post-merge commit then redistributes that state:
+
+1. /Sessions:/ =git mv <name>/.ai/sessions/*= into home's =.ai/sessions/=, inserting the area into the name: =YYYY-MM-DD-HH-MM-<desc>.org= → =YYYY-MM-DD-HH-MM-<name>-<desc>.org=. Dated names make collisions near-impossible; the prefix preserves provenance.
+2. /todo.org:/ append the project's open work as a new top-level section =* <Area> Open Work= (matching =* Home Open Work=), and its resolved section likewise. Each imported section heading carries a properties drawer marking provenance — =:MIGRATED_FROM: <name>= and =:MIGRATED_ON: YYYY-MM-DD= — so the import boundary stays visible to future edits and to the restore runbook. Walk the incoming tasks with Craig to re-grade priorities onto the unified scheme (home's A-D impact/urgency ladder, generalized beyond infra) and add an area tag (=:finances:=, =:jrestate:=, =:danneel:=, …). Then delete =<name>/todo.org=.
+3. /notes.org:/ the project's Project-Specific Context moves to =<name>/notes.org= (area-local reference, linked from home's =.ai/notes.org=). Active Reminders and Pending Decisions merge into home's =.ai/notes.org= with area attribution.
+4. /Inbox:/ process each project's inbox to zero before the fold (preferred), or move unprocessed items into home's =inbox/= renamed =YYYY-MM-DD-from-<name>-<orig>.ext=.
+5. /Workflows + scripts:/ copy =<name>/.ai/project-workflows/*= and =project-scripts/*= into home's, after a filename-collision check (13 workflow files exist across sources; any collision is resolved by area-prefixing the incoming file). Then delete the area's old =.ai/= machinery (=protocols.org=, =workflows/=, =scripts/= — all template-synced duplicates).
+6. /someday-maybe.org:/ append under an =* <Area>= header in home's.
+7. /Memory:/ copy =~/.claude/projects/-home-cjennings-projects-<name>/memory/*.md= into home's memory dir (rename on slug collision), append index lines to =MEMORY.md=, dedupe against existing entries, then archive the source memory dir into the backup tar (it lives outside git).
+8. /Links:/ =grep -rn "projects/<name>" ~/projects/home ~/.emacs.d ~/sync/org ~/org/roam= and fix every absolute reference to the new path. Record the before-count, fix, re-run, and classify any remaining hits as historical (session archives, this spec) or live — live hits block the fold's close. Relative links inside the area survive the move untouched because internal structure is preserved.
+
+** Per-fold manifest
+
+Every fold produces a tracked manifest at =docs/consolidation-manifest-<name>.org=, written as the fold proceeds and committed with the redistribution commit. The manifest is the restore contract and the verification record — without it, "every step is reversible" is a slogan. It records:
+
+- /Source state:/ source path, HEAD sha, branch, =git status --porcelain=v1= output at gate time (must be empty), origin URL.
+- /Tracked universe:/ the =git ls-files= listing from the source (or a sha256 of it, with the listing in an appendix block). After the merge, every path must exist under =home/<name>/= or appear in the redistribution map below.
+- /Untracked, ignored, and inbox inventories:/ each file listed with its explicit disposition — processed, moved (to where), archived, or intentionally dropped. Nothing leaves the source tree without a line here.
+- /Redistribution map:/ sessions moved (old → new names), todo.org section markers added (=:MIGRATED_FROM:= headings), notes/someday-maybe merges, workflows/scripts copied (with collision resolutions), memory files copied + =MEMORY.md= lines added, link rewrites made (=path:line=, before → after).
+- /Commits:/ the fold merge commit sha and the redistribution commit sha.
+- /Retired path:/ where the source dir went.
+
+Verification per fold checks path lists against this manifest, not file counts — a count can pass while losing files and fail on intentional redistribution.
+
+** Safety net and restore
+
+Layered, oldest-to-newest:
+
+- /Layer 0 — filesystem snapshot./ Before anything: =snapper create --description pre-consolidation= (ratio's root is btrfs with snapper) plus a belt-and-suspenders tar of the memory dirs: =tar czf ~/backups/claude-memory-pre-consolidation-$(date +%F).tgz -C ~/.claude projects=. Content-only restore is sufficient for the memory tar — memory files are plain-text markdown the harness reads by path; no permissions, ACL, or xattr metadata is load-bearing, so plain =tar czf= is the contract.
+- /Layer 1 — server bare repos untouched./ Origin repos on cjennings.net remain exactly as they are through v1. They hold every byte of every project's history independent of anything done locally.
+- /Layer 2 — pre-fold tags./ Home gets =git tag pre-consolidation= before the first fold and =git tag pre-fold-<name>= before each subsequent one, pushed to origin.
+- /Layer 3 — retired dirs./ After a fold is verified, the source dir moves to =~/projects/.retired/<name>= (not deleted). Deleted only after the cooling-off period.
+- /Cooling-off:/ 30 days minimum after the final fold, and not before velox is migrated. Only then does vNext server archival (move bares to =~/git/archive/=) become eligible.
+
+*** Restore one project — two modes
+
+/Mode A — resurrect standalone (leaves home alone)./ =git clone cjennings@cjennings.net:git/<name>.git ~/projects/<name>=, restore its memory dir from the tar. The folded copy in home stays as a harmless duplicate (or is removed later via Mode B). This is the fast path when the need is "I want the project back," not "the fold was wrong."
+
+/Mode B — remove the folded state from home./ A fold is two commits plus out-of-git side effects; removal must unwind all of it, using the manifest:
+
+1. =git revert <redistribution-commit>= then =git revert -m 1 <merge-commit>=, in that order (newest first). This is the supported path while the fold is recent — before later edits touch the shared files.
+2. If either revert conflicts (todo.org and =.ai/notes.org= are hot files — expected once home has moved on), abort it and instead excise manually from the manifest's redistribution map: delete the =:MIGRATED_FROM: <name>= todo.org sections, the area-prefixed session files, the copied workflows/scripts, and =git rm -r <name>/= — one removal commit citing the manifest.
+3. Out-of-git effects either way: delete the copied memory files and their =MEMORY.md= index lines (named in the manifest); re-fix any link rewrites if the old path is coming back.
+
+/Restore everything:/ snapper rollback (or restore the snapshot's =~/projects/=), restore the memory tar, =git reset --hard pre-consolidation= on home plus a coordinated forced push — acceptable on a single-user remote, with the tag as the anchor.
+
+** Multi-machine
+
+velox (and any other machine with clones) keeps working against the untouched server bares until its own migration step: pull home (which brings all folded content), then retire its local =~/projects/<name>= clones the same way. Nothing breaks in the interim — the old remotes still exist; they're just frozen. The =ai= launcher discovers projects by =.ai/protocols.org= presence, so retired dirs (moved under =.retired/=, outside its scan roots) drop out automatically. =inbox-send= targets shrink the same way; any rulesets doc or workflow that names a folded project as a handoff target gets updated in the final phase.
+
+* Alternatives Considered
+
+** Keep separate repos, unify only the agenda (org-agenda-files spanning all todo.orgs)
+- Good, because zero migration risk and Craig's emacs agenda can already span files.
+- Bad, because it solves only prioritization-viewing, not management: 10 sessions, 10 inboxes, 10 memory stores remain; Claude still can't see or rebalance the whole picture in one session; cross-project handoffs persist.
+- Bad, because priority schemes stay divergent per file.
+- Neutral, because it could serve as an interim state, but it builds nothing toward the end goal.
+
+** git subtree add per project
+- Good, because one command per fold, no external tooling.
+- Bad, because history isn't path-rewritten: =git log <name>/file= doesn't follow into pre-merge history without =--follow= gymnastics, weakening the evidentiary value of danneel/jr-estate histories.
+- Neutral, because content-wise the result is identical; only history ergonomics differ.
+
+** Import working trees only, archive old repos (no history merge)
+- Good, because the home repo stays small and the procedure is trivially simple.
+- Bad, because in-place history is lost — every "when did this clause change" question requires resurrecting an archived repo.
+- Neutral, because Layer-1 bares preserve history regardless; this is about whether history is /at hand/.
+
+** One new "life" super-repo instead of growing home
+- Good, because a clean slate avoids home's existing 109M history and infra identity.
+- Bad, because home is already the hub (biggest session history, the template patterns, Craig's habits) and would itself need folding in — strictly more work for a cosmetic gain.
+
+* Decisions
+
+** D1 — Merge strategy: filter-repo + merge per project
+- State: accepted
+- Context: critical legal/financial histories must stay queryable in place; restore must be possible regardless.
+- Decision: We will fold each project with =git filter-repo --to-subdirectory-filter= on a temp clone, merged with =--allow-unrelated-histories=.
+- Consequences: easier — full per-area history in one repo, originals untouched; harder — home =.git= grows to ~1.8G, and =git-filter-repo= becomes a migration dependency (AUR: =git-filter-repo=).
+
+** D2 — Disposition of the code-shaped three
+- State: accepted (Craig, 2026-06-11)
+- Context: website (Hugo codebase), little-elisper (code study), fb-photo-scraper (third-party clone, no .ai) are code-shaped, and the target model says code lives standalone in =~/code/=.
+- Decision: We will move website and little-elisper to =~/code/= as standalone AI projects (plain =mv= + memory-dir rename, same as the homelab→home rename runbook), and delete fb-photo-scraper (it's an unmodified upstream clone — re-cloneable from =https://github.com/budavariam/traverse_facebook_galleries.git=, branch =master=; recorded here so the proof survives the deletion).
+- Consequences: easier — =~/projects/= reaches the clean end state (home + work); harder — website's 11 open tasks stay in their own todo.org, outside the unified prioritization (acceptable: they're code tasks, not life tasks).
+
+** D3 — Unified todo.org: one file, per-area top-level sections
+- State: accepted
+- Context: cross-area prioritization wants one surface; the staleness script, agenda, and review workflows all operate on one file today.
+- Decision: We will keep a single =todo.org= with =* <Area> Open Work= top-level sections mirroring =* Home Open Work=, unified under home's A-D priority scheme, with area tags on every imported task.
+- Consequences: easier — one review rotation, one grep, one agenda file covers everything; harder — the file grows to roughly 5-6k lines (~110 incoming open tasks), so reads lean on Grep/offset and the section discipline matters more.
+
+** D4 — Per-area task triage at fold time
+- State: accepted
+- Context: each project graded priorities against siblings only; merging without re-grading would make cross-area priorities meaningless.
+- Decision: We will walk each incoming area's open tasks with Craig at fold time, re-grading to the unified scheme (the task-review walk shape, applied per area).
+- Consequences: easier — the unified list is trustworthy from day one; harder — the big folds (finances at 43 tasks) cost a real review session each.
+
+** D5 — Cooling-off before any destruction
+- State: accepted
+- Context: "if it goes south, I need a way to restore."
+- Decision: We will destroy nothing for 30 days after the final fold: source dirs go to =~/projects/.retired/=, server bares stay, snapshots and tags persist. fb-photo-scraper deletion (D2) is the one exception — it's an unmodified upstream clone.
+- Consequences: easier — every layer of the restore path stays live through the risky window; harder — ~2G of retired duplicates sit on disk for a month.
+
+* Implementation phases
+
+Each phase ends with a working tree, a pushed commit, and a verification gate. One project per session is the expected pace; phases 3+ are repetitions of the runbook proven in phase 2.
+
+** Phase 0 — Pre-flight (global prep; gates per project at its turn)
+Install =git-filter-repo=. Snapper snapshot + memory-dir tar. Tag and push =pre-consolidation= on home.
+
+The *live inventory gate* lives at =docs/consolidation-manifest-inventory.org= and is regenerated *per project, immediately before that project's fold* — not all at once. Craig keeps using not-yet-folded projects (staged freeze), so a single up-front table would go stale by Phase 3; the per-fold regeneration is the gate. Fields per project: default branch, origin URL, dirty count (=git status --porcelain=), ahead/behind vs upstream, inbox file count, =session-context.org= presence, memory file count, project-workflow/-script names (collision candidates), and disposition (fold / relocate / delete / out-of-scope). The gate passes only when: clean tree, ahead/behind 0/0, inbox empty, no live session-context. A failing project gets fixed (wrap, commit, process, push) and its row regenerated before its fold begins.
+
+D2 is resolved (2026-06-11); no open decisions remain in this phase.
+
+** Phase 1 — Pilot fold: philosophy
+Smallest life project, no todo.org, no memories, empty inbox. Run the full fold runbook (git merge + redistribution + manifest + verification). Then the *rollback drill*: in a disposable =--no-local= clone of home (or a throwaway branch), run the Mode-B removal runbook against the pilot's manifest and verify the folded state is fully gone — sessions, workflows, =<name>/= tree. Discard the clone. The legal and financial folds must never be the first test of the removal story. This phase hardens the runbook appendix; expect to amend the spec from what's learned (history entry, not rewrite).
+
+** Phase 2 — Dress rehearsal: clipper
+Nearly as small (23M, no memories, empty inbox) but adds the one runbook path the pilot can't exercise: the todo.org import — =* Clipper Open Work= section, =:MIGRATED_FROM:= markers, and a one-task triage with Craig. After this phase every runbook step has run at least once except the memory merge (premieres in Phase 3; lowest-risk step — plain file copies outside git, tar-backed).
+
+** Phase 3 — jr-estate
+The priority fold. 704M history, 18-task triage, 44 sessions, and the first memory merge (7 files). One session.
+
+** Phase 4 — danneel
+613M history, 10-task triage, 45 sessions, 1 project-workflow. One session.
+
+** Phase 5 — finances
+251M history and the heaviest triage (43 tasks). One session, possibly two if the triage runs long.
+
+** Phase 6 — Remaining folds + code relocations (together)
+Fold documents, elibrary, health, kit (~36 incoming tasks, elibrary/health/kit memories, kit's 4 project-workflows collision-checked). Move website and little-elisper to =~/code/= (mv + memory-dir rename per the homelab→home runbook); delete fb-photo-scraper (origin recorded in D2). After this phase =~/projects/= contains home, work, and =.retired/=.
+
+** Phase 7 — Ecosystem pass
+Fix every absolute-path reference (emacs config, org-roam, agenda-files, bookmarks, rulesets docs naming folded projects as inbox-send/cross-agent targets). Migrate velox (pull home, retire its clones). Write the KB node recording the new layout. Start the 30-day cooling clock; file a dated vNext task for server bare archival and =.retired/= deletion.
+
+* Acceptance criteria
+
+- [ ] =~/projects/= contains exactly =home=, =work=, and =.retired/=.
+- [ ] For each folded project, =git log --oneline <name>/ | tail= in home shows its earliest original commits.
+- [ ] Manifest parity per fold: every path in the source's =git ls-files= listing exists under =home/<name>/= or appears in the manifest's redistribution map; every untracked/ignored/inbox file has a recorded disposition. Path-list comparison, not counts.
+- [ ] =todo.org= passes org-lint; every imported task carries an area tag and an A-D priority Craig re-graded; imported sections carry =:MIGRATED_FROM:= markers.
+- [ ] =task-review-staleness.sh --list todo.org 20= run after each fold surfaces the imported area's tasks as depth-2 review units alongside existing areas (proves the rotation spans the whole list).
+- [ ] Per fold: source memory basenames diffed against home's memory dir and =MEMORY.md= entries — all accounted for; source memory dirs are in the backup tar.
+- [ ] Link-rewrite check per fold: the before-grep count is recorded in the manifest, and the after-grep over =~/.emacs.d ~/sync/org ~/org/roam ~/projects/home= returns only hits classified historical (session archives, this spec) — zero live links.
+- [ ] Layer-1 restore drill passes: clone one folded project from its untouched server bare into =/tmp=, confirm it's whole.
+- [ ] Mode-B rollback drill (Phase 1 pilot) passes: the pilot fold is fully removable from a disposable clone using only its manifest.
+- [ ] A fresh Claude session in home can answer "what are my top 5 tasks across all areas?" from the unified todo.org.
+- [ ] velox runs a clean session in home post-migration with no stale-remote errors.
+
+* Readiness dimensions
+
+- Data model & ownership: every file keeps its owner (Craig); =.ai/= state redistributes per the merge map above; memory dirs are the one store outside git — covered by the tar in Phase 0 and the copy step per fold.
+- Errors, empty states & failure: every fold step is git-tracked, so a failed fold is =git reset --hard <pre-fold tag>= plus re-running from the temp clone (which is rebuilt from scratch each attempt). filter-repo failures abort before anything touches home.
+- Security & privacy: all content stays on the private cjennings.net remote; no new exposure surface. The merged repo concentrates sensitive material (legal + financial + health) in one clone — same machines, same threat model as today.
+- Observability: each fold is one merge commit + one redistribution commit, tagged; progress is the phase checklist in todo.org; verification gates are the acceptance criteria run per-fold.
+- Performance & scale: ~1.8G final =.git=; clone cost noted. todo.org at 5-6k lines stays well within Grep/offset workflows. No runtime performance surface.
+- Reuse & lost opportunities: reuses the homelab→home rename runbook (memory-dir rename, link sweep), the task-review walk for triage, snapper for snapshots, and the established area-dir pattern. git-filter-repo over hand-rolled rewrites.
+- Architecture fit & weak points: area dirs match the working-files convention. Weak point: the =.ai/= redistribution is manual and per-project — mitigated by the pilot phase hardening a written runbook before the critical folds.
+- Config surface: none — no knobs. The one dependency is the =git-filter-repo= package.
+- Documentation plan: this spec is the migration doc; the fold runbook and manifest template live in the appendix below (refined by the Phase 2 pilot); the KB node in Phase 6 records the end state for all future agents.
+- Dev tooling: N/A because the migration is one-shot; the runbook commands in Design are the tooling.
+- Rollout, compatibility & rollback: staged per-project rollout, multi-machine sequencing (velox last), layered rollback (snapshot / untouched bares / tags / retired dirs), 30-day cooling before any destruction. Dry-run equivalent: the pilot fold.
+- External APIs & deps: =git-filter-repo= (AUR, stable, widely used — verify installed in Phase 0). No network APIs.
+
+* Risks, Rabbit Holes, and Drawbacks
+
+- /Link rot is the long tail./ Absolute =file:= links to old project paths can lurk in org-roam, emacs bookmarks, calendar event descriptions, and Keep notes. The Phase 6 grep covers the file-based stores; Keep and calendar references can't be grepped — accept that stragglers get fixed on encounter.
+- /todo.org scale./ 5-6k lines is fine for tools, but the agenda view gets dense. If it becomes noise, the vNext escape hatch is per-area =#+CATEGORY= or splitting resolved sections to an archive file — not re-splitting projects.
+- /Triage fatigue./ Re-grading ~110 tasks is the human bottleneck. Mitigation: it's split across the fold phases, and each area's walk uses the existing 7-at-a-time review muscle.
+- /Workflow collisions./ 13 project-workflow files across sources; names look distinct but the check is mandatory per fold.
+- /The merged repo is a bigger blast radius./ A bad force-push or corrupting operation now touches everything. Mitigation: the same layered backups, plus home already carries this responsibility for its own content.
+- /Drawback accepted:/ per-project session isolation disappears — one project's noisy session history now shares a dir with everything. The area prefix on archived session names keeps provenance.
+
+* Appendix — Fold runbook (per project)
+
+Refined by the Phase 2 pilot; until then this is the v0 contract. Every step either succeeds with the expected output or the fold stops — no improvising past a failed step.
+
+1. /Gate./ Regenerate the project's row in the live inventory (Phase 0 fields). Require: clean =git status --porcelain=, ahead/behind 0/0, inbox empty, no =session-context.org=. Fix and regenerate, or stop.
+2. /Manifest open./ Create =docs/consolidation-manifest-<name>.org= from the template below; fill source state and the =git ls-files= listing; inventory untracked/ignored files with dispositions. The Redistribution row reads "the commit introducing this manifest" — a commit sha can't be embedded in its own commit (pilot learning, 2026-06-11); the merge sha is known beforehand and is recorded literally.
+3. /Tag./ =git tag pre-fold-<name> && git push origin pre-fold-<name>=.
+4. /History fold./ The filter-repo + merge block from Design (with =--no-local=, =$branch=, no =--force=). Record the merge sha in the manifest.
+5. /Redistribute./ Steps 1-8 of the =.ai/= and task merge map, recording each move in the manifest's redistribution map as it happens. One commit; record its sha.
+6. /Verify./ Manifest parity (path lists), org-lint on todo.org, staleness-script check, memory diff, link before/after grep. All green or the fold stops here for repair.
+7. /Retire./ =mv ~/projects/<name> ~/projects/.retired/<name>=; record the path. Push home.
+
+** Manifest template
+
+#+begin_example
+,#+TITLE: Consolidation manifest — <name>
+| Source path | ~/projects/<name> |
+| Origin | <url> |
+| Branch / HEAD | <branch> / <sha> |
+| Gate state | clean / 0-0 / inbox 0 / no session-context |
+| Merge commit | <sha> |
+| Redistribution | <sha> |
+| Retired to | ~/projects/.retired/<name> |
+
+,* Tracked universe
+<git ls-files output, or sha256 + appendix>
+
+,* Untracked / ignored / inbox dispositions
+| file | disposition (processed / moved-to / archived / dropped) |
+
+,* Redistribution map
+- Sessions: <old> → <new> …
+- todo.org: section ":MIGRATED_FROM: <name>" added at <heading>
+- Workflows/scripts copied: <names + collision resolutions>
+- Memory: <files copied> + MEMORY.md lines added
+- Link rewrites: <file:line before → after>
+
+,* Link grep
+- Before: <count> | After: <count, all classified historical>
+#+end_example
+
+* Review dispositions
+
+Findings from the 2026-06-11 Codex review (review file deleted on processing per spec-response). Modified items below; *everything else was accepted as written* — H1 (manifest + redistribution-aware restore), H2 (path-list verification, porcelain gate, find-prune fix by removal), H3 (=--no-local=, no =--force=), H4 (live inventory gate), M2 (pilot rollback drill), M3 (fb-photo-scraper re-clone pointer), the UX provenance markers, the documentation appendix, and the memory/link verification commands.
+
+- /M1 (memory tar metadata) — modified:/ the review offered preserving metadata or declaring content-only sufficient. Chose content-only: memory files are plain-text markdown the harness reads by path; no permissions/ACL/xattr metadata is load-bearing. Stated in Layer 0 rather than adding =--xattrs --acls=.
+- /Test strategy item 2 (staleness fixture test) — modified:/ a live =task-review-staleness.sh --list todo.org 20= check after each fold replaces a new fixture-based unit test. The script already has its own bats suite; the migration-specific question ("are imported area tasks depth-2 review units?") is answered better by the live check on the real file, per fold, than by a one-shot fixture.
+- /Open question 2 (revert vs manifest-removal as the supported runbook) — modified:/ the "choose one" framing doesn't survive the time axis. Supported path: revert both commits (redistribution first) while the fold is recent; once shared files have moved on and reverts conflict, the manifest-driven removal commit is the path. Both are now written in Restore Mode B; the manifest makes the fallback safe, which is why it exists.
+
+* Review and iteration history
+
+** 2026-06-11 Thu @ 15:11:32 -0500 — Claude Code (home, with Craig) — author
+- What changed: re-sequenced the implementation phases to Craig's chosen order — philosophy pilot, clipper dress rehearsal (added as its own phase so the todo.org-import path is proven before real data), then jr-estate → danneel → finances by urgency, with the remaining folds + code relocations merged into one closing phase before the ecosystem pass. Phase 0's live inventory gate is now explicitly per-project-at-its-turn, matching the staged-freeze approach (Craig keeps using not-yet-folded projects until their turn).
+- Why: Craig wants the critical legal/financial projects consolidated early after a proven runbook, and chose staged freeze over a full shutdown. The clipper rehearsal closes the gap where the pilot (no todo.org) never exercises task import.
+- Artifacts: todo.org phase tasks re-sequenced to match.
+
+** 2026-06-11 Thu @ 14:13:49 -0500 — Codex — reviewer
+- What changed or was recommended: assigned =Ready= after re-running spec-review against the incorporated spec; no further blocking review notes and no new review file.
+- Why: the prior blockers are now covered by the per-fold manifest contract, live inventory gate, =--no-local= filter-repo runbook, redistribution-aware restore, Phase 2 rollback drill, and manifest-based acceptance criteria.
+- Artifacts: this spec; [[file:../todo.org::*Project consolidation into home][todo.org tracking task]] updated with Ready status and implementation phase tasks.
+
+** 2026-06-11 Thu @ 13:20:54 -0500 — Claude Code (home) — responder
+- What changed: all four blocking findings accepted and woven in — =--no-local= + no-=--force= runbook with a =$branch= variable (H3, H4's master/main catch), a Per-fold manifest section as the restore/verification contract (H1, H2), two-mode single-project restore covering the redistribution commit (H1), Phase 0 live inventory gate (H4), Phase 2 Mode-B rollback drill (M2), manifest-parity acceptance criteria replacing file counts (H2), fb-photo-scraper re-clone pointer in D2 (M3), =:MIGRATED_FROM:= provenance markers (UX), runbook appendix + manifest template (docs). Three points modified with reasons in Review dispositions; nothing rejected.
+- Why: the review's core finding was right — restore and verification only covered the history merge, not the redistribution commit and the untracked-file universe. The manifest is the single artifact that fixes both.
+- Artifacts: review file (deleted on processing); dispositions section above; todo.org tracking task updated.
+
+** 2026-06-11 Thu @ 13:09:29 -0500 — Codex — reviewer
+- What changed or was recommended: assigned =Not ready= and wrote a blocking review focused on exact rollback semantics, per-fold manifests, live inventory gating, =git clone --no-local= for filter-repo safety, and stronger verification than raw file counts.
+- Why: the design direction is sound, but implementation would still require inventing how to unwind redistributed =.ai/=, =todo.org=, inbox, and memory state safely after each fold.
+- Artifacts: review file deleted during the response pass; retained via the dispositions section above.
+
+** 2026-06-11 Thu @ 12:08:03 -0500 — Claude (with Craig) — author
+- What: initial draft.
+- Why: Craig asked for a consolidation design with restore guarantees — one prioritization surface for all personal projects.
+- Artifacts: survey data gathered live from ~/projects on ratio; todo.org task cross-linked.
diff --git a/inbox/PROCESSED-2026-06-11-1705-from-home-addendum-to-today-s-consolidation.org b/inbox/PROCESSED-2026-06-11-1705-from-home-addendum-to-today-s-consolidation.org
new file mode 100644
index 0000000..392b844
--- /dev/null
+++ b/inbox/PROCESSED-2026-06-11-1705-from-home-addendum-to-today-s-consolidation.org
@@ -0,0 +1,5 @@
+#+TITLE: Addendum to today's consolidation handoff: first concrete to
+#+SOURCE: from home
+#+DATE: 2026-06-11 17:05:20 -0500
+
+Addendum to today's consolidation handoff: first concrete tooling edge case found. todo-cleanup.el --archive-done assumes exactly one level-1 'Open Work' and one 'Resolved' heading per todo.org; home's consolidated file now has per-area pairs (Home Open Work / Home Resolved, Clipper Open Work / Clipper Resolved, more coming) and the pass skips with 'more than one level-1 heading contains Open Work'. Suggested fix: match each '* <Area> Open Work' with its '* <Area> Resolved' sibling and archive within the pair, falling back to current behavior for single-pair files. Until then home archives manually at wrap-up.
diff --git a/todo.org b/todo.org
index 85e676e..03fd971 100644
--- a/todo.org
+++ b/todo.org
@@ -34,6 +34,16 @@ Tags are assigned and refreshed by =task-audit=; =task-review= keeps them honest
* Rulesets Open Work
+** TODO [#B] todo-cleanup.el per-area Open Work / Resolved pairs :feature:
+:PROPERTIES:
+:CREATED: [2026-06-11 Thu]
+:LAST_REVIEWED: 2026-06-11
+:END:
+=--archive-done= assumes exactly one level-1 "Open Work" and one "Resolved" heading per todo.org. Home's consolidated file now carries per-area pairs (Home Open Work / Home Resolved, Clipper Open Work / Clipper Resolved, more arriving per fold) and the pass skips with "more than one level-1 heading contains Open Work". Suggested fix from home's 2026-06-11 addendum handoff: match each =* <Area> Open Work= with its =* <Area> Resolved= sibling and archive within the pair, falling back to current single-pair behavior. Home archives manually at wrap-up until this lands, so every fold widens the manual gap. ERT tests first (multi-pair, single-pair regression, unpaired-area error).
+
+** VERIFY Should new personal projects start as areas inside home rather than standalone ~/projects entries?
+Home's consolidation (2026-06-11) leaves ~/projects with home and work only. The open template question: when Craig starts a new personal project, does =first-session.org= / =install-ai.sh= guidance now say "create an area in home" by default, with standalone reserved for code projects in ~/code? Affects first-session.org, install-ai.sh docs, and the triggers.md "Launch project X" resolution (folded names like "finances" no longer resolve as projects; an area-aware launch could map them to home).
+
** DOING [#C] Check that memories are sync'd across machines via git :spec:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-10