---
name: brownfield
description: "Scan and manage brownfield repository/worktree defaults for interviews"
---

# /ouroboros:brownfield

Scan a root directory for existing git repositories and linked worktrees, then manage default repos used as context in interviews.

## Usage

```
ooo brownfield                # Scan repos and set defaults
ooo brownfield scan           # Scan only (no default selection)
ooo brownfield defaults       # Show current defaults
ooo brownfield set 6,18,19   # Set defaults by repo numbers
ooo brownfield detect [path]  # Author mechanical.toml via one AI call
```

**Trigger keywords:** "brownfield", "scan repos", "default repos", "brownfield scan", "mechanical detect"

---

## How It Works

### Default flow (`ooo brownfield` with no args)

**Step 1: Scan**

Show scanning indicator:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Scanning for Existing Projects...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Looking for git repositories and worktrees up to two directories below the scan root.
Local repos and repos with any remote name are eligible.
This may take a moment...
```

**Implementation — use MCP tools only, do NOT use CLI or Python scripts:**

**CRITICAL — deferred-schema guard (prevents "Invalid tool parameters"):**
This skill can call `ouroboros_brownfield` across multiple turns (`scan`,
`set_defaults`, `defaults`, and `set`). A deferred schema loaded for one turn is
NOT guaranteed to remain loaded for the next. Immediately before EVERY
`ouroboros_brownfield` call, re-run `tool discovery query: "+ouroboros brownfield"`
(idempotent — a no-op when already loaded). If the load returns no matching tool (and the tool is not already callable — an empty load for an already-exposed tool is an expected no-op, not absence),
stop with the MCP-not-available message instead of retrying the failing call.

1. Load the brownfield MCP tool: `tool discovery query: "+ouroboros brownfield"`
2. Call scan+register:
   ```
   Tool: ouroboros_brownfield
   Arguments: { "action": "scan" }
   ```
   This walks `scan_root` (up to two directory levels deep) for valid seed repos/worktrees and registers them in DB. Each repo or worktree found directly by the walk is registered self-only — Git worktree families are not expanded, so worktrees outside the depth-bounded walk (e.g. under `.ouroboros/worktrees`) are not pulled in. Existing defaults are preserved.

The scan response `text` already contains a pre-formatted numbered list with `[default]` markers. **Do NOT make any additional MCP calls to list or query repos.**

**Display the repos in a plain-text 2-column grid** (NOT a markdown table). Use a code block so columns align. Example:

```
Scan complete. 8 repositories registered.

 1. repo-alpha                   5. repo-epsilon
 2. repo-bravo *                 6. repo-foxtrot
 3. repo-charlie                 7. repo-golf *
 4. repo-delta                   8. repo-hotel
```

Include `*` markers for defaults exactly as they appear in the scan response.

**If no repos found**, show:
```
No git repositories or worktrees found.
```
Then stop.

### Scan boundaries

- The filesystem walk starts at `scan_root`; when omitted, `scan_root` defaults to the current user's home directory.
- Repositories are discovered by walking directories inside `scan_root`, at most two levels deep (so `~/repo` and `~/group/repo` are found; deeper nesting is not).
- Dot-prefixed directories and known noisy directories such as `node_modules` are not walked as seed locations.
- Both normal repos (`.git` directory) and linked worktrees (`.git` file) are registered when the walk reaches them. Git worktree families are NOT expanded — a worktree is only registered if the walk finds it directly, not because its main repo's Git metadata reports it.
- Local repos, repos without remotes, and repos whose remotes are not named `origin` are all eligible.

**Step 2: Default Selection**

**Do NOT use `AskUserQuestion` for this selection.** Two rendering constraints
make it unusable here:

- Assistant text emitted between tool calls (scan result → grid → question
  dialog) is not guaranteed to render, so the user may face the dialog
  without ever seeing the repo list.
- Embedding the list in option `preview` fields does not work either — the
  preview box has a fixed height and silently truncates long lists
  ("N lines hidden"), and repo lists routinely exceed it.

Instead, **end the turn with the repo grid as the final message** so its
display is guaranteed, and collect the selection as a plain chat reply.

Immediately below the grid (same message, same code block or right after it),
append the selection prompt:

**If defaults exist:**
```
Current defaults: <current default names> (numbers <current default numbers>)

