@llblab/pi-kit 0.28.0 → 0.29.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/BACKLOG.md +2 -1
- package/CHANGELOG.md +4 -0
- package/README.md +3 -3
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +2 -2
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +5 -2
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +7 -0
- package/node_modules/@llblab/pi-state-flow/README.md +7 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +94 -47
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +8 -27
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +16 -151
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +3 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +4 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +5 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +0 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +0 -36
- package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +20 -31
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +8 -9
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +4 -4
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +18 -23
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +19 -21
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +24 -25
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +89 -48
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +22 -146
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +6 -3
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +4 -2
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +7 -1
- package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +0 -36
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/package.json +2 -2
package/BACKLOG.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Backlog
|
|
2
2
|
|
|
3
|
-
The 0.
|
|
3
|
+
The 0.29.0 composition advances State Flow to 0.26.0; package pins, resource order and bundled runtime ownership remain authoritative in `package.json`. Release outcomes belong in [CHANGELOG.md](./CHANGELOG.md).
|
|
4
4
|
|
|
5
5
|
## Carried checks
|
|
6
6
|
|
|
7
|
+
- **Installed 0.29.0 State Flow smoke (operator-owned):** After separately authorized installation/reload, use disposable storage to confirm `/tree` to an old step and reload keep current memory writable in Active and Passive, a fork copies the parent's current memory, and unreadable current files show `active (blocked)` with Passive retry and Off releasing inference only. Packed validation does not certify installed clients.
|
|
7
8
|
- **Installed 0.28.0 Telegram smoke (operator-owned):** After separately authorized installation/reload and queue drain or accepted waiting-work loss, confirm Restore/routing controls and follower delivery with disposable runtime storage. Do not test damaged-state reset against live shared state. Windows Restore remains fail-closed without strict evidence; packed validation does not certify installed clients.
|
|
8
9
|
- **Installed 0.27.6 restoration/compaction smoke (operator-owned):** After separately authorized installation/reload, use disposable storage to confirm failed Active restoration blocks provider inference across tree/reload, explicit mode recovery remains available, and native Codemode values/deletions survive completed-history compaction. Packed validation does not certify installed clients.
|
|
9
10
|
- **Installed 0.27.5 cleanup smoke (operator-owned):** After separately authorized installation/reload, confirm State Flow missing-deletion hints, recursive empty-object cleanup, inherited fallback and preserved array slots in disposable storage. Packed validation does not certify installed clients.
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@llblab/pi-kit` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.29.0: State Flow Stable Modes
|
|
6
|
+
|
|
7
|
+
- `Step-independent memory`: Advances the exact State Flow pin to `0.26.0`. Memory no longer depends on the Pi step: startup, reload, resume and `/tree` attach current same-session memory, old branch points never block or rewind it, and forks copy the parent's current memory. Passive stays writable across reload; unreadable memory under Active shows `active (blocked)`. Other pins, resources and load order are unchanged.
|
|
8
|
+
|
|
5
9
|
## 0.28.0: Telegram Workspace Restore and Runtime Resilience
|
|
6
10
|
|
|
7
11
|
- `Workspace and Routing`: Advances Telegram to `0.52.0` with conservative Workspace Restore, shared Reroute/Restore/Cancel controls, temporary-Thread lifetimes and 60-minute prompt choice expiry. Strict journal proofs remain required; Windows Restore fails closed. Other pins, resource ownership and load order are unchanged.
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Package links lead to the owning repositories for usage, documentation, issues,
|
|
|
17
17
|
| [`@llblab/pi-clean-room`](https://github.com/llblab/pi-clean-room) | `0.3.0` | Isolated nested Pi TUI with named npm extensions and compatible model selection |
|
|
18
18
|
| [`@llblab/pi-codex-usage`](https://github.com/llblab/pi-codex-usage) | `0.12.1` | Shared Codex quota/Business credit status and persistent priority Fast toggle, mirrored in Telegram |
|
|
19
19
|
| [`@llblab/pi-grow-loop`](https://github.com/llblab/pi-grow-loop) | `0.9.0` | Visible continuation scheduling and bounded worker Skills through compiled, manifest-owned resources |
|
|
20
|
-
| [`@llblab/pi-state-flow`](https://github.com/llblab/pi-state-flow) | `0.
|
|
20
|
+
| [`@llblab/pi-state-flow`](https://github.com/llblab/pi-state-flow) | `0.26.0` | Scoped context/memory compiler with step-independent current memory, stable Passive/Active modes and visible blocked-state status |
|
|
21
21
|
| [`@llblab/pi-telegram`](https://github.com/llblab/pi-telegram) | `0.52.0` | Telegram companion with Workspace Restore, routing lifetime, resilient runtime storage, follower Threads, files, voice, and controls |
|
|
22
22
|
| [`@llblab/skills`](https://github.com/llblab/skills) | `1.15.0` | Portable workflows for engineering, review, design, context maintenance, and other focused tasks |
|
|
23
23
|
|
|
@@ -25,7 +25,7 @@ Versions are exact by design. An upstream release does not change an installed k
|
|
|
25
25
|
|
|
26
26
|
## Install
|
|
27
27
|
|
|
28
|
-
Requires **Pi 1.0.0+** and **Node.js 22.19.0+**. State Flow requires its canonical checkpoint/tail storage format and does not convert unsupported stores in place. Preserve existing stores and consult the [owning package's storage guidance](https://github.com/llblab/pi-state-flow/blob/v0.
|
|
28
|
+
Requires **Pi 1.0.0+** and **Node.js 22.19.0+**. State Flow requires its canonical checkpoint/tail storage format and does not convert unsupported stores in place. Preserve existing stores and consult the [owning package's storage guidance](https://github.com/llblab/pi-state-flow/blob/v0.26.0/docs/usage.md#moving-a-store-and-supported-formats) before changing installations.
|
|
29
29
|
|
|
30
30
|
From npm:
|
|
31
31
|
|
|
@@ -45,7 +45,7 @@ Prefer the kit instead of separately loading the same packages. If you already u
|
|
|
45
45
|
|
|
46
46
|
## Development
|
|
47
47
|
|
|
48
|
-
The `0.
|
|
48
|
+
The `0.29.0` composition includes State Flow `0.26.0` with step-independent current memory and stable modes; all other pins, resources and load order remain unchanged. Telegram runtime storage now uses `tmp/pi-telegram` without migrating the old directory. Drain the prompt queue or accept losing waiting work before reload/restart; damaged-state reset discards all profiles' runtime continuity. Windows Restore remains fail-closed without strict journal evidence. `npm run validate` checks exact installed pins, declared resources, dependency audit and bundled inventory. It does not certify installed-client rendering; carried checks remain in [Backlog](./BACKLOG.md).
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
51
|
npm install
|
|
@@ -18,12 +18,12 @@ The [relocation ledger](docs/agent-contract-relocation.md) maps every pre-compac
|
|
|
18
18
|
|
|
19
19
|
- Treat canonical scope files as semantic authority and Git only as optional backup. Classify complete, wholly absent, partial and malformed cohorts before recovery; absent shared pairs may initialize only under accepted authority, while incomplete/private evidence fails closed. Never repair through ad-hoc writes. See [storage recovery](docs/usage.md#storage-and-recovery) and [transaction rule](docs/filesystem-recovery.md#transaction-rule).
|
|
20
20
|
- Keep exact regular-file, byte-CAS and lock-serialized publication with cancelable waits, single-use callback-scoped capabilities and guarded rollback. Never hold exclusion across inference, source acquisition or Git; do not steal interrupted locks, claim kernel-atomic multi-file publication or promise power-loss durability. See [asynchronous transaction](docs/architecture.md#asynchronous-storage-transaction) and [durability boundary](docs/filesystem-recovery.md#power-loss-durability).
|
|
21
|
-
- Attach Off branches through native policy bookkeeping only, deferring memory acquisition and recovery diagnostics until explicit Passive/Active. Preserve pending Off forks across cold reload with child-owned native markers, without reading the parent header/store until acquisition.
|
|
21
|
+
- Attach Off branches through native policy bookkeeping only, deferring memory acquisition and recovery diagnostics until explicit Passive/Active. Preserve pending Off forks across cold reload with child-owned native markers, without reading the parent header/store until acquisition. Memory never depends on the Pi step: it is the current same-session JSON state, advanced only by accepted `patch_state`/lifecycle publications. Startup, reload, resume and tree navigation validate and accept current same-session memory; native checkpoints supply only mode and run lifecycle, never a revision to rewind to. A fork copies its parent's current memory into a fresh child owner. Never substitute empty, Git, foreign or fabricated memory when current files are missing, corrupt or contradictory. Only accepted candidates install cache, checkpoint and mode. Unreadable current memory under Active retains Active policy, visibly reports `active (blocked)` and fences live inference through public Abort until accepted Active/Passive or explicit Off; never silently expose native history or an inactive indicator as fallback. See [Pi lifecycle](docs/architecture.md#pi-lifecycle) and [fork contract](docs/fork-contract.md).
|
|
22
22
|
- Persist each material semantic change and its affected revisions exactly once, including accepted Session responses. Optional settled-turn Git backup may capture only already-accepted owned files, leave unrelated index/worktree data intact and push without force or semantic side effects. Defer busy backup when the host provides no settlement operation signal rather than blocking Abort; never move it to `turn_end` or add a durable push queue. Off cancels owned captures/pushes and suppresses late reporting; normal agent-operation completion must not cancel an independently admitted push, and foreign callers' pushes retain ownership. See [optional Git backup](docs/architecture.md#optional-git-backup).
|
|
23
23
|
- Accept one atomic `patch_state` cohort across supplied scopes against current shared memory; reject empty scopes, unknown/retired grammar and model-authored `response`. Correct no-ops create no transition. Enforce the single-call inference barrier before sibling tools execute and retain conservative model-facing reconciliation when a result cannot be predicted. See [model tools](docs/architecture.md#model-tools) and [Pi lifecycle](docs/architecture.md#pi-lifecycle).
|
|
24
24
|
- Reconcile the actual accepted ordinary answer at `turn_end` with response-owned cancellation and one accepted lifecycle publication; do not request private repair inference, ceremonial finalization patches or roll back accepted memory after cancellation. See [Pi lifecycle](docs/architecture.md#pi-lifecycle).
|
|
25
25
|
- Capture specifications without writes at `before_agent_start`, then await one cancellable preparation acceptance before active inference; abort failed context preparation through Pi's public hook. Keep user text at user authority and state as fallible data. Preserve an existing conversation for exactly one bootstrap run, not forever. See [Pi lifecycle](docs/architecture.md#pi-lifecycle) and [pre-inference cancellation](docs/compatibility.md#pre-inference-cancellation).
|
|
26
|
-
- Make Start await coherent current-head acceptance; unaccepted Off-to-Active retains deferred history and cannot confer current-memory authority on a superseding Passive choice. Passive selects local policy before asynchronous runtime-only persistence; preserve its independently owned fork/restoration work. Off instead cancels owned memory waits, clears semantic caches and records only native mode/continuation/fork bookkeeping without canonical I/O. Preserve already accepted publications and carried write fences; failed Passive persistence uses a native fence, never a substitute semantic checkpoint. Off exposes no frozen handoff. See [lifecycle planes](docs/architecture.md#lifecycle-planes) and [lifecycle operations](docs/usage.md#lifecycle-operations).
|
|
26
|
+
- Make Start await coherent current-head acceptance; unaccepted Off-to-Active retains deferred history and cannot confer current-memory authority on a superseding Passive choice. Passive selects local policy before asynchronous runtime-only persistence; preserve its independently owned fork/restoration work. Off instead cancels owned memory waits, clears semantic caches and records only native mode/continuation/fork bookkeeping without canonical I/O. Preserve already accepted publications and carried write fences; failed Passive persistence uses a native fence, never a substitute semantic checkpoint; a later explicit Passive retries current-memory acceptance and clears the fence only after acceptance. Off exposes no frozen handoff. See [lifecycle planes](docs/architecture.md#lifecycle-planes) and [lifecycle operations](docs/usage.md#lifecycle-operations).
|
|
27
27
|
- Request completed-history native compaction only after an accepted non-bootstrap settled run, public usage ≥24,000 tokens and a uniquely captured first-user anchor; retain the complete latest run and foreign context. Use per-request owned markers, cancel stale/inactive owned hooks without default summary fallback, and prevent old completion from clearing a new plan. Await its native callback before returning, and leave Pi manual/threshold compaction and append-only history alone. See [lifecycle planes](docs/architecture.md#lifecycle-planes).
|
|
28
28
|
- Contribute only State Flow's compact normative system-prompt section through Pi's section membrane; refresh it with current mode without overwriting foreign sections, forced-prompt precedence or native message identities. Never invent a continuation scheduler. See [lifecycle planes](docs/architecture.md#lifecycle-planes) and [host context compatibility](docs/compatibility.md#context-tools-and-provider-input).
|
|
29
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Backlog
|
|
2
2
|
|
|
3
|
-
The **0.25.5: Active Restoration Fence and Codemode Compaction** hotfix is prepared;
|
|
3
|
+
The **0.25.5: Active Restoration Fence and Codemode Compaction** hotfix is published (exact-tag workflow, GitHub Release and npm commit verified) and bundled in published Pi Kit 0.27.6. **0.26.0: Stable Modes** is prepared and validated locally but not committed, tagged or published; Pi Kit sync follows its release. Outcomes belong in [CHANGELOG.md](CHANGELOG.md). This backlog retains installed-client gates and deferred decisions.
|
|
4
4
|
|
|
5
5
|
## Out of scope
|
|
6
6
|
|
|
@@ -8,9 +8,12 @@ The **0.25.5: Active Restoration Fence and Codemode Compaction** hotfix is prepa
|
|
|
8
8
|
- Nested `lazy_navigation` and intent-ownership warnings, validation or rejection. Authored missing-deletion hints do not change cascade behavior.
|
|
9
9
|
- Any reduction of lifecycle state; the tagged-union question stays deferred.
|
|
10
10
|
|
|
11
|
+
## 0.26.0 acceptance
|
|
12
|
+
|
|
13
|
+
- **Installed stable-mode smoke (operator-owned).** After separately authorized reload, use disposable storage to confirm `/tree` to an old step and reload keep current memory writable in Active and Passive; a fork copies the parent's current memory; unreadable current files show `active (blocked)` in terminal/Telegram, Passive retries and Off releases inference only. Local/native validation does not certify the installed client.
|
|
14
|
+
|
|
11
15
|
## 0.25.5 acceptance
|
|
12
16
|
|
|
13
|
-
- **Publication.** Run the exact-tag workflow and verify GitHub Release/npm identity, then synchronize and release Pi Kit 0.27.6.
|
|
14
17
|
- **Installed restoration/compaction smoke (operator-owned).** After separately authorized reload, use disposable storage to confirm failed Active restoration blocks provider inference across tree/reload, explicit mode recovery remains available, and native Codemode values/deletions survive completed-history compaction. Local/native tests do not certify the installed client.
|
|
15
18
|
|
|
16
19
|
## Carried gates
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
> Each release keeps at most 8 outcome records of at most 512 characters.
|
|
4
4
|
|
|
5
|
+
## 0.26.0: Stable Modes
|
|
6
|
+
|
|
7
|
+
- `Step-independent memory`: Memory no longer depends on the Pi step. Startup, reload, resume and `/tree` attach the current same-session JSON state; native checkpoints supply only mode and run lifecycle. Old or expired branch points never block or rewind memory. Forks copy the parent's current memory. Past values remain readable through `read_state` offsets within retained history.
|
|
8
|
+
- `Removed boundary restoration (library API)`: With nothing left to rewind, `withRestoreTransaction`, `prepareBoundaryRestore`, `restoreBoundary`, `acceptRestoredOrigin`, `prepareBoundaryFork`, `HistoryBoundaryExpiredError` and the temporal boundary selectors are removed. `withForkTransaction(source, lifecycle, …)` now copies the parent's current memory inside its transaction; `lifecycle` carries only mode/bootstrap. Library consumers attach current memory through `withStartTransaction`.
|
|
9
|
+
- `Stable Passive`: Explicit Passive accepts validated current memory like Active and stays writable across reload, including after a failed mode write. Writes stay paused only while current memory is missing, corrupt, contradictory or unpublishable; failed retries add no duplicate fence.
|
|
10
|
+
- `Truthful blocked status`: Unreadable current memory under Active retains Active policy and shows `active (blocked)` in terminal/Telegram, instead of a hidden fence behind an Off indicator. Active or Passive accepts repaired memory; Off releases inference only. Status explains the block and recovery.
|
|
11
|
+
|
|
5
12
|
## 0.25.5: Active Restoration Fence and Codemode Compaction
|
|
6
13
|
|
|
7
14
|
- `Active restoration fence`: Failed retained Active restoration aborts live inference instead of silently exposing native history under an inactive fallback. Expired tree/reload and contradictory-lineage native tests prove zero provider calls and unchanged memory. Valid selection, accepted Start or explicit Passive/Off releases the fence; historical authority is never substituted.
|
|
@@ -201,16 +201,15 @@ The default store is `~/.pi/agent/state-flow/`, independent of registered source
|
|
|
201
201
|
- Shutdown cancels owned pushes and waits for that repository's active push to close or time out.
|
|
202
202
|
- Commit failures warn locally. Repeated push failures produce one concise warning until a push succeeds, with redacted Git detail kept in the local diagnostic log. Neither failure rejects or rolls back accepted memory.
|
|
203
203
|
- Backup needs a Git commit identity; accepting and persisting state does not.
|
|
204
|
-
- Git history can be inspected separately, but it is not the authority for `read_state` or for
|
|
204
|
+
- Git history can be inspected separately, but it is not the authority for `read_state` or for restoring memory.
|
|
205
205
|
|
|
206
206
|
**Resume, tree navigation and forks:**
|
|
207
207
|
|
|
208
|
-
- Memory
|
|
208
|
+
- **State Flow does not depend on the Pi step.** Memory is the current JSON state of each scope and changes only through accepted `patch_state` calls and run lifecycle. Resume and tree navigation restore the branch's mode, never an older memory revision; Off defers acquisition. Past values stay readable through `read_state` offsets within retained history.
|
|
209
209
|
- A new session gets its own session layer.
|
|
210
|
-
- Supported native forks copy the
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
- Malformed storage, unsafe fork copying and concurrent writes remain fenced.
|
|
210
|
+
- Supported native forks copy the parent's **current** session memory into a new owner without changing the parent's private data.
|
|
211
|
+
- Explicit Active or Passive accepts the validated current memory of that same session; modes stay stable.
|
|
212
|
+
- Missing, malformed or contradictory current files, unsafe fork copying and concurrent writes remain fenced and are never replaced by empty or foreign memory.
|
|
214
213
|
|
|
215
214
|
See [fork support](docs/usage.md#fork-support-and-limits) and [storage recovery](docs/usage.md#storage-and-recovery).
|
|
216
215
|
|
|
@@ -221,9 +220,9 @@ See [fork support](docs/usage.md#fork-support-and-limits) and [storage recovery]
|
|
|
221
220
|
|
|
222
221
|
How mode changes interact with storage:
|
|
223
222
|
|
|
224
|
-
- Selecting Passive switches local policy/context immediately and awaits runtime-only persistence. Passive keeps independently owned
|
|
223
|
+
- Selecting Passive switches local policy/context immediately and awaits runtime-only persistence. Passive keeps independently owned attachment/fork work. If its persistence fails, local policy stays and publication is fenced until a later accepted Active or Passive selection.
|
|
225
224
|
- Off cancels owned memory waits and saves only native mode/continuation/fork bookkeeping, without validating or rewriting canonical storage. It also cancels restoration/fork work and defers later acquisition.
|
|
226
|
-
- Explicit Off inspection may read current stored values through a disposable validated reader. It does not activate memory, install cache or change
|
|
225
|
+
- Explicit Off inspection may read current stored values through a disposable validated reader. It does not activate memory, install cache or change pending fork acquisition. Missing private authority stays unavailable.
|
|
227
226
|
- Active waits for a coherent capture and acceptance; another mode or selection can withdraw its wait.
|
|
228
227
|
|
|
229
228
|
State Flow accepts only the canonical store contract and provides no in-place format converter. Preserve existing data and check the [format boundary](docs/usage.md#moving-a-store-and-supported-formats) before changing versions or moving a store.
|
|
@@ -22,7 +22,7 @@ import { selectedBoundaryFailure, selectRetainedCheckpoint, waitForRecovery } fr
|
|
|
22
22
|
import { TemporalRuntime } from "./runtime.js";
|
|
23
23
|
import { discoverSnapshotData, findAssistantToolBatch, findBranchPolicy, findPassiveStopBoundary, hasPendingFork, hasPriorConversation, hasUncheckpointedConversation, isNewSession, retainsPhysicalSessionProjection, SNAPSHOT_ENTRY_TYPE } from "./session.js";
|
|
24
24
|
import { hasCompiledSkillArtifact, hashSkillSource, registeredSkillResolver, SkillReadTracker } from "./skills.js";
|
|
25
|
-
import {
|
|
25
|
+
import { emptySnapshot, isActiveRestorationBlocked, migrationFailure, preRuntimeCheckpoint } from "./snapshot.js";
|
|
26
26
|
import { emptyState, projectStateForModel } from "./state.js";
|
|
27
27
|
import { compactStatus, detailedStatus, STATUS_KEY } from "./status.js";
|
|
28
28
|
import { PublicationBusyError } from "./storage.js";
|
|
@@ -42,7 +42,6 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
42
42
|
let scopeStates = { global: emptyState(), cwd: emptyState(), session: emptyState() };
|
|
43
43
|
let effectiveState = {};
|
|
44
44
|
let branchStartsWithoutRuntime = false;
|
|
45
|
-
let selectedBoundaryError;
|
|
46
45
|
let modePersistenceError;
|
|
47
46
|
/** One pending inactive-mode persistence; later inactive choices coalesce until it publishes. */
|
|
48
47
|
const inactivePersistence = new OwnedOperationSlot();
|
|
@@ -121,10 +120,11 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
121
120
|
if (modePersistenceError)
|
|
122
121
|
throw new Error(`Memory writes paused after mode change: ${modePersistenceError}; use /state-flow-active`);
|
|
123
122
|
}
|
|
123
|
+
/** Active lifecycle work requires validated memory, not merely a selected Active policy. */
|
|
124
124
|
function isActive() {
|
|
125
|
-
return snapshot.config.mode === "active";
|
|
125
|
+
return snapshot.config.mode === "active" && !isActiveRestorationBlocked(snapshot);
|
|
126
126
|
}
|
|
127
|
-
/**
|
|
127
|
+
/** Pending acquisition has no accepted Active memory yet. */
|
|
128
128
|
function inactiveSelection(mode) {
|
|
129
129
|
return mode === "active" ? config.inactiveMode : mode;
|
|
130
130
|
}
|
|
@@ -390,7 +390,6 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
390
390
|
runtime = undefined;
|
|
391
391
|
snapshot = emptySnapshot("off");
|
|
392
392
|
branchStartsWithoutRuntime = withoutRuntime;
|
|
393
|
-
selectedBoundaryError = undefined;
|
|
394
393
|
modePersistenceError = persistenceError;
|
|
395
394
|
forkInitialization = reason === "fork";
|
|
396
395
|
installScopeStates();
|
|
@@ -408,7 +407,6 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
408
407
|
runtime = createRuntime(ctx);
|
|
409
408
|
installScopeStates();
|
|
410
409
|
branchStartsWithoutRuntime = false;
|
|
411
|
-
selectedBoundaryError = undefined;
|
|
412
410
|
forkInitialization = sessionStartReason === "fork";
|
|
413
411
|
let selection = { kind: "settled" };
|
|
414
412
|
let skipped = 0;
|
|
@@ -439,13 +437,11 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
439
437
|
? { ...selected.checkpoint, mode: sourceFence.mode ?? config.inactiveMode } : selected.checkpoint };
|
|
440
438
|
}
|
|
441
439
|
catch (error) {
|
|
442
|
-
|
|
443
|
-
blockInference: selected.checkpoint.mode === "active" && requestedMode === undefined };
|
|
444
|
-
snapshot = selectedBoundaryFailure(diagnosticText(error), inactiveSelection(selected.checkpoint.mode));
|
|
440
|
+
snapshot = selectedBoundaryFailure(diagnosticText(error), requestedMode ?? selected.checkpoint.mode);
|
|
445
441
|
}
|
|
446
442
|
}
|
|
447
443
|
else if (selected.kind === "boundary") {
|
|
448
|
-
selection = { kind: "
|
|
444
|
+
selection = { kind: "attach", checkpoint: selected.checkpoint };
|
|
449
445
|
}
|
|
450
446
|
else if (selected.kind === "pre-runtime") {
|
|
451
447
|
snapshot = emptySnapshot(selected.mode);
|
|
@@ -503,10 +499,9 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
503
499
|
};
|
|
504
500
|
let accepted = false;
|
|
505
501
|
const failSelection = (error) => {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
snapshot = selectedBoundaryFailure(diagnosticText(error), inactiveSelection(snapshot.config.mode));
|
|
502
|
+
const mode = pending.requestedMode ?? (selection.kind === "auto-start" ? "active"
|
|
503
|
+
: selection.kind === "attach" || selection.kind === "fork" ? selection.checkpoint.mode : snapshot.config.mode);
|
|
504
|
+
snapshot = selectedBoundaryFailure(diagnosticText(error), mode);
|
|
510
505
|
installScopeStates();
|
|
511
506
|
};
|
|
512
507
|
// Install accepted memory before native writes; later ancillary failures cannot revert or replay it.
|
|
@@ -544,9 +539,18 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
544
539
|
: migrationFailure({}, "Current State Flow session memory is unavailable", pending.requestedMode ?? selection.mode);
|
|
545
540
|
installScopeStates();
|
|
546
541
|
}
|
|
547
|
-
else if (selection.kind === "
|
|
548
|
-
|
|
542
|
+
else if (selection.kind === "attach") {
|
|
543
|
+
// Memory is the current same-session files; the Pi checkpoint supplies only mode and run lifecycle.
|
|
544
|
+
await candidate.withStartTransaction((current, publish) => {
|
|
549
545
|
assertCurrent();
|
|
546
|
+
if (!current)
|
|
547
|
+
throw new Error("Current State Flow session memory is unavailable");
|
|
548
|
+
const { checkpoint } = selection;
|
|
549
|
+
const restored = { config: { mode: checkpoint.mode }, meta: {
|
|
550
|
+
step: current.meta.step,
|
|
551
|
+
...(checkpoint.bootstrap ? { bootstrap: true } : {}),
|
|
552
|
+
...(checkpoint.specification === undefined ? {} : { specification: checkpoint.specification }),
|
|
553
|
+
} };
|
|
550
554
|
// Canceled preparation or boundary continuation may have no specification. Retain uncompiled native context.
|
|
551
555
|
if (restored.config.mode === "active" && restored.meta.specification === undefined
|
|
552
556
|
&& retainsPhysicalSessionProjection(reason) && hasUncheckpointedConversation(ctx.sessionManager.getBranch()))
|
|
@@ -557,6 +561,7 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
557
561
|
}, signal);
|
|
558
562
|
}
|
|
559
563
|
else if (selection.kind === "fork") {
|
|
564
|
+
// The runtime copies the parent's current memory; the checkpoint supplies only child mode/bootstrap.
|
|
560
565
|
await candidate.withForkTransaction(selection.source, selection.checkpoint, (child, publish) => {
|
|
561
566
|
assertCurrent();
|
|
562
567
|
// Mode is selected independently of creating the child's private memory.
|
|
@@ -601,8 +606,9 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
601
606
|
return;
|
|
602
607
|
}
|
|
603
608
|
settleSelection(ctx, reason, notifyRecovery, skipped, selected !== placeholder);
|
|
604
|
-
if (snapshot.config.mode
|
|
609
|
+
if (snapshot.config.mode === "off" || isActive() || runtime?.view)
|
|
605
610
|
return;
|
|
611
|
+
// Unavailable Active memory may expose shared reads, never substitute private memory or model context.
|
|
606
612
|
const passive = await loadPassiveView(ctx, signal, isCurrent, notifyRecovery);
|
|
607
613
|
if (passive === undefined)
|
|
608
614
|
return;
|
|
@@ -647,10 +653,7 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
647
653
|
function settleSelection(ctx, reason, notifyRecovery, skipped, selectedMemory) {
|
|
648
654
|
const failure = !isActive() && snapshot.meta.validation?.attempt === 0 ? snapshot.meta.validation.error : undefined;
|
|
649
655
|
if (failure !== undefined && notifyRecovery && !modePersistenceError) {
|
|
650
|
-
|
|
651
|
-
notifyProblem(ctx, "State Flow history is outside the retained temporal window; /state-flow-active can use current session memory.", "warning");
|
|
652
|
-
else
|
|
653
|
-
notifyProblem(ctx, `State Flow restore failed: ${failure}`, "error");
|
|
656
|
+
notifyProblem(ctx, `State Flow restore failed: ${failure}`, "error");
|
|
654
657
|
}
|
|
655
658
|
const continuation = selectedMemory ? selectedContinuation(ctx, reason) : undefined;
|
|
656
659
|
if (continuation !== undefined) {
|
|
@@ -891,19 +894,23 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
891
894
|
return { ok: false, message, signal: AbortSignal.any([pending.signal, sharedInspectionLifetime.signal]) };
|
|
892
895
|
}
|
|
893
896
|
}
|
|
894
|
-
|
|
897
|
+
/** Explicit Active or Passive accepts validated current same-session memory without claiming unavailable history. */
|
|
898
|
+
async function activateCurrentState(ctx, pending, mode = "active", owns = () => startActivation.current?.controller === pending) {
|
|
895
899
|
let selected = runtime;
|
|
896
900
|
const owner = ctx.sessionManager.getSessionId();
|
|
897
901
|
const sameSession = sessionIdentity(ctx);
|
|
898
|
-
const
|
|
902
|
+
const policy = () => `${snapshot.config.mode}:${isActive()}`;
|
|
903
|
+
const initialPolicy = policy();
|
|
904
|
+
const acceptedPolicy = `${mode}:${mode === "active"}`;
|
|
905
|
+
const active = mode === "active";
|
|
899
906
|
let accepted = false;
|
|
900
907
|
let receipt = AbortSignal.any([pending.signal, sharedInspectionLifetime.signal]);
|
|
901
908
|
const signal = ctx.signal ? AbortSignal.any([pending.signal, ctx.signal]) : pending.signal;
|
|
902
|
-
const isCurrent = () =>
|
|
903
|
-
&& sameSession() &&
|
|
909
|
+
const isCurrent = () => owns() && !signal.aborted && runtime === selected && !shuttingDown
|
|
910
|
+
&& sameSession() && policy() === (accepted ? acceptedPolicy : initialPolicy);
|
|
904
911
|
const superseded = () => {
|
|
905
912
|
pending.abort();
|
|
906
|
-
return { ok: false, message: "State Flow activation was superseded", signal: pending.signal };
|
|
913
|
+
return { ok: false, message: active ? "State Flow activation was superseded" : "State Flow mode change was superseded", signal: pending.signal };
|
|
907
914
|
};
|
|
908
915
|
try {
|
|
909
916
|
const activation = createRuntime(ctx);
|
|
@@ -918,29 +925,32 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
918
925
|
signal.throwIfAborted();
|
|
919
926
|
if (!isCurrent())
|
|
920
927
|
throw new Error("State Flow activation selection changed while awaiting publication");
|
|
921
|
-
if (!current && !branchStartsWithoutRuntime)
|
|
928
|
+
if (!current && (!active || !branchStartsWithoutRuntime))
|
|
922
929
|
throw new Error(snapshot.meta.validation?.error ?? "Current State Flow session memory is unavailable");
|
|
923
930
|
const boundary = deferred && retainsPhysicalSessionProjection(deferred.reason)
|
|
924
931
|
? findPassiveStopBoundary(ctx.sessionManager.getBranch(), owner, PASSIVE_STOP_ENTRY_TYPE) : undefined;
|
|
925
932
|
const bootstrap = hasPriorConversation(ctx.sessionManager.getBranch()) || passiveContinuation !== undefined || boundary !== undefined;
|
|
926
|
-
const activated =
|
|
927
|
-
|
|
933
|
+
const activated = !active ? deactivateEpisode(current, "passive")
|
|
934
|
+
: current ? resumeEpisode(current, bootstrap) : startEpisode(bootstrap);
|
|
935
|
+
const resumedWrites = modePersistenceError !== undefined;
|
|
928
936
|
publish(activated);
|
|
929
937
|
accepted = true;
|
|
930
|
-
|
|
938
|
+
// Passive acceptance runs inside its own inactive-persistence owner.
|
|
939
|
+
if (active)
|
|
940
|
+
inactivePersistence.cancel();
|
|
931
941
|
runtime = selected = activation;
|
|
932
942
|
snapshot = activated;
|
|
933
943
|
activeContext = ctx;
|
|
934
|
-
selectedBoundaryError = undefined;
|
|
935
944
|
modePersistenceError = undefined;
|
|
936
945
|
installScopeStates();
|
|
937
946
|
const continuation = passiveContinuation ?? bootstrapContinuation ?? (deferred ? selectedContinuation(ctx, deferred.reason) : undefined);
|
|
938
947
|
deferredBranch = undefined;
|
|
939
948
|
clearRunTransient();
|
|
940
949
|
contextProjection.reset();
|
|
941
|
-
passiveContinuation = undefined;
|
|
942
|
-
bootstrapContinuation = snapshot.meta.bootstrap ? continuation : undefined;
|
|
943
|
-
|
|
950
|
+
passiveContinuation = active ? undefined : continuation;
|
|
951
|
+
bootstrapContinuation = active && snapshot.meta.bootstrap ? continuation : undefined;
|
|
952
|
+
if (active)
|
|
953
|
+
deferInferencePreparation();
|
|
944
954
|
receipt = AbortSignal.any([pending.signal, sharedInspectionLifetime.signal]);
|
|
945
955
|
recordPublication();
|
|
946
956
|
syncStateFlowTools();
|
|
@@ -950,20 +960,25 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
950
960
|
pi.appendEntry(PASSIVE_STOP_ENTRY_TYPE, { reset: true, owner });
|
|
951
961
|
}
|
|
952
962
|
appendCheckpoint();
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
963
|
+
if (!active) {
|
|
964
|
+
if (resumedWrites)
|
|
965
|
+
ctx.ui.notify("State Flow passive; memory writes resumed from current session memory.", "info");
|
|
966
|
+
return { ok: true, message: "State Flow passive", signal: receipt };
|
|
967
|
+
}
|
|
968
|
+
ctx.ui.notify(snapshot.meta.bootstrap
|
|
969
|
+
? "State Flow active. The next complete agent run will migrate active context into state."
|
|
970
|
+
: "State Flow active. The next prompt starts a stateful agent run.", "info");
|
|
958
971
|
return { ok: true, message: "State Flow active", signal: receipt };
|
|
959
|
-
}, signal, branchStartsWithoutRuntime);
|
|
972
|
+
}, signal, active && branchStartsWithoutRuntime);
|
|
960
973
|
return isCurrent() ? result : superseded();
|
|
961
974
|
}
|
|
962
975
|
catch (error) {
|
|
963
976
|
if (!isCurrent())
|
|
964
977
|
return superseded();
|
|
965
|
-
const message = conciseDiagnostic(`${accepted ?
|
|
966
|
-
|
|
978
|
+
const message = conciseDiagnostic(`${accepted ? `State Flow ${mode}; lifecycle update failed` : active ? "State Flow activation failed" : "State Flow passive acceptance failed"}: ${diagnosticText(error)}`);
|
|
979
|
+
// Failed Passive acceptance falls back to its caller's write-fence report.
|
|
980
|
+
if (active || accepted)
|
|
981
|
+
notifyProblem(ctx, message, accepted ? "warning" : "error");
|
|
967
982
|
return { ok: accepted, message, signal: receipt };
|
|
968
983
|
}
|
|
969
984
|
}
|
|
@@ -990,11 +1005,13 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
990
1005
|
ctx.ui.notify(detailedStatus(snapshot, statusDiagnostics(ctx)), "info");
|
|
991
1006
|
},
|
|
992
1007
|
});
|
|
1008
|
+
/** Unavailable selection or failed persistence needs current-memory acceptance, not a sticky Passive write fence. */
|
|
1009
|
+
function passiveRecoveryNeeded(mode) {
|
|
1010
|
+
return mode === "passive" && (modePersistenceError !== undefined || snapshot.meta.validation?.attempt === 0);
|
|
1011
|
+
}
|
|
993
1012
|
/** Local policy, tools and UI change before any canonical wait. */
|
|
994
1013
|
function applyInactiveMode(ctx, mode) {
|
|
995
1014
|
snapshot = deactivateEpisode(snapshot, mode);
|
|
996
|
-
if (selectedBoundaryError)
|
|
997
|
-
selectedBoundaryError.blockInference = false;
|
|
998
1015
|
clearRunTransient();
|
|
999
1016
|
syncStateFlowTools();
|
|
1000
1017
|
updateUi(ctx);
|
|
@@ -1027,7 +1044,7 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
1027
1044
|
if (snapshot.config.mode === mode) {
|
|
1028
1045
|
const retained = selectRetainedCheckpoint(discoverSnapshotData(ctx.sessionManager.getBranch()).candidates, config.inactiveMode);
|
|
1029
1046
|
const recordedMode = retained.kind === "pre-runtime" ? retained.mode : retained.kind === "boundary" ? retained.checkpoint.mode : undefined;
|
|
1030
|
-
if (modePersistenceError || recordedMode === mode)
|
|
1047
|
+
if (!passiveRecoveryNeeded(mode) && (modePersistenceError || recordedMode === mode))
|
|
1031
1048
|
return Promise.resolve({ ok: true, message: `State Flow is already ${mode}` });
|
|
1032
1049
|
}
|
|
1033
1050
|
inactivePersistence.cancel();
|
|
@@ -1081,7 +1098,6 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
1081
1098
|
acquisition.reset();
|
|
1082
1099
|
runtime = undefined;
|
|
1083
1100
|
snapshot = emptySnapshot("off");
|
|
1084
|
-
selectedBoundaryError = undefined;
|
|
1085
1101
|
branchStartsWithoutRuntime = preRuntime;
|
|
1086
1102
|
forkInitialization = pendingFork;
|
|
1087
1103
|
deferredBranch = { owner: address.key, cwd: ctx.cwd, reason: pendingFork ? "fork" : undefined };
|
|
@@ -1124,8 +1140,38 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
1124
1140
|
const wasActive = current.config.mode === "active";
|
|
1125
1141
|
let unfinished = current.meta.specification !== undefined
|
|
1126
1142
|
|| (inferencePreparation.current?.prompt !== undefined && !inferencePreparation.current.accepted);
|
|
1143
|
+
const recoverPassive = passiveRecoveryNeeded(mode);
|
|
1127
1144
|
applyInactiveMode(ctx, mode);
|
|
1128
1145
|
const stoppedAt = Date.now();
|
|
1146
|
+
if (recoverPassive) {
|
|
1147
|
+
const superseded = () => ({ ok: false, message: "State Flow mode change was superseded" });
|
|
1148
|
+
const owns = () => inactivePersistence.owns(pending) && !pending.controller.signal.aborted && !shuttingDown;
|
|
1149
|
+
try {
|
|
1150
|
+
// Join pending read-only recovery so its installation cannot supersede this acceptance.
|
|
1151
|
+
const restoring = branchRestoration.current?.operation;
|
|
1152
|
+
if (restoring)
|
|
1153
|
+
await waitForRecovery(restoring, pending.controller.signal);
|
|
1154
|
+
}
|
|
1155
|
+
catch {
|
|
1156
|
+
return superseded();
|
|
1157
|
+
}
|
|
1158
|
+
if (!owns())
|
|
1159
|
+
return superseded();
|
|
1160
|
+
// Passive is a stable mode: explicit selection accepts validated current memory instead of keeping a write fence.
|
|
1161
|
+
const recovered = await activateCurrentState(ctx, pending.controller, "passive", () => inactivePersistence.owns(pending));
|
|
1162
|
+
if (recovered.ok)
|
|
1163
|
+
pending.published = true;
|
|
1164
|
+
if (recovered.ok || !owns())
|
|
1165
|
+
return recovered;
|
|
1166
|
+
if (current.config.mode === mode && modePersistenceError) {
|
|
1167
|
+
// The existing native fence already records this policy; report why acceptance still failed.
|
|
1168
|
+
pending.published = true;
|
|
1169
|
+
const message = conciseDiagnostic(`State Flow passive; memory writes remain paused: ${recovered.message}`);
|
|
1170
|
+
notifyProblem(ctx, message, "warning");
|
|
1171
|
+
return { ok: true, message };
|
|
1172
|
+
}
|
|
1173
|
+
selected = runtime;
|
|
1174
|
+
}
|
|
1129
1175
|
if (modePersistenceError) {
|
|
1130
1176
|
// Writes stay paused; the native marker records only the newly selected inactive policy.
|
|
1131
1177
|
pending.published = true;
|
|
@@ -1227,6 +1273,7 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
1227
1273
|
port: {
|
|
1228
1274
|
snapshot: () => ({
|
|
1229
1275
|
mode: snapshot.config.mode,
|
|
1276
|
+
inferenceBlocked: isActiveRestorationBlocked(snapshot),
|
|
1230
1277
|
step: snapshot.meta.step,
|
|
1231
1278
|
revisions: scopeRevisions(),
|
|
1232
1279
|
bootstrap: snapshot.meta.bootstrap === true,
|
|
@@ -1315,7 +1362,7 @@ export default function stateFlowExtension(pi, options = {}) {
|
|
|
1315
1362
|
}
|
|
1316
1363
|
function prepareContext(messages, ctx) {
|
|
1317
1364
|
// Pi continues after hook errors; public Abort fences inference instead of exposing the native history fallback.
|
|
1318
|
-
if (
|
|
1365
|
+
if (isActiveRestorationBlocked(snapshot) && ctx.signal && !shuttingDown) {
|
|
1319
1366
|
ctx.abort();
|
|
1320
1367
|
notifyProblem(ctx, "State Flow inference blocked: Active memory restoration failed. Select a valid branch or use /state-flow-active for current memory; /state-flow-passive or /state-flow-off explicitly permits native context.", "error");
|
|
1321
1368
|
return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type InactiveMode, type RetainedBoundaryCheckpoint, type Snapshot } from "./snapshot.ts";
|
|
1
|
+
import { type InactiveMode, type RetainedBoundaryCheckpoint, type Snapshot, type StateFlowMode } from "./snapshot.ts";
|
|
2
2
|
export type RetainedCheckpointSelection = {
|
|
3
3
|
kind: "boundary";
|
|
4
4
|
checkpoint: RetainedBoundaryCheckpoint;
|
|
@@ -17,4 +17,4 @@ export declare function selectRetainedCheckpoint(candidates: readonly unknown[],
|
|
|
17
17
|
/** Withdraw a caller's join without cancelling independently owned recovery or mode persistence. */
|
|
18
18
|
export declare function waitForRecovery<T>(operation: Promise<T>, signal: AbortSignal): Promise<T>;
|
|
19
19
|
/** A selected boundary that cannot be resolved stays unavailable; callers never fall through to older evidence. */
|
|
20
|
-
export declare function selectedBoundaryFailure(cause: string, mode?:
|
|
20
|
+
export declare function selectedBoundaryFailure(cause: string, mode?: StateFlowMode): Snapshot;
|
|
@@ -2,7 +2,7 @@ import { type SessionAddress } from "./durable.ts";
|
|
|
2
2
|
import { type ArtifactProvenance, type ArtifactProvenanceRegistry } from "./artifact.ts";
|
|
3
3
|
import { publishTemporalStateToFiles } from "./storage.ts";
|
|
4
4
|
import { type AcceptedTransition, type RecentTransitionWindow } from "./history.ts";
|
|
5
|
-
import { type
|
|
5
|
+
import { type RetainedPiCheckpoint, type Snapshot, type StateFlowMode } from "./snapshot.ts";
|
|
6
6
|
import { type MaterializedState, type SemanticState, type ScopedSemanticStates, type ScopedStates, type StateScope } from "./state.ts";
|
|
7
7
|
import { type TemporalState } from "./temporal.ts";
|
|
8
8
|
export type RuntimePublication = ReturnType<typeof publishTemporalStateToFiles>;
|
|
@@ -12,6 +12,11 @@ export interface RuntimePatchTransaction {
|
|
|
12
12
|
readonly provenance: Record<StateScope, ArtifactProvenanceRegistry>;
|
|
13
13
|
publish(snapshot: Snapshot, accepted?: AcceptedTransition, provenance?: Partial<Record<StateScope, Record<string, ArtifactProvenance>>>): RuntimePublication;
|
|
14
14
|
}
|
|
15
|
+
/** Child policy recorded by the native fork; memory always comes from the parent's current files. */
|
|
16
|
+
export interface ForkLifecycle {
|
|
17
|
+
mode: StateFlowMode;
|
|
18
|
+
bootstrap?: true;
|
|
19
|
+
}
|
|
15
20
|
/** A targeted removed scope was deliberately adopted as empty before refusing the stale semantic patch. */
|
|
16
21
|
export declare class SharedScopeRemovalConflictError extends Error {
|
|
17
22
|
readonly scopes: readonly StateScope[];
|
|
@@ -24,7 +29,6 @@ export declare class TemporalRuntime {
|
|
|
24
29
|
private semanticRevision;
|
|
25
30
|
private savedRuntime;
|
|
26
31
|
private transaction;
|
|
27
|
-
private restoredOriginPending;
|
|
28
32
|
private provenanceByScope;
|
|
29
33
|
/** Shared scopes whose wholly absent live basis was accepted after one stale-target refusal. */
|
|
30
34
|
private readonly absentSharedScopes;
|
|
@@ -52,28 +56,9 @@ export declare class TemporalRuntime {
|
|
|
52
56
|
retainedCheckpoint(snapshot: Snapshot): RetainedPiCheckpoint;
|
|
53
57
|
usesCanonicalFiles(): boolean;
|
|
54
58
|
recent(): RecentTransitionWindow;
|
|
55
|
-
/** Prepare a retained session boundary from current canonical files; shared scopes remain live. */
|
|
56
|
-
prepareBoundaryRestore(checkpoint: RetainedBoundaryCheckpoint): {
|
|
57
|
-
snapshot: Snapshot;
|
|
58
|
-
restore: () => Snapshot;
|
|
59
|
-
};
|
|
60
|
-
private prepareBoundaryRestoreBase;
|
|
61
|
-
/** Restore and canonically accept one retained boundary as a single lifecycle operation. */
|
|
62
|
-
restoreBoundary(checkpoint: RetainedBoundaryCheckpoint): {
|
|
63
|
-
snapshot: Snapshot;
|
|
64
|
-
publication: RuntimePublication;
|
|
65
|
-
};
|
|
66
59
|
/** Await a coherent read-only recovery view; this neither activates policy nor accepts publication authority. */
|
|
67
60
|
refreshCurrentMemory(signal?: AbortSignal): Promise<Snapshot | undefined>;
|
|
68
61
|
private loadCurrentMemoryBase;
|
|
69
|
-
/** Copy one retained source-session boundary over the child's current shared scopes. */
|
|
70
|
-
prepareBoundaryFork(source: SessionAddress, checkpoint: RetainedBoundaryCheckpoint): {
|
|
71
|
-
snapshot: Snapshot;
|
|
72
|
-
fork: () => {
|
|
73
|
-
snapshot: Snapshot;
|
|
74
|
-
publication: RuntimePublication;
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
62
|
initialize(snapshot: Snapshot, allowCreateCwd: boolean, expectedShared?: Pick<ScopedStates, "global" | "cwd">, newSessionOrigin?: boolean): RuntimePublication | undefined;
|
|
78
63
|
private initializeOrigin;
|
|
79
64
|
/** Copy the private origin and apply configured retention folding, preserving live shared values/provenance. */
|
|
@@ -95,16 +80,12 @@ export declare class TemporalRuntime {
|
|
|
95
80
|
withPatchTransaction<T>(action: (transaction: RuntimePatchTransaction) => T, signal?: AbortSignal): Promise<T>;
|
|
96
81
|
/** Activate current owned memory; the caller must authorize a wholly absent private origin after waiting. */
|
|
97
82
|
withStartTransaction<T>(action: (current: Snapshot | undefined, publish: (snapshot: Snapshot) => RuntimePublication) => T, signal?: AbortSignal, allowCreateOrigin?: boolean): Promise<T>;
|
|
98
|
-
/**
|
|
99
|
-
|
|
100
|
-
/** Copy exact retained parent authority into an unoccupied child; the caller rechecks native selection after waiting. */
|
|
101
|
-
withForkTransaction<T>(source: SessionAddress, checkpoint: RetainedBoundaryCheckpoint, action: (selected: Snapshot, publish: (snapshot: Snapshot) => RuntimePublication) => T, signal?: AbortSignal): Promise<T>;
|
|
83
|
+
/** Copy the parent's current session memory into an unoccupied child; the caller rechecks native selection after waiting. */
|
|
84
|
+
withForkTransaction<T>(source: SessionAddress, lifecycle: ForkLifecycle, action: (selected: Snapshot, publish: (snapshot: Snapshot) => RuntimePublication) => T, signal?: AbortSignal): Promise<T>;
|
|
102
85
|
private prepareForkCandidate;
|
|
103
86
|
/** Recheck caller policy after waiting, then accept only config/runtime over an already accepted private basis. */
|
|
104
87
|
withLifecycleTransaction<T>(action: (publish: (snapshot: Snapshot) => RuntimePublication) => T, signal?: AbortSignal): Promise<T>;
|
|
105
88
|
private withPublicationTransaction;
|
|
106
|
-
/** Canonically accept a prepared retained-boundary origin before lifecycle-only persistence. */
|
|
107
|
-
acceptRestoredOrigin(snapshot: Snapshot): RuntimePublication;
|
|
108
89
|
publish(snapshot: Snapshot, semantic?: boolean, accepted?: AcceptedTransition, options?: {
|
|
109
90
|
provenance?: Partial<Record<StateScope, Record<string, ArtifactProvenance>>>;
|
|
110
91
|
}): RuntimePublication | undefined;
|