Adds the technical-writer skill from vercel/chat to .agents/skills, with a
.claude symlink to .agents so Claude Code finds it. AGENTS.md now asks agents
to use the skill for prose in this repo.
CONTRIBUTING.md gets a matching "Writing with AI coding agents" section.
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
Main moved the per-program report lines into zero-cost-compare.mjs and
added sharding and a baseline cache. The runtime-only and
nondeterministic verdicts now print through programLines, count as
compared in merged shard reports, and the runtime pack diff is skipped
when only recording a baseline cache.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A recorded baseline entry now holds a hash of its program's inputs: the
entry file and its relative imports (paths and contents) and the
optimization level. --baseline-cache uses an entry only when the program
still hashes the same, so a program or an import that changed since the
record builds its baseline, instead of a recorded build error or artifact
hash of the old sources settling the comparison as both-fail or identical.
Records take schema 2; older records are ignored.
The full gate takes 30 to 75 minutes on one Sandbox, which made it the
longest step of a validation round. It can now be split and merged:
- --shard=i/n splits the bench and corpus programs (the self-hosted
compiler runs in shard 1, or alone with --set=self), and
scripts/zero-cost-merge.mjs merges the shards' --json reports into one
verdict, recomputing the compile-time intervals over every shard.
- --record-baseline-cache records the baseline's artifact hashes once;
--baseline-cache skips the baseline build of every program whose
candidate artifacts hash the same. The record is tied to the built
baseline checkout, toolchain and paths.
- The candidate-source self build overlaps the comparison builds on
hosts with room for it.
pnpm test:sandbox can reuse a prepared snapshot's LLVM helper and runtime
pack (SCRIPTC_SANDBOX_NATIVE_REFERENCE) when their inputs are identical,
and retries rate-limited Sandbox creation with backoff.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Any change to the runtime's C sources makes every executable differ, so
the gate failed even when every program's IR and LLVM were byte-identical.
The gate now classifies each difference outside --allow:
- runtime-only: IR and LLVM identical, the same LLVM helper, runtime pack
objects that differ between the checkouts (bitcode alone records the
checkout path, so it does not count), and every symbol the executable
gains, loses or resizes defined by a changed runtime object. It passes
with a note that lists the changed runtime functions the program links
(from the release and speed bitcode, through llvm-dis) and the size
change.
- nondeterministic: the baseline builds the program again, and its two
builds differ in the same artifacts. It passes with a note.
- differs: anything else; it fails as before.
--strict fails runtime-only and nondeterministic programs too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parallel changes kept taking the same next corpus number (6992 twice, the
Node island programs renumbered several times). The harness never needed
the numbers: it discovers every entry by glob, and 818 programs already
have descriptive names. AGENTS.md now makes a name, without a number, the
convention for new programs and keeps the numbered ones as they are.
The two scripts that sampled programs by number skipped named programs.
They now key a named program by a stable hash of its name, so they sample
it at the same rate; the numbered programs they pick are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parallel branches kept picking the same numbers: dyn handle tags, SC
diagnostic codes, and the values the LLVM backend copies from runtime
enums.
- Diagnostic codes: codes.ts lists every active, retired and reserved code.
ScrDiagnostic.code is typed by it, and codes.test.ts fails on a code
without a row, a retired code in use, an unused row, or rows out of
order. The Node island codes open PRs already use are reserved.
- Dyn handle tags: a new tag is added by name to SCR_DYNH_NEW_TAGS and the
enum numbers it after the largest pinned value, so branches never pick
a number. The pinned values are unchanged; value 63, never assigned, is
listed as unassigned, and the test fails on any other gap.
- The backend's copies of ScrDynKind, ScrMessageKind, ScrBytesElem, the
closure function_kind bits (now named SCR_CLOSURE_KIND_* in C) and the
%ScrArr spare flags are checked against their C declarations.
- scripts/registry-claims.mjs lists the codes and pinned tags open PRs
claim and reports collisions; it finds handle tag 81 claimed by three
open PRs today.
Every numeric value is unchanged, so IR, LLVM and executables are
byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pnpm node-compat fetched Node's docs on every run, even though only the
classification changes between pins. pnpm node-compat --local now
reclassifies the committed ledger rows from the current sources and
rewrites the ledger and the public artifact, the same files a fetching
run writes while the pin is unchanged. scripts/regen-generated.mjs uses
it after a merge: for each generated file still in conflict it takes the
merged-in branch's version, regenerates the surface manifest and the
compatibility files from the merged sources, and stages them, so these
files never need a hand merge.
node-v24-backlog.json is a pure function of the committed ledger, and only
the backlog command read it. Its summary counts changed with every
classification change, so concurrent compatibility changes conflicted on
them. pnpm node-compat:backlog now builds the backlog in memory from
node-v24-internal.json with the same output, the generator no longer
writes the file, and the local check fails if a merge brings it back.
The Limitations page partials keep one sentence per line so edits to
different sentences merge, but AGENTS.md's general Markdown rule asks
for paragraphs on one line, and changes that followed it conflicted with
the split text. AGENTS.md now names the partials as the exception, and
limitations-partials.mjs gains a check, run by pnpm lint, that fails on a
partial line holding two sentences, and a fix mode that splits such lines.
The one partial that held several sentences per line is split; Markdown
joins the lines, so the page renders the same.
Each limitations partial held its whole text on one line (map-and-set.mdx
was a single 1,080-character line), so any two edits to the same partial
conflicted. The partials now put one sentence per line, with a bullet's
continuation lines indented two spaces. Markdown joins the lines, so the
rendered pages are unchanged.
scripts/limitations-partials.mjs reads a labeled bullet's indented
continuation lines as part of the bullet when it splits and joins the page,
and AGENTS.md states the convention.
Every change that adds a corpus program also added its CI costs to
tests/harness/corpus-costs.json. The table is sorted by program name and
programs are numbered in sequence, so concurrent changes inserted lines at
the same place and conflicted. A change now writes
tests/harness/corpus-costs/<program>.json ({ "plain": ms, "san": ms }).
The shard loader applies these files over the table, and
scripts/ci-corpus-costs.mjs folds them into the table and deletes them when
it refreshes the costs from CI logs. With no per-program files the table and
the shard assignment are unchanged.
node-v24-compatibility-meta.json held two values derived from the public
compatibility artifact: a content hash for the data URL and its row count.
Every compatibility change rewrote the hash line, so concurrent changes
conflicted on it. next.config.mjs now computes both from the committed
artifact and passes them to the page through Next's build-time env, with
the same values. The generator no longer writes the file, and its local
check compares the public artifact itself.
--cachegrind now also runs differing corpus executables (without
arguments, accepting intentional non-zero exits), so emitter changes that
only touch corpus programs get per-function instruction deltas. AGENTS.md
mentions the dynamic-tier symbol rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/zero-cost-gate.mjs compiles a fixed good-code set (the runtime
benchmark workloads, the self-hosted compiler, and the TypeScript corpus)
with a baseline and a candidate checkout. It requires byte-identical IR,
LLVM and release executables, and names the first differing IR function,
LLVM function or executable symbol when something changes. Programs that
match the change's pattern signature (--allow) may differ. It also checks
compile time (paired builds, bootstrap interval), binary size, optional
per-function cachegrind instruction counts, and the two-tier I3 symbol
rule: no executable gains dynamic-tier runtime symbols, and fully typed
benchmark workloads define none.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/content/docs/limitations.mdx now holds the frontmatter, the
headings, the anchor spans and one <include> line per partial. The text
moves unchanged to docs/content/limitations/: one file per labeled
bullet (<section>/<label>.mdx) and one per section's other text
(<section>.mdx). Edits to different bullets no longer touch adjacent
lines of one file.
remarkDocsConventions splices the included partials into the page and
joins the lists that consecutive bullet partials contribute, so the page,
its Markdown twin and the search index render as before. The route tests
read the page with its partials inlined. A page that includes partials
takes its last-modified date, used by the sitemap, from the newest commit
to the page or any of its partials.
docs/scripts/limitations-partials.mjs joins the partials back into one
file, splits a single-file page, and merges a branch's edits to the
single-file page into the partials.
The new docs page (/docs/threads) explains @scriptc/threads: a runnable
example that publishes a million-order ledger and sends it to four
workers, verified under Node.js 24 and as a scriptc executable; what
publish accepts and refuses, and that a refused publish leaves the graph
unchanged; the frozen-object TypeErrors of the write guard; a comparison
with Node's structured clone (constant-time sends, preserved classes and
identity, immortal objects) and the three rules that make a program
behave the same under both; the automatic sharing of deeply frozen
untyped data; and the cost model. The limitations page gains a Published
graphs section (immortality, class and identity differences, write-check
evaluation order, private fields) and links the new page from the
worker-threads section.
This is the first page added since the migration, so the route-test
fixture now accepts pages without a legacy URL, and the agent guide's
checklist for new pages names the fixture.
- Add native worker execution with isolated module state, structured messages, and lifecycle controls.
- Support shared buffers and integer atomics with coordinated runtime ownership and cancellation.
- Extend compiler, runtime-pack, differential, and compatibility coverage for native concurrency.
- Enforce oxlint and oxfmt for owned JavaScript and TypeScript with independent CI checks.
- Preserve compiler import boundaries and protected fixtures while cleaning up lint findings.
- Standardize source formatting and validate import, fixture, and embedded-source protections.
- Remove C emission, debugging options, and automatic backend fallback.
- Complete LLVM lowering and native bootstrap coverage across supported targets.
- Link executables and libraries with precompiled C runtime packs, including iOS and Android.
- Pin GNU runtime packs to glibc 2.36 Zig targets and reject incompatible imports.
- Provision verified Zig builds and exercise published artifacts on Debian Bookworm.
Fixes#349
Co-authored-by: Cruel <383999+Cruel@users.noreply.github.com>
* Expand LLVM native output targets
- Add owned helper and runtime-pack contracts for macOS x64, Linux glibc/musl, Windows x64, and WASI.
- Generalize LLVM target selection, package validation, linker plans, and release/CI matrices.
- Document linker boundaries and add focused native-output and runtime-pack coverage.
* Pin Windows LLVM helper CI to VS 2022
The official LLVM archive needs the Visual Studio 2022 CMake generator, which is not guaranteed by windows-latest.
* Align bootstrap cache with LLVM runtime-pack builds
Use the same target-specific helper and linker identity before and after compiler loading so routed executable cache hits remain lightweight.
* Install Windows LLVM CI tools with Chocolatey
windows-2022 includes Visual Studio but not winget; use its available Chocolatey bootstrap for CMake and Ninja.
* Prevent Zig version probes from leaving runtime-pack objects
Run runtime-pack compiler version probes in a private temporary directory and remove the accidental tracked WASI a.o file.
* Use 7-Zip for Windows LLVM setup
Extract the official LLVM development archive with two-stage 7-Zip instead of Windows tar.exe, which timed out while materializing the toolchain tree.
* Define ssize_t for the MSVC runtime pack
Clang's MSVC target does not expose POSIX ssize_t through sys/types.h; define the pointer-sized runtime type without affecting MinGW.
* Build the Windows runtime pack with Zig
Use the MinGW-compatible Windows sysroot required by the runtime while retaining COFF helper output and installing Zig in the Windows native CI lane.
* Give macOS LLVM differential shard time to finish
Shard 1 passed its setup and focused contracts but was cancelled during its cold LLVM differential slice at the 20-minute job limit.
* Warn on non-null assertions
- Surface non-null assertions during linting without making them blocking.
- Preserve existing assertion sites for opportunistic cleanup.
* Classify internal compiler errors
- Export InternalCompilerError and migrate compiler invariant throws without changing messages.
- Rename the native cache test to match cc.ts and update test scheduling references.
- Document test placement by unit, package integration, and cross-package scope.
* Fix internal compiler error classification
- Retain representative Darwin kqueue coverage in the default gate.
- Schedule native runtime tests by host and make Linux clang invocations portable.
- Resolve canonical OCI manifest digests for direct and indexed images.
- RELEASING.md documents the lockstep three-package prepare flow and the marked-changelog convention
- CHANGELOG.md starts with an Unreleased section and the marked 0.0.1 entry that becomes the GitHub release body
- AGENTS.md states repo-wide build/test conventions and defers docs-site specifics to docs/AGENTS.md
- scripts/sync-versions.mjs stamps runtime and compiler from the CLI version; the workflow's sync check now hints at it
- release.yml gains a github-release job that tags v<version> after a successful publish, never gating npm