# Release publication contract

Rampway deployment has distinct runtime-cutover and publication phases.

A runtime owner may commit a release before Rampway updates `current`. Publication must atomically update the current symlink, then execute configured `after_publish` hooks in order. Failures must include full stack and command context and must distinguish runtime state from publication bookkeeping.

Transport methods must remain bound to their transport instance. Recovery must read back the exact runtime owner state before attempting rollback; never report “current unchanged” as equivalent to “runtime unchanged.”

Healthy activation and publication are also the deploy completion boundary for
release retention. A failure only in Rampway's built-in retention cleanup after
that boundary is a successful deployment with cleanup pending. Rampway still
runs `after_cleanup`; a failure in that hook, `before_cleanup`, report
persistence, lock release, or any earlier phase remains fatal. The successful
deploy report records only bounded cleanup status, a confirmed partial-removal
count, and optional process exit or signal metadata—never remote commands,
stdout/stderr, credentials, paths, or destinations—plus the exact recovery command:

```bash
rampway <environment> cleanup-releases --expected-active-revision <40-character-sha>
```

That cleanup-only command acquires the normal deploy lock and verifies the exact
`current` release revision under the lock before it inventories or deletes. It
accepts a bounded, non-whitespace persisted revision token so local-copy branch
labels and full 64-character revisions remain recoverable. Canonical 40- and
64-character hexadecimal revisions compare case-insensitively; all other tokens
compare exactly. Recovery commands emitted by direct CLI deploys shell-quote the
stage, revision, and resolved config path and preserve `--config`; programmatic
deploys without a config path do not invent one. It
replans from live release, accepted-runtime reference, and durable runtime-pin
state; only valid Rampway-managed, over-retention, unprotected releases are
eligible. Current, active-runtime, draining-runtime, and pinned releases carry
explicit protection reasons. The command replans before each deletion and once
more to verify completion. Exit 255 or a signaled listing/deletion is ambiguous,
so Rampway reads live state again and reports a release removed only when the
operation began with that release present and readback confirms it absent.
Retries are idempotent, and `--dry-run` mutates neither releases nor reports.

Cleanup-only recovery never executes deploy tasks or hooks, asks a runtime owner
to deploy/restart/handoff/retire, rewrites accepted runtime state, or updates
`current`.

If runtime activation committed but `current` publication did not, use
`rampway <environment> resume-publication <release-id>`. The command takes the
normal deploy lock and never deploys, restarts, or retires runtime processes. It
requires an exact retained Rampway release and incumbent, immutable accepted
runtime material, and two matching live committed-owner attestations around the
configured target health checks. It then publishes normal stable runtime state,
commits idempotent runtime metadata, atomically updates `current`, persists boot
state where supported, and runs post-publication hooks, cleanup, and reporting.
Any identity, transition, health, or current-state mismatch fails before those
publication writes. Publication recovery persists accepted boot material but
does not initiate a process-retiring external-owner handoff.

A retained daemon-owned schema-1 target is upgraded only after it exactly
matches a freshly reconstructed target contract; the resulting schema-2 state
is bound to the existing content-addressed daemon manifest and bytes. The
verified daemon runtime computes the normalized target config authority, which
must equal the live committed transition and ready-owner digests. After health,
Rampway re-resolves the target directory and rereads its revision and metadata.
If `current` and stable state already identify the target, recovery uses the
accepted incumbent boot identity to finish publication without another symlink
write. A matching completed JSONL report makes later retries read-only after
fresh runtime and health attestation.

Git dependencies are valid when pinned to immutable revisions and installable from source. Package version supports compatibility admission; immutable revision/content digest proves identity.
