# Upstream status and release evidence

## Managed installs (v1.2.3, completed in v1.2.4)

pi 1.0.1 introduced a managed install: the `pi` on `PATH` is a shell launcher under `~/.pi/agent/bin`, and the package
sits in `~/.pi/agent/install/releases/<version>/node_modules/@earendil-works/pi-coding-agent`. Resolving the theme
module by walking the filesystem up from the launcher therefore found nothing, and md-cache reported
`unsupported: markdown theme unavailable for differential canary` after `pi update`. The theme is now taken from the
host package (`import("@earendil-works/pi-coding-agent")`, which re-exports `getMarkdownTheme`), so the layout no
longer matters; the filesystem walk stays as the fallback for `PI_PACKAGE_ROOT` fixtures.

That fixed the cache itself but not everything else built on `scripts/resolve-pi.mjs`: `/rcstats` printed
`pi ?/pi-tui ?`, and `npm run compat`, `compat:matrix` and the benchmarks could not run at all on a managed host.
v1.2.4 therefore teaches the resolver the layout once, for every consumer: a `pi` on PATH that is not inside a
package is treated as a launcher, `<agentDir>/install/current-version` names the active release, and the package is
read from `<agentDir>/install/releases/<version>/node_modules/`. A missing `current-version` accepts a single present
release; several releases, or a stale pointer, resolve to nothing rather than to a guessed version.

## Supported pi line (v1.2.2)

`compatibility.json` declares `supported.pi: ">=1.0.0"`. Support is that range plus the install-time behavioral
verification, **not** a list of exact versions: a pi build that nobody recorded is still supported when the canaries
pass, and an older or diverging build is not blocked — it takes the same behavioral path and falls back to the
original renderer per patch. The repository's own devDependencies now follow the current pi line (1.0.0) instead of a
frozen 0.84.1 unit, so `npm test` exercises what users actually run. `versions` / `implementationHashes` remain a
history of measured units, useful for reproducing a past measurement.

## pi 1.0.0 re-check (2026-10-02, v1.2.1)

Both upstream premises still hold on released pi **1.0.0**:

- `AssistantMessageComponent.updateContent()` still calls `contentContainer.clear()` and constructs a fresh
  `Markdown` per streamed assistant update, so the component's per-instance line cache is still discarded.
- pi-tui still creates shared `Intl.Segmenter` instances and calls `segment()` on the visible-width path. The new
  `widthCache` in pi-tui memoizes whole-string widths only, so repeated segmentation of changing strings remains.

Measured on pi 1.0.0 (Apple M3, Node 22.23.0, 3 randomized blocks, report-only):

| Workload | seg-cache | md-cache | both |
|---|---:|---:|---:|
| Ordinary streaming Markdown | 1.19× | 10.31× | **13.41×** (retained 70.0 → 4.4 MiB) |
| Styled thinking | 1.66× | 0.87× (fallback by design) | **1.51×** |
| Unicode visible-width work | 2.92× | 1.01× | **2.88×** |

### Fixed in v1.2.1: syntax palette went unobserved on pi 1.0.0

`highlightCode` falls back to one flat `mdCodeBlock` color whenever `supportsLanguage(lang)` is false. pi 1.0.0's
bundled highlighter no longer recognizes `llvm`, which was the single language the theme fingerprint probed, so the
fingerprint stopped observing every syntax color: after a `/theme` switch, cached settled prefixes kept the OLD
syntax colors. The fingerprint now probes five recognized languages (typescript, html, sql, python, swift) that
together cover comment, keyword, function, variable, string, number, type and operator. No highlight.js scope
resolves to `syntaxPunctuation` on this host, so that color cannot appear in rendered output either.

The repository's own theme-invalidation tests could not catch this: they recolored a cloned theme's `fgColors`,
which pi 1.0.0 no longer reads at `fg()` time (it precomputes `fgAnsi` in the Theme constructor), so the switch was
a no-op and the tests failed on their own sanity assertion. `tests/helpers.js` now writes every representation.

