# Copilot Instructions — [PROJECT NAME]

> **Generated by the doc-and-modernize skill (Modernization mode) as an editable starting point.**
> Save this at **`.github/copilot-instructions.md`** (the path GitHub Copilot
> auto-loads). It encodes the *canonical commands* and the *phase-gating rules*
> an agent (or human) must follow while executing `MODERNIZATION_PLAN.md`. Tune
> the gates, commands, and branch rules to your project — the placeholders below
> are intentionally generic. Delete this note once customized.

[PROJECT NAME] is being **modernized**. The safety strategy is **adaptive**: the
legacy stack may be partly or wholly dead, so we do **not** assume a fully-green
legacy CI gate exists up front. Each component is on the **highest achievable rung
of the safety ladder** (L0–L4), has a named **Testability Milestone** (the phase
where it first builds, runs, and passes ≥1 test on a supported toolchain), and is
labeled **pre-testability ("dark")** or **post-testability ("lit")**. CI is stood
up at a named **CI Milestone** (the first lit phase); enforcing it as a required
check is a manual human step. See `MODERNIZATION_PLAN.md` for the phase roadmap,
per-component testability/rung, the CI Milestone, and the residual-risk register;
`ARCHITECTURE.md` for the audited current state. Work one phase at a time; do not
advance until the current phase's exit criteria are demonstrably met.

## Commands

> Fill from the architecture doc's **Commands & Verification Inventory**. Use
> your ecosystem's real runner (npm/yarn/pnpm, `make`, `just`, `cargo`, `go`,
> `poetry`/`tox`/`nox`, `gradle`/`mvn`, …). Delete rows that don't apply.

| Action | Command |
|--------|---------|
| Install / restore deps | `<install command>` |
| Build | `<build command>` |
| Run / serve locally | `<run command>` |
| Unit tests (all) | `<test command>` |
| Single test file | `<single-file test command>` |
| Single test by name | `<single-test-by-name command>` |
| Lint | `<lint command>` |
| Format / check | `<format command>` / `<format-check command>` |
| Typecheck (if applicable) | `<typecheck command>` |
| End-to-end / smoke (if applicable) | `<e2e command>` |
| Contract / characterization tests | `<contract test command>` |

CI (`<path to CI workflow>`) runs `<ordered gate list, e.g. lint → typecheck →
test → e2e>` on `<runtime/version>` for every push and PR. CI was stood up in
**phase `<N>`** (the first *lit* phase). **Enforcement is a separate manual
step:** until a human turns this workflow into a **required status check /
branch-protection rule** (`<platform: e.g. GitHub → Settings → Branches; GitLab
protected branches>`), CI *runs* on PRs but does **not** *block* merges.

> **Keep this table current.** If a phase introduces a new long-term command,
> update this table (and confirm it with the user during planning) — don't leave
> the canonical command list stale.

## Phase gating (regime-aware; applies to every phase)

A phase is **not complete** until its **Verification & Exit Criteria** in
`MODERNIZATION_PLAN.md` pass. Those criteria must be:

1. **Objectively verifiable** — runnable commands / captured evidence, not a
   subjective judgement.
2. **Actually executed and recorded** — run them and note the result in the plan
   before starting the next phase.
3. **Gated** — do **not** advance to phase N+1 until phase N's criteria are
   demonstrably met.

**Which criteria are valid depends on the component's regime:**

- **Post-testability ("lit") phases:** exit on runnable commands / **green CI on
  the phase's branch/PR — the authoritative signal.** Shared baseline: `<lint
  command>` and `<test command>` must pass; if the change touched the client /
  transport / protocol / any public interface, the relevant end-to-end and
  contract/characterization tests must also stay green.
- **Pre-testability ("dark") phases:** the component isn't alive yet, so a green
  CI test gate is a **category error**. Exit on the phase's achievable
  **safety-ladder rung** instead — captured seam/oracle snapshots, reversibility
  scaffolding proven present, a passed smoke checklist, recorded review. **Do not
  block a dark phase on a test suite that can't run yet.** A blessed **downgrade**
  to a lower rung (with residual risk named) is a valid exit, not a failure.

**Never require a component's automated test gate before it crosses its own
Testability Milestone.** Report to the user any phase whose pass/fail is unknown
rather than assuming it passed.

## Decisions

- When a phase is planned, **all sub-decisions must be resolved and documented**
  in the plan so implementation needs no further user input.
- State **"dropped" vs "deferred"** explicitly for anything cut — don't leave it
  ambiguous.
- Update `MODERNIZATION_PLAN.md` status markers (✅ complete / ⏭️ descoped /
  🗑️ dropped) as each phase's exit criteria are met, and **update the
  safety-ladder rung / residual-risk register** as components cross their
  Testability Milestone.

## Branching & PRs

Each phase is developed on its **own branch** — never commit phase work directly
to the default branch (`<default branch>`). Create a new branch at the start of a
phase (e.g. `phase-N-<short-name>`). Once the phase's exit criteria are met and
recorded, push the branch and open a PR to the default branch. For
**post-testability ("lit")** phases, let CI on the PR be the authoritative green
signal before merging. For **pre-testability ("dark")** phases, the PR instead
carries the achievable safety-ladder rung's evidence (captured contracts, smoke
results, reversibility scaffolding) with residual risk named.

**Merge to trunk before the next phase; never stack.** Cut each phase branch
**from the trunk (`<default branch>`)**, and **merge its PR to trunk before
starting the next phase.** Never base a phase branch or its PR on a *sibling*
`phase-N` branch — stacked phase PRs get merged into each other, the trunk
silently stalls several phases behind, and later phases are forced into a bind.
Before starting a phase, verify the previous phase is merged and
`git log origin/<default branch>..HEAD` is empty at branch creation. **Controlled
stacking is allowed only if genuinely unavoidable — and only with a reconciliation
PR that lands the stack onto trunk plus an explicit residual-risk note.**

> **Confirm the trunk name; retire legacy defaults.** Pin the real trunk
> (`<default branch>`). If a second default-ish branch exists (e.g. a legacy
> `master` alongside `main`), mark it "history only — do not target" so phase
> work never lands on the wrong branch.

**Keep the executable docs alive with the code.** Any phase that changes
**topology** — module/reactor membership, removed services, renamed branches,
changed commands, new/removed endpoints — must update **this file**, the
`README`, and any module/topology list **in the same PR**. A stale module list or
a hard-coded old-branch link actively misleads the next agent/human.

**Register transitional-insecure states.** If a phase intentionally introduces a
temporary weak state to stay runnable (permit-all shim, CSRF disabled, an open
endpoint, a placeholder secret), record it with the phase that **closes** it and
a by-design-until-phase-N note, and scope it as tightly as possible — this
preempts recurring scanner/reviewer churn.

> **CI enforcement is a manual, human-only step.** An agent can author and run
> the CI workflow, but making it a **required status check / branch-protection
> rule** so it actually *blocks* merges is a platform-UI/admin action
> (`<GitHub → Settings → Branches; GitLab protected branches; etc.>`) the agent
> cannot perform. Until you configure it, treat "green CI is authoritative" as a
> convention you enforce by hand. Do this once, at/after the CI Milestone phase.