Reply with repo numbers to change defaults (e.g. "6, 18, 19"),
"keep" to keep the current defaults, or "none" to clear them.
```

**If no defaults exist:**
```
No defaults set.

Reply with repo numbers to set defaults (e.g. "6, 18, 19"),
or "none" to run interviews in greenfield mode.
```

Then **end the turn** — no tool calls after the grid. The RFC #1392
breadcrumb footer is still the last line of the message.

On the next turn, parse the user's reply:

- Numbers (any separator) → those indices
- "keep" (defaults exist) → stop; no MCP call needed, confirm defaults unchanged
- "none" → empty indices (clear all)
- Anything else → ask again in plain text; do not guess

Then re-run `tool discovery query: "+ouroboros brownfield"` and use ONE MCP call to update all defaults at once:

```
Tool: ouroboros_brownfield
Arguments: { "action": "set_defaults", "indices": "<comma-separated IDs>" }
```

Example: if the user picks IDs 6, 18, 19 → `{ "action": "set_defaults", "indices": "6,18,19" }`

This clears all existing defaults and sets the selected repos as default in one call.

If "none" → `{ "action": "set_defaults", "indices": "" }` to clear all defaults.

**Step 3: Confirmation**

```
Brownfield defaults updated!
Defaults: grape, podo-app, podo-backend

These repos will be used as context in interviews.
```

Or if "none" selected:
```
No default repos set. Interviews will run in greenfield mode.
You can set defaults anytime with: ooo brownfield
```

Or if "keep" selected:
```
Defaults unchanged: <current default names>
```

---

### Subcommand: `scan`

Scan only, no default selection prompt. Show the numbered list and stop.

---

### Subcommand: `defaults`

Re-run `tool discovery query: "+ouroboros brownfield"`, then call:
```
Tool: ouroboros_brownfield
Arguments: { "action": "scan" }
```

Display only the repos marked with `*` (defaults). If none, show:
```
No default repos set. Run 'ooo brownfield' to configure.
```

---

### Subcommand: `set <indices>`

Directly set defaults without scanning. Parse the comma-separated indices from the user's input, re-run `tool discovery query: "+ouroboros brownfield"`, and call:

```
Tool: ouroboros_brownfield
Arguments: { "action": "set_defaults", "indices": "<indices>" }
```

Show confirmation with updated defaults.

---

### Subcommand: `detect [path]`

Runs one AI call against the target directory (defaults to the user's cwd)
and writes `.ouroboros/mechanical.toml` with validated lint / build / test /
static / coverage commands. Stage 1 of evaluation reads this file verbatim,
so the toml is the authoritative Stage 1 contract — no hardcoded language
presets exist anymore.

Ouroboros auto-runs this detect the first time `ouroboros_evaluate` is
invoked without a toml present, so most users never need to call it
directly. Run it explicitly when:

- you want to pre-author the toml before the first evaluate,
- you moved to a new build tool and want to refresh (`--force`),
- you want to review/edit the commands before Stage 1 trusts them.

**Implementation:** invoke the CLI via Bash.

```
uvx --from ouroboros-ai ouroboros detect [path]
# or, if already installed:
ouroboros detect [path] [--force]
```

Then print the resulting `.ouroboros/mechanical.toml` contents so the user
can confirm the proposed commands or hand-edit them.

If detect reports "could not propose any verifiable commands", surface the
reason (no manifests found, LLM unavailable, every proposal dropped) and
suggest the user write a minimal toml by hand — any single entry like
`test = "pytest -q"` is enough to opt back in to Stage 1 for that check.

## RFC #1392 State Breadcrumb Footer

Your final response MUST end with exactly one breadcrumb footer line:

```
◆ <current state> → next: <recommended action>
```

Derive `<current state>` from live session state via `ouroboros_session_status` when that MCP projection is available; otherwise derive it from this skill's actual outcome. Never use a linear `Step N of M` footer because Ouroboros is an evolutionary loop. When the next action is genuinely a choice, list 2-3 honest options in the `next:` clause. The breadcrumb line must be the last line of the response.
