# Modular Runtime — Reversible Transition Preparation 01

Date: 2026-08-01

Status: prepared but not executed; the clean scoped release, rollback source, selector semantics, state separation, verification commands, fail-back rule, and actual process-manager target are pinned. Changing production authority still requires explicit operator authorization.

## Authority boundary

The only runtime selector is `NYX_RUNTIME_AUTHORITY=legacy|modular` in `apps/moderator/src/runtime-authority.ts`. An absent or blank value resolves to `legacy`; an unknown value fails closed before either runtime starts. `apps/moderator/src/start.ts` calls exactly one selected starter and installs the same clean shutdown boundary around either result.

No selector value, production process, service definition, database, state directory, deployment target, or external configuration was changed during this preparation.

## Discovered process-manager target

Read-only machine and repository inspection identifies the exact target as launchd service `gui/$(id -u)/com.nyx.moderator`, with its immutable environment at `~/Library/LaunchAgents/com.nyx.moderator.plist`, its launcher at `~/.nyx/runtime/current/bin/nyx-core`, and health at `http://127.0.0.1:8787/health`. The portable launcher compiles this same `src/start.ts` entrypoint.

The target is currently unloaded, its plist is absent, and nothing listens on port `8787`. The previous launch agents are archived and inactive. The activated verified legacy portable bundle is pinned at source commit `dc714645fa47d791cec10f024d46c68195d75bdf`. Full evidence and exact bootout/bootstrap semantics are recorded in [`MODULAR_RUNTIME_TRANSITION_TARGET_01.md`](./MODULAR_RUNTIME_TRANSITION_TARGET_01.md).

## Exact rollback source

Git base:

```text
branch: nyx-core-repair
HEAD:   6505fc1d0e21f68076258c99c29e7858735ecd14
```

The working tree contains the accepted vNext implementation plus pre-existing and task changes, so the Git SHA alone is not an exact release identity. A local content-addressed source snapshot therefore pins the transition candidate without staging, committing, or overwriting user work:

```text
.nyx/evidence/transition-prep-vnext-01/nyx-runtime-source-6505fc1d.tar
SHA-256 05b11391e26aeb5de1c002d1ca66678c1159338591e4a077a962dbddef81ece8
212 archive entries · 2.4 MiB
```

`shasum -a 256 -c source.sha256` succeeds. The archive contains the legacy and modular moderator source, selector and process entry, modular package source, package manifests, lockfile, workspace configuration, TypeScript configuration, and focused Vitest workspace. It contains no state database, credential vault, `.env`, home-directory data, or Cloudflare credential. The source archive remains local and is intentionally not copied into the public Studio.

That initial archive remains immutable history. The current release snapshot expands the scope only to include deterministic tests and portable service tooling, and is sealed at SHA-256 `9a951703df442562b03bd82e21e1f372927dca0f92b4cf0eb9172162c5f8cf43`. A clean isolated commit and portable artifact now exist at `c10d9f6bb8ac79efc94a9bd212e7be5d69531065`; see [`MODULAR_RUNTIME_SCOPED_RELEASE_01.md`](./MODULAR_RUNTIME_SCOPED_RELEASE_01.md). No unrelated dirty work entered that commit.

## State rollback

The two runtimes never share a database filename:

- legacy: `${NYX_STATE_ROOT:-$HOME/.nyx}/data/moderator.db`;
- modular: `${NYX_STATE_ROOT:-$HOME/.nyx}/data/modular-builder.sqlite`.

The modular runtime has no migration that rewrites the legacy database. A selector rollback therefore reopens the existing legacy database rather than converting modular state or copying records between stores. Transition must never delete, rename, compact, or archive `moderator.db` before the rollback window closes.

## Verified selector health

Both selected safe-mode processes passed through the real shared entrypoint against in-memory SQLite:

```sh
NYX_COMPILED_SELF_TEST=1 NYX_RUNTIME_AUTHORITY=legacy \
  pnpm --dir apps/moderator exec tsx src/start.ts

NYX_COMPILED_SELF_TEST=1 NYX_RUNTIME_AUTHORITY=modular \
  pnpm --dir apps/moderator exec tsx src/start.ts
```

Both returned HTTP health `status=ok` and `database=ok`, then stopped cleanly. The deterministic regression remains 268 modular tests and 239 moderator/legacy-boundary tests with both TypeScript builds passing.

## Authorized transition procedure

Once the operator explicitly authorizes `com.nyx.moderator`:

1. verify the source snapshot checksum and build the exact scoped release artifact;
2. record the current process/service revision and confirm the legacy database remains intact;
3. run the legacy safe-mode self-test from the release artifact;
4. boot out only `com.nyx.moderator`, generate its plist with `NYX_RUNTIME_AUTHORITY=modular`, and bootstrap exactly that service because `kickstart` does not reload plist environment;
5. require `/health` to report modular authority, the expected build SHA, and database health;
6. submit one bounded direct smoke and one bounded graph smoke through the normally selected production entry;
7. require terminal accepted Git evidence, empty leases, no orphan process, and queryable restart-safe state for both;
8. on any failed health or smoke condition, automatically restore `NYX_RUNTIME_AUTHORITY=legacy`, restart the same process, and require legacy `/health` plus database health;
9. preserve both runtime stores, the exact logs, source snapshot, and smoke evidence regardless of verdict.

The change and fail-back must be one process-manager transaction or one scripted critical section. A human manually noticing a failed smoke later is not rollback proof.

## Stop conditions

Do not begin the switch if any of these remain unknown:

- the exact authorized smoke workspaces and requests;
- the automatic critical section that restores the previous bundle and explicit-legacy plist on any failed condition.

Do not infer these from local development scripts. The implementation and isolated evidence are complete, but production coordination and authority cannot be invented.

## Current decision

Legacy remains the configured default and is recoverable; no Nyx daemon is currently loaded. The clean scoped portable release is accepted. The next action is to obtain explicit authorization to install/load the discovered target and execute the bounded transition above.
