@redue/cli 0.1.0-alpha.4 → 0.1.0-alpha.6
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 +23 -0
- package/README.md +33 -2
- package/bin/redue.mjs +39 -20
- package/docs/README.md +1 -1
- package/docs/user/agents.md +134 -4
- package/docs/user/configuration.md +5 -2
- package/docs/user/direct-typescript.md +96 -0
- package/docs/user/getting-started.md +12 -1
- package/docs/user/supported-projects.md +9 -7
- package/package.json +1 -1
- package/src/agent-integration.mjs +244 -0
- package/src/agent-policy.md +52 -0
- package/src/cli.mjs +14 -2
- package/src/daemon.mjs +67 -16
- package/src/direct-typescript-probe.mjs +47 -0
- package/src/direct-typescript.mjs +72 -0
- package/src/node-onboarding.mjs +12 -1
- package/src/npm-typecheck-environment.mjs +36 -0
- package/src/plan-worker.mjs +9 -1
- package/src/presentation.mjs +1 -0
- package/src/project-location.mjs +34 -0
- package/src/typescript-input-facts.mjs +65 -0
- package/src/typescript-list.mjs +6 -2
- package/src/typescript-qualification.mjs +23 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.6 — 2026-10-07
|
|
4
|
+
|
|
5
|
+
- Reuse guarded compiler discovery for warm direct-TypeScript decisions on macOS
|
|
6
|
+
with healthy historical observation. Membership, absence, compiler bytes,
|
|
7
|
+
caller context and receipt selection remain validated independently.
|
|
8
|
+
- Keep full discovery/reconciliation fallbacks and existing platform boundaries.
|
|
9
|
+
- On one measured project, complete warm decision median fell from roughly
|
|
10
|
+
791 to 474 ms. This is not a universal speedup, agent-task acceleration,
|
|
11
|
+
memory improvement, or a faster relevant-edit/rebuild claim.
|
|
12
|
+
- Stop observers before upgrading and restart with the same config/state.
|
|
13
|
+
Preserve receipts; no configuration migration is performed.
|
|
14
|
+
|
|
15
|
+
## 0.1.0-alpha.5 — 2026-10-07
|
|
16
|
+
|
|
17
|
+
- Add opt-in project-local agent activation and direct TypeScript evidence, with
|
|
18
|
+
fresh-session reuse demonstrated in the tested Codex/macOS configuration.
|
|
19
|
+
- Preserve ordinary npm execution as a separate, recording-only obligation.
|
|
20
|
+
Direct compilation requires explicit selection and a fresh baseline receipt.
|
|
21
|
+
- Initial direct recipe supports reviewed TypeScript 5.6.3/5.9.3 in single-package
|
|
22
|
+
npm projects, with documented Node/environment restrictions.
|
|
23
|
+
- Claude integration mechanics are tested; Claude behavior and cross-host reuse
|
|
24
|
+
remain untested. No universal compliance or inexpensive-check speedup is claimed.
|
|
25
|
+
|
|
3
26
|
## 0.1.0-alpha.4 — 2026-10-07
|
|
4
27
|
|
|
5
28
|
- Withdraw automatic npm-launcher applicability because update notifications consume
|
package/README.md
CHANGED
|
@@ -37,6 +37,11 @@ it; relevant source edits make it stale. [Run the reproducible demo](docs/contri
|
|
|
37
37
|
|
|
38
38
|
## Install the alpha
|
|
39
39
|
|
|
40
|
+
This branch prepares **alpha.5**, not yet published. Its opt-in agent activation
|
|
41
|
+
and npm direct-compiler recipe require the candidate tarball; public alpha.4
|
|
42
|
+
contains only the applicability correction.
|
|
43
|
+
|
|
44
|
+
|
|
40
45
|
REDUE is published on npm as `@redue/cli`. The installed command is `redue`.
|
|
41
46
|
|
|
42
47
|
```sh
|
|
@@ -71,6 +76,30 @@ Start with ordinary `status`. When it cannot establish caller context, use
|
|
|
71
76
|
**Synchronization can cost more than rerunning a cheap check, particularly on
|
|
72
77
|
Windows.** REDUE does not choose or execute that tradeoff for you.
|
|
73
78
|
|
|
79
|
+
Since alpha.4, ordinary npm scripts are recording-only after
|
|
80
|
+
[an npm launcher applicability gap](docs/acceptance/npm-launcher-boundary.md).
|
|
81
|
+
A separate explicit [direct compiler recipe](docs/user/direct-typescript.md) can
|
|
82
|
+
qualify supported npm typechecks. It does not claim that npm/lifecycle scripts ran.
|
|
83
|
+
|
|
84
|
+
## Connect your agent (candidate)
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
redue agent setup codex --dry-run
|
|
88
|
+
redue agent setup codex --apply # or claude
|
|
89
|
+
redue agent doctor
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Start a fresh agent session and give it an ordinary task. Project-local guidance
|
|
93
|
+
teaches it to inspect evidence before deciding whether verification needs repeating.
|
|
94
|
+
Setup is explicit, reversible, and does not change tool permissions or run checks.
|
|
95
|
+
[Activation, removal, and generic-agent guidance](docs/user/agents.md).
|
|
96
|
+
|
|
97
|
+
Alpha.5's claim is **opt-in project-local agent activation and direct TypeScript
|
|
98
|
+
evidence, with fresh-session reuse demonstrated in the tested Codex/macOS
|
|
99
|
+
configuration**. Claude setup/removal mechanics are tested; Claude behavior and
|
|
100
|
+
cross-host reuse are not. This is experimental guidance, not guaranteed agent
|
|
101
|
+
compliance, general sandbox compatibility, or a promise of time savings.
|
|
102
|
+
|
|
74
103
|
## What the states mean
|
|
75
104
|
|
|
76
105
|
| State | Meaning | Normal next step |
|
|
@@ -89,8 +118,10 @@ has been verified.
|
|
|
89
118
|
- macOS, Linux, and Windows on supported local filesystems; Node 22+.
|
|
90
119
|
- Linux also requires Python 3 for observation. No WSL or Git Bash needed on Windows.
|
|
91
120
|
- npm, pinned Yarn `node-modules`, and pinned pnpm 12 isolated/hoisted layouts.
|
|
92
|
-
- Automatic qualification for
|
|
93
|
-
launcher checks
|
|
121
|
+
- Automatic qualification for supported Yarn/pnpm TypeScript invocations; ordinary npm
|
|
122
|
+
launcher checks remain recording-only. The alpha.5 candidate adds an explicit
|
|
123
|
+
[direct local compiler recipe](docs/user/direct-typescript.md) for the reviewed
|
|
124
|
+
npm/TypeScript boundary. Workspace
|
|
94
125
|
boundaries follow the files actually consumed, including built declarations.
|
|
95
126
|
- Existing test/lint/build and arbitrary commands can record results while
|
|
96
127
|
their applicability remains unqualified.
|
package/bin/redue.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import {directCompiler,directQualification,directEnvironment,directInterpretation} from '../src/direct-typescript.mjs';
|
|
3
4
|
import os from 'node:os';
|
|
4
5
|
import path from 'node:path';
|
|
5
6
|
import {createHash} from 'node:crypto';
|
|
@@ -9,7 +10,8 @@ import {fileURLToPath} from 'node:url';
|
|
|
9
10
|
import {discoverNodeProject} from '../src/node-onboarding.mjs';
|
|
10
11
|
import {processAlive} from '../src/process-liveness.mjs';
|
|
11
12
|
import {samePath,withinPath,realObservedPath} from '../src/path-identity.mjs';
|
|
12
|
-
import {
|
|
13
|
+
import {discoverConfig,projectState,canonicalConfig} from '../src/project-location.mjs';
|
|
14
|
+
import {agentCommand} from '../src/agent-integration.mjs';
|
|
13
15
|
import {findExecutable} from '../src/executable-lookup.mjs';
|
|
14
16
|
import {readCachedStatus} from '../src/cached-state.mjs';
|
|
15
17
|
import {assertOwnedStatePlacement} from '../src/owned-state.mjs';
|
|
@@ -22,8 +24,12 @@ const help=`REDUE ${version}
|
|
|
22
24
|
Usage: redue [--config FILE] [--state-dir DIR] COMMAND [OPTIONS]
|
|
23
25
|
|
|
24
26
|
Commands:
|
|
25
|
-
init [--dry-run] [--workspace NAME] [--check KIND]
|
|
27
|
+
init [--dry-run] [--workspace NAME] [--check KIND] [--recipe typescript-direct]
|
|
26
28
|
Discover existing scripts; optionally select one workspace/check
|
|
29
|
+
agent setup codex|claude [--dry-run|--apply] [--json]
|
|
30
|
+
agent doctor [codex|claude] [--json]
|
|
31
|
+
agent remove codex|claude [--dry-run|--apply] [--json]
|
|
32
|
+
Connect project instructions; explicit setup only
|
|
27
33
|
start Start the local observer
|
|
28
34
|
stop Stop this observer
|
|
29
35
|
status [--json|--short] Read conservative cached status
|
|
@@ -39,10 +45,7 @@ function error(message){console.error(`redue: ${message}`);process.exit(2);}
|
|
|
39
45
|
const args=process.argv.slice(2);
|
|
40
46
|
if(args.length===1&&args[0]==='--version'){console.log(version);process.exit(0);}
|
|
41
47
|
if(args.includes('--help')||args.includes('-h')||!args.length){console.log(help);process.exit(0);}
|
|
42
|
-
|
|
43
|
-
const legacyConfig=path.resolve('vstate.config.json');
|
|
44
|
-
let configFile=fs.existsSync(preferredConfig)||!fs.existsSync(legacyConfig)?
|
|
45
|
-
preferredConfig:legacyConfig,stateOverride=null;
|
|
48
|
+
let configFile=null,stateOverride=null;
|
|
46
49
|
for(let i=0;i<args.length;){
|
|
47
50
|
if(args[i]==='--config'||args[i]==='--state-dir'){
|
|
48
51
|
const flag=args[i],value=args[i+1];if(!value)error(`${flag} requires a path`);
|
|
@@ -51,17 +54,26 @@ for(let i=0;i<args.length;){
|
|
|
51
54
|
}else i++;
|
|
52
55
|
}
|
|
53
56
|
const command=args.shift();
|
|
57
|
+
try{configFile??=command==='init'||stateOverride&&['stop','remove-state'].includes(command)?
|
|
58
|
+
path.resolve(fs.existsSync('redue.config.json')||!fs.existsSync('vstate.config.json')?'redue.config.json':'vstate.config.json'):discoverConfig();}
|
|
59
|
+
catch(e){error(e.message);}
|
|
60
|
+
if(fs.existsSync(path.dirname(configFile)))configFile=canonicalConfig(configFile);
|
|
61
|
+
if(command==='agent'){
|
|
62
|
+
try{await agentCommand(args,{configFile,stateOverride,entry:fileURLToPath(import.meta.url)});}
|
|
63
|
+
catch(e){error(e.message);}
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
54
66
|
if(!['init','start','stop','status','detail','explain','run','remove-state'].includes(command))
|
|
55
67
|
error(`unknown command ${command||'<none>'}; use --help`);
|
|
56
68
|
const json=args.includes('--json');
|
|
57
69
|
const sync=args.includes('--sync');
|
|
58
70
|
const dryRun=args.includes('--dry-run');
|
|
59
71
|
const short=args.includes('--short');
|
|
60
|
-
let workspaceSelection=null,checkSelection=null;
|
|
72
|
+
let workspaceSelection=null,checkSelection=null,recipeSelection=null;
|
|
61
73
|
if(command==='init')for(let i=0;i<args.length;){
|
|
62
|
-
if(args[i]==='--workspace'||args[i]==='--check'){
|
|
74
|
+
if(args[i]==='--workspace'||args[i]==='--check'||args[i]==='--recipe'){
|
|
63
75
|
const flag=args[i],value=args[i+1];if(!value||value.startsWith('--'))error(`${flag} requires a name`);
|
|
64
|
-
if(flag==='--workspace')workspaceSelection=value;else checkSelection=value;
|
|
76
|
+
if(flag==='--workspace')workspaceSelection=value;else if(flag==='--recipe')recipeSelection=value;else checkSelection=value;
|
|
65
77
|
args.splice(i,2);
|
|
66
78
|
}else i++;
|
|
67
79
|
}
|
|
@@ -73,7 +85,7 @@ if(short&&(command!=='status'||json||sync))error('--short is a cached status opt
|
|
|
73
85
|
if(dryRun&&command!=='init')error('--dry-run is for init');
|
|
74
86
|
|
|
75
87
|
if(command==='init'){
|
|
76
|
-
let discovery;try{discovery=discoverNodeProject(process.cwd());}
|
|
88
|
+
let discovery;try{discovery=discoverNodeProject(process.cwd(),{recipe:recipeSelection});}
|
|
77
89
|
catch(e){error(e.message);}
|
|
78
90
|
if(workspaceSelection||checkSelection){
|
|
79
91
|
const chosen=discovery.checks.filter(row=>
|
|
@@ -104,7 +116,7 @@ if(command==='init'){
|
|
|
104
116
|
console.log(` ${row.name} (${row.script||row.command?.join(' ')}) — `+
|
|
105
117
|
`${{ready:'ready to qualify',recording:'recording-only',unsupported:'unsupported'}[row.level]||row.level}: ${row.reason}`);
|
|
106
118
|
if(row.script&&row.command)console.log(` Recorded invocation: ${row.command.map(value=>
|
|
107
|
-
value==='@node'?'node':value.startsWith('@typescript-bin:')?
|
|
119
|
+
value==='@node'?'node':value==='@typescript-compiler:.'?'[reviewed local TypeScript compiler implementation]':value.startsWith('@typescript-bin:')?
|
|
108
120
|
`[installed TypeScript in ${value.slice('@typescript-bin:'.length)}]`:value).join(' ')}`);
|
|
109
121
|
}
|
|
110
122
|
for(const row of summary.ambiguous)
|
|
@@ -121,6 +133,7 @@ if(command==='init'){
|
|
|
121
133
|
if(!json){console.log(`Created ${configFile}. No checks were executed.`);
|
|
122
134
|
console.log('Ready to qualify means the supported contract will be validated; it is not verification evidence.');
|
|
123
135
|
console.log(`Next: review the config, then redue start and redue run ${JSON.stringify(discovery.checks[0].config.name)}.`);
|
|
136
|
+
console.log('Connect your agent: redue agent setup codex (or claude). Preview with --dry-run.');
|
|
124
137
|
console.log('Use redue status first. --sync can establish applicability, but may cost more than rerunning a cheap check.');}
|
|
125
138
|
} else if(unsupported&&!json)console.log(`No config written: ${summary.issue||'unsupported discovery boundary'}.`);
|
|
126
139
|
if(json)console.log(JSON.stringify({...summary,proposed_config:discovery.config}));
|
|
@@ -157,10 +170,7 @@ for(const key of Object.keys(publicConfig))
|
|
|
157
170
|
if(!['schema','root','checks','packageManager'].includes(key))error(`unsupported config field ${key}`);
|
|
158
171
|
if(check&&!publicConfig.checks.some(row=>row.name===check))error(`unknown check ${check}; use redue status to list configured checks`);
|
|
159
172
|
const root=realObservedPath(path.resolve(path.dirname(configFile),publicConfig.root||'.'));
|
|
160
|
-
const
|
|
161
|
-
const state=stateOverride||path.join(stateBase,'vstate',
|
|
162
|
-
`vstate-${createHash('sha256').update(stateIdentity(root)+'\0'+
|
|
163
|
-
stateIdentity(configFile)).digest('hex').slice(0,16)}`);
|
|
173
|
+
const state=stateOverride||projectState(root,configFile);
|
|
164
174
|
if(!/^(?:vstate|redue)-/.test(path.basename(state)))
|
|
165
175
|
error('--state-dir must name a dedicated redue-* directory outside the checkout (legacy vstate-* is also supported)');
|
|
166
176
|
const runtimeFile=path.join(state,'project-runtime-v1.json');
|
|
@@ -172,6 +182,10 @@ function which(name){
|
|
|
172
182
|
function token(value){
|
|
173
183
|
if(value==='@node')return process.execPath;
|
|
174
184
|
if(value==='@project')return root;
|
|
185
|
+
if(value==='@typescript-compiler:.'){
|
|
186
|
+
try{return directCompiler(root,{verify:false}).entry;}catch(e){error(`direct compiler unavailable: ${e.code||e.message}`);}
|
|
187
|
+
}
|
|
188
|
+
if(value==='@vstate/direct-typescript-probe')return path.join(productRoot,'src','direct-typescript-probe.mjs');
|
|
175
189
|
if(value.startsWith('@typescript-bin:')){
|
|
176
190
|
const dir=value.slice('@typescript-bin:'.length);
|
|
177
191
|
if(!dir||path.isAbsolute(dir)||dir.split('/').includes('..'))
|
|
@@ -208,8 +222,9 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
208
222
|
for(const category of categories)if(check.coverage?.[category]&&
|
|
209
223
|
typeof check.coverageReview?.[category]!=='string')
|
|
210
224
|
error(`${check.name}: reviewed coverage ${category} needs a rationale`);
|
|
225
|
+
const npmDirect=check.qualification===directQualification;
|
|
211
226
|
const pnpmTypecheck=check.qualification==='pnpm-tsc-v1';
|
|
212
|
-
if(check.script&&check.command&&!pnpmTypecheck)
|
|
227
|
+
if(check.script&&check.command&&!pnpmTypecheck&&!npmDirect)
|
|
213
228
|
error(`${check.name}: choose script or command, not both`);
|
|
214
229
|
const manager=publicConfig.packageManager;
|
|
215
230
|
if(check.script&&!['npm','yarn','pnpm'].includes(manager))
|
|
@@ -218,8 +233,11 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
218
233
|
[`@which:${manager}`,'run',check.script]:null;
|
|
219
234
|
const npmAutomatic=check.qualification==='typescript-noemit-v1';
|
|
220
235
|
const yarnWorkspace=check.qualification==='yarn-workspace-tsc-v1';
|
|
221
|
-
if(check.qualification&&!npmAutomatic&&!yarnWorkspace&&!pnpmTypecheck)
|
|
236
|
+
if(check.qualification&&!npmAutomatic&&!npmDirect&&!yarnWorkspace&&!pnpmTypecheck)
|
|
222
237
|
error(`${check.name}: unknown qualification contract`);
|
|
238
|
+
if(npmDirect&&(manager!=='npm'||!check.script||check.cwd&&check.cwd!=='.'||
|
|
239
|
+
JSON.stringify(check.command)!==JSON.stringify(['@node','@typescript-compiler:.','--noEmit'])))
|
|
240
|
+
error(`${check.name}: direct recipe requires its explicit local compiler command`);
|
|
223
241
|
if(npmAutomatic&&(manager!=='npm'||check.cwd&&check.cwd!=='.'))
|
|
224
242
|
error(`${check.name}: automatic TypeScript qualification currently needs root npm script`);
|
|
225
243
|
if(yarnWorkspace&&(manager!=='yarn'||!check.workspace||check.cwd&&check.cwd!=='.'||
|
|
@@ -237,7 +255,7 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
237
255
|
check.kind==='lint'?'lint plugins, config and resolver inputs need review':
|
|
238
256
|
check.kind==='build'?'build environment and generated inputs need review':
|
|
239
257
|
'check inputs need review';
|
|
240
|
-
const autoProbes=npmAutomatic?[['@node','@vstate/typescript-contract-probe',
|
|
258
|
+
const autoProbes=npmDirect?[['@node','@vstate/direct-typescript-probe','@project',check.script]]:npmAutomatic?[['@node','@vstate/typescript-contract-probe',
|
|
241
259
|
'@project',check.script,'@which:npm']]:yarnWorkspace?
|
|
242
260
|
[['@node','@vstate/yarn-workspace-typecheck-probe','@project',
|
|
243
261
|
check.workspace,check.command[4],'@which:yarn']]:pnpmTypecheck?
|
|
@@ -245,7 +263,7 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
245
263
|
check.workspace||'.',check.script]]:[];
|
|
246
264
|
const windowsContext=process.platform==='win32'?
|
|
247
265
|
['ComSpec','COMSPEC','PATHEXT','USERPROFILE']:[];
|
|
248
|
-
const autoEnvironment=npmAutomatic?{variables:['NODE_OPTIONS','NODE_PATH','CI','HOME',
|
|
266
|
+
const autoEnvironment=npmDirect?directEnvironment:npmAutomatic?{variables:['NODE_OPTIONS','NODE_PATH','CI','HOME',
|
|
249
267
|
'NODE_ENV','BASH_ENV','ENV',...windowsContext],prefixes:['npm_config_','DYLD_','TSGO_'],
|
|
250
268
|
pathExecutables:['node','npm'],executableIdentity:true}:yarnWorkspace?
|
|
251
269
|
{variables:['NODE_OPTIONS','NODE_PATH','CI','HOME','NODE_ENV','BASH_ENV','ENV',...windowsContext],
|
|
@@ -257,7 +275,7 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
257
275
|
return {name:check.name,command:argv(scriptCommand||check.command,`${check.name}.command`),
|
|
258
276
|
cwd:check.cwd,inputs:check.inputs||[],generatedInputs:check.generatedInputs||[],
|
|
259
277
|
installedInputs:check.installedInputs||(
|
|
260
|
-
npmAutomatic?['node_modules/**']:[]),
|
|
278
|
+
npmAutomatic||npmDirect?['node_modules/**']:[]),
|
|
261
279
|
allowedExternalRoots:check.allowedExternalRoots||[],
|
|
262
280
|
probes:[...(check.probes||[]),...autoProbes]
|
|
263
281
|
.map((p,i)=>argv(p,`${check.name}.probes[${i}]`)),
|
|
@@ -267,6 +285,7 @@ const checks=publicConfig.checks.map(check=>{
|
|
|
267
285
|
categories.map(category=>[category,reason])),
|
|
268
286
|
qualification:check.qualification||null,script:check.script||null,
|
|
269
287
|
...(npmAutomatic?{qualificationInterpretation:'npm-launcher-withheld@1'}:{}),
|
|
288
|
+
...(npmDirect?{qualificationInterpretation:directInterpretation}:{}),
|
|
270
289
|
workspace:check.workspace||null,kind:check.kind||null};
|
|
271
290
|
});
|
|
272
291
|
const runtime={schema:1,provider:'declared-project@1',root,state,checks};
|
package/docs/README.md
CHANGED
|
@@ -5,7 +5,7 @@ For users:
|
|
|
5
5
|
- [Install, initialize, run, and remove](user/getting-started.md)
|
|
6
6
|
- [Supported projects and conservative boundaries](user/supported-projects.md)
|
|
7
7
|
- [Configuration](user/configuration.md)
|
|
8
|
-
- [
|
|
8
|
+
- [Connect coding agents and apply the decision policy](user/agents.md)
|
|
9
9
|
- [JSON contract](user/json.md)
|
|
10
10
|
- [Shell usage](user/shell.md)
|
|
11
11
|
|
package/docs/user/agents.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Agent decision policy
|
|
2
2
|
|
|
3
|
-
Use the CLI
|
|
4
|
-
|
|
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
5
|
|
|
6
6
|
1. Query ordinary `redue status --json` first.
|
|
7
|
-
2. If a check has `freshness: "CURRENT"`, `result: "PASS"`, and
|
|
8
|
-
`reuse_eligible: true`, reuse it. Do not rerun merely for freshness.
|
|
7
|
+
2. Require schema 1 and healthy observation. If a check has `freshness: "CURRENT"`, `result: "PASS"`, and
|
|
8
|
+
`reuse_eligible: true`, reuse it. Missing eligibility means false. Do not rerun merely for freshness.
|
|
9
9
|
3. If STALE, run `redue run CHECK` when that verification is needed.
|
|
10
10
|
4. If the historical `result` is FAIL, report it honestly. The human CLI calls
|
|
11
11
|
this FAILED; applicability is a separate field, never an excuse to call it green.
|
|
@@ -25,8 +25,138 @@ check is not universal product correctness. Report additional uncaptured checks
|
|
|
25
25
|
separately. Do not infer that an outer invocation's success proves a specific
|
|
26
26
|
check ran or that an upstream cache was hit; inspect `target_provenance`.
|
|
27
27
|
|
|
28
|
+
Reassess at the decision point after edits or context changes; previous CURRENT is
|
|
29
|
+
not continuing authorization. A status exit code of zero is not proof of CURRENT.
|
|
30
|
+
An empty changed-input list does not prove nothing changed. `run CHECK --json`
|
|
31
|
+
streams check output; use a subsequent status/explain query for structured evidence.
|
|
32
|
+
Explicit fresh-execution requests still require execution.
|
|
33
|
+
|
|
28
34
|
On a CLI error, unhealthy observation, or unavailable context, do not infer
|
|
29
35
|
CURRENT. Do not delete state or reset receipts to make the output green.
|
|
30
36
|
|
|
31
37
|
REDUE tells you what evidence exists and whether it still applies. It does not
|
|
32
38
|
promise that establishing applicability is cheaper than every possible check.
|
|
39
|
+
|
|
40
|
+
## Connect once (candidate)
|
|
41
|
+
|
|
42
|
+
The alpha.5 candidate supports opt-in project-local activation and direct
|
|
43
|
+
TypeScript evidence, with fresh-session reuse demonstrated for Codex CLI 0.160.1
|
|
44
|
+
on macOS under the documented owner-approved checkout/state/socket route. CLI
|
|
45
|
+
mechanics are tested on macOS/Linux/Windows; model behavior is not claimed for
|
|
46
|
+
every host/platform or sandbox policy. Claude setup/removal mechanics are tested,
|
|
47
|
+
but Claude behavior and cross-host reuse remain untested. Reuse is not guaranteed,
|
|
48
|
+
and the existing subsecond example establishes no meaningful net time saving.
|
|
49
|
+
|
|
50
|
+
After installing this candidate and running `redue init` in a trusted project:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
redue agent setup codex --dry-run
|
|
54
|
+
redue agent setup codex --apply
|
|
55
|
+
# Or: redue agent setup claude --apply
|
|
56
|
+
redue agent doctor
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Start a fresh agent session in this checkout, then give it your ordinary task.
|
|
60
|
+
Interactive setup shows the changes and asks before applying; noninteractive
|
|
61
|
+
setup requires `--apply`. `--dry-run` never writes. Installing REDUE or running
|
|
62
|
+
`init` does not connect an agent automatically. Setup does not start an observer
|
|
63
|
+
or execute verification. Use `redue start` when you want observation.
|
|
64
|
+
|
|
65
|
+
Codex gets a short managed section in project `AGENTS.md` and
|
|
66
|
+
`.agents/skills/redue-verification/SKILL.md`. Claude Code gets a managed section
|
|
67
|
+
in `CLAUDE.md` and `.claude/skills/redue-verification/SKILL.md`. Each uses the same
|
|
68
|
+
policy source; detailed guidance is loaded when verification is relevant. Small
|
|
69
|
+
ownership records in `.redue/agents/` support safe updates/removal. These are
|
|
70
|
+
portable project files, not receipts; review and commit them if the team wants
|
|
71
|
+
this integration. Do not ignore just the ownership records while committing the
|
|
72
|
+
managed files.
|
|
73
|
+
|
|
74
|
+
Existing instruction text is retained. Review it in the preview: setup cannot
|
|
75
|
+
prove arbitrary natural-language policies are consistent. Conflicts such as a
|
|
76
|
+
root `AGENTS.override.md` or an alternative `.claude/CLAUDE.md` are reported
|
|
77
|
+
instead of silently outranked. Global/managed policies, nested instructions,
|
|
78
|
+
Codex instruction-size limits, skill disabling, and host-specific exclusions
|
|
79
|
+
still apply. Complete the host's ordinary trust/permission prompts yourself;
|
|
80
|
+
REDUE never grants tool permission. Sandboxed hosts may need owner-approved access
|
|
81
|
+
to the checkout, owned state directory and local observer socket. A healthy daemon
|
|
82
|
+
does not establish that the agent can reach it; doctor reports control access
|
|
83
|
+
separately. Do not disable sandbox protections to make this work. Do not use a mode that disables project
|
|
84
|
+
instructions and expect automatic activation.
|
|
85
|
+
|
|
86
|
+
Control access is not simply file-read permission. The observer can reconcile and
|
|
87
|
+
write its owned index, run the trusted configuration's probes in its own process
|
|
88
|
+
context, reload receipts, and stop. Approve only the intended checkout/state and
|
|
89
|
+
endpoint, accounting for that authority. Doctor sends only a bounded metrics
|
|
90
|
+
request; it does not synchronize or run these probes.
|
|
91
|
+
|
|
92
|
+
`agent doctor [codex|claude] --json` is read-only. It distinguishes command lookup,
|
|
93
|
+
config resolution, cached observer health, a bounded read-only control-access probe,
|
|
94
|
+
managed-file integrity, detected host
|
|
95
|
+
version, and loading guidance. `behavior_verified: false` is deliberate: intact
|
|
96
|
+
files do not prove the agent followed them. No hooks are installed. Doctor neither
|
|
97
|
+
executes checks nor starts observers, reconciles inputs, or installs a host.
|
|
98
|
+
|
|
99
|
+
Doctor separates missing/unreadable state, a missing or refused endpoint, an
|
|
100
|
+
explicit EPERM/EACCES access denial, and timeout/invalid response. A denial does
|
|
101
|
+
not identify whether OS permissions or host policy caused it. A live PID and
|
|
102
|
+
healthy cached observation do not prove control access. An older cached response
|
|
103
|
+
without receipt-selection validation gets stop/start guidance. Windows command
|
|
104
|
+
shims whose target has not been established are reported as unknown, not a
|
|
105
|
+
proven installation mismatch.
|
|
106
|
+
|
|
107
|
+
Codex CLI 0.160.1 on macOS can use the approved exact observer-socket route while
|
|
108
|
+
other sockets and direct network access remain denied. Its independent sessions
|
|
109
|
+
receive different proxy values. Ordinary npm invocation is **not** equivalent
|
|
110
|
+
across arbitrary notifier state: this candidate withholds automatic npm-launcher
|
|
111
|
+
reuse. Do not change proxy settings or permissions to get green evidence.
|
|
112
|
+
|
|
113
|
+
The separate opt-in [direct local compiler recipe](direct-typescript.md) does not
|
|
114
|
+
run npm. Its reviewed compiler implementation does not consume npm/proxy settings;
|
|
115
|
+
a digest preserves their observed provenance without treating them as compiler
|
|
116
|
+
inputs. Other execution context remains strict, and cached status still cannot
|
|
117
|
+
assert caller eligibility. An explicit user request for `npm run typecheck` still
|
|
118
|
+
requires npm execution; direct compiler evidence is not a substitute.
|
|
119
|
+
|
|
120
|
+
Before model trials, run `redue agent doctor --json` and
|
|
121
|
+
`redue status --sync --json` inside the agent's actual command boundary. The
|
|
122
|
+
contributor helper `test/acceptance/codex-preflight.mjs --config FILE --check CHECK`
|
|
123
|
+
performs the same bounded, read-only decision check and exits 2 when reuse is not
|
|
124
|
+
eligible. It neither executes verification nor grants access; synchronization
|
|
125
|
+
may run configured probes. A successful outside-shell result is insufficient.
|
|
126
|
+
|
|
127
|
+
Use the same setup command after a candidate upgrade; it updates intact managed
|
|
128
|
+
content idempotently. Changed skill text or a changed managed block causes a
|
|
129
|
+
conflict instead of an overwrite. Review your edits before retrying.
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
redue agent remove codex --dry-run
|
|
133
|
+
redue agent remove codex --apply
|
|
134
|
+
redue agent remove claude --apply
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Removal deletes only intact REDUE-owned content for that host. Unrelated text,
|
|
138
|
+
other integrations, project config, receipts and installed dependencies remain.
|
|
139
|
+
User edits outside the managed section survive. Modified managed content is left
|
|
140
|
+
intact with a diagnostic; compare it with a preview and resolve manually. Empty
|
|
141
|
+
parent directories may remain. If the selected config has been deleted, restore
|
|
142
|
+
it or manually remove only the marked REDUE section, that host's skill, and its
|
|
143
|
+
`.redue/agents/HOST.json` ownership record after review. Do not delete an entire
|
|
144
|
+
instruction file containing user content.
|
|
145
|
+
|
|
146
|
+
## Project identity and generic agents
|
|
147
|
+
|
|
148
|
+
Commands from nested directories search toward the nearest Git root. If more than
|
|
149
|
+
one configuration applies, select one with `--config FILE`; REDUE refuses to guess.
|
|
150
|
+
The generated instruction names its project-relative configuration and applies it
|
|
151
|
+
to status/run/explain. External configs or custom machine-local `--state-dir`
|
|
152
|
+
setups should use a reviewed generic instruction instead of committing absolute
|
|
153
|
+
paths. Other worktrees and remote containers have separate local evidence.
|
|
154
|
+
|
|
155
|
+
For another agent, put a short instruction in its documented project mechanism:
|
|
156
|
+
“Before deciding whether configured verification needs repeating, read REDUE's
|
|
157
|
+
agent policy, query ordinary `redue status --json` for the intended config, and
|
|
158
|
+
apply the schema/health/reuse rules.” Supply this document and the
|
|
159
|
+
[JSON contract](json.md) as the detailed policy. Review the agent's actual tool
|
|
160
|
+
trace before calling activation verified. A local npm installation does not install
|
|
161
|
+
REDUE in a remote container; that environment needs its own CLI, checkout,
|
|
162
|
+
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,9 @@ 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
|
+
|
|
31
34
|
## Arbitrary commands
|
|
32
35
|
|
|
33
36
|
An unrecognized ecosystem can still record ordinary execution:
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Explicit local TypeScript verification (unreleased candidate)
|
|
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 an existing standalone
|
|
8
|
+
`tsc --noEmit` script, installed dependencies, Node 22/24 and TypeScript 5.6.3/5.9.3:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
redue init --recipe typescript-direct --check typecheck --dry-run
|
|
12
|
+
redue init --recipe typescript-direct --check typecheck
|
|
13
|
+
redue start
|
|
14
|
+
redue run typecheck
|
|
15
|
+
redue status --sync
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The preview shows the discovered script and recorded direct invocation. Nothing
|
|
19
|
+
executes during init. package.json, environment and dependencies remain unchanged.
|
|
20
|
+
A generated check contains:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"name": "typecheck",
|
|
25
|
+
"script": "typecheck",
|
|
26
|
+
"kind": "typecheck",
|
|
27
|
+
"command": ["@node", "@typescript-compiler:.", "--noEmit"],
|
|
28
|
+
"cwd": ".",
|
|
29
|
+
"qualification": "npm-typescript-direct-v1",
|
|
30
|
+
"inputs": ["package.json", "package-lock.json", "tsconfig.json", "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs,json,jsonc}", "!node_modules/**", "!.git/**"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`script` identifies the reviewed source recipe; `command` is what actually runs:
|
|
35
|
+
the resolved Node executable and local TypeScript implementation, with exact argv
|
|
36
|
+
and no shell. TypeScript 5.6.3 uses `lib/tsc.js`; 5.9.3 uses `lib/_tsc.js` directly,
|
|
37
|
+
without its outer compile-cache-enabling shim. No compiler is fetched or bundled.
|
|
38
|
+
The entire installed package must match reviewed official distribution bytes.
|
|
39
|
+
|
|
40
|
+
Existing configs are never overwritten. To compare choices, use a new project-local
|
|
41
|
+
`--config redue.direct.config.json` with init; this explicitly selects separate
|
|
42
|
+
state. To replace an existing check deliberately, preview JSON, stop its observer,
|
|
43
|
+
review/edit that check's config, and restart using the same config/state. Existing
|
|
44
|
+
npm receipts remain historical; the new command/interpretation needs a fresh run.
|
|
45
|
+
Do not delete receipts. `redue run` always executes the configured command.
|
|
46
|
+
|
|
47
|
+
## Existing npm configuration: deliberate replacement
|
|
48
|
+
|
|
49
|
+
First upgrade through the [alpha.4 containment](npm-launcher-notice.md), stopping
|
|
50
|
+
observers before the installation change and restarting with the same config/state.
|
|
51
|
+
The old npm check becomes recording-only; its receipts remain historical.
|
|
52
|
+
To opt into this candidate afterward:
|
|
53
|
+
|
|
54
|
+
1. Stop the observer, install the reviewed candidate tarball into the same prefix,
|
|
55
|
+
and keep the original `redue.config.json` and any explicit `--state-dir` selection.
|
|
56
|
+
2. Run `redue init --recipe typescript-direct --check typecheck --dry-run --json`
|
|
57
|
+
using that config selection. Inspect `proposed_config.checks` and the recorded
|
|
58
|
+
invocation. This does not write anything, even when the config already exists.
|
|
59
|
+
3. In your editor, replace only the intended check object with the reviewed proposed
|
|
60
|
+
object. Preserve its name, the top-level project configuration, and every other
|
|
61
|
+
check. Do not replace the whole config with a one-check preview. Keep a local
|
|
62
|
+
backup outside observed inputs if desired.
|
|
63
|
+
4. Run `redue start` with the same config/state. `redue status --sync --json` must
|
|
64
|
+
not treat the old npm receipt as eligible compiler evidence.
|
|
65
|
+
5. Run `redue run typecheck`, then `redue status --sync --json`. A qualified success
|
|
66
|
+
now records the direct compiler recipe with a new run ID. Old npm runs remain
|
|
67
|
+
immutable history. Other check definitions are unchanged.
|
|
68
|
+
|
|
69
|
+
Substitute the actual selected check name throughout. Repeating plain `init`
|
|
70
|
+
does **not** migrate an existing config. A deliberately separate `--config` file
|
|
71
|
+
is useful for comparison, but has separate state by design. Do not create one
|
|
72
|
+
accidentally when intending to preserve the original selection.
|
|
73
|
+
|
|
74
|
+
Pre/post scripts, compound commands, wrappers, environment assignments, workspace
|
|
75
|
+
projects and unsupported compiler versions are not automatically converted.
|
|
76
|
+
Init retains the original script with a reason. Development-mode source-map helpers,
|
|
77
|
+
Node preloads/loaders/compile-cache settings, unsupported compiler plugins or
|
|
78
|
+
incremental/composite configuration, outside-root inputs and uncertain observation
|
|
79
|
+
withhold applicability. Extra custom probes cannot inherit this recipe's context
|
|
80
|
+
exception. Relevant source, declaration, config, membership and installed-content
|
|
81
|
+
changes invalidate or withdraw applicability normally.
|
|
82
|
+
|
|
83
|
+
The versioned `npm-direct-typescript@1` interpretation retains relevant Node context
|
|
84
|
+
and identity. Reviewed compiler code does not parse npm settings or proxy variables;
|
|
85
|
+
these remain untouched in the child environment and are recorded only as a digest
|
|
86
|
+
of observed provenance. This is not an environment ignore option for arbitrary
|
|
87
|
+
commands or other providers. No remote service equivalence is claimed. Ordinary
|
|
88
|
+
cached status remains conservative; synchronize deliberately when worth the cost.
|
|
89
|
+
|
|
90
|
+
Explain/JSON report `verification_recipe: "npm-direct-typescript@1"` for receipts
|
|
91
|
+
recorded with this recipe. Report compiler evidence as compiler evidence. A user's
|
|
92
|
+
explicit request for `npm run typecheck` is not satisfied by this different command.
|
|
93
|
+
|
|
94
|
+
The injected `NODE_USE_ENV_PROXY=1` setting is admitted only on Node 22.13.0,
|
|
95
|
+
where it is inert; it remains strictly tracked. Other Node versions with this
|
|
96
|
+
setting need review and stay unqualified. REDUE does not alter the setting.
|
|
@@ -90,7 +90,10 @@ reusability. Qualification can change when configuration or installation changes
|
|
|
90
90
|
|
|
91
91
|
`run` streams normal output and preserves execution environment and cancellation.
|
|
92
92
|
For the narrow pnpm TypeScript contract, `init` explicitly shows the direct installed
|
|
93
|
-
compiler invocation it selects
|
|
93
|
+
compiler invocation it selects. In this candidate, npm scripts remain recording-only;
|
|
94
|
+
use `redue init --recipe typescript-direct --dry-run` to preview a distinct,
|
|
95
|
+
explicit [local compiler recipe](direct-typescript.md). Other scripts run through
|
|
96
|
+
the package manager. No existing configuration is silently migrated.
|
|
94
97
|
Only use configs and probes from trusted repositories: these execute local code.
|
|
95
98
|
|
|
96
99
|
`status` is cached and conservative. `status --sync` and `explain` revalidate caller
|
|
@@ -133,3 +136,11 @@ all observed roots; its basename must start with `redue-` or legacy `vstate-`.
|
|
|
133
136
|
For a removed checkout, `redue --state-dir /your/owned/redue-project-state remove-state`
|
|
134
137
|
still works without rebuilding its compiler/configuration. Ownership/active-run conflicts
|
|
135
138
|
are actionable errors, never resolved merely by deleting an old lock.
|
|
139
|
+
|
|
140
|
+
## Connect an agent explicitly
|
|
141
|
+
|
|
142
|
+
After initialization, use `redue agent setup codex --dry-run` (or `claude`) to
|
|
143
|
+
review project-local instructions, then repeat with `--apply`. Start a fresh host
|
|
144
|
+
session. `redue agent doctor` checks prerequisites without running verification.
|
|
145
|
+
See [agent activation](agents.md) for loading rules, generic agents, and removal.
|
|
146
|
+
The released alpha.2 does not contain these candidate commands yet.
|
|
@@ -15,13 +15,15 @@ At the repository root, `init` looks for existing typecheck, test, lint, and
|
|
|
15
15
|
build scripts. It prefers familiar script names, then unique recognizable
|
|
16
16
|
`tsc`, Vitest/Jest, ESLint, or Vite commands under other names. Multiple
|
|
17
17
|
matches are reported as ambiguous rather than guessed. It never creates a new
|
|
18
|
-
project script.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
project script. Automatic npm-launcher applicability was withdrawn in alpha.4;
|
|
19
|
+
ordinary npm scripts remain recording-only. See the [maintainer notice](npm-launcher-notice.md).
|
|
20
|
+
The following direct recipe is opt-in and new in the alpha.5 candidate. The opt-in `init --recipe typescript-direct` supports
|
|
21
|
+
a standalone `tsc --noEmit` script in a single-package npm installation using
|
|
22
|
+
reviewed TypeScript 5.6.3/5.9.3 and Node 22/24. It executes the local compiler,
|
|
23
|
+
not npm. Full installed compiler identity, config/membership, installed inputs
|
|
24
|
+
and relevant Node environment are checked before reuse. See the
|
|
25
|
+
[exact direct boundary](direct-typescript.md). Unsupported plugins, preloads,
|
|
26
|
+
configuration or outside-root inputs remain UNVERIFIED. Root and package-level npm/Yarn workspace scripts are discovered from
|
|
25
27
|
`package.json` workspace declarations. Pinned Yarn 4 `node-modules`/classic
|
|
26
28
|
workspaces with a standalone `tsc -p .` script, local TypeScript, a conventional
|
|
27
29
|
`src` include, and Node module resolution can qualify automatically. For one
|