@redue/cli 0.0.0-stage → 0.1.0-alpha.2
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 +22 -0
- package/LICENSE +180 -0
- package/README.md +123 -2
- package/bin/redue.mjs +329 -0
- package/bin/vstate.mjs +3 -0
- package/docs/README.md +20 -0
- package/docs/user/agents.md +32 -0
- package/docs/user/configuration.md +57 -0
- package/docs/user/getting-started.md +127 -0
- package/docs/user/json.md +59 -0
- package/docs/user/shell.md +25 -0
- package/docs/user/supported-projects.md +89 -0
- package/examples/redue.config.json +8 -0
- package/package.json +46 -4
- package/src/cached-state.mjs +27 -0
- package/src/cli.mjs +390 -0
- package/src/control-endpoint.mjs +11 -0
- package/src/daemon.mjs +989 -0
- package/src/decision-profile.mjs +18 -0
- package/src/decision-validation.mjs +41 -0
- package/src/declared-plan.mjs +125 -0
- package/src/executable-lookup.mjs +18 -0
- package/src/glob.mjs +9 -0
- package/src/history-worker.mjs +18 -0
- package/src/index.mjs +306 -0
- package/src/installed-inputs.mjs +110 -0
- package/src/linux-inotify.py +228 -0
- package/src/linux-observer.mjs +79 -0
- package/src/node-onboarding.mjs +263 -0
- package/src/npm-typecheck-probe.mjs +120 -0
- package/src/observation.mjs +37 -0
- package/src/owned-state.mjs +32 -0
- package/src/path-identity.mjs +43 -0
- package/src/plan-worker.mjs +131 -0
- package/src/plan.mjs +10 -0
- package/src/platform-observation.mjs +17 -0
- package/src/platform-state.mjs +14 -0
- package/src/pnpm-inputs.mjs +355 -0
- package/src/pnpm-typecheck-probe.mjs +47 -0
- package/src/presentation.mjs +52 -0
- package/src/probe-result.mjs +21 -0
- package/src/process-liveness.mjs +11 -0
- package/src/run-lock.mjs +77 -0
- package/src/state-store.mjs +37 -0
- package/src/toolchain-probe.mjs +21 -0
- package/src/typescript-contract-probe.mjs +188 -0
- package/src/typescript-list.mjs +68 -0
- package/src/typescript-qualification.mjs +96 -0
- package/src/windows-command.mjs +16 -0
- package/src/windows-process.mjs +15 -0
- package/src/yarn-workspace-inputs.mjs +148 -0
- package/src/yarn-workspace-typecheck-probe.mjs +107 -0
package/bin/vstate.mjs
ADDED
package/docs/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
For users:
|
|
4
|
+
|
|
5
|
+
- [Install, initialize, run, and remove](user/getting-started.md)
|
|
6
|
+
- [Supported projects and conservative boundaries](user/supported-projects.md)
|
|
7
|
+
- [Configuration](user/configuration.md)
|
|
8
|
+
- [Coding-agent decision policy](user/agents.md)
|
|
9
|
+
- [JSON contract](user/json.md)
|
|
10
|
+
- [Shell usage](user/shell.md)
|
|
11
|
+
|
|
12
|
+
For contributors:
|
|
13
|
+
|
|
14
|
+
- [Architecture](contributor/architecture.md)
|
|
15
|
+
- [Observation and recovery](contributor/observation-recovery.md)
|
|
16
|
+
- [Reproducible terminal demo](contributor/demo.md)
|
|
17
|
+
- [Release procedure](contributor/releasing.md)
|
|
18
|
+
|
|
19
|
+
[Historical acceptance evidence](acceptance/README.md) is retained separately.
|
|
20
|
+
It records measured environments and limitations; it is not the getting-started guide.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Agent decision policy
|
|
2
|
+
|
|
3
|
+
Use the CLI; no SDK or bespoke agent integration is required. Add these
|
|
4
|
+
instructions to a session or project only with its owner's permission.
|
|
5
|
+
|
|
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.
|
|
9
|
+
3. If STALE, run `redue run CHECK` when that verification is needed.
|
|
10
|
+
4. If the historical `result` is FAIL, report it honestly. The human CLI calls
|
|
11
|
+
this FAILED; applicability is a separate field, never an excuse to call it green.
|
|
12
|
+
5. If UNVERIFIED, inspect its reason. Use `status --sync --json` when establishing
|
|
13
|
+
applicability is worthwhile, or rerun the underlying check when cheaper/simpler.
|
|
14
|
+
Use `redue run CHECK` if a new receipt is wanted. Incomplete coverage can remain
|
|
15
|
+
UNVERIFIED even after success.
|
|
16
|
+
6. Do not assume synchronization is cheaper than execution. There are no universal
|
|
17
|
+
package-manager or OS thresholds. Inexpensive checks may be cheaper to rerun.
|
|
18
|
+
|
|
19
|
+
`redue explain CHECK --json` gives synchronized detail, including a known changed
|
|
20
|
+
input when available. It has the same cost caveat as synchronized status.
|
|
21
|
+
|
|
22
|
+
No previous conversation history is needed to read a persisted receipt. Still
|
|
23
|
+
consider independent task-specific reasons to run verification: the configured
|
|
24
|
+
check is not universal product correctness. Report additional uncaptured checks
|
|
25
|
+
separately. Do not infer that an outer invocation's success proves a specific
|
|
26
|
+
check ran or that an upstream cache was hit; inspect `target_provenance`.
|
|
27
|
+
|
|
28
|
+
On a CLI error, unhealthy observation, or unavailable context, do not infer
|
|
29
|
+
CURRENT. Do not delete state or reset receipts to make the output green.
|
|
30
|
+
|
|
31
|
+
REDUE tells you what evidence exists and whether it still applies. It does not
|
|
32
|
+
promise that establishing applicability is cheaper than every possible check.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Prefer `redue init` over hand-authoring a qualified contract. A typical generated
|
|
4
|
+
npm configuration is concise and portable:
|
|
5
|
+
|
|
6
|
+
```json
|
|
7
|
+
{
|
|
8
|
+
"schema": 1,
|
|
9
|
+
"root": ".",
|
|
10
|
+
"packageManager": "npm",
|
|
11
|
+
"checks": [{
|
|
12
|
+
"name": "typecheck",
|
|
13
|
+
"script": "typecheck",
|
|
14
|
+
"kind": "typecheck",
|
|
15
|
+
"qualification": "typescript-noemit-v1",
|
|
16
|
+
"inputs": ["package.json", "package-lock.json", "tsconfig*.json", "src/**"]
|
|
17
|
+
}]
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The exact inputs are derived from the detected project; use the emitted config,
|
|
22
|
+
not this example to assert your project's coverage. Generated Yarn/pnpm workspace
|
|
23
|
+
checks also identify the owning workspace and actual command. Large dependency
|
|
24
|
+
relationships stay in local runtime state. `qualification` selects a supported
|
|
25
|
+
validation recipe; it is not a blanket coverage assertion.
|
|
26
|
+
|
|
27
|
+
Use `--config FILE` to select an external configuration. `root` is relative to
|
|
28
|
+
that file. Runtime paths, resolved executables, local evidence, and sockets stay
|
|
29
|
+
out of version-controlled configuration.
|
|
30
|
+
|
|
31
|
+
## Arbitrary commands
|
|
32
|
+
|
|
33
|
+
An unrecognized ecosystem can still record ordinary execution:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"schema": 1,
|
|
38
|
+
"checks": [{
|
|
39
|
+
"name": "migration",
|
|
40
|
+
"command": ["@node", "tools/check-migrations.mjs"],
|
|
41
|
+
"inputs": ["migrations/**", "tools/check-migrations.mjs"]
|
|
42
|
+
}]
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Commands are exact argv, not shell text. Use `cwd` for a project-relative working
|
|
47
|
+
directory. `@node`, `@project`, and `@which:NAME` resolve explicit invocation facts.
|
|
48
|
+
Manual checks start recording-only: a plausible list of files is not proof of a
|
|
49
|
+
complete input boundary. Do not copy coverage assertions from unrelated projects.
|
|
50
|
+
|
|
51
|
+
Advanced explicit contracts may declare `generatedInputs`, `installedInputs`, narrow
|
|
52
|
+
`allowedExternalRoots`, read-only `probes`, and relevant `environment`. These are
|
|
53
|
+
reviewed escape hatches, not onboarding requirements. A coverage rationale cannot
|
|
54
|
+
override unsupported storage, unresolved links, missing inputs, or observation failure.
|
|
55
|
+
|
|
56
|
+
Changing commands, relevant configuration, installed material, or consumed inputs
|
|
57
|
+
invalidates prior applicability. It does not erase historical execution outcomes.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Install and use REDUE
|
|
2
|
+
|
|
3
|
+
Requirements: Git; Node 22 or newer with npm; an existing local JS/TS checkout
|
|
4
|
+
with its dependencies installed. Linux additionally needs `python3`. Supported
|
|
5
|
+
storage is local APFS on macOS, NTFS on Windows, and the documented native Linux
|
|
6
|
+
filesystems. Network/FUSE/overlay mounts are not qualified Linux storage.
|
|
7
|
+
Node 22 and 24 are the release-test matrix; newer majors are not yet acceptance claims.
|
|
8
|
+
|
|
9
|
+
Install the public alpha:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install --global @redue/cli@alpha
|
|
13
|
+
redue --version
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
For an unpublished source candidate, run `npm ci` and `npm pack --json`, then
|
|
17
|
+
install the exact filename reported by npm with `npm install --global ./<filename>`.
|
|
18
|
+
|
|
19
|
+
These commands also work in PowerShell (use `npm.cmd`/`redue.cmd` when a local
|
|
20
|
+
PowerShell script policy blocks generated `.ps1` shims; do not change policy).
|
|
21
|
+
No build step, custom installer, account, or login service is required. Installing
|
|
22
|
+
npm dependencies uses the registry; normal local observation does not require network.
|
|
23
|
+
|
|
24
|
+
For a reversible user-owned prefix, POSIX shells:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
npm install --global --prefix "$HOME/.local/redue-alpha" @redue/cli@alpha
|
|
28
|
+
export PATH="$HOME/.local/redue-alpha/bin:$PATH"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
PowerShell:
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
$reduePrefix = Join-Path $env:LOCALAPPDATA 'redue-alpha-install'
|
|
35
|
+
npm.cmd install --global --prefix $reduePrefix @redue/cli@alpha
|
|
36
|
+
$env:PATH = "$reduePrefix;$env:PATH"
|
|
37
|
+
redue.cmd --help
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
These PATH changes affect only the current shell. Alternatively invoke the
|
|
41
|
+
installed entry point directly: POSIX `node "$HOME/.local/redue-alpha/lib/node_modules/@redue/cli/bin/redue.mjs"`;
|
|
42
|
+
Windows `node "$reduePrefix/node_modules/@redue/cli/bin/redue.mjs"`.
|
|
43
|
+
|
|
44
|
+
## Moving from alpha.1
|
|
45
|
+
|
|
46
|
+
If the personal-scope alpha.1 package is installed, stop the project's observer
|
|
47
|
+
and replace that package before installing the canonical command:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
redue stop
|
|
51
|
+
npm uninstall --global @msiric/redue
|
|
52
|
+
npm install --global @redue/cli@alpha
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Use the same `--prefix` on both npm commands if your installation has a custom
|
|
56
|
+
prefix. Uninstalling the package does not remove local verification evidence;
|
|
57
|
+
`redue remove-state` is a separate, explicit action. Alpha.1 remains available as
|
|
58
|
+
historical software and is superseded for package identity, not a runtime defect.
|
|
59
|
+
|
|
60
|
+
## First project
|
|
61
|
+
|
|
62
|
+
From the project root:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
redue init --dry-run
|
|
66
|
+
redue init
|
|
67
|
+
redue start
|
|
68
|
+
redue run typecheck
|
|
69
|
+
redue status
|
|
70
|
+
redue explain typecheck
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use a check actually printed by `init`. For a workspace:
|
|
74
|
+
`redue init --workspace @example/package --check typecheck`.
|
|
75
|
+
Initialization previews detected commands and qualification confidence before writing
|
|
76
|
+
`redue.config.json`. An existing config is never overwritten. No checks are run and
|
|
77
|
+
no dependencies installed. A missing/unsupported boundary is explained.
|
|
78
|
+
|
|
79
|
+
“Ready to qualify” means REDUE has a supported recipe whose prerequisites will be
|
|
80
|
+
validated. It is not a receipt. “Recording-only” can record PASS/FAIL without claiming
|
|
81
|
+
reusability. Qualification can change when configuration or installation changes.
|
|
82
|
+
|
|
83
|
+
`run` streams normal output and preserves execution environment and cancellation.
|
|
84
|
+
For the narrow pnpm TypeScript contract, `init` explicitly shows the direct installed
|
|
85
|
+
compiler invocation it selects; other scripts run through the package manager.
|
|
86
|
+
Only use configs and probes from trusted repositories: these execute local code.
|
|
87
|
+
|
|
88
|
+
`status` is cached and conservative. `status --sync` and `explain` revalidate caller
|
|
89
|
+
context and may execute read-only probes. Synchronization can be slower than a cheap
|
|
90
|
+
check, especially on Windows. Choose deliberately. A timeout is UNVERIFIED, not green.
|
|
91
|
+
|
|
92
|
+
## Lifecycle and removal
|
|
93
|
+
|
|
94
|
+
`start` starts this config's owned observer, or reports that it is already running.
|
|
95
|
+
If already running, use `status`; do not create a second state directory just to
|
|
96
|
+
start another observer. Startup may report initialization before inputs are ready.
|
|
97
|
+
`stop` stops that observer and retains historical evidence. After restart, observation
|
|
98
|
+
is reconciled before reuse.
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
redue stop
|
|
102
|
+
redue start
|
|
103
|
+
redue remove-state
|
|
104
|
+
npm uninstall --global @redue/cli
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For an isolated installation, use the same `--prefix` on uninstall. Remove state
|
|
108
|
+
**before** uninstalling the command. No broad recursive deletion command is needed.
|
|
109
|
+
`remove-state` checks its ownership marker and stops only that observer. It does not
|
|
110
|
+
remove project files, dependencies, another tool's watches, or other REDUE configurations.
|
|
111
|
+
To remove project configuration, inspect and delete `redue.config.json` yourself.
|
|
112
|
+
|
|
113
|
+
Runtime state is separate from durable project config. Legacy directory spelling is
|
|
114
|
+
retained for compatibility, not copied into your config:
|
|
115
|
+
|
|
116
|
+
| OS | Default state base |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| macOS | `~/Library/Application Support/vstate/` |
|
|
119
|
+
| Linux | `$XDG_STATE_HOME/vstate/`, otherwise `~/.local/state/vstate/` |
|
|
120
|
+
| Windows | `%LOCALAPPDATA%/vstate/` |
|
|
121
|
+
|
|
122
|
+
A checkout/config identity selects a dedicated child directory. Use
|
|
123
|
+
`--state-dir /your/owned/redue-project-state` to choose a dedicated directory outside
|
|
124
|
+
all observed roots; its basename must start with `redue-` or legacy `vstate-`.
|
|
125
|
+
For a removed checkout, `redue --state-dir /your/owned/redue-project-state remove-state`
|
|
126
|
+
still works without rebuilding its compiler/configuration. Ownership/active-run conflicts
|
|
127
|
+
are actionable errors, never resolved merely by deleting an old lock.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Alpha JSON interface (schema 1)
|
|
2
|
+
|
|
3
|
+
Use `status --json` for cached state, `status --sync --json` for caller-aware
|
|
4
|
+
applicability, and `explain CHECK --json` for selected synchronized detail.
|
|
5
|
+
`detail` remains an alias. Successful reads emit one JSON object, no human prose.
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"schema": 1,
|
|
10
|
+
"state": "stale",
|
|
11
|
+
"current": 0, "stale": 1, "failed": 0, "observed_failed": 0, "unverified": 0,
|
|
12
|
+
"checks": [{
|
|
13
|
+
"name": "typecheck",
|
|
14
|
+
"result": "PASS",
|
|
15
|
+
"freshness": "STALE",
|
|
16
|
+
"reason": "src/main.ts changed",
|
|
17
|
+
"changed_inputs": ["src/main.ts"],
|
|
18
|
+
"reuse_eligible": false,
|
|
19
|
+
"invocation": {"runId": "opaque-run-id", "status": "exited", "exitCode": 0, "durationMs": 940}
|
|
20
|
+
}],
|
|
21
|
+
"observation": {"healthy": true}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Stable-enough-for-alpha fields:
|
|
26
|
+
|
|
27
|
+
| Field | Contract |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| `checks[].name` | Configured check identity. |
|
|
30
|
+
| `result` | Historical `PASS`, `FAIL`, or null. A failed invocation is not green even with CURRENT applicability. |
|
|
31
|
+
| `freshness` | `CURRENT`, `STALE`, or `UNVERIFIED`, independent of result. |
|
|
32
|
+
| `reuse_eligible` | True only for qualified, applicable passing evidence. Never derive permission to reuse from outcome alone. Missing means false. |
|
|
33
|
+
| `reason` | Human explanation; not a stable machine enum. Do not parse it to authorize reuse. |
|
|
34
|
+
| `changed_inputs` | Known changed relevant paths when available, possibly only the first difference; empty/missing is not proof of no changes. |
|
|
35
|
+
| `invocation` | Null without a receipt; otherwise run ID, completion `status`, duration, exit code/signal when known. Status distinguishes exited, interrupted, and start/capture failure. |
|
|
36
|
+
| `target_provenance` | Available target evidence. Unknown is not executed or cache-hit. |
|
|
37
|
+
| `observation.healthy` | False means no check is reusable. Additional reason/phase diagnostics may appear. |
|
|
38
|
+
| `state` | Aggregate lowercase current/stale/failed/unverified (and runtime pending states where applicable). Use per-check fields for decisions. |
|
|
39
|
+
|
|
40
|
+
Counts cover the whole configuration even when `explain CHECK` filters `checks`.
|
|
41
|
+
`failed` counts applicable failures; `observed_failed` preserves historical failures
|
|
42
|
+
regardless of applicability. Fields not listed here are diagnostic and may evolve.
|
|
43
|
+
Ignore unknown fields; reject unknown schema versions. These responses contain local
|
|
44
|
+
paths/check names and must not be uploaded automatically.
|
|
45
|
+
|
|
46
|
+
`init --json` returns discovery levels (`ready`, `recording`, `unsupported`),
|
|
47
|
+
reasons, workspace ownership, `written`, and `proposed_config`. Ready is not PASS.
|
|
48
|
+
`init --dry-run --json` writes no config and runs no check.
|
|
49
|
+
|
|
50
|
+
Read commands normally exit 0 even when the evidence is not current. Errors exit
|
|
51
|
+
nonzero; synchronized transport failures may still return conservative JSON.
|
|
52
|
+
Usage/configuration errors go to stderr and are not guaranteed JSON. Never treat
|
|
53
|
+
a failed read as authority from a previously cached answer.
|
|
54
|
+
|
|
55
|
+
`run CHECK --json` preserves ordinary command stdin/stdout/stderr and appends a
|
|
56
|
+
JSON summary. **Its stdout is not a JSON-only stream.** Query status/details after
|
|
57
|
+
completion for machine-readable evidence. Normal check exit codes are preserved;
|
|
58
|
+
interruption/process-start failures are nonzero. REDUE retains metadata and receipts,
|
|
59
|
+
not arbitrary terminal output. The CLI does not infer tests executed from prose.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Shell usage
|
|
2
|
+
|
|
3
|
+
Run `redue start` once for the project/configuration you want to observe. A shell,
|
|
4
|
+
terminal multiplexer, and agent using that same config share its backend. Closing
|
|
5
|
+
the terminal does not stop the observer. `redue stop` does.
|
|
6
|
+
|
|
7
|
+
`redue status --short` is the intended small indicator:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
REDUE UNVERIFIED
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
It reads the cached snapshot, checks its expiry and observer liveness, and never
|
|
14
|
+
synchronizes, traverses installed packages, or runs probes/checks. Like ordinary
|
|
15
|
+
status, it can remain conservative when caller context or installed hardlinks
|
|
16
|
+
need a synchronized read. Do not turn that uncertainty into a green badge.
|
|
17
|
+
|
|
18
|
+
For an existing async/bounded prompt framework, use `redue status --short` from
|
|
19
|
+
the project root as the segment command and display unavailable on errors or
|
|
20
|
+
timeout. Node startup and configuration parsing still have a cost. REDUE does
|
|
21
|
+
not install a shell hook, edit global shell files, or provide its own prompt
|
|
22
|
+
scheduler. Running it manually is supported in PowerShell and POSIX shells.
|
|
23
|
+
|
|
24
|
+
Never put `status --sync` or `explain` in a prompt. Use those deliberately when
|
|
25
|
+
you need a decision and synchronization is worth its cost.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Supported Node projects
|
|
2
|
+
|
|
3
|
+
`init` detects npm from `package-lock.json`/`npm-shrinkwrap.json` or an npm
|
|
4
|
+
`packageManager` declaration. It detects Yarn from `yarn.lock` or its
|
|
5
|
+
declaration and reads `.yarnrc.yml` to distinguish node-modules/classic from
|
|
6
|
+
PnP and other modes. A Yarn v1 lockfile can identify the classic layout, but
|
|
7
|
+
without a declared Yarn version `init` does not create a runnable config:
|
|
8
|
+
Corepack can select a different version and edit `package.json`. Conflicting
|
|
9
|
+
package managers are reported without pretending that installation coverage
|
|
10
|
+
is known. When npm is not pinned in `package.json`,
|
|
11
|
+
`init` reads the local npm executable's package manifest if available; it
|
|
12
|
+
leaves the version unknown rather than guessing if that inspection fails.
|
|
13
|
+
|
|
14
|
+
At the repository root, `init` looks for existing typecheck, test, lint, and
|
|
15
|
+
build scripts. It prefers familiar script names, then unique recognizable
|
|
16
|
+
`tsc`, Vitest/Jest, ESLint, or Vite commands under other names. Multiple
|
|
17
|
+
matches are reported as ambiguous rather than guessed. It never creates a new
|
|
18
|
+
project script. It recognizes canonical
|
|
19
|
+
`tsc --noEmit` on local npm installations as a candidate for automatic
|
|
20
|
+
qualification. Before CURRENT is possible, a read-only probe checks the
|
|
21
|
+
TypeScript configuration and effective file list, local compiler, installed
|
|
22
|
+
contents, npm/Node identity, and relevant caller context. Unsupported plugins,
|
|
23
|
+
preloads, config graphs, or outside-root inputs leave the check UNVERIFIED with
|
|
24
|
+
an explanation. A discovered script can still be run and recorded in that
|
|
25
|
+
state. Root and package-level npm/Yarn workspace scripts are discovered from
|
|
26
|
+
`package.json` workspace declarations. Pinned Yarn 4 `node-modules`/classic
|
|
27
|
+
workspaces with a standalone `tsc -p .` script, local TypeScript, a conventional
|
|
28
|
+
`src` include, and Node module resolution can qualify automatically. For one
|
|
29
|
+
workspace, use `redue init --workspace NAME --check typecheck`; it writes only
|
|
30
|
+
that check and keeps derived relationships out of project configuration. The
|
|
31
|
+
contract observes selected `src` membership, root/package TypeScript config,
|
|
32
|
+
built declarations of internal workspace dependencies, and physical installed
|
|
33
|
+
files. It rechecks TypeScript's effective input list with a read-only probe.
|
|
34
|
+
A sibling workspace is not an input merely because it shares the repository.
|
|
35
|
+
When an internal dependency is consumed through built declarations, changing
|
|
36
|
+
only its source does not stale the selected check until the consumed output
|
|
37
|
+
changes. Unsupported custom resolution, project references, outside-root
|
|
38
|
+
source links, and installation modes remain recording-only. Other Yarn
|
|
39
|
+
typechecks, Vitest/Jest, ESLint, and builds start recording-only unless a
|
|
40
|
+
separately justified explicit contract is provided.
|
|
41
|
+
In particular, test caches and build-generated inputs are not excluded to
|
|
42
|
+
make evidence green.
|
|
43
|
+
|
|
44
|
+
Pinned pnpm 12 projects are read from `packageManager`, `pnpm-workspace.yaml`,
|
|
45
|
+
the lockfile, and the installed `node_modules/.modules.yaml` metadata. The
|
|
46
|
+
supported local layouts are pnpm's standard isolated and hoisted
|
|
47
|
+
`node_modules` with a project-local `.pnpm` virtual store. `init` can discover
|
|
48
|
+
root and workspace scripts. For a standalone `tsc --noEmit` or `tsc -p ...`
|
|
49
|
+
script in the narrow TypeScript contract, it records the exact installed
|
|
50
|
+
compiler invocation directly. This avoids pnpm 12's task-run bookkeeping
|
|
51
|
+
writes during `pnpm run`; it does not alter the project's script. Test, lint,
|
|
52
|
+
build, and ambiguous TypeScript scripts still execute through `pnpm run` and
|
|
53
|
+
start recording-only. The generated `@typescript-bin:WORKSPACE` token resolves
|
|
54
|
+
the local compiler when the check runs; it is not an absolute machine path.
|
|
55
|
+
|
|
56
|
+
The pnpm contract indexes consumed installed package contents inside the
|
|
57
|
+
project, selected workspace source, linked workspace declaration outputs,
|
|
58
|
+
relevant manifests, configuration, and installation metadata. The global pnpm
|
|
59
|
+
store is neither watched nor deleted. PnP, custom modules/virtual-store roots,
|
|
60
|
+
global virtual stores, injected workspace dependencies, and external links
|
|
61
|
+
without an observed boundary remain recording-only with a reason. Installed
|
|
62
|
+
files with hard-linked aliases outside the checkout remain recording-only on
|
|
63
|
+
macOS: writes through an unseen alias cannot support CURRENT there. On Linux,
|
|
64
|
+
redue watches project-installed file inodes and rehashes the selected
|
|
65
|
+
installed inputs on every synchronized read. A cached read remains UNVERIFIED
|
|
66
|
+
for these pnpm checks; a synchronized read can establish CURRENT after the
|
|
67
|
+
rehash. If an inode watch cannot be installed, observation becomes unavailable
|
|
68
|
+
instead of dropping that file. The global store is not watched. An absent
|
|
69
|
+
optional package remains unqualified when Node could later
|
|
70
|
+
resolve it from an unobserved ancestor `node_modules`; project-local candidate
|
|
71
|
+
locations are still tracked for plan changes. No configuration assertion is
|
|
72
|
+
generated to hide either gap.
|
|
73
|
+
|
|
74
|
+
An unobservable source symlink or missing Git checkout is reported by `init`
|
|
75
|
+
before writing a config. A local explicit configuration can grant a narrow
|
|
76
|
+
external observation root after review; `init` will not add machine-specific
|
|
77
|
+
paths to a project config automatically.
|
|
78
|
+
|
|
79
|
+
The generated config is project-relative and versioned. Runtime state and
|
|
80
|
+
receipts live separately. `packageManager`, `checks[].script`, `kind`,
|
|
81
|
+
`inputs`, optional `workspace`, and optional `qualification` are the generated
|
|
82
|
+
public fields. The
|
|
83
|
+
CLI also accepts `checks[].command` as exact argv for arbitrary checks;
|
|
84
|
+
`@node`, `@project`, `@which:NAME`, and the narrow
|
|
85
|
+
`@typescript-bin:WORKSPACE` token are resolved at invocation. A command
|
|
86
|
+
or input-declaration change invalidates previous evidence.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
Windows supports the same qualified contracts on local NTFS, with project-visible installed hardlinks revalidated during synchronized reads. Cached hardlink-sensitive applicability is conservative. No package-manager or platform promises that synchronization is cheaper than execution.
|
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redue/cli",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.1.0-alpha.2",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"tag": "alpha"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"bin": {
|
|
11
|
+
"redue": "./bin/redue.mjs"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "node --test --test-concurrency=1 test/*.test.mjs",
|
|
15
|
+
"test:package": "node test/acceptance/package-smoke.mjs",
|
|
16
|
+
"demo": "node test/acceptance/package-smoke.mjs --demo"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@parcel/watcher": "2.5.6",
|
|
20
|
+
"picomatch": "2.3.2",
|
|
21
|
+
"yaml": "2.8.3"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=22"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "5.6.3"
|
|
28
|
+
},
|
|
29
|
+
"description": "Persistent verification state for developers and coding agents.",
|
|
30
|
+
"homepage": "https://github.com/msiric/redue",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/msiric/redue.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/msiric/redue/issues"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"bin/",
|
|
40
|
+
"src/",
|
|
41
|
+
"examples/",
|
|
42
|
+
"docs/user/",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE",
|
|
45
|
+
"CHANGELOG.md"
|
|
46
|
+
],
|
|
47
|
+
"license": "Apache-2.0"
|
|
48
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// The same fail-conservative cached reader serves the CLI and execution layer.
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {processAlive} from './process-liveness.mjs';
|
|
5
|
+
const unknown=(reason,checks)=>({schema:1,state:'unverified',current:0,stale:0,failed:0,observed_failed:0,
|
|
6
|
+
unverified:checks.length,
|
|
7
|
+
checks:checks.map(c=>({name:c.name,result:null,freshness:'UNVERIFIED',reason,
|
|
8
|
+
invocation:null,changed_inputs:[],reuse_eligible:false})),
|
|
9
|
+
observation:{healthy:false,reason}});
|
|
10
|
+
export function unavailableCached(state,reason,checks=[]) {
|
|
11
|
+
try {const value=JSON.parse(fs.readFileSync(path.join(state,'status.json')));
|
|
12
|
+
const checks=(value.checks||[]).map(row=>({...row,freshness:'UNVERIFIED',
|
|
13
|
+
reason,reuse_eligible:false,declared_inputs_match:null}));
|
|
14
|
+
return {...value,state:'unverified',current:0,stale:0,failed:0,
|
|
15
|
+
unverified:Math.max(1,checks.length),checks,
|
|
16
|
+
observation:{...value.observation,healthy:false,reason}};
|
|
17
|
+
}catch{return unknown(reason,checks);}
|
|
18
|
+
}
|
|
19
|
+
export function readCachedStatus(state,checks=[]) {
|
|
20
|
+
try{const value=JSON.parse(fs.readFileSync(path.join(state,'status.json')));
|
|
21
|
+
if(Date.now()>=value.updated_at&&Date.now()<=value.expires_at&&
|
|
22
|
+
value.expires_at-value.updated_at<=3000){
|
|
23
|
+
if(processAlive(value.pid))return value;
|
|
24
|
+
return unavailableCached(state,'observer process unavailable',checks);}
|
|
25
|
+
}catch{}
|
|
26
|
+
return unavailableCached(state,'observer heartbeat expired or unavailable',checks);
|
|
27
|
+
}
|