# OpenChrome v1.11.0

Release date: 2026-05-12

## Summary

v1.11.0 is the **portability-harness contract** release. It establishes a
durable `core` / `pilot` tier split inside `openchrome-mcp`, ships a substantial
batch of harness primitives in the core tier (no flag required), and stubs out
the pilot tier behind a single `--pilot` opt-in flag. The release is
backward-compatible: existing v1.10.x configurations keep working unchanged.

This release lands as a single cohesive publishable package after a focused
cleanup of the 35 PRs that had accumulated against four in-flight epics
(skill state graph, outcome contracts, perception, verified skill memory).
The cleanup was governed by the new contract in
`docs/roadmap/portability-harness-contract.md`.

---

## Why this minor release exists

After v1.10.4, four epics had ~30 stacked PRs whose unconstrained adoption
would have compromised two existing OpenChrome value propositions:

1. **Backward compatibility** — harness features that mutate the 1.10 tool
   surface by default break existing clients silently.
2. **MCP portability** — features that quietly require API keys, network egress
   to third-party LLM providers, or native modules without fallback degrade the
   "anywhere-compatible" property of `npx openchrome-mcp` and the Tauri
   desktop app.

The v1.11.0 cycle resolved that drift with a contract (P1–P5), a `core`/`pilot`
directory split inside the same npm package, a dependency-cruiser lint that
enforces the tier boundary, a two-stage CI workflow, and a `--pilot` CLI flag
plus per-family sub-flags for fine-grained pilot activation.

---

## What ships in v1.11.0

### Core tier (registered unconditionally, no flag)

| Subsystem | Modules | New MCP surface |
|---|---|---|
| Trace recorder | `src/core/trace/` (JSONL storage, credential redactor) | (recorder hooks land in a follow-up) |
| Skill state graph | `src/core/skill/` (JSON-per-domain storage, state hashing) | `openchrome://skill-graph/<domain>` MCP resource (read-only) |
| Skill memory | `src/core/skill-memory/` (JSON-per-domain store, audit-log stats resolver) | `oc_skill_record`, `oc_skill_recall` MCP tools |
| Outcome contracts | `src/core/contracts/` (DSL, pHash DCT-II, screenshot class, evaluators) | `oc_assert`, `oc_evidence_bundle` MCP tools |
| Perception primitives | `src/core/perception/` (perceptual DOM metadata + cache, Sobel + color distance cross-check) | (consumed by contracts via evidence bundle) |

Four new Tier 1 MCP tools (`oc_assert`, `oc_evidence_bundle`, `oc_skill_record`,
`oc_skill_recall`) bump the Tier 1 count from 34 to 38. One new MCP resource
template is registered (`openchrome://skill-graph/<domain>`).

### Pilot tier (opt-in via `--pilot`)

The pilot tier exists as a working stub for the first time in v1.11.0. The
following modules are present and load lazily when `--pilot` is set, but each
is independently gated by a per-family sub-flag. The default (no sub-flag set)
is active inside pilot; set the corresponding env to `0` / `false` to turn an
individual family off without losing the rest.

| Family | Module | Sub-flag |
|---|---|---|
| Contract runtime (retry, idempotency, verdict taxonomy, `beforeIrreversibleAction`) | `src/pilot/runtime/` | `OPENCHROME_CONTRACT_RUNTIME` |
| Handoff token + AES-256-GCM persistence (ephemeral key default) | `src/pilot/handoff/` | `OPENCHROME_HANDOFF_PERSIST` |
| Multi-model voting framework (deterministic voters only) | `src/pilot/voting/` | `OPENCHROME_PERCEPTION_VOTING` |
| Skill curator (extractor + recall ranking + structural passes 1/2/3 + PID lock + runner) | `src/pilot/curator/` | `OPENCHROME_SKILL_CURATOR` |

Pilot tools are namespaced (`oc_pilot_*`) so MCP clients can distinguish their
experimental nature from the core surface.

### What is explicitly out of scope

The contract's principle P3 forbids outbound LLM API calls from inside the
server — even in pilot. Two pieces from the original epic plans were
redirected to separate packages rather than landing here:

- LLM voting providers (Anthropic + OpenAI HTTP wrappers) → tracked in #775 as
  the future `openchrome-perception-voters` package.
- LLM merge requester for the skill curator → tracked in #776 as the future
  `openchrome-skill-curator-llm` package.

The corresponding `Voter` and merge interfaces remain in `openchrome-mcp` so
those separate packages can plug in cleanly when they arrive.

---

## Architecture changes

### `src/core/` ↔ `src/pilot/` tier split

```
src/
├── core/              # P1–P5 strictly enforced; no flag; backward-compatible
│   ├── trace/
│   ├── skill/
│   ├── skill-memory/
│   ├── contracts/
│   ├── perception/
│   ├── cli/
│   ├── mcp/
│   └── resources/
└── pilot/             # opt-in via --pilot; P1/P4 relaxed; P3 still enforced
    ├── runtime/
    ├── handoff/
    ├── voting/
    └── curator/
```

