- Add branch naming convention: type/scope/short-description - Update gitea-push skill: branch guard in Step 1 (never commit to main) - Update rules-mcp-builder: create branch before any MCP build - Update rules-bigmind: create branch before any BigMind task - Update rules-homelab: create branch before any homelab task - Add Section 11 to REPO_STRATEGY.md: full branching strategy doc (types, scopes, workflow, Lumen responsibilities, examples) - Ticketing decision: Gitea Issues only, no Docker ticketing service
12 KiB
Monorepo Strategy — Patrick's Homelab Workshop
Written: 2026-04-04 | Authors: Patrick + Lumen
1. Why This Document Exists
The repo started as pi_mcps — a home for Python MCP servers. Then two older Java web projects arrived: mss-failsafe and Wellmann-Shop. This is not an accident — it's the beginning of a pattern: a single place to keep all of Patrick's personal engineering work, regardless of language.
This document defines the strategy for the repo so that both of us — human and AI — can navigate it without confusion now and in two years from now.
2. Philosophy: Polyglot Monorepo, Not a Dump
A monorepo is not code colocation. The key principle from monorepo.tools: projects must have well-defined relationships and clear boundaries. What we are building is closer to a workshop — a curated collection of distinct tools and projects under one roof, organized by language/purpose, each independently buildable and deployable.
We are NOT:
- Sharing dependencies across Java and Python (they live in entirely separate ecosystems)
- Using a monorepo build tool like Nx or Turborepo (overkill for a personal homelab)
- Creating a monolith (each project is independently deployable)
We ARE:
- Keeping one git history (single place to look for all changes)
- Using a clear directory taxonomy to signal what kind of thing each project is
- Making it easy for an AI (Lumen) or a new contributor to orient quickly
- Preventing repo sprawl — one Gitea repo instead of a dozen
3. Repo Rename: pi_mcps → workshop
The name pi_mcps no longer describes what the repo contains. It was named for Raspberry Pi MCP servers — neither of which is accurate anymore (Fedora homelab, not Pi; more than just MCP servers).
Proposed new name: workshop
Why workshop?
- Neutral, language-agnostic
- Conveys personal creative output (not corporate, not framework-specific)
- Short, memorable
- Maps well to
http://192.168.188.119:30008/pplate/workshop
Action required:
- Rename the Gitea repo at
http://192.168.188.119:30008/pplate/pi_mcps→workshop - Update the local remote:
git remote set-url origin http://192.168.188.119:30008/pplate/workshop.git - The local folder on disk can stay as
~/pi_mcps/or be renamed to~/workshop/— Patrick's choice. The folder name and repo name do not need to match.
4. Directory Taxonomy
Every directory at the repo root belongs to one of three categories:
| Category | Directory | Purpose |
|---|---|---|
| Language group | mcp/ |
Python MCP servers — FastMCP, uv, pytest |
| Language group | java/ |
Java web projects — Maven, Jakarta EE |
| Tooling/Config | .roo/ |
IDE config, Roo mode rules, MCP wiring |
| Tooling/Config | plans/ |
Architecture plans, assessments, strategy docs |
| Root files | README.md, .gitignore |
Navigation index + polyglot ignores |
Future language groups (when they arrive):
| Directory | Purpose |
|---|---|
ts/ |
TypeScript MCP servers or web frontends |
go/ |
Go utilities or services |
scripts/ |
Shell/Python one-off automation |
4.1 Full Target Structure
workshop/
├── mcp/ # Python MCP servers
│ ├── bigmind/ # BigMind persistent memory server
│ │ ├── src/server.py
│ │ ├── bigmind/ # library code
│ │ ├── tests/
│ │ ├── pyproject.toml
│ │ └── run.sh
│ └── webscraper/ # Web scraping MCP server
│ ├── src/server.py
│ ├── tests/
│ ├── pyproject.toml
│ └── run.sh
│
├── java/ # Java web projects
│ ├── mss-failsafe/ # MSS Failsafe (Java EE multi-module, WildFly)
│ │ ├── mssfailsafeWeblayer/
│ │ ├── userManagement/
│ │ └── pom.xml
│ └── wellmann-shop/ # Wellmann Shop (JSF/PrimeFaces, Java 8, MySQL)
│ ├── src/
│ └── pom.xml
│
├── plans/ # Architecture plans and strategy docs
│ └── REPO_STRATEGY.md # this file
│
├── .roo/ # Roo Code IDE configuration
│ ├── mcp.json # MCP server wiring (paths updated post-move)
│ └── rules-*/ # Per-mode Roo rules
│
├── .gitignore # Polyglot: Python + Java + Node + OS
└── README.md # Navigation index (the front door)
5. Naming Conventions
Consistency matters — both for humans and for AI tools reading directory listings.
| Rule | Convention | Rationale |
|---|---|---|
| Directory names | kebab-case |
Unix-friendly, consistent across all languages |
| Java project dirs | kebab-case matching Maven artifactId |
No surprise mapping needed |
| Python package dirs | kebab-case at group level, snake_case inside for Python modules |
PEP 8 inside, Unix outside |
| Plan files | UPPER_SNAKE.md in plans/ |
Stands out from code files |
| README per project | Required | Each project is independently comprehensible |
Normalization needed:
Wellmann-Shop/→java/wellmann-shop/(lowercase the W, move underjava/)mss-failsafe/→java/mss-failsafe/(already correct name, just needs moving)bigmind/→mcp/bigmind/webscraper/→mcp/webscraper/
6. Language-Specific Rules
6.1 Python (mcp/)
- Package manager: uv (already standardized)
- Framework: FastMCP for all MCP servers
- Testing: pytest with
pytest-mockandpytest-cov - Each server is an independent Python package with its own
pyproject.tomland.venv - No shared
requirements.txtat root — dependency isolation is a feature - Run pattern:
cd mcp/bigmind && ./run.sh
6.2 Java (java/)
- Build tool: Maven (both existing projects use it)
- Java version: Currently Java 8 (Wellmann-Shop) and unspecified (mss-failsafe — legacy NetBeans project)
- Future Java projects should target Java 21+ (current LTS)
- Each project has its own
pom.xml— no shared parent POM at root (cross-language root POMs are an antipattern) - Target servers: WildFly / Payara / GlassFish (Jakarta EE)
- No shared Maven
settings.xmlneeded — use standard~/.m2/settings.xml
6.3 Future: TypeScript (ts/)
- Package manager: npm or pnpm
- Framework: FastMCP (TypeScript flavor) for MCP servers
- Each project has its own
package.json
7. .gitignore Strategy
The root .gitignore must cover all languages in the repo. Currently it only covers Python. After the reorganization, it must also cover:
To add:
# Java / Maven
target/
*.class
*.war
*.jar
*.ear
*.nar
.classpath
.project
.settings/
nb-configuration.xml
nbactions.xml
*.iml
# Node / TypeScript (future)
node_modules/
dist/
*.js.map
package-lock.json
# Test coverage
.coverage
coverage.xml
htmlcov/
Note: nb-configuration.xml is NetBeans IDE config — already present in mss-failsafe/ and Wellmann-Shop/. It should be in .gitignore for new projects but is intentionally tracked here since it carries build configuration for legacy projects.
8. IDE Wiring: .roo/mcp.json After Move
The webscraper path in .roo/mcp.json currently points to /home/pplate/pi_mcps/webscraper. After moving to mcp/webscraper/, it must be updated:
Before:
"webscraper": {
"args": ["run", "--directory", "/home/pplate/pi_mcps/webscraper", "src/server.py"]
}
After:
"webscraper": {
"args": ["run", "--directory", "/home/pplate/pi_mcps/mcp/webscraper", "src/server.py"]
}
(If the local folder is also renamed to workshop/, the path changes to /home/pplate/workshop/mcp/webscraper)
The same applies to any external MCP configs (e.g., IntelliJ/PyCharm mcp.json files stored outside this repo).
9. README.md — The Front Door
The root README.md should function as a navigation index, not a tutorial. Readers (Patrick, Lumen, future contributors) should land there and know exactly where to go within 10 seconds.
Structure:
# Workshop — Patrick Plate's Homelab Monorepo
## What's Here
[table: project name | language | description | status]
## MCP Servers (mcp/)
[short list with links]
## Java Projects (java/)
[short list with links]
## Plans & Architecture
[link to plans/]
## Gitea
[link to homelab Gitea]
10. Migration Plan (Ordered Steps)
Step 1: Rename Gitea repo pi_mcps → workshop (Gitea UI)
Step 2: Update local git remote URL
Step 3: Move mcp/bigmind ← bigmind/
Step 4: Move mcp/webscraper ← webscraper/
Step 5: Move java/mss-failsafe ← mss-failsafe/
Step 6: Move java/wellmann-shop ← Wellmann-Shop/ (normalize name)
Step 7: Update .roo/mcp.json webscraper path
Step 8: Update any external MCP configs pointing to old paths
Step 9: Expand .gitignore with Java + Node patterns
Step 10: Rewrite root README.md as navigation index
Step 11: git add -A && git commit -m "chore: reorganize into polyglot monorepo structure"
Step 12: git push origin master
Important: Git tracks renames as move+add. Using git mv preserves file history. Use it for each moved file/directory.
11. Branching Strategy
11.1 The One Rule
Never commit directly to main. Every session that touches code or plans starts by creating a branch. Branches are cheap. Broken main history is not.
11.2 Branch Naming Convention
Format: type/scope/short-description
| Type | When |
|---|---|
feat |
New feature, new MCP server, new tool |
fix |
Bug fix |
docs |
Documentation, plans, strategy files only |
chore |
Refactoring, config, CI, build tooling |
spike |
Experimental / throwaway exploration |
Scope = the affected project area:
| Scope | Covers |
|---|---|
bigmind |
mcp/bigmind — the memory MCP server |
webscraper |
mcp/webscraper |
cannamanage |
future CannaManage Java project |
workshop |
repo-level changes (README, .gitignore, structure) |
roo |
.roo/ — IDE config, modes, skills, rules |
plans |
plans/ — architecture docs only |
homelab |
TrueNAS, Docker Compose, infrastructure |
Examples:
feat/bigmind/people-contacts
fix/bigmind/health-check-bugs
docs/plans/cannamanage-strategy
chore/workshop/monorepo-reorganize
feat/webscraper/ssl-cert-fallback
chore/roo/branching-strategy
11.3 Workflow
Session starts
└─ git checkout -b feat/scope/name ← ALWAYS first step
Work happens, commits stack up on the branch
Session ends / feature complete
└─ git push origin feat/scope/name
└─ (optional) open Gitea PR for review
└─ git checkout main && git merge --no-ff feat/scope/name
└─ git push origin main
11.4 Lumen's Responsibility
In every homelab session, Lumen must:
- Check
git branch --show-currentbefore first edit - If on
main→ create a branch before touching any file - Include the branch name in
memory_announce_focus() - Use the
gitea-push skillwhich enforces the branch guard
The mode rules for mcp-builder, bigmind, and homelab all include this step explicitly.
12. What We Are NOT Doing
It's worth being explicit about choices we considered and rejected:
| Considered | Decision | Reason |
|---|---|---|
| Separate repo per project | Rejected | Polyrepo tax: fragmented history, harder for AI context |
| Nx / Turborepo monorepo tools | Rejected | Overkill for personal homelab; adds tooling complexity without benefit |
| Shared Maven parent POM at root | Rejected | Java-specific tooling at repo root would confuse Python tooling |
Keeping pi_mcps name |
Reconsidered | The name no longer describes the content; workshop is future-proof |
src/ at root with language subdirs |
Rejected | Less clear at a glance than top-level mcp/, java/ groupings |
13. Visual Overview
graph TD
Root[workshop/] --> MCP[mcp/]
Root --> Java[java/]
Root --> Plans[plans/]
Root --> Roo[.roo/]
Root --> GI[.gitignore]
Root --> RM[README.md]
MCP --> BM[bigmind/]
MCP --> WS[webscraper/]
MCP --> FutMCP[future MCP servers...]
Java --> MSS[mss-failsafe/]
Java --> WSh[wellmann-shop/]
Java --> FutJava[future Java projects...]
Plans --> STRAT[REPO_STRATEGY.md]
Plans --> FutPlans[future plans...]
This document is the living reference for how this repo is organized. Update it when structure changes.