Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,30 @@ jobs:
if: ${{ !cancelled() }}
run: python3 scripts/gap_snapshot.py --self-test

# Two halves of the same gate (#7582).
#
# `--self-test` unit-checks the checker. `--audit` runs the checker's
# OFFLINE half against the committed files: every known_failures.json
# entry must carry provenance (issue + date, #797), name a test that
# still exists, and — for gap-suite entries — be corroborated by
# `test-parity/gap_snapshot.json`, which is GENERATED and bidirectional.
# An entry absent from that snapshot is one the snapshot asserts passes,
# i.e. a suppression that has outlived its bug.
#
# This belongs on `lint` rather than only on `parity` because `parity` is
# TAG-gated: the live half of the ratchet fires after every merge it was
# meant to judge. `test_gap_diagchannel_3082_3084_3085_3086` sat here from
# 2026-07-04 and absorbed a real data-loss regression for six days (#7580);
# this step would have named it on the day it was added. Costs ~0.1s and
# runs no tests.
- name: Platform-aware parity allowlist self-test
if: ${{ !cancelled() }}
run: python3 scripts/parity_known_failures.py --self-test

- name: Parity allowlist ratchet (provenance + stale entries)
if: ${{ !cancelled() }}
run: python3 scripts/parity_known_failures.py --audit

# Moving-GC gate wiring. The GC gates are the ones this repo has most
# often found unable to fail (CLAUDE.md's four hazards), and every miss so
# far was caught by a human re-deriving it mid-incident. This asserts the
Expand Down Expand Up @@ -1739,7 +1759,12 @@ jobs:
cat test-parity/reports/parity_threshold_latest.md >> "$GITHUB_STEP_SUMMARY"
exit "$status"

- name: Check for new failures
# Bidirectional since #7582: red on a failure that is not allowed here,
# AND red on an allowlist entry whose test ran on this platform and
# PASSED. The second direction is the one that matters — the file was a
# pure suppression list, so a fixed test kept its entry forever and the
# entry silently absorbed that test's next regression (#7580).
- name: Check for new and stale failures
run: >-
python3 scripts/parity_known_failures.py
--report test-parity/reports/latest.json
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and LLVM for code generation.

**Current Version:** 0.5.1344
**Current Version:** 0.5.1345


## TypeScript Parity Status

Tracked via the gap test suite (`test-files/test_gap_*.ts`). Compared byte-for-byte against `node --experimental-strip-types`. Run via `./scripts/run_gap_tests.sh` (a thin wrapper over `run_parity_tests.sh --filter test_gap_` that builds the compiler itself and gates on no new untriaged failures).

**The oracle is Node `26.5.0`, pinned in `.node-version` at the repo root** — the single source of truth every CI workflow reads via `setup-node`'s `node-version-file`. **Run the gap suite against that exact version locally**, or your results won't match CI. The version is a *correctness input*, not an incidental toolchain detail: when node can't run a test (a feature newer than the pinned node), node exits non-zero, the harness classifies it `node_fail`, and the test is **silently dropped from the gate** rather than going red. CI sat on Node 22 while the suite grew Node 24/26 features, which hid 14 tests — all of Temporal, plus DisposableStack, Float16Array, and `Uint8Array` base64/hex (#6364). Node patch releases also change observable output (error-message text, `v8` heap fields), which is why the pin is exact. Raising it is a deliberate act: measure the failure delta under both oracles first, then triage what it exposes.
**The oracle is Node `26.5.1`, pinned in `.node-version` at the repo root** (the FILE is authoritative — this prose drifted once, #7599) — the single source of truth every CI workflow reads via `setup-node`'s `node-version-file`. **Run the gap suite against that exact version locally**, or your results won't match CI. The version is a *correctness input*, not an incidental toolchain detail: when node can't run a test (a feature newer than the pinned node), node exits non-zero, the harness classifies it `node_fail`, and the test is **silently dropped from the gate** rather than going red. CI sat on Node 22 while the suite grew Node 24/26 features, which hid 14 tests — all of Temporal, plus DisposableStack, Float16Array, and `Uint8Array` base64/hex (#6364). Node patch releases also change observable output (error-message text, `v8` heap fields), which is why the pin is exact. Raising it is a deliberate act: measure the failure delta under both oracles first, then triage what it exposes.

Two workflows are deliberately exempt and say so inline: `node-core-subset.yml` derives its Node from `test-compat/node-core/pinned-version.txt` (it runs Node's *own* test corpus, which must match its own Node line), and the two release workflows use Node purely as an npm *publishing* toolchain.

Expand Down
Loading
Loading