@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.
Files changed (52) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +180 -0
  3. package/README.md +123 -2
  4. package/bin/redue.mjs +329 -0
  5. package/bin/vstate.mjs +3 -0
  6. package/docs/README.md +20 -0
  7. package/docs/user/agents.md +32 -0
  8. package/docs/user/configuration.md +57 -0
  9. package/docs/user/getting-started.md +127 -0
  10. package/docs/user/json.md +59 -0
  11. package/docs/user/shell.md +25 -0
  12. package/docs/user/supported-projects.md +89 -0
  13. package/examples/redue.config.json +8 -0
  14. package/package.json +46 -4
  15. package/src/cached-state.mjs +27 -0
  16. package/src/cli.mjs +390 -0
  17. package/src/control-endpoint.mjs +11 -0
  18. package/src/daemon.mjs +989 -0
  19. package/src/decision-profile.mjs +18 -0
  20. package/src/decision-validation.mjs +41 -0
  21. package/src/declared-plan.mjs +125 -0
  22. package/src/executable-lookup.mjs +18 -0
  23. package/src/glob.mjs +9 -0
  24. package/src/history-worker.mjs +18 -0
  25. package/src/index.mjs +306 -0
  26. package/src/installed-inputs.mjs +110 -0
  27. package/src/linux-inotify.py +228 -0
  28. package/src/linux-observer.mjs +79 -0
  29. package/src/node-onboarding.mjs +263 -0
  30. package/src/npm-typecheck-probe.mjs +120 -0
  31. package/src/observation.mjs +37 -0
  32. package/src/owned-state.mjs +32 -0
  33. package/src/path-identity.mjs +43 -0
  34. package/src/plan-worker.mjs +131 -0
  35. package/src/plan.mjs +10 -0
  36. package/src/platform-observation.mjs +17 -0
  37. package/src/platform-state.mjs +14 -0
  38. package/src/pnpm-inputs.mjs +355 -0
  39. package/src/pnpm-typecheck-probe.mjs +47 -0
  40. package/src/presentation.mjs +52 -0
  41. package/src/probe-result.mjs +21 -0
  42. package/src/process-liveness.mjs +11 -0
  43. package/src/run-lock.mjs +77 -0
  44. package/src/state-store.mjs +37 -0
  45. package/src/toolchain-probe.mjs +21 -0
  46. package/src/typescript-contract-probe.mjs +188 -0
  47. package/src/typescript-list.mjs +68 -0
  48. package/src/typescript-qualification.mjs +96 -0
  49. package/src/windows-command.mjs +16 -0
  50. package/src/windows-process.mjs +15 -0
  51. package/src/yarn-workspace-inputs.mjs +148 -0
  52. package/src/yarn-workspace-typecheck-probe.mjs +107 -0
package/bin/vstate.mjs ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ // Compatibility entry point for local pre-release workflows.
3
+ import './redue.mjs';
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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "schema": 1,
3
+ "checks": [{
4
+ "name": "migration",
5
+ "command": ["@node", "tools/check-migrations.mjs"],
6
+ "inputs": ["migrations/**", "tools/check-migrations.mjs"]
7
+ }]
8
+ }
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "@redue/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
+ }