@redue/cli 0.1.0-alpha.3 → 0.1.0-alpha.31

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +831 -0
  2. package/README.md +157 -99
  3. package/bin/redue.mjs +322 -66
  4. package/docs/README.md +3 -1
  5. package/docs/user/agents.md +333 -15
  6. package/docs/user/configuration.md +28 -2
  7. package/docs/user/direct-typescript.md +219 -0
  8. package/docs/user/getting-started.md +50 -7
  9. package/docs/user/json.md +4 -2
  10. package/docs/user/node-script.md +177 -0
  11. package/docs/user/npm-launcher-notice.md +42 -0
  12. package/docs/user/pilot.md +146 -0
  13. package/docs/user/sandbox.md +326 -0
  14. package/docs/user/shell.md +3 -3
  15. package/docs/user/supported-projects.md +69 -23
  16. package/docs/user/tests-direct.md +143 -0
  17. package/package.json +4 -3
  18. package/src/agent-integration.mjs +467 -0
  19. package/src/agent-policy.md +28 -0
  20. package/src/cached-state.mjs +24 -1
  21. package/src/claude-hook.mjs +616 -0
  22. package/src/cli.mjs +449 -54
  23. package/src/daemon.mjs +442 -93
  24. package/src/decision-profile.mjs +15 -1
  25. package/src/decision-validation.mjs +12 -1
  26. package/src/declared-plan.mjs +38 -6
  27. package/src/direct-run-certificate.mjs +254 -0
  28. package/src/direct-typescript-probe.mjs +27 -0
  29. package/src/direct-typescript.mjs +205 -0
  30. package/src/glob.mjs +8 -0
  31. package/src/history-worker.mjs +21 -13
  32. package/src/index.mjs +108 -21
  33. package/src/installed-inputs.mjs +7 -1
  34. package/src/installed-observation.mjs +23 -0
  35. package/src/landlock.py +527 -0
  36. package/src/linux-inotify.py +39 -10
  37. package/src/node-onboarding.mjs +203 -54
  38. package/src/node-script.mjs +406 -0
  39. package/src/npm-integrity.mjs +124 -0
  40. package/src/npm-typecheck-environment.mjs +36 -0
  41. package/src/npmrc.mjs +16 -0
  42. package/src/observation.mjs +34 -12
  43. package/src/path-identity.mjs +8 -0
  44. package/src/plan-worker.mjs +17 -17
  45. package/src/pnpm-inputs.mjs +122 -57
  46. package/src/pnpm-shim-templates.json +180 -0
  47. package/src/pnpm-shims.mjs +54 -0
  48. package/src/pnpm-typecheck-probe.mjs +11 -6
  49. package/src/presentation.mjs +13 -4
  50. package/src/probe-deadline.mjs +37 -0
  51. package/src/probe-result.mjs +7 -3
  52. package/src/project-location.mjs +34 -0
  53. package/src/python-onboarding.mjs +89 -0
  54. package/src/run-recorder.cjs +91 -0
  55. package/src/sandbox.mjs +659 -0
  56. package/src/setup.mjs +224 -0
  57. package/src/stats.mjs +72 -0
  58. package/src/test-direct.mjs +608 -0
  59. package/src/test-recorder.cjs +435 -0
  60. package/src/typescript-contract-probe.mjs +4 -187
  61. package/src/typescript-input-facts.mjs +92 -0
  62. package/src/typescript-invocation.mjs +92 -0
  63. package/src/typescript-list.mjs +118 -13
  64. package/src/typescript-qualification.mjs +29 -49
  65. package/src/workspace-manifests.mjs +24 -0
  66. package/src/yarn-workspace-inputs.mjs +3 -0
  67. package/src/yarn-workspace-typecheck-probe.mjs +2 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,836 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.31 — 2026-11-03
