@llblab/pi-kit 0.25.0 → 0.26.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.
Files changed (104) hide show
  1. package/BACKLOG.md +5 -1
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +9 -7
  4. package/node_modules/@llblab/pi-actors/AGENTS.md +2 -0
  5. package/node_modules/@llblab/pi-actors/CHANGELOG.md +4 -1
  6. package/node_modules/@llblab/pi-actors/LICENSE +21 -0
  7. package/node_modules/@llblab/pi-actors/README.md +1 -1
  8. package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +1 -1
  9. package/node_modules/@llblab/pi-actors/package.json +4 -3
  10. package/node_modules/@llblab/pi-claude-usage/AGENTS.md +6 -3
  11. package/node_modules/@llblab/pi-claude-usage/BACKLOG.md +2 -1
  12. package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +8 -0
  13. package/node_modules/@llblab/pi-claude-usage/README.md +48 -3
  14. package/node_modules/@llblab/pi-claude-usage/index.ts +8 -1159
  15. package/node_modules/@llblab/pi-claude-usage/lib/extension.ts +30 -0
  16. package/node_modules/@llblab/pi-claude-usage/lib/fast.ts +24 -0
  17. package/node_modules/@llblab/pi-claude-usage/lib/query.ts +146 -0
  18. package/node_modules/@llblab/pi-claude-usage/lib/status-format.ts +297 -0
  19. package/node_modules/@llblab/pi-claude-usage/lib/status.ts +366 -0
  20. package/node_modules/@llblab/pi-claude-usage/lib/telegram.ts +44 -0
  21. package/node_modules/@llblab/pi-claude-usage/lib/usage-store.ts +221 -0
  22. package/node_modules/@llblab/pi-claude-usage/lib/usage.ts +128 -0
  23. package/node_modules/@llblab/pi-claude-usage/package.json +9 -5
  24. package/node_modules/@llblab/pi-clean-room/AGENTS.md +1 -0
  25. package/node_modules/@llblab/pi-clean-room/CHANGELOG.md +5 -0
  26. package/node_modules/@llblab/pi-clean-room/LICENSE +21 -0
  27. package/node_modules/@llblab/pi-clean-room/README.md +1 -1
  28. package/node_modules/@llblab/pi-clean-room/package.json +3 -2
  29. package/node_modules/@llblab/pi-codex-usage/AGENTS.md +9 -6
  30. package/node_modules/@llblab/pi-codex-usage/BACKLOG.md +2 -1
  31. package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +17 -0
  32. package/node_modules/@llblab/pi-codex-usage/README.md +75 -17
  33. package/node_modules/@llblab/pi-codex-usage/index.ts +8 -1602
  34. package/node_modules/@llblab/pi-codex-usage/lib/extension.ts +25 -0
  35. package/node_modules/@llblab/pi-codex-usage/lib/fast.ts +23 -0
  36. package/node_modules/@llblab/pi-codex-usage/lib/query.ts +368 -0
  37. package/node_modules/@llblab/pi-codex-usage/lib/status-format.ts +347 -0
  38. package/node_modules/@llblab/pi-codex-usage/lib/status.ts +435 -0
  39. package/node_modules/@llblab/pi-codex-usage/lib/telegram.ts +45 -0
  40. package/node_modules/@llblab/pi-codex-usage/lib/usage-store.ts +229 -0
  41. package/node_modules/@llblab/pi-codex-usage/lib/usage.ts +425 -0
  42. package/node_modules/@llblab/pi-codex-usage/package.json +11 -6
  43. package/node_modules/@llblab/pi-command-fast/AGENTS.md +7 -0
  44. package/node_modules/@llblab/pi-command-fast/BACKLOG.md +9 -0
  45. package/node_modules/@llblab/pi-command-fast/CHANGELOG.md +7 -0
  46. package/node_modules/@llblab/pi-command-fast/LICENSE +21 -0
  47. package/node_modules/@llblab/pi-command-fast/README.md +42 -0
  48. package/node_modules/@llblab/pi-command-fast/dist/command.d.ts +8 -0
  49. package/node_modules/@llblab/pi-command-fast/dist/command.js +52 -0
  50. package/node_modules/@llblab/pi-command-fast/dist/index.d.ts +3 -0
  51. package/node_modules/@llblab/pi-command-fast/dist/index.js +3 -0
  52. package/node_modules/@llblab/pi-command-fast/dist/models-json.d.ts +10 -0
  53. package/node_modules/@llblab/pi-command-fast/dist/models-json.js +81 -0
  54. package/node_modules/@llblab/pi-command-fast/package.json +49 -0
  55. package/node_modules/@llblab/pi-grow-loop/AGENTS.md +1 -0
  56. package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +4 -1
  57. package/node_modules/@llblab/pi-grow-loop/LICENSE +21 -0
  58. package/node_modules/@llblab/pi-grow-loop/README.md +1 -1
  59. package/node_modules/@llblab/pi-grow-loop/package.json +3 -2
  60. package/node_modules/@llblab/pi-state-flow/AGENTS.md +6 -5
  61. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +3 -2
  62. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +7 -1
  63. package/node_modules/@llblab/pi-state-flow/LICENSE +21 -0
  64. package/node_modules/@llblab/pi-state-flow/README.md +5 -5
  65. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +1 -1
  66. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +1 -1
  67. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +238 -46
  68. package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +2 -2
  69. package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +16 -5
  70. package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +10 -1
  71. package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +60 -1
  72. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +6 -0
  73. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +8 -5
  74. package/node_modules/@llblab/pi-state-flow/dist/package.json +10 -9
  75. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +11 -7
  76. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +2 -2
  77. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +4 -2
  78. package/node_modules/@llblab/pi-state-flow/docs/usage.md +14 -13
  79. package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +2 -2
  80. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +221 -46
  81. package/node_modules/@llblab/pi-state-flow/lib/git.ts +14 -5
  82. package/node_modules/@llblab/pi-state-flow/lib/session.ts +52 -1
  83. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +7 -5
  84. package/node_modules/@llblab/pi-state-flow/package.json +10 -9
  85. package/node_modules/jsonc-parser/CHANGELOG.md +76 -0
  86. package/node_modules/jsonc-parser/LICENSE.md +21 -0
  87. package/node_modules/jsonc-parser/README.md +364 -0
  88. package/node_modules/jsonc-parser/SECURITY.md +41 -0
  89. package/node_modules/jsonc-parser/lib/esm/impl/edit.js +185 -0
  90. package/node_modules/jsonc-parser/lib/esm/impl/format.js +261 -0
  91. package/node_modules/jsonc-parser/lib/esm/impl/parser.js +659 -0
  92. package/node_modules/jsonc-parser/lib/esm/impl/scanner.js +443 -0
  93. package/node_modules/jsonc-parser/lib/esm/impl/string-intern.js +29 -0
  94. package/node_modules/jsonc-parser/lib/esm/main.d.ts +351 -0
  95. package/node_modules/jsonc-parser/lib/esm/main.js +178 -0
  96. package/node_modules/jsonc-parser/lib/umd/impl/edit.js +201 -0
  97. package/node_modules/jsonc-parser/lib/umd/impl/format.js +275 -0
  98. package/node_modules/jsonc-parser/lib/umd/impl/parser.js +682 -0
  99. package/node_modules/jsonc-parser/lib/umd/impl/scanner.js +456 -0
  100. package/node_modules/jsonc-parser/lib/umd/impl/string-intern.js +42 -0
  101. package/node_modules/jsonc-parser/lib/umd/main.d.ts +351 -0
  102. package/node_modules/jsonc-parser/lib/umd/main.js +194 -0
  103. package/node_modules/jsonc-parser/package.json +37 -0
  104. package/package.json +7 -7
@@ -1,4 +1,4 @@
1
- import { parseRetainedPiCheckpoint } from "./snapshot.js";
1
+ import { parseRetainedPiCheckpoint, readCheckpointMode } from "./snapshot.js";
2
2
  export const SNAPSHOT_ENTRY_TYPE = "state-flow-snapshot";
3
3
  /** Enumerate active-branch snapshots newest-first while containing hostile entries. */
4
4
  export function discoverSnapshotData(branch) {
@@ -16,6 +16,65 @@ export function discoverSnapshotData(branch) {
16
16
  }
17
17
  return { candidates, errors };
18
18
  }
