leerness 1.36.185 → 1.36.187
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 +17 -0
- package/README.ko.md +5 -0
- package/README.md +14 -4
- package/bin/leerness.js +291 -57
- package/docs/e2e-observation-contract.md +51 -0
- package/docs/runtime-compatibility-api.md +183 -0
- package/docs/state-paths-api.md +92 -0
- package/docs/state-scopes.md +266 -0
- package/docs/worktree-runtime-migration.md +278 -0
- package/lib/claims-baseline.js +1 -1
- package/lib/file-leases.js +2 -2
- package/lib/git.js +64 -15
- package/lib/io.js +9 -3
- package/lib/migrate.js +1 -1
- package/lib/preview-serve.js +5 -1
- package/lib/pure-utils.js +20 -0
- package/lib/role-fallback.js +3 -3
- package/lib/role-store.js +2 -2
- package/lib/runtime-layout.js +395 -0
- package/lib/runtime-writes.js +166 -0
- package/lib/session-close.js +1 -1
- package/lib/state-git.js +138 -0
- package/lib/state-inspect.js +39 -0
- package/lib/state-inventory.js +69 -0
- package/lib/state-paths.js +59 -0
- package/lib/workspace-dir.js +34 -10
- package/package.json +10 -6
- package/scripts/command-flags-probe.js +1 -1
- package/scripts/dead-flags-probe.js +1 -1
- package/scripts/e2e-child-diagnostics-probe.js +143 -0
- package/scripts/e2e-child-diagnostics.js +33 -0
- package/scripts/e2e-temp-scope-probe.js +127 -0
- package/scripts/e2e.js +108 -27
- package/scripts/encoding-selftest-probe.js +222 -0
- package/scripts/false-claim-probe.js +34 -3
- package/scripts/file-lease-probe.js +5 -2
- package/scripts/legacy-runtime-negative-probe.js +72 -0
- package/scripts/mutation-integrity-probe.js +3 -0
- package/scripts/role-fallback-probe.js +67 -6
- package/scripts/runtime-admission-probe.js +282 -0
- package/scripts/runtime-git-write-probe.js +116 -0
- package/scripts/runtime-layout-probe.js +1198 -0
- package/scripts/runtime-repl-probe.js +271 -0
- package/scripts/runtime-replacement-probe.js +190 -0
- package/scripts/runtime-write-probe.js +458 -0
- package/scripts/selftest-cleanup-probe.js +168 -0
- package/scripts/state-inspect-cli-probe.js +209 -0
- package/scripts/state-scopes-probe.js +590 -0
- package/scripts/workspace-dir-lock-order-probe.js +310 -35
- package/scripts/workspace-dir-migration-probe.js +17 -2
- package/scripts/workspace-selection-probe.js +230 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# E2E observation contract
|
|
2
|
+
|
|
3
|
+
T-0182 and T-0183 correct test observation, not production runtime admission.
|
|
4
|
+
The original full E2E assertions and supported OS/Node matrix remain required.
|
|
5
|
+
|
|
6
|
+
## Diagnostic helper
|
|
7
|
+
|
|
8
|
+
- childDiagnostics(result, elapsedMs, timeoutMs, parsedReport): summarize an actual child result without executing, retrying, mutating or accepting it.
|
|
9
|
+
|
|
10
|
+
## Fields
|
|
11
|
+
|
|
12
|
+
- status: the native exit status; null remains null.
|
|
13
|
+
- signal: the native termination signal or null.
|
|
14
|
+
- errorCode: the native spawn error code, bounded to80 characters, or null.
|
|
15
|
+
- errno: the native numeric errno or a bounded string, or null.
|
|
16
|
+
- errorMessage: at most160 characters, or null.
|
|
17
|
+
- elapsedMs: nonnegative monotonic duration captured immediately after the child returns.
|
|
18
|
+
- timeoutMs: the actual child deadline.
|
|
19
|
+
- stdoutBytes: captured byte count; null means the stream was not captured.
|
|
20
|
+
- stderrBytes: captured byte count; null means the stream was not captured.
|
|
21
|
+
- stdoutTail: at most256 characters, or null for an uncaptured stream.
|
|
22
|
+
- stderrTail: at most256 characters, or null for an uncaptured stream.
|
|
23
|
+
- version: at most64 characters from a parsed doctor report, or null.
|
|
24
|
+
- mcpTools: the parsed finite numeric count, or null.
|
|
25
|
+
- healthy: the parsed boolean, or null.
|
|
26
|
+
- selftest: bounded pass/total/ok/failure count and at most five failure names of120 characters each, or null.
|
|
27
|
+
|
|
28
|
+
## Preserved behavior
|
|
29
|
+
|
|
30
|
+
The fresh-migration handoff, doctor/commands and JSON121 blocks retain their
|
|
31
|
+
actual child invocation, fixture environment, success predicates and runtime
|
|
32
|
+
warning gate. Diagnostics are printed only on failure, including the setup
|
|
33
|
+
migrate/init result. An uncaptured stream is not described as empty output.
|
|
34
|
+
|
|
35
|
+
Only JSON121's doctor deadline changes:990000ms covers its nested900000ms
|
|
36
|
+
selftest deadline plus90000ms for environment probes and startup/teardown.
|
|
37
|
+
The other14 queries retain180000ms, init300000ms, the separate doc/surface
|
|
38
|
+
doctor300000ms, commands15000ms and fresh handoff/migrate15000/60000ms.
|
|
39
|
+
This is deadline consistency, not a measured speed improvement or a claim that
|
|
40
|
+
the historical CI handoff/doc-surface failures were caused by timeouts.
|
|
41
|
+
|
|
42
|
+
The134 leftover counter reads the same `sb` used for child TMPDIR/TEMP/TMP.
|
|
43
|
+
A foreign parent marker must not affect it; a real child-sb marker must fail.
|
|
44
|
+
Observation preserves fixture bytes/mtime and never deletes unrelated files.
|
|
45
|
+
|
|
46
|
+
## Verification limits
|
|
47
|
+
|
|
48
|
+
The small probes execute the original assertion blocks with controlled fixtures
|
|
49
|
+
and actual short-lived child failure results. They prove observation behavior,
|
|
50
|
+
not a full product run. Separate real original-block executions and final
|
|
51
|
+
same-SHA CI are required. Static function/field matching is not semantic proof.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Runtime compatibility, before migration
|
|
2
|
+
|
|
3
|
+
P-0021 / T-0180 implements compatibility checking only. Legacy data stays in place.
|
|
4
|
+
No command creates a descriptor, moves data, activates a runtime or finalizes a run.
|
|
5
|
+
|
|
6
|
+
## Read-only diagnosis
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
leerness state compatibility . --json
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Accepts one optional project path or `--path`; the explicit flag takes precedence.
|
|
13
|
+
Unknown/duplicate flags, blank paths and extra operands fail before bookkeeping.
|
|
14
|
+
Exit 0 means the observed legacy layout is compatible; exit 1 means blocked.
|
|
15
|
+
`state inspect` remains a separate metadata-only path/inventory operation.
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"schema": "leerness.runtime-compatibility/v1",
|
|
20
|
+
"schemaVersion": 1,
|
|
21
|
+
"ok": true,
|
|
22
|
+
"compatible": true,
|
|
23
|
+
"writeDisposition": "allowed",
|
|
24
|
+
"reasonCode": "legacy_absent",
|
|
25
|
+
"scope": "worktree",
|
|
26
|
+
"observedLayout": "legacy",
|
|
27
|
+
"supportedWriterProtocol": 1,
|
|
28
|
+
"activationSupported": false,
|
|
29
|
+
"workspaceAdmission": "operation-start"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The report contains bounded reason codes, not descriptor text, raw Git output, private
|
|
34
|
+
conversations or inferred migration success. It creates no cache, lock or presence record.
|
|
35
|
+
|
|
36
|
+
## Reader exports
|
|
37
|
+
|
|
38
|
+
- createRuntimeCompatibilityReader(root): capture topology/admission and return a fresh observation function.
|
|
39
|
+
- inspectRuntimeCompatibility(root): new admission and one read-only report.
|
|
40
|
+
- assertRuntimeWriteAllowed(root): join writer admission, then return an allowed report or throw a bounded compatibility error.
|
|
41
|
+
|
|
42
|
+
## Fields
|
|
43
|
+
|
|
44
|
+
- schema: `leerness.runtime-compatibility/v1`.
|
|
45
|
+
- schemaVersion: 1.
|
|
46
|
+
- ok: the observation is compatible.
|
|
47
|
+
- compatible: the legacy writer is admitted by this observation.
|
|
48
|
+
- writeDisposition: `allowed` or `blocked`.
|
|
49
|
+
- reasonCode: bounded stable reason, never descriptor contents.
|
|
50
|
+
- scope: `worktree`, `project-local`, or `unknown` when authority cannot be established.
|
|
51
|
+
- observedLayout: `legacy`, `unsupported`, or `unknown`.
|
|
52
|
+
- supportedWriterProtocol: 1.
|
|
53
|
+
- activationSupported: false.
|
|
54
|
+
- workspaceAdmission: `operation-start`.
|
|
55
|
+
|
|
56
|
+
## Fixed authority and strict input
|
|
57
|
+
|
|
58
|
+
- Git: `<GIT_DIR>/leerness/layout.json`, fixed for the whole worktree, outside projectKey.
|
|
59
|
+
- Non-Git: `<projectRoot>/.leerness/cache/state-layout.json`, independent of workspace selection.
|
|
60
|
+
- Only the six fields described in [the migration contract](worktree-runtime-migration.md)
|
|
61
|
+
are accepted. Maximum 16 KiB; strict UTF-8, no BOM, duplicate/unknown keys, hard links,
|
|
62
|
+
unsafe parent links, special files or changed-during-read input.
|
|
63
|
+
- New Git `leerness/projects` (even empty), alternate legacy-workspace layout indicators,
|
|
64
|
+
non-Git state-runtime, or unresolved introduction of Git block legacy writes.
|
|
65
|
+
- Missing Git is acceptable only for positively identified non-repositories. Broken Git,
|
|
66
|
+
discovery overrides, ambiguous ownership and topology changes fail closed.
|
|
67
|
+
|
|
68
|
+
## Writer operation boundary
|
|
69
|
+
|
|
70
|
+
`createRuntimeCompatibilityReader(root)` resolves one immutable Git topology snapshot.
|
|
71
|
+
It admits workspace ownership/selection once at operation start. It rechecks directory
|
|
72
|
+
types/links, topology identity, descriptor bytes and fixed runtime indicators on later reads.
|
|
73
|
+
It does not recursively scan runtime records or reclassify an operation's own transient files.
|
|
74
|
+
This distinction preserves existing init and lock-owned legacy workspace migration.
|
|
75
|
+
New public inspections and later writer operations make a new workspace admission.
|
|
76
|
+
New writer operations may read-only wait for an existing regular, single-linked legacy
|
|
77
|
+
workspace migration lock before classifying ownership. They reclassify after the peer
|
|
78
|
+
finishes; waiting never grants lock ownership or permission to overwrite a conflict.
|
|
79
|
+
The existing migration wait budget defaults to 10 seconds, is configurable through
|
|
80
|
+
`LEERNESS_WORKSPACE_MIGRATION_LOCK_WAIT_MS`, and is clamped to 0–60 seconds. Expired or
|
|
81
|
+
non-regular/linked lock observations block with `workspace_dir_migration_locked`; no
|
|
82
|
+
lock is read, reclaimed or deleted by admission. The budget bounds contention waiting,
|
|
83
|
+
not unrelated Git/filesystem I/O. Public `state compatibility` remains immediate.
|
|
84
|
+
An observed non-workspace denial is terminal even if a peer subsequently removes its
|
|
85
|
+
descriptor. A conflict snapshot gets at most one extra classification when no lock is
|
|
86
|
+
seen, covering a peer that completed between observations without accepting persistent
|
|
87
|
+
dual-live state.
|
|
88
|
+
|
|
89
|
+
Canonical project identities share one admitted reader across 8.3, namespaced and
|
|
90
|
+
junction aliases. Each target is resolved again, so retargeting an alias does not retain
|
|
91
|
+
stale authority. Nested operations on another project receive independent admission;
|
|
92
|
+
an operation never waits for its own migration lock through an equivalent path.
|
|
93
|
+
Standalone stores may coexist with their producers' exact lock/release, temporary,
|
|
94
|
+
corruption-backup and first-install names. Unknown names, links and incorrect entry
|
|
95
|
+
kinds remain refused; the reader does not open store or recovery contents. This
|
|
96
|
+
preserves concurrent role/provenance writers without accepting an arbitrary folder.
|
|
97
|
+
Existing standalone output directories are recognized by exact name and regular
|
|
98
|
+
directory kind, so a producer's first successful write does not block its next operation:
|
|
99
|
+
|
|
100
|
+
| Exact top-level directory | Existing producer |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `previews` | Preview commands and direct store-free builder |
|
|
103
|
+
| `api-skills` | API document/skeleton storage |
|
|
104
|
+
| `skills` | Local skill learn/install |
|
|
105
|
+
| `personas` | Custom persona templates |
|
|
106
|
+
| `skills-export` | Local skill export/export-all |
|
|
107
|
+
| `reviews` | Review prompt `--emit md` directory |
|
|
108
|
+
| `incidents` | Incident JSON storage |
|
|
109
|
+
| `skills-publish`, `skills-publish-tarball` | Existing local publication staging |
|
|
110
|
+
|
|
111
|
+
Admission neither enumerates nor reads their contents, and does not certify domain
|
|
112
|
+
records, authorize publication, or bypass a producer's own checks. Linked directories,
|
|
113
|
+
wrong entry kinds, lookalike names and foreign siblings remain refused. The existing
|
|
114
|
+
E2E API collision/corruption/JSON contract is preserved without requiring `init`.
|
|
115
|
+
|
|
116
|
+
The same exact-name rule covers existing standalone files below, including their
|
|
117
|
+
already-defined lock/temporary/recovery shapes. Metadata recognition is not a claim
|
|
118
|
+
that each command can execute without its own prerequisites or user authorization.
|
|
119
|
+
|
|
120
|
+
| Exact top-level files | Existing producer |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `user-requests.json` | Request recording |
|
|
123
|
+
| `shell-failures.json` | Shell analysis `--record` (not command execution) |
|
|
124
|
+
| `platform-constraints.json` | Custom platform constraints |
|
|
125
|
+
| `wakeup-history.json` | Local wakeup history/interval settings |
|
|
126
|
+
| `agent-slash-commands.json` | Slash-command snapshot recording |
|
|
127
|
+
| `environment.json` | Environment detection writeback |
|
|
128
|
+
| `agent-permissions.json`, `credentials.local.json` | Explicit local settings/credential registration |
|
|
129
|
+
| `llm-bench-history.md` | Manual benchmark recording |
|
|
130
|
+
| `glossary.md`, `glossary.json` | Glossary build |
|
|
131
|
+
| `reuse-map.md`, `design-system.md` | Reuse registration/design-guide merge |
|
|
132
|
+
| `skill-suggestions.md`, `skill-auto-cache.json` | Skill suggestions/official catalog cache |
|
|
133
|
+
| `provider-probe-cache.json`, `orchestrate-log.md` | Provider-probe cache/explicit orchestration log |
|
|
134
|
+
| `feature-graph.md` | Feature graph, with the existing project/explicit-force gate |
|
|
135
|
+
| `enforce.json` | Hook installation, still requiring Git and its installation checks |
|
|
136
|
+
| `agent-reminders.md` | Explicit stale-handoff writeback |
|
|
137
|
+
|
|
138
|
+
No cache refresh, provider call, server, credential operation, scheduling or publication
|
|
139
|
+
is performed by compatibility inspection. This is a bounded legacy-producer inventory,
|
|
140
|
+
not a new migration manifest or a guarantee about unregistered external writers.
|
|
141
|
+
|
|
142
|
+
`withRuntimeWrites(root, callback)` provides an operation-local synchronous/async failure
|
|
143
|
+
latch. CLI admission precedes automatic workspace migration and bookkeeping and uses the
|
|
144
|
+
handler's actual target/precedence. MCP telemetry, long-lived REPL turns, known direct
|
|
145
|
+
module writers, I/O paths, retained descriptors and lock heartbeat use the same reader.
|
|
146
|
+
Synchronous filesystem interception is active only inside writer operations; importing
|
|
147
|
+
the module alone does not modify the host's filesystem methods. Windows subprocess-based
|
|
148
|
+
replacement and mutating Git commands have explicit pre-attempt checks.
|
|
149
|
+
|
|
150
|
+
CLI startup rejection uses `runtime_layout_incompatible`; direct writer rejection uses
|
|
151
|
+
`E_RUNTIME_LAYOUT_INCOMPATIBLE` with `reasonCode`. Unsafe descriptor parents or ambiguous
|
|
152
|
+
standalone ownership are rejected before domain-specific validation. Direct read-only
|
|
153
|
+
store APIs retain their own specific diagnostics. Existing workspace selection errors
|
|
154
|
+
(such as conflicting live workspaces) retain their established CLI error contract.
|
|
155
|
+
|
|
156
|
+
`pathWriter` recognizes metadata paths; callers writing arbitrary project files must carry
|
|
157
|
+
their project operation explicitly. Raw external editors, subprocesses, old installed hooks,
|
|
158
|
+
other clones and unsupported external writers are not fenced by this API. A caught guard
|
|
159
|
+
error must not become successful completion. Already prepared recovery material is retained
|
|
160
|
+
if later incompatibility prevents cleanup; do not automatically delete it or assume rollback.
|
|
161
|
+
|
|
162
|
+
Topology is reused to avoid repeated Git processes; compatibility itself is never a stale
|
|
163
|
+
cache. A 50-read fixture used one Git query and one workspace enumeration after admission,
|
|
164
|
+
versus 50 enumerations in the first implementation. This is an I/O count, not a throughput benchmark.
|
|
165
|
+
|
|
166
|
+
## Limits and verification
|
|
167
|
+
|
|
168
|
+
An external change between the final check and actual write is still possible. Generation
|
|
169
|
+
is not a fencing token. Do not activate a future layout under A-only clients. Real v1.36.186
|
|
170
|
+
CLI and already-loaded writer controls demonstrate that older clients ignore the descriptor.
|
|
171
|
+
Phase B requires separate approval, stopped/upgraded participants, a writer admission
|
|
172
|
+
protocol and verified recovery/retention. None is supplied by an `allowed` report.
|
|
173
|
+
|
|
174
|
+
`npm run test:runtime-compatibility` runs reader, bounded admission/alias/denial controls,
|
|
175
|
+
real CLI/MCP/module/lock/FD, Git transport,
|
|
176
|
+
Windows replacement and encoding-diagnostic probes. Windows-only controls are not implied
|
|
177
|
+
by POSIX results. Release-only old-client controls require an existing installation:
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
node scripts/legacy-runtime-negative-probe.js /path/to/installed/leerness-1.36.186
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The probe does not install a package and checks the old installation's source remains unchanged.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# State inspection API v1
|
|
2
|
+
|
|
3
|
+
Available in v1.36.186. T-0174 / P-0020 is an additive inspection-only foundation.
|
|
4
|
+
It does not move data or activate a new backend. The complete staged design is in
|
|
5
|
+
[State scopes and migration](state-scopes.md).
|
|
6
|
+
|
|
7
|
+
## CLI
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
leerness state inspect
|
|
11
|
+
leerness state inspect ./project --json
|
|
12
|
+
leerness state inspect --path ./project --language en
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The target must be an existing directory. `--path` wins over the optional positional
|
|
16
|
+
target; otherwise the target is the current directory. Blank paths, extra positionals,
|
|
17
|
+
duplicate `--path`, unknown options and unsupported write flags fail before discovery.
|
|
18
|
+
Text defaults to Korean; `--language` or `LEERNESS_LANG` chooses English/Korean without
|
|
19
|
+
reading a project manifest. JSON is one document, with `ok: true` on success, or the
|
|
20
|
+
standard `ok: false` / `code` / `error` envelope and exit 1 on failure.
|
|
21
|
+
|
|
22
|
+
## Module export
|
|
23
|
+
|
|
24
|
+
- `resolveStatePaths(root, options)` from `lib/state-paths.js`: read-only resolution;
|
|
25
|
+
default root is cwd. `options.env` supplies the child Git environment and workspace
|
|
26
|
+
override; `options.envValue` overrides workspace selection. Neither is persisted.
|
|
27
|
+
|
|
28
|
+
`inspectState(root, options)` from `lib/state-inspect.js` adds `ok` and the fixed-list
|
|
29
|
+
inventory; `formatStateInspection(report, language)` renders the already resolved
|
|
30
|
+
snapshot without more I/O. The resolver does not initialize the CLI or discover skills.
|
|
31
|
+
|
|
32
|
+
## Fields
|
|
33
|
+
|
|
34
|
+
- schemaVersion: 1.
|
|
35
|
+
- schema: `leerness.state-paths/v1` (inspection: `leerness.state-inspection/v1`).
|
|
36
|
+
- activeLayout: `legacy`; existing writers remain authoritative.
|
|
37
|
+
- runtimeActivated: false.
|
|
38
|
+
- migrationAvailable: false.
|
|
39
|
+
- projectRoot: canonical absolute directory of the requested project, not necessarily the Git root.
|
|
40
|
+
- projectKey: `project-` plus SHA-256 of the canonical repository-relative project path.
|
|
41
|
+
- projectRelativePath: forward-slash relative path, or `.` for a repository root/non-Git project.
|
|
42
|
+
- git: absolute worktreeRoot/gitDir/gitCommonDir and linkedWorktree, or null for genuine non-Git.
|
|
43
|
+
- workspace: selected name/path, canonical path, detectedPaths, legacy presence and recognition status.
|
|
44
|
+
- scopes: exactly project, worktree, commonControl, immutableRecord and generatedView.
|
|
45
|
+
- warnings: explicit non-Git, unrecognized/foreign and legacy-workspace observations.
|
|
46
|
+
|
|
47
|
+
All `proposedPath` / `proposedPaths` values are future addresses, **not created, activated,
|
|
48
|
+
validated as writable, or authorization to write**. Project scope separately reports
|
|
49
|
+
`currentPath`. Inventory rows report the actual legacy path, classification, proposed
|
|
50
|
+
semantic scope, migrationAvailable=false and lstat metadata (including links/errors).
|
|
51
|
+
They are not a move plan. Mixed task/context/queue documents must be split by field;
|
|
52
|
+
human intent is not disposable generated state.
|
|
53
|
+
|
|
54
|
+
Inventory covers the selected path plus any other existing canonical/legacy workspace,
|
|
55
|
+
with workspacePath and selectedWorkspace on each row. A legacy reader selection must not
|
|
56
|
+
hide canonical runtime, nor may a canonical selection hide residual legacy evidence.
|
|
57
|
+
Text output prefixes rows with the workspace directory name; contents are never merged.
|
|
58
|
+
|
|
59
|
+
Project identity is independent of branch name and session. Matching repository-relative
|
|
60
|
+
projects in linked worktrees share a common-control proposal, but never private runtime.
|
|
61
|
+
Siblings differ. Separate clones/hosts do not share live control. Non-Git proposals use
|
|
62
|
+
project-local `cache/state-runtime`, with commonControl unavailable, not an invented shared store.
|
|
63
|
+
These keys are namespaces, not credentials. Moving a project inside a repo changes its key.
|
|
64
|
+
|
|
65
|
+
## Failures and limits
|
|
66
|
+
|
|
67
|
+
Path errors distinguish invalid/not-found/not-directory/unreadable targets. Git errors
|
|
68
|
+
distinguish missing, unsupported, bare, metadata-directory, timeout, output-limit,
|
|
69
|
+
unreadable, ambiguous output and repository discovery failure. Filesystem
|
|
70
|
+
errors in Git-returned paths or the discovery marker walk remain Git-specific;
|
|
71
|
+
they never misreport an existing inspection target as missing. Existing workspace
|
|
72
|
+
conflict/override/link errors retain their codes; strict inspection adds workspace_unreadable.
|
|
73
|
+
Git failure never silently falls back to a different backend. Existing discovery ceilings
|
|
74
|
+
are respected; nonexistent ceilings are ignored as Git does. Git location/config injection
|
|
75
|
+
overrides are sanitized through the existing gateway, not through a duplicate subprocess wrapper.
|
|
76
|
+
|
|
77
|
+
One Git topology query has a 5-second process timeout and 64-KiB output cap (Windows executable
|
|
78
|
+
discovery is a separate bounded gateway step). Git must support `--path-format=absolute`.
|
|
79
|
+
Workspace discovery reads immediate directory names; inventory uses a fixed set of leaves
|
|
80
|
+
and cached parent metadata without contents or recursive traversal. Links are not followed
|
|
81
|
+
for inventory. This is an observational, non-transactional filesystem snapshot; it is not
|
|
82
|
+
record validation, tracking detection, filesystem locking or a migration-integrity certificate.
|
|
83
|
+
|
|
84
|
+
## Verification
|
|
85
|
+
|
|
86
|
+
`npm run test:state-scopes` runs selector equivalence, topology/metadata and real CLI tests.
|
|
87
|
+
The CLI test instruments normal execution without internal/no-migration/no-stale bypasses:
|
|
88
|
+
one Git query, no npm/provider command, no project content read, no write; it also compares
|
|
89
|
+
all fixture/cwd/Git file bytes and mtimes. Windows may perform trusted Git location and
|
|
90
|
+
console encoding operations. No new runtime dependency, persistent config or MCP tool is added.
|
|
91
|
+
Invalid option diagnostics are instrumented too: neither target nor unrelated cwd
|
|
92
|
+
manifest contents are read merely to choose an error language.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# State scopes and migration design
|
|
2
|
+
|
|
3
|
+
Status: scope inspection implemented; runtime architecture remains proposed (2026-09-05).
|
|
4
|
+
Request: UR-0097; implementation/optimization approval: UR-0098. Audit: T-0173.
|
|
5
|
+
First implementation: T-0174 / approved P-0020. See [the inspection API](state-paths-api.md).
|
|
6
|
+
|
|
7
|
+
**Path inspection and an approved compatibility-only write boundary are implemented; stores and migration below remain designs.**
|
|
8
|
+
The first implementation covers path resolution and read-only inspection. P-0021 adds
|
|
9
|
+
`state compatibility` and observed-layout rejection; see [its API](runtime-compatibility-api.md).
|
|
10
|
+
Existing data locations and task IDs stay unchanged. No migration or activation is available.
|
|
11
|
+
|
|
12
|
+
## 1. Evidence from the current implementation
|
|
13
|
+
|
|
14
|
+
Audited baseline: v1.36.185, commit `c84ab03b5b5d385985ee2797a95c02c7d4004be4`.
|
|
15
|
+
|
|
16
|
+
| Surface | Existing source / storage | Structural consequence |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Project directory | `lib/workspace-dir.js` resolves `.leerness` and migrates `.harness` | The baseline had no scope resolver. T-0174 adds one without replacing this migration; a pure selector reuses the existing inspection snapshot. |
|
|
19
|
+
| Session presence | `lib/session-presence.js` predicates and `bin/leerness.js` I/O use `.leerness/cache/sessions/` | Sessions have addresses and ignored runtime files already, but different worktrees cannot see each other's presence through this store. |
|
|
20
|
+
| Handoff freshness | `bin/leerness.js`: `.leerness/cache/handoffs/` | Session-bound freshness markers are consumed by handoff/enforcement; migrate those consumers together. |
|
|
21
|
+
| REPL conversation sessions | `bin/leerness.js`: `.leerness/cache/agent-sessions/<sessionId>.jsonl` | This is a separate local conversation surface, not presence. Do not promote raw conversations into public audit records. |
|
|
22
|
+
| Source-file lease | `lib/file-leases.js`: `.leerness/cache/file-leases.json` | Exact-file TTL coordination is local to a checkout; it is not a repository-wide task claim. |
|
|
23
|
+
| State substrate | `bin/leerness.js`: `.leerness/state.json`, `runs/run-N.json`, `handoff/` | Session ownership fixes same-checkout cross-talk, but counters and mutable run files remain local branch files rather than globally unique completion records. |
|
|
24
|
+
| Decisions and lessons | `_saveDecisions` / `_saveLessons`: JSON arrays plus Markdown projections | Valid JSON arrays take precedence. Current readers silently fall back to Markdown for invalid JSON/non-arrays; migration must not. Both the array and its projection are rewritten, so independent records still change the same tracked files on separate branches. |
|
|
25
|
+
| Task progress | `readProgressRows` / `writeProgressRows`: `.leerness/progress-tracker.md` | The table is currently authoritative, not an event-derived view. Reclassifying it without migrating all readers and writers would lose task updates. |
|
|
26
|
+
| Session close | `lib/session-close.js` reads task rows, writes handoff, updates auto-marked current-state lines, invokes further bookkeeping | File locks serialize local writes, not Git merges or a whole multi-file snapshot. The first in-progress task selects the recommendation, which need not be the current session's task. |
|
|
27
|
+
| Execution provenance | `lib/role-fallback.js`: `.leerness/execution-ledger.jsonl` | Revision-bound role/fallback evidence exists, but this checkout ignores the ledger. It is not a durable Git audit record. |
|
|
28
|
+
| Runtime-like tracked files | `git ls-files` includes `active-wakeups.json`, `auto-resume-plan.json`, `next-action-queue.json`, `pre-wake-report.json`, `last-handoff.json`, `routing-log.json` | Ignoring `cache/` alone does not remove mutable operational state from merge inputs. Classification must be per surface, not extension-based. |
|
|
29
|
+
| Integrity checks | `lib/state-integrity.js` inspects only immediate `.leerness/*.json` parseability | Moving to nested stores needs explicit schema/record coverage; a green legacy scan cannot attest to new scopes. |
|
|
30
|
+
|
|
31
|
+
Some fields mix intent with execution: a queued next action or resume plan may contain
|
|
32
|
+
user-authored instructions. Preserve those as project/task inputs, and move only execution
|
|
33
|
+
status/cursors to runtime. Never classify an entire mixed file as disposable cache.
|
|
34
|
+
|
|
35
|
+
## 2. Three storage layers, five semantic scopes
|
|
36
|
+
|
|
37
|
+
The three physical layers are **versioned project data**, **worktree-private execution**,
|
|
38
|
+
and **repository-common coordination**. Immutable-Record and Generated-View are semantic
|
|
39
|
+
scopes within that topology, not two additional database servers.
|
|
40
|
+
|
|
41
|
+
| Scope | Proposed location | Authority and writer |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Project | `<project>/.leerness/` and optional `config/` | Versioned policy, role definitions, project identity, task specifications and human-authored context; explicit project mutations only. |
|
|
44
|
+
| Worktree | `<gitDir>/leerness/projects/<projectKey>/runtime/` | Per-session/per-run execution state. One owner per mutable session record; no branch name as identity. |
|
|
45
|
+
| Common-Control | `<gitCommonDir>/leerness/control/projects/<projectKey>/` | Claims, leases, dependencies, registered worktrees, fencing revisions and run status. All writes pass the same ControlStore transaction boundary. |
|
|
46
|
+
| Immutable-Record | `<project>/.leerness/memory/{decisions,lessons}/` and `.leerness/records/runs/<runId>/` | Individual durable knowledge/result/review records. Exclusive creation; corrected decisions link `supersedes`, never silently overwrite. |
|
|
47
|
+
| Generated-View | `.leerness/generated/` for canonical projections; private runtime `views/` for live session views | Deterministic output with input digests and schema/generator versions. Canonical summary is written only by the consolidator. Live view is local and ignored. |
|
|
48
|
+
|
|
49
|
+
The main worktree commonly has `gitDir === gitCommonDir`. Distinct `runtime/` and
|
|
50
|
+
`control/` namespaces are therefore mandatory even there. A session subdirectory is still
|
|
51
|
+
required: two agents can operate in one worktree.
|
|
52
|
+
|
|
53
|
+
The audited repository confirmed the linked checkout's Git directory ends in
|
|
54
|
+
`.git/worktrees/t0165-convergence`, while the main checkout and both common-directory
|
|
55
|
+
queries resolve to the main `.git`. This matches the [Git worktree documentation](https://git-scm.com/docs/git-worktree#_details).
|
|
56
|
+
Use Git's [absolute path queries](https://git-scm.com/docs/git-rev-parse#_options_for_files),
|
|
57
|
+
not string concatenation with `<project>/.git`, which can be a gitfile.
|
|
58
|
+
|
|
59
|
+
### Identity and unsupported environments
|
|
60
|
+
|
|
61
|
+
- Resolve topology through the existing `lib/git.js` environment-sanitizing, shell-free
|
|
62
|
+
gateway. Resolve the worktree root separately from the Leerness project root.
|
|
63
|
+
- Preserve existing workspace markers and foreign-directory detection. A directory with
|
|
64
|
+
only new `config/memory/records/generated` children is not automatically recognized by
|
|
65
|
+
today's workspace classifier; a versioned marker/compatibility update is required.
|
|
66
|
+
- P-0020 uses a deterministic project key derived from the canonical repository-relative
|
|
67
|
+
project path (`.` for the root); identical subprojects across linked worktrees match,
|
|
68
|
+
sibling monorepo projects do not. A future explicit project ID can preserve identity
|
|
69
|
+
across project moves. Neither ID is a credential or an authorization boundary.
|
|
70
|
+
- Resolve Windows case/alias/junction and symlink containment before writing. Reject
|
|
71
|
+
ambiguous mappings instead of silently sharing or relocating another project's state.
|
|
72
|
+
- Bare repositories, broken gitfiles, permission failures, unsupported Git and Git absence
|
|
73
|
+
must be distinguishable. Git errors do not silently select a different storage backend.
|
|
74
|
+
- True non-Git projects retain an explicitly labelled, ignored project-local runtime
|
|
75
|
+
fallback; they have no cross-worktree coordination guarantee. Inspection creates nothing.
|
|
76
|
+
- Submodules use their own Git topology. Separate clones and separate hosts do not share
|
|
77
|
+
`gitCommonDir`; remote coordination is out of scope. Network filesystems need a separate
|
|
78
|
+
locking guarantee before they are supported for common control.
|
|
79
|
+
|
|
80
|
+
## 3. Module boundaries and reuse
|
|
81
|
+
|
|
82
|
+
The inspection modules exist now. Store/facade/view names below remain planned contracts:
|
|
83
|
+
|
|
84
|
+
| Module | Responsibility | Existing component to reuse |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `lib/state-paths.js`, `lib/state-git.js` (implemented) | Five-scope map, canonical project namespace and read-only Git topology; no activation | `lib/git.js`, one `lib/workspace-dir.js` snapshot + pure selection without migration |
|
|
87
|
+
| `lib/state-inventory.js`, `lib/state-inspect.js` (implemented) | Fixed known-surface metadata inventory and CLI JSON/text projection; no recursive content scan | Existing workspace discovery; CLI exact early dispatch skips usage/migration/stale checks and unused skillpack/npm discovery |
|
|
88
|
+
| `lib/state-manager.js` | Narrow orchestration facade, schema dispatch, explicit migration status; no giant all-purpose store | Existing CLI/MCP adapters delegate to this facade incrementally |
|
|
89
|
+
| `lib/worktree-state.js` | Addressed sessions, runs, handoffs and resumable execution; explicit ownership | Session key and freshness contracts in `lib/session-presence.js`; existing run ownership rules |
|
|
90
|
+
| `lib/control-store.js` | Repository-scoped task claim, revision CAS and fencing; transaction ordering | Existing lock primitives after common-root/multi-process validation; no duplication of Git execution |
|
|
91
|
+
| `lib/memory-store.js` | Strict, bounded immutable record load/create; supersession/index projection | Existing decision/lesson parsers and renderers as legacy import adapters |
|
|
92
|
+
| `lib/run-record.js` | Validate execution/review envelopes, finalize and durable receipt | `lib/role-agent-schema.js`, `lib/role-store.js`, `lib/role-fallback.js` provenance contracts |
|
|
93
|
+
| `lib/state-views.js` | Pure deterministic rendering from an explicitly consistent snapshot | Existing Markdown renderers and dashboard serialization, preserving handwritten text |
|
|
94
|
+
|
|
95
|
+
Dependency direction: CLI/MCP → StateManager → domain stores / views → path, Git and I/O
|
|
96
|
+
primitives. Read-only topology inspection must not call initialization, workspace migration,
|
|
97
|
+
telemetry, presence registration, lease creation or providers. Avoid reusing a convenient
|
|
98
|
+
helper whose discovery path has write side effects.
|
|
99
|
+
|
|
100
|
+
Runtime dependencies remain zero, Node >=18. Start with bounded JSON records and existing
|
|
101
|
+
file-lock primitives, not a new YAML parser or SQLite package. `ControlStore` is a storage
|
|
102
|
+
interface; a database backend is a future evidence-driven option, not an MVP dependency.
|
|
103
|
+
|
|
104
|
+
## 4. Concurrency and conflict rules
|
|
105
|
+
|
|
106
|
+
1. A session owns its mutable runtime files; other sessions submit records/messages through
|
|
107
|
+
a store operation, never directly edit its progress or handoff.
|
|
108
|
+
2. Runtime is not a Git merge input. Moving files alone is insufficient: migrate ignore
|
|
109
|
+
rules, old writers, hooks, telemetry, integrity checks, packaging and cleanup too.
|
|
110
|
+
3. Persistent knowledge is record-oriented. Use built-in random UUIDs or an equivalently
|
|
111
|
+
collision-resistant scheme, not a branch-local maximum counter. Preserve legacy IDs as
|
|
112
|
+
qualified import metadata; never merge two unrelated `T-0174`/`run-0001` by label alone.
|
|
113
|
+
4. Same ID + same canonical payload is an idempotent replay. Same ID + different payload is
|
|
114
|
+
`record_id_conflict` and changes no records. Create atomically without overwrite.
|
|
115
|
+
5. Generated-file conflicts are resolved by regenerating from accepted inputs. Preserve
|
|
116
|
+
human-written sections as project context before deprecating old mixed documents.
|
|
117
|
+
6. Semantic decision disagreement creates a separate decision/review, not `merge=union`.
|
|
118
|
+
7. A single logical consolidator publishes canonical project summaries. A role label alone
|
|
119
|
+
is insufficient: validate owner, lease generation and expected revision at publication.
|
|
120
|
+
Expired writers cannot publish after a successor acquires ownership (fencing).
|
|
121
|
+
8. Physical source-file leases and repository task claims are distinct. Two worktrees can
|
|
122
|
+
edit their separate copies of the same path. Intentional duplicate task execution is
|
|
123
|
+
coordinated by a repository task key; source leases remain keyed by physical identity.
|
|
124
|
+
9. Common control transactions cannot rely on a thread holding a lock elsewhere. Define
|
|
125
|
+
lock ordering, bounded critical sections, stale-owner recovery and byte/row limits;
|
|
126
|
+
verify concurrent acquisition and crash recovery with real processes.
|
|
127
|
+
Existing lock ownership must not be stolen solely because a PID looks absent or a TTL
|
|
128
|
+
expires. A new task-claim lease and a local write mutex have different recovery contracts.
|
|
129
|
+
10. Visibility is not authority: provider observations can be unknown or stale. A role or
|
|
130
|
+
policy revision change requires revalidation; cross-worktree policy divergence cannot
|
|
131
|
+
be resolved by taking whichever branch updated control most recently.
|
|
132
|
+
|
|
133
|
+
Presence currently records handoff/close observations, not a heartbeat protocol or proof
|
|
134
|
+
that a process is alive. Common control must distinguish observed presence, a held lease,
|
|
135
|
+
an expired heartbeat and unknown availability. Retain existing session identity validation.
|
|
136
|
+
|
|
137
|
+
## 5. Run/review provenance and finalize
|
|
138
|
+
|
|
139
|
+
Each run has separate implementer, reviewer and terminal result records. Fields include:
|
|
140
|
+
schema version, globally unique run/task/agent identity, role, requested and actual
|
|
141
|
+
provider/model, observed identity source, resolution/fallback chain and reasons,
|
|
142
|
+
role/routing/availability revisions, branch/base/source commit, changed-file or diff digest,
|
|
143
|
+
commands with exit results, tests/evidence references, issues, timestamps, and next role.
|
|
144
|
+
Unknown model identity is explicitly unknown; never claim a specific model because it was
|
|
145
|
+
requested. Existing strict high-risk review-independence policy remains intact.
|
|
146
|
+
|
|
147
|
+
A review binds to the exact reviewed source commit (or explicitly identified uncommitted
|
|
148
|
+
diff digest). Approval of one commit does not approve a later commit or a conflict-resolved
|
|
149
|
+
merge. Dirty work is not represented as clean `HEAD` evidence. Record source commit and
|
|
150
|
+
publication commit separately to avoid a self-referential commit hash inside its own record.
|
|
151
|
+
|
|
152
|
+
Proposed lifecycle:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
running → execution-terminal → review/gate evaluated → finalize-prepared
|
|
156
|
+
→ immutable records durable → integrated/accepted → cleanup-eligible
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`failed`, `blocked` and `rejected` are valid terminal records; persisting them is not a
|
|
160
|
+
successful task-completion claim. A record on an unmerged branch is provisional evidence,
|
|
161
|
+
not canonical accepted project state. Consolidation uses accepted records from the selected
|
|
162
|
+
integration revision plus an explicit control snapshot, not arbitrary branch-local files.
|
|
163
|
+
|
|
164
|
+
Proposed `finalize` must be bounded, idempotent and crash-recoverable: validate owner/revision,
|
|
165
|
+
freeze input digests, persist records, verify them by reading back, then update the control
|
|
166
|
+
receipt. A missing/different record or changed source revision prevents cleanup. Do not mark
|
|
167
|
+
finalized before the durable writes succeed. Recovery uses the journal/receipt to complete
|
|
168
|
+
or reject a partial attempt without recreating a different result under the same ID.
|
|
169
|
+
|
|
170
|
+
**A file written in a worktree is not yet safe against worktree removal.** Cleanup eligibility
|
|
171
|
+
requires records/evidence referenced by an accepted retained Git revision (or an explicitly
|
|
172
|
+
configured durable store); merely staged/untracked records are insufficient. Local ignored
|
|
173
|
+
logs must be promoted or have their missing evidence represented before that receipt.
|
|
174
|
+
|
|
175
|
+
Leerness can enforce finalize on its own adapter cleanup path, not intercept arbitrary
|
|
176
|
+
external `git worktree remove --force`, manual deletion or `git prune`. There is no promise
|
|
177
|
+
of an unbypassable Git removal hook. Worktree locks may reduce accidental pruning but are
|
|
178
|
+
not a substitute for finalization and user-authorized cleanup. Never delete a worktree or
|
|
179
|
+
its metadata as a side effect of inspect, handoff or migration.
|
|
180
|
+
|
|
181
|
+
## 6. Staged delivery and migration order
|
|
182
|
+
|
|
183
|
+
| Stage | Tracking | Deliverable / gate |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| Audit and design | T-0173 | Actual state map, reuse inventory, structural risks, compatibility order and preview; no runtime activation. |
|
|
186
|
+
| Scope foundation | M-0014 / T-0174 / P-0020 | Resolver and `state inspect` read-only CLI contract; current/proposed locations distinguished; no stores moved and no new execution adapter. |
|
|
187
|
+
| Private runtime | M-0015 / T-0175 | Compatibility-only guard first (P-0021 proposed / T-0180), then separately approved migration of coupled runtime units; ownership and interrupted recovery. See [source-backed migration design](worktree-runtime-migration.md). |
|
|
188
|
+
| Common control | M-0016 / T-0176 | Task identity, claims, owner generations, version/revision compatibility and bounded ControlStore transactions. |
|
|
189
|
+
| Durable records | M-0017 / T-0177 | Append-only memory import, run/review records and finalize durability receipts; old evidence retained. |
|
|
190
|
+
| Views and adapters | M-0018 / T-0178 | Accepted-input snapshot, single-writer summaries, integrity/claims/CLI/MCP/cleanup integration; legacy window closed only with evidence. |
|
|
191
|
+
|
|
192
|
+
M-0010's existing v2 validators stay usable and legacy runtime writes stay authoritative.
|
|
193
|
+
Finalize its storage/migration design against M-0014 before implementing another independent
|
|
194
|
+
path migration. Runtime activation must also satisfy M-0015 compatibility and M-0016 control
|
|
195
|
+
contracts. M-0011 dispatch, M-0012 live visualization and M-0013 UI consume the same State API.
|
|
196
|
+
Do not prematurely move the already documented role files into `config/`: filename aliases,
|
|
197
|
+
CLI/MCP compatibility and the migration manifest must be specified first.
|
|
198
|
+
|
|
199
|
+
Migration rules:
|
|
200
|
+
|
|
201
|
+
- Inventory all writers/readers and classify fields, not just filenames. Snapshot original
|
|
202
|
+
bytes, inventory digest, source schema and Git tracking before asking to apply.
|
|
203
|
+
- Legacy memory import must distinguish missing JSON from corrupt/invalid JSON. Existing
|
|
204
|
+
permissive loaders may fall back to stale Markdown; reuse parsers/renderers only behind a
|
|
205
|
+
strict source selection/validation boundary. Invalid canonical data stops migration and
|
|
206
|
+
preserves all original bytes, rather than silently promoting a Markdown fallback.
|
|
207
|
+
- Quiesce all participating writers; a new lock cannot stop an old CLI that does not know it.
|
|
208
|
+
Known legacy clients block activation, and absence of observed clients does not prove
|
|
209
|
+
quiescence. Require an explicit maintenance boundary; unknown participants defer activation.
|
|
210
|
+
Do not claim mixed-version safety from a new manifest alone. Old clients must be
|
|
211
|
+
upgraded/stopped before the boundary moves; a pre-write check alone is not fencing.
|
|
212
|
+
- Stage copied data and validate digests, IDs, counters and provenance before activating one
|
|
213
|
+
versioned manifest. Use single-authority writes; do not create two independent writable
|
|
214
|
+
JSON/Markdown or legacy/v2 truths during a compatibility window.
|
|
215
|
+
- Preserve originals as explicitly labelled legacy archives. Never blanket-untrack or delete
|
|
216
|
+
`.leerness`. Index/ignore changes and project instructions are part of an approved migration.
|
|
217
|
+
- Pre-activation rollback preserves bytes. Post-activation rollback must first reconcile
|
|
218
|
+
newer events/records; copying an old backup over new writes is not rollback.
|
|
219
|
+
- Default handoff and inspect remain tracked-file-read-only. Explicit project memory,
|
|
220
|
+
consolidation and finalization are the durable-write boundaries.
|
|
221
|
+
|
|
222
|
+
## 7. Acceptance matrix
|
|
223
|
+
|
|
224
|
+
- Main + two real linked worktrees: private paths differ, common paths match, sibling
|
|
225
|
+
subprojects remain separate; branch switch/detached HEAD do not change runtime identity.
|
|
226
|
+
- Same worktree, two sessions: no current-run/evidence cross-talk; absent/invalid explicit
|
|
227
|
+
session identity fails safely for concurrent mutation instead of silently borrowing ownership.
|
|
228
|
+
- Non-Git, Git missing, bare, broken gitfile, moved worktree, submodule, spaces, Unicode,
|
|
229
|
+
Windows alias/case/junction, permission errors and inherited Git location overrides.
|
|
230
|
+
- Inspect/show: byte and mtime snapshots of project and Git metadata remain identical, no
|
|
231
|
+
cache/usage/salt/lease/lock creation, no subprocess provider calls, bounded stdout/JSON errors.
|
|
232
|
+
- Multi-process claim/lease races, owner expiry/replacement, clock movement, duplicate IDs,
|
|
233
|
+
truncated JSONL, corrupt/future schema, failed writes and interruption at every commit point.
|
|
234
|
+
- Independent records merge without shared counter edits; conflicting IDs/policy revisions
|
|
235
|
+
fail closed; decision disagreement stays explicit; generated views reproduce from digests.
|
|
236
|
+
- Finalize replay, record durability failure, stale review commit, rejected review, failed
|
|
237
|
+
tests, missing provenance, evidence outside retained Git and worktree-removal preflight.
|
|
238
|
+
- Legacy fixtures, handoff/MCP presence, file-lease and role-fallback probes plus installed
|
|
239
|
+
cleanroom and supported Node/Windows/POSIX release tests before enabling new runtime writes.
|
|
240
|
+
|
|
241
|
+
## Inspection optimization and verification boundaries
|
|
242
|
+
|
|
243
|
+
Each valid inspection makes one Git topology query through the existing gateway. On Windows
|
|
244
|
+
the gateway also runs the trusted System32 executable locator; the normal console encoding
|
|
245
|
+
bootstrap is unchanged. Inspection skips unrelated `npm root -g` skillpack discovery and
|
|
246
|
+
does not call providers, register presence, take usage locks, or write caches.
|
|
247
|
+
Workspace discovery enumerates the two immediate workspace directories once. Inventory covers
|
|
248
|
+
known leaves in both existing locations (selected/unselected are explicit), with cached parent
|
|
249
|
+
metadata: it does not read state contents,
|
|
250
|
+
enumerate runtime descendants, query Git tracking, or certify record/schema integrity.
|
|
251
|
+
No long-lived path cache is used: moving a worktree or changing the target refreshes topology.
|
|
252
|
+
|
|
253
|
+
`npm run test:state-scopes` checks selector compatibility, real main/two linked worktrees,
|
|
254
|
+
project namespaces, moved/detached worktrees, actual submodule topology, aliases, Git failure
|
|
255
|
+
taxonomy, and CLI byte/mtime preservation with normal bookkeeping enabled. The scope probe
|
|
256
|
+
also passed on Node 18/Windows; POSIX execution remains a separate CI check, not implied by it.
|
|
257
|
+
Later concurrency/finalize/adapter acceptance bullets above do not apply to the implemented
|
|
258
|
+
inspection-only stage and are not reported complete by its tests.
|
|
259
|
+
|
|
260
|
+
## Not included in P-0020
|
|
261
|
+
|
|
262
|
+
No automatic migration, control database, task dispatch, paid provider calls, source lease
|
|
263
|
+
relocation, decision import, finalize command, worktree deletion or dashboard is implied by
|
|
264
|
+
the path-inspection preview. Existing review/release rules still apply to implementation.
|
|
265
|
+
Later stages require their own
|
|
266
|
+
implementation scope and verification; this design does not mark them complete.
|