#+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 /= 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 =/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/ symbolic-ref --short HEAD) git clone --no-local ~/projects/ /tmp/fold- cd /tmp/fold- git filter-repo --to-subdirectory-filter cd ~/projects/home git remote add fold- /tmp/fold- git fetch fold- git merge --allow-unrelated-histories -m "feat(): fold project into home" "fold-/$branch" git remote remove fold- #+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 =/=, so after the merge =git log /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 =/=, including its old =.ai/= and =todo.org=. A post-merge commit then redistributes that state: 1. /Sessions:/ =git mv /.ai/sessions/*= into home's =.ai/sessions/=, inserting the area into the name: =YYYY-MM-DD-HH-MM-.org= → =YYYY-MM-DD-HH-MM--.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 =* Open Work= (matching =* Home Open Work=), and its resolved section likewise. Each imported section heading carries a properties drawer marking provenance — =:MIGRATED_FROM: = 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 =/todo.org=. 3. /notes.org:/ the project's Project-Specific Context moves to =/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--.ext=. 5. /Workflows + scripts:/ copy =/.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 =* = header in home's. 7. /Memory:/ copy =~/.claude/projects/-home-cjennings-projects-/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/" ~/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-.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//= 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-= before each subsequent one, pushed to origin. - /Layer 3 — retired dirs./ After a fold is verified, the source dir moves to =~/projects/.retired/= (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/.git ~/projects/=, 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 = then =git revert -m 1 =, 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: = todo.org sections, the area-prefixed session files, the copied workflows/scripts, and =git rm -r /= — 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/= 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 /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 =* 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, =/= 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 / | 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//= 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 = 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-.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- && git push origin pre-fold-=. 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/ ~/projects/.retired/=; record the path. Push home. ** Manifest template #+begin_example ,#+TITLE: Consolidation manifest — | Source path | ~/projects/ | | Origin | | | Branch / HEAD | / | | Gate state | clean / 0-0 / inbox 0 / no session-context | | Merge commit | | | Redistribution | | | Retired to | ~/projects/.retired/ | ,* Tracked universe ,* Untracked / ignored / inbox dispositions | file | disposition (processed / moved-to / archived / dropped) | ,* Redistribution map - Sessions: … - todo.org: section ":MIGRATED_FROM: " added at - Workflows/scripts copied: - Memory: + MEMORY.md lines added - Link rewrites: ,* Link grep - Before: | After: #+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.