@6reduk/workspace-pipeline 0.1.0
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/LICENSE +21 -0
- package/README.md +78 -0
- package/docs/collaboration.md +59 -0
- package/docs/config-fields.md +65 -0
- package/docs/contracts.md +149 -0
- package/docs/doctor.md +165 -0
- package/docs/launch.md +50 -0
- package/docs/lifecycle-cli.md +141 -0
- package/docs/lifecycle.md +42 -0
- package/docs/migrations/unity.md +288 -0
- package/docs/native-provider-format.md +149 -0
- package/docs/provider-bundles.md +81 -0
- package/docs/provider-resources.md +37 -0
- package/docs/release.md +25 -0
- package/docs/remove.md +70 -0
- package/docs/repair.md +80 -0
- package/docs/repositories.md +209 -0
- package/docs/repository-manual-recovery.md +102 -0
- package/docs/repository-observations.md +29 -0
- package/docs/repository-recovery.md +204 -0
- package/docs/repository-retention.md +46 -0
- package/docs/repository-transport-budgets.md +26 -0
- package/docs/retention.md +237 -0
- package/docs/source.md +50 -0
- package/docs/switch.md +412 -0
- package/package.json +39 -0
- package/schemas/common.schema.json +251 -0
- package/schemas/inventory.schema.json +15 -0
- package/schemas/operation.schema.json +286 -0
- package/schemas/pipeline.schema.json +317 -0
- package/schemas/state.schema.json +302 -0
- package/schemas/workspace.schema.json +67 -0
- package/src/cli.js +7 -0
- package/src/commands/adopt.js +2 -0
- package/src/commands/bootstrap-recovery.js +90 -0
- package/src/commands/dispatch.js +394 -0
- package/src/commands/init.js +84 -0
- package/src/commands/launch.js +69 -0
- package/src/commands/migration-apply.js +53 -0
- package/src/commands/migration.js +50 -0
- package/src/commands/repositories.js +61 -0
- package/src/commands/repository-abandon.js +16 -0
- package/src/commands/repository-ancestors.js +21 -0
- package/src/commands/repository-locks.js +77 -0
- package/src/contracts/parse.js +57 -0
- package/src/contracts/semantic.js +240 -0
- package/src/contracts/validate.js +21 -0
- package/src/launch/grok.js +20 -0
- package/src/migrations/legacy-unity-begin.js +35 -0
- package/src/migrations/legacy-unity-compensate.js +82 -0
- package/src/migrations/legacy-unity-deactivate.js +60 -0
- package/src/migrations/legacy-unity-deactivation-resume-apply.js +62 -0
- package/src/migrations/legacy-unity-deactivation-resume.js +81 -0
- package/src/migrations/legacy-unity-finalize.js +88 -0
- package/src/migrations/legacy-unity-install-recovery.js +76 -0
- package/src/migrations/legacy-unity-install-resume.js +60 -0
- package/src/migrations/legacy-unity-install.js +88 -0
- package/src/migrations/legacy-unity-lease.js +136 -0
- package/src/migrations/legacy-unity-preflight.js +67 -0
- package/src/migrations/legacy-unity-preview.js +91 -0
- package/src/migrations/legacy-unity-resume-apply.js +39 -0
- package/src/migrations/legacy-unity-resume.js +41 -0
- package/src/migrations/legacy-unity-resumed-evidence.js +88 -0
- package/src/migrations/legacy-unity.js +99 -0
- package/src/operations/apply.js +576 -0
- package/src/operations/backup.js +94 -0
- package/src/operations/bootstrap-lock.js +87 -0
- package/src/operations/bootstrap-owner-retirement.js +121 -0
- package/src/operations/bundle-update.js +54 -0
- package/src/operations/config-fields.js +24 -0
- package/src/operations/continuation-lifecycle.js +77 -0
- package/src/operations/doctor.js +214 -0
- package/src/operations/history.js +170 -0
- package/src/operations/installer-identity.js +49 -0
- package/src/operations/journal.js +142 -0
- package/src/operations/lifecycle.js +133 -0
- package/src/operations/lineage-guard.js +20 -0
- package/src/operations/lock.js +109 -0
- package/src/operations/maintenance.js +62 -0
- package/src/operations/migration-pending.js +22 -0
- package/src/operations/ownership.js +122 -0
- package/src/operations/plan.js +278 -0
- package/src/operations/reconciliation.js +112 -0
- package/src/operations/recovery-lease.js +66 -0
- package/src/operations/remove.js +140 -0
- package/src/operations/repair.js +188 -0
- package/src/operations/repository-abandon.js +192 -0
- package/src/operations/repository-ancestors.js +158 -0
- package/src/operations/repository-apply.js +122 -0
- package/src/operations/repository-authorization.js +48 -0
- package/src/operations/repository-bootstrap-continuation.js +190 -0
- package/src/operations/repository-bootstrap-reconcile.js +106 -0
- package/src/operations/repository-bootstrap-recover.js +114 -0
- package/src/operations/repository-bootstrap.js +82 -0
- package/src/operations/repository-clone.js +63 -0
- package/src/operations/repository-history.js +108 -0
- package/src/operations/repository-inputs.js +41 -0
- package/src/operations/repository-journal.js +127 -0
- package/src/operations/repository-lock-reconcile.js +401 -0
- package/src/operations/repository-pending.js +29 -0
- package/src/operations/repository-reconcile.js +182 -0
- package/src/operations/repository-resumption-approvals.js +77 -0
- package/src/operations/repository-retention-apply.js +75 -0
- package/src/operations/repository-retention.js +137 -0
- package/src/operations/repository-workspace.js +78 -0
- package/src/operations/retention-apply.js +133 -0
- package/src/operations/retention-combined-scan.js +30 -0
- package/src/operations/retention-combined.js +41 -0
- package/src/operations/retention-policy.js +65 -0
- package/src/operations/retention-receipts.js +126 -0
- package/src/operations/retention-scan.js +86 -0
- package/src/operations/retention.js +56 -0
- package/src/operations/state.js +210 -0
- package/src/operations/switch-activate.js +64 -0
- package/src/operations/switch-backups.js +29 -0
- package/src/operations/switch-continuation-journal.js +94 -0
- package/src/operations/switch-continuation-pending.js +60 -0
- package/src/operations/switch-continuation-records.js +109 -0
- package/src/operations/switch-continuation-recovery.js +91 -0
- package/src/operations/switch-continuation-runtime.js +135 -0
- package/src/operations/switch-continuation-store.js +120 -0
- package/src/operations/switch-continuation.js +76 -0
- package/src/operations/switch-execute.js +68 -0
- package/src/operations/switch-inspect.js +45 -0
- package/src/operations/switch-journal-store.js +109 -0
- package/src/operations/switch-journal.js +71 -0
- package/src/operations/switch-lifecycle.js +72 -0
- package/src/operations/switch-pending.js +43 -0
- package/src/operations/switch-preflight.js +73 -0
- package/src/operations/switch-prepare.js +75 -0
- package/src/operations/switch-records.js +60 -0
- package/src/operations/switch-recovery-store.js +74 -0
- package/src/operations/switch.js +52 -0
- package/src/operations/toml-fields.js +133 -0
- package/src/providers/bundles.js +42 -0
- package/src/providers/common-entry.js +16 -0
- package/src/providers/grok.js +26 -0
- package/src/providers/interface.js +25 -0
- package/src/providers/kimi.js +26 -0
- package/src/providers/native.js +155 -0
- package/src/providers/registry.js +10 -0
- package/src/providers/shared.js +51 -0
- package/src/providers/source.js +30 -0
- package/src/source/git.js +303 -0
- package/src/source/inventory.js +87 -0
- package/src/source/repository-budget.js +18 -0
- package/src/source/snapshot.js +37 -0
- package/src/workspace/paths.js +54 -0
- package/src/workspace/profiles.js +8 -0
- package/src/workspace/repositories.js +57 -0
- package/src/workspace/repository-inventory.js +77 -0
- package/src/workspace/repository-observation.js +38 -0
- package/src/workspace/repository-preflight.js +129 -0
- package/src/workspace/repository-preview.js +196 -0
- package/src/workspace/repository-tree.js +57 -0
- package/src/workspace/reserved.js +11 -0
- package/src/workspace/resolve.js +53 -0
package/docs/switch.md
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# Switch lifecycle (internal APIs and CLI)
|
|
2
|
+
|
|
3
|
+
Current implementation includes phase execution, repeated uncertain continuation,
|
|
4
|
+
final activation and doctor/history integration. CLI preview/apply routing is
|
|
5
|
+
available with the packaged Codex/Claude registry. This does not authorize a live
|
|
6
|
+
project migration. See [CLI contract](lifecycle-cli.md).
|
|
7
|
+
The CLI routes uncertain-target and clean-boundary continuation, including a
|
|
8
|
+
completed journal whose activation is still pending. See boundary rules below.
|
|
9
|
+
Older prerequisite sections describe their historical implementation boundaries;
|
|
10
|
+
the CLI contract and boundary section describe the current combined behavior.
|
|
11
|
+
Prerequisite sections describe their own limited scope, not execution authority.
|
|
12
|
+
|
|
13
|
+
`composeSwitchPreview({previous, removal, replacement})` is pure, non-executable
|
|
14
|
+
composition. `removal` is a full-removal native preview against actual previous
|
|
15
|
+
state. `replacement` is a setup candidate against the projected post-removal
|
|
16
|
+
configuration, not a setup request executed against an active workspace.
|
|
17
|
+
|
|
18
|
+
The function checks both envelopes, enforces the same workspace/layout, different
|
|
19
|
+
pipeline identity and snapshot digest, and binds incoming before bytes to removal
|
|
20
|
+
results wherever paths overlap. It retains separate remove-old/install-new phases,
|
|
21
|
+
initial observations and projected final results. Foreign observations survive.
|
|
22
|
+
No mutation of input, filesystem, Git, configs or approvals occurs.
|
|
23
|
+
|
|
24
|
+
The returned envelope has applySupported=false and sourceVerification=not-verified.
|
|
25
|
+
Pure schema/hash consistency is not proof of installed ownership, trusted adapter
|
|
26
|
+
replay or staged source bytes. The future coordinator must stage and validate the
|
|
27
|
+
new Git source before any removal and obtain fresh approval under a live lock.
|
|
28
|
+
Source manifests cannot inject executable adapters.
|
|
29
|
+
|
|
30
|
+
## Git-backed preparation (internal, no apply)
|
|
31
|
+
|
|
32
|
+
`prepareSwitch({wrapper, manifestPath, network?, tempRoot?}, registry)` in
|
|
33
|
+
`operations/switch-prepare.js` stages an explicitly selected Git source outside
|
|
34
|
+
the wrapper. It replays the installed package to prepare full removal, verifies
|
|
35
|
+
the incoming package, invokes trusted CLI adapters, and composes incoming requests
|
|
36
|
+
against projected post-removal bytes. Existing foreign files/JSON fields remain
|
|
37
|
+
subject to normal ownership checks; switch grants no takeover authority.
|
|
38
|
+
|
|
39
|
+
The old removal/state, incoming manifest, staged snapshot and observed destination
|
|
40
|
+
bytes are rechecked after adapter work. The outer private envelope reports
|
|
41
|
+
`sourceVerification: verified-at-preparation`, not ongoing source freshness; its
|
|
42
|
+
embedded pure phase preview deliberately retains `not-verified`. Preparation can
|
|
43
|
+
write disposable Git staging directories outside the workspace (also on failure),
|
|
44
|
+
but never applies removal, installs provider files, creates a journal, or modifies
|
|
45
|
+
workspace state. No temporary-directory deletion or cleanup policy is added here.
|
|
46
|
+
|
|
47
|
+
`applySupported` remains false. There is no lock, atomic snapshot, approval or
|
|
48
|
+
crash-recovery guarantee for this preview. A future executor must replay/approve
|
|
49
|
+
the exact two-phase operation under a live workspace lock and use one phased
|
|
50
|
+
journal. Public source switches remain unavailable.
|
|
51
|
+
|
|
52
|
+
Public switch routing remains unimplemented. Existing native
|
|
53
|
+
single-phase journals cannot simply concatenate targets when the same path is
|
|
54
|
+
deleted/restored and later recreated. The phased journal keeps those two
|
|
55
|
+
steps and their readbacks distinct under one operation, with non-ready state on
|
|
56
|
+
interruption. No remove-plus-unrelated-setup workaround is enabled.
|
|
57
|
+
|
|
58
|
+
## Two-phase event model
|
|
59
|
+
|
|
60
|
+
`inspectSwitchEvents(preview, previous, events)` verifies a single ordered chain
|
|
61
|
+
bound to the reconstructed two-phase preview. Events have exact keys, sequence,
|
|
62
|
+
previous canonical event digest and preview digest. A start is followed by
|
|
63
|
+
phase-qualified intent/outcome pairs in target order. An unfinished intent is
|
|
64
|
+
uncertain; failed/uncertain outcomes stop progress. A `phase-checked` event binds
|
|
65
|
+
the expected whole projected path/hash map after every target in that phase.
|
|
66
|
+
Only then may the next phase begin, even when a phase has no targets. Both phase
|
|
67
|
+
checks are necessary for event-chain completion; completion is not activation.
|
|
68
|
+
|
|
69
|
+
The same path can occur once in each phase, without flattening targets or losing
|
|
70
|
+
which write an outcome describes. The future executor must obtain actual target
|
|
71
|
+
readback evidence, enforce approval and bind transaction recovery to this model.
|
|
72
|
+
This pure helper neither reads nor creates journal files. Its chain
|
|
73
|
+
uses canonical event digests, not hashes of serialized file bytes. It does not
|
|
74
|
+
validate source provenance or attest that asserted filesystem observations occurred.
|
|
75
|
+
|
|
76
|
+
This is a full, bounded in-memory inspection. Do not call it over all accumulated
|
|
77
|
+
events before every persisted append: that would repeat work quadratically.
|
|
78
|
+
The internal cursor advances one event at a time; durable writer/head checks are
|
|
79
|
+
described below. No retention guarantee is claimed by this helper.
|
|
80
|
+
|
|
81
|
+
## Internal journal storage
|
|
82
|
+
|
|
83
|
+
`createSwitchJournal` / `readSwitchJournal` in `switch-journal-store.js` persist
|
|
84
|
+
and inspect these events under `.pipeline/journals/<uuid>/`. The writer requires
|
|
85
|
+
a live workspace lock, reports the exact directory through `onLocation`, creates
|
|
86
|
+
each event exclusively, syncs its file and checks the recorded bytes. A failed
|
|
87
|
+
append poisons the writer; neither automatic append-resume nor repair is offered.
|
|
88
|
+
Existing evidence is retained. A read-only reader reconstructs incomplete intents
|
|
89
|
+
as uncertain and rejects malformed, reordered or incorrectly bound events.
|
|
90
|
+
|
|
91
|
+
Each append checks the last file's byte hash, while the event chain uses canonical
|
|
92
|
+
digests. Full audits occur at initialization, both phase checks and failed/uncertain
|
|
93
|
+
outcomes. Older prefix corruption may only be found at these audits, not the next
|
|
94
|
+
append. Tests count head reads and audits; there is no complete performance benchmark
|
|
95
|
+
or guarantee against concurrent hostile filesystem access/power loss.
|
|
96
|
+
|
|
97
|
+
This storage is internal and not connected to the public CLI. Storage primitives
|
|
98
|
+
alone grant no activation or write authority. The lifecycle and history readers
|
|
99
|
+
described below bind the exact prepared switch, approval, snapshots and recovery
|
|
100
|
+
envelope. Do not bypass those checks or create real workspace switch journals
|
|
101
|
+
through these low-level APIs.
|
|
102
|
+
|
|
103
|
+
## Recovery envelope (structural binding)
|
|
104
|
+
|
|
105
|
+
`switch-records.js` validates a prepared switch against an exact approval digest
|
|
106
|
+
and previous state, then builds a `switch-recovery` envelope bound to one journal.
|
|
107
|
+
It reconstructs the two-phase preview, checks the full-removal record and required
|
|
108
|
+
backup inventory, and retains both snapshot descriptors. The envelope is detached
|
|
109
|
+
and digest-bound; a wrong approval, replaced phase, missing backup descriptor or
|
|
110
|
+
modified recovery snapshot is rejected. No synthetic nested approval is created.
|
|
111
|
+
|
|
112
|
+
These helpers perform no I/O. `sourceVerification` is a claim from preparation,
|
|
113
|
+
not proof re-established by record validation. The envelope does not demonstrate
|
|
114
|
+
that its journal exists or that snapshots/backups have been durably installed.
|
|
115
|
+
`activationSupported` stays false. Locked adapter/source replay, persistence and
|
|
116
|
+
generic recovery/history integration remain required before execution is enabled.
|
|
117
|
+
|
|
118
|
+
## Locked preflight
|
|
119
|
+
|
|
120
|
+
`verifySwitchApproval(lock, prepared, approval, registry, previous)` in
|
|
121
|
+
`switch-preflight.js` detaches and validates the exact record before awaiting,
|
|
122
|
+
requires a live lock, and verifies actual state bytes, full old-package removal
|
|
123
|
+
replay (including backups), incoming origin and staged package bytes. Staging
|
|
124
|
+
directories must exist outside and not contain the workspace. It reconstructs
|
|
125
|
+
the incoming adapter plan against the approved projected post-removal observations
|
|
126
|
+
and compares the exact result and observation scope.
|
|
127
|
+
|
|
128
|
+
State, source, removal and target observations are repeated after asynchronous
|
|
129
|
+
adapter execution. This preflight does not fetch Git, write recovery records,
|
|
130
|
+
modify provider files, or activate anything. It returns `applySupported: false`.
|
|
131
|
+
Passing it is not a reusable capability: the executor must recheck relevant
|
|
132
|
+
dependencies at persistence/write boundaries and handle intervening external edits.
|
|
133
|
+
|
|
134
|
+
## Prerequisite persistence (internal, no target writes)
|
|
135
|
+
|
|
136
|
+
`persistSwitchRecovery` in `switch-recovery-store.js` performs locked preflight,
|
|
137
|
+
bounds the recovery record, copies/verifies the new snapshot, initializes one
|
|
138
|
+
phased journal and exclusively writes/syncs/readbacks the associated recovery file
|
|
139
|
+
at `.pipeline/transactions/<same-uuid>/recovery.json`. Preflight and durable
|
|
140
|
+
evidence inspection are repeated before returning exact recovery hash and paths.
|
|
141
|
+
No journal writer capability, pending/active transition or target write is returned.
|
|
142
|
+
|
|
143
|
+
`readSwitchRecovery` checks record/journal identity, both persisted snapshot trees,
|
|
144
|
+
old backup hashes and the event chain without requiring the temporary source
|
|
145
|
+
directory. It does not inspect current provider-target state or authorize resumption.
|
|
146
|
+
Partial/orphan metadata is retained on errors, including an unusable recovery file.
|
|
147
|
+
There is no automatic retry, deletion or generic-history bypass. Executor and
|
|
148
|
+
activation helpers perform their own current-state checks.
|
|
149
|
+
|
|
150
|
+
Incoming ownership backups are derived by `incomingSwitchBackups` from approved
|
|
151
|
+
post-removal observation bytes. Whole-file hashes and owned JSON-field before
|
|
152
|
+
values are verified separately; backups retain the entire observed file. All
|
|
153
|
+
existing backup collisions are checked before creating new backups. An identical
|
|
154
|
+
backup is reused; different bytes at the same path cause failure, not overwrite.
|
|
155
|
+
Backups are saved before journal/recovery creation and checked by recovery reads.
|
|
156
|
+
Descriptor derivation is deterministic from the frozen preview, so no additional
|
|
157
|
+
recovery-record field or historical record rewrite is introduced. Legacy field
|
|
158
|
+
backup collisions with changed foreign siblings fail closed and are not resolved
|
|
159
|
+
automatically by this step.
|
|
160
|
+
|
|
161
|
+
## Pending transition (internal)
|
|
162
|
+
|
|
163
|
+
`markSwitchPending` in `switch-pending.js` requires the exact persisted recovery
|
|
164
|
+
path/hash, a live lock and current explicit approval. It verifies the untouched
|
|
165
|
+
start-only journal, replays preflight, stages state bytes, repeats checks before
|
|
166
|
+
rename and verifies the resulting state file. Old active deployment and activation
|
|
167
|
+
history remain unchanged; status becomes `needs-reconciliation`.
|
|
168
|
+
|
|
169
|
+
For switch, `pending` binds the canonical recovery-record digest (including the
|
|
170
|
+
unique journal identity), not merely equal desired bytes or a repeatable preview.
|
|
171
|
+
Generic readers must learn this switch-specific binding before public routing.
|
|
172
|
+
Interruption after rename leaves pending state; no rollback or false ready result
|
|
173
|
+
is attempted. Scratch/evidence files may remain on failure. The helper does not
|
|
174
|
+
write provider targets or authorize their execution. Advisory locking does not
|
|
175
|
+
exclude hostile same-user OS races.
|
|
176
|
+
|
|
177
|
+
## Pending inspection
|
|
178
|
+
|
|
179
|
+
`inspectPendingSwitch(workspace, recoveryPath)` verifies exact pending-state binding
|
|
180
|
+
to this transaction, durable evidence and actual target bytes. It reconstructs the
|
|
181
|
+
expected intermediate state from completed events in phase order. For interrupted
|
|
182
|
+
intent/uncertain outcome it distinguishes `uncertain-before`, `uncertain-desired`
|
|
183
|
+
and `conflict`; seeing desired bytes never manufactures a completed outcome.
|
|
184
|
+
Other observed paths must match the intermediate projection, including unchanged
|
|
185
|
+
dependencies. It repeats state/evidence/target checks to reject observed drift.
|
|
186
|
+
|
|
187
|
+
The result always remains `needs-reconciliation` with `executionAllowed: false`.
|
|
188
|
+
Journal completion, if present, is reported separately and is not activation.
|
|
189
|
+
It neither writes nor resumes an operation, and is not yet wired into generic
|
|
190
|
+
doctor/history. No atomic snapshot or hostile-concurrency guarantee is implied.
|
|
191
|
+
|
|
192
|
+
## Explicit phase execution (internal)
|
|
193
|
+
|
|
194
|
+
`executeSwitchPhase` accepts one phase name, exact recovery path/hash and current
|
|
195
|
+
approval. It verifies the pending transaction and intact intermediate files,
|
|
196
|
+
reopens only an intact `open` journal at its verified head and executes that phase.
|
|
197
|
+
Installation cannot be selected while removal is current. Uncertain or stopped
|
|
198
|
+
chains cannot be reopened through this entry point.
|
|
199
|
+
|
|
200
|
+
Each target gets a durable intent before mutation and a completed outcome only
|
|
201
|
+
after readback. Existing checked file-write/delete primitives are reused with
|
|
202
|
+
unchanged bodies. State/recovery hashes and all projected observed paths are
|
|
203
|
+
checked around writes; journal head checks remain incremental. Full evidence and
|
|
204
|
+
snapshot audits occur at phase entry/exit, not before each append. Prefix/snapshot
|
|
205
|
+
drift may therefore be detected at the boundary rather than at the next target.
|
|
206
|
+
This is not an overall linear-time claim: target dependency scans still cover the
|
|
207
|
+
whole observed scope at each write.
|
|
208
|
+
|
|
209
|
+
Both phases share one journal. Phase completion verifies the intermediate state
|
|
210
|
+
and records its projection check. Even after both phases, state stays pending;
|
|
211
|
+
no active-deployment promotion or user-ready claim is made. An error after intent
|
|
212
|
+
retains uncertainty and blocks ordinary rerun; no outcome is invented or history
|
|
213
|
+
rewritten. History/doctor integration and explicit continuation are described
|
|
214
|
+
below; nothing is exposed as a public CLI command.
|
|
215
|
+
|
|
216
|
+
## Final activation (internal)
|
|
217
|
+
|
|
218
|
+
`activateSwitch` requires exact recovery hash, current approval, live lock, both
|
|
219
|
+
completed phase checks, matching pending identity and conflict-free final files.
|
|
220
|
+
It stages and rechecks the transition before rename. The new deployment becomes
|
|
221
|
+
active with an anchor containing recovery path/byte hash and terminal journal
|
|
222
|
+
sequence/byte hash; pending is cleared. Snapshots, backups, approvals and journal
|
|
223
|
+
history are not rewritten. Runtime remains `not-run`.
|
|
224
|
+
|
|
225
|
+
`inspectActivatedSwitch` confirms the exact active deployment and anchor, completed
|
|
226
|
+
journal and final file hashes with repeated dependency/target checks. It can establish
|
|
227
|
+
that activation was written after an interruption at rename, without reapplying.
|
|
228
|
+
A returned `applied` is local configuration evidence, not live-provider readiness.
|
|
229
|
+
Generic doctor/history recognize these records as described below. Public write
|
|
230
|
+
routing is still absent. Uncertain phases require the separate continuation path.
|
|
231
|
+
|
|
232
|
+
## History and doctor integration
|
|
233
|
+
|
|
234
|
+
History dispatches exact `switch-recovery` records to the phased evidence reader,
|
|
235
|
+
retaining unfinished/orphan/corrupt diagnostics and normal predecessor-anchor
|
|
236
|
+
checks. Historical switch verification uses stored evidence, not today's target
|
|
237
|
+
bytes. Completed journal status alone still does not prove activation.
|
|
238
|
+
|
|
239
|
+
Doctor selects the exact active anchor, or identifies a pending switch by its
|
|
240
|
+
unique recovery digest. Switch readiness uses exact activation/final-projection
|
|
241
|
+
inspection; pending switches always remain non-ready. A stale explicit selection
|
|
242
|
+
or invalid historical predecessor cannot be hidden by a valid current switch.
|
|
243
|
+
Native setup/update/repair/removal dispatch and field projections remain unchanged.
|
|
244
|
+
Switch-specific comparison is conservative and exact; it does not yet extend native
|
|
245
|
+
foreign-field projection allowances to completed switch results. Public switch
|
|
246
|
+
execution and release qualification remain pending; internal continuation follows.
|
|
247
|
+
|
|
248
|
+
## Continuation preview (read-only)
|
|
249
|
+
|
|
250
|
+
`prepareSwitchContinuation` binds a proposed new continuation to the exact pending
|
|
251
|
+
recovery, journal sequence/canonical head/byte head, state bytes and observations.
|
|
252
|
+
For a conflict-free uncertain operation, before bytes select
|
|
253
|
+
`retry-approved-target`; desired bytes select `verify-desired` without a duplicate
|
|
254
|
+
write. Remaining approved targets and phase checks are listed in original order.
|
|
255
|
+
Equal before/desired hashes also select verification only.
|
|
256
|
+
|
|
257
|
+
The preview is digest-bound, `applySupported: false`, and requires fresh approval.
|
|
258
|
+
It rechecks dependencies before returning and never rewrites the predecessor or
|
|
259
|
+
marks its uncertain outcome completed. Foreign changes and failed journals are
|
|
260
|
+
rejected. Verified clean boundaries use the rules below. Recovery/journal lineage, execution and resolution of
|
|
261
|
+
historical unfinished diagnostics are separate helpers described below.
|
|
262
|
+
|
|
263
|
+
## Continuation approval verification (internal, read-only)
|
|
264
|
+
|
|
265
|
+
`verifySwitchContinuationApproval` accepts only an exact `decision: approve` and
|
|
266
|
+
`previewDigest` binding. It detaches caller inputs before awaiting, validates the
|
|
267
|
+
preview digest, checks the live workspace lock, and reconstructs the preview from
|
|
268
|
+
current recovery, journal, state and target observations. Any changed dependency
|
|
269
|
+
or observation invalidates the old approval. The lock is checked again at return.
|
|
270
|
+
|
|
271
|
+
This is a point-in-time read-only check, not a durable authorization receipt or
|
|
272
|
+
permission to append to the old uncertain journal. `applySupported` stays false.
|
|
273
|
+
Future execution must recheck its dependencies at mutation boundaries; advisory
|
|
274
|
+
locking does not prevent unrelated programs from editing files.
|
|
275
|
+
|
|
276
|
+
## Continuation event model (internal, pure)
|
|
277
|
+
|
|
278
|
+
`createSwitchContinuationCursor` interprets a new chain for an already verified
|
|
279
|
+
continuation preview. The start event binds the exact predecessor descriptor;
|
|
280
|
+
later events bind the preview digest and previous event digest. It never appends
|
|
281
|
+
to the predecessor. Retry operations require intent and outcome. A first target
|
|
282
|
+
marked `verify-desired` instead accepts readback without a write intent. Both
|
|
283
|
+
paths require the desired hash for completion and ordered phase projection checks.
|
|
284
|
+
|
|
285
|
+
An unfinished intent remains uncertain; failed/uncertain outcomes stop the chain.
|
|
286
|
+
An invalid append poisons the cursor. A completed chain is not activation or
|
|
287
|
+
runtime evidence. Validation here is structural and sequencing only, not proof
|
|
288
|
+
that predecessor files, approval or observed bytes exist. Event storage is
|
|
289
|
+
described below, as are locked execution and history resolution. This model does not
|
|
290
|
+
make continuation available through the CLI.
|
|
291
|
+
|
|
292
|
+
## Continuation journal storage (internal)
|
|
293
|
+
|
|
294
|
+
`createSwitchContinuationJournal` verifies exact approval under the workspace
|
|
295
|
+
lock before creating a fresh UUID journal. Location callbacks report planned,
|
|
296
|
+
created and initialized paths. Approval/dependency checks are repeated around
|
|
297
|
+
initialization callbacks. The predecessor journal is never a valid destination.
|
|
298
|
+
|
|
299
|
+
Events use exclusive creation, sync and byte-hash readback. Appends check the live
|
|
300
|
+
lock and previous file hash; full replay runs at initialization, phase boundaries
|
|
301
|
+
and stopped outcomes, not on every event. Prefix corruption may therefore be
|
|
302
|
+
detected at a boundary rather than at the next append. IO/validation failure
|
|
303
|
+
poisons the writer and preserves partial files. `openSwitchContinuationJournal`
|
|
304
|
+
can reopen only an audited open chain with the expected byte head; uncertain or
|
|
305
|
+
failed chains cannot reopen. No cleanup is provided here.
|
|
306
|
+
`readSwitchContinuationJournal` performs a bounded read-only event audit against
|
|
307
|
+
the supplied preview. It does not prove approval, live target state or resolution
|
|
308
|
+
of the predecessor's uncertainty.
|
|
309
|
+
|
|
310
|
+
This is internal evidence storage only. It does not write provider targets or
|
|
311
|
+
change pending/active state. The recovery wrapper below persists the binding;
|
|
312
|
+
execution-boundary checks and generic history integration are separate helpers
|
|
313
|
+
before continuation can be exposed through the CLI. Separate chains created
|
|
314
|
+
here are not treated as automatic permission to execute or as resolved history.
|
|
315
|
+
|
|
316
|
+
## Continuation recovery binding (internal)
|
|
317
|
+
|
|
318
|
+
`persistSwitchContinuationRecovery` stores a strict `switch-continuation-recovery`
|
|
319
|
+
record beside the new chain, using the same UUID for transaction and journal.
|
|
320
|
+
The envelope includes the exact preview, approval and new journal path. The full
|
|
321
|
+
record is size-bounded before writing; exclusive creation, sync and hash readback
|
|
322
|
+
are followed by repeated locked approval and evidence checks. Partial records
|
|
323
|
+
remain on failure. No mutable writer or execution permission is returned.
|
|
324
|
+
|
|
325
|
+
`readSwitchContinuationRecovery` checks the envelope, UUID binding, predecessor
|
|
326
|
+
recovery byte hash, original snapshots/backups and exact old journal position.
|
|
327
|
+
It reconstructs the interrupted target, remaining approved operations and
|
|
328
|
+
historical observations from the immediate predecessor's plan and journal, with
|
|
329
|
+
the original switch verified through the ancestry chain. Both old dependencies
|
|
330
|
+
and the new journal are rechecked for drift. Stored hashes are integrity bindings,
|
|
331
|
+
not signatures or authentication of a human decision.
|
|
332
|
+
|
|
333
|
+
This reader checks historical evidence independently of current target files.
|
|
334
|
+
An intact record can remain readable after a user edit, without authorizing that
|
|
335
|
+
edit or continuation. Selection, target execution guards, final activation and
|
|
336
|
+
generic history resolution are described below. The
|
|
337
|
+
old uncertainty is not relabelled successful by record creation or validation.
|
|
338
|
+
|
|
339
|
+
## Selecting the pending continuation (internal)
|
|
340
|
+
|
|
341
|
+
`markSwitchContinuationPending` requires the exact recovery byte hash, matching
|
|
342
|
+
stored/current approval and an initialized one-event continuation journal. It
|
|
343
|
+
revalidates the preview against the old pending state, stages a new state file,
|
|
344
|
+
then repeats evidence, approval, staged-byte and current-state checks before
|
|
345
|
+
rename. Only `pending` changes: its new digest identifies the exact continuation
|
|
346
|
+
record (including its unique journal), not just the same desired configuration.
|
|
347
|
+
The active deployment and previous activation anchor are retained.
|
|
348
|
+
|
|
349
|
+
`inspectSelectedSwitchContinuation` verifies that exact pending identity and
|
|
350
|
+
historical evidence, including after interruption following rename. It does not
|
|
351
|
+
claim current target readiness: `executionAllowed` remains false. Errors preserve
|
|
352
|
+
staged or renamed state rather than rolling back. An ordinary rerun against the
|
|
353
|
+
old pending state fails after selection; the original switch executor also cannot
|
|
354
|
+
continue under the new identity. No public command is added here.
|
|
355
|
+
|
|
356
|
+
## Continuation execution, activation and history
|
|
357
|
+
|
|
358
|
+
`executeSwitchContinuationPhase` executes exactly one selected remaining phase.
|
|
359
|
+
It checks the recovery byte hash, stored approval, exact pending state, journal
|
|
360
|
+
head and projected target bytes. A verified desired first target gets readback
|
|
361
|
+
only; retries and later targets receive intent/write/readback/outcome. It reuses
|
|
362
|
+
checked file primitives. State, recovery and observed targets are guarded around
|
|
363
|
+
writes; full evidence audits run at phase boundaries. This is not an OS-wide lock
|
|
364
|
+
or an overall linear-time claim. Failed writes preserve uncertainty.
|
|
365
|
+
|
|
366
|
+
`activateSwitchContinuation` requires a completed chain, conflict-free final
|
|
367
|
+
projection and matching selected state. It stores the new desired deployment
|
|
368
|
+
with an exact continuation recovery/head anchor, repeating checks before rename.
|
|
369
|
+
`inspectSwitchContinuation` checks pending projection or exact completed active
|
|
370
|
+
state, including activation readback after a crash. Runtime remains not-run.
|
|
371
|
+
|
|
372
|
+
History retains the original uncertain status and adds `resolvedBy` only after
|
|
373
|
+
verifying a completed continuation against that exact predecessor. This removes
|
|
374
|
+
only its unfinished diagnostic, not corrupt/orphan diagnostics. Doctor recognizes
|
|
375
|
+
pending continuation digests and exact activation anchors; stale selections and
|
|
376
|
+
invalid dependencies cannot claim ready.
|
|
377
|
+
|
|
378
|
+
An interrupted continuation may now be the predecessor of a fresh, explicitly
|
|
379
|
+
approved continuation. `readSwitchLineage` performs two iterative ancestry passes,
|
|
380
|
+
rejects cycles and allows at most 32 continuation links plus the original switch.
|
|
381
|
+
Preparation rejects exceeding that budget before creating the next journal.
|
|
382
|
+
Every link binds exact parent bytes and journal position; the original switch
|
|
383
|
+
supplies snapshots, backups and desired installation. Each immediate predecessor
|
|
384
|
+
supplies its remaining operations and verified progress. Completed operations
|
|
385
|
+
are not replayed, and readback-only authority cannot expand into write authority.
|
|
386
|
+
Final activation selects the new record, not a timestamp or equal desired hash.
|
|
387
|
+
History resolves the verified ancestors without rewriting them.
|
|
388
|
+
|
|
389
|
+
## Clean-boundary continuation
|
|
390
|
+
|
|
391
|
+
A pending original switch or continuation may have an `open` journal with no
|
|
392
|
+
uncertain target, or a `completed` journal not yet activated. Fresh continuation
|
|
393
|
+
uses `uncertain: null` and binds the exact predecessor head, pending selection,
|
|
394
|
+
observed projection and remaining suffix. Completed outcomes are skipped; a
|
|
395
|
+
missing phase check is retained even when that phase has no operations left.
|
|
396
|
+
Existing readback-only authority stays readback-only, never becomes a write retry.
|
|
397
|
+
|
|
398
|
+
Both recorded phase checks allow an empty remaining list. Its new start-only
|
|
399
|
+
journal is completed structurally; pending selection and activation still repeat
|
|
400
|
+
source/ancestry/current-target validation. Neither record creation nor completion
|
|
401
|
+
alone declares the installation active. A crash of this new continuation can be
|
|
402
|
+
continued again with a new exact approval, within the existing ancestry bound.
|
|
403
|
+
|
|
404
|
+
History accepts verified open/completed predecessors as well as uncertain ones
|
|
405
|
+
only through validated lineage. It preserves their original records and statuses.
|
|
406
|
+
No timestamp selection, inferred outcomes, replay of completed writes, or reopening
|
|
407
|
+
of the predecessor journal is permitted. Failed or corrupt chains stay rejected.
|
|
408
|
+
This bounds one ancestry read; scanning all history is not claimed to be linear.
|
|
409
|
+
|
|
410
|
+
Repository moves, documentation relocation, changing layout, same-pipeline updates
|
|
411
|
+
and partial provider removal are not this switch preview's scope. Caller-defined
|
|
412
|
+
payloads are private and may contain config secrets; do not publish them as logs.
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@6reduk/workspace-pipeline",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Workspace-local Git pipeline configuration dispatcher",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"workspace-pipeline": "src/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"src/",
|
|
11
|
+
"schemas/",
|
|
12
|
+
"docs/"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/6reduk/workspace-pipeline-cli.git"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"check": "node --check src/cli.js",
|
|
24
|
+
"test": "node --test test/*.test.js",
|
|
25
|
+
"pack:check": "npm pack --dry-run --ignore-scripts",
|
|
26
|
+
"test:packed": "node scripts/verify-packed-cli.mjs",
|
|
27
|
+
"test:packed:identity": "node scripts/verify-packed-identity.mjs",
|
|
28
|
+
"test:packed:providers": "node scripts/verify-packed-providers.mjs",
|
|
29
|
+
"test:packed:pilot": "node scripts/verify-packed-pilot.mjs"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"ajv": "8.20.0",
|
|
33
|
+
"yaml": "2.9.1",
|
|
34
|
+
"toml-eslint-parser": "0.10.1"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|