34 added, 798 removed. Audit A to A.
---
name: repo-setup
description: "First-time setup for an EXISTING repo, single or fleet-wide (--batch)."
version: 1.0.0
---
# Repo Setup
## When to Use
- Starting work in a new project repository for the first time
- `/update-docs` reports `tracker_missing` — the project lacks coordination infrastructure
- PM asks to set up project tracking in an existing repo
- **Marketplace first-run** — new coordinator plugin user setting up their first project
- **Creating a NEW repo from scratch** (not onboarding an existing folder)? → use `coordinator:new-project`, which creates + scaffolds a stack + delegates the onboarding half back to this skill.
**`claude-klabauter` is a hard prerequisite** — resolved via `CLAUDE_KLABAUTER_ROOT` / the machine-local
`repos.claude_klabauter` registry entry — for coordinator-claude itself, so it must already
resolve before this skill's own fences will run (private repo until its OSS release; the
maintainer grants access on request, same model as `project-rag`).
- **Setup is sufficient — downstream skills add-to, never create-from-scratch.** This skill produces minimum-viable versions of all coordinator artifacts the operator will rely on (`state/orientation_cache.md`, `docs/project-tracker.md`, `docs/README.md`, `CLAUDE.md`). Downstream skills (`/update-docs`, `/workstream-start`) add to these artifacts as content accumulates, and they self-gate when invoked against fresh substrate. → [`docs/wiki/produce-not-prescribe.md`](../../docs/wiki/produce-not-prescribe.md) for the underlying principle. (`/workday-start` is the morning cadence skill — it runs unconditionally as part of session orientation, so the produce-not-prescribe / self-gate axis does not apply to it.)
+ **Setup is sufficient — downstream skills add-to, never create-from-scratch.** This skill produces minimum-viable versions of all coordinator artifacts the operator will rely on (`state/orientation_cache.md`, `docs/README.md`, `CLAUDE.md`). Downstream skills (`/update-docs`, `/workstream-start`) add to these artifacts as content accumulates, and self-gate against fresh substrate — underlying principle: wiki (`produce-not-prescribe`). (`/workday-start` runs unconditionally as session orientation; the produce-not-prescribe axis doesn't apply to it.)
## Flag contract
- **Default (no flag) — single-repo interactive.** Runs from inside one repo's cwd. PM-present; asks the 3 cold questions when needed; full Phase 1 → Phase 4 flow as documented below.
- - **`--root <path>` (alias `--target <path>`) — single-repo only, optional.** Onboards a sibling repo by absolute or relative path without cd-ing the session into it — defaults to `$(pwd)` when omitted. Lets an operator sitting in one repo's session context (plan, conversation, orientation) drive onboarding of another repo on disk without abandoning that context. Orthogonal to `--batch` — `--batch` reads paths from `working-repos.yaml` and loops the fleet; `--root`/`--target` targets exactly one repo named on the command line. See § Phases preamble below for the resolution mechanic.
+ - **`--root <path>` (alias `--target <path>`) — single-repo only, optional.** Onboards a sibling repo by absolute or relative path without cd-ing the session into it — defaults to `$(pwd)` when omitted. Orthogonal to `--batch` — `--batch` reads paths from `working-repos.yaml` and loops the fleet; `--root`/`--target` targets exactly one repo named on the command line. Resolution mechanic: § Phases preamble below.
- **`--batch` — fleet non-interactive.** Reads `~/.claude/working-repos.yaml` and loops the single-repo flow per repo. Phase-2 cold-asks substituted by detected defaults (Phase 1 marker scan + Phase 1.5 substrate) OR skipped via lazy-creation discipline when the target artifact already exists. See § Batch Mode below.
- **`--check-only` and `--non-interactive` are batch-mode-only.** If passed to the default single-repo mode (without `--batch`), the skill exits with the one-line remediation: `"--check-only and --non-interactive are only valid with --batch; for non-interactive single-repo setup, set coordinator.local.md first and re-run /repo-setup."` Never silently pick a meaning for an ambiguous flag combination — detect it and fail loud instead.
## Batch Mode (--batch)
- Batch mode runs fleet-wide setup non-interactively. Intended for PM use from `~/.claude` against all repos in the fleet.
-
- **Driver:** delegates to `lib/bootstrap-orchestrate.py` for the per-repo loop (repointed to drive this consolidated skill in non-interactive mode — see C3a commit).
-
- **Per-repo flow:**
-
- 1. Reads `~/.claude/working-repos.yaml`, normalizes paths, filters to repos on disk (repos not on disk are counted as `not-on-disk` in the summary table and skipped).
- 2. For each on-disk repo: dispatches the single-repo phases (Phase 1, 1.5, 3, 3g, 4) in non-interactive mode.
- 3. **SKIPS Phase 2 cold-asks.** Cold-asks are substituted by detected defaults from Phase 1's marker scan + Phase 1.5 substrate profile. When the target artifact already exists (e.g. `CLAUDE.md` present), lazy-creation discipline applies — no overwrite, no re-ask.
-
- **Idempotency:** a re-run on a fully-bootstrapped fleet (all repos have `docs/coordinator-currency.yaml` matching current schema) exits 0 with per-repo "already current" rows and zero writes. The currency stamp is the load-bearing idempotency primitive — already-current stamps short-circuit Phase 3/3g for that repo.
-
- **Hook-respect:** target-repo commit hooks run normally (no `--no-verify`); a hook failure surfaces the repo as failed and the overall run exits non-zero.
-
- **Summary table** printed at end of run (columns: repo path / status / writes):
-
- | Repo | Status | Notes |
- |------|--------|-------|
- | `/x/some-repo` | succeeded | currency stamp updated |
- | `/x/other-repo` | already current | 0 writes |
- | `/x/missing-repo` | not-on-disk | skipped |
- | `/x/hook-fail-repo` | failed | post-commit hook exited non-zero |
-
- Overall exit code: 0 if all on-disk repos succeeded or were already current; non-zero if any failed.
-
- AC4, AC6, AC10 bind this section. AC9 binds the lib/detect-onboarding-offer.py emitting `/repo-setup` (single-repo form, no flags) — never `/repo-setup --batch` in the per-repo offer (batch mode is PM-from-~/.claude, not per-repo), and never with a `--refresh` flag (the command is idempotent; re-running `/repo-setup` on a stale repo re-stamps currency).
+ Batch mode runs fleet-wide setup non-interactively, driving the single-repo phases per repo read from `~/.claude/working-repos.yaml`. For the full per-repo flow, idempotency contract, hook-respect, and the summary table shape, read `residue/batch-mode.md` before running with `--batch`.
## Prerequisites
- You are in the project's working directory (not `~/.claude`) — OR pass `--root <path>` (alias `--target <path>`) to onboard a sibling repo from a parent repo's session context without cd-ing the session; see § Phases preamble below.
- PM is available for 3 questions (Step 2)
## Phases
- **Target-root resolution (run before Phase 1).** Resolve `$_TARGET_ROOT` — the `--root`/`--target` value extracted from `${ARGUMENTS:-}` (mirroring the `${ARGUMENTS:-}` string-match convention `coordinator:install` uses for its own flags, `commands/install.md`, e.g. `[[ "${ARGUMENTS:-}" == *"--check-only"* ]]`) if given, else cwd — via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/repo-setup-args-and-register" resolve-target-root`. It validates the resolved path is an existing directory inside a git repo, printing the absolute path to stdout on success, or a fail-loud `ERROR: ...` line on stderr and exit 1 on failure — mirror that fail-loud idiom rather than silently falling back to cwd.
+ **Target-root resolution (run before Phase 1).** Resolve `$_TARGET_ROOT` — the `--root`/`--target` value extracted from `${ARGUMENTS:-}` if given, else cwd — via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/repo-setup-args-and-register" resolve-target-root`. It validates the resolved path is an existing directory inside a git repo, printing the absolute path to stdout on success or a fail-loud `ERROR: ...` line on stderr with exit 1 on failure — mirror that idiom, never silently fall back to cwd.
When an explicit `--root`/`--target` was passed, change the shell's working directory to
- `$_TARGET_ROOT` as the first action, before Phase 1 begins.
-
- This is the whole mechanism — every downstream cwd-relative step (the `Write`/`Edit` calls that author `CLAUDE.md`, `docs/project-tracker.md`, etc., the `mkdir -p docs` in Phase 3e, and every helper invoked with `--root "$(pwd)"` or a bare `"$(pwd)"` argument) transparently targets the sibling repo once the shell cwd has moved — no per-site threading of a path variable is needed or permitted. **Only the shell cwd for scaffolding moves; the session's conversational and plan context is retained** — this is the supported "drive a sibling repo's onboarding from the parent repo's context" path. When `--root`/`--target` is absent, `$_TARGET_ROOT` resolves to `$(pwd)` and this preamble is a no-op.
+ `$_TARGET_ROOT` as the first action, before Phase 1 begins. Every downstream cwd-relative step
+ then transparently targets the sibling repo — no per-site path-variable threading. Only the shell
+ cwd for scaffolding moves; the session's conversational and plan context stays put. When
+ `--root`/`--target` is absent, `$_TARGET_ROOT` resolves to `$(pwd)` and this preamble is a no-op.
### Phase 1: DETECT — Survey Existing State
Before scaffolding, check what already exists. **Never overwrite existing files.**
Check for each of these and record status (exists / missing / incomplete):
```
├── CLAUDE.md — project conventions
├── docs/README.md — documentation index (wikis, research, specs, reference)
- ├── docs/project-tracker.md — workstream tracking
- ├── docs/wiki/ — wiki guides (LAZY — created by coordinator:distill on first guide extraction)
+ ├── docs/wiki/ — wiki guides (EAGER, seeded — see audit table below)
├── docs/wiki/DIRECTORY_GUIDE.md — guide index with decision record mapping
- ├── docs/plans/ — implementation plans (LAZY — created when first plan is copied from ~/.claude/plans/)
- ├── docs/research/ — research outputs (LAZY — created by coordinator:research on first run)
+ ├── docs/plans/ — implementation plans (EAGER, seeded — see audit table below)
+ ├── docs/research/ — research outputs (EAGER, seeded — see audit table below)
├── state/lessons/ — engineering patterns, one per-entry YAML file (LAZY — created by coordinator:workstream-complete on first lesson)
├── archive/completed/ — completion archive (LAZY — created by coordinator:workstream-complete on first completion)
- ├── state/handoffs/ — session continuity (LAZY — created by coordinator:handoff on first handoff)
+ ├── state/handoffs/ — session continuity (EAGER, seeded — see audit table below)
├── CONTEXT.md — domain glossary (LAZY — never scaffold; produced when first term is resolved)
├── DIRECTORY.md — source index
└── .gitignore — check for .claude/settings.local.json entry
```
- **If `docs/project-tracker.md` already exists:** tracker presence alone does not prove the scaffold is complete — a repo can carry a hand-authored `CLAUDE.md` + tracker while the load-bearing scaffold (`docs/coordinator-currency.yaml`, `cross-repo/inbox/`) never ran. Detect-then-fail-loud-safe, per § Detect-then-fail-loud: check BOTH `docs/coordinator-currency.yaml` AND `cross-repo/inbox/` for presence.
+ **If `CLAUDE.md` already exists:** its presence alone does not prove the scaffold is complete — a repo can carry a hand-authored `CLAUDE.md` while the load-bearing scaffold (`docs/coordinator-currency.yaml`, `cross-repo/inbox/`) never ran. Check BOTH for presence.
- **Tracker exists AND both markers present:** the scaffold is genuinely complete. This skill becomes a health check — verify the tracker format matches the standard template, flag deviations, and skip to Phase 4 (REPORT).
- **Tracker exists but either marker is absent:** the repo is only partially onboarded. Do NOT skip to Phase 4 — proceed through Phase 2/Phase 3 scaffolding as normal to fill the gap. This is safe: every Phase 3 helper is idempotent / no-clobber, so re-running scaffolding against a partially-onboarded repo only creates what's missing and never overwrites the existing tracker or `CLAUDE.md`.
**Global detection:** Check if `~/.claude/CLAUDE.md` exists. If yes, the generated CLAUDE.md will include an "extends global" reference. If not, the template is fully self-contained — no dependency on global config.
**Repo classification (PM ask):** Check if `.gitignore` excludes session infrastructure directories (`tasks/`, `archive/`, `state/handoffs/`). Capture this as a hint string — do not make a decision from it:
- 2+ of these are gitignored → hint = `_(detected: 2+ of 3 session dirs gitignored — looks like a distribution repo)_`
- Fewer or none gitignored → hint = `_(detected: standard working-tree layout)_`
Always ask the PM:
> **Is this repo:**
> - **(a) a working repo** — for active development, with session artifacts tracked
> - **(b) a published artifact / template** — distributed for downstream consumers; no session infrastructure
> - **(c) both** — a working repo that publishes itself as the artifact
>
> _(detected: {hint})_
**Branch on the PM's answer:**
- **(a)** → proceed to Phase 1.5 / Phase 2 unchanged. No injection.
- **(b)** → STOP. Do not proceed to Phase 2. Report:
> _"You answered (b) — distribution repo. Onboarding infrastructure doesn't belong here. Track work on this repo from your parent project's tracker instead."_
- **(c)** → proceed exactly like (a), AND inject a one-line note in the generated CLAUDE.md (Phase 3a) and the generated tracker (Phase 3b):
> _"This repo is published as its own working artifact — consumers see the full directory shape including `tasks/` and `archive/`."_
Report what exists and what needs to be created before proceeding.
- **Project type short-circuit:** Check if `coordinator.local.md` exists at the repo root.
-
- If it exists, read it and capture `project_type`, `project_subtypes`, and `cross_platform` (all optional). Record `_CROSS_PLATFORM_DECLARED=true` when `cross_platform: true` is present. Emit a one-line confirmation:
-
- > Project type: {type}{ +subtypes: [{subtypes}] if any}. From coordinator.local.md — skipping Phase 2 question 2.
-
- If `coordinator.local.md`'s `project_type` differs from the `detected_type` derived from the marker scan, append this one-line challenge immediately after the confirmation (PM remains authoritative — this is informational only, not a re-ask):
-
- > *`coordinator.local.md` says `{type}` but detected stack is mostly `{detected_type}` — keeping the file value (PM authoritative). If wrong, edit `coordinator.local.md` and re-run.*
-
- If `coordinator.local.md` is missing, proceed to Phase 2 question 2 (cold-ask) as normal.
-
- Also check for legacy values in the file: if `project_type` is `unreal`, `meta`, or bare `web`, emit a one-line warning with the migration hint (e.g. `unreal` → `project_type: game-dev` + `project_subtypes: [unreal]`). Do not auto-rewrite.
-
- **`cross_platform` inference (when absent from `coordinator.local.md` or when `coordinator.local.md` does not exist):** Run the cross-platform inference signal check and store results for the "Optional Tripwire Installs" offer later in this run. Two signals, either is sufficient:
-
- - **(a)** A `.github/workflows/*.yml` file carries an `os:` matrix with multiple entries (more than one OS value present — e.g. `ubuntu-latest` plus `macos-latest` and/or `windows-latest`).
- - **(b)** `*.sh` files exist in `bin/` AND a Windows-operator marker is present in `coordinator.local.md` (e.g. `project_type` or a custom field that implies Windows as a primary development environment).
-
- If either fires, set `_CROSS_PLATFORM_INFERRED=true` and record `_CROSS_PLATFORM_SIGNAL` as a human-readable description of which signal fired (e.g. `"detected: OS matrix with 3 entries in .github/workflows/ci.yml"`). **Do NOT auto-write `cross_platform: true`** — the correct shape is detect-then-ask; the offer prompt fires in "Optional Tripwire Installs." Detect-then-silently-pick is a footgun: an incorrect auto-enable installs a pytest CI snippet into a TypeScript repo.
-
- **Negative check — suppress duplicate install offer:** Before setting `_CROSS_PLATFORM_INFERRED=true`, check whether `templates/ci/cross-platform-matrix.snippet.yml` already exists in the repo (or a consumer copy at an equivalent path). If signal (a) fires AND the snippet file is already present, the repo has already adopted the CI discipline — suppress the install offer and emit a one-line note instead:
-
- > _CI reference already installed (`templates/ci/cross-platform-matrix.snippet.yml` present) — skipping cross-platform install offer._
-
- Set `_CROSS_PLATFORM_INFERRED=false` (or leave unset) in this case. The signal correctly fired; the action it normally triggers is already done. This prevents the offer from self-firing on the meta-repo itself (which dogfoods the matrix as of C6) and on any consumer repo that has already copied the snippet.
-
- **Runtime marker scan:** Run `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/detect-project-runtime"` — the marker scan is advisory, so warn and continue (do not abort onboarding) if the forwarder or its claude-klabauter target is unresolvable: `⚠ detect-project-runtime not found — skipping advisory runtime detection (coordinator plugin install may be incomplete, or claude-klabauter root unresolved). PM's answer to Phase 2 question 2 remains authoritative.`
-
- Capture the output. Show to PM in Phase 2 above question 2 as `_(detected stack: <one-line summary>)_`. PM's answer is authoritative; detection is sanity-check only. Output is advisory stdout — no skill/agent/hook reads it programmatically; adding a consumer requires a separate plan.
-
- **Derived type from markers:** Once the marker scan returns, derive a `detected_type` (and `detected_subtypes` if applicable) using these rules, in priority order:
-
- - `*.uplugin` or `*.uproject` present → `detected_type: game-dev`, `detected_subtypes: [unreal]`
- - `package.json` + any of `next.config.js`, `vite.config.*`, `nuxt.config.*`, `svelte.config.*`, `remix.config.*` present → `detected_type: web-dev`
- - `requirements.txt` or `pyproject.toml` present (and no UE markers) → `detected_type: data-science`
- - `Cargo.toml`, `go.mod`, or none of the above → `detected_type: general`
-
- Capture these as part of the Phase 1 profile. If `coordinator.local.md` already exists and its `project_type` differs from `detected_type`, emit a one-line challenge inline in the Phase 1 report (see **Project type short-circuit** block above for the exact wording).
-
- **coordinator_whoami availability (install-surface-completeness):**
-
- The Phase 4 binding probe (`python3 -m coordinator_whoami.project_rag`) requires the `coordinator_whoami` package. On a fresh machine where this is the first onboarded repo, the package is not yet installed. Probe and install idempotently — owning the binding-probe contract this skill advertises rather than punting to a separate meta-package command — via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/repo-setup-args-and-register" whoami-status` (add `--check-only` when batch mode's `CHECK_ONLY=1` is active). It never exits non-zero (matching the original never-block contract) and prints `whoami_status: <ready|installed|would-install|failed>` to stdout, plus a following `pip_stderr: ...` line when the status is `failed`.
-
- Record `coordinator_whoami: <whoami_status>` in the Phase 4 status table.
-
- - **`ready`:** package was already importable — no mutation.
- - **`installed`:** `pip install -e` succeeded; binding probe will work in Phase 4.
- - **`would-install`:** `--check-only` is set; package missing; no mutation. Reported in status table.
- - **`failed`:** pip itself errored (no Python, no pip, or pip exit non-zero). Do NOT halt the skill — Phase 4's existing `ModuleNotFoundError` fallback (`Run /coordinator:install to install the introspection package.`) remains the last-resort signal. Log pip stderr (captured in `pip_stderr`) to the status table notes.
-
- Idempotent: re-running the skill on an already-bootstrapped repo short-circuits at the `import` probe with no pip invocation.
+ **Project type short-circuit, `cross_platform` inference, the runtime marker scan, the derived-type rules, and `coordinator_whoami` availability** — read `residue/phase1-detection-details.md` before running Phase 1 against a repo you haven't onboarded before. Short version: `coordinator.local.md`'s `project_type` (if present) short-circuits Phase 2 question 2; cross-platform-ness is detected then offered, never auto-written; the runtime marker scan and derived-type rules feed the PM's Phase 2 prompt as advisory detection; and the `coordinator_whoami` package is probed and installed idempotently so the Phase 4 binding probe works.
### Phase 1.5: INVESTIGATE — Read substrate, draft proposals
Skip when Phase 1 found a genuinely empty repo (no README, no CONTRIBUTING, no top-level manifest).
**Substrate-first onboarding.** Read the project's accumulated institutional memory before asking the PM cold: `README.md`, `CLAUDE.md`, `state/lessons/`, `state/improvement-queue/` if present (1.5a); most-recent 5 handoffs for stack/tooling clues if `state/handoffs/` exists (1.5b); sibling `CLAUDE.md` files for stack-shared conventions via the central state repo-registry (resolved via `coordinator-state-root.py --central`'s `<central-state>/repo-registry.md`, claude-klabauter-resident) `stack_tags` (1.5c). Output: a 5–10 line substrate snapshot. Cold-ask is the fallback when substrate is empty.
**Roadmap orientation (run immediately after the substrate snapshot):** Query the completed archive for recent roadmap items — especially valuable when joining cold. Resolve the claude-klabauter root the same way the rest of this skill does (`REPO_CLAUDE_KLABAUTER` / `CLAUDE_KLABAUTER_ROOT` / the machine-local registry pointer; fail loud with remediation if unresolved), then invoke `<claude-klabauter-root>/coordinator/bin/lib/records_query.py completion "nature=roadmap" markdown-list 10 --sort "-loe.tshirt" --since "90d"` via `${COORDINATOR_PYTHON:-python3}`.
Render under `#### Recent roadmap (last 90d, top-10 by size)` in the Phase 4 REPORT — count-always, so `(none)` is expected and rendered explicitly on new repos, never omitted. Otherwise:
1. Read top-level `README.md` / `README.rst` / `README.txt` if present.
2. Read `CONTRIBUTING.md` if present.
3. Read top-level manifests: `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `*.uplugin`, `*.uproject`, etc. — whichever exist.
4. Skim recent commit subjects: `git log --oneline -20`.
Draft proposals from what you read:
- **Project name** — from README H1 or repo directory name.
- **Project type + subtypes** — from manifest signals + README role description, reconciled with Phase 1 runtime-marker output. If proposal differs from `detected_type`, surface both with proposal winning and emit:
> *Detected stack suggests `{detected_type}`. README/manifests suggest `{proposed_type}`. Going with `{proposed_type}` — confirm or override.*
- **Initial workstreams (1-3)** — derived from README "what this does" + recent commit subjects + any "Roadmap" / "TODO" / "Status" sections. If the repo names sibling repos (path on disk, GitHub URL, or "split" / "addon" / "upstream" / "downstream" language), capture each as `peer_repo_candidates`.
Present proposals to the PM for ratification:
> Before I scaffold, here's what I found:
>
> **Project name:** {proposed}
> **Project type:** {proposed}{, subtypes: [...] if any}
> **Workstreams (proposed):**
> 1. {WS1} — {2-3 deliverables}
> 2. {WS2} — {...}
>
> **Sibling repos referenced:** {list with file:line citations from README/CONTRIBUTING}
>
> Ratify, correct, or say "go cold" to skip this and ask from scratch.
On ratification: skip Phase 2's name + workstreams questions; only ask if PM corrected something or said "go cold."
On peer-repo presence: ask once whether to dispatch parallel Explore scouts (recommended). If yes, dispatch each with: *"Read README, CONTRIBUTING, and recent commits. Identify shared schemas, integration contracts, and shipped vs in-flight work relevant to {this repo's name}. Reply with file:line citations."* Wait for results before drafting tracker workstreams.
### Phase 2: ASK — PM Input
**Skip questions Phase 1.5 already ratified. Phase 1.5 may have already pinned project name and/or workstreams; only ask the questions whose answers are still missing.** **If `coordinator.local.md` was found in Phase 1**, skip question 2 — project type already pinned. Ask:
> **1. Project name** — short name (e.g., "example-repo MVP", "example-sim-repo")
> **2. Initial workstreams** (1-3) — name, 2-3 deliverables, optional deps/blockers. Say "stubs" for placeholders.
**If `coordinator.local.md` was NOT found** (cold-ask path), present all three:
> **1. Project name** — short name (e.g., "example-repo MVP", "example-sim-repo")
> _(detected stack: <one-line summary>)_
> **2. Project type:**
> - `game-dev` — Game development (adds the Game Dev Reviewer reviewer, game-dev domain agents)
> - `web-dev` — Web frameworks (adds the Front-End Reviewer for front-end review, the UX Reviewer for UX)
> - `data-science` — Notebooks, pipelines (adds the Data Science Reviewer reviewer)
> - `general` — Standard conventions only
> **3. Initial workstreams** (1-3) — name, 2-3 deliverables, optional deps/blockers. Say "stubs" for placeholders.
Wait for PM response before proceeding.
### Phase 3: GENERATE — Create Missing Files
Create only what's missing. Use the templates in this skill's `templates/` directory as the base.
#### Lazy-creation discipline
Only scaffold files that have **meaningful day-1 content**. A placeholder header trains agents to ignore the directory; empty scaffolding has zero signal value. Create files and directories only when there is a real artifact to write.
- **Audit verdict — Phase 3 scaffold items:**
-
- | Item | Verdict | Reasoning |
- |------|---------|-----------|
- | `CLAUDE.md` | EAGER | Project conventions apply immediately; filled in Phase 2 |
- | `docs/project-tracker.md` | EAGER | Workstreams established in Phase 2; real content on day 1 |
- | `docs/README.md` | EAGER | Structural index with project name, pointers to plans/research/wikis |
- | `docs/exec-summary.md` | EAGER | One-screen per-repo brief (identity + what's special + goals + progress). Two MANAGED sections derive from README + week-changelog on day 1; two HAND sections are placeholders. EAGER-with-HAND-placeholder is produce-not-prescribe compliant — real derivable content exists immediately. Generated by `bin/generate-exec-summary.py` in Phase 3d.5. |
- | `.gitignore` entry | EAGER | Prevents accidental credential commits from first commit onwards |
- | Post-commit hook | EAGER | Auto-push crash insurance is needed from the very first commit |
- | `cross-repo/` dir | EAGER (contract-bearing) | Inbound cross-repo memo channel — sibling EMs address this repo's `cross-repo/` by name; must exist before any memo arrives. Scaffolded with `README.md` (real content, not `.gitkeep`) by the claude-klabauter `coordinator_core.install.scaffold_structure` CLI. Schema: `cross-repo-memo`. Source of truth: `canonical-structure.yaml`. |
- | `state/orientation_cache.md` | EAGER | Project name, type, workstreams, sibling-repo refs all ratified in Phase 2 — meaningful day-1 content exists. Applies the lazy-creation rule at `:235-238`, not a reversal. |
- | `state/lessons/` dir | LAZY | Empty directory; no per-entry YAML files exist until first session runs |
- | `state/handoffs/` dir | LAZY | No handoffs until first session ends via `/handoff` |
- | `state/handoff-tracker.md` | LAZY (render) | Per-repo handoff tracker. **Never scaffold manually** — lazily created on first render by `bin/render-handoff-tracker.py`. Edit-resistance: two layers (agent hook + editor guard, both wired automatically). |
- | `archive/completed/` dir | LAZY | No completed work until first work item ships |
- | `docs/wiki/` dir | LAZY | Wiki guides come from `/distill` after artifacts accumulate |
- | `docs/plans/` dir | LAZY | Plans come from plan mode; none exist on day 1 |
- | `docs/research/` dir | LAZY | Research outputs come from `coordinator:research` pipelines |
- | `state/review-trail/` dir | LAZY | Review records written by `/workstream-complete` and `/handoff` |
-
- LAZY items are NOT created here. Each has a designated "create on first use" owner noted in its section below.
-
- #### 3a. CLAUDE.md (if missing)
-
- Use `templates/CLAUDE.md.template` via the `render-template` forwarder. Construct three substitution values before calling it:
-
- 1. **`GLOBAL_EXTENDS_LINE`** — `Extends global \`~/.claude/CLAUDE.md\`.` if that file exists; else `""`.
- 2. **`PROJECT_TYPE_BLOCK`** — concatenated per-type convention section bodies, one per selected type, blank line between multiple. Each type's body is the literal content of this skill's own `templates/project-type-block.<type>.template` (`game-dev`, `web-dev`, `data-science`). `general` type, and any type without a matching template file: empty string.
- 3. **Render helper call:**
-
- ```bash
- "${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/render-template" \
- templates/CLAUDE.md.template \
- -o CLAUDE.md \
- PROJECT_NAME="<derived-name>" \
- PROJECT_TYPE="<type>" \
- SUBTYPES="<comma-separated-list-or-empty>" \
- GLOBAL_EXTENDS_LINE="<line-or-empty>" \
- PROJECT_TYPE_BLOCK="<concatenated-blocks-or-empty>"
- ```
-
- The forwarder self-resolves its own claude-klabauter target — no separate root resolution is
- needed at this call site. It substitutes every `{{KEY}}` placeholder and exits non-zero if any
- remain (template/key drift guard). Leave `<!-- Fill in -->` comments as-is; they are prompts
- for the PM.
- 4. **Runtime conventions population:** populate the rendered `## Runtime conventions` section
- bullets from the Phase 1 marker-scan output — one bullet per detected stack line. If the scan
- reported no known stack markers, replace the placeholder bullets with
- `- <!-- no runtime markers detected; PM to fill -->`. Do not edit other `<!-- Fill in -->`
- placeholders.
-
- Use absolute `$HOME`-anchored paths. Leave `<!-- Fill in -->` comments as-is.
-
- After `render-template.py` returns successfully, set `_PHASE_3A_RENDERED_CLAUDE_MD=true` so Phase 4 item 1 can fire its conditional. (When CLAUDE.md exists before Phase 3a and is left untouched, the flag stays unset and Phase 4 item 1 is suppressed — the intended behavior for bespoke CLAUDE.md.)
-
- #### 3b. docs/project-tracker.md (if missing)
-
- Use `templates/tracker.md.template`:
-
- 1. Replace `[PROJECT_NAME]`, `[DATE]` (today), `[YEAR]`, `[MONTH]`
- 2. Replace `[WORKSTREAMS]` with formatted workstream blocks from PM input:
-
- For each workstream the PM provided:
- ```markdown
- ### N. [Workstream Name]
- **Status:** Ready
- **Specs:** <!-- link when spec is written -->
-
- - [ ] [Deliverable 1]
- - [ ] [Deliverable 2]
- - [ ] [Deliverable 3]
- ```
-
- If PM said "stubs": create one placeholder workstream:
- ```markdown
- ### 1. [Define workstreams]
- **Status:** Ready
-
- - [ ] _PM: Define initial workstreams and deliverables_
- ```
-
- #### 3c. state/lessons/ — SKIP (lazy)
-
- Do NOT create this directory during onboarding — no meaningful day-1 content. Its first per-entry YAML file is created by `coordinator:workstream-complete` on first lesson capture.
-
- #### 3d. docs/README.md (if missing)
-
- Render `templates/README.md.template` via `render-template.py`, substituting `[PROJECT_NAME]` and `[DATE]`.
-
- #### 3d.5. docs/exec-summary.md (if missing)
-
- Generate the per-repo executive summary brief using the coordinator generator — resolve and run it via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/repo-setup-args-and-register" resolve-exec-summary-generator --run`. It checks the coordinator-plugin-root copy first, falls back to the claude-klabauter sibling copy (via `REPO_CLAUDE_KLABAUTER`/`CLAUDE_KLABAUTER_ROOT`/the `.claude-klabauter-root` pointer), and degrades gracefully with a stderr warning — `generate-exec-summary.py unresolvable ... exec-summary generation skipped` (exit 1) — rather than aborting the skill when neither copy resolves.
-
- The generator populates the two MANAGED sections from current disk artifacts (identity from README
- H1 + lead paragraph; progress from `state/week-changelog/` latest Highlights + `orientation_cache`
- Counters + `git log` since last weekly reset, with a git-log fallback when week-changelog is
- absent). The two HAND sections (`<!-- BEGIN HAND: special -->`, `<!-- BEGIN HAND: goals -->`) ship
- as documented placeholders for PM hand-authoring on first run.
-
- **Idempotency on existing file:** when `docs/exec-summary.md` already exists the generator
- re-emits the MANAGED sections from current disk data and copies both HAND sections forward
- verbatim. If a HAND fence is malformed or absent the generator exits non-zero, names the file
- + the broken fence, and writes nothing — per detect-then-fail-loud doctrine.
-
- **Backfill (--batch):** `repo-setup --batch` runs Phase 3d.5 across the fleet in no-clobber
- mode — the generator's no-clobber create path fires only when `docs/exec-summary.md` is genuinely
- absent. Repos that already have the file are skipped cleanly.
-
- **After generation, prompt the PM to hand-author the two HAND sections:**
-
- 1. **What makes this project special** (`<!-- BEGIN HAND: special -->`) — the differentiator or
- architectural bet. Seed from the machine-local sibling-repo registry entry for this repo
- (`machine-local get repos.<key>`) if one exists.
- 2. **Near-term goals** (`<!-- BEGIN HAND: goals -->`) — the 2–4 highest-priority near-term items.
- The generator may pre-fill a commented seed from `week-changelog/HEADER.md` Priorities when
- non-blank.
-
- Record in Phase 4 REPORT: `### Created` if generated this run, `### Already Existed` if the file
- was already present and left untouched. Any fail-loud generator exit (malformed HAND fence) surfaces
- under `### Needs Attention` with the generator's error text verbatim.
-
- #### 3e. Directories
-
- Only create directories with real day-1 content or referenced by files being written in this phase:
- create `docs` (for `project-tracker.md` in 3b and `README.md` in 3d), and the ephemeral,
- git-ignored `scratch/subagent-sandbox` (deliberately outside `canonical-structure.yaml`, which
- would otherwise scaffold README.md/.gitkeep sentinels only to have them immediately git-ignored —
- its git-tracked twin, `state/subagent-share/`, IS in `canonical-structure.yaml` and is scaffolded
- by the invocation below).
-
- **Scaffold contract-bearing directories and the full `state/` skeleton** by invoking the claude-klabauter `coordinator_core.install.scaffold_structure` CLI. This is idempotent — safe to re-run; never clobbers existing content. Resolve the claude-klabauter root the same way the rest of this skill does (`REPO_CLAUDE_KLABAUTER` / `CLAUDE_KLABAUTER_ROOT` / the machine-local registry pointer), then invoke `python3 -m coordinator_core.install.scaffold_structure --manifest-root <coordinator-plugin-root>` from that root with `CLAUDE_KLABAUTER_ROOT` exported and `PYTHONPATH` including it (`--root` defaults to the current git repo root when omitted, so no explicit `--root` is needed when run from the target repo). Skip with a stderr note — `canonical structure scaffold skipped — claude-klabauter not resolvable` — when the claude-klabauter root doesn't resolve.
-
- Reads `canonical-structure.yaml` (source of truth for the skeleton). For each `creation: eager` entry: contract-bearing dirs get a `README.md` (schema-documenting, e.g. `cross-repo/inbox/`); `gitkeep: true` dirs get a `.gitkeep` sentinel (full `state/` subdir skeleton + `tasks/`). Idempotent — `.gitkeep` skips dirs containing real files.
-
- **Most tracker files are NOT pre-created** (`state/lessons/` entries, `state/handoff-tracker.md`, etc.) — they are written lazily by their owning skills on first use (see table above). Pre-creating empty tracker files trains agents to ignore the directory; empty scaffolding has zero signal value. **Exception — `state/orientation_cache.md`** is now eagerly seeded by Phase 3h below: PM has just ratified project name, type, and workstreams in Phase 2, so meaningful day-1 content exists. See `docs/wiki/produce-not-prescribe.md` for the underlying principle.
-
- #### 3f. .gitignore handling
-
- Ensure `.gitignore` contains the canonical block:
-
- ```
- # Machine-specific Claude settings (do not commit)
- .claude/settings.local.json
-
- # Scratch — transient agent output, investigation notes, workstream byproduct.
- # `scratch/` matches at any depth (top-level scratch/, tasks/scratch/, etc.)
- scratch/
- tasks/_*.log
-
- # Per-session transient markers (produce-not-prescribe sentinel — consumed by /workstream-start)
- state/.repo-setup-*
-
- # Ceremony/coverage per-run transients — receipts, gate results, last-phase caches written
- # by the wsc ceremony op every /workstream-complete run. Tracking them re-dirties the tree and
- # wedges the dirty-tree gate on the op's OWN regenerated output (self-transient loop).
- state/ceremony/*.json
- state/coverage/*.json
- ```
-
- Procedure:
-
- 1. **If `.gitignore` doesn't exist:** Create it with the canonical block above.
- 2. **If `.gitignore` exists but is missing any of the canonical rules:** Append only the missing rules under a single comment header (`# Coordinator universal — scratch + machine-local settings`).
- 3. **If all canonical rules are present:** Skip silently.
- 4. **If the ceremony/coverage transients are already TRACKED** (`git ls-files state/ceremony/*.json state/coverage/*.json` non-empty): after adding the ignore rules, `git rm --cached` them — a tracked-then-ignored transient still wedges the dirty-tree gate until untracked.
-
- **Warning checks:**
-
- - If `.gitignore` ignores all of `.claude/` (`.claude/` or `.claude/*`), warn: only `.claude/settings.local.json` needs ignoring.
- - If tracked content exists under `scratch/` or `tasks/_*.log`, surface count and offer `git rm --cached -r` cleanup (confirm with PM first — don't auto-untrack).
-
- #### 3f.5. Auto-push post-commit hook
-
- Delegate to the canonical idempotent self-heal helper — it handles install (hook absent), repair (hook present but not routed), and exec-bit fix (hook present but `chmod -x`) in one place: `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/coordinator-ensure-post-commit-hook"`.
-
- Idempotent and near-zero cost when already installed (one stat + one grep). A repo that pre-dated the doctrine, had its `.git/hooks/` wiped, or was cloned without `/repo-setup` ever being run is self-healed by re-running `/repo-setup`, not by session boot alone.
-
- Skip if a custom auto-push hook already exists and the PM has signed off on it.
-
- #### 3f.5.6. Session-Id trailer prepare-commit-msg hook
-
- Delegate to the same idempotent self-heal pattern as 3f.5 — installs the `prepare-commit-msg` hook that injects a `Session-Id: <id>` git trailer on every commit (resolution-order: `CLAUDE_SESSION_ID` → `CLAUDE_CODE_SESSION_ID` → `.git/coordinator-sessions/.current-session-id`). The trailer is the substrate `~/.claude/plugins/coordinator/bin/review-brightline-gate.py --session-id` filters on so the brightline gate fires on this session's commits, not the whole shared-branch diff: `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/coordinator-ensure-prepare-commit-msg-hook"`.
-
- Idempotent; silent no-op when no session-id resolves (legitimate non-coordinator commits stay unaffected). Self-healing runs by re-invoking `/repo-setup`, not via a session-boot hook.
-
- #### 3f.7. Concurrent-EM git config hardening
-
- Harden this repo's git config against two concurrent-EM Git-for-Windows failure modes — `gc.autoDetach false` so git's auto-maintenance runs synchronously instead of detaching into a background process that can orphan the index lock, and `core.checkStat minimal` so the index comparison ignores the NTFS-unstable `ctime/ino/dev` fields that cause a phantom-dirty tree under concurrent index rewrites — via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/coordinator-configure-git"`.
-
- Idempotent — safe to re-run; a no-op if already hardened.
-
- #### 3f.5.5. Meta-repo pre-commit exec-bit gate (conditional)
-
- Install via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/install-meta-repo-precommit-hook" "$HOME/.claude"`.
-
- Idempotent. Pass `"$HOME/.claude"` explicitly so the install is cwd-independent — without the arg the installer derives the repo root from cwd, which is the consumer *project* repo during `/repo-setup`, so the gate would silently never land in the meta-repo. The helper still internally gates on `canon(repo-root) == canon($HOME/.claude)` — installs the pre-commit gate only in the meta-repo itself, no-ops in consumer repos. If an existing `pre-commit` hook is present without the gate marker, the installer appends the invocation instead of clobbering it.
-
- **Why this is conditional.** The helper scans `~/.claude/plugins/*` for exec-bit drift on `.sh` files — a meta-repo concern. Consumer-repo commits don't touch that tree; installing the hook in a consumer repo would fire the helper on every commit only to have it immediately exit 0. The `/workday-complete` Step 5 gate remains the meta-repo's end-of-day backstop; this hook is the earlier-cadence catch.
-
- **Override:** `COORDINATOR_OVERRIDE_PRECOMMIT_EXEC_BIT=1 git commit ...` bypasses the gate for emergency commits.
-
- #### 3f.6. VS Code read-only guard for generated trackers
-
- Mark the generated handoff tracker renders read-only in VS Code (and forks that
- honor `files.readonlyInclude`) so a human does not accidentally hand-edit a file
- the renderer overwrites. This is the editor-side complement to the agent-side
- guard (the `preuse-bash-dispatch.py` PreToolUse(Bash) dispatcher's tracker-edit
- guard, which ships with the plugin and needs no per-project setup). Idempotent — merges two globs into
- `.vscode/settings.json` without clobbering existing settings, via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/ensure-vscode-readonly" --root "$(pwd)"`.
-
- The helper skips loudly if `jq` is absent or `.vscode/settings.json` is JSONC
- (comments/trailing commas) — in that case the report should note the key to
- add by hand (`files.readonlyInclude` → `"**/state/handoff-tracker.md": true`).
- (The `"**/state/doe-handoff-tracker.md": true` key this note used to also list is retired — the
- DoE-aggregate `--all-repos` render mode no longer exists.) Offer-shaped, not a hard lock: a user
- can still override per-file via VS Code's "Set Active Editor Writeable".
-
- #### 3g. DIRECTORY.md
-
- Do NOT create this file directly — requires source file analysis handled by `/update-docs` Phase 2. Do NOT add a prescription to the Phase 4 REPORT telling the PM to run `/update-docs` — the precondition probe self-gates and will run when DIRECTORY.md analysis is warranted. → `docs/wiki/produce-not-prescribe.md`.
-
- ### Phase 3i. Currency stamp (ALWAYS — idempotent)
-
- Record which `COORDINATOR_SCHEMA_VERSION` this project was onboarded against. Idempotent —
- safe to re-run; overwrites only when the schema version has been bumped since the last stamp.
-
- Skip for distribution repos (answer (b) from Phase 1). Apply for working repos ((a) and (c)).
-
- Resolve `CLAUDE_PLUGIN_ROOT` as the coordinator plugin root (e.g. `~/.claude/plugins/coordinator-claude/coordinator`) and the claude-klabauter root the same way the rest of this skill does (`REPO_CLAUDE_KLABAUTER` / `CLAUDE_KLABAUTER_ROOT` / the machine-local registry pointer; fail loud with remediation if either is unresolved), then invoke `<claude-klabauter-root>/coordinator/lib/coordinator_currency.py write "$(pwd)" <coordinator-plugin-root>` via `python3`.
-
- If the write succeeds: add `docs/coordinator-currency.yaml` to the **Created** list (or **Already Existed** if idempotent no-op). If it fails with a clear error, add a **Needs Attention** warning — the stamp is non-fatal for onboarding but required for the drift probe.
-
- #### 3h. state/orientation_cache.md (if missing)
-
- Authority for this eager seed: the lazy-creation rule at `:235-238` — *"Only scaffold files that have meaningful day-1 content."* PM input from Phase 2 (project name, type, initial workstreams, sibling-repo refs) is *exactly* the meaningful day-1 content that licenses an eager seed. This is the produce-not-prescribe principle (→ `docs/wiki/produce-not-prescribe.md`) applied to the orientation surface: setup has the maximum-possible context for this project, so setup writes the cache rather than punting to `/update-docs` Phase 13 against an empty repo.
-
- Render to `state/orientation_cache.md` with the project context just gathered:
-
- ```markdown
- # Orientation Cache
-
- ## Active workstreams
- [WORKSTREAM_LIST — name + 2-3 deliverables each, from Phase 2 PM input]
-
- ## Branch
- [CURRENT_BRANCH]
-
- ## Pinboard
- [empty — populated by future workday-start / workstream-start runs]
- ```
-
- Substitute the bracketed tokens from Phase 1.5 / Phase 2 ratified inputs. Leave `## Pinboard` empty (intentional — populated later). Future `/update-docs` Phase 13 reads this cache and updates it rather than overwriting from scratch.
-
- **The heading set is closed, and the cache verifier enforces it** — a section whose heading is not on the allowlist fails verification, so do not invent one here. Seed only the headings that carry meaningful day-1 content; the generator adds the rest (branch health, recent commits, wiki, atlas, fast test, audits, housekeeping, recheck dates) once there is something real to report.
-
- **Why there is no project-summary or status section:** the cache is a CACHE, not a record. It carries computed pointers to what exists and where — its routing question is *"does this have a truth-expiry?"*, and if yes it is cache and never doctrine. A project-purpose line re-quotes what the repo's own `CLAUDE.md` already told every agent at boot, and counts of handoffs, lessons, or backlog entries are the least useful thing a cache can hold: they expire the moment they are written, they tell an agent nothing it can act on, and a stale count reads as current — which is worse than absent. Seed routes, not answers.
-
- ---
-
- ### Phase 3j. Extended substrate seeds (ALWAYS — idempotent)
-
- Wire in the four substrate seeds that complete the coordinator machinery for this repo. Each helper is idempotent and fail-loud on ambiguity — safe to re-run; skips cleanly when the artifact already exists or the condition doesn't apply.
-
- Each of the four helpers migrated to `claude-klabauter` as a module-main with a `coordinator/lib/` trampoline (cross-repo memo `2026-07-23-claude-klabauter-em-bash-remnant-kill-answers.md`, Ask 4) — resolve the claude-klabauter root via the same `_cc_claude_klabauter` seam idiom used elsewhere in this skill (§ 3f.5), then invoke the trampoline as a **subprocess** via `"${COORDINATOR_PYTHON:-python3}" <path>` — every helper is fail-loud and calls `exit` on ambiguity, so `source`-ing would terminate the repo-setup shell (and `setup-rag-decision.py` is `$0`-guarded, so sourcing it bare silently no-ops the decision block); the subprocess form isolates each exit. The target repo root is passed explicitly as `"$(pwd)"` (required by the test-command detector; defaulted to cwd by the others). Run in sequence:
-
- **1. Test-command detection** — detect the stack's test command and write `fast_test_cmd` / `full_test_cmd` into `coordinator.local.md`: `<claude-klabauter-root>/coordinator/lib/setup-detect-test-cmd.py --root "$(pwd)"` via `${COORDINATOR_PYTHON:-python3}` (see the intro paragraph above for the `<claude-klabauter-root>` resolution + fail-loud contract).
-
- Detects `package.json` test scripts, `pyproject.toml`/`pytest.ini`, `Cargo.toml`. Presents candidates for operator confirmation (or accepts `--non-interactive` pre-set). Fails loud when multiple ambiguous candidates are found — never silent-picks. Writes both keys as flat top-level entries in `coordinator.local.md` (the shape `cs_resolve_fast_test_cmd` / `cs_resolve_full_test_cmd` already reads). Skip if both keys are already present. The configured command is invoked only at cadence gates, never on every commit — capped parallelism, commit ≠ trigger.
-
- **2. Health ledger seed** — seed `state/health-ledger.md` from the daily-summary schema: `<claude-klabauter-root>/coordinator/lib/setup-seed-health-ledger.py "$(pwd)"` via `${COORDINATOR_PYTHON:-python3}` (same `<claude-klabauter-root>` resolution as item 1).
-
- Seeds every system row at grade `?` (never fabricates grades). Idempotent — skips if `state/health-ledger.md` already exists. Reference shape: this repo's own `state/health-ledger.md`.
-
- **3. RAG-index decision** — resolve the three-branch RAG-index decision tree and write the outcome into the repo `CLAUDE.md`: `<claude-klabauter-root>/coordinator/lib/setup-rag-decision.py --root "$(pwd)"` via `${COORDINATOR_PYTHON:-python3}` (same `<claude-klabauter-root>` resolution as item 1).
-
- Branch logic (do not write a dead offer for non-UE repos):
- - UE repo + project-rag daemon present → offer to index.
- - Non-UE repo (any daemon state) → tripwire path (upstream `.uproject`-abstention defect blocks non-UE indexing; cite the memo).
- - No daemon → tripwire path.
-
- Tripwire branches write `un-indexed; use Tier-3 (Read/Grep/Glob)` into the repo `CLAUDE.md`.
-
- **4. fnm pin-resolution** — ensure the repo's pinned Node version is installed via machine-level fnm: `<claude-klabauter-root>/coordinator/lib/setup-fnm-pin.py "$(pwd)"` via `${COORDINATOR_PYTHON:-python3}` (same `<claude-klabauter-root>` resolution as item 1).
-
- Acts only when `.node-version` or `.nvmrc` is present; pure no-op when neither exists. When a pin file is found: checks whether the `fnm` binary is installed; if present, runs `fnm install <pinned>` and emits fnm's own shell-init guidance (its `fnm env` output, meant to be eval'd) as PATH guidance for no-version-manager shells; if absent, fails loud: `"fnm not installed — run coordinator:install to install the Node toolchain manager, then re-run repo-setup."` **repo-setup MUST NOT install the fnm binary** — binary install is machine-level only (per `coordinator:install` Phase 3).
-
- Record outcomes in the Phase 4 REPORT under `### Created` or `### Already Existed` as appropriate. Any fail-loud exit from a helper surfaces under `### Needs Attention` with the helper's remediation text verbatim.
-
- **`coordinator:new-project` inherits all four seeds via its Phase-4 delegation to `coordinator:repo-setup` — no re-implementation in `new-project` is needed or permitted.**
-
- ### Phase 3k. Packageability-compliant starter agent-install-manifest.json (ALWAYS — idempotent)
-
- Seed `docs/install/agent-install-manifest.json` (shape below) so every repo inherits the
- packageability contract at birth, rather than by per-repo goodwill later. **Skip entirely if `docs/install/agent-install-manifest.json` already
- exists** — this phase never overwrites a hand-authored or previously-seeded manifest; a repo that
- outgrows the starter shape edits the file directly.
-
- Substitute `[REPO_NAME]` with the same project name ratified in Phase 2, and `[SETUP_SKILL]` with
- `/coordinator:setup` only when this repo IS coordinator-claude itself — every other repo uses its
- own onboarding skill invocation (default `/coordinator:repo-setup` unless the project defines its
- own). Create the `docs/install` directory.
-
- ```json
- {
- "agent_install_contract_version": 3,
- "repo_id": "[REPO_NAME]",
- "setup_skill": "/coordinator:repo-setup",
- "standalone_setup_script": {
- "posix": "scripts/setup.sh",
- "windows": "scripts/setup.ps1",
- "entry_point_contract": {
- "non_interactive_flag": "--i-am-agent",
- "check_only_flag": "--check",
- "deterministic_exit": true
- }
- },
- "direct_deps": [],
- "required_env_vars": [],
- "override_flags": {
- "skip_dep_check": "--skip-dep-check",
- "accept_hallucination_risk": "--accept-missing-deps-risk"
- },
- "tested_platforms": [],
- "configurable_locations": [
- {
- "name": "install_root",
- "discovery": {
- "candidates": [
- "[REPO_NAME_UPPER]_INSTALL_ROOT env var, if set",
- "default: cwd-relative resolution ($(pwd) at setup time)"
- ]
- },
- "default": "$(pwd)",
- "override": {
- "env": "[REPO_NAME_UPPER]_INSTALL_ROOT"
- }
- }
- ],
- "packageability_compliance": {
- "declared": true
- }
- }
- ```
-
- <!-- Negative-spec: the `override` block must use the unified `{flag?, env?}` vocabulary — NOT
- the retired `{mechanism, name}` shape, which the schema's `additionalProperties:false`
- rejects and which fails `validate-install-contract.py` point-6's
- `.override | (.flag // .env)` check. The seed must also include
- `standalone_setup_script.entry_point_contract`, required by point-2 — omitting it leaves a
- manifest that is schema-valid but validator-failing despite
- `packageability_compliance.declared: true`. -->
-
- This is the MINIMAL compliant shape, not a complete one — it declares points 1 (via
- `functional_probe`/`remediation` once `direct_deps` gains entries), 4 (`tested_platforms: []` — an
- honest "no platform verified yet" claim for a fresh repo, NOT an unbacked `["macos"]`; the field is
- derived from `state/platform-outcomes/` records once they exist, and empty is schema-valid), 5
- (`packageability_compliance.declared: true`, checked by `validate-install-contract.py` only when a
- repo opts in), and 6 (`configurable_locations`, one worked example) at the smallest shape that
- passes `validate-install-contract.py`. `direct_deps: []` and `required_env_vars: []` are legitimately
- empty for a fresh repo with no upstream deps yet — the packageability checks that key on
- non-empty `direct_deps` entries (point 1's per-dep remediation, point 2's `entry_point_contract`)
- simply have nothing to check yet. `standalone_setup_script.posix`/`.windows` point at
- conventional-but-not-yet-created paths (`scripts/setup.sh`/`.ps1`) — this repo's own onboarding
- work creates those scripts; the manifest declares the contract shape ahead of the scripts existing,
- consistent with "inherits the contract at birth" rather than "inherits it once someone remembers."
- The optional top-level `programmatic_entry_point` field is deliberately omitted from this greenfield
- seed because a fresh repo's `scripts/setup.sh` unifies chain-walk and install into one script, so
- Point-2 falls back to `standalone_setup_script.entry_point_contract` until (if ever) this repo grows
- a separate non-interactive install entry point distinct from its setup script (see
- `docs/install/AGENT.md` § Packageability contract for the PREFERRED/FALLBACK precedence rule).
-
- **Point 5 stay-in-shape applies from the first dependency this repo adds onward** — see the
- code-reviewer's install-surface coverage lens (`agents/code-reviewer.md § Install-surface coverage
- lens`), which fires on any diff adding a dep/prereq/env-var without a paired manifest update in the
- same commit.
-
- Record `docs/install/agent-install-manifest.json` under `### Created` in the Phase 4 REPORT (or
- `### Already Existed` if the skip-if-present branch fired).
-
- ### Phase 3l. Strategic self-description skeleton (ALWAYS — idempotent)
-
- Born-compliant emit-hold, same shape as Phase 3k: a repo is born WITH a conformant,
- provenance-marked skeleton `state/strategic/self-description.yaml` (schema:
- `coordinator/schemas/strategic-self-description.schema.json`) plus a curation prompt — NOT a hard
- onboarding gate that blocks until full vision/OKRs are authored. **Skip entirely if
- `state/strategic/self-description.yaml` already exists** — never overwrites a curated instance.
-
- Scaffold via `coordinator:strategic-self-description-refresh`'s skeleton-authoring path (or the
- authoring surface named in its SKILL.md) with every field's provenance marked `asserted` or absent
- (present-as-null) until a human ratifies. After scaffolding, prompt once:
-
- > Strategic self-description skeleton written to `state/strategic/self-description.yaml` — curate
- > vision/lifecycle/CTA now, or leave for the weekly refresh nudge (`/workweek-complete` Step 4i)?
-
- **Fold the same offer into this curation prompt** — do not run a second, separate ask. This reads
- like <inferred domain> work — want me to record which inspirations / peers / competitors /
- aspirational-targets you have in mind? It goes in the same `state/strategic/self-description.yaml`
- skeleton just scaffolded and makes later deliverable planning easier. (Skip freely — it's an offer,
- not a gate.) On opt-in, write each named entity into the `competitors[]` array of the
- already-scaffolded skeleton (schema: `coordinator/schemas/strategic-self-description.schema.json`)
- — `name`, `relationship` (`competitor | peer | aspirational-target | complement | prior-art |
- superseded-by | supersedes`), `note`, `provenance: curated`. This is the same self-description
- artifact and the same authoring surface referenced above; there is no second marking store.
-
- Record under `### Created` (or `### Already Existed`) in the Phase 4 REPORT. **Presence/staleness is
- advisory, not a gate** — an absent or stale instance never blocks onboarding completion; it surfaces
- the same way other advisory seeds do (Phase 4 status table note), consistent with the
- generated-draft → human-ratify → curated reconciliation model owned by the refresh skill.
-
- ### Phase 3m. Guard-regression tripwire tests (ALWAYS — idempotent)
-
- Unlike the Windows console-subprocess and cross-platform-CI tripwires under **Optional Tripwire
- Installs** below (opt-in, PM-offered), this seed is **ALWAYS installed, not offered** — the whole
- point is that a repo gets this protection automatically at birth, the same way it gets
- `fast_test_cmd` or the health ledger in Phase 3j, rather than depending on an operator accepting
- an offer. Skip a file individually (idempotent no-op) if it already exists at the destination —
- never overwrite a customized copy (an operator may have edited an `EXACT_FILES` allowlist in
- place).
-
- **Destination is derived from `fast_test_cmd`, never hardcoded to `tests/guards/` at the repo
- root.** Provisioning the files is not the whole job — a guard test that pytest never collects is
- indistinguishable from no guard at all (this is exactly the defect DoE-claude's own copy of this
- step shipped with: `tests/guards/` at the repo root while its `fast_test_cmd` was scoped to
- `python -m pytest coordinator/tests`, so the guards sat on disk, `ls`-visible, run by nothing —
- see `coordinator/tests/test_guard_templates_reachable_by_test_runner.py` for the regression gate
- that now catches a repeat of exactly that). Parse the path argument off this repo's own
- `fast_test_cmd` line in `coordinator.local.md` (the `<path>` in `python -m pytest <path>` /
- `pytest <path>`) and create `<that-path>/guards/` — e.g. `tests/guards/` when `fast_test_cmd` is
- scoped to `pytest tests`, `coordinator/tests/guards/` when it is scoped to `pytest
- coordinator/tests`. If `fast_test_cmd` has no parseable path argument (a bare `pytest` with no
- scope, or a non-pytest test runner), fall back to `tests/guards/` at the repo root — pytest's
- default collection root — and note the fallback in the Phase 4 REPORT so the PM can verify
- reachability by hand.
-
- Create the resolved `<scope>/guards/` directory if absent, then copy each of these four files
- from `<coordinator-plugin-root>/tests/templates/` (resolve `<coordinator-plugin-root>` the same way
- the rest of this skill does) into `<scope>/guards/` in the target repo, no-clobber:
-
- - `test_machine_local_state_tracked.py` — flags tracked files that bake in a machine-absolute
- home path (content-scanned, JSON/YAML/dotfile-state only) or match a known kill-switch /
- last-known-good-snapshot filename shape.
- - `test_foreign_platform_paths.py` — flags tracked config carrying a path whose syntax belongs
- to a platform other than the one running the test (Windows drive-letter path on a POSIX host,
- or vice versa), a path mixing `\` and `/` separators within one token, or a UNC path on a
- non-Windows host. (Note: matches a single-segment drive-letter path — drive letter, colon,
- backslash, then one directory name, with nothing after it — as well as multi-segment ones;
- an earlier revision of this template's regex missed the
- single-segment shape, which is the exact form a real 2026-07-28 incident hit; fixed the same
- day it was found.)
- - `test_registry_toml_machine_paths.py` — conditional on the target repo carrying a tracked file
- named `registry.toml` anywhere (the coordinator machine-local registry convention); a no-op
- (zero findings) elsewhere. When such a file exists, flags any string value shaped like an
- absolute path — a tracked `registry.toml` must declare keys only; the actual per-machine path
- values belong in the gitignored `registry.local.toml` sibling.
- - `test_guard_wiring_completeness.py` — conditional on the target repo shipping its own
- `hooks/hooks.json`-shaped surface; a no-op (zero findings) elsewhere. When such a surface
- exists, flags `guard-*` scripts never referenced from hooks.json (directly or via a wrapper
- `.sh` file it invokes), and the silent-skip shape — an existence test guarding a script
- invocation with no `else` branch, so an absent script passes unnoticed — in any `.sh` file
- hooks.json references.
-
- Each template is self-contained (stdlib + `git`, `test_registry_toml_machine_paths.py` also uses
- stdlib `tomllib`, Python 3.11+) and runs standalone (`python3 <scope>/guards/<file>.py`) or under
- pytest — no new dependency is introduced. Each template's own docstring documents its detection
- heuristic and limits in full; do not duplicate that here.
-
- **Fix the repo-root parent-walk depth to match `<scope>`.** Each template's `REPO_ROOT` fallback
- (used when `TRIPWIRE_REPO_ROOT` is unset) is computed as a fixed number of `.parent` hops off its
- own `__file__` — written assuming `tests/guards/<file>.py` directly under the repo root (2 hops:
- `guards` → `tests` → root). If `<scope>` is deeper than `tests/` (e.g. `coordinator/tests`, giving
- `coordinator/tests/guards/<file>.py`), that fixed hop count under-counts and every template will
- silently resolve the WRONG root. Adjust `Path(__file__).resolve().parents[N]` (every template,
- including `test_no_bare_console_subprocess.py`, uses this same idiom) to the correct hop count
- for `<scope>` before running the copies for the first time — verify with
- `python3 <scope>/guards/<file>.py`
- against a repo with no findings expected, or by checking `REPO_ROOT` prints the actual repo root.
-
- **Scope note — "unclassified absolute paths" was considered and deliberately narrowed.** An
- earlier draft of this brief asked for a blanket check flagging any absolute path in tracked
- config lacking positive proof of portability. That blanket form was not built: a generic
- consumer repo can legitimately carry absolute paths with nothing to do with machine identity
- (container paths, systemd unit paths, deployment mount points), and flagging all of them would
- be exactly the ignored-noise failure mode this effort exists to prevent. The safely-narrow slice
- of that risk is covered by the two checks above that target unambiguous shapes (home-directory
- paths, and `registry.toml` path values) — see `test_registry_toml_machine_paths.py`'s own
- docstring for the full reasoning.
-
- **Why ALWAYS, not offered.** The failure class these tests catch is invisible until it causes an
- outage (four bricked sessions on one day) — an opt-in offer is exactly the shape that let the
- five guards this incident is named after ship untested-in-practice for weeks. Every check is
- designed to prefer silence over a false positive (documented per-check in each template's
- docstring), so an ALWAYS install carries negligible noise risk against a repo with none of these
- problems.
-
- Record `<scope>/guards/` under `### Created` in the Phase 4 REPORT (or `### Already Existed` if
- every target file was already present).
-
- **Verify reachability, don't just assume it.** After copying, confirm the guards are actually
- collected by the repo's own `fast_test_cmd` (e.g. run it and check the new `test_*` node ids
- appear) rather than trusting the path arithmetic above blindly — this step exists precisely
- because that trust broke once already. A companion regression gate,
- `coordinator/tests/test_guard_templates_reachable_by_test_runner.py` in the coordinator plugin
- source, catches a repeat of the "present on disk, run by nothing" shape in DoE-claude's own
- suite; a target repo onboarded via this skill does not automatically inherit that gate and should
- either add an equivalent check or rely on the reachability confirmation above.
-
- #### 3x. Fleet memo-destination registration
-
- Single-repo `/repo-setup` scaffolds the in-repo `cross-repo/inbox/` CHANNEL (Phase 3e, via the claude-klabauter `coordinator_core.install.scaffold_structure` CLI), but that channel has no ADDRESS until this repo is also registered as a `repos.<name>` entry in the machine-local registry — per `bin/cross-repo-memo`, a repo becomes an addressable `--to <name>-em` receiver only through that registry entry. Without this step a freshly-onboarded repo is a receiving channel no sibling EM can find. This mirrors `coordinator:install`'s F16 fix (`register-discovered-repos.py`, commit `43182780`) — same registry, same only-if-absent discipline, applied at single-repo onboarding time instead of fleet-discovery time.
-
- **Offer, don't nag.** Default YES for working repos (Phase-1 classification (a) working or (c) both — the tracked-session-artifact case where sibling EMs plausibly need to reach this repo). Default skip (offer still shown, default answer no) for (b) published-artifact repos — a distribution repo is not something a sibling EM addresses directly.
-
- > Register this repo as a fleet memo destination so sibling EMs can `--to <name>-em` it? [Y/n]
-
- On accept, register this repo — only-if-absent, never clobbering an existing `repos.<key>` value — via `"${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/repo-setup-args-and-register" register-repo`. It derives `<key>` the same way `cross-repo-memo`'s `_receiver_repo_key` (`${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/_machine_local.py`) resolves `--to <name>-em`: lowercase basename, non-alnum runs collapsed to a single `_`, leading/trailing `_` stripped — and prints `repos.<key> already registered — leaving as-is.` or `repos.<key> registered -> <path>`.
-
- Then append a row to `~/.claude/working-repos.yaml` under the `repos:` list, only-if-absent (skip if a row with this `path` already exists), matching the existing row shape:
-
- ```yaml
- - path: <absolute path, same OS-native form as sibling rows>
- posix_path: <posix-normalized path>
- purpose: <one-line from README H1/lead paragraph, or the Phase 2 project description if README is absent>
- source: repo-setup
- ```
+ A seed clears that bar — and is EAGER rather than LAZY — only when it satisfies **all four**
+ conditions: it (a) names what writes into the directory, (b) names what event fills it, (c) names
+ which skill owns it, and (d) carries NO frontmatter — schema-inert by construction, so it cannot
+ trip the directory's own schema'd consumer (plan scanner, review-trail parser, handoff hook) on
+ day one.
- On decline: skip both writes and note the decline for Phase 4 (see below).
+ **Phase 3 scaffold classification.** EAGER items (`CLAUDE.md`,
+ `docs/README.md`, `docs/exec-summary.md`, `.gitignore` entry, post-commit hook, `cross-repo/`,
+ `state/orientation_cache.md`, `state/handoffs/`, `docs/wiki/`, `docs/plans/`, `docs/research/`,
+ `state/review-trail/`) are scaffolded now from `canonical-structure.yaml`'s `readme:` block.
+ LAZY items are NOT created here — each is created on first use by its owner: `state/lessons/`
+ (first session), `archive/completed/` (first ship). Full per-item audit and
+ reasoning: wiki.
- **Phase 4 REPORT surfacing.** After Phase 3 completes, check whether this repo is now a memo destination (`machine-local has "repos.$_repo_key"`):
+ **Phases 3a–3g — CLAUDE.md, docs/README.md, docs/exec-summary.md, and DIRECTORY.md.** Read `residue/phase3-core-docs.md` before scaffolding any of these; it carries the render-template invocations, the workstream-block formatting, and the exec-summary generator contract.
- - **Registered this run:** add a `### Created` line — `Registered as fleet memo destination: repos.{key} → {path}`.
- - **Still NOT a memo destination** (registration declined, skipped, or `machine-local` unavailable): surface LOUDLY under `### Needs Attention`:
+ **Phases 3e–3f.6 — directories, .gitignore, and the git-hook installs.** Read `residue/phase3-infra-hooks.md` before running the `canonical-structure.yaml` scaffold or touching `.gitignore`, the post-commit hook, the session-id trailer hook, git config hardening, the meta-repo pre-commit gate, or the VS Code read-only guard.
- > This repo is not yet a fleet memo destination — sibling EMs cannot `--to <name>-em` it. Run: `machine-local set repos.<name> <path>` and add a working-repos.yaml row. `<name>` = lowercased basename with every non-alnum run collapsed to a single underscore (matching cross-repo-memo's `-em` resolution).
+ **Phases 3h–3m and 3x — the currency stamp, orientation cache, extended substrate seeds, install manifest, strategic self-description skeleton, guard-regression tripwire tests, and fleet memo-destination registration.** Read `residue/phase3-substrate-seeds.md` before running any of these — they are ALWAYS-run, idempotent seeds, not optional offers, so skipping the reference is not the same as skipping the step. This is also where the extended substrate seeds land: `fast_test_cmd`/`full_test_cmd`, `state/health-ledger.md`, the RAG-index decision, and the fnm Node-version pin.
---
### Phase 4: REPORT
- **Declared exemption from the ≤200-word EM→PM budget (global `CLAUDE.md § Communication Style`).** This
- phase's walkthrough prose below (the `~/.claude` surface explanation, `claude-doe` launch
- instructions, "Fill in CLAUDE.md", the cross-platform CI note, and § Verify the coordinator
- binding) invokes that budget's own escape hatch — *"the content is a document."* It was reviewed
- and deliberately exempted during the 2026-07-31 report-by-exception sweep: recurrence is the
- discriminator, and this is a first-run onboarding walkthrough read once per repo by an operator
- who has no other source for it, not a recurring status report printed at every ceremony close
- (contrast `coordinator/skills/workstream-complete/SKILL.md § Final Summary`, which the same sweep
- converted to report-by-exception because *that* block prints on every close). **Do not shorten
- the walkthrough prose to satisfy the word budget** — a future editor sweeping this repo for the
- fixed-block anti-pattern should leave Phase 4's walkthrough alone; cutting it would strand a
- first-time user with no other source for this content. The word-budget Stop-hook advisory that
- measures EM→PM output length may still fire here — expected, not a defect to fix by shortening,
- since that hook is non-blocking and advisory by construction.
-
- If Phase 1.5 dispatched peer-repo scouts, ensure the tracker's workstream blocks include `file:line` citations from the scout reports.
-
- **`coordinator_whoami` status row.** Emit a one-line status row based on `whoami_status` from Phase 1 (vocabulary: `coordinator_whoami: ready | installed | would-install | failed`). Route by value: `ready` → `### Already Existed`; `installed` → `### Created`; `would-install` or `failed` → `### Needs Attention` (include `pip_stderr` for `failed`).
-
- **Report-by-exception on `### Already Existed`.** `### Created` and `### Needs Attention` always
- print — the first is the receipt for what this run actually did, the second is the actionable
- list. `### Already Existed (untouched)` is a list of things that did nothing; print it only when
- non-empty, following the `| Line | Include only when |` shape from
- `coordinator/skills/workstream-complete/SKILL.md § Final Summary`:
-
- | Line | Include only when |
- |---|---|
- | `### Already Existed (untouched)` | at least one file/dir was already present and left untouched this run |
-
- `### Recent Roadmap (last 90d, top-10 by size)` stays **count-always** — do not fold it into the
- table above. Its zero-row `(none)` render is documented load-bearing behavior
- (§ Phase 1.5 above, "count-always, so `(none)` is expected and rendered explicitly on new repos,
- never omitted") — an explicit "found nothing yet" signal for a fresh repo, not the same shape as
- an omitted list of no-ops.
-
- Present what was done:
-
- ```
- ## Onboarding Complete — [Project Name]
-
- ### Created
- - [list each file/directory created]
-
- ### Already Existed (untouched)
- - [list each file that was skipped — omit this whole heading if nothing was already present]
-
- ### Needs Attention
- - [any warnings — .gitignore issues, incomplete CLAUDE.md sections to fill in]
-
- ### Recent Roadmap (last 90d, top-10 by size)
- _(Results from Phase 1.5 roadmap orientation query — one bullet per row. Render "(none)" when the query returns zero rows. Heading always present — count-always per orientation-surfacing-doctrine.)_
-
- ### What's next
-
- Setup left this repo with `state/orientation_cache.md`, `docs/project-tracker.md`, `docs/README.md`, and `CLAUDE.md` — minimum-viable versions of all coordinator artifacts. The standard coordinator skills (`/update-docs`, `/workstream-start`, `/workday-start`, `/workstream-complete`) will keep these in sync as the project accumulates work — invoke them when there's something to maintain. Both `/update-docs` and `/workstream-start` self-gate on fresh substrate and will emit a one-liner rather than running an empty pipeline (→ `docs/wiki/produce-not-prescribe.md` for the underlying principle).
-
- Two things worth flagging before you dive in:
-
- 0. **Your `~/.claude` is the surface you evolve** — it is a git-tracked repo holding your config, lessons, and working-data. Customize it (CLAUDE.md, lessons, wiki), commit, and push. The coordinator **plugin source** lives in the DoE clone (`repos.doe_claude`), resolved live via `--plugin-dir`. Launch with `claude-doe` (not bare `claude`) as the persistent launch surface — the wrapper regenerates the settings.json hook block and execs `claude --plugin-dir <doe_clone>/coordinator` on every invocation, so skills, agents, and hooks always resolve from the DoE clone. Direct-editing the DoE clone's coordinator source IS the intended editable-install workflow; those edits take effect at next Claude Code boot for both skills/agents and hooks — restart `claude-doe` to pick them up. If a mid-session plugin-reload command (`/reload-plugins`) is available in your Claude Code build it may pick up skills/agents edits immediately without a full restart, otherwise a restart is required. SessionStart hooks are boot-only regardless — they do not fire on mid-session settings.json edits.
-
- 1. **Fill in CLAUDE.md** *(only if Phase 3a rendered the template this session — skip if CLAUDE.md was authored bespoke)* — the `<!-- Fill in -->` sections need project-specific details. Skip silently if `_PHASE_3A_RENDERED_CLAUDE_MD=true` was not set.
-
- 2. **Cross-platform CI reference available** — if this repo targets multiple OSes, a 3-OS matrix snippet and honest-measurement marker conventions are available at `templates/ci/cross-platform-matrix.snippet.yml`; the principle lives at `docs/wiki/cross-platform-ci-discipline.md`. Declare `cross_platform: true` in `coordinator.local.md` and re-run `/repo-setup` to trigger the language-aware install offer.
-
- To verify the install: `python3 -m coordinator_whoami.project_rag`.
-
- To start your first workstream now, just describe what you want to do — the EM has full context from the setup conversation.
-
- ### Verify the coordinator binding
-
- Run the envelope-branch check below to verify the coordinator sees this project correctly: `python3 -m coordinator_whoami.project_rag` (POSIX/macOS) or `py -3 -m coordinator_whoami.project_rag` (Windows Git Bash/PowerShell). Output is compact JSON by default — no `--json` flag needed; pipe through `python -m json.tool` for pretty-print.
-
- Parse `binding.kind` and `binding.target` from the JSON envelope (`cross-plugin-whoami-contract.md §Operator wiring`):
-
- - **`binding.kind == "bound"` AND `binding.target` matches cwd:** emit `Coordinator binding healthy: project-rag is bound to <binding.target>.`
- - **`binding.kind == "bound"` AND `binding.target` does NOT match cwd:** emit a mismatch block:
- ```
- Binding mismatch:
- envelope binding.target : <binding.target>
- expected (cwd) : <cwd>
- Run /project-rag:setup to re-register this project root.
- ```
- - **`binding.kind == "unbound"`:** emit:
- `project-rag is not bound to this project. Run /project-rag:setup to register this project root.`
- - **Import fails (`ModuleNotFoundError`) OR the command exits non-zero:** emit:
- `coordinator_whoami is not installed. Run /coordinator:install to install the introspection package.`
-
- **If `machine-local get repos.*` fails** — the machine-local registry is not yet bootstrapped for this project. Work the three failure shapes in order:
-
- - **No registry directory.** The substrate was never bootstrapped — run `/coordinator:install` Phase 3.
- - **Registry present but no `repos.*` keys.** Expected on a fresh install; nobody has seeded the machine-specific sibling paths yet. Declare one per sibling repo with `machine-local set repos.<name> <path>`. Machine-specific values belong in the `.local.toml` layer, never in a tracked file.
- - **The `machine-local` command itself is not found.** Setup is incomplete rather than misconfigured — re-run `/coordinator:install` Phase 3. On macOS and Linux, `~/.claude/bin` is deliberately NOT on PATH; bare-name reach comes from the `coordinator/bin` forwarder that Phase 3 installs, so a missing bare name means a missing forwarder, not a PATH edit you should make by hand.
-
- ### Documentation System
- The documentation index is live at `docs/README.md`. Subdirectories are created lazily as artifacts accumulate:
- - **`docs/wiki/`** — created by `/distill` when first guide is extracted
- - **`docs/plans/`** — created when first plan is written in plan mode
- - **`docs/research/`** — created by `coordinator:research` on first run
- - `/update-docs` maintains docs/README.md; `/distill` creates wiki guides from session artifacts
- ```
+ Read `residue/phase4-report-template.md` before writing this report — it carries the declared word-budget exemption (this is a once-per-repo walkthrough, not a recurring status report; do not shorten it), the `coordinator_whoami` status-row routing, the report-by-exception rule for `### Already Existed`, the full report template (`### Created` / `### Already Existed` / `### Needs Attention` / `### Recent Roadmap` / `### What's next`), and the coordinator-binding verification procedure.
### Sentinel — signal that setup just ran
As the final action of `/coordinator:repo-setup`, write a session-scoped sentinel so `/workstream-start` (if invoked in this same session) detects that setup just ran and emits the produce-not-prescribe one-liner instead of re-orienting: create the `state/` directory if absent, then touch `state/.repo-setup-just-ran`.
The sentinel is single-shot: `/workstream-start`'s Preflight consumes it on first read (`rm -f`). It MUST be gitignored — see Phase 3f for the `.gitignore` line. Per-machine transient marker, never committed.
## Optional Tripwire Installs
- After Phase 3 scaffolding completes, offer to install coordinator-standard tripwire tests into the consuming repo's test suite. Each tripwire is a copyable template — copy, customize the allowlist, and wire into CI.
-
- ### Windows console-subprocess tripwire (offer always on Windows-operator repos)
-
- Offer this tripwire when the consuming repo includes shell scripts that may run on
- Windows operator machines (any `*.sh` in the repo root or a `scripts/` / `bin/` subtree
- is a reliable signal).
-
- **What it catches:** bare `python -c`, `python3 -c`, `python.exe -c`, `powershell.exe`,
- and PowerShell `& python` invocations in `*.sh` files — shapes that pop a
- focus-stealing console window on Windows when spawned from the headless Bash-tool
- parent process.
-
- **Canonical suppression markers (two forms, honored identically by all layers):**
- - `# popup-intentional-last-resort` — the popup occurs and is accepted (pythonw fallback or genuine console need).
- - `# popup-safe-env-suppressed` — the popup is suppressed at this site by env-var means and is therefore safe.
-
- Place the applicable marker on the same line as the bare call (shell/Python comment form). When inside an embedded interpreter string (`python -c "..."`) place the marker on the surrounding SHELL line, outside the string — the marker inside a Python string argument is parsed by Python at runtime, not by the tripwire regex. The retired form `# noqa: bare-subprocess-windows` is NOT honoured; do not use it.
-
- **Install steps:**
-
- 1. Copy `<coordinator-plugin-root>/tests/templates/test_no_bare_console_subprocess.py` into the consuming repo at `tests/test_no_bare_console_subprocess.py` (resolve `<coordinator-plugin-root>` the same way the rest of this skill does — `CLAUDE_PLUGIN_ROOT` / the `.doe-root` pointer — and fail loud if unresolved).
- 2. Customize the allowlist at the top of the copied file: `PREFIXES` — subtree paths that are known-safe (e.g. `vendor/`, `tests/fixtures/`); `EXACT_FILES` — individual files allowed to use bare calls (e.g. the safe-path wrapper itself).
- 3. Verify it runs and reports nothing unexpected: `python3 tests/test_no_bare_console_subprocess.py` (or `pytest tests/test_no_bare_console_subprocess.py`).
- 4. Add the appropriate suppression marker to any remaining bare calls in files NOT covered by the allowlist — `# popup-intentional-last-resort` if the popup is accepted (last-resort / pythonw fallback); `# popup-safe-env-suppressed` if the popup is already suppressed by env-var means.
-
- **Template path:** `~/.claude/plugins/coordinator/tests/templates/test_no_bare_console_subprocess.py`
-
- Offer the install when the PM has not already done so (check for the file in the
- consuming repo's test tree). If the PM declines, note it in the Phase 4 REPORT under
- `### Needs Attention` with a one-line pointer to the template path.
-
- ### Cross-platform CI reference (offer when `cross_platform` is declared or inferred-and-confirmed)
-
- Offer this CI reference when `_CROSS_PLATFORM_DECLARED=true` (from Phase 1 `coordinator.local.md` capture) OR when `_CROSS_PLATFORM_INFERRED=true` and the PM confirms the inference prompt.
-
- **Inference prompt (when `_CROSS_PLATFORM_INFERRED=true` and `_CROSS_PLATFORM_DECLARED` is unset):**
-
- > This repo looks cross-platform (detected: {_CROSS_PLATFORM_SIGNAL}). Declare `cross_platform: true` in `coordinator.local.md` and install the CI reference? [yes / no / not now]
-
- On "yes": write `cross_platform: true` as a flat top-level entry into `coordinator.local.md` (same shape as `fast_test_cmd`) and set `_CROSS_PLATFORM_DECLARED=true`, then proceed to the offer below. On "no" or "not now": skip the CI reference offer and note the decline in `### Needs Attention`. **Never auto-write without asking — detect-then-ask, not detect-then-silently-pick.**
-
- **Why this uses an explicit declared field rather than pure signal-detect:** repo-setup's existing tripwire offers key on detected code signals (e.g. `*.sh` presence), but `cross_platform: true` is a deliberate departure from that pattern. Cross-platform-ness is a cross-cutting property that applies equally to TS, Python, C++, and Rust repos; it is most honestly declared by an operator who has thought it through. Silent inference risks a false positive — e.g. inferring cross-platform from `*.sh` in `bin/` and auto-installing a pytest CI snippet into a TypeScript repo. The explicit optional field preserves operator judgment while keeping the detect-then-ask path for convenience.
-
- **Offer text (once cross-platform is declared or inferred-and-confirmed):**
-
- > This repo declares cross-platform support. Install the cross-platform CI reference (3-OS matrix + honest-measurement markers)?
- >
- > Reference snippet: `~/.claude/plugins/coordinator/templates/ci/cross-platform-matrix.snippet.yml`
-
- **Language-aware install — IMPORTANT: do not hand a pytest snippet to a non-Python repo.**
-
- - **Python repos** (`detected_type == data-science` OR `pyproject.toml` / `requirements.txt` / `pytest.ini` detected in Phase 1): auto-copy `templates/ci/cross-platform-matrix.snippet.yml` into the consuming repo, then link the principle wiki and add a `### Needs Attention` reminder to adapt the marker names and deselect logic for the project's hardware-gated tests:
-
- 1. Copy `<coordinator-plugin-root>/templates/ci/cross-platform-matrix.snippet.yml` into the consuming repo at `templates/ci/cross-platform-matrix.snippet.yml` (create `templates/ci/` if absent; resolve `<coordinator-plugin-root>` the same way the rest of this skill does).
- 2. Review inline comments — adapt marker names (`cross_repo_fix_locus` is coordinator-standard; hardware-gate markers like `real_spawn` are project-rag-specific examples, replace with your own).
- 3. Wire the matrix block into your CI workflow (GitHub Actions, GitLab CI, etc.).
-
- - **Non-Python repos (TS, Rust, UE-C++, general):** do NOT copy the pytest snippet. Instead, surface the wiki + snippet as a worked example:
-
- > The cross-platform CI reference (`cross-platform-matrix.snippet`) is a worked **pytest** example of the language-agnostic principle. Adapt the matrix and honest-measurement marker conventions to your CI system and test runner.
-
- **Template path:** `~/.claude/plugins/coordinator/templates/ci/cross-platform-matrix.snippet.yml`
-
- Offer the install when the PM has not already done so (check for the snippet in the consuming repo's tree). If the PM declines, note it in the Phase 4 REPORT under `### Needs Attention` with a one-line pointer to the template path and wiki.
-
- ## Coordinator Conventions — Discovery Summary
-
- When a new project is onboarded, surface these convention introductions so the EM has them at hand from day one. These are one-line pointers; the canonical docs hold the full mechanics.
-
- - **Extended substrate (Phase 3j):** setup now seeds `fast_test_cmd`/`full_test_cmd` in `coordinator.local.md`, `state/health-ledger.md` (grade `?` baseline), the RAG-index decision (index-offer or `un-indexed` tripwire in `CLAUDE.md`), and the fnm Node-version pin if `.node-version`/`.nvmrc` is present. These remove the silent-skip gaps in `/workday-complete` Step 1 and Step 4d and the Node toolchain mismatch on repos with a pinned version.
-
- ## Onboarding Bug Fixes — Three-Layer Rule
-
- Any onboarding bug fix without all three layers recurs: **(1) Prevention** — fix the install script; **(2) Reactive repair** — `doctor`-style recovery or idempotent re-run path for users who already hit it; **(3) Searchable docs** — a troubleshooting table row keyed on the literal error text. New failures: verify all three layers before closing.
+ After Phase 3 scaffolding completes, offer to install coordinator-standard tripwire tests into the consuming repo's test suite — the Windows console-subprocess tripwire (offered), the widened `.py`/`.ps1` spawn tripwire (always installed, non-optional), and the cross-platform CI reference (offered when `cross_platform` is declared or inferred-and-confirmed). Read `residue/tripwire-installs.md` for the install steps, suppression-marker conventions, exemption mechanisms, and the language-aware install branch for the CI reference before running any of these — it carries no inline steps here, to avoid duplicating that file.
## Notes
- - This skill creates the **skeleton**; `/update-docs` handles ongoing tracker maintenance. Tracker format matches the tracker-maintenance skill for consistency.
- - Handoffs live at `state/handoffs/` (git-tracked); `settings.local.json` in `.gitignore`.
- - **Template architecture:** One base CLAUDE.md template with conditional blocks per project type — NOT 4 separate files (stays under 12-file ceiling). Works standalone for marketplace users; DETECT phase adds "extends global" reference if `~/.claude/CLAUDE.md` exists.
+ - This skill creates the **skeleton**; `/update-docs` handles ongoing tracker maintenance, in the same format.
+ - Any onboarding bug fix needs all three layers to not recur: prevention (fix the install script), reactive repair (`doctor`-style recovery for users who already hit it), searchable docs (a troubleshooting row keyed on the literal error text). Rationale: wiki.
+ - Rationale for the Phase 3j extended-substrate seeds and the CLAUDE.md template architecture: wiki.