06dba9a4ad
- 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
372 lines
12 KiB
Markdown
372 lines
12 KiB
Markdown
# 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](https://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:**
|
|
1. Rename the Gitea repo at `http://192.168.188.119:30008/pplate/pi_mcps` → `workshop`
|
|
2. Update the local remote: `git remote set-url origin http://192.168.188.119:30008/pplate/workshop.git`
|
|
3. 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 under `java/`)
|
|
- `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-mock` and `pytest-cov`
|
|
- Each server is an **independent Python package** with its own `pyproject.toml` and `.venv`
|
|
- No shared `requirements.txt` at 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.xml` needed — 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:**
|
|
```gitignore
|
|
# 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:**
|
|
```json
|
|
"webscraper": {
|
|
"args": ["run", "--directory", "/home/pplate/pi_mcps/webscraper", "src/server.py"]
|
|
}
|
|
```
|
|
|
|
**After:**
|
|
```json
|
|
"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:
|
|
1. Check `git branch --show-current` before first edit
|
|
2. If on `main` → create a branch before touching any file
|
|
3. Include the branch name in `memory_announce_focus()`
|
|
4. Use the [`gitea-push skill`](.roo/skills/gitea-push/SKILL.md) which 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
|
|
|
|
```mermaid
|
|
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.*
|