@redue/cli 0.1.0-alpha.17 → 0.1.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/README.md +9 -5
- package/bin/redue.mjs +26 -9
- package/docs/user/agents.md +11 -0
- package/docs/user/configuration.md +6 -0
- package/docs/user/direct-typescript.md +62 -5
- package/docs/user/getting-started.md +7 -7
- package/docs/user/node-script.md +153 -0
- package/docs/user/pilot.md +6 -5
- package/docs/user/supported-projects.md +26 -15
- package/docs/user/tests-direct.md +13 -3
- package/package.json +2 -2
- package/src/agent-integration.mjs +16 -8
- package/src/claude-hook.mjs +119 -34
- package/src/cli.mjs +34 -16
- package/src/daemon.mjs +23 -8
- package/src/declared-plan.mjs +9 -6
- package/src/direct-typescript-probe.mjs +5 -3
- package/src/direct-typescript.mjs +58 -11
- package/src/glob.mjs +8 -0
- package/src/index.mjs +10 -4
- package/src/node-onboarding.mjs +117 -37
- package/src/node-script.mjs +362 -0
- package/src/npm-integrity.mjs +124 -0
- package/src/npmrc.mjs +16 -0
- package/src/plan-worker.mjs +4 -1
- package/src/pnpm-inputs.mjs +63 -35
- package/src/pnpm-shim-templates.json +180 -0
- package/src/pnpm-shims.mjs +54 -0
- package/src/pnpm-typecheck-probe.mjs +11 -6
- package/src/presentation.mjs +8 -1
- package/src/test-direct.mjs +103 -21
- package/src/test-recorder.cjs +101 -14
- package/src/typescript-input-facts.mjs +7 -7
- package/src/typescript-invocation.mjs +92 -0
- package/src/typescript-list.mjs +2 -2
- package/src/typescript-qualification.mjs +8 -9
- package/src/workspace-manifests.mjs +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,106 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.19 — 2026-10-24
|
|
4
|
+
|
|
5
|
+
A general recipe for typecheck and lint scripts that the strict recipes do not
|
|
6
|
+
take. Test scripts stay on the direct test recipe (Vitest, Jest).
|
|
7
|
+
|
|
8
|
+
- `redue init` tries the strict recipes first, then writes a general check
|
|
9
|
+
(`"qualification": "node-script-v1"`) for a root typecheck or lint script.
|
|
10
|
+
`redue run` runs the script through the project's package manager (npm,
|
|
11
|
+
pnpm 9-12 or Yarn with the `node-modules` linker) with REDUE's recorder in
|
|
12
|
+
every Node process, on macOS and Linux. The input is the whole checkout but
|
|
13
|
+
`.git`, `node_modules` and runner caches, plus every workspace
|
|
14
|
+
`node_modules` observed as installed files, the package manager and its
|
|
15
|
+
version, and the environment. See docs/user/node-script.md.
|
|
16
|
+
- pnpm's launchers are trusted only when their text matches a template a pnpm
|
|
17
|
+
release writes (pnpm 8.0 to 12.14). The pnpm executable, Corepack's
|
|
18
|
+
pnpm-native included, is toolchain; its configuration files are kept by
|
|
19
|
+
content.
|
|
20
|
+
- A run that starts a program REDUE does not record is UNVERIFIED and the
|
|
21
|
+
reason names it: native programs from installed packages (esbuild, turbo,
|
|
22
|
+
tsgolint, biome), git, find, and shells that read startup files.
|
|
23
|
+
- `status` and the hook's skip message name the recipe that made the receipt
|
|
24
|
+
("general recipe"). The Claude Code hook recognizes lint commands as it does
|
|
25
|
+
typecheck and test commands: `npm run lint`, `pnpm lint`, and for a script
|
|
26
|
+
that is one plain command, that command and its `npx` form.
|
|
27
|
+
- In the census of 108 public TypeScript repos, the general recipe qualifies
|
|
28
|
+
23 typecheck and 21 lint scripts (both recorded runs clean, CURRENT after
|
|
29
|
+
the second). Of the scripts whose runs start only Node and the package
|
|
30
|
+
manager's own launchers (35 typecheck, 37 lint, measured with strace), init
|
|
31
|
+
proposes and observes about 21 and 22, and 18 of each qualify. The rest:
|
|
32
|
+
init does not pick script names such as `tsc:build`, fails in monorepos
|
|
33
|
+
over 50 packages, or refuses source directory links and custom install
|
|
34
|
+
setups; plans with submodules or dangling links are unavailable.
|
|
35
|
+
- Known limits: on macOS, pnpm 12's temporary files in the project root can
|
|
36
|
+
arrive as an event on the root and make a run UNVERIFIED. Writes into
|
|
37
|
+
`node_modules` during a run make it UNVERIFIED, except pnpm's workspace
|
|
38
|
+
state and vue-tsc's global types, which stay inputs and are kept as the run
|
|
39
|
+
left them. A workspace's recording checks now leave out nested
|
|
40
|
+
`node_modules`, so `redue init` rewrites them once.
|
|
41
|
+
|
|
42
|
+
- Contributors: `census.mjs --product` applies the product's own rule and
|
|
43
|
+
lists the files an unstable run touched; the eval kills a timed-out
|
|
44
|
+
command's whole process group; the agent eval has lint tasks.
|
|
45
|
+
|
|
46
|
+
## 0.1.0-alpha.18 — 2026-10-23
|
|
47
|
+
|
|
48
|
+
Typecheck in more project shapes, and pnpm test reuse on Linux. In the census
|
|
49
|
+
of 108 public TypeScript repos, the ones `init` makes ready went from 8 to 11
|
|
50
|
+
for typecheck (the census clones each repo's current head, so one or two
|
|
51
|
+
repos move between runs) and stayed at 22 for tests.
|
|
52
|
+
|
|
53
|
+
- pnpm test checks are reused on Linux. A recorded run accepts an installed
|
|
54
|
+
file hard-linked into the pnpm store the install recorded, when the store
|
|
55
|
+
holds it at its content address (pnpm names store files by their sha512).
|
|
56
|
+
Links anywhere else stay UNVERIFIED. Each file is hashed once; REDUE keeps
|
|
57
|
+
its identity and store path in its state and hashes it again only when the
|
|
58
|
+
identity changes. A 46 MB install takes about 160 ms to check the first
|
|
59
|
+
time. Limit: an in-place edit of an installed file in another project that
|
|
60
|
+
shares the store file is not seen until the next recorded run.
|
|
61
|
+
|
|
62
|
+
- Typecheck scripts in more shapes. A script of `tsc --noEmit` runs with
|
|
63
|
+
`-p`/`--project`, `--skipLibCheck` or `--pretty`, in any argument order,
|
|
64
|
+
qualifies for the direct npm recipe and the pnpm contract. A chain of such
|
|
65
|
+
runs joined by `&&` becomes one check per run (`typecheck.1`,
|
|
66
|
+
`typecheck.2`); the hook skips the script only when every run is CURRENT
|
|
67
|
+
and otherwise runs the stale ones through `redue run`. `check-types` joins
|
|
68
|
+
the recognized script names.
|
|
69
|
+
- The hook acts on a typecheck script's form only while the script in
|
|
70
|
+
package.json still has exactly the configured `tsc` runs. Before, a script
|
|
71
|
+
changed to `tsc --noEmit && eslint .` was rewritten to `redue run
|
|
72
|
+
typecheck`, which ran tsc alone.
|
|
73
|
+
- Without a typecheck script, `init` proposes a `tsc --noEmit` check for a
|
|
74
|
+
root `tsconfig.json` (direct npm recipe, pnpm) and for each pnpm workspace
|
|
75
|
+
package with one, unless a script runs a TypeScript checker in another form
|
|
76
|
+
(`tsc -b`, `vue-tsc`, ...). package.json is not changed; the check is
|
|
77
|
+
written only when the contract holds.
|
|
78
|
+
- The pnpm contract no longer needs `include: ["src"]`. Its source inputs are
|
|
79
|
+
the directories the config's `include` covers, as TypeScript computes them
|
|
80
|
+
for new files, minus `node_modules`. `exclude` entries stay inputs, since an
|
|
81
|
+
import can still reach an excluded file. A config extended from an installed
|
|
82
|
+
package is an installed input.
|
|
83
|
+
- Fixed: a config with three or more pnpm or test checks never got a
|
|
84
|
+
synchronized answer. The observer dropped control requests over 4 KB, and a
|
|
85
|
+
sync request carries about 1.5 KB of context digests per check; status
|
|
86
|
+
showed "Unexpected end of JSON input" for every check. The limit is 1 MiB.
|
|
87
|
+
|
|
88
|
+
- The direct npm TypeScript recipe takes any TypeScript 5.x or 6.0, not only
|
|
89
|
+
the five reviewed releases. Another release qualifies when package-lock.json
|
|
90
|
+
records the registry's `typescript` at that version with an integrity
|
|
91
|
+
(sha512, or sha1 from registries that record only sha1), npm's cache holds
|
|
92
|
+
the tarball under it, and the installed package is exactly the tarball's
|
|
93
|
+
files. Nothing is downloaded; a missing tarball
|
|
94
|
+
keeps the check recording-only with `npm-tarball-uncached`. The check takes
|
|
95
|
+
about 100 ms per full probe (TypeScript 5.x and 6.0 tarballs, 120-140 files).
|
|
96
|
+
CI runs the direct contract suite against 5.0.4, 5.1.6, 5.2.2, 5.3.3, 5.4.5,
|
|
97
|
+
5.5.4, 5.7.3 and 5.8.3.
|
|
98
|
+
|
|
99
|
+
- Contributors: `npm test` runs up to four test files at a time, keeping two
|
|
100
|
+
cores free (a 3-core CI macOS runner runs one at a time), and takes about
|
|
101
|
+
6 minutes on the owner's Mac (was 19.6). The two TypeScript 6 fixture
|
|
102
|
+
suites are separate files so they run side by side.
|
|
103
|
+
|
|
3
104
|
## 0.1.0-alpha.17 — 2026-10-22
|
|
4
105
|
|
|
5
106
|
Workspaces and package managers beyond npm. In the census of 108 public
|
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ it; relevant source edits make it stale. [Run the reproducible demo](docs/contri
|
|
|
37
37
|
|
|
38
38
|
## Install the alpha
|
|
39
39
|
|
|
40
|
-
The opt-in pilot uses **0.1.0-alpha.
|
|
40
|
+
The opt-in pilot uses **0.1.0-alpha.18**. Follow the
|
|
41
41
|
[fixed-version pilot guide](docs/user/pilot.md) for supported projects, setup,
|
|
42
42
|
updates and voluntary feedback. No external usage results are claimed yet.
|
|
43
43
|
|
|
@@ -76,10 +76,14 @@ Start with ordinary `status`. When it cannot establish caller context, use
|
|
|
76
76
|
**Synchronization can cost more than rerunning a cheap check, particularly on
|
|
77
77
|
Windows.** REDUE does not choose or execute that tradeoff for you.
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
`init` tries the strict recipes first: the [direct compiler recipe](docs/user/direct-typescript.md)
|
|
80
|
+
for npm typechecks, the pnpm and Yarn TypeScript recipes, and the
|
|
81
|
+
[direct test recipe](docs/user/tests-direct.md). A root typecheck or lint
|
|
82
|
+
script none of them takes can use the [general recipe](docs/user/node-script.md),
|
|
83
|
+
which runs the script through the package manager and records every Node
|
|
84
|
+
process; a script that starts another program (git, esbuild, turbo) stays
|
|
85
|
+
UNVERIFIED and the reason names it. Test scripts use the direct test recipe
|
|
86
|
+
(Vitest, Jest); other test scripts stay recording-only.
|
|
83
87
|
|
|
84
88
|
## Connect your agent (experimental)
|
|
85
89
|
|
package/bin/redue.mjs
CHANGED
|
@@ -4,7 +4,9 @@ import {mark,traceBase,traceContext,traceEnvironment,traceId} from '../src/decis
|
|
|
4
4
|
traceBase({...traceContext(),request:traceId(),work:'client'});
|
|
5
5
|
mark('client.loaded');
|
|
6
6
|
import {directCompiler,directQualification,directEnvironment,directInterpretation} from '../src/direct-typescript.mjs';
|
|
7
|
+
import {runArgv,tscRun} from '../src/typescript-invocation.mjs';
|
|
7
8
|
import {testEnvironment,testRunnerAt,testsInterpretation,testsQualification} from '../src/test-direct.mjs';
|
|
9
|
+
import {scriptEnvironment,scriptInterpretation,scriptKinds,scriptQualification} from '../src/node-script.mjs';
|
|
8
10
|
import os from 'node:os';
|
|
9
11
|
import path from 'node:path';
|
|
10
12
|
import {createHash} from 'node:crypto';
|
|
@@ -26,7 +28,7 @@ const help=`REDUE ${version}
|
|
|
26
28
|
Usage: redue [--config FILE] [--state-dir DIR] COMMAND [OPTIONS]
|
|
27
29
|
|
|
28
30
|
Commands:
|
|
29
|
-
init [--dry-run] [--workspace NAME] [--check KIND] [--recipe typescript-direct|tests-direct]
|
|
31
|
+
init [--dry-run] [--workspace NAME] [--check KIND] [--recipe typescript-direct|tests-direct|node-script]
|
|
30
32
|
Discover existing scripts; optionally select one workspace/check
|
|
31
33
|
agent setup codex|claude [--dry-run|--apply] [--json]
|
|
32
34
|
agent doctor [codex|claude] [--json]
|
|
@@ -245,6 +247,7 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
245
247
|
const npmDirect=check.qualification===directQualification;
|
|
246
248
|
const pnpmTypecheck=check.qualification==='pnpm-tsc-v1';
|
|
247
249
|
const testsDirect=check.qualification===testsQualification;
|
|
250
|
+
const generalScript=check.qualification===scriptQualification;
|
|
248
251
|
if(check.script&&check.command&&!pnpmTypecheck&&!npmDirect&&!testsDirect)
|
|
249
252
|
error(`${check.name}: choose script or command, not both`);
|
|
250
253
|
const manager=publicConfig.packageManager;
|
|
@@ -254,10 +257,15 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
254
257
|
[`@which:${manager}`,'run',check.script]:null;
|
|
255
258
|
const npmAutomatic=check.qualification==='typescript-noemit-v1';
|
|
256
259
|
const yarnWorkspace=check.qualification==='yarn-workspace-tsc-v1';
|
|
257
|
-
if(check.qualification&&!npmAutomatic&&!npmDirect&&!yarnWorkspace&&!pnpmTypecheck&&!testsDirect)
|
|
260
|
+
if(check.qualification&&!npmAutomatic&&!npmDirect&&!yarnWorkspace&&!pnpmTypecheck&&!testsDirect&&!generalScript)
|
|
258
261
|
error(`${check.name}: unknown qualification contract`);
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
// The general recipe runs the root package script through the package manager.
|
|
263
|
+
if(generalScript&&(!['npm','pnpm','yarn'].includes(manager)||!check.script||check.command||check.cwd&&check.cwd!=='.'||
|
|
264
|
+
check.workspace||!scriptKinds.includes(check.kind)))
|
|
265
|
+
error(`${check.name}: the general recipe needs a root typecheck, test or lint script, without command or cwd`);
|
|
266
|
+
if(npmDirect&&(manager!=='npm'||check.cwd&&check.cwd!=='.'||!Array.isArray(check.command)||
|
|
267
|
+
check.command[0]!=='@node'||check.command[1]!=='@typescript-compiler:.'||
|
|
268
|
+
!tscRun({},{script:null,args:check.command.slice(2)}).run?.noEmit))
|
|
261
269
|
error(`${check.name}: direct recipe requires its explicit local compiler command`);
|
|
262
270
|
// The script's own arguments follow the runner; qualification compares them with the script.
|
|
263
271
|
if(testsDirect&&(!['npm','pnpm','yarn'].includes(manager)||!check.script||check.cwd&&check.cwd!=='.'&&!check.workspace||!Array.isArray(check.command)||
|
|
@@ -270,25 +278,32 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
270
278
|
check.command[1]!=='workspace'||check.command[2]!==check.workspace||
|
|
271
279
|
check.command[3]!=='run'))
|
|
272
280
|
error(`${check.name}: Yarn workspace qualification needs its discovered workspace command`);
|
|
273
|
-
if(pnpmTypecheck&&(manager!=='pnpm'||!
|
|
281
|
+
if(pnpmTypecheck&&(manager!=='pnpm'||!Array.isArray(check.command)||
|
|
274
282
|
check.command[0]!=='@node'||
|
|
275
283
|
check.command[1]!==`@typescript-bin:${check.cwd||'.'}`||
|
|
276
284
|
check.workspace&&check.cwd==='.'||
|
|
277
|
-
!check.command.slice(2).
|
|
285
|
+
!tscRun({},{script:null,args:check.command.slice(2)}).run))
|
|
278
286
|
error(`${check.name}: pnpm qualification needs its discovered standalone TypeScript command`);
|
|
279
287
|
const reason=check.kind==='test'?'test runtime, transforms and cache inputs need review':
|
|
280
288
|
check.kind==='lint'?'lint plugins, config and resolver inputs need review':
|
|
281
289
|
check.kind==='build'?'build environment and generated inputs need review':
|
|
282
290
|
'check inputs need review';
|
|
283
|
-
|
|
291
|
+
// A chained script has one check per tsc run: each check's run counts them,
|
|
292
|
+
// so a run added to or removed from the script invalidates them all.
|
|
293
|
+
const runCount=(npmDirect||pnpmTypecheck)&&check.script?publicConfig.checks.filter(other=>
|
|
294
|
+
other.qualification===check.qualification&&other.script===check.script&&
|
|
295
|
+
(other.cwd||'.')===(check.cwd||'.')&&(other.workspace||null)===(check.workspace||null)).length:1;
|
|
296
|
+
if(runCount>16)error(`${check.name}: more than 16 checks for script ${check.script}`);
|
|
297
|
+
const run=npmDirect||pnpmTypecheck?runArgv({script:check.script??null,args:check.command.slice(2),count:runCount}):null;
|
|
298
|
+
const autoProbes=npmDirect?[['@node','@vstate/direct-typescript-probe','@project',...run]]:npmAutomatic?[['@node','@vstate/typescript-contract-probe',
|
|
284
299
|
'@project',check.script,'@which:npm']]:yarnWorkspace?
|
|
285
300
|
[['@node','@vstate/yarn-workspace-typecheck-probe','@project',
|
|
286
301
|
check.workspace,check.command[4],'@which:yarn']]:pnpmTypecheck?
|
|
287
302
|
[['@node','@vstate/pnpm-typecheck-probe','@project',
|
|
288
|
-
check.workspace||'.'
|
|
303
|
+
check.workspace||'.',...run]]:[];
|
|
289
304
|
const windowsContext=process.platform==='win32'?
|
|
290
305
|
['ComSpec','COMSPEC','PATHEXT','USERPROFILE']:[];
|
|
291
|
-
const autoEnvironment=npmDirect?directEnvironment:testsDirect?testEnvironment:npmAutomatic?{variables:['NODE_OPTIONS','NODE_PATH','CI','HOME',
|
|
306
|
+
const autoEnvironment=npmDirect?directEnvironment:testsDirect?testEnvironment:generalScript?scriptEnvironment(manager):npmAutomatic?{variables:['NODE_OPTIONS','NODE_PATH','CI','HOME',
|
|
292
307
|
'NODE_ENV','BASH_ENV','ENV',...windowsContext],prefixes:['npm_config_','DYLD_','TSGO_'],
|
|
293
308
|
pathExecutables:['node','npm'],executableIdentity:true}:yarnWorkspace?
|
|
294
309
|
{variables:['NODE_OPTIONS','NODE_PATH','CI','HOME','NODE_ENV','BASH_ENV','ENV',...windowsContext],
|
|
@@ -310,9 +325,11 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
310
325
|
coverageReasons:check.coverageReasons||Object.fromEntries(
|
|
311
326
|
categories.map(category=>[category,reason])),
|
|
312
327
|
qualification:check.qualification||null,script:check.script||null,
|
|
328
|
+
...(runCount>1?{runCount}:{}),
|
|
313
329
|
...(npmAutomatic?{qualificationInterpretation:'npm-launcher-withheld@1'}:{}),
|
|
314
330
|
...(npmDirect?{qualificationInterpretation:directInterpretation}:{}),
|
|
315
331
|
...(testsDirect?{qualificationInterpretation:testsInterpretation}:{}),
|
|
332
|
+
...(generalScript?{qualificationInterpretation:scriptInterpretation}:{}),
|
|
316
333
|
workspace:check.workspace||null,kind:check.kind||null};
|
|
317
334
|
});
|
|
318
335
|
const runtime={schema:1,provider:'declared-project@1',root,state,checks};
|
package/docs/user/agents.md
CHANGED
|
@@ -122,6 +122,17 @@ post-scripts. In every other case the command runs as typed: turbo caches its
|
|
|
122
122
|
own results, so the hook never rewrites it. Filters (`--filter`) and nx are not
|
|
123
123
|
matched.
|
|
124
124
|
|
|
125
|
+
For a typecheck check that runs the compiler, the script's forms act only when
|
|
126
|
+
the script in package.json still has exactly the configured runs: one `tsc`
|
|
127
|
+
run per check with the same arguments, and no pre- or post-script. Otherwise
|
|
128
|
+
the command runs as typed. A script that chains `tsc` runs with `&&` has one
|
|
129
|
+
check per run, `typecheck.1`, `typecheck.2` and so on (see
|
|
130
|
+
[direct TypeScript](direct-typescript.md#script-forms)); each run's own
|
|
131
|
+
`npx tsc ...` form matches its check. The hook skips the script when all its
|
|
132
|
+
runs are CURRENT, PASS and `reuse_eligible`, and otherwise rewrites it to
|
|
133
|
+
`redue run` of the runs that are not, in the script's order, joined by `&&`.
|
|
134
|
+
In a turbo or `pnpm -r` fan-out, a package's script counts only the same way.
|
|
135
|
+
|
|
125
136
|
Each form may end with `2>&1` and then one `| tail -n N`, `| head -n N`,
|
|
126
137
|
`| tail -N` or `| head -N`. It may also be the first command of a `;` or `&&`
|
|
127
138
|
chain. Nothing else matches. Each form has its own `if` rule, so other Bash
|
|
@@ -30,6 +30,8 @@ out of version-controlled configuration.
|
|
|
30
30
|
|
|
31
31
|
For the explicit direct compiler choice and generated exact argv, see
|
|
32
32
|
[direct TypeScript](direct-typescript.md). Existing script receipts cannot satisfy it.
|
|
33
|
+
A general check (`"qualification": "node-script-v1"`) has a `script` and no
|
|
34
|
+
`command`; see the [general recipe](node-script.md).
|
|
33
35
|
|
|
34
36
|
## Arbitrary commands
|
|
35
37
|
|
|
@@ -56,6 +58,10 @@ Advanced explicit contracts may declare `generatedInputs`, `installedInputs`, na
|
|
|
56
58
|
reviewed escape hatches, not onboarding requirements. A coverage rationale cannot
|
|
57
59
|
override unsupported storage, unresolved links, missing inputs, or observation failure.
|
|
58
60
|
|
|
61
|
+
A chained typecheck script gets one generated check per `tsc` run, all with
|
|
62
|
+
the script's name (see [script forms](direct-typescript.md#script-forms)). A
|
|
63
|
+
proposed check for a project without a typecheck script has no `script`.
|
|
64
|
+
|
|
59
65
|
Input patterns are relative to the project root. They cannot name a `.git`
|
|
60
66
|
directory, because REDUE does not observe one; `!.git/**` is fine.
|
|
61
67
|
|
|
@@ -4,8 +4,10 @@ This check means: the reviewed local TypeScript compiler completed the configure
|
|
|
4
4
|
check against declared, observed inputs and relevant execution context. It does
|
|
5
5
|
not mean npm or npm lifecycle scripts completed.
|
|
6
6
|
|
|
7
|
-
For a supported single-package npm project with
|
|
8
|
-
|
|
7
|
+
For a supported single-package npm project with a typecheck script of `tsc`
|
|
8
|
+
runs (see [script forms](#script-forms)) or no typecheck script and a root
|
|
9
|
+
`tsconfig.json`, installed dependencies, Node 22/24 and TypeScript 5.x or 6.0
|
|
10
|
+
(see [compiler identity](#compiler-identity)):
|
|
9
11
|
|
|
10
12
|
```sh
|
|
11
13
|
redue init --recipe typescript-direct --check typecheck --dry-run
|
|
@@ -33,9 +35,64 @@ A generated check contains:
|
|
|
33
35
|
|
|
34
36
|
`script` identifies the reviewed source recipe; `command` is what actually runs:
|
|
35
37
|
the resolved Node executable and local TypeScript implementation, with exact argv
|
|
36
|
-
and no shell.
|
|
37
|
-
without its outer compile-cache-enabling shim
|
|
38
|
-
|
|
38
|
+
and no shell. The entry is `lib/_tsc.js` where the package has one (5.7 and
|
|
39
|
+
later), without its outer compile-cache-enabling shim, and `lib/tsc.js`
|
|
40
|
+
otherwise. No compiler is fetched or bundled.
|
|
41
|
+
|
|
42
|
+
## Compiler identity
|
|
43
|
+
|
|
44
|
+
The entire installed `node_modules/typescript` must be an official package,
|
|
45
|
+
byte for byte, in one of two ways:
|
|
46
|
+
|
|
47
|
+
- TypeScript 5.5.2, 5.6.3, 5.9.3, 6.0.2 or 6.0.3: its files match the digest
|
|
48
|
+
REDUE ships for that release.
|
|
49
|
+
- Any other TypeScript 5.x or 6.0 release: package-lock.json records the
|
|
50
|
+
registry's `typescript` package at the installed version (no alias, an
|
|
51
|
+
`https` tarball URL, not a file or git source) with an integrity (sha512,
|
|
52
|
+
or sha1 where a registry records only sha1), npm's cache holds the tarball
|
|
53
|
+
under that integrity, and the installed files are exactly the tarball's
|
|
54
|
+
files. REDUE reads the cache only; it never downloads. The cache is the one
|
|
55
|
+
npm uses: `npm_config_cache`, else `cache` in the project's `.npmrc`, then
|
|
56
|
+
the user's, else `~/.npm` (`%LocalAppData%\npm-cache` on Windows); the
|
|
57
|
+
global npmrc is not read. `npm-shrinkwrap.json` is not read on this path.
|
|
58
|
+
`npm ci` fills the cache. When the tarball is missing the check stays
|
|
59
|
+
recording-only with the reason `npm-tarball-uncached`; `npm cache add
|
|
60
|
+
typescript@VERSION` adds it. The check's compiler identity is then the
|
|
61
|
+
lockfile integrity, so a lockfile change re-probes.
|
|
62
|
+
|
|
63
|
+
CI runs the same contract suite against the last release of each minor from
|
|
64
|
+
5.0 to 5.8 that the reviewed releases do not cover. Later minors (6.1 and up)
|
|
65
|
+
wait until CI covers them. TypeScript 7 (the native compiler) is not
|
|
66
|
+
supported.
|
|
67
|
+
|
|
68
|
+
## Script forms
|
|
69
|
+
|
|
70
|
+
A typecheck script qualifies when it is one or more `tsc` runs joined by `&&`,
|
|
71
|
+
each with `--noEmit` and only these arguments, in any order: `-p`/`--project`
|
|
72
|
+
with a config file or directory inside the project, `--skipLibCheck`, and
|
|
73
|
+
`--pretty` (optionally `true` or `false`). For example
|
|
74
|
+
`tsc -p tsconfig.app.json --noEmit` or
|
|
75
|
+
`tsc --noEmit && tsc --noEmit -p tsconfig.node.json`. `tsc -b`, `--watch`,
|
|
76
|
+
other options, quotes, variables and other commands keep the script
|
|
77
|
+
recording-only.
|
|
78
|
+
|
|
79
|
+
A chain gets one check per run, named `typecheck.1`, `typecheck.2` and so on,
|
|
80
|
+
each with the script's name and that run's arguments in its command. Each run
|
|
81
|
+
is checked as its own program against its own config, and is reused only while
|
|
82
|
+
the script still has as many runs as the config has checks for it, one of them
|
|
83
|
+
with exactly those arguments. Adding or removing a run, or a pre- or
|
|
84
|
+
post-script, makes every check of the script not reusable until `init` runs
|
|
85
|
+
again. The script as a whole
|
|
86
|
+
(`npm run typecheck`) is skipped only when its current runs and the configured
|
|
87
|
+
checks correspond one to one and all are CURRENT (see [agents](agents.md)).
|
|
88
|
+
|
|
89
|
+
With no typecheck script and a root `tsconfig.json`, init proposes a
|
|
90
|
+
`tsc --noEmit` check with no `script` field, unless a script already runs a
|
|
91
|
+
TypeScript checker in another form (`tsc -b`, `vue-tsc`, `svelte-check`,
|
|
92
|
+
`tsgo`, `astro check`, `nuxi typecheck`). package.json is not changed. The
|
|
93
|
+
check is written only when the contract holds; otherwise no typecheck check is
|
|
94
|
+
added. The pnpm contract does the same for each workspace package with a
|
|
95
|
+
`tsconfig.json` and no typecheck script.
|
|
39
96
|
|
|
40
97
|
Existing configs are never overwritten. To compare choices, use a new project-local
|
|
41
98
|
`--config redue.direct.config.json` with init; this explicitly selects separate
|
|
@@ -82,9 +82,10 @@ Use a check actually printed by `init`. For a workspace:
|
|
|
82
82
|
`redue init --workspace @example/package --check typecheck`.
|
|
83
83
|
Initialization previews detected commands and qualification confidence before writing
|
|
84
84
|
`redue.config.json`. An existing config is never overwritten. No checks are run and
|
|
85
|
-
no dependencies installed. A missing/unsupported boundary is explained.
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
no dependencies installed. A missing/unsupported boundary is explained. `init` tries
|
|
86
|
+
the strict recipes first and uses the [general recipe](node-script.md) for a root
|
|
87
|
+
typecheck or lint script none of them takes. Test scripts use the
|
|
88
|
+
[direct test recipe](tests-direct.md).
|
|
88
89
|
|
|
89
90
|
“Ready to qualify” means REDUE has a supported recipe whose prerequisites will be
|
|
90
91
|
validated. It is not a receipt. “Recording-only” can record PASS/FAIL without claiming
|
|
@@ -92,10 +93,9 @@ reusability. Qualification can change when configuration or installation changes
|
|
|
92
93
|
|
|
93
94
|
`run` streams normal output and preserves execution environment and cancellation.
|
|
94
95
|
For the narrow pnpm TypeScript contract, `init` explicitly shows the direct installed
|
|
95
|
-
compiler invocation it selects
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
the package manager. No existing configuration is silently migrated.
|
|
96
|
+
compiler invocation it selects, and for npm the
|
|
97
|
+
[local compiler recipe](direct-typescript.md). General checks and other scripts
|
|
98
|
+
run through the package manager. No existing configuration is silently migrated.
|
|
99
99
|
Only use configs and probes from trusted repositories: these execute local code.
|
|
100
100
|
|
|
101
101
|
`status` is cached and conservative. `status --sync` and `explain` revalidate caller
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# General recipe (typecheck and lint scripts)
|
|
2
|
+
|
|
3
|
+
The general recipe records a project's own typecheck or lint script, run
|
|
4
|
+
through its package manager, and reports later whether that result still
|
|
5
|
+
applies to the files you have. It is a lower tier than the strict recipes:
|
|
6
|
+
`redue init` tries the [direct TypeScript recipe](direct-typescript.md), the
|
|
7
|
+
pnpm and Yarn TypeScript recipes and the [direct test recipe](tests-direct.md)
|
|
8
|
+
first, and uses the general recipe for a root typecheck or lint script none of
|
|
9
|
+
them takes. Test scripts use the direct test recipe; `init` does not propose
|
|
10
|
+
the general recipe for them.
|
|
11
|
+
|
|
12
|
+
It supports a project installed by npm, pnpm 9-12 (isolated or hoisted
|
|
13
|
+
`node_modules`) or Yarn with the `node-modules` linker, with one lockfile kind
|
|
14
|
+
matching any `packageManager` declaration, on macOS and Linux with Node 22 or
|
|
15
|
+
24. Workspaces are supported for root scripts. `init --recipe node-script`
|
|
16
|
+
writes general checks only.
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
redue init
|
|
22
|
+
redue start
|
|
23
|
+
redue run lint
|
|
24
|
+
redue status --sync
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The config gets one field for the recipe, written by `init`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{"name": "lint", "script": "lint", "kind": "lint", "qualification": "node-script-v1", "inputs": ["**", "..."]}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`redue run lint` runs `npm run lint` (or `pnpm run lint`, `yarn run lint`) with
|
|
34
|
+
REDUE's recorder loaded in every Node process, and npm's and pnpm's update
|
|
35
|
+
checks turned off. With the Claude Code hook, `npm run lint`, `pnpm lint` and,
|
|
36
|
+
for a script that is one plain command such as `eslint .`, that command itself
|
|
37
|
+
and `npx eslint .` are recognized like typecheck and test commands.
|
|
38
|
+
`status` and the hook's skip message name the recipe that made the receipt.
|
|
39
|
+
|
|
40
|
+
## What REDUE claims
|
|
41
|
+
|
|
42
|
+
CURRENT means the last run's inputs are unchanged:
|
|
43
|
+
|
|
44
|
+
- every file in the checkout, except `.git`, every `node_modules`, the runner
|
|
45
|
+
caches listed below and the files the run itself wrote;
|
|
46
|
+
- the installed files in the root's and every workspace package's
|
|
47
|
+
`node_modules`, and Yarn's install state, by file identity;
|
|
48
|
+
- the lockfile and `package.json`, as files of the checkout;
|
|
49
|
+
- the package manager's executable and Node, by file identity, and the exact
|
|
50
|
+
script;
|
|
51
|
+
- every environment variable the run's JavaScript read directly, and always
|
|
52
|
+
`TZ`, `LANG`, `PATH`, `HOME`, `CI`, `XDG_CONFIG_HOME` and every `NODE_*`,
|
|
53
|
+
`LC_*`, `VITE_*`, `DYLD_*`, `LD_*`, `npm_config_*`, `pnpm_config_*`,
|
|
54
|
+
`PNPM_*`, `COREPACK_*` and `YARN_*` variable;
|
|
55
|
+
- the executables of npm, pnpm, Yarn and Corepack on PATH, by file identity,
|
|
56
|
+
since a script may run another package manager;
|
|
57
|
+
- small files read outside the checkout (up to 1 MB), by content, and lookups
|
|
58
|
+
outside it, asked again before each answer.
|
|
59
|
+
|
|
60
|
+
Runner caches are not inputs, and a run may read and write them: `.cache`,
|
|
61
|
+
`.vite`, `.vitest`, `.turbo`, `.nx`, `.swc`, `.jest-cache`, `.parcel-cache`,
|
|
62
|
+
`.angular/cache`, `.next/cache` and `.tmp` directories, `*.tsbuildinfo`,
|
|
63
|
+
`.eslintcache`, `.stylelintcache`, `.prettiercache`, and the
|
|
64
|
+
`_tmp_<pid>_<hex>` files pnpm writes and removes at every run. A file with
|
|
65
|
+
such a path that git does not ignore is source: reading it makes the run
|
|
66
|
+
UNVERIFIED. At the top of each `node_modules`, only `.cache`, `.vite`,
|
|
67
|
+
`.vite-temp`, `.vitest` and `.vitest-cache` are left out, and `*.tsbuildinfo`
|
|
68
|
+
anywhere in it.
|
|
69
|
+
|
|
70
|
+
Two installed files are rewritten by tools during a run: pnpm's
|
|
71
|
+
`node_modules/.pnpm-workspace-state-v1.json` at the first run after an
|
|
72
|
+
install, and the `node_modules/.vue-global-types/*.d.ts` files vue-tsc writes
|
|
73
|
+
before it reads them. They stay inputs. When they are the only files a run
|
|
74
|
+
changed, and the run wrote them (a recorded process wrote the file, or the
|
|
75
|
+
pnpm executable ran, for its state), the result is kept with the files as the
|
|
76
|
+
run left them, and a later change to them makes it STALE.
|
|
77
|
+
|
|
78
|
+
It does not mean a rerun would give the same result: a test that depends on
|
|
79
|
+
the time or on randomness can pass now and fail later on the same inputs.
|
|
80
|
+
|
|
81
|
+
## Programs
|
|
82
|
+
|
|
83
|
+
The recorder sees only Node processes. Every other program a run starts must be
|
|
84
|
+
one REDUE can account for:
|
|
85
|
+
|
|
86
|
+
- `sh` or `dash`, or `bash` without `BASH_ENV`, running a command that, read
|
|
87
|
+
as text, starts only Node programs, package managers and shell builtins
|
|
88
|
+
(`cd`, `echo`, `true`, `export`, `exec` and a few more). Words are looked up
|
|
89
|
+
on the PATH the shell got. A Node program is the Node executable, a file
|
|
90
|
+
whose `#!` line runs Node, or a pnpm launcher. A version manager's `node`
|
|
91
|
+
shim (asdf, nodenv) is a script and does not count. Other shells read
|
|
92
|
+
startup files and are refused. The shell must still have REDUE's recorder in
|
|
93
|
+
`NODE_OPTIONS`: npm's and pnpm's `node-options` setting replaces it, and a
|
|
94
|
+
run under such a setting is UNVERIFIED;
|
|
95
|
+
- a pnpm launcher in `node_modules/.bin`: the `#!/bin/sh` script pnpm writes,
|
|
96
|
+
which runs `sed`, `dirname`, `uname` or `readlink` before it starts Node. It
|
|
97
|
+
is trusted only when its text is exactly one of the templates pnpm 8.0 to
|
|
98
|
+
12.14 write (`src/pnpm-shim-templates.json`), with only the bin file and
|
|
99
|
+
`NODE_PATH` filled in;
|
|
100
|
+
- the pnpm executable (pnpm 12, also the copy Corepack downloads): REDUE cannot
|
|
101
|
+
see what it does, so the scripts it runs are read as text the same way,
|
|
102
|
+
their `pre` and `post` scripts included. Filters and recursive runs
|
|
103
|
+
(`--filter`, `-r`) are refused. At least one Node process it starts must
|
|
104
|
+
have loaded the recorder, and its configuration files outside the checkout
|
|
105
|
+
(`pnpm/rc`, `pnpm/config.yaml`, `~/.npmrc`, the global `npmrc`) are kept by
|
|
106
|
+
content;
|
|
107
|
+
- `ps -A -o ppid,pid`, which pnpm loaded into Corepack runs.
|
|
108
|
+
|
|
109
|
+
Anything else makes the result UNVERIFIED and names the program: `git`,
|
|
110
|
+
`sleep`, `find`, and native programs from installed packages such as esbuild,
|
|
111
|
+
turbo, tsgo, tsgolint and biome, whose reads, writes and network use REDUE
|
|
112
|
+
cannot see. `init` reads the script the same way and keeps a script that
|
|
113
|
+
starts such a program recording-only, with the program in the reason.
|
|
114
|
+
|
|
115
|
+
A command line may use `&&`, `||`, `;`, `|`, quotes without expansions,
|
|
116
|
+
globs in arguments and redirection to `/dev/null`. Variables, command
|
|
117
|
+
substitution, input redirection, subshells, here-documents and `command -p`
|
|
118
|
+
are refused. Setting or clearing `NODE_OPTIONS`, `PATH`, `REDUE_RUN_RECORD`,
|
|
119
|
+
`BASH_ENV`, `ENV`, or npm's or pnpm's `node-options` or `script-shell` is
|
|
120
|
+
refused, since it could stop a Node process from loading the recorder.
|
|
121
|
+
`node --env-file` and Node's config-file options are refused: Node reads those
|
|
122
|
+
files natively. `process.loadEnvFile` is recorded as a read.
|
|
123
|
+
|
|
124
|
+
## The guard
|
|
125
|
+
|
|
126
|
+
As in the [direct test recipe](tests-direct.md#the-guard), the result is kept
|
|
127
|
+
but marked UNVERIFIED, with the reason, when the run read a git-ignored file
|
|
128
|
+
REDUE does not observe and did not create first, changed an input during the
|
|
129
|
+
run (a formatter's `--write`, a generated `version.ts`), listed a directory or
|
|
130
|
+
read a large file outside the checkout, used the network, or started a program
|
|
131
|
+
REDUE does not account for. Reads through a workspace package's link in
|
|
132
|
+
`node_modules` count where the link leads.
|
|
133
|
+
|
|
134
|
+
The package managers' own installations, Corepack's downloads and npm's log
|
|
135
|
+
directory are toolchain, identified by the package manager's executable, not
|
|
136
|
+
inputs.
|
|
137
|
+
|
|
138
|
+
## Limits
|
|
139
|
+
|
|
140
|
+
- On macOS, a file created and removed directly in the project root during a
|
|
141
|
+
run (pnpm 12 does this) can be reported by the file watcher as an event on
|
|
142
|
+
the root itself, an observation gap that makes the run UNVERIFIED. Linux
|
|
143
|
+
reports the file, which is not an input.
|
|
144
|
+
- The pnpm executable and the pnpm launchers' helpers are trusted as
|
|
145
|
+
toolchain: what they read is not checked.
|
|
146
|
+
- Code that copies the environment and reads the copy, and native code that
|
|
147
|
+
reads files or variables (native addons such as Rust-based resolvers), is
|
|
148
|
+
not seen.
|
|
149
|
+
- A project whose `.npmrc` sets `node-options` stays UNVERIFIED: npm replaces
|
|
150
|
+
`NODE_OPTIONS` with it, which drops REDUE's recorder.
|
|
151
|
+
- A script that runs a build first (`npm run build && tsc --noEmit`) usually
|
|
152
|
+
starts esbuild or another native bundler and stays UNVERIFIED.
|
|
153
|
+
- Windows is not supported; the check stays recording-only there.
|
package/docs/user/pilot.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Opt-in development pilot: alpha.
|
|
1
|
+
# Opt-in development pilot: alpha.18
|
|
2
2
|
|
|
3
3
|
Use one fixed build for several ordinary development sessions. The owner will
|
|
4
4
|
invite two or three willing testers and approve their projects; nothing is
|
|
@@ -9,8 +9,9 @@ controlled compiler/agent trials are acceptance evidence, not independent adopti
|
|
|
9
9
|
|
|
10
10
|
Start with a trusted, single-package npm Git checkout, normally installed locked
|
|
11
11
|
dependencies, and an existing standalone `tsc --noEmit` script without pre/post
|
|
12
|
-
scripts. The direct recipe accepts only
|
|
13
|
-
|
|
12
|
+
scripts. The direct recipe accepts only an official, unchanged TypeScript **5.x or
|
|
13
|
+
6.0** package (a reviewed release, or one matching the tarball package-lock.json
|
|
14
|
+
names in npm's cache) and Node **22 or 24**. No workspaces, named
|
|
14
15
|
tsconfig selection, emitted/incremental/composite builds, custom loaders or
|
|
15
16
|
outside-root inputs are added by this pilot. Do not downgrade or change your
|
|
16
17
|
project to fit; record an unsupported setup as feedback.
|
|
@@ -35,7 +36,7 @@ are **NOT RUN**. The recording shortcut is macOS/direct-recipe only.
|
|
|
35
36
|
For a new default npm installation:
|
|
36
37
|
|
|
37
38
|
```sh
|
|
38
|
-
npm install --global @redue/cli@0.1.0-alpha.
|
|
39
|
+
npm install --global @redue/cli@0.1.0-alpha.18
|
|
39
40
|
redue --version
|
|
40
41
|
cd my-project
|
|
41
42
|
redue --config redue.config.json init --recipe typescript-direct --check typecheck --dry-run
|
|
@@ -89,7 +90,7 @@ using it; keep the same npm prefix, config and any explicit state selection.
|
|
|
89
90
|
|
|
90
91
|
```sh
|
|
91
92
|
redue --config redue.config.json stop
|
|
92
|
-
npm install --global @redue/cli@0.1.0-alpha.
|
|
93
|
+
npm install --global @redue/cli@0.1.0-alpha.18
|
|
93
94
|
redue --config redue.config.json agent setup codex --dry-run
|
|
94
95
|
redue --config redue.config.json agent setup codex --apply
|
|
95
96
|
redue --config redue.config.json start
|
|
@@ -15,11 +15,17 @@ At the repository root, `init` looks for existing typecheck, test, lint, and
|
|
|
15
15
|
build scripts. It prefers familiar script names, then unique recognizable
|
|
16
16
|
`tsc`, Vitest/Jest, ESLint, or Vite commands under other names. Multiple
|
|
17
17
|
matches are reported as ambiguous rather than guessed. It never creates a new
|
|
18
|
-
project script.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
project script. Without `--recipe`, `init` tries the strict recipes below first,
|
|
19
|
+
then the [general recipe](node-script.md) for a root typecheck or lint
|
|
20
|
+
script: the script run through the package manager with every Node process
|
|
21
|
+
recorded and the whole checkout as its input. `--recipe typescript-direct`,
|
|
22
|
+
`tests-direct` or `node-script` selects one recipe alone. The direct TypeScript recipe supports
|
|
23
|
+
a typecheck script of `tsc --noEmit` runs in any argument order, chained runs,
|
|
24
|
+
or no typecheck script at all (a proposed `tsc --noEmit`; see
|
|
25
|
+
[script forms](direct-typescript.md#script-forms)), in a single-package npm installation using
|
|
26
|
+
TypeScript 5.x or 6.0 (a reviewed release, or one whose installed files match the
|
|
27
|
+
tarball package-lock.json names in npm's cache; see
|
|
28
|
+
[compiler identity](direct-typescript.md#compiler-identity)) and Node 22/24. It executes the local compiler,
|
|
23
29
|
not npm. Full installed compiler identity, config/membership, installed inputs
|
|
24
30
|
and relevant Node environment are checked before reuse. See the
|
|
25
31
|
[exact direct boundary](direct-typescript.md). Unsupported plugins, preloads,
|
|
@@ -37,11 +43,11 @@ When an internal dependency is consumed through built declarations, changing
|
|
|
37
43
|
only its source does not stale the selected check until the consumed output
|
|
38
44
|
changes. Unsupported custom resolution, project references, outside-root
|
|
39
45
|
source links, and installation modes remain recording-only. Other Yarn
|
|
40
|
-
typechecks, Vitest/Jest, ESLint, and builds
|
|
41
|
-
separately justified explicit contract is provided.
|
|
42
|
-
project whose test script runs Vitest 4/5 or Jest 29
|
|
43
|
-
`init
|
|
44
|
-
[direct tests](tests-direct.md).
|
|
46
|
+
typechecks, Vitest/Jest, ESLint, and builds in workspace packages start
|
|
47
|
+
recording-only unless a separately justified explicit contract is provided.
|
|
48
|
+
For a single-package project whose test script runs Vitest 4/5 or Jest 29
|
|
49
|
+
directly, `init` uses the direct test recipe, which records the run and guards
|
|
50
|
+
its inputs; see [direct tests](tests-direct.md).
|
|
45
51
|
In particular, test caches and build-generated inputs are not excluded to
|
|
46
52
|
make evidence green.
|
|
47
53
|
|
|
@@ -62,12 +68,17 @@ the installed one. Only the project's files are read: settings from a user or
|
|
|
62
68
|
global rc file, or `npm_config_*` variables during install, are not. The
|
|
63
69
|
supported local layouts are pnpm's standard isolated and hoisted
|
|
64
70
|
`node_modules` with a project-local `.pnpm` virtual store. `init` can discover
|
|
65
|
-
root and workspace scripts. For a
|
|
66
|
-
script
|
|
67
|
-
|
|
71
|
+
root and workspace scripts. For a typecheck script of `tsc` runs
|
|
72
|
+
([script forms](direct-typescript.md#script-forms); `tsc -p .` without
|
|
73
|
+
`--noEmit` is also accepted), or a package with a `tsconfig.json` and no
|
|
74
|
+
typecheck script, it records the exact installed compiler invocation directly.
|
|
75
|
+
The source inputs are the directories the config's `include` covers, as
|
|
76
|
+
TypeScript itself computes them for new files, minus `node_modules` (`exclude`
|
|
77
|
+
entries stay inputs: an import can still reach an excluded file); a file the
|
|
78
|
+
program reads outside them keeps the check recording-only. This avoids pnpm's task-run bookkeeping
|
|
68
79
|
writes during `pnpm run`; it does not alter the project's script. Test, lint,
|
|
69
|
-
build, and ambiguous TypeScript scripts still execute through `pnpm run
|
|
70
|
-
|
|
80
|
+
build, and ambiguous TypeScript scripts still execute through `pnpm run`; root
|
|
81
|
+
typecheck and lint ones can use the [general recipe](node-script.md). The generated `@typescript-bin:WORKSPACE` token resolves
|
|
71
82
|
the local compiler when the check runs; it is not an absolute machine path.
|
|
72
83
|
|
|
73
84
|
The pnpm contract indexes consumed installed package contents inside the
|