@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.
- package/CHANGELOG.md +831 -0
- package/README.md +157 -99
- package/bin/redue.mjs +322 -66
- package/docs/README.md +3 -1
- package/docs/user/agents.md +333 -15
- package/docs/user/configuration.md +28 -2
- package/docs/user/direct-typescript.md +219 -0
- package/docs/user/getting-started.md +50 -7
- package/docs/user/json.md +4 -2
- package/docs/user/node-script.md +177 -0
- package/docs/user/npm-launcher-notice.md +42 -0
- package/docs/user/pilot.md +146 -0
- package/docs/user/sandbox.md +326 -0
- package/docs/user/shell.md +3 -3
- package/docs/user/supported-projects.md +69 -23
- package/docs/user/tests-direct.md +143 -0
- package/package.json +4 -3
- package/src/agent-integration.mjs +467 -0
- package/src/agent-policy.md +28 -0
- package/src/cached-state.mjs +24 -1
- package/src/claude-hook.mjs +616 -0
- package/src/cli.mjs +449 -54
- package/src/daemon.mjs +442 -93
- package/src/decision-profile.mjs +15 -1
- package/src/decision-validation.mjs +12 -1
- package/src/declared-plan.mjs +38 -6
- package/src/direct-run-certificate.mjs +254 -0
- package/src/direct-typescript-probe.mjs +27 -0
- package/src/direct-typescript.mjs +205 -0
- package/src/glob.mjs +8 -0
- package/src/history-worker.mjs +21 -13
- package/src/index.mjs +108 -21
- package/src/installed-inputs.mjs +7 -1
- package/src/installed-observation.mjs +23 -0
- package/src/landlock.py +527 -0
- package/src/linux-inotify.py +39 -10
- package/src/node-onboarding.mjs +203 -54
- package/src/node-script.mjs +406 -0
- package/src/npm-integrity.mjs +124 -0
- package/src/npm-typecheck-environment.mjs +36 -0
- package/src/npmrc.mjs +16 -0
- package/src/observation.mjs +34 -12
- package/src/path-identity.mjs +8 -0
- package/src/plan-worker.mjs +17 -17
- package/src/pnpm-inputs.mjs +122 -57
- 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 +13 -4
- package/src/probe-deadline.mjs +37 -0
- package/src/probe-result.mjs +7 -3
- package/src/project-location.mjs +34 -0
- package/src/python-onboarding.mjs +89 -0
- package/src/run-recorder.cjs +91 -0
- package/src/sandbox.mjs +659 -0
- package/src/setup.mjs +224 -0
- package/src/stats.mjs +72 -0
- package/src/test-direct.mjs +608 -0
- package/src/test-recorder.cjs +435 -0
- package/src/typescript-contract-probe.mjs +4 -187
- package/src/typescript-input-facts.mjs +92 -0
- package/src/typescript-invocation.mjs +92 -0
- package/src/typescript-list.mjs +118 -13
- package/src/typescript-qualification.mjs +29 -49
- package/src/workspace-manifests.mjs +24 -0
- package/src/yarn-workspace-inputs.mjs +3 -0
- package/src/yarn-workspace-typecheck-probe.mjs +2 -1
package/docs/user/agents.md
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
# Agent decision policy
|
|
2
2
|
|
|
3
|
-
Use the CLI
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
1.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
Use the CLI with explicit project-local activation below, or add this policy to a
|
|
4
|
+
generic agent's instructions with the project owner's permission.
|
|
5
|
+
|
|
6
|
+
1. If fresh execution is already required, execute it; do not synchronize merely
|
|
7
|
+
to confirm an irrelevant reuse opportunity. Use `redue run CHECK` when recording
|
|
8
|
+
the configured check. An explicit npm-script request still requires npm.
|
|
9
|
+
2. For reuse of the explicitly configured direct compiler recipe
|
|
10
|
+
(`qualification: "npm-typescript-direct-v1"`, direct compiler command; receipt
|
|
11
|
+
`verification_recipe: "npm-direct-typescript@1"`), query once:
|
|
12
|
+
`redue --config CONFIG status --sync --json`. Do not infer a recipe from its name.
|
|
13
|
+
Cached status cannot establish its caller context. In mixed configurations,
|
|
14
|
+
assess each check's contract separately; this is not a global sync-first policy.
|
|
15
|
+
3. For other/unknown recipes, `status --json` synchronizes too (`--sync` is the
|
|
16
|
+
same); `status --cached --json` and `--short` remain cheap inspection.
|
|
17
|
+
4. Reuse only schema 1, healthy observation and the selected check's CURRENT/PASS
|
|
18
|
+
with `reuse_eligible: true`. Missing eligibility means false. A historical FAIL
|
|
19
|
+
is never green evidence. Do not rerun eligible evidence merely for freshness.
|
|
20
|
+
5. STALE requires execution when verification is needed. UNVERIFIED requires an
|
|
21
|
+
honest choice of synchronization, permitted execution or reporting the limitation.
|
|
22
|
+
Recording-only success can remain UNVERIFIED. A deliberate cheap-check rerun is
|
|
23
|
+
permitted; there are no universal platform/package-manager timing thresholds.
|
|
24
|
+
6. Use a successful synchronized response for the current decision without repeated
|
|
25
|
+
sync/explain calls unless edits, context changes or missing information require it.
|
|
26
|
+
Do not loop until green or use an earlier response after a later query fails.
|
|
18
27
|
|
|
19
28
|
`redue explain CHECK --json` gives synchronized detail, including a known changed
|
|
20
29
|
input when available. It has the same cost caveat as synchronized status.
|
|
@@ -25,8 +34,317 @@ check is not universal product correctness. Report additional uncaptured checks
|
|
|
25
34
|
separately. Do not infer that an outer invocation's success proves a specific
|
|
26
35
|
check ran or that an upstream cache was hit; inspect `target_provenance`.
|
|
27
36
|
|
|
37
|
+
Reassess at the decision point after edits or context changes; previous CURRENT is
|
|
38
|
+
not continuing authorization. A status exit code of zero is not proof of CURRENT.
|
|
39
|
+
An empty changed-input list does not prove nothing changed. `run CHECK --json`
|
|
40
|
+
streams check output; use a subsequent status/explain query for structured evidence.
|
|
41
|
+
Explicit fresh-execution requests still require execution.
|
|
42
|
+
|
|
28
43
|
On a CLI error, unhealthy observation, or unavailable context, do not infer
|
|
29
44
|
CURRENT. Do not delete state or reset receipts to make the output green.
|
|
30
45
|
|
|
31
46
|
REDUE tells you what evidence exists and whether it still applies. It does not
|
|
32
47
|
promise that establishing applicability is cheaper than every possible check.
|
|
48
|
+
|
|
49
|
+
## Connect once (experimental)
|
|
50
|
+
|
|
51
|
+
Alpha.5 and later support opt-in project-local activation and direct
|
|
52
|
+
TypeScript evidence, with fresh-session reuse demonstrated for Codex CLI 0.160.1
|
|
53
|
+
and subsequent 0.162.0 trials on macOS under the documented owner-approved checkout/state/socket route. CLI
|
|
54
|
+
mechanics are tested on macOS/Linux/Windows; model behavior is not claimed for
|
|
55
|
+
every host/platform or sandbox policy. Claude setup/removal mechanics are tested,
|
|
56
|
+
but Claude behavior and cross-host reuse remain untested. Reuse is not guaranteed,
|
|
57
|
+
and the existing subsecond example establishes no meaningful net time saving.
|
|
58
|
+
|
|
59
|
+
After installing REDUE and running `redue init` in a trusted project:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
redue agent setup codex --dry-run
|
|
63
|
+
redue agent setup codex --apply
|
|
64
|
+
# Or: redue agent setup claude --apply
|
|
65
|
+
redue agent doctor
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Start a fresh agent session in this checkout, then give it your ordinary task.
|
|
69
|
+
Interactive setup shows the changes and asks before applying; noninteractive
|
|
70
|
+
setup requires `--apply`. `--dry-run` never writes. Installing REDUE or running
|
|
71
|
+
`init` does not connect an agent automatically. Setup does not start an observer
|
|
72
|
+
or execute verification. With Claude Code, a SessionStart hook starts the
|
|
73
|
+
observer when a session starts (below); otherwise use `redue start`.
|
|
74
|
+
|
|
75
|
+
## Claude Code typecheck hook
|
|
76
|
+
|
|
77
|
+
`redue agent setup claude --apply` (and `redue setup claude`) also adds a
|
|
78
|
+
PreToolUse hook and a SessionStart hook to `.claude/settings.local.json`.
|
|
79
|
+
Both run `redue agent hook claude`, which needs a local REDUE install, so
|
|
80
|
+
they are per-developer; keep that file out of commits. Setup names REDUE
|
|
81
|
+
plainly only when the `redue` that both your shell and a login shell find on
|
|
82
|
+
PATH is the install running setup. Otherwise the hooks name this install's
|
|
83
|
+
Node and entry by absolute path, so a Claude Code started from an IDE, a
|
|
84
|
+
desktop app or another shell still runs the right REDUE; run setup again
|
|
85
|
+
after moving or upgrading Node. `redue agent doctor` reports a hook whose
|
|
86
|
+
paths no longer exist. When the hook runs a check through REDUE for the
|
|
87
|
+
agent, it likewise writes plain `redue run` only if its own PATH finds this
|
|
88
|
+
install, else the absolute form.
|
|
89
|
+
|
|
90
|
+
Agents often chain an edit and a check (`printf … >> README.md && npm run
|
|
91
|
+
lint`). In a simple chain (commands joined by `&&`, `||` or `;`, with no
|
|
92
|
+
subshell, here-document, command substitution, background job or shell
|
|
93
|
+
keyword) where every part before a check is a program on PATH (not a
|
|
94
|
+
builtin such as `cd` or `export`, a shell function such as `nvm`, or a bare
|
|
95
|
+
assignment), the hook rewrites each check to `redue run CHECK --if-due`. That
|
|
96
|
+
command decides when its turn comes, after the earlier parts may have
|
|
97
|
+
changed files: it skips the check (exit 0, and says so) when its last pass
|
|
98
|
+
still applies, and otherwise runs it through REDUE with the exit code a plain
|
|
99
|
+
run gives. A script that runs several checks becomes `{ redue run a --if-due
|
|
100
|
+
&& redue run b --if-due; }`. The rest of the chain is unchanged. The hook
|
|
101
|
+
rewrites only while the observer is healthy and knows each check. It changes
|
|
102
|
+
such a command without approving it, so your permission rules apply to the
|
|
103
|
+
rewritten command; a rule that allows only `npm run lint` will ask about
|
|
104
|
+
`redue run lint --if-due`. Anything more complex runs untouched. Known
|
|
105
|
+
limit: if REDUE cannot start the check when its turn comes (another
|
|
106
|
+
`redue run` holds the project's run lock), that part exits with REDUE's
|
|
107
|
+
error instead of running the check. Other settings in the file are kept,
|
|
108
|
+
but the file is rewritten as 2-space JSON. `.claude/settings.json` is not touched.
|
|
109
|
+
`redue agent remove claude --apply` removes only the entries REDUE added.
|
|
110
|
+
|
|
111
|
+
When a session starts, resumes, clears or compacts, the SessionStart hook starts
|
|
112
|
+
this project's observer if none is running. It launches `redue start` in the
|
|
113
|
+
background and returns at once, and prints nothing, so it adds nothing to the
|
|
114
|
+
agent's context. Until the observer's first index is done, checks are
|
|
115
|
+
UNVERIFIED and run as typed. An observer you stopped with `redue stop` starts
|
|
116
|
+
again with the next session; remove the hook to prevent that. Setups from
|
|
117
|
+
alpha.15 or earlier get the hook by running `redue agent setup claude --apply`
|
|
118
|
+
again.
|
|
119
|
+
|
|
120
|
+
The hook skips an exact rerun of a configured typecheck (a check with
|
|
121
|
+
`kind: "typecheck"` or named `typecheck`) or direct test check. It matches
|
|
122
|
+
these commands, run from the project root:
|
|
123
|
+
|
|
124
|
+
- `redue run CHECK`, or `redue --config FILE run CHECK` when the config is not
|
|
125
|
+
`redue.config.json`
|
|
126
|
+
- the check's script through the project's package manager: `npm run SCRIPT`
|
|
127
|
+
(and `npm test`), `pnpm SCRIPT`, `pnpm run SCRIPT`, `yarn SCRIPT` or
|
|
128
|
+
`yarn run SCRIPT`. The short form is left out when the script is named like
|
|
129
|
+
one of the package manager's own commands.
|
|
130
|
+
- the tool the check runs: `npx tsc ARGS` (and `pnpm exec tsc ARGS` with pnpm)
|
|
131
|
+
for a direct TypeScript check, or the runner's command, alone or after `npx`,
|
|
132
|
+
for a direct test check
|
|
133
|
+
- the check's `command`, when it has no `@` tokens
|
|
134
|
+
- for a workspace package's check: `pnpm --filter NAME SCRIPT` (also
|
|
135
|
+
`--filter=NAME`, `-F NAME`, and with `run`), `yarn workspace NAME SCRIPT`, or
|
|
136
|
+
`npm run SCRIPT -w NAME` (also `--workspace NAME`, `--workspace=NAME` and
|
|
137
|
+
`npm -w NAME run SCRIPT`). After `cd` into the package's directory, the
|
|
138
|
+
package-manager script forms and tool forms match that check.
|
|
139
|
+
|
|
140
|
+
A `turbo run TASK` (or `turbo TASK`, alone or after `npx` or `pnpm exec`) or,
|
|
141
|
+
in a pnpm project, `pnpm -r TASK` (`--recursive`, with or without `run`) that
|
|
142
|
+
runs a checked task in every workspace package is skipped only when every check
|
|
143
|
+
it would run is CURRENT, PASS and `reuse_eligible`. Every package with the
|
|
144
|
+
task's script must have a check. turbo must define the task, with `dependsOn`
|
|
145
|
+
listing at most `^TASK`, no `with`, no `PACKAGE#TASK` entries and no package
|
|
146
|
+
`turbo.json`; `pnpm -r` must not include the workspace root. A root script
|
|
147
|
+
whose text is such a command counts as that command, unless it has pre- or
|
|
148
|
+
post-scripts. In every other case the command runs as typed: turbo caches its
|
|
149
|
+
own results, so the hook never rewrites it. Filters (`--filter`) and nx are not
|
|
150
|
+
matched.
|
|
151
|
+
|
|
152
|
+
For a typecheck check that runs the compiler, the script's forms act only when
|
|
153
|
+
the script in package.json still has exactly the configured runs: one `tsc`
|
|
154
|
+
run per check with the same arguments, and no pre- or post-script. Otherwise
|
|
155
|
+
the command runs as typed. A script that chains `tsc` runs with `&&` has one
|
|
156
|
+
check per run, `typecheck.1`, `typecheck.2` and so on (see
|
|
157
|
+
[direct TypeScript](direct-typescript.md#script-forms)); each run's own
|
|
158
|
+
`npx tsc ...` form matches its check. The hook skips the script when all its
|
|
159
|
+
runs are CURRENT, PASS and `reuse_eligible`, and otherwise rewrites it to
|
|
160
|
+
`redue run` of the runs that are not, in the script's order, joined by `&&`.
|
|
161
|
+
In a turbo or `pnpm -r` fan-out, a package's script counts only the same way.
|
|
162
|
+
|
|
163
|
+
Each form may end with `2>&1` and then one `| tail -n N`, `| head -n N`,
|
|
164
|
+
`| tail -N` or `| head -N`. It may also be the first command of a `;` or `&&`
|
|
165
|
+
chain. Nothing else matches. Each form has its own `if` rule, so other Bash
|
|
166
|
+
commands never start the hook. The installed skill lists these exact commands,
|
|
167
|
+
so the agent uses forms the hook recognizes.
|
|
168
|
+
|
|
169
|
+
On a match, the hook runs `redue status --sync --json`. It waits up to half the
|
|
170
|
+
duration of the check's last completed run, at least 2 seconds and at most 10
|
|
171
|
+
seconds. A status call usually takes 70-250 ms, so a fast check (mypy in 0.2 s)
|
|
172
|
+
is still skipped when CURRENT, or run through `redue run` and recorded when not.
|
|
173
|
+
When the observer is slow or stuck, a matching command can wait the full 2
|
|
174
|
+
seconds before it runs as written. Claude Code's own limit for the hook is 15
|
|
175
|
+
seconds.
|
|
176
|
+
|
|
177
|
+
To see why the hook decided what it did, set `REDUE_HOOK_LOG` to an absolute
|
|
178
|
+
file path in the environment Claude Code starts with. The hook appends one JSON
|
|
179
|
+
line per Bash command: the command, the decision (`deny`, `rewrite` or
|
|
180
|
+
`allow`) and why, such as `no check matches the command` or `status did not
|
|
181
|
+
answer within 2000 ms`.
|
|
182
|
+
It blocks the command only when the check is CURRENT, PASS and
|
|
183
|
+
`reuse_eligible: true`. The message names the check and the receipt's run ID. Every
|
|
184
|
+
other result allows the command: STALE, UNVERIFIED, FAILED, a timeout, an error, or
|
|
185
|
+
a missing `redue`. A command that starts with `REDUE_FORCE=1` always runs. A
|
|
186
|
+
blocked chain runs none of its commands; the message names the rest of the chain
|
|
187
|
+
so the agent can run it on its own.
|
|
188
|
+
|
|
189
|
+
When the check is not CURRENT but the observer answered for it, the hook rewrites
|
|
190
|
+
the command to `redue run CHECK` and allows it, keeping any `2>&1` and
|
|
191
|
+
`| tail`/`| head` suffix. It adds `--config FILE` when the config is not
|
|
192
|
+
`redue.config.json`. The run is recorded, so the next identical command can be
|
|
193
|
+
skipped. Without a healthy answer (timeout, error, no observer) the command runs
|
|
194
|
+
as typed. Claude Code still applies deny and ask rules to the rewritten command.
|
|
195
|
+
A chain is never rewritten: the rewrite is allowed without a prompt, and that
|
|
196
|
+
would also skip the prompt for the rest of the chain.
|
|
197
|
+
|
|
198
|
+
Limits:
|
|
199
|
+
|
|
200
|
+
- The hook judges its own environment, which Claude Code passes to it. The Bash
|
|
201
|
+
tool can add variables from your shell profile. The hook cannot see those.
|
|
202
|
+
- Commands run from a session that started in a subdirectory, after a `cd`
|
|
203
|
+
outside the project, or combined with `||`, `&` or other pipes, are not
|
|
204
|
+
matched. After a `cd` into any other directory than the root or a checked
|
|
205
|
+
package's, nothing matches.
|
|
206
|
+
- A skip writes nothing. If a typecheck command also emits files, later
|
|
207
|
+
commands see the files from its last run.
|
|
208
|
+
- Only the Bash tool is covered, not PowerShell.
|
|
209
|
+
- Run setup again after you rename a check or script.
|
|
210
|
+
- The rewrite is allowed without a permission prompt, even where the original
|
|
211
|
+
command would have prompted.
|
|
212
|
+
|
|
213
|
+
## Update an existing connection
|
|
214
|
+
|
|
215
|
+
Installing a newer package does **not** rewrite project instructions. From the
|
|
216
|
+
same project and installation, stop every observer using that installation before
|
|
217
|
+
replacing it. Keep the original config and state selection; do not create a second
|
|
218
|
+
config or delete receipts. Example for a default npm installation/config:
|
|
219
|
+
|
|
220
|
+
```sh
|
|
221
|
+
redue --config redue.config.json stop
|
|
222
|
+
npm install --global @redue/cli@alpha
|
|
223
|
+
redue --config redue.config.json agent setup codex --dry-run
|
|
224
|
+
redue --config redue.config.json agent setup codex --apply
|
|
225
|
+
redue --config redue.config.json start
|
|
226
|
+
redue --config redue.config.json status --sync --json
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Use the **same `--prefix`** as the existing npm installation when it has a custom
|
|
230
|
+
prefix, and invoke its corresponding `redue` binary. Keep your actual config path
|
|
231
|
+
on every command. For Claude, select `claude` in both setup commands. Preserve any
|
|
232
|
+
existing `--state-dir` on lifecycle/status commands; setup does not embed custom
|
|
233
|
+
state locations, so retain the documented generic instruction path if your agent
|
|
234
|
+
workflow needs an explicit custom state. PowerShell may use the existing
|
|
235
|
+
`npm.cmd`/`redue.cmd` shims without changing script policy.
|
|
236
|
+
|
|
237
|
+
Review the preview before applying. Intact owned content updates; unrelated text
|
|
238
|
+
is preserved. Edited managed content is refused, not overwritten. If refused,
|
|
239
|
+
review/reconcile those edits deliberately; do not remove ownership records to force
|
|
240
|
+
an update. Restart the observer with its original selection even if you postpone
|
|
241
|
+
updating instructions, then start a **fresh agent session** after a successful
|
|
242
|
+
update. Setup creates no verification receipt.
|
|
243
|
+
|
|
244
|
+
Managed project metadata can itself be an observed input. Prior receipts remain
|
|
245
|
+
historical evidence, but setup may make them STALE or UNVERIFIED. Reassess normally
|
|
246
|
+
and run required checks; an upgrade is not a promise that existing receipts remain
|
|
247
|
+
CURRENT. Do not suppress that invalidation or reset state.
|
|
248
|
+
|
|
249
|
+
Codex gets a short managed section in project `AGENTS.md` that points to
|
|
250
|
+
`.agents/skills/redue-verification/SKILL.md`. Claude Code gets one in `CLAUDE.md`
|
|
251
|
+
that names the typecheck command the hook matches and says what a skip means,
|
|
252
|
+
plus `.claude/skills/redue-verification/SKILL.md`. The skill holds the reuse
|
|
253
|
+
rules and the exact commands for the selected config. When the hook matches a
|
|
254
|
+
typecheck, the `CLAUDE.md` section does not point to the skill: the hook does
|
|
255
|
+
the work, and the skill is there for agents that look for it. Small
|
|
256
|
+
ownership records in `.redue/agents/` support safe updates/removal. These are
|
|
257
|
+
portable project files, not receipts; review and commit them if the team wants
|
|
258
|
+
this integration. Do not ignore just the ownership records while committing the
|
|
259
|
+
managed files.
|
|
260
|
+
|
|
261
|
+
Existing instruction text is retained. Review it in the preview: setup cannot
|
|
262
|
+
prove arbitrary natural-language policies are consistent. Conflicts such as a
|
|
263
|
+
root `AGENTS.override.md` or an alternative `.claude/CLAUDE.md` are reported
|
|
264
|
+
instead of silently outranked. Global/managed policies, nested instructions,
|
|
265
|
+
Codex instruction-size limits, skill disabling, and host-specific exclusions
|
|
266
|
+
still apply. Complete the host's ordinary trust/permission prompts yourself;
|
|
267
|
+
REDUE never grants tool permission. Sandboxed hosts may need owner-approved access
|
|
268
|
+
to the checkout, owned state directory and local observer socket. A healthy daemon
|
|
269
|
+
does not establish that the agent can reach it; doctor reports control access
|
|
270
|
+
separately. Do not disable sandbox protections to make this work. Do not use a mode that disables project
|
|
271
|
+
instructions and expect automatic activation.
|
|
272
|
+
|
|
273
|
+
Control access is not simply file-read permission. The observer can reconcile and
|
|
274
|
+
write its owned index, run the trusted configuration's probes in its own process
|
|
275
|
+
context, reload receipts, and stop. Approve only the intended checkout/state and
|
|
276
|
+
endpoint, accounting for that authority. Doctor sends only a bounded metrics
|
|
277
|
+
request; it does not synchronize or run these probes.
|
|
278
|
+
|
|
279
|
+
`agent doctor [codex|claude] --json` is read-only. It distinguishes command lookup,
|
|
280
|
+
config resolution, cached observer health, a bounded read-only control-access probe,
|
|
281
|
+
managed-file integrity, detected host
|
|
282
|
+
version, and loading guidance. `behavior_verified: false` is deliberate: intact
|
|
283
|
+
files do not prove the agent followed them. For Claude, doctor reports whether the
|
|
284
|
+
typecheck hook is installed. Doctor neither
|
|
285
|
+
executes checks nor starts observers, reconciles inputs, or installs a host.
|
|
286
|
+
|
|
287
|
+
Doctor separates missing/unreadable state, a missing or refused endpoint, an
|
|
288
|
+
explicit EPERM/EACCES access denial, and timeout/invalid response. A denial does
|
|
289
|
+
not identify whether OS permissions or host policy caused it. A live PID and
|
|
290
|
+
healthy cached observation do not prove control access. An older cached response
|
|
291
|
+
without receipt-selection validation gets stop/start guidance. Windows command
|
|
292
|
+
shims whose target has not been established are reported as unknown, not a
|
|
293
|
+
proven installation mismatch.
|
|
294
|
+
|
|
295
|
+
Codex CLI 0.160.1 on macOS can use the approved exact observer-socket route while
|
|
296
|
+
other sockets and direct network access remain denied. Its independent sessions
|
|
297
|
+
receive different proxy values. Ordinary npm invocation is **not** equivalent
|
|
298
|
+
across arbitrary notifier state: REDUE withholds automatic npm-launcher
|
|
299
|
+
reuse. Do not change proxy settings or permissions to get green evidence.
|
|
300
|
+
|
|
301
|
+
The separate opt-in [direct local compiler recipe](direct-typescript.md) does not
|
|
302
|
+
run npm. Its reviewed compiler implementation does not consume npm/proxy settings;
|
|
303
|
+
a digest preserves their observed provenance without treating them as compiler
|
|
304
|
+
inputs. Other execution context remains strict, and cached status still cannot
|
|
305
|
+
assert caller eligibility. An explicit user request for `npm run typecheck` still
|
|
306
|
+
requires npm execution; direct compiler evidence is not a substitute.
|
|
307
|
+
|
|
308
|
+
Before model trials, run `redue agent doctor --json` and
|
|
309
|
+
`redue status --sync --json` inside the agent's actual command boundary. The
|
|
310
|
+
contributor helper `test/acceptance/codex-preflight.mjs --config FILE --check CHECK`
|
|
311
|
+
performs the same bounded, read-only decision check and exits 2 when reuse is not
|
|
312
|
+
eligible. It neither executes verification nor grants access; synchronization
|
|
313
|
+
may run configured probes. A successful outside-shell result is insufficient.
|
|
314
|
+
|
|
315
|
+
Use the same setup command after an upgrade; it updates intact managed
|
|
316
|
+
content idempotently. Changed skill text or a changed managed block causes a
|
|
317
|
+
conflict instead of an overwrite. Review your edits before retrying.
|
|
318
|
+
|
|
319
|
+
```sh
|
|
320
|
+
redue agent remove codex --dry-run
|
|
321
|
+
redue agent remove codex --apply
|
|
322
|
+
redue agent remove claude --apply
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Removal deletes only intact REDUE-owned content for that host. Unrelated text,
|
|
326
|
+
other integrations, project config, receipts and installed dependencies remain.
|
|
327
|
+
User edits outside the managed section survive. Modified managed content is left
|
|
328
|
+
intact with a diagnostic; compare it with a preview and resolve manually. Empty
|
|
329
|
+
parent directories may remain. If the selected config has been deleted, restore
|
|
330
|
+
it or manually remove only the marked REDUE section, that host's skill, and its
|
|
331
|
+
`.redue/agents/HOST.json` ownership record after review. Do not delete an entire
|
|
332
|
+
instruction file containing user content.
|
|
333
|
+
|
|
334
|
+
## Project identity and generic agents
|
|
335
|
+
|
|
336
|
+
Commands from nested directories search toward the nearest Git root. If more than
|
|
337
|
+
one configuration applies, select one with `--config FILE`; REDUE refuses to guess.
|
|
338
|
+
The generated skill names its project-relative configuration and gives the exact
|
|
339
|
+
status and run commands for it. External configs or custom machine-local `--state-dir`
|
|
340
|
+
setups should use a reviewed generic instruction instead of committing absolute
|
|
341
|
+
paths. Other worktrees and remote containers have separate local evidence.
|
|
342
|
+
|
|
343
|
+
For another agent, put a short instruction in its documented project mechanism:
|
|
344
|
+
“Before deciding whether configured verification needs repeating, read REDUE's
|
|
345
|
+
agent policy, identify the selected recipe and use its decision query for the intended config.
|
|
346
|
+
Apply the schema/health/reuse rules.” Supply this document and the
|
|
347
|
+
[JSON contract](json.md) as the detailed policy. Review the agent's actual tool
|
|
348
|
+
trace before calling activation verified. A local npm installation does not install
|
|
349
|
+
REDUE in a remote container; that environment needs its own CLI, checkout,
|
|
350
|
+
dependencies and state. There is no cloud/team receipt synchronization.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Configuration
|
|
2
2
|
|
|
3
|
-
Prefer `redue init` over hand-authoring a
|
|
4
|
-
|
|
3
|
+
Prefer `redue init` over hand-authoring a contract. An ordinary generated npm script (recording-only in this candidate)
|
|
4
|
+
configuration is concise and portable:
|
|
5
5
|
|
|
6
6
|
```json
|
|
7
7
|
{
|
|
@@ -28,6 +28,11 @@ Use `--config FILE` to select an external configuration. `root` is relative to
|
|
|
28
28
|
that file. Runtime paths, resolved executables, local evidence, and sockets stay
|
|
29
29
|
out of version-controlled configuration.
|
|
30
30
|
|
|
31
|
+
For the explicit direct compiler choice and generated exact argv, see
|
|
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).
|
|
35
|
+
|
|
31
36
|
## Arbitrary commands
|
|
32
37
|
|
|
33
38
|
An unrecognized ecosystem can still record ordinary execution:
|
|
@@ -53,5 +58,26 @@ Advanced explicit contracts may declare `generatedInputs`, `installedInputs`, na
|
|
|
53
58
|
reviewed escape hatches, not onboarding requirements. A coverage rationale cannot
|
|
54
59
|
override unsupported storage, unresolved links, missing inputs, or observation failure.
|
|
55
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
|
+
|
|
65
|
+
Input patterns are relative to the project root. They cannot name a `.git`
|
|
66
|
+
directory, because REDUE does not observe one; `!.git/**` is fine.
|
|
67
|
+
|
|
56
68
|
Changing commands, relevant configuration, installed material, or consumed inputs
|
|
57
69
|
invalidates prior applicability. It does not erase historical execution outcomes.
|
|
70
|
+
|
|
71
|
+
Installed inputs (under `node_modules` or other installed roots) are observed by
|
|
72
|
+
file identity: inode, size, mode, link count, and modification and change times.
|
|
73
|
+
REDUE does not read every installed file, so large installations become ready
|
|
74
|
+
quickly. Any write to an installed file makes dependent checks STALE until they
|
|
75
|
+
run again, even when it restores earlier bytes, reinstalls identical packages
|
|
76
|
+
(`npm ci`), copies the installation, or remounts it under another device. Timestamps tick in milliseconds, so a file
|
|
77
|
+
changed in the last 2 seconds could be rewritten at the same size without a new
|
|
78
|
+
identity; `redue run` waits until such files are 2 seconds old before it records
|
|
79
|
+
a checkpoint, which adds up to 2 seconds right after an install. Source files are
|
|
80
|
+
content-hashed, and the direct TypeScript recipe's probe content-checks every file
|
|
81
|
+
the compiler reads. The 2-second window assumes the filesystem clock matches this
|
|
82
|
+
machine's; on a network or VM-shared mount whose clock runs behind, keep the
|
|
83
|
+
installation on a local disk.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Explicit local TypeScript verification
|
|
2
|
+
|
|
3
|
+
This check means: the reviewed local TypeScript compiler completed the configured
|
|
4
|
+
check against declared, observed inputs and relevant execution context. It does
|
|
5
|
+
not mean npm or npm lifecycle scripts completed.
|
|
6
|
+
|
|
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)). TypeScript 7 is a native
|
|
11
|
+
compiler this recipe cannot run: `init` refuses it
|
|
12
|
+
(`direct-typescript-version-unsupported`):
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
redue init --recipe typescript-direct --check typecheck --dry-run
|
|
16
|
+
redue init --recipe typescript-direct --check typecheck
|
|
17
|
+
redue start
|
|
18
|
+
redue run typecheck
|
|
19
|
+
redue status --sync
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The preview shows the discovered script and recorded direct invocation. Nothing
|
|
23
|
+
executes during init. package.json, environment and dependencies remain unchanged.
|
|
24
|
+
A generated check contains:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"name": "typecheck",
|
|
29
|
+
"script": "typecheck",
|
|
30
|
+
"kind": "typecheck",
|
|
31
|
+
"command": ["@node", "@typescript-compiler:.", "--noEmit"],
|
|
32
|
+
"cwd": ".",
|
|
33
|
+
"qualification": "npm-typescript-direct-v1",
|
|
34
|
+
"inputs": ["package.json", "package-lock.json", "tsconfig.json", "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs,json,jsonc}", "!node_modules/**", "!.git/**"]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`script` identifies the reviewed source recipe; `command` is what actually runs:
|
|
39
|
+
the resolved Node executable and local TypeScript implementation, with exact argv
|
|
40
|
+
and no shell. The entry is `lib/_tsc.js` where the package has one (5.7 and
|
|
41
|
+
later), without its outer compile-cache-enabling shim, and `lib/tsc.js`
|
|
42
|
+
otherwise. No compiler is fetched or bundled.
|
|
43
|
+
|
|
44
|
+
## Compiler identity
|
|
45
|
+
|
|
46
|
+
The entire installed `node_modules/typescript` must be an official package,
|
|
47
|
+
byte for byte, in one of two ways:
|
|
48
|
+
|
|
49
|
+
- TypeScript 5.5.2, 5.6.3, 5.9.3, 6.0.2 or 6.0.3: its files match the digest
|
|
50
|
+
REDUE ships for that release.
|
|
51
|
+
- Any other TypeScript 5.x or 6.0 release: package-lock.json records the
|
|
52
|
+
registry's `typescript` package at the installed version (no alias, an
|
|
53
|
+
`https` tarball URL, not a file or git source) with an integrity (sha512,
|
|
54
|
+
or sha1 where a registry records only sha1), npm's cache holds the tarball
|
|
55
|
+
under that integrity, and the installed files are exactly the tarball's
|
|
56
|
+
files. REDUE reads the cache only; it never downloads. The cache is the one
|
|
57
|
+
npm uses: `npm_config_cache`, else `cache` in the project's `.npmrc`, then
|
|
58
|
+
the user's, else `~/.npm` (`%LocalAppData%\npm-cache` on Windows); the
|
|
59
|
+
global npmrc is not read. `npm-shrinkwrap.json` is not read on this path.
|
|
60
|
+
`npm ci` fills the cache. When the tarball is missing the check stays
|
|
61
|
+
recording-only with the reason `npm-tarball-uncached`; `npm cache add
|
|
62
|
+
typescript@VERSION` adds it. The check's compiler identity is then the
|
|
63
|
+
lockfile integrity, so a lockfile change re-probes.
|
|
64
|
+
|
|
65
|
+
CI runs the same contract suite against the last release of each minor from
|
|
66
|
+
5.0 to 5.8 that the reviewed releases do not cover. Later minors (6.1 and up)
|
|
67
|
+
wait until CI covers them. TypeScript 7 (the native compiler) is not
|
|
68
|
+
supported.
|
|
69
|
+
|
|
70
|
+
## Script forms
|
|
71
|
+
|
|
72
|
+
A typecheck script qualifies when it is one or more `tsc` runs joined by `&&`,
|
|
73
|
+
each with `--noEmit` and only these arguments, in any order: `-p`/`--project`
|
|
74
|
+
with a config file or directory inside the project, `--skipLibCheck`, and
|
|
75
|
+
`--pretty` (optionally `true` or `false`). For example
|
|
76
|
+
`tsc -p tsconfig.app.json --noEmit` or
|
|
77
|
+
`tsc --noEmit && tsc --noEmit -p tsconfig.node.json`. `tsc -b`, `--watch`,
|
|
78
|
+
other options, quotes, variables and other commands keep the script
|
|
79
|
+
recording-only.
|
|
80
|
+
|
|
81
|
+
A chain gets one check per run, named `typecheck.1`, `typecheck.2` and so on,
|
|
82
|
+
each with the script's name and that run's arguments in its command. Each run
|
|
83
|
+
is checked as its own program against its own config, and is reused only while
|
|
84
|
+
the script still has as many runs as the config has checks for it, one of them
|
|
85
|
+
with exactly those arguments. Adding or removing a run, or a pre- or
|
|
86
|
+
post-script, makes every check of the script not reusable until `init` runs
|
|
87
|
+
again. The script as a whole
|
|
88
|
+
(`npm run typecheck`) is skipped only when its current runs and the configured
|
|
89
|
+
checks correspond one to one and all are CURRENT (see [agents](agents.md)).
|
|
90
|
+
|
|
91
|
+
With no typecheck script and a root `tsconfig.json`, init proposes a
|
|
92
|
+
`tsc --noEmit` check with no `script` field, unless a script already runs a
|
|
93
|
+
TypeScript checker in another form (`tsc -b`, `vue-tsc`, `svelte-check`,
|
|
94
|
+
`tsgo`, `astro check`, `nuxi typecheck`). package.json is not changed. The
|
|
95
|
+
check is written only when the contract holds; otherwise no typecheck check is
|
|
96
|
+
added. The pnpm contract does the same for each workspace package with a
|
|
97
|
+
`tsconfig.json` and no typecheck script.
|
|
98
|
+
|
|
99
|
+
Existing configs are never overwritten. To compare choices, use a new project-local
|
|
100
|
+
`--config redue.direct.config.json` with init; this explicitly selects separate
|
|
101
|
+
state. To replace an existing check deliberately, preview JSON, stop its observer,
|
|
102
|
+
review/edit that check's config, and restart using the same config/state. Existing
|
|
103
|
+
npm receipts remain historical; the new command/interpretation needs a fresh run.
|
|
104
|
+
Do not delete receipts. `redue run` always executes the configured command.
|
|
105
|
+
|
|
106
|
+
## Existing npm configuration: deliberate replacement
|
|
107
|
+
|
|
108
|
+
First upgrade through the [alpha.4 containment](npm-launcher-notice.md), stopping
|
|
109
|
+
observers before the installation change and restarting with the same config/state.
|
|
110
|
+
The old npm check becomes recording-only; its receipts remain historical.
|
|
111
|
+
To opt into the direct recipe afterward:
|
|
112
|
+
|
|
113
|
+
1. Stop the observer, install the selected released version into the same prefix,
|
|
114
|
+
and keep the original `redue.config.json` and any explicit `--state-dir` selection.
|
|
115
|
+
2. Run `redue init --recipe typescript-direct --check typecheck --dry-run --json`
|
|
116
|
+
using that config selection. Inspect `proposed_config.checks` and the recorded
|
|
117
|
+
invocation. This does not write anything, even when the config already exists.
|
|
118
|
+
3. In your editor, replace only the intended check object with the reviewed proposed
|
|
119
|
+
object. Preserve its name, the top-level project configuration, and every other
|
|
120
|
+
check. Do not replace the whole config with a one-check preview. Keep a local
|
|
121
|
+
backup outside observed inputs if desired.
|
|
122
|
+
4. Run `redue start` with the same config/state. `redue status --sync --json` must
|
|
123
|
+
not treat the old npm receipt as eligible compiler evidence.
|
|
124
|
+
5. Run `redue run typecheck`, then `redue status --sync --json`. A qualified success
|
|
125
|
+
now records the direct compiler recipe with a new run ID. Old npm runs remain
|
|
126
|
+
immutable history. Other check definitions are unchanged.
|
|
127
|
+
|
|
128
|
+
Substitute the actual selected check name throughout. Repeating plain `init`
|
|
129
|
+
does **not** migrate an existing config. A deliberately separate `--config` file
|
|
130
|
+
is useful for comparison, but has separate state by design. Do not create one
|
|
131
|
+
accidentally when intending to preserve the original selection.
|
|
132
|
+
|
|
133
|
+
Pre/post scripts, compound commands, wrappers, environment assignments, workspace
|
|
134
|
+
projects and unsupported compiler versions are not automatically converted.
|
|
135
|
+
Init retains the original script with a reason. Development-mode source-map helpers,
|
|
136
|
+
Node preloads/loaders/compile-cache settings, `TS_ETW_MODULE_PATH` (including empty or case aliases), unsupported compiler plugins, a
|
|
137
|
+
`composite` root tsconfig, a program that uses a referenced project's files,
|
|
138
|
+
outside-root inputs and uncertain observation withhold applicability. Extra custom probes cannot inherit this recipe's context
|
|
139
|
+
exception. Relevant source, declaration, config, membership and installed-content
|
|
140
|
+
changes invalidate or withdraw applicability normally. Installed files are observed
|
|
141
|
+
by identity, so reinstalling identical packages or restoring an installed file's
|
|
142
|
+
bytes also needs one rerun (see [configuration](configuration.md)).
|
|
143
|
+
|
|
144
|
+
Vitest writes its results under `node_modules/.vite/vitest` at every run.
|
|
145
|
+
They are not inputs, so a test run leaves the typecheck CURRENT. Everything
|
|
146
|
+
else under `node_modules/.vite` is still an input. A program that asks about
|
|
147
|
+
anything under `node_modules/.vite` (by any spelling or through a link that
|
|
148
|
+
resolves there), or lists `node_modules`, is UNVERIFIED: REDUE does not
|
|
149
|
+
observe what Vitest writes there. A check configured before 0.1.0-alpha.25 gets the new inputs on
|
|
150
|
+
its own and reports STALE once after the upgrade.
|
|
151
|
+
|
|
152
|
+
A root tsconfig with `incremental: true` is supported. tsc reads and writes
|
|
153
|
+
its build-info file (`tsBuildInfoFile`, or the default next to the config) on
|
|
154
|
+
each run, so REDUE leaves that file out of the inputs and lets the run write
|
|
155
|
+
only that file and the directories it needs; any other write makes the run
|
|
156
|
+
non-reusable. The result is what your own incremental tsc reports, so it
|
|
157
|
+
trusts TypeScript's build-info cache, which TypeScript discards after a
|
|
158
|
+
compiler or option change. The file must be inside the checkout and named
|
|
159
|
+
`*.tsbuildinfo`, with no glob characters in its path.
|
|
160
|
+
`assumeChangesOnlyAffectDirectDependencies` is refused: with it, the result
|
|
161
|
+
depends on earlier runs. REDUE reads the setting when the observer starts:
|
|
162
|
+
after turning `incremental` on or moving the file, restart the observer;
|
|
163
|
+
status says so until then. On Linux, a run that creates the build-info directory is an
|
|
164
|
+
observation gap, so the first run after that is not reusable.
|
|
165
|
+
|
|
166
|
+
A root tsconfig may reference other configs (`references`), for example a
|
|
167
|
+
composite `tsconfig.node.json`. Plain `tsc --noEmit` reads those configs but
|
|
168
|
+
does not build them, so REDUE treats them as configuration. If the program
|
|
169
|
+
uses a referenced project's sources or built outputs, the check is not
|
|
170
|
+
qualified.
|
|
171
|
+
|
|
172
|
+
On macOS and Linux, `redue run` records which files the compiler looked up and
|
|
173
|
+
compares them with what the observer's last probe saw. The probe only builds the
|
|
174
|
+
program. With `declaration: true`, tsc also resolves the project's dependencies
|
|
175
|
+
while it checks declarations, so the run looks up files the probe never did,
|
|
176
|
+
some outside the checkout, and reads those dependencies' `package.json`. The
|
|
177
|
+
receipt keeps the run's answers to those existence, `realpath` and
|
|
178
|
+
`package.json` lookups as run facts. Before every CURRENT answer, status asks
|
|
179
|
+
each one again; a cached `redue status` asks them again when it is read. If any
|
|
180
|
+
now answers differently, the check is STALE and the reason names the path. Any
|
|
181
|
+
other file the run read, or a directory it listed, that the probe never did
|
|
182
|
+
still makes the run non-reusable, as do more than 10,000 run facts. Receipts
|
|
183
|
+
with run facts use a new format, so earlier observers do not reuse them. A
|
|
184
|
+
direct receipt recorded before run facts is UNVERIFIED until the check runs
|
|
185
|
+
again. Windows does not record direct runs, so it has no run facts: there, a
|
|
186
|
+
lookup only declaration checks make is not checked again.
|
|
187
|
+
|
|
188
|
+
The versioned `npm-direct-typescript@1` interpretation retains relevant Node context
|
|
189
|
+
and identity. Reviewed compiler code does not parse npm settings or proxy variables;
|
|
190
|
+
these remain untouched in the child environment and are recorded only as a digest
|
|
191
|
+
of observed provenance. This is not an environment ignore option for arbitrary
|
|
192
|
+
commands or other providers. No remote service equivalence is claimed. Ordinary
|
|
193
|
+
cached status remains conservative; synchronize deliberately when worth the cost.
|
|
194
|
+
|
|
195
|
+
Explain/JSON report `verification_recipe: "npm-direct-typescript@1"` for receipts
|
|
196
|
+
recorded with this recipe. Report compiler evidence as compiler evidence. A user's
|
|
197
|
+
explicit request for `npm run typecheck` is not satisfied by this different command.
|
|
198
|
+
|
|
199
|
+
The injected `NODE_USE_ENV_PROXY=1` setting is admitted only on Node 22.13.0,
|
|
200
|
+
where it is inert; it remains strictly tracked. Other Node versions with this
|
|
201
|
+
setting need review and stay unqualified. REDUE does not alter the setting.
|
|
202
|
+
|
|
203
|
+
## Node settings
|
|
204
|
+
|
|
205
|
+
Since alpha.11 the direct recipe accepts these `NODE_*` settings:
|
|
206
|
+
|
|
207
|
+
- `NODE_OPTIONS`, when every token is one of `--max-old-space-size=<n>`,
|
|
208
|
+
`--max-semi-space-size=<n>`, `--use-openssl-ca`, `--use-bundled-ca`,
|
|
209
|
+
`--use-system-ca` or `--dns-result-order=ipv4first|ipv6first|verbatim`.
|
|
210
|
+
Any other flag, quotes, backslashes or tabs are refused.
|
|
211
|
+
- `NODE_EXTRA_CA_CERTS`.
|
|
212
|
+
- `NODE_PATH`.
|
|
213
|
+
|
|
214
|
+
`NODE_ENV` set to `production`, `test` or empty was already accepted. Every other non-empty
|
|
215
|
+
`NODE_*` setting withholds applicability. The values are part of the recorded
|
|
216
|
+
execution context: a run under one value is not reusable under another. A
|
|
217
|
+
`--require` in `NODE_OPTIONS` still runs inside REDUE's own process before REDUE
|
|
218
|
+
refuses it. The npm, pnpm and Yarn recipes still refuse `NODE_OPTIONS` and
|
|
219
|
+
`NODE_PATH`.
|