# Convert Harness

Change the active binding with the bundled transaction. Conversion preserves protected project state and runs only at a safe ownership boundary.

## 1. Resolve The Loop And Destination

Require `codex` or `pi`. A missing destination reports the current binding plus `$dirtyloops convert codex` and `$dirtyloops convert pi` without mutation.

Locate the document root and Beads epic from the loop. Read both harness references.

Completion criterion: source, destination, document root, and epic are explicit.

## 2. Dry-Run The Transaction

Run:

```sh
node <dirtyloops-skill>/scripts/convert-harness.mjs \
  --doc-root docs/implementation/<stream> \
  --to <codex|pi> \
  --coordinator-id <certified-current-coordinator-id> \
  --authored-path CONTEXT.md \
  --authored-path adr/ADR-0001.md \
  --dry-run
```

The helper discovers historical v2 loops without a binding as Codex, checks ownership and unresolved completion/CI state, validates and assembles the complete destination-current generated contract, hashes protected files, audits execution readiness, and reports every planned action. An explicitly `stopped` strategy is a safe conversion boundary only when no owner or completion remains and CI is `ci-green`, `ci-repaired-and-green`, `ci-unavailable-with-evidence`, or explicitly not configured. Readiness is report-only during conversion: never reinterpret or rewrite authored phases. Use the helper's inferred epic or pass `--epic` when needed.

Roadmaps, numbered phase docs, turn docs, and storyboards are protected by convention. Pass one exact, repeatable `--authored-path <loop-doc-root-relative-file>` for every additional authored support file. Declared files must exist as regular files, cannot overlap generated paths or use case/symlink aliases, and participate in the same before/after hash check. Undeclared ambiguous files remain a blocker. Reuse the identical list for apply and repeat validation.

Completion criterion: dry-run reports `ready`, `already-target`, or a complete blocker list and changes no files or Beads state.

## 3. Apply And Verify

Run the same command without `--dry-run` only when preflight is ready. The helper stages `IMPLEMENT.md`, the current run prompt, mutable resume mirror, destination binding and adapter policy, current schemas, and generation manifest behind one recovery lock. It applies that rollback boundary atomically, updates Beads metadata, verifies protected hashes, writes `harness-conversion-report.json`, and removes the lock. The resume mirror participates in rollback and destination agreement but is excluded from deterministic generation identity so ordinary phase advancement does not stale activation.

An interrupted transaction is recovered on the next invocation before new conversion work. A failed apply restores every generated file and Beads metadata and reports `rolled-back`. Historical `.dirtyloops-convert.lock` snapshots remain recoverable for compatibility. Do not bypass an active-ownership blocker.

A material conversion writes `runtime/activation.json` transactionally and reports `runtime_status: activation-required` for Pi. It records only the source coordinator identity, never a future callback target. End the source coordinator after conversion; a destination Pi run must activate from a different session through the live vanilla completion-and-acknowledgement path. Codex destinations report `activation-ready` because their first-party runtime has no injected adapter closure to reload; the destination run still revalidates its live manifest and required capabilities before ownership.

Completion criterion: Beads, `runtime/generation.json`, `runtime/activation.json`, `runtime/binding.json`, generated `runtime/adapter.json` presence/content, schemas, run prompt, and `loop-state.md` agree on the destination generation; protected hashes are identical; the report says `converted` or `already-target`; material conversion does not claim runnable status; and no recovery lock remains. Otherwise the exact pre-conversion state is restored.
