--- name: install-runbook description: > Install the execution + verification surface into a Plenipo product repo so any agent can run it and prove a change works without rediscovering anything: RUNBOOK.md, a discoverable `.claude/skills/run-` skill, the Testcontainers integration fixture, the golden-eval harness, the committed `.http` request catalog, and `.claude/launch.json`. Re-runnable — it reconciles what exists and reports drift instead of clobbering. USE FOR: a product with no runbook, a product whose runbook has gone stale, or standardizing a repo that predates this contract. DO NOT USE FOR: running or debugging the product (the installed runbook does that), or platform-level Plenipo work (the Plenipo repo has its own run skill). license: MIT --- # Install the runbook Every Plenipo product must answer two questions the same way, so an agent never has to guess: **how do I run this, and how do I prove a change works?** This skill writes those answers into the product repo as durable, discoverable files. The failure this prevents is real and measured across the existing fleet: the platform repo ships a run skill, but products built on it ship none — so each new session rediscovers the AppHost command, the dev-auth headers, the Mock provider, the pgvector requirement, and the WorkingDirectory trap from scratch, or worse, doesn't and ships unverified. ## When to Use - A product repo has no `RUNBOOK.md` or no `.claude/skills/run-*`. - A repo's operations doc references projects or layouts that no longer exist (stale runbook). - A product has integration tests but no golden evals, or no integration tests at all. - Right after `/deliver:scaffold-product`, before the first feature issue is worked. ## Stop Signals - **You want to run or debug the product** → read the installed `RUNBOOK.md`, don't reinstall it. - **This is the Plenipo platform repo itself** → it owns `.claude/skills/run-plenipo`; leave it alone. - **The product isn't on Plenipo** (no `Plenipo.*` package references) → this contract assumes the platform's dev-auth, Mock provider, and AG-UI surface. Stop and say so. ## Inputs | Input | Where it comes from | Used for | |---|---|---| | Product name (PascalCase) | the `.slnx` / `src/.Host` folder | `{{Product}}` in every asset | | Product slug (kebab/lower) | repo folder name | `{{product}}` — container names, ports, file names | | Module id | the module's `ModuleManifest.Id` | `{{ModuleId}}` in AG-UI routes and evals | | Module assembly suffix | `src/.` | test project naming | | A sample user prompt | `SuggestedPrompts` in the manifest | `{{SamplePrompt}}` in the AG-UI example | Read these from the repo — never invent them. If `src/.Host` doesn't exist, the repo isn't a Plenipo product host yet; stop. ## Workflow 1. **Detect.** Confirm a Plenipo product: `src/.Host` exists and references `Plenipo.*` packages. Record the five inputs above from the actual files. Read the module's manifest for the id, tool names, which tools set `RequiresApproval`, and the suggested prompts. 2. **Inventory what's already there.** For each artifact below, record present / missing / stale. *Stale* means it exists but names a project, port, or module id the repo no longer has. | Artifact | Path | |---|---| | Runbook | `RUNBOOK.md` | | Discovery skill | `.claude/skills/run-/SKILL.md` | | E2E fixture on the kit | `tests/.IntegrationTests/Fixture.cs` — derives `PlenipoHostFixture` and declares the four kit classes | | E2E project | `tests/.IntegrationTests/.IntegrationTests.csproj` — references `Plenipo.Testing` at `$(PlenipoVersion)` | | Golden evals | `tests/.IntegrationTests/Evals/cases/*.json` | | Request catalog | `.http` | | IDE launch | `.claude/launch.json` | 3. **Write what's missing.** Copy from `assets/`, substituting the placeholders: | Asset | Destination | |---|---| | `RUNBOOK.md` | `RUNBOOK.md` | | `run-product-SKILL.md` | `.claude/skills/run-/SKILL.md` | | `Fixture.cs.template` | `tests/.IntegrationTests/Fixture.cs` | | `IntegrationTests.csproj.template` | `tests/.IntegrationTests/.IntegrationTests.csproj` | | `eval-case.json` | `tests/.IntegrationTests/Evals/cases/-write-requires-approval.json` | | `launch.json` | `.claude/launch.json` | Never overwrite an existing file silently. If one is **stale**, show the specific wrong lines and ask before replacing. **A copied harness is drift, not an install.** A product that predates the kit carries its own `IntegrationFixture.cs`, `Evals/EvalCase.cs` and an eval runner copied from the platform's sample suite. Once the csproj references `Plenipo.Testing`, those files are the duplicate the kit exists to remove: replace them with `Fixture.cs` (the product's `ProductContract` plus the four one-line kit classes), delete the copies, and keep only the product's own journeys. The kit is versioned with the platform, so a product cannot adopt it before the release that first ships it — until then report the copies as drift and leave them. 4. **Seed real content, not placeholders.** A runbook full of `{{…}}` is worse than none — an agent will trust it and be wrong. Every substitution must resolve to something you read from the repo. The eval case must name a **real** approval-gated tool from the manifest. 5. **Backfill the request catalog.** If `.http` is missing or thin, generate one request per mapped endpoint (read the module's `MapEndpoints` plus the platform routes the runbook lists), each with the dev-auth headers. 6. **Prove the install.** This is the exit condition — do not report success without it: ```bash dotnet build .slnx dotnet test tests/.IntegrationTests ``` Both must pass, and the run must include the fixture booting a Testcontainers Postgres and the kit's `SpineConformance`, `ManifestConformance`, `TenancyConformance` and `GoldenEvals` classes passing against the product — a kit invariant that fails here is a finding about the product, not about the install. If Docker isn't available, say so explicitly and mark the install **unverified** rather than done. 7. **Report drift.** List what you wrote, what you left alone, and anything stale you found but didn't change. Drift you stayed silent about is drift the next agent inherits. ## Guardrails - **Read values, don't guess them.** Ports, project names, module ids, and tool names all come from the repo. A confidently wrong runbook is the worst possible output of this skill. - **The eval case must reference a tool that exists** and is genuinely `RequiresApproval = true`. Otherwise rung 4 fails on first run and the next agent deletes the whole harness. - **pgvector, always.** The fixture image must be `pgvector/pgvector`, never stock `postgres` — the platform's RAG migration creates a vector column at startup. - **Never copy the platform's fixture, parser or eval runner into a product.** They ship in `Plenipo.Testing`; a copy is a fork of the harness that no platform fix ever reaches, and the reason four products each carried their own Testcontainers advisory. The product owns one file: `Fixture.cs`. - **The `ProductContract` names real tools.** `ReadTool` must be ungated and `WriteTool` must be `RequiresApproval = true` in the manifest; `PlenipoManifestConformance` checks both on the first run, and a wrong name fails every spine test at once. - **No secrets in any generated file.** Provider keys are per-tenant runtime settings. - **Keep the discovery skill thin.** Depth belongs in `RUNBOOK.md`; the skill is the index that makes it findable. If the skill grows past ~80 lines you are duplicating the runbook. ## Common Pitfalls | Pitfall | Consequence | Do instead | |---|---|---| | Copying assets with placeholders unresolved | agents follow a runbook that names nothing real | resolve every `{{…}}` from repo files | | Writing the runbook without running the tests | the harness ships broken | step 6 is mandatory | | Overwriting a hand-tuned `RUNBOOK.md` | loses product-specific hard-won knowledge | reconcile section by section, ask before replacing | | Using stock `postgres` in the fixture | migration fails on the `vector` type | `pgvector/pgvector:pg17` | | Asserting approvals through `AuthorizedScopeAsync()` | test passes while the gate is broken | security-shaped assertions go through `AdminClient()` | | Generating evals for tools that don't exist yet | rung 4 red on a clean repo | seed from the manifest only | ## Reference Files - [`assets/RUNBOOK.md`](assets/RUNBOOK.md) — the full contract. **Load when:** writing or reconciling the runbook. - [`assets/IntegrationFixture.cs.template`](assets/IntegrationFixture.cs.template) — the E2E host. **Load when:** the product has no integration fixture. - [`references/verifier-ladder.md`](references/verifier-ladder.md) — which rung catches which class of bug, and the cost of each. **Load when:** deciding how far to climb for a given change. ## Related skills - `/deliver:verify-runtime` — *uses* what this installs, to drive the run → observe → fix → lock-in loop. - `/harness:plenipo-runbook` — the generic, product-independent version of this knowledge.