19
+ /** Read native mode policy only; semantic checkpoint validity remains the recovery owner's concern. */
20
+ export function findBranchPolicy(branch, sessionId, stopEntryType, inactiveMode) {
21
+ let stopReset = false;
22
+ for (let index = branch.length - 1; index >= 0; index--) {
23
+ try {
24
+ const entry = branch[index];
25
+ if (entry?.type !== "custom")
26
+ continue;
27
+ if (entry.customType === SNAPSHOT_ENTRY_TYPE) {
28
+ const mode = readCheckpointMode(entry.data, inactiveMode);
29
+ if (mode !== undefined)
30
+ return { mode };
31
+ const data = entry.data;
32
+ if (data?.disabled === true && !Object.hasOwn(data, "mode") && !Object.hasOwn(data, "enabled"))
33
+ return { mode: inactiveMode };
34
+ }
35
+ else if (stopEntryType !== undefined && entry.customType === stopEntryType) {
36
+ const data = entry.data;
37
+ if (!data || stopReset || (sessionId === undefined ? typeof data.owner !== "string" || !data.owner.trim() : data.owner !== sessionId))
38
+ continue;
39
+ if (data.reset === true) {
40
+ stopReset = true;
41
+ continue;
42
+ }
43
+ if (Number.isSafeInteger(data.at) && data.at >= 0 && data.memoryDeferred === true && data.mode === "off") {
44
+ return { mode: "off", ...(typeof data.persistenceError === "string" && data.persistenceError.trim() ? { persistenceError: data.persistenceError } : {}) };
45
+ }
46
+ if (Number.isSafeInteger(data.at) && data.at >= 0 && typeof data.persistenceError === "string" && data.persistenceError.trim()) {
47
+ return { mode: data.mode === "off" || data.mode === "passive" ? data.mode : inactiveMode, persistenceError: data.persistenceError };
48
+ }
49
+ }
50
+ }
51
+ catch {
52
+ // Malformed native policy cannot prevent another explicit retained choice from being read.
53
+ }
54
+ }
55
+ return undefined;
56
+ }
57
+ /** Native policy bookkeeping retains an unacquired fork across extension reloads. */
58
+ export function hasPendingFork(branch, sessionId, entryType) {
59
+ for (let index = branch.length - 1; index >= 0; index--) {
60
+ try {
61
+ const entry = branch[index];
62
+ if (entry?.type !== "custom" || entry.customType !== entryType)
63
+ continue;
64
+ const data = entry.data;
65
+ if (data?.owner !== sessionId)
66
+ continue;
67
+ if (data.reset === true)
68
+ return false;
69
+ if (data.forkPending === true)
70
+ return true;
71
+ }
72
+ catch {
73
+ // Unrelated native entries grant no fork authority.
74
+ }
75
+ }
76
+ return false;
77
+ }
19
78
  export function snapshotDataNewestFirst(branch) {
20
79
  return discoverSnapshotData(branch).candidates;
21
80
  }
@@ -14,6 +14,12 @@ export declare function isStateFlowMode(value: unknown): value is StateFlowMode;
14
14
  export interface SnapshotConfig {
15
15
  mode: StateFlowMode;
16
16
  }