4
+
5
+ A check that runs longer than init's trial limit no longer holds up
6
+ `init` for three runs, and can be set up in the sandbox later.
7
+
8
+ - **A run past the trial limit never agrees.** Each trial run at `init`
9
+ stops after 5 minutes. alpha.30 counted a timeout on both sides as
10
+ agreement and ran every trial of a check that timed out. Now, when the
11
+ plain run reaches the limit, `init` runs nothing in the sandbox and
12
+ writes the fallback; when a sandboxed run reaches it, no further trial
13
+ follows. On the 13 census repos with the slowest checks, `init --dry-run`
14
+ took 6224 s in all with alpha.30 and 3670 s now on Linux, 8331 s and
15
+ 4776 s on macOS. ADOSMissionControl went from 1138 s to 581 s (Linux),
16
+ agent-afk from 936 s to 323 s, Nomi from 860 s to 528 s (macOS). Checks
17
+ that moved from the sandbox to their fallback: 2 of 210 on Linux
18
+ (ts-liveview typecheck, open-science lint), 3 of 210 on macOS (Nomi and
19
+ ts-liveview typecheck, OneUptime lint).
20
+ - **`redue init --no-time-limit`.** `redue setup` names the checks that
21
+ ran past the limit and prints one command, such as
22
+ `redue init --check typecheck --no-time-limit`. It runs their trials with
23
+ no limit and updates only their rows in the existing config (a row that
24
+ runs the same script), restarts a running observer, and leaves the
25
+ config one `redue remove` still deletes. `init --json` gives such a
26
+ check's kind as `time_limit`.
27
+
28
+ ## 0.1.0-alpha.30 — 2026-11-03
29
+
30
+ `init` runs a check fewer times, and tests try the sandbox first.
31
+
32
+ - **Fewer trial runs at init.** A check proposed for the sandboxed recipe
33
+ now runs once plainly and once in the sandbox with ignored files and
34
+ documentation hidden (`sandbox-v3`). If they differ, it runs once more
35
+ with the whole checkout (`sandbox-v1`), compared with the same plain run.
36
+ When the plain run passed and the sandboxed one failed only on reading a
37
+ hidden file, the check gets `sandbox-v1` without that run. `init` no
38
+ longer tries `sandbox-v2`; existing `sandbox-v2` checks keep working.
39
+ On the 13 census repos with the slowest checks, `init --dry-run` took
40
+ 4740 s in all before and 3870 s after on Linux, 6929 s and 5784 s on
41
+ macOS. OneUptime went from 1204 s to 903 s (Linux) and 1206 s to 605 s
42
+ (macOS). Nomi did not get faster (485 s to 383 s on Linux, 836 s to
43
+ 893 s on macOS): its typecheck agrees on the first trial, and each of its
44
+ two runs stops at init's 5-minute limit.
45
+ - **Tests try the sandbox first.** For a Node test script, `init` tries the
46
+ sandboxed recipe before the direct test recipe, which becomes its
47
+ fallback, when both would run the same script. In the census, on the repos where both qualified (2 on each OS),
48
+ the direct recipe's results went STALE when the project's build rewrote
49
+ its output, and the sandboxed results stayed CURRENT. A test script now
50
+ costs `init` one plain run and one or two sandboxed runs.
51
+ - Known limit: artsy/eigen's typecheck, which fails in the census, no
52
+ longer agrees with the whole checkout at init and falls back to the
53
+ general recipe (Linux) or recording (macOS).
54
+
55
+ ## 0.1.0-alpha.29 — 2026-11-03
56
+
57
+ Editing documentation no longer makes sandboxed checks STALE, a fast check
58
+ is skipped or recorded as it should be, and macOS test runs can no longer
59
+ reach a service started outside them.
60
+
61
+ - **Documentation is hidden too (`sandbox-v3`).** A sandboxed run now also
62
+ hides the project's documentation: files named `*.md`, `*.mdx`, `*.rst`,
63
+ `LICENSE*` or `CHANGELOG*` anywhere, and text, image and PDF files in the
64
+ root `docs/` folder (code there stays visible). The receipt names the
65
+ files the run hid, and a later edit to one of them leaves the result
66
+ CURRENT: editing the README no longer makes the tests STALE. A new
67
+ documentation file still counts. `init` tries this first, then the
68
+ git-ignored files only (`sandbox-v2`), then the whole checkout. A check
69
+ that reads documentation (a doctest over the README) keeps `sandbox-v2`.
70
+ Run `redue init` again to move an existing check to `sandbox-v3`.
71
+ - **A fast check is no longer missed by the hook.** The hook waited half of
72
+ the check's last run for `redue status`, so a 0.2 s mypy got 0.1 s, the
73
+ status answer came too late, and the agent's run went unrecorded. The
74
+ wait is now at least 2 s. `REDUE_HOOK_LOG` (an absolute file path) makes
75
+ the hook write one line per Bash command with its decision and why.
76
+ - **macOS test runs get no network.** Seatbelt cannot refuse only the ports
77
+ that were already listening (a per-port rule under a loopback allow is not
78
+ applied; an allow list of every other port does not compile), so a macOS
79
+ test run now gets Unix sockets in its own temporary directory only, as a
80
+ typecheck or lint does. A suite that needs loopback fails `init`'s trial
81
+ and runs without REDUE. Test checks set up by alpha.28 on macOS are not
82
+ CURRENT after the upgrade.
83
+ - **`redue status` reconciles by default.** `redue status --cached` gives the
84
+ observer's last published answer; `--sync` is still accepted. Like
85
+ `--sync`, plain `status` exits 2 when it cannot reach the observer (after
86
+ `redue stop`, for example); `--cached` exits 0.
87
+ - **`redue setup` says more and prints less.** It lists the checks it left
88
+ out and why (a kind it found nothing for, a proposed `tsc --noEmit` no
89
+ recipe takes), says what recording only means, and prints one line per
90
+ recorded run instead of the check's whole output.
91
+ - `redue remove-state` waits for the observer to exit before removing its
92
+ state (a Windows ENOTEMPTY).
93
+ - **Measured.** In the product census, repositories whose qualifying
94
+ sandboxed check keeps the documentation hidden, out of those with one:
95
+ TypeScript on Linux, typecheck 17 of 19, lint 20 of 20, tests 7 of 8; on
96
+ macOS 12 of 13, 14 of 16, 6 of 9. Python on Linux 15 of 15, 22 of 22, 12
97
+ of 17; on macOS 11 of 13, 17 of 17, 8 of 11. No network for macOS test
98
+ runs cost 1 TypeScript suite (it starts a server on 127.0.0.1) and 2
99
+ Python suites: test suites qualifying on macOS went from 12 to 11
100
+ (TypeScript) and 14 to 11 (Python; one checkout no longer installs). The
101
+ strace cross-check found no read outside the recorded inputs. In a Claude
102
+ Code follow-up on starlette and nestjs-api-gateway, a README edit made no
103
+ check STALE; the hook skipped mypy, pytest and the lint, and each skipped
104
+ command passed when run plainly.
105
+
106
+ ## 0.1.0-alpha.28 — 2026-11-02
107
+
108
+ Test suites can run in the sandbox, so REDUE can reuse a passing test run
109
+ for more projects, Python included.
110
+
111
+ - **Sandboxed tests.** A root test script that the direct test recipe does
112
+ not take, and pytest in a Python project's `.venv`, can now use the
113
+ sandboxed recipe. `init` keeps it only when the run in the sandbox gives the
114
+ same exit status and test counts as a plain run. On top of what a
115
+ typecheck or lint gets, a test run gets:
116
+ - **Loopback only.** It may listen on any address and connect to the local
117
+ host and Unix sockets, never to a remote host. On macOS, Seatbelt
118
+ enforces that. On Linux, a seccomp filter refuses UDP and other non-TCP
119
+ sockets, TCP Fast Open and `io_uring`, and hands each `connect` to
120
+ REDUE's launcher. The launcher allows a local port nothing listens on or
121
+ one the run's own processes listen on, and refuses everything else,
122
+ including a service you started outside the run (a local database). If
123
+ the launcher cannot start or stops early, the result is UNVERIFIED.
124
+ - **A private `/tmp`.** Its `TMPDIR` is new for each run, and it may not
125
+ write elsewhere in `/tmp` or `/var/tmp`.
126
+ - **A fresh home** for each run, as on CI.
127
+ - **Ignored files hidden** when the trial agrees, else the whole checkout.
128
+ - **Measured.** In the product census, test suites with a qualifying check
129
+ (alpha.27 in brackets): TypeScript on Linux 11 (2), on macOS 12 (2);
130
+ Python on Linux 17 (0), on macOS 14 (0). The strace cross-check found no
131
+ read outside the recorded inputs. The Linux connect supervisor added at
132
+ most 1.5% over the sandbox without it on suites with worker processes
133
+ (pytest-xdist, Jest, Vitest): apprise 233 s to 237 s, run-to-run spread
134
+ 218-243 s. In a pilot with Claude Code on two pytest projects, the hook
135
+ skipped both "do the tests still pass?" reruns (19 s to 6 s and 28 s to
136
+ 7 s), and plain reruns agreed with both skips.
137
+ - **macOS hides contents only.** On macOS, a hidden file's contents and
138
+ execution are refused, but its metadata is not, as on Linux. A test that
139
+ writes into an ignored folder works.
140
+ - Known limits: a suite that reads back ignored files it writes in the same
141
+ run (a coverage database, a build it starts) gets the whole checkout, and
142
+ one that writes tracked files or coverage data during the run ends
143
+ UNVERIFIED. On Linux, a test that needs a service started outside the run
144
+ fails in the sandbox, so `init` leaves it to a plain run.
145
+
146
+ ## 0.1.0-alpha.27 — 2026-11-01
147
+
148
+ A build or test run no longer makes a sandboxed typecheck or lint STALE,
149
+ and `redue stats` shows what REDUE saved you.
150
+
151
+ - **Files git ignores are hidden from sandboxed runs.** A sandboxed
152
+ typecheck or lint now runs without the files git ignores (`dist/`,
153
+ `.next/`, coverage files, `.env`), except `node_modules`, `.venv` and
154
+ runner caches. Those files are not its inputs, so a build or test run that
155
+ writes them leaves the result CURRENT. The claim: the result holds for a
156
+ run that sees only the project's files that git doesn't ignore, its
157
+ installed packages and the toolchain. Only the project's `.gitignore`
158
+ files and `.git/info/exclude` count, not your global excludes file.
159
+ - **Checks that need ignored files keep working.** `init` tries the
160
+ sandbox with ignored files hidden first (`sandbox-v2`), then with the
161
+ whole checkout (`sandbox-v1`), then the general recipe. A hidden run that
162
+ fails on a hidden file runs again in the sandbox without hiding, and that
163
+ result is kept. Checks set up by alpha.26 stay `sandbox-v1` until you run
164
+ `redue init` again.
165
+ - **Measured.** In the product census, after each project's own build and
166
+ tests ran, checks that stayed CURRENT (alpha.26 in brackets, from the
167
+ measurement census): TypeScript on Linux 31 of 37 (5 of 43), on macOS 24
168
+ of 34 (5 of 38); Python on Linux 31 of 38 (24 of 37), on macOS 28 of 34
169
+ (20 of 33). Where a check qualifies with both, the sandbox stayed CURRENT
170
+ 16 times and the general recipe 9 of 23 (Linux). The strace cross-check
171
+ found no read outside the recorded inputs.
172
+ - **`redue stats`.** Per check: reruns the hook skipped, the time that
173
+ saved, recorded runs, and the top reasons a check was UNVERIFIED, from a
174
+ log in REDUE's local state.
175
+ - `redue remove-state` no longer fails on Windows while the observer is
176
+ still closing its files.
177
+ - Known limits: a sandboxed run can still see that a hidden file exists
178
+ (its name on macOS; listings, sizes and times on Linux), so a tool that
179
+ acts on existence alone is not covered; tests do not use hidden files for
180
+ that reason. On Linux, a file a run creates in a folder that holds hidden
181
+ files cannot be read back in the same run.
182
+ - Contributors: eval entry points that run third-party code refuse to start
183
+ unless `GITHUB_ACTIONS=true`, and importing any eval entry point throws
184
+ before it does anything.
185
+
186
+ ## 0.1.0-alpha.26 — 2026-10-31
187
+
188
+ Typecheck and lint checks run inside an OS sandbox, so REDUE can reuse them
189
+ for native tools and for Python. Python projects are supported for the first
190
+ time.
191
+
192
+ - **Sandboxed recipe.** On macOS (Seatbelt) and Linux 6.7+ (Landlock), a
193
+ root typecheck or lint script runs in a sandbox that sees only the
194
+ project, its installed packages and the toolchain, the way CI does. Its
195
+ inputs are the whole checkout, git-ignored files included, plus the
196
+ installed packages and a fingerprint of the environment it was given. A
197
+ result holds for a run that sees only those. `init` tries the precise
198
+ TypeScript recipes first, then the sandbox, then the general recipe. See
199
+ [sandboxed recipe](docs/user/sandbox.md).
200
+ - **Python.** `redue setup claude` and `init` find mypy, pyright, ty and
201
+ ruff in the project's `.venv`, from its CI workflows, Makefile, justfile,
202
+ tox, nox and scripts. The Claude Code hook recognizes `uv run`,
203
+ `poetry run`, `python -m` and `.venv/bin` forms.
204
+ - **What the sandbox changes.** Network is off. HOME and the temp folder
205
+ are private to the check; HOME is kept between runs so caches persist.
206
+ Tools can read `.git`, but git commands find no repository. A background
207
+ process the check leaves running is stopped when the run ends.
208
+ - **Checked at init.** `init` runs each check plainly and sandboxed, and
209
+ proposes the sandbox only when exit status and output (timings and paths
210
+ aside) match. Otherwise the general recipe applies. A failing run whose
211
+ output looks like a sandbox refusal is rerun plainly; if the plain run
212
+ exits differently, the result is UNVERIFIED. Other failures run once.
213
+ - **Coverage.** In a census of 120 public TypeScript repositories (86
214
+ installed on macOS), 35 have a qualifying check (alpha.24 census: 30):
215
+ typecheck 22, lint 25, tests 2. Of 120 Python repositories, 23 of the 75
216
+ that installed on Linux have one (typecheck 15, lint 22); 20 of 64 on
217
+ macOS. On Linux, every sandboxed run was traced with strace: each file
218
+ it read in the checkout was a recorded input, a cache or its own output.
219
+ - **Measured with Claude Code.** On starlette, graphon and
220
+ claude-agent-sdk-python, sessions took 58 s with REDUE and 125 s without.
221
+ REDUE skipped 10 typechecks and every one matched a plain rerun.
222
+ - Known limits: inside Claude Code's own macOS sandbox and on Windows, the
223
+ sandbox can't start and the general recipe applies. On Linux before 6.7,
224
+ sandboxed runs are UNVERIFIED.
225
+ A build or test run that writes into the checkout (`dist/`, `.next/`,
226
+ coverage files) makes a sandboxed check STALE, as it does a
227
+ general-recipe check: about 1 in 4 TypeScript and 2 in 3 Python checks
228
+ stayed CURRENT through the project's build and tests.
229
+
230
+ ## 0.1.0-alpha.25 — 2026-10-29
231
+
232
+ Running your tests no longer makes a typecheck STALE, and `status --sync`
233
+ answers about twice as fast.
234
+
235
+ - **Vitest and the direct TypeScript recipe.** A Vitest run writes its
236
+ results under `node_modules/.vite/vitest`, which the recipe counted as an
237
+ installed input, so the typecheck turned STALE after every test run. Those
238
+ files are no longer inputs. Everything else under `node_modules/.vite`
239
+ still is. A program that asks the compiler about anything under
240
+ `node_modules/.vite`, or lists `node_modules`, is UNVERIFIED instead. A
241
+ check set up by an earlier alpha reports STALE ("input plan changed") once
242
+ after the upgrade.
243
+ - **Faster status.** `status --sync`, `detail` and `explain` no longer start
244
+ a second Node process on macOS and Linux, the YAML parser loads only for
245
+ pnpm projects, and each call to the observer no longer waits on a fresh
246
+ read of its status file. On the 800-file bench, warm `status --sync` adds
247
+ 27 ms over cached status on a GitHub Linux runner (alpha.24: 120 ms) and
248
+ 36 ms on a macOS runner (alpha.24: 137 ms).
249
+ - **Releases are benched.** The release smoke now benches the candidate
250
+ against the last release on macOS and Linux runners; a slower candidate,
251
+ or one over the warm-sync or run-overhead budget, blocks the release.
252
+ - Known limit: on the maintainer's Mac, which runs Microsoft Defender,
253
+ `redue run` still adds about 15-20% to a 2.7 s typecheck (3% on a GitHub
254
+ Linux runner).
255
+
256
+ ## 0.1.0-alpha.24 — 2026-10-28
257
+
258
+ Checks keep working after a normal `npm install`, and agents that chain an
259
+ edit and a check get the same skip-or-record as a check run on its own.
260
+
261
+ - **Hard-linked installed files.** Without a pnpm store, any installed file
262
+ with a second hard link made a recorded run UNVERIFIED. esbuild's install
263
+ makes one (npm, not Yarn or Windows), so after an ordinary `npm install`
264
+ general-recipe and test checks in projects with esbuild stayed
265
+ UNVERIFIED. Such a file is now accepted when every one of its links is an
266
+ installed file the check observes; its link count is checked again before
267
+ every answer, so a link added later is noticed.
268
+ - **Checks inside a chain.** In a simple chain (`printf ... >> README.md &&
269
+ npm run lint`), the Claude Code hook rewrites each check to the new
270
+ `redue run CHECK --if-due`, which skips the check when its last pass still
271
+ applies at that moment and otherwise runs it through REDUE with the same
272
+ exit code. The hook changes the command without approving it, so your
273
+ permission rules still apply. Chains with subshells, substitutions,
274
+ here-documents, background jobs, shell keywords or builtins before a check
275
+ run untouched.
276
+ - The CLAUDE.md section asks agents to run each check as a command of its
277
+ own. Setups from earlier alphas are recognized and updated.
278
+ - The README's coverage numbers now come from a census that installs with
279
+ dependencies' install scripts on, as users do: of 120 public TypeScript
280
+ repositories, 86 installed and 30 have a qualifying check (typecheck 21,
281
+ lint 18, tests 2).
282
+ - Known limit, unchanged: a Vitest run writes under `node_modules/.vite`,
283
+ which makes a direct TypeScript typecheck STALE until it runs again.
284
+
285
+ - Contributors: census `--install-scripts`; the stranger test can install
286
+ from npm (`--npm`) and run a follow-up session that uses the hooks.
287
+
288
+ ## 0.1.0-alpha.23 — 2026-10-26
289
+
290
+ One command to set up REDUE with Claude Code, and one to undo it.
291
+
292
+ - **`redue setup claude`** runs `init` (when there is no
293
+ `redue.config.json`), connects Claude Code, starts the observer, waits for
294
+ it to index the project, and records each check that can qualify once. It
295
+ asks once (`--yes` for no prompts), prints every file it writes, and a
296
+ second run changes nothing. It stops before writing when dependencies are
297
+ not installed or nothing can be set up.
298
+ - **`redue remove`** undoes exactly what setup created: the integration (or
299
+ only this machine's hooks), the observer state, the local ignore line, and
300
+ the config if it is unchanged since setup wrote it. Anything that existed
301
+ before setup stays. Setup notes what it created in the clone's Git
302
+ directory, never in a committed file.
303
+ - **Hooks find REDUE.** The Claude Code hooks name plain `redue` only when
304
+ the `redue` that your shell and a login shell find is this install;
305
+ otherwise they name this install's Node and entry by absolute path, so a
306
+ Claude Code started from an IDE or with a shorter PATH still runs it.
307
+ Checks the hook runs for the agent follow the same rule.
308
+ - `init` keeps a typecheck that runs TypeScript 7's `tsc` (or `tsgo` from
309
+ `@typescript/native-preview`) recording-only and says why. The pnpm and
310
+ Yarn TypeScript recipes refuse TypeScript 7 with a clear reason instead
311
+ of an error from inside the compiler API.
312
+ - The README is rewritten around a 5-minute quickstart, what REDUE covers
313
+ today (census qualifiers) and what it won't do.
314
+ - Known limits, found by the stranger test: a Vitest run writes under
315
+ `node_modules/.vite`, which makes a direct TypeScript typecheck STALE until
316
+ it runs again; an installed file with a second hard link (esbuild's install
317
+ makes one) keeps the test check UNVERIFIED.
318
+
319
+ - Contributors: the census can run every recipe (`--all-recipes`) and
320
+ counts direct TypeScript checks; its unrecorded-program check no longer
321
+ flags Yarn's temporary `node` wrapper; `eval/stranger.mjs` runs fresh
322
+ Claude Code sessions that set REDUE up from the README alone.
323
+
324
+ ## 0.1.0-alpha.22 — 2026-10-25
325
+
326
+ A correctness fix for recorded runs. Earlier alphas could report CURRENT for
327
+ a script that replaced itself with another program.
328
+
329
+ - **Fixed: a script that replaced itself with another program could be
330
+ CURRENT.** Node's `process.execve` (Node 22.15 and later) swaps a process
331
+ for another program under the same PID. The recorder did not see it, so
332
+ that program ran unseen. TypeScript 7's `tsc` does this to start its
333
+ native compiler, so alphas 19 to 21 could report a TypeScript 7 typecheck
334
+ as CURRENT while REDUE saw none of what the compiler did. The general
335
+ recipe and the direct test recipe now judge the new program like any
336
+ program a run starts: TypeScript 7's `tsc` makes the run UNVERIFIED and
337
+ names it. Support for TypeScript 7 is planned.
338
+ - Runs that use Node's bindings with file, network or program access
339
+ (`process.binding('fs')`, `'spawn_sync'` and others), or run Node with
340
+ `--expose-internals`, are UNVERIFIED: the recorder cannot follow them.
341
+ - Direct test recipe: a shell a test starts is read by its command, as in the
342
+ general recipe. One that runs another program before it becomes Node makes
343
+ the run UNVERIFIED.
344
+ - General recipe, on Linux: pnpm 12 writes a file with no name in
345
+ `node_modules` when it rewrites its workspace state, which left the first
346
+ run after an install UNVERIFIED. That file now counts as the run's output
347
+ when the pnpm executable ran and no file has its name. Known limit: another
348
+ program's file with no name there, during such a run, is taken as pnpm's.
349
+ - UNVERIFIED reasons for an input that changed during a run name up to five
350
+ files and a count of the rest.
351
+
352
+ - Contributors: the census traces each run on Linux and flags programs the
353
+ recorder missed.
354
+
355
+ ## 0.1.0-alpha.21 — 2026-10-25
356
+
357
+ `init` finds more typecheck scripts and no longer stops in large monorepos.
358
+ In the census of 108 public TypeScript repos, the general recipe qualifies 26
359
+ typecheck scripts (was 23) and 20 lint scripts.
360
+
361
+ - `init` prefers typecheck scripts named `tsc`, `types` or `lint:types`, then
362
+ takes one script named under a typecheck name (`typecheck:test`,
363
+ `tsc:build`, ...), watch scripts aside. Two such scripts are reported as
364
+ ambiguous unless a command alone decides. Scripts named `build` or `dev`
365
+ that run tsc are not taken: they write output.
366
+ - A workspace of more than 50 packages no longer stops `init`. It reads up to
367
+ 1000 packages, proposes the root's checks, and past 50 packages skips
368
+ per-package checks and says so (`skipped` in `--json`, a "Skipped:" line
369
+ otherwise). Five census repos got no check at all before.
370
+ - General recipe: pnpm 12 writes its workspace state through a temporary
371
+ `node_modules/.tmpXXXXXX` file. Like the state file, it counts as the run's
372
+ output when the pnpm executable ran. Known limit: the agent eval's seed lint
373
+ run on one pnpm 12 project is still UNVERIFIED for an input event REDUE does
374
+ not yet name.
375
+
376
+ - Contributors: the agent eval records each run's seed and final receipt,
377
+ and the files a session changed when its seed run is not stable.
378
+
379
+ ## 0.1.0-alpha.20 — 2026-10-24
380
+
381
+ A fix for agents on macOS.
382
+
383
+ - Fixed: on macOS, `redue status --sync --json`, `status --json` and
384
+ `explain --json` read by an agent's shell tool stopped at 8 KB, leaving
385
+ invalid JSON. The agent instructions REDUE installs run `status --sync
386
+ --json`; its output passes 8 KB at about 25 checks, or sooner when STALE
387
+ checks list many changed files. Through a shell pipe, `init --json`
388
+ stopped at 64 KB. The CLI exited with output still queued; it now writes
389
+ all of it first. Linux and Windows were not affected.
390
+
391
+ ## 0.1.0-alpha.19 — 2026-10-24
392
+
393
+ A general recipe for typecheck and lint scripts that the strict recipes do not
394
+ take. Test scripts stay on the direct test recipe (Vitest, Jest).
395
+
396
+ - `redue init` tries the strict recipes first, then writes a general check
397
+ (`"qualification": "node-script-v1"`) for a root typecheck or lint script.
398
+ `redue run` runs the script through the project's package manager (npm,
399
+ pnpm 9-12 or Yarn with the `node-modules` linker) with REDUE's recorder in
400
+ every Node process, on macOS and Linux. The input is the whole checkout but
401
+ `.git`, `node_modules` and runner caches, plus every workspace
402
+ `node_modules` observed as installed files, the package manager and its
403
+ version, and the environment. See docs/user/node-script.md.
404
+ - pnpm's launchers are trusted only when their text matches a template a pnpm
405
+ release writes (pnpm 8.0 to 12.14). The pnpm executable, Corepack's
406
+ pnpm-native included, is toolchain; its configuration files are kept by
407
+ content.
408
+ - A run that starts a program REDUE does not record is UNVERIFIED and the
409
+ reason names it: native programs from installed packages (esbuild, turbo,
410
+ tsgolint, biome), git, find, and shells that read startup files.
411
+ - `status` and the hook's skip message name the recipe that made the receipt
412
+ ("general recipe"). The Claude Code hook recognizes lint commands as it does
413
+ typecheck and test commands: `npm run lint`, `pnpm lint`, and for a script
414
+ that is one plain command, that command and its `npx` form.
415
+ - In the census of 108 public TypeScript repos, the general recipe qualifies
416
+ 23 typecheck and 21 lint scripts (both recorded runs clean, CURRENT after
417
+ the second). Of the scripts whose runs start only Node and the package
418
+ manager's own launchers (35 typecheck, 37 lint, measured with strace), init
419
+ proposes and observes about 21 and 22, and 18 of each qualify. The rest:
420
+ init does not pick script names such as `tsc:build`, fails in monorepos
421
+ over 50 packages, or refuses source directory links and custom install
422
+ setups; plans with submodules or dangling links are unavailable.
423
+ - Known limits: on macOS, pnpm 12's temporary files in the project root can
424
+ arrive as an event on the root and make a run UNVERIFIED. Writes into
425
+ `node_modules` during a run make it UNVERIFIED, except pnpm's workspace
426
+ state and vue-tsc's global types, which stay inputs and are kept as the run
427
+ left them. A workspace's recording checks now leave out nested
428
+ `node_modules`, so `redue init` rewrites them once.
429
+
430
+ - Contributors: `census.mjs --product` applies the product's own rule and
431
+ lists the files an unstable run touched; the eval kills a timed-out
432
+ command's whole process group; the agent eval has lint tasks.
433
+
434
+ ## 0.1.0-alpha.18 — 2026-10-23
435
+
436
+ Typecheck in more project shapes, and pnpm test reuse on Linux. In the census
437
+ of 108 public TypeScript repos, the ones `init` makes ready went from 8 to 11
438
+ for typecheck (the census clones each repo's current head, so one or two
439
+ repos move between runs) and stayed at 22 for tests.
440
+
441
+ - pnpm test checks are reused on Linux. A recorded run accepts an installed
442
+ file hard-linked into the pnpm store the install recorded, when the store
443
+ holds it at its content address (pnpm names store files by their sha512).
444
+ Links anywhere else stay UNVERIFIED. Each file is hashed once; REDUE keeps
445
+ its identity and store path in its state and hashes it again only when the
446
+ identity changes. A 46 MB install takes about 160 ms to check the first
447
+ time. Limit: an in-place edit of an installed file in another project that
448
+ shares the store file is not seen until the next recorded run.
449
+
450
+ - Typecheck scripts in more shapes. A script of `tsc --noEmit` runs with
451
+ `-p`/`--project`, `--skipLibCheck` or `--pretty`, in any argument order,
452
+ qualifies for the direct npm recipe and the pnpm contract. A chain of such
453
+ runs joined by `&&` becomes one check per run (`typecheck.1`,
454
+ `typecheck.2`); the hook skips the script only when every run is CURRENT
455
+ and otherwise runs the stale ones through `redue run`. `check-types` joins
456
+ the recognized script names.
457
+ - The hook acts on a typecheck script's form only while the script in
458
+ package.json still has exactly the configured `tsc` runs. Before, a script
459
+ changed to `tsc --noEmit && eslint .` was rewritten to `redue run
460
+ typecheck`, which ran tsc alone.
461
+ - Without a typecheck script, `init` proposes a `tsc --noEmit` check for a
462
+ root `tsconfig.json` (direct npm recipe, pnpm) and for each pnpm workspace
463
+ package with one, unless a script runs a TypeScript checker in another form
464
+ (`tsc -b`, `vue-tsc`, ...). package.json is not changed; the check is
465
+ written only when the contract holds.
466
+ - The pnpm contract no longer needs `include: ["src"]`. Its source inputs are
467
+ the directories the config's `include` covers, as TypeScript computes them
468
+ for new files, minus `node_modules`. `exclude` entries stay inputs, since an
469
+ import can still reach an excluded file. A config extended from an installed
470
+ package is an installed input.
471
+ - Fixed: a config with three or more pnpm or test checks never got a
472
+ synchronized answer. The observer dropped control requests over 4 KB, and a
473
+ sync request carries about 1.5 KB of context digests per check; status
474
+ showed "Unexpected end of JSON input" for every check. The limit is 1 MiB.
475
+
476
+ - The direct npm TypeScript recipe takes any TypeScript 5.x or 6.0, not only
477
+ the five reviewed releases. Another release qualifies when package-lock.json
478
+ records the registry's `typescript` at that version with an integrity
479
+ (sha512, or sha1 from registries that record only sha1), npm's cache holds
480
+ the tarball under it, and the installed package is exactly the tarball's
481
+ files. Nothing is downloaded; a missing tarball
482
+ keeps the check recording-only with `npm-tarball-uncached`. The check takes
483
+ about 100 ms per full probe (TypeScript 5.x and 6.0 tarballs, 120-140 files).
484
+ CI runs the direct contract suite against 5.0.4, 5.1.6, 5.2.2, 5.3.3, 5.4.5,
485
+ 5.5.4, 5.7.3 and 5.8.3.
486
+
487
+ - Contributors: `npm test` runs up to four test files at a time, keeping two
488
+ cores free (a 3-core CI macOS runner runs one at a time), and takes about
489
+ 6 minutes on the owner's Mac (was 19.6). The two TypeScript 6 fixture
490
+ suites are separate files so they run side by side.
491
+
492
+ ## 0.1.0-alpha.17 — 2026-10-22
493
+
494
+ Workspaces and package managers beyond npm. In the census of 108 public
495
+ TypeScript repos, the ones `init` makes ready went from 5 to 8 for typecheck
496
+ and from 6 to 22 for tests.
497
+
498
+ - pnpm 9-12 for the pnpm TypeScript contract (it took only an exact pnpm 12
499
+ pin). The installed `.modules.yaml` names the version; a pin is optional,
500
+ with or without Corepack's `+sha512` hash (pins with a hash never matched
501
+ before). `.npmrc` settings that only change what gets installed are
502
+ accepted; settings that move or copy installed files, or run code during
503
+ install, are refused in either file: custom modules, virtual-store or
504
+ lockfile directories, the global virtual store, injected workspace
505
+ packages, separate lockfiles, pnpmfile hooks, `configDependencies`.
506
+ - The tests recipe takes single-package pnpm 9-12 and Yarn `node-modules`
507
+ installs, and gives each workspace package (npm or Yarn `workspaces`, pnpm
508
+ `packages`) whose test script runs Vitest directly its own `PACKAGE:test`
509
+ check, run in the package directory. Inputs stay the whole checkout; every
510
+ package's node_modules is an installed input. Jest and root test scripts in
511
+ workspaces stay recording-only. A package added later makes the
512
+ workspace's checks UNVERIFIED until `init` runs again.
513
+ - A recorded test run is UNVERIFIED when an installed file has another hard
514
+ link: a package store outside the checkout (pnpm's default on Linux, Yarn's
515
+ hardlinks modes) could change it unseen. pnpm on macOS clones files and is
516
+ not affected; on Linux, pnpm test checks qualify but are not reused unless
517
+ pnpm copies files.
518
+ - Observer: an installed link to a directory (pnpm links every package) is
519
+ observed by its link chain when the target is itself observed installed;
520
+ any other directory link still makes observation unavailable.
521
+ - Workspace patterns honour `!pattern` exclusions; before, a negated pattern
522
+ matched every directory.
523
+ - Fixed: a new workspace package manifest did not re-plan a test check, for
524
+ npm workspaces too.
525
+
526
+ Eval on alpha.17 code (CI 39828002753, 84 sessions, test tasks on twilio,
527
+ cheerio and SwitchHosts plus the pnpm project devops-daily): 0 critical
528
+ findings; 23 skipped test runs, each passing three plain reruns; nothing was
529
+ skipped on devops-daily, whose recorded runs were UNVERIFIED on the Linux
530
+ runner.
531
+ ## 0.1.0-alpha.16 — 2026-10-22
532
+
533
+ Changes to the Claude Code integration, and one fix for commands that meet
534
+ on fresh state. Run `redue agent setup claude --apply` again to get the new
535
+ hook entries.
536
+
537
+ - A SessionStart hook starts the project's observer when a session starts,
538
+ resumes, clears or compacts, if none is running. It returns at once and
539
+ prints nothing. Without a running observer every check was UNVERIFIED, so
540
+ the hook could neither skip nor record. `agent doctor` reports it.
541
+ - The hook matches more command forms, each mapping to one configured check:
542
+ `pnpm SCRIPT`, `pnpm run SCRIPT`, `yarn SCRIPT`, `yarn run SCRIPT`,
543
+ `pnpm exec tsc ...`; for a workspace package's check, `pnpm --filter NAME
544
+ SCRIPT`, `yarn workspace NAME SCRIPT`, `npm run SCRIPT -w NAME`, and its
545
+ script after a `cd` into the package. In the census of 108 public
546
+ TypeScript repos, 61 use pnpm or Yarn.
547
+ - `turbo run TASK` and, in pnpm projects, `pnpm -r TASK` (or a root script
548
+ that is one of them) are skipped only when every workspace package with the
549
+ task's script has a check and all are CURRENT; otherwise they run as typed,
550
+ never rewritten. No skip when turbo may run more (other `dependsOn` tasks,
551
+ `with`, package-scoped keys, a package turbo.json), when pnpm includes the
552
+ workspace root, or for a root script with pre/post scripts. Filters and nx
553
+ are not matched.
554
+ - Fixed: when two commands met on fresh state (SessionStart's `start` and the
555
+ first `status`), the second failed and no observer started.
556
+
557
+ Pilot eval on alpha.16 code (CI 39799994225, 96 sessions over twilio,
558
+ semiotic, Ultra-Card and SwitchHosts): 0 critical findings; 29 skipped
559
+ typechecks, each confirmed by a plain rerun.
560
+ ## 0.1.0-alpha.15 — 2026-10-22
561
+
562
+ No change to observation, status or `redue run` since alpha.14; the changes
563
+ are to the Claude Code integration.
564
+
565
+ - The CLAUDE.md block now tells agents to run the typecheck or test command
566
+ before saying it passes, even after an edit that seems irrelevant, and to
567
+ leave skipping to REDUE's hook. In the alpha.14 eval, two of six mixed-task
568
+ sessions skipped their final test run on their own after a README edit;
569
+ with the new block, none of six did (twilio and SwitchHosts, CI
570
+ 39702429765), at the same token cost. Run `redue agent setup claude --apply`
571
+ again to update the block; the earlier wording is recognized and replaced.
572
+ - The hook also matches a typecheck or test command after a leading
573
+ `cd <project root>;` or `cd <project root> &&`. A skip denies the whole
574
+ command; a rewrite keeps the `cd`. A `cd` to any other directory matches
575
+ nothing.
576
+
577
+ ## 0.1.0-alpha.14 — 2026-10-21
578
+
579
+ Bench numbers below are from one 800-file project on macOS arm64, Node 22.13.0.
580
+ Released alpha.13 and this build ran interleaved on the same machine; the
581
+ typecheck decision path is unchanged within noise (warm `status --sync` 162/157
582
+ ms on alpha.13, 169/166/289 ms on alpha.14; `redue run` overhead 12/14% and
583
+ 12/7/18%; states correct, no idle probe launches).
584
+
585
+ - New opt-in recipe for unit tests: `redue init --recipe tests-direct --check
586
+ test` records a single-package npm project's Vitest 4/5 or Jest 29 run on
587
+ macOS and Linux. The check's inputs are the whole checkout (minus `*.md`,
588
+ `*.mdx` and, with `--coverage`, `coverage/`), the installed files, the Node
589
+ binary, the exact command, and every environment variable the run's
590
+ JavaScript reads directly, compared by value. A recorder loaded into every
591
+ Node process and worker thread of the run guards the rest: reading an
592
+ excluded or git-ignored file, a directory listing or large file outside the
593
+ checkout, network use other than loopback, or a process that escaped the
594
+ recorder makes the result UNVERIFIED with the reason. Lookups outside the
595
+ checkout become run facts that status checks again. Two runs on the same
596
+ inputs with different results make the check UNVERIFIED until the inputs
597
+ change. See [direct tests](docs/user/tests-direct.md) for the claim and its
598
+ limits.
599
+ - Claude Code: the hook skips or records a direct test check's runs (`npm run
600
+ <script>`, `npm test`, the script's own command) like the typecheck's.
601
+ - Linux: a directory created or deleted in the checkout is now an event, not
602
+ an observation gap. Before, every new directory forced a full reconciliation,
603
+ and a second one during it left the observer UNVERIFIED (`plan_gap`).
604
+ - An excluded installed path appearing (a runner cache, a TypeScript build-info
605
+ file) no longer changes the input plan. Checks with such an exclusion are
606
+ STALE with "input plan changed" once after the upgrade, until their next run.
607
+ - Measured with Claude Code on three public projects (Sonnet 5.5, CI Linux,
608
+ 72 sessions): agents skipped 21 test runs, every skip confirmed by three
609
+ plain reruns on its tree, and session time fell from 515 to 295 s summed over
610
+ the task medians. In two sessions the agent itself left out its final test
611
+ run after a README-only edit, without asking REDUE; both said so, and the
612
+ final trees passed.
613
+
614
+ ## 0.1.0-alpha.13 — 2026-10-19
615
+
616
+ Bench numbers below are from one 800-file project on macOS arm64, Node 22.13.0.
617
+ Released alpha.12 and this build ran interleaved on the same machine; the
618
+ decision path is unchanged within noise (warm `status --sync` 192/197 ms on
619
+ alpha.12, 174/198 ms on alpha.13; states correct, no idle probe launches).
620
+ On the CI screen of 38 public TypeScript projects, 22 qualify for the direct
621
+ recipe, up from 19 at alpha.12: worldmonitor, Recordly and open-cowork, which
622
+ the fixed 5 s probe deadline blocked.
623
+
624
+ - A full state probe may run longer on large projects. Its deadline was a
625
+ fixed 5 s (10 s on Windows and for pnpm); now it is the larger of twice the
626
+ last successful probe and the last completed run, at least that floor and at
627
+ most 60 s, doubling after a timeout. A probe that never finishes is still
628
+ killed at its deadline and the check stays UNVERIFIED. `redue status --sync`
629
+ and `redue run` wait for the observer up to the sum of its checks' probe
630
+ deadlines plus 10 s (`probe_deadline_ms` in status JSON), never less than
631
+ before. While a full probe runs the observer does not answer, so with a hung
632
+ probe a decision can wait up to 60 s per check before it is UNVERIFIED.
633
+
634
+ ## 0.1.0-alpha.12 — 2026-10-19
635
+
636
+ Bench numbers below are from one 800-file project on macOS arm64, Node 22.13.0.
637
+ Released alpha.11 and this build ran interleaved on the same machine; the
638
+ decision path is unchanged within noise (warm `status --sync` 183/410 ms on
639
+ alpha.11, 298/174 ms on alpha.12; states correct, no idle probe launches).
640
+ On a screen of 38 public TypeScript projects in CI, 10 qualified for the
641
+ direct recipe before the run-facts change, 17 after it and 19 after incremental
642
+ and references support. worldmonitor and Recordly now stop at the 5 s probe
643
+ timeout, and open-cowork at its end-checkpoint probe.
644
+
645
+ - Large installations reach ready quickly. Installed files are observed by
646
+ identity (inode, size, mode, link count, times), not by hashing their contents;
647
+ the compiler's own reads stay content-checked by the probe. On macOS:
648
+ Recordly (75k files in `node_modules`) ready in 7 s instead of failing after
649
+ 120 s; worldmonitor (143k) in 30 s instead of not ready after 15 min.
650
+ Behavior change: reinstalling identical packages, restoring an installed
651
+ file's bytes or copying the installation now makes the check STALE once.
652
+ - The direct TypeScript recipe supports TypeScript 6.0.2 and 6.0.3.
653
+ - Claude Code: the typecheck hook also matches a typecheck that starts a `;` or
654
+ `&&` chain. When it skips one, the message names the rest of the chain. The
655
+ skill lists the exact commands the hook matches for the selected config.
656
+ - Shorter agent instructions: the CLAUDE.md block is 235 bytes instead of 739,
657
+ the skill 1.8 KB instead of 5 KB. The reuse rules are unchanged. When the
658
+ Claude Code hook matches a typecheck, the block no longer points to the
659
+ skill; the skill stays for agents that look for it.
660
+ - Claude Code hook: it waits for status up to half the last completed run's
661
+ duration, at most 10 s, instead of a fixed 2 s. Run `redue agent setup claude
662
+ --apply` again to raise the hook's Claude Code timeout from 5 s to 15 s.
663
+ - Linux: the observer no longer watches `.git` directories. Before, each new
664
+ directory git created there (on most commits) was an observation gap: status
665
+ was UNVERIFIED until a full reindex and probe finished, about 5 s on a
666
+ 26k-file project. Input patterns that name a `.git` directory are now
667
+ refused; REDUE never observed changes there.
668
+ - Direct TypeScript recipe: runs with `declaration: true` are reusable. tsc's
669
+ declaration checks look up files that building the program does not, and
670
+ read dependencies' `package.json`; before, any such lookup made the run
671
+ UNVERIFIED. The receipt now keeps those existence, `realpath` and
672
+ `package.json` answers as run facts, and status asks them again before every
673
+ CURRENT answer, including when a cached status is read. Every direct run is
674
+ now recorded, also one checked by full probes. The probe also records
675
+ `realpath` while it parses a tsconfig `extends` from a package.
676
+ Behavior change: a direct receipt recorded by an earlier version is
677
+ UNVERIFIED until the check runs again (macOS and Linux). Limit: Windows does
678
+ not record direct runs, so declaration-only lookups are not checked there.
679
+ - Direct TypeScript recipe: a root tsconfig with `incremental: true` is
680
+ supported. Its build-info file is left out of the inputs, and the run may
681
+ write only that file. A root tsconfig that references a composite config
682
+ (such as Vite's `tsconfig.node.json`) is supported when the program does not
683
+ use the referenced project's files. A `composite` root is still refused.
684
+ - Releases are published to the `latest` npm tag as well as `alpha`, so
685
+ `npm install -g @redue/cli` installs the newest release.
686
+
687
+ ## 0.1.0-alpha.11 — 2026-10-18
688
+
689
+ Bench numbers below are from one 800-file project on macOS arm64, Node 22.13.0.
690
+ Released alpha.10 and this build ran back to back on the same machine.
691
+
692
+ - Faster status decisions for the direct TypeScript recipe on macOS and Linux.
693
+ The observer checks the compiler's recorded filesystem questions in-process
694
+ instead of starting a probe that rebuilds the whole program. A full probe runs
695
+ only when that check fails, the plan or toolchain changes, or observation was
696
+ interrupted. While idle it no longer starts any probe process.
697
+ - warm `status --sync`: 741 → 194 ms (+683 → +154 ms over cached `status`)
698
+ - `status --sync` after an unrelated edit: 619 → 219 ms
699
+ - `status --sync` after a relevant edit: 1472 → 321 ms. It answers STALE without
700
+ a full probe when the edited inputs already differ from the receipt.
701
+ - probe processes started in 20 s idle: 4 → 0
702
+ - Cheaper `redue run` on macOS and Linux. The compiler records its own inputs
703
+ while it runs, so REDUE no longer probes before and after the compile. After
704
+ a relevant edit, the run builds the new certificate from that recording instead
705
+ of running a full probe. Output and exit code are those of plain `tsc`.
706
+ - repeat run: 4143 → 2752 ms, overhead over plain `tsc` 72% → 16%
707
+ - run right after a relevant edit: 3990 → 2802 ms, overhead 65% → 18%
708
+ - The direct TypeScript recipe accepts inert Node settings. Before, any non-empty
709
+ `NODE_*` setting other than `NODE_ENV` kept a check from becoming CURRENT.
710
+ Now accepted: `NODE_EXTRA_CA_CERTS`, `NODE_PATH`, and `NODE_OPTIONS` made only of
711
+ `--max-old-space-size`, `--max-semi-space-size`, `--use-openssl-ca`,
712
+ `--use-bundled-ca`, `--use-system-ca` and `--dns-result-order`. A run under one
713
+ value is not reused under another. See [Node settings](docs/user/direct-typescript.md#node-settings).
714
+ - `redue agent setup claude --apply` adds a Claude Code hook to
715
+ `.claude/settings.local.json`. When the agent reruns a configured typecheck
716
+ that is CURRENT and PASS, the hook blocks it and names the passing run. When
717
+ the check is not CURRENT, it rewrites the command to `redue run CHECK`, so the
718
+ result is recorded and the next identical command can be skipped. Prefix a
719
+ command with `REDUE_FORCE=1` to always run it. On the bench: a skip decision
720
+ takes about 155 ms; a forced command adds 39 ms. Tested live with Claude Code
721
+ 2.1.302 (`claude -p`). See [the hook](docs/user/agents.md#claude-code-typecheck-hook).
722
+ - Unstable-run and observation-gap reasons now name the failed check or operation.
723
+ - macOS counts each input event once, which removes an intermittent UNVERIFIED
724
+ after an edit.
725
+
726
+ Known limits:
727
+
728
+ - Two bench targets are still missed: warm sync adds 154 ms over cached status
729
+ (target < 100 ms), and `redue run` adds 16–18% over plain `tsc` (target < 10%).
730
+ - An edit that changes imports, configuration or lib files still costs one full
731
+ probe, at the end of the next run.
732
+ - Windows keeps the earlier probe-based path, except the STALE shortcut. Yarn
733
+ and pnpm recipes still probe on each decision. The bench was not run on Linux.
734
+ - The Claude hook covers the Bash tool only, from the project root. It allows the
735
+ rewritten command without a permission prompt. It judges its own environment,
736
+ not variables the Bash tool adds from your shell profile.
737
+ - To upgrade, stop observers, install into the same prefix, and keep config, state
738
+ and receipts. Rerun `redue agent setup claude --apply` to add the hook.
739
+
740
+ ## 0.1.0-alpha.10 — 2026-10-10
741
+
742
+ - Combine guarded caller-discovery reuse and cheaper non-reusable recording on
743
+ the existing macOS direct-TypeScript path. Healthy runs still validate both
744
+ boundaries in the caller context, falling back to full probes when necessary.
745
+ - Once a healthy start observation is missing, omit qualification-only work that
746
+ cannot repair it. Execute the configured compiler and durably record its true
747
+ outcome; later observer recovery cannot make that invocation reusable.
748
+ - Refuse missing, malformed or mismatched state ownership before execution.
749
+ Preserve cancellation, immutable history and newest-receipt selection.
750
+ - Three fixed A–H cycles cost 15.16/15.35/15.82 seconds versus matched ordinary
751
+ compiler totals of 16.69/16.66/16.56 seconds. These modest CLI savings do not
752
+ establish real-world reuse frequency, CPU/memory or whole-agent benefit.
753
+ - Provide a [fixed-build opt-in pilot guide](docs/user/pilot.md). External usage
754
+ has not started. No compiler/platform expansion or policy redesign is included;
755
+ Claude behavior and cross-host handoff remain untested.
756
+ - Stop observers before upgrading in the same prefix, preserve config/state and
757
+ receipts, preview/apply project-local policy updates, then restart and reassess.
758
+ Never silently migrate a check. Alpha.9 remains an unshipped candidate.
759
+
760
+ ## 0.1.0-alpha.9 — unshipped candidate (2026-10-09)
761
+
762
+ - Reduce repeated caller discovery on the guarded macOS direct-TypeScript path.
763
+ Both execution boundaries still validate in the actual caller environment,
764
+ with full-probe fallback when a discovery certificate cannot be used.
765
+ - Preserve required content/membership, compiler/context, observation and durable
766
+ receipt-selection guards. The configured compiler still executes on every run.
767
+ - Recording overhead fell in the measured debugger-project sample, but every
768
+ complete A–H candidate cycle remained slower than eight ordinary compiler runs.
769
+ No net workflow saving, broader support or CPU/memory improvement is claimed.
770
+ - Stop observers before upgrading in the existing prefix, retain config/state
771
+ and receipts, then restart. No automatic migration is performed.
772
+
773
+ ## 0.1.0-alpha.8 — 2026-10-08
774
+
775
+ - Consume compiler-certificate input asynchronously while preserving the input-size
776
+ limit, parent deadline, complete-input validation and conservative fallbacks.
777
+ - Support the exact reviewed TypeScript 5.5.2 distribution in the explicitly selected
778
+ single-package npm direct-compiler recipe. Enforce implementation membership and
779
+ reject ETW module overrides before compiler API loading.
780
+ - Real independent Codex/macOS sessions reused compiler evidence on the pinned
781
+ vscode-js-debug project. Cross-platform CLI/package acceptance is separate;
782
+ Claude behavior and cross-host handoff remain untested.
783
+ - The measured eight-case workflow avoided four compiler executions but cost
784
+ 20.01 seconds versus 16.97 seconds for eight ordinary compiler runs. No net
785
+ workflow or whole-agent speedup is claimed. This verifies compiler inputs only,
786
+ not npm lifecycle behavior or application correctness.
787
+ - Stop observers before upgrading, retain the same configuration/state, then
788
+ restart. Do not delete receipts or automatically convert existing checks.
789
+
790
+ ## 0.1.0-alpha.7 — 2026-10-07
791
+
792
+ - Guide explicitly configured direct-compiler reuse through one caller-aware
793
+ synchronized query; skip reuse queries when fresh execution is already required.
794
+ - Update intact project-local agent instructions safely; installation alone does
795
+ not update them. See the [existing-user procedure](docs/user/agents.md#update-an-existing-connection).
796
+ - In the finite Codex/macOS comparison, revised guidance reached eligible evidence
797
+ and reused it in 4/4 opportunities versus 1/4; verification tool calls fell
798
+ from 28 to 14. Evidence semantics are unchanged. No universal compliance,
799
+ tail-latency or causal agent-task speedup is claimed. Claude behavior and
800
+ cross-host handoff remain untested.
801
+
802
+ ## 0.1.0-alpha.6 — 2026-10-07
803
+
804
+ - Reuse guarded compiler discovery for warm direct-TypeScript decisions on macOS
805
+ with healthy historical observation. Membership, absence, compiler bytes,
806
+ caller context and receipt selection remain validated independently.
807
+ - Keep full discovery/reconciliation fallbacks and existing platform boundaries.
808
+ - On one measured project, complete warm decision median fell from roughly
809
+ 791 to 474 ms. This is not a universal speedup, agent-task acceleration,
810
+ memory improvement, or a faster relevant-edit/rebuild claim.
811
+ - Stop observers before upgrading and restart with the same config/state.
812
+ Preserve receipts; no configuration migration is performed.
813
+
814
+ ## 0.1.0-alpha.5 — 2026-10-07
815
+
816
+ - Add opt-in project-local agent activation and direct TypeScript evidence, with
817
+ fresh-session reuse demonstrated in the tested Codex/macOS configuration.
818
+ - Preserve ordinary npm execution as a separate, recording-only obligation.
819
+ Direct compilation requires explicit selection and a fresh baseline receipt.
820
+ - Initial direct recipe supports reviewed TypeScript 5.6.3/5.9.3 in single-package
821
+ npm projects, with documented Node/environment restrictions.
822
+ - Claude integration mechanics are tested; Claude behavior and cross-host reuse
823
+ remain untested. No universal compliance or inexpensive-check speedup is claimed.
824
+
825
+ ## 0.1.0-alpha.4 — 2026-10-07
826
+
827
+ - Withdraw automatic npm-launcher applicability because update notifications consume
828
+ unobserved remote/cache/time state. Npm scripts still run and record outcomes.
829
+ - Preserve historical PASS/FAIL and require stop/start when upgrading an observer.
830
+ Do not delete receipts. See the [maintainer notice](docs/user/npm-launcher-notice.md).
831
+ - Supported Yarn/pnpm and explicit reviewed contracts are unchanged. No agent
832
+ activation or npm direct-compiler recipe is included in this correction.
833
+
3
834
  ## 0.1.0-alpha.3 — 2026-10-06
4
835
 
5
836
  Install: `npm install --global @redue/cli@alpha`.