Import direction is enforced unidirectionally by a `dependency-cruiser` rule:
`src/core/**` may not import from `src/pilot/**`. The CI workflow runs this
check on every PR.

### `--pilot` CLI flag

```bash
# Default v1.10.x experience — preserved bit-identically
openchrome serve

# Opt into the pilot tier (loads src/pilot/**)
openchrome serve --pilot

# Fine-grained activation inside pilot
OPENCHROME_CONTRACT_RUNTIME=0 openchrome serve --pilot
```

When `--pilot` is unset, no module from `src/pilot/**` is loaded into the
process (verified by a unit test that inspects `require.cache`).

### `src/harness/flags.ts`

New helper module exposing `isPilotEnabled()`, per-family getters
(`isTraceEnabled()`, `isStateGraphEnabled()`, `isContractRuntimeEnabled()`,
`isHandoffPersistEnabled()`, `isPerceptionVotingEnabled()`,
`isSkillCuratorEnabled()`), `activeFamilies()`, `logActiveFlags()`, and
`bootstrapPilot()`. Lives at `src/harness/` so both tiers may import it
without tripping the import-direction lint.

### Storage policy

`better-sqlite3` is **not adopted**. All storage layers added in v1.11.0 use
JSONL or JSON files plus `proper-lockfile` via the existing
`src/utils/atomic-file.ts` helpers. The only mandatory native runtime
dependency in `openchrome-mcp` remains `argon2`.

### Handoff token encryption

The pilot handoff persistence layer encrypts tokens with AES-256-GCM. The
encryption key is **ephemeral by default** — generated at boot, lost on
restart, persisted tokens invalidated. Operators wanting cross-restart
persistence set `OPENCHROME_HANDOFF_KEY_FILE=<path>` to a 32-byte key file
they manage themselves. No OS keychain integration (issue #721 closed per
P3).

---

## Boundary plumbing

Three boundary-enforcement PRs landed before any tier-routed work:

- **#787** — `dependency-cruiser` config + `src/core/`, `src/pilot/`
  placeholders with tier documentation. New `npm run lint:tier` script.
- **#788** — `lint:tier` wired into `.github/workflows/ci.yml` after the
  existing eslint step. `tests/{core,pilot}/` scaffolding with READMEs.
- **#789** — `--pilot` CLI flag plumbing on `serve`; `src/harness/flags.ts`
  with 32 unit tests covering argv/env parsing, cache behavior, family
  defaults and overrides, stderr-only startup logging, and the
  `bootstrapPilot()` lazy import guarantee.

---

## Reliability and security

This release does not modify the `tests/security/` or `tests/transports/`
suites except for the documented bump of the Tier 1 tool count (34 → 38)
in the cross-env Cursor verification harness. The HTTP auth fail-closed
policy from v1.10.4 is unchanged.

`#742` ports forward into v1.11.0: the `basic-ftp@^5.3.1` and
`ip-address@^10.1.1` overrides remain in `package.json` so the production
dependency tree continues to ship with zero `npm audit --omit=dev`
findings.

---

## Breaking changes

None. v1.10.x configurations work bit-identically when `--pilot` is unset.

The new MCP tools and resource are purely additive. MCP clients that list
tools dynamically will see the four new core tools (`oc_assert`,
`oc_evidence_bundle`, `oc_skill_record`, `oc_skill_recall`) and the new
resource template; clients that pin a specific Tier 1 count need to bump
their expected value from 34 to 38.

---

## Cleanup outcomes

- **35 originally-open PRs** all reached terminal state.
- **26 new PRs** merged to develop during the cleanup (PR #774 → PR #815).
- **18 new tracking issues** filed. Five remain open (#775, #776, #778,
  #779, #780); the rest were closed by their replacement PRs.
- **Two PRs redirected** to separate-package extraction issues (#760 → #775,
  #765 → #776).
- **Three SQLite-backed PRs rewritten** as JSONL/JSON + `proper-lockfile`
  per principle P5.
- **Zero abandoned work**: every closed PR's branch is preserved (cleanup
  tracked in #779).

Detailed Phase 0–6 execution log lives at
`docs/roadmap/history/openchrome-1.11-cleanup.md` (moved from
`docs/roadmap/` after this release ships). The durable contract remains at
`docs/roadmap/portability-harness-contract.md`.

---

## Upgrade

```bash
npm install -g openchrome-mcp@1.11.0
openchrome update
```

Or for a fresh install:

```bash
npm install -g openchrome-mcp@latest
openchrome setup
```

No configuration changes are required. To explore the pilot tier:

```bash
openchrome serve --pilot
```

The server prints `[harness] core+pilot enabled (<families>)` on stderr at
startup when pilot is on.

---

## Acknowledgments

The cleanup was driven against `docs/roadmap/portability-harness-contract.md`
(landed in PR #774) and the per-PR application plan in
`docs/roadmap/openchrome-1.11-cleanup.md`. The hybrid resolution of issue
#768 (`core/pilot` tier split proposal) with the contract content is recorded
in that issue's comment thread.
