Files
rea/tests/fixtures/processReactiveScenario.mjs
morluto 7ee3f236a9 test: replace implementation lock-in with behavioural assertions (#498)
* fix(process): normalize reactive rendered-frame timestamps

A reactive `resize` action stamped `rendered_frames[].at_ms` with the raw
elapsed time while every other rendered frame used
`normalizeProcessElapsedTime`. Under the default 10ms time bucket the next
frame buckets down and appears to move backwards, so `parseProcessCapture`
rejected the entire capture with "rendered_frames: timestamps must be
ordered". No test combined a reactive resize with time bucketing, so the
path was never exercised.

Thread the scenario's bucket into the reactive effect host and normalize the
renderer call, matching what the scheduled-event resize path already did.
`dispatched_at_ms` and `captured_at_ms` stay raw on both paths, so this
changes only the one inconsistent clock.

Also replace the wall-clock-scheduled interactive PTY scenario with
terminal_text triggers. A fixed `at_ms` could fire before the child wrote
its prompt under host contention, dropping the input and the resize echo.
That rewrite is what surfaced this bug, and it now passes deterministically.

Replace the 11 `if (!capability.available) return;` guards across the PTY
suite with a shared it.skipIf gate. The old form reported a green pass with
zero assertions on any host lacking native PTY authority; skips are now
named and reported.

Verified by reverting only the normalization, which reproduces the
validation failure immediately.

* fix(install): add recovery guidance to version-mismatch failure

Every installer failure except one told the user what to do next. The
version-mismatch failure reported only that the installed version did not
match, with no remedy, which contradicts the requirement to keep
diagnostics actionable for mismatch locations.

Add a remedy in the same style as the neighbouring failures and drop the
exemption the test carried for it, so all ten installer failures now assert
they carry a recovery action.

* ci: repair stale curated Windows lane and unblind the duplication gate

The `windows-curated` job listed fifteen test files and nine of them no
longer existed, including six `processOwnership*` files moved to
`src/process/` in 4ecc7a72. Vitest silently drops unmatched paths, so the
job ran six files and reported success. Repoint the paths at their current
locations and add a test that fails when any listed path is renamed or
removed, so the lane cannot silently lose coverage again.

The duplication gate ignored `**/*.test.ts`, so it reported zero clones
across the test tree while running on every PR. Include test files, remove
the two largest duplicated clusters, and ratchet the threshold to the
measured result so the gate can no longer pass by not looking.

Run local tests with two workers instead of one. A single worker made a
full local run cost ~140s of wall time at ~100% CPU on a 10-core host,
which was the largest dev-cycle cost in the repository. Local now matches
the concurrency CI already proves green, and PTY scenarios moved to a
serial project because they contend for host terminal resources. Full local
suite: 140s to ~89s.

Regenerate the managed conformance manifest. Commit 4ecc7a72 edited
SKILL.md without refreshing the digest, so `npm run check:pr` has been
failing on main since that commit.

* test: replace implementation lock-in with behavioural assertions

Audit the suite for tests that cost maintenance without catching defects,
then remove the lock-in rather than the coverage.

Replace assertions that froze incidental detail:

- toolContracts.test.ts pinned group sizes and 50 lines of literal tool
  names, so any additive catalog change required a test edit. Replace with
  four structural invariants: global name uniquenes