Lab Init: a safe place for project data
The Lab is where MasterMind keeps raw, project-specific material: codebase notes, captured
patterns, signature profiles, anything with real names. It is local and gitignored; only the
genericized, name-free output ever graduates to a shareable field pack. This exists because raw
material sitting in a publishable tree is how confidential data leaks. Make it structural, not a habit.
Golden rule: patterns leave the quarantine, identities never do. Company/product/person/package names
stay in lab/. Only the general rule, stripped of every name, goes into a field pack.
What it sets up
lab/
├── .denylist ← your sensitive terms (gitignored); feeds the guards
├── raw/ ← untouched captures from a codebase
├── analysis/ ← working notes, `signature` profiles
└── MANIFEST.md ← what's here, what's distilled, what's pending
.githooks/
├── pre-commit ← blocks staged lab/ paths, denylisted terms, and real secrets
└── pre-push ← scans every commit being pushed (catches --no-verify + old history)
Steps (idempotent: safe to re-run)
Run from the target repo root. The skill's files live in assets/ next to this SKILL.md.
Create the quarantine (preserving any existing content):
mkdir -p lab/raw lab/analysis
- If
lab/.denylist is missing, copy assets/denylist.template → lab/.denylist, then help the
user fill it: company, product/app names, internal package scopes (@acme/*), colleague names,
private domains/hosts. Never commit this file.
- If
lab/MANIFEST.md is missing, copy assets/MANIFEST.template.md → lab/MANIFEST.md.
Gitignore the quarantine: if lab/ isn't already ignored, append assets/gitignore-snippet.txt to the
repo's .gitignore. Verify with git check-ignore lab/.
Install the guards:
mkdir -p .githooks && cp assets/pre-commit assets/pre-push .githooks/ && chmod +x .githooks/pre-commit .githooks/pre-push
git config core.hooksPath .githooks
- If the repo already has a
core.hooksPath or a hook manager (Husky, etc.), leave theirs in
place. Tell the user, and offer to chain the guard into their existing pre-commit instead.
Prove it works (do this: a guard you haven't tested is a guard you don't have):
Stage a throwaway file containing a denylisted term and attempt a commit; confirm it's blocked,
then unstage. Try staging a lab/ file; confirm the quarantine blocks it.
Now prove pre-push too: it's the layer that catches --no-verify and history committed
before the guard existed, so the pre-commit test does not cover it. Use a local throwaway remote
(no network, nothing is published: --dry-run still runs the hook):
printf 'ACME_TERM internal notes\n' > leak-test.md # swap in a real term from lab/.denylist
git add leak-test.md && git commit --no-verify -m "temp: pre-push test"
git init --bare /tmp/mm-throwaway.git
git push --dry-run /tmp/mm-throwaway.git HEAD:refs/heads/mm-test # must FAIL
Expect ✖ BLOCKED: commit <sha> temp: pre-push test contains confidential terms:, then
Push aborted … and a non-zero exit. If the push succeeds, the guard is not live: check
git config core.hooksPath, that .githooks/pre-push is executable, and that the term is in
lab/.denylist (the hook scans every file type, but skips lab/ itself. That's the quarantine).
Clean up: --soft, never --hard: a hard reset here would discard any uncommitted work in
the user's repo. git reset --soft HEAD~1 && git restore --staged leak-test.md && rm -f leak-test.md && rm -rf /tmp/mm-throwaway.git
Report what was created/changed, and remind: raw data → lab/; only genericized output ships.
Guardrails
- The guards are generic and safe to publish; the denylist is not: terms live only in the gitignored
lab/.denylist. Never bake a real name into a hook, .gitignore, or the manifest (use *-glob patterns).
- Escape hatch:
ALLOW_SENSITIVE=1 git commit … bypasses the guard for a deliberate, reviewed case.
- Not a substitute for review: the guard catches known terms and obvious secrets, not everything.
Read a diff before pushing to any public remote (
core/agent-loop.md).
- Distilling
lab/ into a pack is a separate step (the levelup capture flow), this skill
only stands up the safe container.
1---2name: quarantine3description: Lab Init: a safe place for project data4---56# Lab Init: a safe place for project data78The Lab is where MasterMind keeps **raw, project-specific material**: codebase notes, captured9patterns, `signature` profiles, anything with real names. It is **local and gitignored**; only the10**genericized, name-free output** ever graduates to a shareable field pack. This exists because raw11material sitting in a publishable tree is how confidential data leaks. Make it structural, not a habit.1213> **Golden rule: patterns leave the quarantine, identities never do.** Company/product/person/package names14> stay in `lab/`. Only the general rule, stripped of every name, goes into a field pack.1516## What it sets up1718```19lab/20├── .denylist ← your sensitive terms (gitignored); feeds the guards21├── raw/ ← untouched captures from a codebase22├── analysis/ ← working notes, `signature` profiles23└── MANIFEST.md ← what's here, what's distilled, what's pending24.githooks/25├── pre-commit ← blocks staged lab/ paths, denylisted terms, and real secrets26└── pre-push ← scans every commit being pushed (catches --no-verify + old history)27```2829## Steps (idempotent: safe to re-run)3031Run from the target repo root. The skill's files live in `assets/` next to this SKILL.md.32331. **Create the quarantine** (preserving any existing content):34 - `mkdir -p lab/raw lab/analysis`35 - If `lab/.denylist` is missing, copy `assets/denylist.template` → `lab/.denylist`, then help the36 user fill it: company, product/app names, internal package scopes (`@acme/*`), colleague names,37 private domains/hosts. **Never commit this file.**38 - If `lab/MANIFEST.md` is missing, copy `assets/MANIFEST.template.md` → `lab/MANIFEST.md`.39402. **Gitignore the quarantine**: if `lab/` isn't already ignored, append `assets/gitignore-snippet.txt` to the41 repo's `.gitignore`. Verify with `git check-ignore lab/`.42433. **Install the guards:**44 - `mkdir -p .githooks && cp assets/pre-commit assets/pre-push .githooks/ && chmod +x .githooks/pre-commit .githooks/pre-push`45 - `git config core.hooksPath .githooks`46 - If the repo already has a `core.hooksPath` or a hook manager (Husky, etc.), **leave theirs in47 place**. Tell the user, and offer to chain the guard into their existing pre-commit instead.48494. **Prove it works** (do this: a guard you haven't tested is a guard you don't have):50 - Stage a throwaway file containing a denylisted term and attempt a commit; confirm it's **blocked**,51 then unstage. Try staging a `lab/` file; confirm the quarantine **blocks** it.52 - **Now prove `pre-push` too**: it's the layer that catches `--no-verify` and history committed53 before the guard existed, so the pre-commit test does not cover it. Use a local throwaway remote54 (no network, nothing is published: `--dry-run` still runs the hook):5556 ```bash57 printf 'ACME_TERM internal notes\n' > leak-test.md # swap in a real term from lab/.denylist58 git add leak-test.md && git commit --no-verify -m "temp: pre-push test"59 git init --bare /tmp/mm-throwaway.git60 git push --dry-run /tmp/mm-throwaway.git HEAD:refs/heads/mm-test # must FAIL61 ```6263 Expect `✖ BLOCKED: commit <sha> temp: pre-push test contains confidential terms:`, then64 `Push aborted …` and a non-zero exit. If the push succeeds, the guard is not live: check65 `git config core.hooksPath`, that `.githooks/pre-push` is executable, and that the term is in66 `lab/.denylist` (the hook scans every file type, but skips `lab/` itself. That's the quarantine).67 - Clean up: **`--soft`, never `--hard`**: a hard reset here would discard any uncommitted work in68 the user's repo. `git reset --soft HEAD~1 && git restore --staged leak-test.md && rm -f69 leak-test.md && rm -rf /tmp/mm-throwaway.git`70715. **Report** what was created/changed, and remind: raw data → `lab/`; only genericized output ships.7273## Guardrails7475- **The guards are generic and safe to publish; the denylist is not**: terms live only in the gitignored76 `lab/.denylist`. Never bake a real name into a hook, `.gitignore`, or the manifest (use `*-glob` patterns).77- **Escape hatch:** `ALLOW_SENSITIVE=1 git commit …` bypasses the guard for a deliberate, reviewed case.78- **Not a substitute for review**: the guard catches known terms and obvious secrets, not everything.79 Read a diff before pushing to any public remote (`core/agent-loop.md`).80- Distilling `lab/` into a pack is a separate step (the `levelup` capture flow), this skill81 only stands up the safe container.