Status: Accepted Date: 2026-01-10 Authors: Development Team Reviewers: Architecture Team Supersedes: N/A Superseded by: N/A
Context and Problem Statement#
The Oshun platform is undergoing a major monorepo migration to consolidate the
existing lilith and yemaya codebases into a unified Nx workspace. Currently,
both lilith and yemaya exist as nested directories within the oshun root,
each maintaining their own independent git repositories:
- lilith/.git: 88 commits, 48MB repository, remote at
github.com:GreyChimp/lilith.git - yemaya/.git: 3 commits, 18MB repository, remote at
github.com:GreyChimp/yemaya.git - yemaya/packages/godot/gdextension/native/build/_deps/godot-cpp-src/.git: Build dependency (CMake FetchContent artifact)
We need to decide on a git strategy for the unified monorepo:
- Absorb the nested repositories by removing their
.gitdirectories and creating a single unified git history - Submodules to maintain lilith and yemaya as separate git repositories referenced from the parent
This decision is foundational and will affect all subsequent development workflows, CI/CD pipelines, and team collaboration patterns for the duration of the project.
Decision Drivers#
- Developer Experience: Simplified workflows, reduced cognitive overhead, faster onboarding
- CI/CD Simplicity: Single pipeline vs. multi-repo coordination, build caching, artifact management
- Atomic Changes: Ability to make cross-project changes in a single commit/PR
- Code Sharing: Ease of sharing code between lilith, yemaya, and new domains (isis, sophia, hathor, bellona)
- Nx Compatibility: Optimal integration with Nx workspace features (affected commands, caching, task orchestration)
- History Preservation: Retaining or abandoning existing git history
- Team Workflow: PR reviews, branch management, merge conflict resolution
- Repository Size: Total repo size over time, clone performance
- Release Management: Coordinated releases across domains vs. independent versioning
Considered Options#
Option 1: Absorb Nested Repositories (Recommended)#
Description: Remove the .git directories from lilith and yemaya,
initialize a new git repository at the oshun root, and treat all code as a
single unified codebase. Existing git history is preserved via backup and
archived for reference but not incorporated into the new repo.
Pros:
- ✅ Single source of truth: One repository, one history, one set of branches
- ✅ Atomic cross-domain changes: Refactoring that spans lilith, yemaya, and shared libraries can be done in a single commit
- ✅ Nx optimization: Full compatibility with
nx affected, build caching, and task graph without submodule complexity - ✅ Simplified CI/CD: Single pipeline configuration, no submodule checkout steps, straightforward caching
- ✅ Easier code reviews: PRs show all related changes together, reviewers see complete context
- ✅ Standard monorepo patterns: Follows industry best practices (Google, Meta, Microsoft monorepo approaches)
- ✅ Simplified onboarding: New developers clone once, no submodule initialization required
- ✅ Branch management: Single branch strategy, no cross-repo branch synchronization
- ✅ Merge conflict resolution: All conflicts resolved in one place with full context
- ✅ Dependency management: pnpm workspace hoisting works seamlessly across all packages
Cons:
- ❌ History discontinuity: New repository starts fresh; existing 88 + 3 commits archived separately
- ❌ Initial setup effort: Requires coordinated migration, backup procedures, and team communication
- ❌ Repository size growth: Single repo will grow larger over time (mitigated by git LFS for binaries)
- ❌ Independent release complexity: If lilith and yemaya need truly independent release cycles, requires additional tooling (Nx release, changesets)
Cost: Low - primarily coordination and documentation effort Risk: Low - standard industry pattern with well-understood tradeoffs Effort: 1-2 days for migration, including backup and verification
Option 2: Git Submodules#
Description: Maintain lilith and yemaya as separate git repositories, referenced from the oshun parent repository via git submodules. Each project retains its independent git history and can be versioned/released independently.
Pros:
- ✅ Preserved history: Full git history retained for both lilith and yemaya
- ✅ Independent versioning: Each project can have its own release cycle and semantic versioning
- ✅ Smaller initial clones: Shallow clones of parent repo possible without submodule contents
- ✅ Separate access control: Theoretically possible to have different permissions per repo (rarely needed)
Cons:
- ❌ Complex workflows: Developers must understand submodule commands
(
git submodule update --init --recursive) - ❌ Cross-repo changes are painful: Changes spanning lilith and yemaya
require:
- Commit in lilith submodule
- Commit in yemaya submodule
- Update submodule references in parent
- Coordinate PRs across 3 repositories
- ❌ CI/CD complexity: Pipeline must handle submodule checkout, caching is more complex
- ❌ Nx compatibility issues:
nx affecteddoesn't work optimally across submodule boundaries - ❌ Detached HEAD confusion: Submodules often end up in detached HEAD state, confusing developers
- ❌ Merge conflicts in .gitmodules: Additional conflict surface area
- ❌ Branch synchronization nightmare: Keeping branches aligned across repos is error-prone
- ❌ Onboarding friction: New developers frequently forget
--recursiveflag on clone - ❌ Stale submodule references: Easy to have mismatched submodule versions across branches
- ❌ Tooling gaps: Many Git GUIs have poor submodule support
Cost: Medium - ongoing workflow complexity overhead Risk: High - known developer experience issues, submodule-specific bugs are common Effort: 1 day initial setup, but ongoing maintenance overhead
Option 3: Git Subtree#
Description: Use git subtree to embed lilith and yemaya repositories while preserving their history in the main repository.
Pros:
- ✅ History preserved inline: Full commit history visible in main repo
- ✅ No special checkout commands: Standard git clone works
- ✅ Can push changes upstream: Changes can be split out to original repos if needed
Cons:
- ❌ Complex history: Merge commits from subtree operations pollute history
- ❌ Split/push operations are arcane:
git subtree splitandgit subtree pushare rarely understood - ❌ Large initial history import: 88 + 3 commits imported adds complexity without clear benefit
- ❌ Limited tooling support: Less mature than submodules, fewer resources available
- ❌ Nx incompatibility: Same issues as submodules for Nx task graph
Cost: Medium - complex setup and maintenance Risk: Medium - less common pattern, team unfamiliarity Effort: 2-3 days for setup with history preservation
Decision Outcome#
Chosen option: Option 1 - Absorb Nested Repositories
Justification:
The decision to absorb nested repositories is driven by the following key factors:
-
Monorepo Philosophy Alignment: The entire purpose of migrating to an Nx monorepo is to gain the benefits of unified code management. Submodules undermine this by maintaining artificial boundaries that complicate the very cross-domain changes we want to enable.
-
Nx Workspace Optimization: Nx's most powerful features (
nx affected, computation caching, task graph orchestration) work best with a single git repository. Submodules create boundaries that breakaffecteddetection and complicate caching. -
Developer Experience: The unanimous industry experience is that git submodules create significant developer friction. The commands are non-intuitive, the mental model is complex, and errors are common. A single repository dramatically simplifies daily workflows.
-
Cross-Domain Integration: The migration plan includes creating shared libraries (
@oshun/types,@oshun/errors,@oshun/config, etc.) that will be used across lilith, yemaya, and the new domains. Atomic changes across these boundaries are essential and trivial with a single repo. -
History Value Assessment: The existing history (88 commits in lilith, 3 in yemaya) represents early-stage development. While valuable for reference, it does not justify the ongoing complexity cost of submodules. Archiving the history as backup provides adequate preservation.
-
CI/CD Simplicity: A single repository means a single CI/CD pipeline with straightforward caching. Submodules would require complex checkout steps, cross-repo cache invalidation logic, and multi-repo PR coordination.
Trade-offs Accepted:
- Git history starts fresh at the oshun root (mitigated by archived backups)
- Repository size will grow larger over time (mitigated by git LFS for binary assets)
Implementation Plan:
-
Phase 1: Backup and Archive (Day 1)
- Create full backups of lilith/.git and yemaya/.git
- Tag current state as
pre-nx-migrationin both repos - Push backup branches to GitHub archive
-
Phase 2: Repository Consolidation (Day 1)
- Remove lilith/.git directory
- Remove yemaya/.git directory
- Remove godot-cpp-src build artifact .git
- Initialize new git repository at oshun root
- Create unified .gitignore
- Initial commit with consolidated codebase
-
Phase 3: Verification (Day 2)
- Verify all files are tracked
- Confirm no data loss
- Test basic git operations
- Document rollback procedure
Success Metrics:
- All source files from lilith and yemaya present and tracked in new repo
git statusshows clean working directory after initial commit- Developers can clone with single
git clonecommand - Nx commands (
nx affected,nx build,nx test) work correctly - CI/CD pipeline runs successfully on new repository structure
Review Schedule: 30 days post-migration to assess any unforeseen issues
Implementation Details#
Technical Specifications#
Pre-Migration Backup Commands:
# Archive lilith history
cd /home/ubuntu/oshun/lilith
git tag pre-nx-migration
git bundle create ~/lilith-archive-$(date +%Y%m%d).bundle --all
cp -r .git ~/lilith-git-backup-$(date +%Y%m%d)
# Archive yemaya history
cd /home/ubuntu/oshun/yemaya
git tag pre-nx-migration
git bundle create ~/yemaya-archive-$(date +%Y%m%d).bundle --all
cp -r .git ~/yemaya-git-backup-$(date +%Y%m%d)
Repository Consolidation Commands:
cd /home/ubuntu/oshun
# Remove nested git directories
rm -rf lilith/.git
rm -rf yemaya/.git
rm -rf yemaya/packages/godot/gdextension/native/build/_deps/godot-cpp-src/.git
# Initialize unified repository
git init
git add .
git commit -m "Initial commit: Oshun monorepo consolidation
Consolidates lilith and yemaya codebases into unified Nx workspace.
Previous history archived separately.
See: docs/adr/ADR-0001-git-repository-consolidation-strategy.md"
Unified .gitignore Structure:
# Dependencies
node_modules/
.pnpm-store/
# Build outputs
dist/
build/
.nx/
# IDE
.idea/
.vscode/
*.swp
# Environment
.env
.env.local
.env.*.local
# Logs
*.log
logs/
# OS
.DS_Store
Thumbs.db
# Testing
coverage/
.nyc_output/
# Package managers
*.tgz
package-lock.json
yarn.lock
Migration Strategy#
From: Two independent git repositories nested within oshun directory To: Single unified git repository at oshun root Steps:
- Communicate plan to all developers, establish migration window
- Ensure all work-in-progress is committed/pushed in original repos
- Execute backup procedures
- Remove .git directories
- Initialize new repository
- Create initial commit
- Set up new remote (github.com:GreyChimp/oshun.git or equivalent)
- Push to new remote
- Update CI/CD pipelines
- Notify team of successful migration
Rollback Plan: If critical issues discovered within 48 hours:
- Restore .git directories from backup:
cp -r ~/lilith-git-backup-* lilith/.git - Restore .git directories from backup:
cp -r ~/yemaya-git-backup-* yemaya/.git - Remove oshun-level .git:
rm -rf .git - Investigate issues and revise approach
Testing Strategy#
Verification Tests:
- File count comparison:
find . -type f | wc -lbefore and after - Directory structure integrity check
- Git status confirms all files tracked
- Nx workspace validation:
nx show projects - Build verification:
nx run-many -t build - Test verification:
nx run-many -t test
Consequences#
Positive Consequences#
- ✅ Unified Development Experience: All developers work in a single repository with consistent tooling
- ✅ Atomic Cross-Domain Changes: Refactoring that spans lilith, yemaya, and shared libraries becomes trivial
- ✅ Nx Full Functionality:
nx affected, caching, and task orchestration work optimally - ✅ Simplified Onboarding: New team members clone once and have everything
- ✅ Single CI/CD Pipeline: One pipeline configuration, straightforward caching strategy
- ✅ Reduced Cognitive Load: No need to understand submodule commands or cross-repo workflows
Negative Consequences#
- ❌ Fresh Git History: Existing commit history archived rather than preserved inline
- ❌ Migration Coordination: Requires team synchronization during migration window
- ❌ Repository Size Growth: Long-term, repo will be larger than individual repos would be
Risks and Mitigation#
| Risk | Probability | Impact | Mitigation Strategy |
|---|---|---|---|
| Data loss during migration | Low | High | Full backups before migration, verification checklist |
| Team confusion during transition | Medium | Low | Clear communication, documented procedures, office hours for questions |
| CI/CD pipeline breaks | Medium | Medium | Test pipeline on branch before merging, maintain rollback capability |
| Large file bloat over time | Medium | Medium | Implement git LFS for binary assets (images, models, etc.) |
Compliance and Security#
Security Implications#
- Access Control: Single repository simplifies access management (one set of permissions)
- Audit Trail: Unified git history provides complete audit trail going forward
- Secret Management: Consolidate .env handling, ensure no secrets committed
- Code Scanning: Single repository means single security scanning configuration
Compliance Requirements#
- History Retention: Original git histories archived and retained for compliance reference
- Change Tracking: All changes tracked in unified history with proper commit messages
- Access Logs: GitHub/GitLab provides unified access logging
Monitoring and Observability#
Metrics to Track#
- Repository Size: Track
.gitdirectory size monthly - Clone Time: Monitor time for fresh clone operations
- CI/CD Duration: Track pipeline execution times
- Developer Satisfaction: Survey team on workflow improvements
Alerting Strategy#
- Repository Size Alert: If
.gitexceeds 500MB, investigate and clean up - Clone Time Alert: If fresh clone exceeds 5 minutes, optimize with LFS or shallow clones
Related Decisions#
Upstream Dependencies#
- Monorepo Strategy: This ADR implements the monorepo consolidation decision
- Nx Adoption: Drives requirement for single-repo Nx compatibility
Downstream Impacts#
- ADR-0002: Package Manager Choice (pnpm workspace requires single repo)
- CI/CD Configuration: Pipeline design assumes single repository
- Branch Strategy: Single branching model for entire codebase
- Release Management: Coordinated releases via Nx release or changesets
References#
External Resources#
- Google Monorepo: Why Google Stores Billions of Lines of Code in a Single Repository
- Nx Monorepo Documentation
- Git Submodules Considered Harmful
- Atlassian Monorepo Guide
- Microsoft's Journey to a Single Engineering System
Internal Resources#
- RESPONSIBILITY_SPLIT_RECOMMENDATION.md
- TODOS.md
- Lilith ADRs —
lilith/docs/adr/(pre-consolidation source repo)
Revision History#
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2026-01-10 | Development Team | Initial version |