Skip to content

feat(attest): choose the type checker, with tsrs support - #1706

Merged
ssalbdivad merged 7 commits into
mainfrom
attest-tsrs
Oct 22, 2026
Merged

ssalbdivad merged 7 commits into
mainfrom
attest-tsrs

Conversation

@ssalbdivad

Copy link
Copy Markdown
Member

Adds a checker: "tsjs" | "tsgo" | "tsrs" setting (--checker tsrs, ATTEST_checker='"tsrs"'). tsrs, the Rust port of TypeScript 7, serves the same native API as tsgo, so it only changes which package attest loads its API client, AST and compiler binary from.

Unset, attest uses tsrs when its binary resolves alongside TypeScript 7, else tsgo on TypeScript 7, else tsjs. An unknown checker, or one that doesn't match the installed TypeScript major, throws. tsrs is an optional peer dependency.

CI: this repo's typed tests now default to tsrs. A new attest@tsgo task in testTsVersions reruns them on tsgo, and the repo typecheck stays on tsc.

Measured locally (Linux x64, tsrs 0.18.0 vs tsgo 7.1.0-dev.20261006.1):

tsgo tsrs
ark/attest (63 passing) 62s 28s
ark/type (890 passing) 95s 61s
repo check time 30.8s 8.3s
repo instantiations 5,172,042 5,142,738

Locally, prChecks passed everything except buildDocs: docs pages exceeded Next.js's 60s render timeout on WSL, and docs pages don't import attest.

🤖 Generated with Claude Code

ssalbdivad and others added 3 commits October 21, 2026 17:56
tsrs, the Rust port of TypeScript 7, serves the same native API as tsgo, so
the `tsrs` option (`--tsrs` or `ATTEST_tsrs=true`) only changes which package
attest loads its API client, AST and compiler binary from. It's an optional
peer dependency resolved relative to attest, like typescript.

The TS 7.1 version guard is skipped for tsrs, whose version names the
upstream commit it ports. Instantiation counts still come from the
compiler's --extendedDiagnostics, which tsrs prints in the same format.

Measured against tsgo 7.1.0-dev.20261006.1 with tsrs
0.18.0-ts7.1.0-dev.20260929 (upstream b85298b6a81f), Linux x64:
- ark/attest: 63/63 passing on both, 28s vs 62s wall
- ark/type: 890/890 passing on both, 61s vs 95s wall
- whole repo --extendedDiagnostics: 5,142,738 vs 5,172,042 instantiations
  (0.6% lower), 8.3s vs 30.8s check time

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Replaces the tsrs boolean with one setting naming the checker, so future
backends don't each add a flag. Left unset, attest uses tsrs when it
resolves alongside TypeScript 7, else tsgo for TypeScript 7, else tsjs.
An explicit checker that doesn't match the installed TypeScript major, or
an unknown name, throws rather than silently falling back.

Since tsrs is now an attest devDependency, this repo's own suites default
to tsrs; ATTEST_checker='"tsgo"' runs them on tsgo (63/63 on both).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tsrs ships its binary in per-platform optional dependencies, so the
package installs without one on platforms it doesn't support, like the
Windows CI runner. Auto-detection now requires a platform package (or
TSRS_BINARY) to resolve.

Since this repo's typed tests now default to tsrs, the attest@tsgo CI task
reruns them on tsgo, which most consumers check with. The repo typecheck
stays on tsc.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new checker option is silently ignored when set through setup() — only --checker/ATTEST_checker take effect. Details inline.

Reviewed changes

Adds a checker: "tsjs" | "tsgo" | "tsrs" attest option selecting which TypeScript-compatible API and compiler binary attest analyzes with, defaulting to tsrs where its binary is installed, then tsgo on TypeScript 7, then tsjs.

  • checker config (ark/attest/config.ts) — new Checker type and checker: undefined default.
  • Checker selection (ark/attest/ts7/server.ts) — getChecker/hasTsrsBinary choose the compiler package that ast, API, createFileSystemLayer and tscPath load from, throwing on an unknown or version-mismatched checker.
  • Packaging (ark/attest/package.json, pnpm-lock.yaml) — tsrs devDependency plus an optional peer, with per-platform optional binaries.
  • CI (ark/repo/testTsVersions.ts) — typed tests default to tsrs, with a new attest@tsgo task rerunning them on tsgo.

ℹ️ New checker option isn't on the options page

ark/docs/content/docs/attest/options.mdx states it lists "the current defaults for all available options" and mirrors getDefaultAttestConfig, but the new checker: undefined default isn't included, so the --checker/ATTEST_checker surface ships undocumented.

Technical details
# checker missing from options.mdx

## Affected sites
- ark/docs/content/docs/attest/options.mdx:25-41 — defaults snippet omits `checker`
- ark/attest/config.ts:48-65 — `getDefaultAttestConfig` now includes `checker: undefined`

## Required outcome
- The options page reflects the new option. A short subsection like the existing `skipTypes`/`typeToStringFormat` ones would fit, since the default-selection behavior (tsrs → tsgo → tsjs) is not obvious from the name alone.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Comment thread ark/attest/ts7/server.ts Outdated
return checker
}

