Status: ready-for-agent

# 03 — Fail-closed startup admission lifecycle

## What to build

Gate `run_startup` on a fresh, matching successful capability report before routable Tracker registration. A Node selected for a Model Preset/shard must fail closed if its recipe cannot perform the doctor forward: no ready/registered endpoint and no paid request acceptance.

Keep local diagnostic behavior useful: a failed report may be persisted/exposed locally, but the Node must not advertise the failed model/shard as ready. Define a bounded freshness/match rule so a report cannot be reused for a different model revision, shard, recipe, or backend identity.

**Code refs:**

- `packages/node/meshnet_node/startup.py` — download/load/start/register sequence
- `packages/node/meshnet_node/cli.py` — `start` and default startup error paths
- `packages/node/meshnet_node/torch_server.py` — server lifecycle
- `tests/test_node_startup.py` — fake startup and registration capture patterns

## Test-first

1. Red: backend validation failure still causes `/v1/nodes/register` to be called.
2. Red: a success report for one arbitrary model/shard is reused for another.
3. Green: matching successful validation reaches registration; failed/stale/mismatched validation exits before registration.

## Acceptance criteria

- [ ] Explicit selected model/shard fails closed before routable registration when validation fails
- [ ] Startup sends only a matching successful capability report with its registration payload
- [ ] Failed, stale, model-mismatched, shard-mismatched, recipe-mismatched, and backend-mismatched reports are rejected locally
- [ ] Existing stub/test startup remains usable through an explicit test-safe capability path, not a production bypass
- [ ] Tests prove the tracker receives no registration on a failed validation

## Blocked by

`01-generic-capability-report.md`, `02-doctor-real-forward.md`.