17
+ /**
18
+ * Read only mode policy, without validating or accessing semantic checkpoint metadata.
19
+ * Missing/invalid policy stays undecided; callers must not treat this as restoration proof.
20
+ * Legacy `enabled:false` follows the caller's inactive policy.
21
+ */
22
+ export declare function readCheckpointMode(value: unknown, inactiveMode?: InactiveMode): StateFlowMode | undefined;
17
23
  interface LegacyValidationFeedback {
18
24
  attempt: number;
19
25
  error: string;
@@ -15,10 +15,13 @@ export function isStateFlowMode(value) {
15
15
  return value === "active" || value === "passive" || value === "off";
16
16
  }
17
17
  /**
18
- * Read-only compatibility for session config and native checkpoints written before `mode`:
19
- * `enabled:true` stays active; `enabled:false` stays the caller's inactive policy.
18
+ * Read only mode policy, without validating or accessing semantic checkpoint metadata.
19
+ * Missing/invalid policy stays undecided; callers must not treat this as restoration proof.
20
+ * Legacy `enabled:false` follows the caller's inactive policy.
20
21
  */
21
- function decodeLegacyMode(value, inactiveMode) {
22
+ export function readCheckpointMode(value, inactiveMode = "passive") {
23
+ if (!isObject(value))
24
+ return undefined;
22
25
  if (Object.hasOwn(value, "mode"))
23
26
  return Object.hasOwn(value, "enabled") || !isStateFlowMode(value.mode) ? undefined : value.mode;
24
27
  return typeof value.enabled === "boolean" ? value.enabled ? "active" : inactiveMode : undefined;
@@ -82,7 +85,7 @@ export function parseSessionRuntime(config, runtimeSource, cwd, sessionId) {
82
85
  let runtime;
83
86
  try {
84
87
  const settings = JSON.parse(config);
85
- const mode = isObject(settings) && Object.keys(settings).length === 1 ? decodeLegacyMode(settings, "passive") : undefined;
88
+ const mode = isObject(settings) && Object.keys(settings).length === 1 ? readCheckpointMode(settings, "passive") : undefined;
86
89
  if (mode === undefined)
87
90
  throw new Error("Invalid State Flow runtime configuration or counters");
88
91
  runtime = { config: { mode }, meta: JSON.parse(runtimeSource) };
@@ -166,7 +169,7 @@ export function parseRetainedPiCheckpoint(value, inactiveMode = "passive") {
166
169
  if (keys.length === 1 && (value.mode === "passive" || value.mode === "off"))
167
170
  return { mode: value.mode };
168
171
  const allowed = new Set(["boundary", "mode", "enabled", "step", "bootstrap", "specification"]);
169
- const mode = decodeLegacyMode(value, inactiveMode);
172
+ const mode = readCheckpointMode(value, inactiveMode);
170
173
  if (keys.some((key) => !allowed.has(key))
171
174
  || typeof value.boundary !== "string" || value.boundary.trim().length === 0
172
175
  || mode === undefined
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@llblab/pi-state-flow",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
+ "license": "MIT",
4
5
  "private": false,
5
6
  "description": "Incremental scoped state/context/memory compiler for Pi, inspired by SKILL.state",
6
7
  "keywords": [
@@ -66,16 +67,16 @@
66
67
  "node": ">=22.19.0"
67
68
  },
68
69
  "peerDependencies": {
69
- "@earendil-works/pi-agent-core": ">=0.87.0",
70
- "@earendil-works/pi-ai": ">=0.87.0",
71
- "@earendil-works/pi-coding-agent": ">=0.87.0",
72
- "@earendil-works/pi-tui": ">=0.87.0"
70
+ "@earendil-works/pi-agent-core": ">=1.0.0",
71
+ "@earendil-works/pi-ai": ">=1.0.0",
72
+ "@earendil-works/pi-coding-agent": ">=1.0.0",
73
+ "@earendil-works/pi-tui": ">=1.0.0"
73
74
  },
74
75
  "devDependencies": {
75
- "@earendil-works/pi-agent-core": "0.87.0",
76
- "@earendil-works/pi-ai": "0.87.0",
77
- "@earendil-works/pi-coding-agent": "0.87.0",
78
- "@earendil-works/pi-tui": "0.87.0",
76
+ "@earendil-works/pi-agent-core": "1.0.0",
77
+ "@earendil-works/pi-ai": "1.0.0",
78
+ "@earendil-works/pi-coding-agent": "1.0.0",
79
+ "@earendil-works/pi-tui": "1.0.0",
79
80
  "@types/node": "^26.4.0",
80
81
  "typescript": "^7.0.2"
81
82
  }
@@ -105,15 +105,17 @@ A proven pre-runtime branch has no accepted runtime to persist: an inactive new-
105
105
 
106
106
  Explicit Start independently prepares the validated current same-session canonical cohort rather than replaying the selected Pi pointer. Active/passive or unfinished runtime metadata and expired/pre-runtime selections do not erase current private memory or block activation. `withStartTransaction` acquires exclusion before capture and binds private stream identity to current runtime lineage, with one synchronous, single-use exact-cohort acceptance before installation. Pending repeats share the same operation. Current branch/physical identity, initialization permission and bootstrap context are rechecked after waiting; Stop, selection and shutdown withdraw obsolete activation. Only acceptance enables the new mode, clears Stop fences and cancels older Stop persistence. Caches, preparation policy and one native checkpoint install before yielding without a second persistence call; a later failure cannot roll them back. Commands, deferred settled Start and Telegram await completion, and presentation receipts for both success and failure revoke with selection. It preserves private values, artifact provenance, independent revisions and step, discards the old unfinished specification, and retains available aligned history within the configured limit. Incompatible but independently valid live shared streams require a fresh origin rather than invented cross-writer history. An empty session origin is allowed only with wholly absent private authority and initialization-safe branch provenance; incomplete or contradictory evidence remains closed. Initial physical fork copying still requires its exact-source contract; an already accepted child can activate its own current memory without recopying its parent. Repeated Start while already active does not change the current run or pending response reconciliation.
107
107
 
108
- Lifecycle-only persistence for accepted runtimes reconciles valid live global/CWD drift before publishing the current session's config/runtime pair. Changed shared streams establish a fresh proven origin, not a semantic transition; the runtime adopts their already-advanced owner revisions without incrementing them, while semantic files and all provenance files remain unchanged. Cached reads may constrain wider tails left by another writer without rewriting them. Same-session file races and explicitly requested stale provenance writes still fail closed under CAS. The host refreshes its scope cache after adoption: Stop freezes the accepted view, and new-run registered-artifact maintenance runs against that view before inference.
108
+ The Pi adapter's Passive lifecycle-only persistence for accepted runtimes reconciles valid live global/CWD drift before publishing the current session's config/runtime pair. Changed shared streams establish a fresh proven origin, not a semantic transition; the runtime adopts their already-advanced owner revisions without incrementing them, while semantic files and all provenance files remain unchanged. Cached reads may constrain wider tails left by another writer without rewriting them. Same-session file races and explicitly requested stale provenance writes still fail closed under CAS. The host refreshes its scope cache after adoption: Stop freezes the accepted view, and new-run registered-artifact maintenance runs against that view before inference.
109
109
 
110
- Passive/Off selection immediately applies the selected tools/context policy and disables active response/compaction behavior before attempting canonical persistence. For accepted runtimes it freezes the passive handoff immediately, then awaits `withLifecycleTransaction` with Stop-owned cancellation and any available Pi operation signal. Pending inactive choices share one acceptance of the latest mode. After acquisition, recheck runtime/physical owner/policy and derive the snapshot from current lifecycle state, including an intervening same-instance passive patch. Successful publication installs the adopted shared cache, final handoff and native checkpoint before yielding. Session/tree selection, shutdown or accepted Start revoke obsolete Stop work; a failed Start leaves it pending. Shutdown drains the canceled operation. A post-acceptance lifecycle failure never restores old metadata or retries native writes. If persistence fails, it keeps accepted cached memory and all available native context, then records `owner`, the selected inactive `mode`, `persistenceError` and `preserveContext: true` in the existing native passive-stop marker. This is a same-session policy override and write fence, not semantic authority or a substitute checkpoint. No canonical failure is repaired by resetting memory. Tree/reload/resume with that pending marker use `TemporalRuntime.refreshCurrentMemory()` to validate and read current memory without historical restoration or publication; unavailable evidence remains unavailable. A later accepted checkpoint supersedes the fence, while preserving the context boundary for bootstrap. Repeating the same degraded choice is inert; another inactive choice updates only native policy and preserves the fence. An in-flight read-only recovery applies the latest choice, never an older captured mode. Successful explicit Start uses the same detached validation path under CAS before clearing the fence. Status and inspection distinguish accepted cached/read-only memory from unavailable publication. If Pi's own trace is unwritable, the local disablement still precedes the error, but durable fallback cannot be guaranteed.
110
+ Passive selection immediately applies the selected tools/context policy and disables active response/compaction behavior before attempting canonical persistence. For accepted runtimes it freezes the passive handoff immediately, then awaits `withLifecycleTransaction` with Stop-owned cancellation and any available Pi operation signal. Pending inactive choices share one acceptance of the latest mode. After acquisition, recheck runtime/physical owner/policy and derive the snapshot from current lifecycle state, including an intervening same-instance passive patch. Successful publication installs the adopted shared cache, final handoff and native checkpoint before yielding. Off, session/tree selection, shutdown or accepted Start revoke obsolete Passive persistence; a failed Start leaves it pending. Shutdown drains the canceled operation. A post-acceptance lifecycle failure never restores old metadata or retries native writes. If persistence fails, it keeps accepted cached memory and all available native context, then records `owner`, the selected inactive `mode`, `persistenceError` and `preserveContext: true` in the existing native passive-stop marker. This is a same-session policy override and write fence, not semantic authority or a substitute checkpoint. No canonical failure is repaired by resetting memory. Memory-enabled tree/reload/resume with that pending marker use `TemporalRuntime.refreshCurrentMemory()` to validate and read current memory without historical restoration or publication; unavailable evidence remains unavailable. A later accepted checkpoint supersedes the fence, while preserving the context boundary for bootstrap. Repeating the same degraded choice is inert; another inactive choice updates only native policy and preserves the fence. An in-flight read-only recovery retains a repeated Passive choice; Off cancels it before further acquisition. Successful explicit Start uses the same detached validation path under CAS before clearing the fence. Status and inspection distinguish accepted cached/read-only memory from unavailable publication. If Pi's own trace is unwritable, the local disablement still precedes the error, but durable fallback cannot be guaranteed.
111
+
112
+ Off uses a separate local owner: it aborts restore/fork, activation, preparation, response, model-patch and Passive-persistence lifetimes, clears cached semantic views and records native policy without any canonical transaction. A usable cached accepted boundary may be bookmarked read-only in a native Off checkpoint; an unusable cached bookmark never prevents local Off or authorizes replacement memory. The owner-local stop marker's `memoryDeferred: true` plus `mode: "off"` selects Off even when canonical runtime mode is still Active/Passive. It also retains continuation timestamps, a carried write fence and an unaccepted fork marker when needed. Exact selected-boundary restoration remains separate from current-memory Active; already accepted canonical bytes are not rolled back. Late canceled model patches do not log memory diagnostics. Automatic context, Skill/artifact tracking, queued tool failures, settlement and shutdown callbacks remain memory-inert in Off, including with opt-in logging. Only native policy bookkeeping and release of already-owned protocol resources survive.
111
113
 
112
114
  The existing native passive-stop marker stores the stop timestamp and an optional `from` timestamp identifying the active run's first user message. Native user events are observed independently of State Flow enablement, so activating mid-tool and repeated mode changes retain the actual first-user timestamp. Native user-run preparation and session-start/tree events reset capture; semantic mode changes do not. The same marker accepts optional `preserveContext: true` when compilation is unfinished and no narrower incoming boundary is sufficient; omitted flags keep legacy selection behavior. This projection flag creates no semantic storage authority. Transcript bodies remain in Pi's trace rather than being copied into another state store. A recorded active anchor uses the same conservative selector as active inference: if native compaction removed it, or matching is ambiguous/nonfinite, retain the available native summary and tool trajectory without guessing a post-stop boundary or rereading discarded raw entries. An interrupted run keeps its captured anchor even after Pi becomes idle; if capture is unavailable, Stop preserves all available context. Completed idle runs and legacy markers without an active anchor or preservation flag retain only post-stop conversation plus foreign custom context. The initial system prompt is composed at `before_agent_start`; Stop does not rewrite an already-issued request, while the next provider request receives the current owned protocol section as described below.
113
115
 
114
116
  The current user specification stays at user authority and appears only in synthetic user runtime context. State is fallible assistant-produced data. Active/passive protocol contributes to Pi's native `state_flow` system-prompt section at `before_agent_start`, rather than forcing the entire prompt. Later companion sections and `context_with_system` transformations compose normally; explicit foreign forced prompts retain Pi's documented precedence. Native section diffs remove/reinstate the initial protocol across user requests. At `context_with_system`, the context domain also refreshes only the owned section from current enablement/bootstrap/passive policy, covering Stop/Start inside the same tool loop and accepted-boundary continuations. Unchanged effective protocol reuses the original array without relocating native deltas; a changed mode preserves foreign sections/content/tools and conversation identity/order without mutating native frames or creating missing system authority. Accepted completion removes the specification, not memory availability: a companion's actionable `turn_end` or `agent_before_settle` continuation can request another inference without `before_agent_start`. Every enabled request still gets one current-memory projection, omitting an absent specification and using the captured native anchor when available; no synthetic user run, persisted continuation field or State Flow scheduler is created. Completed trajectories leave model context at user-run boundaries, while Pi's full JSONL trace remains inspectable.
115
117
 
116
- After an accepted non-bootstrap run settles with no queued input, State Flow may request native manual compaction under a generation-private marker when public `getContextUsage()` reports at least 24,000 tokens. The settled handler awaits native completion/error callbacks before returning, so Pi can dispatch deferred companion prompts after every observer finishes without racing an in-flight manual compaction. This waits for one existing native operation, without adding a timer, queue or second continuation owner. This token signal provides a modest margin above Pi's default 20,000-token retained suffix; Pi still owns preparation and may benignly decline when custom settings leave no compactable prefix. The extension supplies no model-generated state body: it forwards the existing `runAnchorTimestamp` to the planner, requires one matching native user entry, and keeps the complete accepted run including later steering and tools. A missing, ambiguous, or unanswered anchor produces no request; the planner never falls back to the nearest user message. Compaction details still contain only the retained semantic boundary/step. `buildContextEntries()` then omits the older completed prefix while append-only JSONL/tree history remains intact.
118
+ After an accepted non-bootstrap run settles with no queued input, State Flow may request native manual compaction under an extension-private prefix and a fresh per-request marker when public `getContextUsage()` reports at least 24,000 tokens. The settled handler awaits native completion/error callbacks before returning, so Pi can dispatch deferred companion prompts after every observer finishes without racing an in-flight manual compaction. The `state-flow-boundary:` namespace identifies owned requests even after extension recreation. Inactive, missing-plan, completed or superseded owned requests return cancellation even after transient-plan cleanup, never default model-summary fallback. Callback completion clears only its own marker's plan; an old callback cannot clear a new request. Foreign manual and native threshold/overflow hooks remain untouched. This waits for one existing native operation, without adding a timer, queue or second continuation owner. This token signal provides a modest margin above Pi's default 20,000-token retained suffix; Pi still owns preparation and may benignly decline when custom settings leave no compactable prefix. The extension supplies no model-generated state body: it forwards the existing `runAnchorTimestamp` to the planner, requires one matching native user entry, and keeps the complete accepted run including later steering and tools. A missing, ambiguous, or unanswered anchor produces no request; the planner never falls back to the nearest user message. Compaction details still contain only the retained semantic boundary/step. `buildContextEntries()` then omits the older completed prefix while append-only JSONL/tree history remains intact.
117
119
 
118
120
  Pi 0.87 supports retain-none boundary compactions, but State Flow intentionally does not use them. Completed canonical state omits the exact user prompt, and foreign custom context can legitimately occur inside the latest retained iteration; hiding both would make the projected semantic state a lossy substitute for native context. Unknown or smaller usage, foreign custom metadata or native `custom_message` context in the removed prefix, stale selection, Stop/bootstrap/error/abort, and pending input do not produce this boundary. User manual and native threshold/overflow compaction remain unmodified; unaccepted work stays under Pi's native compaction contract.
119
121
 
@@ -176,7 +178,9 @@ Accepted-answer reconciliation also uses `withPatchTransaction`: `turn_end` awai
176
178
 
177
179
  `TemporalRuntime.refreshCurrentMemory(signal?)` supplies an awaited read-only recovery view of current same-session authority. It shares current-memory validation with Start, but neither publishes nor accepts write authority: returned policy is disabled and unfinished specifications are omitted. Current private values, step, revisions, bootstrap and provenance remain available beside independently validated shared streams; retention is constrained only in memory. Absence returns `undefined` without creation, and malformed evidence or cancellation (including during capture) leaves the prior cache unchanged. Lifecycle/patch publication still requires accepted authority or explicit Start. Native failed-Stop reload uses it and keeps the write fence.
178
180
 
179
- Native `session_start` and `session_tree` await one extension-owned branch restoration. Its synchronous prelude revokes older selection work, pins session id, file, header timestamp and CWD, and selects active-branch evidence through the recovery domain's pure `selectRetainedCheckpoint`: newer malformed envelopes are skipped, while revision pointers and every failure resolving the selected boundary fail closed. While it waits, mode is the selected inactive policy and private reads/publication report the pending selection. The selected boundary, exact-source fork, truly new auto-start origin (`withStartTransaction` with creation authority, rechecking branch evidence after waiting) or failed-Stop read-only recovery then use the awaited runtime API. Bootstrap/policy derive after waiting and publish in that single acceptance; only the current lifetime installs memory, checkpoint, continuation, tools and UI before yielding, and later native-write failure only warns. New selection revokes older work; shutdown drains current and superseded restoration operations. Passive/Off selection never cancels retained restoration, new-session initialization or fork copying, including attachment requested by a now-cancelled Active waiter. The pending publisher applies the latest inactive policy inside its single acceptance; Passive can then patch memory without an artificial error fence, while Off exposes no model access. Repeated selections are inert with respect to that acceptance. Start after Stop joins the independent memory operation before activating current memory. Selection changes, shutdown and native operation cancellation still revoke obsolete work; real validation/publication failures remain unavailable rather than becoming empty memory. Start joins pending restoration, owns initial attachment and fork retry without cancelling itself, and is inert when the result is active. A cancelled Start withdraws its join without cancelling independently owned restoration or Stop persistence. Read-only recovery uses detached candidates and rechecks cancellation/physical identity before host installation; passive attachment cannot overwrite a newer cache established by an intervening patch or inspection. Six synchronous runtime methods remain supported for library consumers and local tests/benchmarks; production lifecycle wiring uses the awaited APIs. Their contracts and cancellation boundaries are documented in [library API compatibility](compatibility.md#state-flow-library-api-compatibility).
181
+ Native `session_start` and `session_tree` first read only mode policy through `session.findBranchPolicy` and `snapshot.readCheckpointMode`. Off attaches without constructing a temporal runtime, resolving semantic boundaries, reading memory or emitting recovery warnings; native mode/write-fence bookkeeping remains available. Deferred fork ownership is recorded in a child-owned `forkPending` native marker and survives extension recreation; accepted child initialization resets it. Explicit Passive restores the deferred selected boundary (or fenced read-only current authority), while explicit Active retains documented current-memory activation after attachment. Policy decoding is never proof that a historical boundary is valid. Automatic callbacks remain memory-inert in Off; installed-client acceptance gates remain separate in [BACKLOG](../BACKLOG.md).
182
+
183
+ Memory-enabled native `session_start` and `session_tree`, and explicit acquisition after an Off attachment, await one extension-owned branch restoration. Its synchronous prelude revokes older selection work, pins session id, file, header timestamp and CWD, and selects active-branch evidence through the recovery domain's pure `selectRetainedCheckpoint`: newer malformed envelopes are skipped, while revision pointers and every failure resolving the selected boundary fail closed. While it waits, mode is the selected inactive policy and private reads/publication report the pending selection. The selected boundary, exact-source fork, truly new auto-start origin (`withStartTransaction` with creation authority, rechecking branch evidence after waiting) or failed-Stop read-only recovery then use the awaited runtime API. Bootstrap/policy derive after waiting and publish in that single acceptance; only the current lifetime installs memory, checkpoint, continuation, tools and UI before yielding, and later native-write failure only warns. New selection revokes older work; shutdown drains current and superseded restoration operations. Passive selection retains independently owned restoration, new-session initialization and fork copying, including attachment requested by a now-cancelled Active waiter. Off cancels those owned waits and retains only native policy/source bookkeeping for later explicit acquisition. The pending publisher applies the latest inactive policy inside its single acceptance; Passive can then patch memory without an artificial error fence, while Off exposes no model access. Repeated selections are inert with respect to that acceptance. Start joins retained Passive acquisition; after Off, non-fork Active goes directly through one cancellable current-head Start transaction, keeping the deferred native selection and local Off policy until publication. A superseding Passive cancels that activation and acquires its original retained private boundary, not the current-memory candidate; native Abort silently withdraws Active without inventing a write fence or losing later acquisition choices. Accepted activation reconstructs any native continuation from its proven current memory. Exact-source fork acquisition retains its independent restoration owner. Selection changes, shutdown and native operation cancellation still revoke obsolete work; real validation/publication failures remain unavailable rather than becoming empty memory. Start joins pending restoration, owns initial attachment and fork retry without cancelling itself, and is inert when the result is active. A cancelled Start withdraws its join without cancelling independently owned restoration or Stop persistence. Read-only recovery uses detached candidates and rechecks cancellation/physical identity before host installation; passive attachment cannot overwrite a newer cache established by an intervening patch or inspection. Six synchronous runtime methods remain supported for library consumers and local tests/benchmarks; production lifecycle wiring uses the awaited APIs. Their contracts and cancellation boundaries are documented in [library API compatibility](compatibility.md#state-flow-library-api-compatibility).
180
184
 
181
185
  The advisory [continuation-candidate reader](#session-continuation) also awaits coherent capture. Current-head activation on an attached branch uses the awaited Start transaction. Raw precomputed replay keeps its selected-target guard, unlike current-head authored patch staging. Model inference, source acquisition and Git commands do not belong inside a canonical critical section; artifact freshness validation remains part of publication validation.
182
186
 
@@ -188,11 +192,11 @@ Scope artifact provenance records only current evidence. Restore/fork drops sess
188
192
 
189
193
  After response reconciliation and Pi's retry/queue processing, `agent_before_settle` may commit the already-accepted State Flow-owned files once. `backupCurrentStateFlowFiles(root, signal?, waitForLock = true)` now returns `Promise<string | undefined>` and must be awaited. It awaits its own Git mutex and canonical exclusion to inventory the bounded root/CWD/session namespace and capture regular-file bytes, then releases canonical exclusion before every Git command or filter. `withFilePublicationLock` owns the shared acquisition/release mechanics: both mutexes retain exact ownership across awaits, refuse recursion and preserve replacement owners or combined action/cleanup failures. The backup mutex spans capture and Git completion; the branch/head is rechecked after waiting. It never descends into artifact sources, `.git`, or unrelated directory trees. A private temporary worktree/index stages the captured snapshot with Git ignore/filter policy preserved; concurrent writers may advance canonical files without changing that snapshot.
190
194
 
191
- Settlement combines an available Pi operation signal with shutdown cancellation and awaits the local backup; shutdown cancels and drains its own attempts before waiting for remote pushes. Pi SDK 0.87 has no operation signal at `agent_before_settle`, and native Abort cannot cancel a wait there. On such a host the adapter passes `waitForLock = false`: uncontended work proceeds, while live/initializing ownership raises `PublicationBusyError` and produces an explicit backup-deferred notice. Invalid/interrupted evidence remains an error, never a successful or partial capture. No commit or push follows deferral; a later accepted turn may retry. This is a narrow optional-backup admission policy, not semantic-write conflict repair or an operator configuration. The operator accepts this best-effort deferral independently of power-loss durability and retains `agent_before_settle` as the backup boundary. Moving backup to `turn_end` or extending the SDK solely for settlement waiting is not planned; backup is not a stronger canonical persistence guarantee. See the [SDK boundary evidence](compatibility.md#settlement-cancellation).
195
+ Settlement combines an available Pi operation signal with the extension-owned backup lifetime and awaits the local backup. Off or shutdown revoke that lifetime, cancel pending capture and suppress late reporting; only release of already-owned locks/resources may continue. An Off attachment revokes the previous memory-enabled background lifetime too. Shutdown drains its own attempts before waiting for remote pushes. Pi SDK 0.87 has no operation signal at `agent_before_settle`, and native Abort cannot cancel a wait there. On such a host the adapter passes `waitForLock = false`: uncontended work proceeds, while live/initializing ownership raises `PublicationBusyError` and produces an explicit backup-deferred notice. Invalid/interrupted evidence remains an error, never a successful or partial capture. No commit or push follows deferral; a later accepted turn may retry. This is a narrow optional-backup admission policy, not semantic-write conflict repair or an operator configuration. The operator accepts this best-effort deferral independently of power-loss durability and retains `agent_before_settle` as the backup boundary. Moving backup to `turn_end` or extending the SDK solely for settlement waiting is not planned; backup is not a stronger canonical persistence guarantee. See the [SDK boundary evidence](compatibility.md#settlement-cancellation).
192
196
 
193
197
  Only exact backed-up owned paths are synchronized in the caller's index, preserving unrelated staged additions, modifications, deletions, index-only content, and worktree edits. HEAD-owned paths remain candidates when their deletion is already staged. Unchanged trees and unowned-only initial backups are skipped; failed index synchronization rolls back only the backup ref, never canonical files. Failure cannot suppress the answer or trigger another inference. Notification-only `agent_settled` does not perform backup writes.
194
198
 
195
- After a successful backup attempt, State Flow resolves only the attached branch's explicitly configured remote and destination ref, snapshots the exact current commit, and starts one non-interactive, non-force push outside all backup and canonical locks. Settlement does not await network completion. Failure is diagnostic-only; no queue is persisted, and the next accepted settled turn attempts the latest current backup again. A repository without an explicitly configured branch remote remains local-only.
199
+ After a successful backup attempt, State Flow resolves only the attached branch's explicitly configured remote and destination ref, snapshots the exact current commit, and starts one non-interactive, non-force push outside all backup and canonical locks. Settlement does not await network completion. `pushCurrentStateFlowBackup(root, signal?)` and `startStateFlowBackupPush(root, onFailure, onSuccess?, signal?)` accept an optional caller-owned cancellation signal; overlap refusal does not attach the rejected caller's signal to the existing push. The adapter passes its captured backup-lifetime signal, not the completed agent-operation signal. Off/shutdown terminate only their admitted process group, retain the in-flight slot until process close, and suppress canceled success/failure callbacks. Already accepted commits remain intact; cancellation is not remote rollback. Failure is diagnostic-only; no queue is persisted, and the next accepted settled turn attempts the latest current backup again. A repository without an explicitly configured branch remote remains local-only.
196
200
 
197
201
  Durable push queues, publication workers, leases, retry generations, queue filesystem state, and publication-policy metadata remain absent. Git revision restore, immutable-revision fork APIs, and the legacy semantic Git backend have been removed from `TemporalRuntime`; all initialization, passive loading, model patches, runtime-only persistence, retained-boundary restoration, and retained-boundary forks use canonical files only.
198
202
 
@@ -288,7 +292,7 @@ Agent configuration is read once per extension load; session runtime configurati
288
292
 
289
293
  The inspection-capable Telegram port accepts synchronous or Promise-returning `select(mode)` results with optional revocation signals, while the legacy `StateFlowTelegramPort` stays synchronous. Controls initiate callback acknowledgement alongside execution rather than waiting for a network round trip before local Stop. Final feedback follows completion, uses the current menu and escapes late failures without answering the callback twice. Revoked receipts, newer callback navigation and disposal suppress stale view writes; they never roll back canonical acceptance. Obsolete start/stop callback keyboards may refresh the current view but never silently select a mode.
290
294
 
291
- Status is a projection of the selected runtime and semantic view, not a second store. Compact terminal status uses accent `state-flow` with dim `active` or `passive`, and is hidden in Off. Telegram main-menu status uses `State Flow: active`, `State Flow: passive` or `State Flow: off`. `/state-flow-status` retains the `g#c#s#` vector beside concise diagnostics and blank-line-separated top-level semantic JSON. Mode is read directly from the session's selected enum, never derived from a pending patch or separate passive flags. Requested Global, CWD and Session Rich snapshots show their independent `#revision`, while Effective shows the vector. Global/CWD Rich views omit the empty structural response placeholder; Session and Effective expose the Session-owned response. Missing evidence stays unavailable instead of appearing empty. The optional Telegram leaf adapter presents the current mode as a monospace value in the submenu heading, followed by matching Mode and Inspect memory headings (long-dash-separated description ending in a colon), each separated by a blank line from its settings-style monospaced-key list, above one radio row `Off | Passive | Active`: selected Off uses 🟡, Passive 🟣 or Active 🟢, and inactive choices use ⚫️; four direct scope-inspection buttons follow, while inspection remains available in all three modes. Inspection may refresh live Global/CWD streams in memory so foreign accepted revisions become visible, but never publishes or increments a revision. If model-facing passive access is disabled and no runtime is selected, inspection may lazily load existing canonical shared state under the same read-only rule. The awaited `StateFlowTelegramInspectionPort` returns a `StateFlowTelegramInspection` containing state and matching revisions, plus an optional revocation signal checked immediately before presentation. Stop, selection changes and shutdown cancel obsolete reads without altering newer memory or clearing write fences. The existing synchronous `StateFlowTelegramPort` contract remains supported. A callback is acknowledged before waiting; late failures appear escaped in the existing menu, without a second answer to an expired query. Registration is fail-open and disposal belongs to session shutdown. Local diagnostics stay outside semantic state and cannot change accepted state. Operator-facing fields and privacy boundaries are in [usage](usage.md#status-and-controls).
295
+ Status is a projection of the selected runtime and semantic view, not a second store. Compact terminal status uses accent `state-flow` with dim `active` or `passive`, and is hidden in Off. Telegram main-menu status uses `State Flow: active`, `State Flow: passive` or `State Flow: off`. `/state-flow-status` retains the `g#c#s#` vector beside concise diagnostics and blank-line-separated top-level semantic JSON. Mode is read directly from the session's selected enum, never derived from a pending patch or separate passive flags. Requested Global, CWD and Session Rich snapshots show their independent `#revision`, while Effective shows the vector. Global/CWD Rich views omit the empty structural response placeholder; Session and Effective expose the Session-owned response. Missing evidence stays unavailable instead of appearing empty. The optional Telegram leaf adapter presents the current mode as a monospace value in the submenu heading, followed by matching Mode and Inspect memory headings (long-dash-separated description ending in a colon), each separated by a blank line from its settings-style monospaced-key list, above one radio row `Off | Passive | Active`: selected Off uses 🟡, Passive 🟣 or Active 🟢, and inactive choices use ⚫️; four direct scope-inspection buttons follow, while inspection remains available in all three modes. Inspection may refresh live Global/CWD streams in memory so foreign accepted revisions become visible, but never publishes or increments a revision. Off inspection uses a fresh disposable `TemporalRuntime`: Global/CWD use coherent shared reads; Session/Effective use `refreshCurrentMemory` and reject absent, incomplete or malformed same-session private evidence rather than manufacturing an empty layer/revision or borrowing foreign private data. A result checks its revocation lifetime and physical owner before presentation. No reader installs the extension runtime/cache, changes native policy or canonical bytes, clears a carried write fence, acquires an unaccepted fork parent, or replaces the selected historical target. Expired selected history may coexist with inspectable current stored memory; later Passive still restores the selected past fail-closed while Active validates current memory. Memory-enabled inspection retains its accepted-private/shared-refresh and failed-Passive cache rules. The awaited `StateFlowTelegramInspectionPort` returns a `StateFlowTelegramInspection` containing state and matching revisions, plus an optional revocation signal checked immediately before presentation. Stop, selection changes and shutdown cancel obsolete reads without altering newer memory or clearing write fences. The existing synchronous `StateFlowTelegramPort` contract remains supported. A callback is acknowledged before waiting; late failures appear escaped in the existing menu, without a second answer to an expired query. Registration is fail-open and disposal belongs to session shutdown. Local diagnostics stay outside semantic state and cannot change accepted state. Operator-facing fields and privacy boundaries are in [usage](usage.md#status-and-controls).
292
296
 
293
297
  ## Validation boundaries
294
298
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## Supported Pi stack
4
4
 
5
- State Flow requires matching `pi-coding-agent`, `pi-agent-core`, `pi-ai`, and `pi-tui` packages at `>=0.87.0`. Keep all four on the same release line. The open-ended peer range permits newer SDK releases; it does not certify them.
5
+ State Flow requires matching `pi-coding-agent`, `pi-agent-core`, `pi-ai`, and `pi-tui` packages at `>=1.0.0`. Keep all four on the same release line. The open-ended peer range permits newer SDK releases; it does not certify them.
6
6
 
7
- The repository-local verified stack is Linux/x64, Node 26.8.1, Git 2.55.0 and Pi SDK 0.87.0. Repository validation covers tests, typecheck, build, compiled imports and package dry-run; successful results are bound to the validated source and dependency identities. The release workflow uses Node 24; its result is a separate verification gate.
7
+ The repository-local verified stack is Linux/x64, Node 26.8.1, Git 2.55.0 and matching Pi SDK 1.0.0 packages. Earlier source-bound measurements on Pi 0.87.0 remain historical evidence, not 1.0.0 performance results. Repository validation covers tests, typecheck, build, compiled imports and package dry-run; successful results are bound to the validated source and dependency identities. The release workflow uses Node 24; its result is a separate verification gate.
8
8
 
9
9
  Tests use isolated stores and scripted providers through the real Pi SDK. They do not certify installed Telegram/TUI reachability, live provider behavior, other operating systems, mixed SDK versions or untested newer SDK releases. Detailed behavioral witnesses live in [temporal acceptance](temporal-acceptance.md); benchmark methodology and source-bound results live in [performance](performance.md).
10
10
 
@@ -29,9 +29,11 @@ Artifact provenance is current-only, not a historical registry. Any retained par
29
29
 
30
30
  `TemporalRuntime.withForkTransaction(source, checkpoint, action, signal?)` pins source identity/boundary before waiting and selects exact parent authority plus an unoccupied child under one awaited exclusion. The caller rechecks native selection/policy and publishes its child lifecycle synchronously once. Parent evidence is revalidated before publication, the child cohort is CAS-protected, and only accepted memory installs. Cancellation or rejection cannot initialize an empty child; post-acceptance failure cannot roll it back or authorize another parent copy. Existing child storage, identity mismatch, missing parent files, malformed storage, concurrency conflict, or an expired boundary fails closed.
31
31
 
32
- Native fork adoption and Start's exact-source retry use this transaction inside the extension's owned restoration lifetime; the synchronous `prepareBoundaryFork()` adapter remains supported for library consumers. Both paths publish the fresh child origin before any runtime-only lifecycle write. Native evidence holds a publisher across fork adoption; it does not certify idle native Abort.
32
+ An Off native fork defers parent-header acquisition and canonical copying. Only a child-owned pending-fork marker is appended to the native trace; it carries no semantic authority. The marker survives cold extension reload and permits later explicit Passive/Active acquisition of the still-selected exact parent boundary, subject to the same identity, retention and occupied-child checks. Accepted initialization resets the marker. Parent expiry while Off is diagnosed only on explicit acquisition, never silently replaced with newer parent memory.
33
33
 
34
- A failed or expired selection never substitutes the parent's current/newer private state and never falls through to an older disabled marker. In the same live extension instance, explicit Start may retry the unaccepted fork after missing identity or storage evidence is corrected. Passive/Off selection does not cancel an in-flight fork or its activation-owned retry: the latest requested inactive mode is applied inside the existing fork acceptance. Cancelling the Start waiter does not cancel that independently owned copy. After acceptance, Passive exposes both tools for child memory without active episode behavior, while Off exposes neither; ordinary cold reopening loads that child-owned state. Selection, shutdown, native Abort, invalid source evidence and expired history still can prevent acceptance. Cold recovery before the first child-owned checkpoint remains unsupported; missing child files never authorize a parent recopy. Once child storage has been accepted, explicit Start can activate its validated current child-owned memory even after selecting an inherited parent checkpoint; this neither restores parent history nor copies newer parent data. Child-owned checkpoints subsequently use ordinary retained-boundary reload/resume without rereading the parent header.
34
+ Memory-enabled native fork adoption and Start's exact-source retry use this transaction inside the extension's owned restoration lifetime; the synchronous `prepareBoundaryFork()` adapter remains supported for library consumers. Both paths publish the fresh child origin before any runtime-only lifecycle write. Native evidence holds a publisher across fork adoption; it does not certify idle native Abort.
35
+
36
+ A failed or expired selection never substitutes the parent's current/newer private state and never falls through to an older disabled marker. In the same live extension instance, explicit Start may retry the unaccepted fork after missing identity or storage evidence is corrected. Passive selection retains an in-flight fork or its activation-owned retry and applies Passive inside that existing acceptance. Off instead aborts the owned copy/retry before acceptance and records child-owned native Off/pending-fork policy without publishing memory; a later explicit Passive/Active request reacquires the exact source. Cancelling the Start waiter does not cancel that independently owned copy. After acceptance, Passive exposes both tools for child memory without active episode behavior, while Off exposes neither; ordinary memory-enabled cold reopening loads that child-owned state, while Off defers loading it. Off, selection, shutdown, native Abort, invalid source evidence and expired history still can prevent acceptance. Cold recovery before the first child-owned checkpoint remains unsupported without the explicit Off-deferred pending marker; missing child files alone never authorize a parent recopy. Once child storage has been accepted, explicit Start can activate its validated current child-owned memory even after selecting an inherited parent checkpoint; this neither restores parent history nor copies newer parent data. Child-owned checkpoints subsequently use ordinary retained-boundary reload/resume without rereading the parent header.
35
37
 
36
38
  A child-owned passive-projection reset prevents copied parent Stop markers from resurfacing after child reload. Inactive sources retain their selected mode, including a same-owner native failed-Stop policy that could not reach canonical config. A child inherits neither that parent's write fence nor its passive projection; source history must still be provable and copying must pass CAS. Ordinary activation policy is not overridden. Nested forks require each direct parent boundary to remain retained; ancestry is not recursively reconstructed.
37
39
 
@@ -18,33 +18,34 @@ One session-owned `mode` selects these behaviors; there are no independent passi
18
18
 
19
19
  Here, “bootstrap from state” means constructing model context from durable memory. The implementation's `meta.bootstrap` is narrower: the one transition run that retains an existing conversation while active mode is first enabled and that conversation is compiled into state. It is not a flag that must be re-entered on every active iteration. Native compaction is also separate from model-context projection; its safety checks and usage threshold still apply.
20
20
 
21
- Active, Passive and Off select the current session's workflow and model-facing access. They do not choose a different storage algorithm or cancel creation of a fork's private memory. A fork receives its own initial Session state from the selected parent boundary, then lives independently in its selected mode. See [fork support](#fork-support-and-limits).
21
+ Active, Passive and Off select the current session's workflow and model-facing access, not a different storage algorithm. Native Off attachment defers memory acquisition, including creation of a fork's private memory, until explicit Passive/Active selection. Once acquired, a fork owns Session state copied from the selected parent boundary and lives independently in its selected mode. See [fork support](#fork-support-and-limits).
22
22
 
23
23
  ### Lifecycle operations
24
24
 
25
- `/state-flow-active` activates the current Pi branch over validated current same-session memory, initializing absent storage when safe. No remote is required. Starting mid-conversation retains Pi's active context for one complete bootstrap run, during which the agent must compile future-relevant information into state. Repeating Active while already active leaves the in-progress run unchanged. On an attached branch, current-memory activation waits asynchronously for a coherent canonical cohort; pending repeats share the wait. Until acceptance, the existing inactive mode and any write fence remain in effect. Passive, Off or branch selection can withdraw obsolete activation; an error after acceptance does not undo accepted memory.
25
+ `/state-flow-active` activates the current Pi branch over validated current same-session memory, initializing absent storage when safe. No remote is required. Starting mid-conversation retains Pi's active context for one complete bootstrap run, during which the agent must compile future-relevant information into state. Repeating Active while already active leaves the in-progress run unchanged. On an attached branch, current-memory activation waits asynchronously for a coherent canonical cohort; pending repeats share the wait. Until acceptance, the existing inactive mode, deferred historical selection and any write fence remain in effect. Cancelling pending Active from Off preserves later acquisition choices; a superseding Passive still selects its retained private boundary rather than newer current memory, and ordinary cancellation creates no write fence. Passive, Off or branch selection can withdraw obsolete activation; an error after acceptance does not undo accepted memory.
26
26
 
27
27
  - **New session:** Adopts global `mode`, defaulting to Off. An inactive default is recorded once in Pi as `{mode:"off"}` or `{mode:"passive"}` without creating semantic storage. An Active default initializes a distinct empty Session layer over global/CWD memory, never another session's private continuation.
28
- - **Resume:** Restores the selected session's retained mode, state and lineage. Later global default changes do not override it.
29
- - **Tree navigation:** Restores the selected retained private boundary over live shared scopes without checking out or resetting the shared store.
28
+ - **Resume:** Retains the selected session's mode; Passive/Active restore state and lineage, while Off attaches native policy only without probing semantic files or emitting recovery warnings. Later global default changes do not override it.
29
+ - **Tree navigation:** In Passive/Active, restores the selected retained private boundary over live shared scopes without checking out or resetting the shared store. Off defers this acquisition until explicit mode selection.
30
30
  - **Abort inference:** Stops generation or an outstanding response-publication wait while already accepted patches remain durable for continued work and corrected direction in the same session. Cancellation before response acceptance keeps the previous response and unfinished run; cancellation after acceptance never rolls it back. It does not require immediate remote replication.
31
31
  - **Native boundary continuation:** A companion may continue through Pi's `turn_end` or `agent_before_settle` boundary without a new user prompt. State Flow keeps projecting current memory and accepted response across those requests and subsequent patches; it does not restore the completed specification or request another turn itself.
32
- - **Passive or Off:** `/state-flow-passive` enables both memory tools and projection; `/state-flow-off` removes both tools and all State Flow model context immediately. A proven pre-runtime branch records only `{mode}` in Pi, without creating canonical files or publishing its cached view. Accepted runtimes persist mode and adopt unrelated shared drift without semantic/provenance writes or revision/step changes. Repeated selections are inert; pending inactive choices share one acceptance of the latest choice. Global defaults and other sessions remain unchanged.
33
- - **If an inactive choice cannot persist:** The selected Passive/Off policy stays applied. Accepted memory and native conversation remain intact; Off still exposes no State Flow context or tools. Pi records the selected mode and a write fence, not a replacement semantic checkpoint. Tree/reload/resume read validated current same-session memory without publishing or restoring an older selection. Newer mode choices survive an in-flight read-only recovery. Repeating the same choice is inert; changing inactive mode updates only native policy and keeps the fence. Explicit Active clears the fence only after canonical acceptance. This fallback requires a writable Pi trace and never repairs storage; native fenced policy overrides an older canonical config.
32
+ - **Passive:** `/state-flow-passive` enables both memory tools and projection. A proven pre-runtime branch records only `{mode}` in Pi and loads shared memory read-only. Accepted runtimes persist Passive and adopt unrelated shared drift without semantic/provenance writes or revision/step changes. Pending repeats share one acceptance.
33
+ - **Off:** `/state-flow-off` removes memory tools/context, cancels owned restoration/fork, activation, preparation, response, patch and Passive-persistence waits, and clears semantic caches immediately. It saves native policy and continuation/fork bookmarks only; existing canonical bytes, including the old stored runtime mode, stay untouched even when malformed or busy. Repeated Off is inert. Already accepted data is preserved; future explicit Passive/Active reacquires memory. Global defaults and other sessions remain unchanged.
34
+ - **If Passive cannot persist:** The selected Passive policy stays applied; Off itself never attempts canonical persistence. Accepted memory and native conversation remain intact; Off still exposes no State Flow context or tools. Pi records the selected mode and a write fence, not a replacement semantic checkpoint. Tree/reload/resume in Passive read validated current same-session memory without publishing or restoring an older selection. Off retains native policy and the write fence without reading memory; explicit Passive may acquire that read-only current authority later. Newer mode choices survive an in-flight read-only recovery. Repeating the same choice is inert; changing inactive mode updates only native policy and keeps the fence. Explicit Active clears the fence only after canonical acceptance. This fallback requires a writable Pi trace and never repairs storage; native fenced policy overrides an older canonical config.
34
35
  - **Continue in Passive after Active:** The same physical session projects a frozen state handoff, any interrupted current request and tool trajectory (including late results), and post-stop conversation. Outside an unfinished bootstrap, a proven active boundary excludes completed earlier conversation; when native split-turn compaction removed the original request anchor, Stop instead preserves the available summary and tools without reconstructing discarded raw input. An unfinished bootstrap keeps all available native context, or the earlier passive boundary it received; repeated Start/Stop cannot move that boundary past uncompiled conversation. An interrupted run retains its captured anchor even after Pi becomes idle, falling back to all available context when that anchor is unknown. Other extensions' custom context survives. Only Stop after a completed idle run retains just later conversation plus foreign custom context. Reload/resume/tree preserve this projection; new/forked physical sessions do not inherit it. Mid-tool Start and repeated Start/Stop retain the first user event already observed while disabled, so subsequent Stop does not mistake that busy run for idle. Active restart uses the retained projection for one bootstrap run. Off retains this boundary for a later Passive/Active selection but never projects it.
35
- - **Completed-history compaction:** After an accepted run settles without queued input, State Flow asks Pi for a native compaction boundary only when public context usage reaches 24,000 tokens. No extra model summary is requested; Pi keeps the complete latest run—from its original request through steering, tools, foreign context and final answer—in active history and retains the complete append-only JSONL/tree. State Flow uses the native first-user anchor, independent of image-normalization hints or later steering; images and earlier tool results remain available to the model. Uncertain projection retains available context without changing that anchor. A missing or ambiguous native anchor skips compaction instead of choosing the last steering message. On resume, native `buildContextEntries()` and TUI rendering omit the older completed prefix. Unknown or smaller usage skips the request, and custom Pi retention settings may still decline it benignly. Foreign custom context in the removed prefix, bootstrap/abort/error, Stop and pending input prevent State Flow-owned shortening; ordinary manual/threshold/overflow compaction remains native and may preserve unfinished work not yet patched into memory.
36
+ - **Completed-history compaction:** After an accepted run settles without queued input, State Flow asks Pi for a native compaction boundary only when public context usage reaches 24,000 tokens. No extra model summary is requested; Pi keeps the complete latest run—from its original request through steering, tools, foreign context and final answer—in active history and retains the complete append-only JSONL/tree. State Flow uses the native first-user anchor, independent of image-normalization hints or later steering; images and earlier tool results remain available to the model. Uncertain projection retains available context without changing that anchor. A missing or ambiguous native anchor skips compaction instead of choosing the last steering message. On resume, native `buildContextEntries()` and TUI rendering omit the older completed prefix. Unknown or smaller usage skips the request, and custom Pi retention settings may still decline it benignly. Foreign custom context in the removed prefix, bootstrap/abort/error, Stop and pending input prevent State Flow-owned shortening; obsolete/inactive owned requests are canceled before their hook can fall through to a model summary, and late completion cannot clear a newer request; ordinary manual/threshold/overflow compaction remains native and may preserve unfinished work not yet patched into memory.
36
37
 
37
38
  State Flow does not undo tool effects. After interruption or returning to an older branch, check the relevant workspace or external system before repeating consequential operations. Restored memory is not restored reality.
38
39
 
39
40
  ### Fork support and limits
40
41
 
41
- Native fork replacement copies the source session checkpoint, retained patch tail and matching provenance into the new session's own storage. Global/CWD values and provenance stay current; applying a smaller `historyLimit` may fold shared tails under CAS. An earlier fork selection copies that point's private state, not the parent's later private work. Parent-private data/history remain intact; the selected mode is retained, so an inactive source does not become Active automatically.
42
+ Memory-enabled native fork replacement copies the source session checkpoint, retained patch tail and matching provenance into the new session's own storage. Off records child-owned pending-fork policy only, deferring header/store reads and copying until explicit Passive/Active, including after cold reload. Global/CWD values and provenance stay current; applying a smaller `historyLimit` may fold shared tails under CAS. An earlier fork selection copies that point's private state, not the parent's later private work. Parent-private data/history remain intact; the selected mode is retained, so an inactive source does not become Active automatically.
42
43
 
43
44
  The child starts at step zero and a new temporal origin. Its copied tail obeys the configured retention limit, but pre-origin records are not additional aligned causal boundaries addressable through `effective[n]` or scoped paths. The child's own transitions build its hot window; owned checkpoints support normal reload/resume. Parent Stop projection is not inherited, including after child reload.
44
45
 
45
46
  Initial copying requires a native fork start event, a regular canonical direct-parent session file, matching CWD/identity, a readable temporal source and an unused child namespace. Missing/unsafe evidence or CAS conflicts leave the copy unavailable rather than importing unrelated or newer private state. Explicit Start can retry an unaccepted copy in the same loaded fork after the cause is corrected.
46
47
 
47
- Selecting a copied parent checkpoint through the child's `/tree` does not make it child-owned: historical restoration stays disabled without resetting existing child data. Select a child-owned checkpoint, resume the original session, or explicitly Start from the validated current child-owned memory; Start does not copy newer parent data. Cold recovery before the first child checkpoint, startup paths lacking the fork event, in-memory parent locators and cross-CWD imports remain outside this slice. File-only copying requires an exact still-available source cohort. See the [contract](fork-contract.md) and [SDK compatibility boundary](compatibility.md#public-host-seams); do not rewrite UUIDs or delete pointers to force recovery.
48
+ Selecting a copied parent checkpoint through the child's `/tree` does not make it child-owned: historical restoration stays disabled without resetting existing child data. Select a child-owned checkpoint, resume the original session, or explicitly Start from the validated current child-owned memory; Start does not copy newer parent data. Cold recovery before the first child checkpoint requires an Off-deferred pending-fork marker; otherwise it and startup paths lacking the fork event remain unsupported. In-memory parent locators and cross-CWD imports remain unsupported. File-only copying requires an exact still-available source cohort. See the [contract](fork-contract.md) and [SDK compatibility boundary](compatibility.md#public-host-seams); do not rewrite UUIDs or delete pointers to force recovery.
48
49
 
49
50
  ## Configuration
50
51
 
@@ -65,7 +66,7 @@ The canonical store is `state-flow/` beneath the agent directory. Keeping config
65
66
  - `showSuccessfulPatches`: Defaults to `true`. In interactive Pi, successful `patch_state` rows show only the applied pretty-printed JSON arguments, with blank lines between adjacent memory sections; set it to `false` to keep only the compact summary. Rejected calls still use ordinary error rendering; State Flow adds no private validation turn.
66
67
  - `historyLimit`: Defaults to `7` and accepts integers from `0` through `100`. It counts accepted semantic transitions, **not elapsed time or conversation length**. It bounds materialized-history and scope patch-history offsets. Lowering it on reload/restore/fork folds excess tails forward without losing current state; selected boundaries outside the new window are unavailable. Zero retains only current checkpoints. Raising the limit affects only future retention and cannot reconstruct discarded history.
67
68
 
68
- Session `config.json` uses the same `mode` key for its concrete choice; commands and Telegram change that session only. Before canonical runtime acceptance, Pi's native `{mode}` checkpoint owns the choice instead of a manufactured storage pair. Edit global defaults manually or through an authorized agent, not `patch_state`. Legacy flag decoding is read-only; see [mode compatibility](compatibility.md#mode-configuration-compatibility).
69
+ Session `config.json` uses the same `mode` key for its concrete choice; commands and Telegram change that session only. Before canonical runtime acceptance, Pi's native `{mode}` checkpoint owns the choice instead of a manufactured storage pair. Off remains native-only even after an accepted runtime: its mode/bookmark overrides the earlier canonical mode without requiring store access or granting semantic authority. Edit global defaults manually or through an authorized agent, not `patch_state`. Legacy flag decoding is read-only; see [mode compatibility](compatibility.md#mode-configuration-compatibility).
69
70
 
70
71
  **Passive model-facing footprint:** When selected, Passive declares both memory tools even with no canonical store; its system-prompt section and projected memory message appear only after a validated memory view is loaded. New sessions default to Off, which exposes none of these State Flow model-facing surfaces. With unavailable memory the tools may still reject reads or writes; declared tools do not prove usable storage.
71
72
 
@@ -91,7 +92,7 @@ Logs remain local unless you move them; rotation/deletion is operator-owned. Sta
91
92
 
92
93
  Status omits the already-visible mode and generic ownership/configuration prose. Failed inspection reports unavailable evidence, not invented empty state. Status is observational: it does not read source files, calculate fingerprints, create invalidations, or mutate semantic state.
93
94
 
94
- The terminal indicator is accent `state-flow` plus dim `active` or `passive`; Off hides it. Global, CWD and Session own independent semantic revisions; one atomic transition advances each materially changed scope once, including session-only response reconciliation. Effective has no scalar counter and uses the compact lowercase `g#c#s#` revision vector (for example, `g15c8s31`), without slashes or spaces between counters. That vector appears in `/state-flow-status` and Telegram's Effective inspection, not the compact indicators. When `pi-telegram` is available, its main-menu section shows `State Flow: active`, `State Flow: passive` or `State Flow: off`. Off exposes neither tool nor State Flow model context. Requested owner-scope Rich snapshots show `#revision`; Effective shows the vector. During a failed-Stop write fence, inspection uses the accepted cache without a potentially conflicting refresh. Otherwise, Telegram inspection waits cancelably to load or refresh one coherent shared view, even when passive model tools are disabled. It does not initialize, publish, or advance storage. Data and displayed revisions belong to the same observation; absent/invalid memory stays unavailable. Stop, session/tree changes and shutdown cancel obsolete observations. The button acknowledges immediately, and a late failure appears in the menu instead of an expired callback popup. The submenu heading displays the current value in monospace. The bold Mode heading uses a long dash, description ending in a colon, and a blank line before its settings-style list. Each line uses a monospaced minus and lowercase monospaced mode value, then a plain colon and description. The descriptions progress from regular chat with no memory (Off, the new-session default), to ordinary chat with memory tools and an available combined memory view (Passive), to the same memory access with completed answers followed by memory-first continuation (Active); they do not claim a new physical Pi session or disable native compaction. The bold Inspect memory heading follows the same long-dash-description-colon and blank-line pattern. Its four lines use the same monospaced minus/value and plain colon format for `global`, `cwd`, `session` and `effective`, describing individual scopes and their combined view. Inspection works in Off even though its memory does not reach the agent. A horizontal radio row presents `Off | Passive | Active`: the selected option uses 🟡, 🟣 or 🟢 respectively, and each inactive option uses ⚫️. Four direct Global/CWD/Session/Effective buttons follow without another chooser. Ordinary successful controls add no redundant mode receipt; diagnostic outcomes remain visible. Telegram Active requested during a run waits for settlement; Passive and Off apply immediately. All controls use the same lifecycle owners as the terminal commands. The adapter is optional and the Pi commands remain available without it. Open implementation work is tracked in [BACKLOG.md](../BACKLOG.md).
95
+ The terminal indicator is accent `state-flow` plus dim `active` or `passive`; Off hides it. Global, CWD and Session own independent semantic revisions; one atomic transition advances each materially changed scope once, including session-only response reconciliation. Effective has no scalar counter and uses the compact lowercase `g#c#s#` revision vector (for example, `g15c8s31`), without slashes or spaces between counters. That vector appears in `/state-flow-status` and Telegram's Effective inspection, not the compact indicators. When `pi-telegram` is available, its main-menu section shows `State Flow: active`, `State Flow: passive` or `State Flow: off`. Off exposes neither tool nor State Flow model context. Requested owner-scope Rich snapshots show `#revision`; Effective shows the vector. During a failed-Passive write fence, memory-enabled inspection uses the accepted cache without a potentially conflicting refresh. Otherwise, Telegram inspection waits cancelably to load or refresh one coherent shared view, even when passive model tools are disabled. It does not initialize, publish, or advance storage. Data and displayed revisions belong to the same observation; absent/invalid memory stays unavailable. Stop, session/tree changes and shutdown cancel obsolete observations. The button acknowledges immediately, and a late failure appears in the menu instead of an expired callback popup. The submenu heading displays the current value in monospace. The bold Mode heading uses a long dash, description ending in a colon, and a blank line before its settings-style list. Each line uses a monospaced minus and lowercase monospaced mode value, then a plain colon and description. The descriptions progress from regular chat with no memory (Off, the new-session default), to ordinary chat with memory tools and an available combined memory view (Passive), to the same memory access with completed answers followed by memory-first continuation (Active); they do not claim a new physical Pi session or disable native compaction. The bold Inspect memory heading follows the same long-dash-description-colon and blank-line pattern. Its four lines use the same monospaced minus/value and plain colon format for `global`, `cwd`, `session` and `effective`, describing individual scopes and their combined view. Explicit Off inspection reads current stored memory through a disposable reader; Session and Effective require validated same-session private authority and cannot show a fabricated empty layer or revision. Shared Global/CWD inspection remains available independently of private failures. These reads install no model/runtime cache, change no bytes or mode, clear no write fence, and leave the selected historical/fork boundary intact for future Passive/Active acquisition; automatic Off callbacks never acquire memory. Current stored data is not proof that a selected past boundary is restorable. A horizontal radio row presents `Off | Passive | Active`: the selected option uses 🟡, 🟣 or 🟢 respectively, and each inactive option uses ⚫️. Four direct Global/CWD/Session/Effective buttons follow without another chooser. Ordinary successful controls add no redundant mode receipt; diagnostic outcomes remain visible. Telegram Active requested during a run waits for settlement; Passive and Off apply immediately. All controls use the same lifecycle owners as the terminal commands. The adapter is optional and the Pi commands remain available without it. Open implementation work is tracked in [BACKLOG.md](../BACKLOG.md).
95
96
 
96
97
  ## Storage and recovery
97
98
 
@@ -122,7 +123,7 @@ Missing artifact provenance inside an otherwise complete scope `meta.json` means
122
123
 
123
124
  Canonical scope/runtime files own current materialization and retained hot history regardless of Git availability. Pi checkpoints identify a retained semantic boundary, not a Git commit or arbitrary historical snapshot. Restart and branch restoration fail closed when the selected boundary has expired rather than substituting newer files as the selected past.
124
125
 
125
- After an accepted turn has reconciled its response, Pi 0.87's final actionable `agent_before_settle` boundary may create one best-effort backup commit when Git is available. The local attempt completes before settlement continues. Its capture waits cancelably when Pi supplies an operation signal; on Pi 0.87 that signal is absent at settlement, so an occupied backup/storage mutex explicitly defers backup until a later accepted turn instead of trapping Abort. Deferral neither changes memory nor starts a push. Shutdown cancels and drains pending local attempts. If the attached branch has an explicitly configured remote/ref, State Flow starts a non-interactive asynchronous push of the exact current commit without force. Settlement does not wait for the network. Within one Pi process, an in-flight push per repository skips overlapping attempts; a later accepted turn retries the latest backup without a durable queue. Session shutdown waits for that repository's in-flight push to close or time out, suppressing push-failure reporting after shutdown begins. Commit or push failure is diagnostic-only; repeated push failures warn once per failure streak and remain locally diagnosable. Git availability never changes semantic authority, step, or retained lineage.
126
+ After an accepted turn has reconciled its response, Pi 0.87's final actionable `agent_before_settle` boundary may create one best-effort backup commit when Git is available. The local attempt completes before settlement continues. Its capture waits cancelably when Pi supplies an operation signal; on Pi 0.87 that signal is absent at settlement, so an occupied backup/storage mutex explicitly defers backup until a later accepted turn instead of trapping Abort. Deferral neither changes memory nor starts a push. Off and shutdown cancel owned pending local attempts. Only cleanup of already-acquired locks/resources may continue; no new capture is admitted in Off. If the attached branch has an explicitly configured remote/ref, State Flow starts a non-interactive asynchronous push of the exact current commit without force. Settlement does not wait for the network. Within one Pi process, an in-flight push per repository skips overlapping attempts; a later accepted turn retries the latest backup without a durable queue. Off terminates only its admitted push and suppresses canceled reporting; an overlapping caller cannot revoke another owner's push. Normal completion of the agent operation does not revoke independent push ownership. Shutdown cancels its own pushes and waits for that repository's in-flight push to close or time out. Already accepted local/remote commits are never rolled back by cancellation. Commit or push failure is diagnostic-only; repeated push failures warn once per failure streak and remain locally diagnosable. Git availability never changes semantic authority, step, or retained lineage.
126
127
 
127
128
  ### Moving a store and the 0.17 format boundary
128
129
 
@@ -138,7 +139,7 @@ Final-answer reconciliation also waits cancelably, then saves the response and c
138
139
 
139
140
  Run preparation and missing-artifact maintenance wait cancelably before the first enabled inference, accepting current shared memory and lifecycle together. If preparation fails, State Flow aborts that native operation rather than sending a rejected or stale draft to the provider; previously accepted memory remains available. Cancellation can leave the new request without a specification checkpoint, so its native conversation is conservatively preserved through idle Stop/reload. Boundary continuation never replays a completed specification.
140
141
 
141
- Telegram shared inspection also awaits exclusion read-only. Backup capture also uses the awaited API, with the no-signal settlement exception described above. Accepted-runtime Passive/Off selection changes local tools/context immediately, then awaits runtime-only persistence; pending inactive choices share one acceptance of the latest mode. Selection/shutdown or a successful Start cancel obsolete Stop work. An available host operation signal can cancel persistence without restoring an older mode; idle commands do not necessarily have that signal. Current-head Start similarly waits before enabling mode, with Stop/selection/shutdown cancellation and any available native operation signal. Startup, tree, auto-start, fork and failed-Stop reload restoration, including Start's initial attachment and fork retry, also await exclusion; until acceptance, mode stays in the selected inactive policy and private memory reports the pending selection. Off remains Off; later inactive choices survive read-only recovery without cancelling it. Interrupted, malformed or unreadable locks are never stolen. Reconcile the owner rather than deleting locks or state directories merely because an operation is slow. File-cohort exclusion, exact prepared bytes and compare-and-swap checks are not kernel-atomic multi-file transactions against nonparticipating writers.
142
+ Telegram shared inspection also awaits exclusion read-only. Backup capture also uses the awaited API, with the no-signal settlement exception described above. Accepted-runtime Passive selection changes local tools/context immediately, then awaits runtime-only persistence; pending repeats share one acceptance. Off cancels that wait and records native policy without acquiring the store. Selection/shutdown or a successful Start cancel obsolete Stop work. An available host operation signal can cancel persistence without restoring an older mode; idle commands do not necessarily have that signal. Current-head Start similarly waits before enabling mode, with Stop/selection/shutdown cancellation and any available native operation signal. Startup, tree, auto-start, fork and failed-Stop reload restoration, including Start's initial attachment and fork retry, also await exclusion; until acceptance, mode stays in the selected inactive policy and private memory reports the pending selection. Off remains Off; later inactive choices survive read-only recovery without cancelling it. Interrupted, malformed or unreadable locks are never stolen. Reconcile the owner rather than deleting locks or state directories merely because an operation is slow. File-cohort exclusion, exact prepared bytes and compare-and-swap checks are not kernel-atomic multi-file transactions against nonparticipating writers.
142
143
 
143
144
  Fatal process termination can leave an incomplete canonical file cohort. Before repair, quiesce all store writers and preserve the complete store plus selected Pi retained-boundary references. Reconcile exact files against the last complete checkpoint/tail/metadata cohort; no automatic crash repair or power-loss durability is promised. Git backup has no semantic recovery authority.
144
145
 
@@ -1,5 +1,5 @@
1
- import { estimateTokens, type AgentMessage } from "@earendil-works/pi-agent-core";
2
- import type { CompactionResult } from "@earendil-works/pi-coding-agent";
1
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
+ import { estimateTokens, type CompactionResult } from "@earendil-works/pi-coding-agent";
3
3
 
4
4
  export const STATE_FLOW_COMPACTION_SUMMARY = "State Flow accepted the completed work before this boundary. Current memory is restored from its retained semantic boundary and projected separately; use the retained native entries for subsequent work.";
5
5
  /** A modest margin above Pi's default 20k retained suffix absorbs estimation drift. */