const checker = getChecker()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checker is resolved eagerly at module load, so setup({ checker: "tsgo" }) is silently ignored: @ark/attest's entry graph (index.ts → fixtures.ts → ts7/analyze.ts → here) evaluates before setup() writes ATTEST_CONFIG, and the derived ast/API/tscPath constants can't change afterward. Only --checker/ATTEST_checker work.

Technical details
# setup({ checker }) has no effect

## Affected sites
- ark/attest/ts7/server.ts:59 — `const checker = getChecker()` runs during module evaluation
- ark/attest/ts7/server.ts:62-80 — `compiler`, `ast`, `API`, `createFileSystemLayer`, `tscPath` are all module-level consts derived from `checker`
- ark/attest/fixtures.ts:9-12 — `setup()` only writes `process.env.ATTEST_CONFIG` when it is called
- ark/attest/config.ts:111-117 — `addEnvConfig` is what reads that env var
- ark/repo/mocha.globalSetup.ts:1-10 — the repo's own global setup imports `@ark/attest` (line 1) before calling `setup()` (line 6), so it can't set `checker` either

## Required outcome
- `setup({ checker })` must select the checker, or `checker` must not be offered on the setup-facing `AttestConfig` (with CLI/env-only usage made explicit). As written, the type advertises the option but the runtime ignores it, and a user following the docs gets the default checker with no warning.

## Suggested approach (optional)
- Resolve the checker lazily on first `TsgoServer.instance` access (turn `ast`/`API`/`createFileSystemLayer`/`tscPath` into getters), since `ATTEST_CONFIG` cannot exist before the module graph is evaluated.

Comment thread ark/repo/testTsVersions.ts Outdated
// recorded with the workspace's TS 7, whose type strings and counts differ
// type assertions default to tsrs where it's installed, but tsgo is what
// most consumers check with
"attest@tsgo": `ATTEST_checker='"tsgo"' pnpm testTypedLoose && cd ark/attest && ATTEST_checker='"tsgo"' pnpm test`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the two-line comment just above (type snapshots ... differ) originally explained the attest@6.0.3 task below it; inserting the new comment between them now leaves it reading as if it describes attest@tsgo. Move the new comment/task below it so each comment stays attached to the task it explains.

ssalbdivad and others added 4 commits October 21, 2026 19:03
The checker was read while @ark/attest's entry graph evaluated, before
setup() writes ATTEST_CONFIG, so setup({ checker }) was silently ignored.
The compiler is now loaded on first use: ast is populated in place, and
noTruncation and tscPath become getNoTruncation() and getTscPath().
writeAssertionData dispatches on getChecker(), so a tsjs/TS 7 mismatch
throws there too.

Also documents checker on the options page and keeps each
testTsVersions comment beside the task it explains.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	ark/attest/config.ts
#	ark/attest/ts7/server.ts
Its --tsconfig null dropped the repo's ark-ts customConditions, so
workspace packages resolved to their built out/ declarations. CI builds
first, but locally a stale build made the loose run fail on changes like
#1691's that hadn't been rebuilt. It now resolves source like every other
typed run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds tsrs support and the checker option (#1706).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ssalbdivad
ssalbdivad merged commit 3fddc2a into main Oct 22, 2026
1 check passed
@ssalbdivad
ssalbdivad deleted the attest-tsrs branch October 22, 2026 11:29
@github-project-automation github-project-automation Bot moved this from To do to Done (merged or closed) in arktypeio Oct 22, 2026
ssalbdivad added a commit that referenced this pull request Oct 22, 2026
main contributes attest 0.58.0: a `checker` option ("tsjs", "tsgo" or
"tsrs") and support for tsrs, a Rust port of TypeScript 7 serving tsgo's
API, which attest picks by default when its binary is installed alongside
TypeScript 7. server.ts now loads the compiler lazily, after setup() has
written attest's config, so `ast`, the no-truncation flag and the tsc path
are read on first use (getNoTruncation, getTscPath). testTsVersions gains
an attest@tsgo task, since the repo itself now checks with tsrs on the
platforms it ships for.

Conflicts:

- ark/attest/CHANGELOG.md: featherduster's Unreleased section stays on
  top, with main's 0.58.0 section below it.
- ark/attest/ts7/instantiations.ts: featherduster's countVariants, which
  returns the parsed counts directly, now passes getTscPath() in place of
  the removed tscPath.
- ark/docs/content/docs/attest/options.mdx: featherduster's options table
  replaces the getDefaultAttestConfig listing main added `checker` to, so
  `checker` gets a table row pointing at main's new section instead.
- package.json: featherduster's testTsCompat and bench (with
  benchJsonSchema), and main's testTypedLoose, which resolves workspace
  packages through the ark-ts condition.
- ark/docs/app/layout.tsx: featherduster's. main removed the ArkRegex
  release banner from its fumadocs layout, and featherduster's own layout
  never rendered one.
- pnpm-lock.yaml: featherduster's, reinstalled against the merged
  manifests, so the only change is tsrs and its platform binaries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done (merged or closed)

Development

Successfully merging this pull request may close these issues.

1 participant