Context
The 361-coders-nz org hosted two siblings that drifted apart in scope but overlapped in content:
oxflow— deployed static hub atoxflow.design.3sixtyone.co. Landingindex.htmllinking to four self-contained sub-apps (app/,flows-app/,presentation/,prototypes/). Also collected 43 stray PNGs from Playwright MCP sessions and a 9.5 MBrev1/archive of superseded design work.oxflow-docs— knowledge repo withCLAUDE.md,TEAM.md,BRANDING.md,templates/,docs/(85 formal specs across 5 entity layers),research/,meetings/,status/, and a vanilla-JS SPA doc viewer at/app/on port 8910.
Byte-level inventory showed the docs/ trees, plus presentation/, prototypes/, proposal/, and app/ folders, were identical copies between the two repos. Two places to write the same content invites drift; four team members working with AI agents would inevitably diverge. No ADRs existed to record why things were split.
We want a single source of truth for both planning decisions (research, ADRs, meetings) and implementation progress (specs, BMAD sync from the codebase).
We will merge
oxflowandoxflow-docsinto a single361-coders-nz/oxflowmonorepo, with history from both preserved viagit-filter-repo.
Decision
Merge using git-filter-repo:
- Clone each repo into a temporary
_rewrite/workspace. - Rewrite
oxflow’s history: drop the redundantdocs/(canonical copy stays inoxflow-docs), drop local.claude/, then--to-subdirectory-filter apps/site. - Leave
oxflow-docsstructure unchanged. git inita freshoxflow-mono. Fetch + merge both rewritten repos with--allow-unrelated-histories.- In a single reorg commit, flatten
apps/site/into the repo root — the duplicate folders (presentation/,prototypes/,proposal/,app/) were byte-identical to the oxflow-docs copies, so onlyindex.html,vercel.json,.vercelignore, andflows-app/needed to move up.apps/site/was then removed. - Move root PNGs →
archive/screenshots/,.playwright-mcp/→archive/mcp-snapshots/,rev1/→archive/rev1/. - Unify
README.md(combined content of both) and.gitignore(adopt the broader oxflow rules + add Quartz build exclusions). Rewrite.vercelignoreto excludedocs/,research/,decisions/,meetings/,status/,prompts/,raw-dumps/,templates/,meta/,apps/,archive/from the static-site build.
Result: repo root matches the live Vercel serve path, so the existing Vercel project needs no configuration change. apps/ is reserved for the Quartz wiki (Phase 2).
Alternatives considered
- Keep the two repos, sync with CI — rejected because two-PR workflow for cross-cutting changes creates drift and slows multi-agent work. Sync is harder than merge at this stage.
git subtree add— simpler thanfilter-repobut doesn’t rename tags cleanly and leaves a messier graph log.filter-repodeduplicated empty commits (commits that only touched dropped paths) automatically, whichsubtreedoesn’t.- New repo, copy files, no history preserved — rejected; we wanted
git log --followto work on every file.
Consequences
Positive
- One PR per change. One review flow. One CODEOWNERS. One Vercel project (+ a second for the wiki in Phase 2).
git log --followtraces every file back to its original commit in either source repo.apps/cleanly hosts future build-step apps (Quartz, and anything else) without polluting the deployed static hub.
Negative
filter-repopruned commits from the oxflow side that only touched the redundantdocs/(e.g. “Add DevOps & Infrastructure design spec” + its revert). That’s fine because the canonical copy of those changes is in the oxflow-docs history, but it means agit log --allshows 28 commits instead of 31.- The two old repos should be archived in GitHub to prevent confused contributors pushing there.
Follow-up
- Archive
361-coders-nz/oxflow(old) and361-coders-nz/oxflow-docsin GitHub with a README pointer to the new repo. - Update the Vercel project to pull from the new monorepo.
- Phase 2: deploy Quartz from
apps/wiki/on a new subdomain. - Phase 2: wire the BMAD sync GitHub Action once the real codebase repo exists (see 0003-bmad-sync-contract).