Checked **2026-08-07** against released pi **0.84.1**, commit [`53fa77ccd8a279eb87e92294ef3687b03ff80112`](https://github.com/earendil-works/pi/tree/53fa77ccd8a279eb87e92294ef3687b03ff80112), and newer upstream `main` commit [`4bf1bba203c699a0b79da669b084052c72b7a35a`](https://github.com/earendil-works/pi/tree/4bf1bba203c699a0b79da669b084052c72b7a35a). No intervening commit touches the four hot-path files, and both targets from #6665 remain present:

- [`AssistantMessageComponent.updateContent()` still clears its container](https://github.com/earendil-works/pi/blob/4bf1bba203c699a0b79da669b084052c72b7a35a/packages/coding-agent/src/modes/interactive/components/assistant-message.ts#L89-L95) and [constructs a fresh `Markdown`](https://github.com/earendil-works/pi/blob/4bf1bba203c699a0b79da669b084052c72b7a35a/packages/coding-agent/src/modes/interactive/components/assistant-message.ts#L104-L116) for streamed assistant text.
- [`Markdown.render()` still lexes the complete transformed text](https://github.com/earendil-works/pi/blob/4bf1bba203c699a0b79da669b084052c72b7a35a/packages/tui/src/components/markdown.ts#L285-L303) on a cold component.
- pi-tui still creates shared [`Intl.Segmenter` instances](https://github.com/earendil-works/pi/blob/4bf1bba203c699a0b79da669b084052c72b7a35a/packages/tui/src/utils.ts#L4-L18) and repeatedly calls `segment()`, including the [visible-width path](https://github.com/earendil-works/pi/blob/4bf1bba203c699a0b79da669b084052c72b7a35a/packages/tui/src/utils.ts#L270-L286).

## Related upstream work

- [#6665](https://github.com/earendil-works/pi/issues/6665) is open, assigned, and marked in progress.
- [#7017](https://github.com/earendil-works/pi/pull/7017) was closed without merge. It limits terminal output after component rendering, so it complements rather than replaces the inner Markdown-render cache.
- [#7082](https://github.com/earendil-works/pi/pull/7082) was closed without merge. It targets outer transcript/per-keystroke work, so it complements rather than removes Markdown rebuilds or segmentation calls.
- [#6792](https://github.com/earendil-works/pi/issues/6792) is excluded from core-performance evidence: its reporter retracted the report after identifying an extension fault.

## Controlled v1.1.1 evidence

Apple M3, Node 22.23.0, ICU 78.2, pi/pi-tui 0.84.1; 20 randomized complete blocks per workload and three repetitions per isolated mode run. Speedup is baseline divided by mode time; brackets are 95% paired whole-block bootstrap CIs. RSS values are median paired mode-minus-baseline replay-peak/retained-end deltas; negative is lower.

| Workload | Mode | Median speedup [95% CI] | Paired RSS Δ peak / retained end (MiB) |
|---|---|---:|---:|
| ordinary Markdown | seg-cache | 1.51× [1.38, 1.59] | +0.53 / +0.53 |
| ordinary Markdown | md-cache | 14.88× [13.03, 16.34] | -17.31 / -17.31 |
| ordinary Markdown | both | 16.42× [14.85, 18.42] | -16.88 / -16.88 |
| styled thinking | seg-cache | 1.50× [1.37, 1.58] | +0.05 / +0.05 |
| styled thinking | md-cache fallback | 0.94× [0.88, 1.00] | +0.13 / +0.13 |
| styled thinking | both | 1.50× [1.39, 1.64] | +0.12 / +0.12 |
| Unicode width | seg-cache | 2.34× [2.24, 2.58] | +0.05 / +0.05 |
| Unicode width | md-cache | n/a (no Markdown work) | +0.03 / +0.03 |
| Unicode width | both | 2.40× [2.35, 2.52] | +0.04 / +0.04 |

All Checkpoint B paired replay-peak RSS gates passed the +20 MiB limit; the worst median increase was +0.53 MiB.

The durable sanitized result, environment, hashes, and exact unrounded values are in [`evidence/v1.1.1/summary.json`](https://github.com/axelbaumlisto/pi-render-cache/blob/v1.1.1/evidence/v1.1.1/summary.json). From a source checkout, reproduce the full run with `npm run premise`; use `npm run test:perf` for a short non-release performance check and `npm run compat` for the selected compatibility unit.

Since v1.2.0, activation is decided behaviorally at startup (md-cache differential canary + sampled miss-time self-verification; seg-cache structural + native canary) — the pi version and implementation hashes recorded in `compatibility.json` are diagnostic bookkeeping only. pi 0.84.3 was verified as a tested unit with identical `Markdown.prototype.render`/`getMarkdownTheme` hashes to 0.84.1.

On pi 0.84.1 both patches are **active** after their independent canaries. `md-cache` deliberately falls back for styled thinking and Markdown transformer options; these paths are enforced by tests and are not claimed as cacheable. `seg-cache` remains active there and produced about 1.5× in the controlled thinking replay.

## Live pi 0.82.1 smoke check

After the automated gates, the packaged extension was loaded by the real pi host with `pi -e ./extensions/index.ts --no-session -p ...`. An in-process probe verified the actual host prototypes and lifecycle state:

```text
LIVE_CHECK {"mdState":"active","segState":"active","mdPatched":true,"segPatched":true}
```

The request completed and rendered normally. This is an ecological load/wiring check; controlled performance claims still come only from the blocked replay above.

## Independent retirement protocol

Each patch is retired independently and only after correctness parity; see the [full plan](https://github.com/axelbaumlisto/pi-render-cache/blob/v1.1.0/.pi/plans/validate-and-extend-render-cache.md#retirement-protocol-future-released-upstream).

- **Structural no-work route:** released upstream removes the hot path; reachability, canaries, and deterministic replay show no reachable work or hits; then soak/live-check removal.
- **Statistical equivalence route:** the patch remains active with nonzero work; run at least 20 randomized complete blocks per workload and representative supported environment.
- Do not pool environments; a one-platform result retires the patch only on that platform.
- Use the two predeclared marginal contrasts per patch with the no-patch mode as denominator.
- CPU and latency use within-block log ratios and paired 95% whole-block bootstrap CIs.
- Equivalence requires every interval inside ratio margin `[0.95, 1.05]`; memory uses paired replay-peak and retained-end RSS with a justified margin.
- Fix sample count before the final run; no optional stopping.
- Report exactly one outcome: **equivalent**, **not equivalent**, or **inconclusive**; failure to prove equivalence is not automatically a meaningful difference.
- All workload, metric, and environment intervals must pass, followed by a soak/live ecological check before removal.
