@llblab/pi-kit 0.26.0 → 0.27.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 (88) hide show
  1. package/BACKLOG.md +2 -2
  2. package/CHANGELOG.md +5 -0
  3. package/README.md +4 -4
  4. package/node_modules/@llblab/pi-state-flow/AGENTS.md +1 -1
  5. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +12 -5
  6. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +9 -0
  7. package/node_modules/@llblab/pi-state-flow/README.md +116 -34
  8. package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +24 -1
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +80 -1
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +17 -0
  11. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +40 -0
  12. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +149 -298
  13. package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +29 -0
  14. package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +58 -0
  15. package/node_modules/@llblab/pi-state-flow/dist/lib/operation.d.ts +37 -0
  16. package/node_modules/@llblab/pi-state-flow/dist/lib/operation.js +59 -0
  17. package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.d.ts +31 -0
  18. package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.js +117 -0
  19. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +7 -7
  20. package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +1 -1
  21. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +2 -0
  22. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +28 -0
  23. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +6 -1
  24. package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
  25. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +14 -6
  26. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +2 -2
  27. package/node_modules/@llblab/pi-state-flow/docs/README.md +19 -9
  28. package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +4 -4
  29. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +644 -91
  30. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +116 -37
  31. package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +118 -21
  32. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +68 -8
  33. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +88 -14
  34. package/node_modules/@llblab/pi-state-flow/docs/performance.md +83 -66
  35. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +391 -62
  36. package/node_modules/@llblab/pi-state-flow/docs/usage.md +317 -62
  37. package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +85 -1
  38. package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +47 -0
  39. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +161 -295
  40. package/node_modules/@llblab/pi-state-flow/lib/git.ts +63 -0
  41. package/node_modules/@llblab/pi-state-flow/lib/operation.ts +75 -0
  42. package/node_modules/@llblab/pi-state-flow/lib/ownership.ts +120 -0
  43. package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +7 -8
  44. package/node_modules/@llblab/pi-state-flow/lib/query.ts +1 -1
  45. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +1 -1
  46. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +1 -2
  47. package/node_modules/@llblab/pi-state-flow/lib/status.ts +29 -0
  48. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +5 -1
  49. package/node_modules/@llblab/pi-state-flow/package.json +1 -1
  50. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +14 -6
  51. package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +2 -2
  52. package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -0
  53. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +10 -0
  54. package/node_modules/@llblab/pi-telegram/README.md +1 -1
  55. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +4 -1
  56. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +16 -12
  57. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +1 -1
  58. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +7 -1
  59. package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +12 -3
  60. package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +137 -83
  61. package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +26 -0
  62. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.d.ts +57 -2
  63. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +109 -4
  64. package/node_modules/@llblab/pi-telegram/dist/lib/model.js +2 -4
  65. package/node_modules/@llblab/pi-telegram/dist/lib/status.d.ts +3 -1
  66. package/node_modules/@llblab/pi-telegram/dist/lib/status.js +31 -1
  67. package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +4 -4
  68. package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +1 -0
  69. package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +17 -4
  70. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +2 -2
  71. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +48 -12
  72. package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
  73. package/node_modules/@llblab/pi-telegram/docs/architecture.md +6 -5
  74. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +2 -0
  75. package/node_modules/@llblab/pi-telegram/docs/public-api.md +2 -2
  76. package/node_modules/@llblab/pi-telegram/docs/ui-style.md +4 -0
  77. package/node_modules/@llblab/pi-telegram/lib/bindings.ts +17 -10
  78. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +8 -2
  79. package/node_modules/@llblab/pi-telegram/lib/commands.ts +135 -97
  80. package/node_modules/@llblab/pi-telegram/lib/extension.ts +25 -0
  81. package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +140 -4
  82. package/node_modules/@llblab/pi-telegram/lib/model.ts +2 -4
  83. package/node_modules/@llblab/pi-telegram/lib/status.ts +30 -1
  84. package/node_modules/@llblab/pi-telegram/lib/sync.ts +4 -4
  85. package/node_modules/@llblab/pi-telegram/lib/threads.ts +21 -3
  86. package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +46 -13
  87. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  88. package/package.json +3 -3
@@ -8,48 +8,126 @@ For the concept and installation, start with the [README](../README.md). This gu
8
8
 
9
9
  State Flow has three distinct model-facing states. **Active versus passive changes the agent's workflow, not the existence of disk memory.**
10
10
 
11
- - **Active:** Both `read_state` and `patch_state` are available, subject to host restrictions and valid memory authority. Prompts require the agent to consolidate future-relevant results into state before ending an iteration. The final meaningful semantic patch preserves decisions, outcomes and continuation needed after the completed conversation is removed from model projection. The next iteration starts from accepted state and its new input, not the previous iteration's completed reasoning. Native trace remains inspectable; a clean model context does not mean deleting Pi history.
12
- - **Passive:** Both memory tools are available. Existing state is projected into context, and the agent may read or patch it as useful. Ordinary conversation continuity remains: State Flow does not impose the active iteration-ending context reset or the same mandatory consolidation pressure. Accepted patches still reach the same canonical store with the same validation and ownership guarantees.
11
+ - **Active:** Both `read_state` and `patch_state` are available, subject to host restrictions and valid memory authority.
12
+ - Prompts require the agent to consolidate future-relevant results into state before ending an iteration.
13
+ - The final meaningful semantic patch preserves the decisions, outcomes and continuation needed once the completed conversation leaves model projection.
14
+ - The next iteration starts from accepted state and its new input, not from the previous iteration's completed reasoning.
15
+ - The native trace stays inspectable: a clean model context does not mean deleting Pi history.
16
+ - **Passive:** Both memory tools are available, existing state is projected into context, and the agent may read or patch it as useful.
17
+ - Ordinary conversation continuity remains: there is no active iteration-ending context reset and no mandatory consolidation pressure.
18
+ - Accepted patches still reach the same canonical store, with the same validation and ownership guarantees.
13
19
  - **Off:** Neither memory tool is exposed to the model, and State Flow injects no protocol, bootstrap/state context or frozen passive handoff. Stored memory and the native conversation trace are not deleted.
14
20
 
15
- One session-owned `mode` selects these behaviors; there are no independent passive-tool/projection switches. Host restrictions and genuine unavailable/corrupt-memory fences remain separate from mode selection.
21
+ One session-owned `mode` selects these behaviors; there are no separate passive-tool or projection switches. Host restrictions and genuinely unavailable or corrupt memory are fenced independently of the mode.
16
22
 
17
- **Completion is semantic, not ceremonial.** In active mode, necessary final state changes must be accepted before relying on state-only continuation. This does not require an empty `patch_state` when memory is already current, an extra model turn, or a special finalization tool. Each `patch_state` remains an inference barrier, not automatically the end of an iteration; the runtime separately persists the accepted ordinary answer as Session `response` and completes the run.
23
+ **Completion is semantic, not ceremonial.** In active mode, necessary final state changes must be accepted before relying on state-only continuation. That does not require:
18
24
 
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.
25
+ - an empty `patch_state` when memory is already current;
26
+ - an extra model turn;
27
+ - a special finalization tool.
20
28
 
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).
29
+ Each `patch_state` is an inference barrier, not automatically the end of an iteration. The runtime separately persists the accepted ordinary answer as Session `response` and completes the run.
22
30
 
23
- ### Lifecycle operations
31
+ **Two meanings of “bootstrap”:**
32
+
33
+ - “Bootstrap from state” means building model context from durable memory.
34
+ - The implementation's `meta.bootstrap` is narrower: it marks the one transition run that keeps an existing conversation when active mode is first enabled, so that conversation can be compiled into state. It is not re-entered on every active iteration.
24
35
 
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.
36
+ Native compaction is separate from model-context projection; its safety checks and usage threshold still apply.
26
37
 
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:** 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
- - **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
- - **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:** `/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.
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.
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.
38
+ Active, Passive and Off select the 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 Passive or Active is explicitly selected. 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).
39
+
40
+ ### Lifecycle operations
37
41
 
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.
42
+ **`/state-flow-active`** activates the current Pi branch over validated current same-session memory, initializing absent storage when safe. No remote is required.
43
+
44
+ - Starting mid-conversation keeps Pi's active context for one complete bootstrap run, during which the agent must compile future-relevant information into state.
45
+ - Repeating Active while already active leaves the in-progress run unchanged.
46
+ - On an attached branch, activation waits asynchronously for a coherent canonical cohort; pending repeats share the wait.
47
+ - Until acceptance, the existing inactive mode, deferred historical selection and any write fence stay in effect.
48
+ - Cancelling a 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.
49
+ - Passive, Off or a branch selection can withdraw an obsolete activation. An error after acceptance does not undo accepted memory.
50
+
51
+ How each lifecycle event behaves:
52
+
53
+ - **New session:** Adopts the global `mode`, defaulting to Off.
54
+ - An inactive default is recorded once in Pi as `{mode:"off"}` or `{mode:"passive"}`, without creating semantic storage.
55
+ - An Active default initializes a distinct empty Session layer over global/CWD memory, never another session's private continuation.
56
+ - **Resume:** Keeps the selected session's mode; later global default changes do not override it.
57
+ - Passive/Active restore state and lineage.
58
+ - Off attaches native policy only, without probing semantic files or emitting recovery warnings.
59
+ - **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 a mode is explicitly selected.
60
+ - **Abort inference:** Stops generation or an outstanding response-publication wait. Already accepted patches stay durable, so work and corrected direction can continue in the same session.
61
+ - Cancellation before response acceptance keeps the previous response and the unfinished run.
62
+ - Cancellation after acceptance never rolls it back.
63
+ - Abort does not require immediate remote replication.
64
+ - **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 the accepted response across those requests and later patches. It does not restore the completed specification or request another turn itself.
65
+ - **Passive:** `/state-flow-passive` enables both memory tools and projection.
66
+ - A proven pre-runtime branch records only `{mode}` in Pi and loads shared memory read-only.
67
+ - Accepted runtimes persist Passive and adopt unrelated shared drift without semantic/provenance writes or revision/step changes.
68
+ - Pending repeats share one acceptance.
69
+ - **Off:** `/state-flow-off` removes memory tools and context, and immediately clears semantic caches.
70
+ - It cancels owned restoration/fork, activation, preparation, response, patch and Passive-persistence waits.
71
+ - It saves only native policy and continuation/fork bookmarks. Existing canonical bytes, including the old stored runtime mode, stay untouched even when malformed or busy.
72
+ - Repeated Off is inert. Already accepted data is preserved, and a later explicit Passive/Active reacquires memory.
73
+ - Global defaults and other sessions remain unchanged.
74
+ - **If Passive cannot persist:** Off itself never attempts canonical persistence; this fallback concerns Passive.
75
+ - The selected Passive policy stays applied. Accepted memory and the native conversation stay intact.
76
+ - Pi records the selected mode and a write fence, not a replacement semantic checkpoint. This needs a writable Pi trace and never repairs storage; native fenced policy overrides an older canonical config.
77
+ - Tree/reload/resume in Passive read validated current same-session memory without publishing or restoring an older selection.
78
+ - Off keeps the native policy and the write fence without reading memory, and still exposes no State Flow context or tools; explicit Passive may acquire that read-only current authority later.
79
+ - Newer mode choices survive an in-flight read-only recovery. Repeating the same choice is inert; changing the inactive mode updates only native policy and keeps the fence.
80
+ - Explicit Active clears the fence only after canonical acceptance.
81
+ - **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 the conversation after Stop. Which earlier conversation is kept:
82
+ - Outside an unfinished bootstrap, a proven active boundary excludes completed earlier conversation.
83
+ - If native split-turn compaction removed the original request anchor, Stop keeps the available summary and tools instead, without reconstructing discarded raw input.
84
+ - 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.
85
+ - An interrupted run keeps its captured anchor even after Pi becomes idle, and falls back to all available context when that anchor is unknown.
86
+ - Only Stop after a completed idle run keeps just the later conversation plus foreign custom context. Other extensions' custom context survives in every case.
87
+ - Mid-tool Start and repeated Start/Stop keep the first user event already observed while disabled, so a later Stop does not mistake that busy run for idle.
88
+ - Reload/resume/tree preserve this projection; new or forked physical sessions do not inherit it.
89
+ - Active restart uses the retained projection for one bootstrap run. Off keeps this boundary for a later Passive/Active selection but never projects it.
90
+ - **Completed-history compaction:** After an accepted run settles without queued input, State Flow asks Pi for a native compaction boundary, but only when public context usage reaches 24,000 tokens. No extra model summary is requested.
91
+ - Pi keeps the complete latest run in active history, from its original request through steering, tools, foreign context and final answer, and keeps the complete append-only JSONL/tree.
92
+ - State Flow uses the native first-user anchor, independent of image-normalization hints or later steering; images and earlier tool results stay available to the model. Uncertain projection keeps available context without changing that anchor.
93
+ - A missing or ambiguous native anchor skips compaction instead of choosing the last steering message.
94
+ - On resume, native `buildContextEntries()` and TUI rendering omit the older completed prefix.
95
+ - Unknown or smaller usage skips the request, and custom Pi retention settings may still decline it benignly.
96
+ - These prevent State Flow-owned shortening: foreign custom context in the prefix that would be removed, bootstrap/abort/error, Stop and pending input.
97
+ - Obsolete or inactive owned requests are canceled before their hook can fall through to a model summary, and a late completion cannot clear a newer request.
98
+ - Ordinary manual/threshold/overflow compaction stays native and may preserve unfinished work not yet patched into memory.
99
+
100
+ State Flow does not undo tool effects. After an interruption or a return to an older branch, check the relevant workspace or external system before repeating consequential operations. Restored memory is not restored reality.
39
101
 
40
102
  ### Fork support and limits
41
103
 
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.
104
+ **What a fork copies.** Memory-enabled native fork replacement copies the source session checkpoint, retained patch tail and matching provenance into the new session's own storage.
105
+
106
+ - Off records only a child-owned pending-fork policy. Header/store reads and copying wait until an explicit Passive/Active, including after a cold reload.
107
+ - Global/CWD values and provenance stay current. Applying a smaller `historyLimit` may fold shared tails under CAS.
108
+ - An earlier fork selection copies that point's private state, not the parent's later private work.
109
+ - Parent-private data and history stay intact. The selected mode is kept, so an inactive source does not become Active automatically.
110
+
111
+ **The child's own history.** The child starts at step zero with a new temporal origin.
112
+
113
+ - 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.
114
+ - The child's own transitions build its hot window, and owned checkpoints support normal reload/resume.
115
+ - Parent Stop projection is not inherited, including after a child reload.
43
116
 
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.
117
+ **Requirements for the initial copy:** 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 or unsafe evidence or a CAS conflict leaves the copy unavailable rather than importing unrelated or newer private state. Explicit Start can retry an unaccepted copy in the same loaded fork once the cause is corrected.
45
118
 
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.
119
+ **Limits:**
47
120
 
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.
121
+ - 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. Instead, 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.
122
+ - 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.
123
+ - In-memory parent locators and cross-CWD imports remain unsupported.
124
+ - File-only copying requires an exact still-available source cohort.
125
+
126
+ See the [contract](fork-contract.md) and the [SDK compatibility boundary](compatibility.md#public-host-seams). Do not rewrite UUIDs or delete pointers to force recovery.
49
127
 
50
128
  ## Configuration
51
129
 
52
- Optional global `config.json` at the root of the State Flow repository, normally `~/.pi/agent/state-flow/config.json`:
130
+ An optional global `config.json` lives at the root of the State Flow repository, normally `~/.pi/agent/state-flow/config.json`:
53
131
 
54
132
  ```json
55
133
  {
@@ -60,27 +138,52 @@ Optional global `config.json` at the root of the State Flow repository, normally
60
138
  }
61
139
  ```
62
140
 
63
- The canonical store is `state-flow/` beneath the agent directory. Keeping configuration inside that repository removes the separate agent-level `state-flow.json`; SDK embeddings may still provide an explicit repository override.
64
- - `mode`: `"active"`, `"passive"` or `"off"`; defaults to `"off"`. Supplies the default only for genuinely new sessions. Active initializes missing storage when safe; Passive reads existing memory without publishing, and its first explicit patch may initialize absent storage without starting an episode or compaction. Off exposes neither memory tools nor State Flow context.
65
- - `logging`: Defaults to `false`. When enabled, records rejected patch executions, active barrier blocks, preparation failures and accepted-answer reconciliation failures locally at `tmp/state-flow/logs.jsonl` beneath the agent directory. Asynchronous Git push failures are recorded there even when this setting is off.
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.
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.
141
+ The canonical store is `state-flow/` beneath the agent directory. Keeping configuration inside that repository replaces the separate agent-level `state-flow.json`; SDK embeddings may still provide an explicit repository override.
142
+
143
+ - `mode`: `"active"`, `"passive"` or `"off"`; defaults to `"off"`. It supplies the default only for genuinely new sessions.
144
+ - Active initializes missing storage when safe.
145
+ - Passive reads existing memory without publishing; its first explicit patch may initialize absent storage without starting an episode or compaction.
146
+ - Off exposes neither memory tools nor State Flow context.
147
+ - `logging`: Defaults to `false`. When enabled, rejected patch executions, active barrier blocks, preparation failures and accepted-answer reconciliation failures are recorded locally at `tmp/state-flow/logs.jsonl` beneath the agent directory. Asynchronous Git push failures are recorded there even when this setting is off.
148
+ - `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.
149
+ - `historyLimit`: Defaults to `7` and accepts integers from `0` through `100`. It counts accepted semantic transitions, **not elapsed time or conversation length**, and bounds materialized-history and scope patch-history offsets.
150
+ - Lowering it on reload/restore/fork folds excess tails forward without losing current state; selected boundaries outside the new window become unavailable.
151
+ - Zero keeps only current checkpoints.
152
+ - Raising it affects only future retention and cannot reconstruct discarded history.
68
153
 
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).
154
+ **Session configuration.** A session's `config.json` uses the same `mode` key for its concrete choice; commands and Telegram change that session only.
70
155
 
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.
156
+ - Before canonical runtime acceptance, Pi's native `{mode}` checkpoint owns the choice instead of a manufactured storage pair.
157
+ - Off stays native-only even after an accepted runtime: its mode/bookmark overrides the earlier canonical mode without needing store access or granting semantic authority.
158
+ - Edit global defaults manually or through an authorized agent, not through `patch_state`.
159
+ - Legacy flag decoding is read-only; see [mode compatibility](compatibility.md#mode-configuration-compatibility).
72
160
 
73
- A source-bound UTF-8 byte probe of the 0.22.0 tree (`3242d762`, isolated `tests/harness.ts` and `tests/storage-fixture.ts`, default config, empty native transcript, `before_agent_start("Probe")` then `context`) measured the two `{name,description,parameters}` tool definitions as **1,728 JSON bytes**. A wholly absent store added **0 protocol and 0 projected-message bytes**. A validated empty Global state (`{}`) added **959 protocol bytes** and **321 serialized message bytes**; `global.working={sample:"x"}` added the same **959** plus **351 message bytes**. These component sizes include the projection marker in the message but exclude native prompt/tool wrappers, conversation, provider tokenization and variable user memory; they are not token-cost or cache-hit claims.
161
+ **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 surfaces. With unavailable memory the tools may still reject reads or writes: declared tools do not prove usable storage.
74
162
 
75
- Settings are read once at extension load. After editing, use `/reload` or restart Pi. A missing file uses defaults without creating a configuration file; malformed JSON, unknown keys, or invalid values fail loading rather than silently selecting another store.
163
+ **Loading rules.** Settings are read once at extension load; after editing, use `/reload` or restart Pi. A missing file uses defaults without creating a configuration file. Malformed JSON, unknown keys or invalid values fail loading rather than silently selecting another store.
76
164
 
77
165
  `PI_CODING_AGENT_DIR` changes both the default State Flow repository and its global configuration location. State Flow has no source-directory or Knowledge-root configuration. SDK repository overrides are documented under [embedding](architecture.md#embedding); an overridden repository owns its own root `config.json`.
78
166
 
79
167
  ### Diagnostic logging and privacy
80
168
 
81
- Rejected `patch_state` execution records may contain exact attempted arguments and useful draft text, plus the error category and tool/call identity. The `barrier-block` category instead records only the blocked tool name, call id, reason and batch tool names (never sibling arguments or reasoning); Passive has no patch barrier, and logging off records no barrier blocks. Asynchronous push failures retain the available redacted Git error there regardless of `logging`; interactive warnings stay short and appear once per failure streak, then reset on success. If logging the push failure is unavailable, one warning exposes the available detail instead. Successful patches are not logged; reasoning bodies are excluded. Logs are not semantic state, scope metadata, Pi checkpoints, or publication input. If the log path overlaps a custom state repository, capture fails closed instead of committing it. A logging failure changes no accepted state and produces at most one local warning.
169
+ **What gets recorded:**
170
+
171
+ - Rejected `patch_state` executions may include the exact attempted arguments and useful draft text, plus the error category and tool/call identity.
172
+ - The `barrier-block` category records only the blocked tool name, call id, reason and batch tool names, never sibling arguments or reasoning. Passive has no patch barrier, and with logging off no barrier blocks are recorded.
173
+ - Asynchronous push failures keep the available redacted Git error in the log regardless of `logging`. Interactive warnings stay short, appear once per failure streak and reset on success. If logging the push failure is unavailable, one warning shows the available detail instead.
174
+ - Successful patches are not logged, and reasoning bodies are excluded.
175
+
176
+ **What logs are not:** semantic state, scope metadata, Pi checkpoints or publication input. If the log path overlaps a custom state repository, capture fails closed instead of committing it. A logging failure changes no accepted state and produces at most one local warning. Logs stay local unless you move them; rotation and deletion are up to the operator.
82
177
 
83
- Logs remain local unless you move them; rotation/deletion is operator-owned. State Flow-authored errors and warnings display as one compact line: flatten nested/aggregate causes into transportable text rather than relying on `Error.cause`. Elide long operands with `…` before shortening prose so the operation, exact offending scope, target basename/suffix and actionable reason remain visible; do not split Unicode pairs or mistake prose apostrophes for quoted paths. Enabled diagnostic records keep the full target and rejected input for investigation. An explicit Start retry reports its final failure once rather than repeating its startup warning. Tool failures still keep the required blank line beneath their heading. Treat logs and state files as private. Removing a secret from current state does not erase older offsets, Git history, native sessions, or remote copies.
178
+ **How errors are displayed.** State Flow-authored errors and warnings appear as one compact line:
179
+
180
+ - Nested and aggregate causes are flattened into transportable text instead of relying on `Error.cause`.
181
+ - Long operands are elided with `…` before prose is shortened, so the operation, the exact offending scope, the target basename/suffix and the actionable reason stay visible. Unicode pairs are never split, and prose apostrophes are not mistaken for quoted paths.
182
+ - Enabled diagnostic records keep the full target and the rejected input for investigation.
183
+ - An explicit Start retry reports its final failure once instead of repeating its startup warning.
184
+ - Tool failures keep the required blank line beneath their heading.
185
+
186
+ Treat logs and state files as private. Removing a secret from current state does not erase older offsets, Git history, native sessions or remote copies.
84
187
 
85
188
  ## Status and controls
86
189
 
@@ -88,11 +191,53 @@ Logs remain local unless you move them; rotation/deletion is operator-owned. Sta
88
191
 
89
192
  - Selected CWD/session keys, internal step, effective `g#c#s#` scope-revision vector, and available hot-history depth.
90
193
  - Known recovery or publication failures, actual artifact counts when nonzero, and pending invalidations. Status does not discover or validate sources.
194
+ - A `Scope memory:` block with one line per scope that has content: the UTF-8 byte size of each present nonempty plane and, when `working` or `lazy` has top-level entries, the share owned by an open intent of that scope (for example `- cwd: intents 137 B, working 32 B; intent-owned working 1/2`). It is operator-only: no notice, threshold or model-facing effect.
91
195
  - One JSON representation of effective global → CWD → session memory, with a blank line between top-level semantic planes. Nested JSON is unchanged; individual scope JSON remains available through `read_state`.
92
196
 
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.
197
+ 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.
198
+
199
+ **Revisions and indicators:**
94
200
 
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).
201
+ - The terminal indicator is accent `state-flow` plus dim `active` or `passive`; Off hides it.
202
+ - Global, CWD and Session own independent semantic revisions. One atomic transition advances each materially changed scope once, including session-only response reconciliation.
203
+ - Effective has no scalar counter. It uses the compact lowercase `g#c#s#` revision vector (for example, `g15c8s31`), with no slashes or spaces between counters. The vector appears in `/state-flow-status` and in Telegram's Effective inspection, not in the compact indicators.
204
+
205
+ ### Telegram controls
206
+
207
+ When `pi-telegram` is available, its main-menu section shows `State Flow: active`, `State Flow: passive` or `State Flow: off`. The adapter is optional; the Pi commands work without it. All Telegram controls use the same lifecycle owners as the terminal commands.
208
+
209
+ **Mode controls:**
210
+
211
+ - A horizontal radio row presents `Off | Passive | Active`. The selected option uses 🟡, 🟣 or 🟢 respectively; each inactive option uses ⚫️.
212
+ - Telegram Active requested during a run waits for settlement; Passive and Off apply immediately.
213
+ - Ordinary successful controls add no redundant mode receipt; diagnostic outcomes stay visible.
214
+ - Off exposes neither tool nor State Flow model context.
215
+
216
+ **Menu layout:**
217
+
218
+ - The submenu heading shows the current value in monospace.
219
+ - The bold Mode heading uses a long dash, a description ending in a colon, and a blank line before its settings-style list. Each line has a monospaced minus and lowercase monospaced mode value, then a plain colon and description.
220
+ - 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 disabled native compaction.
221
+ - 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 the individual scopes and their combined view.
222
+ - Four direct Global/CWD/Session/Effective buttons follow without another chooser.
223
+
224
+ **Memory inspection:**
225
+
226
+ - Owner-scope Rich snapshots show `#revision`; Effective shows the vector.
227
+ - During a failed-Passive write fence, memory-enabled inspection uses the accepted cache without a potentially conflicting refresh.
228
+ - Otherwise, 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.
229
+ - Data and displayed revisions come from the same observation; absent or invalid memory stays unavailable.
230
+ - Stop, session/tree changes and shutdown cancel obsolete observations.
231
+ - The button acknowledges immediately, and a late failure appears in the menu instead of an expired callback popup.
232
+
233
+ **Inspecting while Off.** Explicit Off inspection reads current stored memory through a disposable reader.
234
+
235
+ - Session and Effective require validated same-session private authority and cannot show a fabricated empty layer or revision. Shared Global/CWD inspection stays available independently of private failures.
236
+ - 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 a future Passive/Active acquisition.
237
+ - Automatic Off callbacks never acquire memory.
238
+ - Current stored data does not prove that a selected past boundary is restorable.
239
+
240
+ Open implementation work is tracked in [BACKLOG.md](../BACKLOG.md).
96
241
 
97
242
  ## Storage and recovery
98
243
 
@@ -103,62 +248,172 @@ Use a dedicated directory. State storage and registered artifact sources have se
103
248
  <any exact registered path> optional external source owned outside State Flow
104
249
  ```
105
250
 
106
- Each scope materializes an anchored semantic-only `checkpoint.json` plus semantic-only lines in `patches.jsonl`. Scope `meta.json` holds temporal boundaries, CWD ownership where applicable, and runtime-owned artifact evidence. The session additionally uses `config.json` for behavior and `runtime.json` for branch/run recovery metadata; a full prompt is retained there only while its run is unfinished. CWD/session directories mirror Pi's native naming while validating canonical identities separately. See the [storage contract](architecture.md#storage-and-identity) for the exact layout.
251
+ Files per scope:
252
+
253
+ - Each scope materializes an anchored semantic-only `checkpoint.json` plus semantic-only lines in `patches.jsonl`.
254
+ - Scope `meta.json` holds temporal boundaries, CWD ownership where applicable, and runtime-owned artifact evidence.
255
+ - The session additionally uses `config.json` for behavior and `runtime.json` for branch/run recovery metadata. A full prompt is kept there only while its run is unfinished.
256
+ - CWD/session directories mirror Pi's native naming, while canonical identities are validated separately.
257
+
258
+ See the [storage contract](architecture.md#storage-and-identity) for the exact layout.
107
259
 
108
260
  ### Missing, partial, and malformed storage
109
261
 
110
- Missing documented fields inside a valid checkpoint or patch are supported. Current and historical semantic views include only known fields present in the selected scope or overlay; absent fields and empty responses are omitted. Higher scopes contribute only present values. Unknown top-level fields are ignored when reading checkpoints/patches and are not emitted on subsequent writes; nested data within known planes remains intact. An explicit `read_state` value query for an absent documented top-level field returns `null`, including empty/absent `session.response`. Reading and Start do not normalize files, advance revisions or require a migration. An empty semantic object is different from a missing file or missing ownership metadata.
262
+ **Missing fields are fine.** Missing documented fields inside a valid checkpoint or patch are supported.
111
263
 
112
- A checkpoint and tail are one semantic pair. If both live files for a global or CWD scope disappear, State Flow treats that complete absence as current empty shared reality. An authored `patch_state` applies to that empty basis under exclusion; normal file-cohort CAS creates the accepted pair without resurrecting cold values or orphaned compilation evidence. Raw precomputed replay still refuses a removed selected target rather than replaying stale normalized changes.
264
+ - Current and historical semantic views include only known fields present in the selected scope or overlay; absent fields and empty responses are omitted. Higher scopes contribute only present values.
265
+ - Unknown top-level fields are ignored when reading checkpoints/patches and are not emitted on later writes; nested data within known planes stays intact.
266
+ - An explicit `read_state` value query for an absent documented top-level field returns `null`, including an empty or absent `session.response`.
267
+ - Reading and Start do not normalize files, advance revisions or require a migration.
268
+ - An empty semantic object is different from a missing file or missing ownership metadata.
113
269
 
114
- Exactly one surviving pair member is corruption and fails closed. Present malformed JSON, incomplete predecessor envelopes, semantic/metadata boundary mismatches, identity contradictions, and partial session runtime evidence also remain fail-closed and are not replaced. A missing or expired private retained boundary is unavailable; State Flow does not substitute Git history or newer private files.
270
+ **Wholly absent shared files.** A checkpoint and its tail are one semantic pair. If both live files of a global or CWD scope disappear, State Flow treats that complete absence as current empty shared reality. An authored `patch_state` applies to that empty basis under exclusion, and normal file-cohort CAS creates the accepted pair without resurrecting cold values or orphaned compilation evidence. Raw precomputed replay still refuses a removed selected target rather than replaying stale normalized changes.
115
271
 
116
- After a selected-boundary failure, Passive may still expose current global/CWD memory, but it never grants access to the unavailable historical session layer or permission to publish an empty replacement. Historical session reads and every `patch_state` refuse without changing canonical files or appending substitute checkpoints. Passive/Off selection remains available and records the native policy/write fence described above; a subsequent reload may expose validated current memory read-only, not the unavailable selected history. Status distinguishes a write fence from unavailable materialization.
272
+ **Corruption fails closed.** These are never replaced:
117
273
 
118
- **Explicit Start uses current memory, not unavailable history.** It independently validates the current same-session canonical cohort, preserving private memory, artifact provenance, revisions, step and available aligned history. Expired active/passive pointers and unfinished runtime work no longer block activation. A pre-runtime selection also keeps current accepted same-session memory rather than resetting it. Start bootstraps the conversation available on the selected Pi branch without resurrecting an old unfinished specification or claiming that expired historical private state was restored. Independently advanced shared scopes may require a new temporal origin; unavailable history is never invented. Exact-cohort CAS rejects a concurrent writer, and incomplete/corrupt storage remains untouched. An unaccepted native fork still retries its exact source rather than inventing child memory. When evidence is missing, repair it, select a retained boundary, or open a genuinely new Pi session.
274
+ - exactly one surviving pair member;
275
+ - present malformed JSON or unsupported checkpoint envelopes;
276
+ - semantic/metadata boundary mismatches and identity contradictions;
277
+ - partial session runtime evidence.
119
278
 
120
- Missing artifact provenance inside an otherwise complete scope `meta.json` means compilation evidence is unavailable while semantic state remains usable; removing the whole metadata file also removes temporal authority and fails closed. An unavailable registered source path does not prove that durable artifact routing was deleted, and external files are never created. State Flow has no durable push queue or publication-worker lease; failed replication is attempted again only after a later accepted turn. See the complete [filesystem recovery contract](filesystem-recovery.md).
279
+ A missing or expired private retained boundary is unavailable; State Flow does not substitute Git history or newer private files.
280
+
281
+ **After a selected-boundary failure:**
282
+
283
+ - Passive may still expose current global/CWD memory, but never the unavailable historical session layer or permission to publish an empty replacement.
284
+ - Historical session reads and every `patch_state` refuse without changing canonical files or appending substitute checkpoints.
285
+ - Passive/Off selection stays available and records the native policy/write fence described above. A later reload may expose validated current memory read-only, not the unavailable selected history.
286
+ - Status distinguishes a write fence from unavailable materialization.
287
+
288
+ **Explicit Start uses current memory, not unavailable history.**
289
+
290
+ - It independently validates the current same-session canonical cohort, preserving private memory, artifact provenance, revisions, step and available aligned history.
291
+ - Expired active/passive pointers and unfinished runtime work do not block activation. A pre-runtime selection also keeps current accepted same-session memory instead of resetting it.
292
+ - Start bootstraps the conversation available on the selected Pi branch, without resurrecting an old unfinished specification or claiming that expired historical private state was restored.
293
+ - Independently advanced shared scopes may require a new temporal origin; unavailable history is never invented.
294
+ - Exact-cohort CAS rejects a concurrent writer, and incomplete or corrupt storage stays untouched.
295
+ - An unaccepted native fork still retries its exact source rather than inventing child memory.
296
+ - When evidence is missing, repair it, select a retained boundary, or open a genuinely new Pi session.
297
+
298
+ **Artifact evidence and replication:**
299
+
300
+ - Missing artifact provenance inside an otherwise complete scope `meta.json` means compilation evidence is unavailable, while semantic state stays usable. Removing the whole metadata file also removes temporal authority and fails closed.
301
+ - An unavailable registered source path does not prove that durable artifact routing was deleted, and external files are never created.
302
+ - State Flow has no durable push queue or publication-worker lease; failed replication is retried only after a later accepted turn.
303
+
304
+ See the complete [filesystem recovery contract](filesystem-recovery.md).
121
305
 
122
306
  ### Canonical files and optional Git backup
123
307
 
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.
308
+ Canonical scope/runtime files own the current materialization and retained hot history, whether or not Git is available. Pi checkpoints identify a retained semantic boundary, not a Git commit or an arbitrary historical snapshot. Restart and branch restoration fail closed when the selected boundary has expired, rather than substituting newer files as the selected past.
125
309
 
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.
310
+ **Local backup commit:**
127
311
 
128
- ### Moving a store and the 0.17 format boundary
312
+ - After an accepted turn has reconciled its response, Pi'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.
313
+ - The capture waits cancelably when Pi supplies an operation signal. When that signal is absent at settlement, an occupied backup/storage mutex explicitly defers the backup until a later accepted turn instead of trapping Abort. Deferral neither changes memory nor starts a push.
314
+ - Off and shutdown cancel owned pending local attempts. Only cleanup of already-acquired locks/resources may continue; Off admits no new capture.
129
315
 
130
- An SDK `repositoryRoot` override or a different `PI_CODING_AGENT_DIR` selects a location; it does not relocate existing state or retained history. Copy the complete canonical store while all writers are quiescent, or use a genuinely new Pi session for an independent store. Copying only current checkpoints without their tails and metadata cannot preserve retained boundaries.
316
+ **Remote push:**
131
317
 
132
- Starting with 0.17, State Flow accepts only its canonical checkpoint/tail, temporal metadata, and separate session config/runtime contract; that boundary still applies to current versions. A canonical 0.17 scope written before independent revisions remains readable: its initial counter uses only the retained semantic tail and is persisted in metadata version 2 on the next owned write, without inventing folded ancestry. Version 1 remains readable; older writers refuse version 2 through the existing provenance-version fence, so cooperating instances should upgrade together. Predecessor checkpoint envelopes, combined session metadata, `state.json`, hashed layouts, and semantic Pi checkpoint envelopes fail as unsupported without rewriting existing bytes. Canonical semantic objects lacking fields introduced later, such as `intents` or `lazy`, are valid sparse state and do not cross this format boundary. State Flow does not provide an in-place converter; external conversion or a fresh store is operator-owned.
318
+ - 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.
319
+ - Within one Pi process, an in-flight push per repository makes overlapping attempts skip; a later accepted turn retries the latest backup, without a durable queue.
320
+ - Off terminates only its own 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.
321
+ - Shutdown cancels its own pushes and waits for that repository's in-flight push to close or time out.
322
+ - Cancellation never rolls back already accepted local or remote commits.
323
+
324
+ Commit or push failure is diagnostic-only; repeated push failures warn once per failure streak and stay locally diagnosable. Git availability never changes semantic authority, step or retained lineage.
325
+
326
+ ### Moving a store and supported formats
327
+
328
+ **Moving a store.** An SDK `repositoryRoot` override or a different `PI_CODING_AGENT_DIR` selects a location; it does not relocate existing state or retained history. Copy the complete canonical store while all writers are quiescent, or use a genuinely new Pi session for an independent store. Copying only current checkpoints, without their tails and metadata, cannot preserve retained boundaries.
329
+
330
+ **Supported formats.** State Flow accepts only canonical checkpoint/tail files, temporal metadata and the separate session config/runtime contract.
331
+
332
+ - A canonical scope without a revision counter is readable. Its initial counter uses only the retained semantic tail and is persisted in metadata version 2 on the next owned write, without inventing folded ancestry.
333
+ - Version 1 stays readable. Older writers refuse version 2 through the existing provenance-version fence, so cooperating instances should upgrade together.
334
+ - Unsupported checkpoint envelopes, combined session metadata, `state.json`, hashed layouts and semantic Pi checkpoint envelopes fail as unsupported, without rewriting existing bytes.
335
+ - Canonical semantic objects lacking optional fields, such as `intents` or `lazy`, are valid sparse state and do not cross this boundary.
336
+ - There is no in-place converter; external conversion or a fresh store is up to the operator.
133
337
 
134
338
  ### Conflicts and interrupted publication
135
339
 
136
- `patch_state` asynchronously waits for a live cooperating writer, with native cancellation and no ordinary-contention deadline. It then applies authored Global/CWD operations to current canonical values: unmentioned fields survive, overlapping assignments follow successful acceptance order, and correct repeats return `State already current.` without another semantic revision. Session remains private; invalid/unavailable evidence and an independently changed private cohort still fail closed. Do not repeat external actions while memory publication waits.
340
+ **Patches.** `patch_state` waits asynchronously for a live cooperating writer, with native cancellation and no ordinary-contention deadline. It then applies authored Global/CWD operations to the current canonical values:
341
+
342
+ - Unmentioned fields survive.
343
+ - Overlapping assignments follow successful acceptance order.
344
+ - Correct repeats return `State already current.` without another semantic revision.
345
+ - Session stays private; invalid or unavailable evidence and an independently changed private cohort still fail closed.
137
346
 
138
- Final-answer reconciliation also waits cancelably, then saves the response and completed-run lifecycle together over current shared memory. Stop, session/tree changes, shutdown and a superseding answer cancel obsolete waits without modifying newer work. A failed or canceled publication leaves the prior response and unfinished run intact; it never requests a repair inference.
347
+ Do not repeat external actions while memory publication waits.
139
348
 
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.
349
+ **Final answers.** Final-answer reconciliation also waits cancelably, then saves the response and the completed-run lifecycle together over current shared memory. Stop, session/tree changes, shutdown and a superseding answer cancel obsolete waits without modifying newer work. A failed or canceled publication leaves the prior response and unfinished run intact; it never requests a repair inference.
141
350
 
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.
351
+ **Run preparation.** 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 stays 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.
143
352
 
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.
353
+ **Other waits:**
145
354
 
146
- Independently valid shared streams may require a fresh composed origin without inventing cross-writer history. Authored patches use that current basis; raw precomputed replay still refuses an advanced target instead of applying stale normalized changes. Rollback restores only bytes still matching that publisher's output and preserves detected external changes. See [performance evidence](performance.md) for measured contention and the [acceptance map](temporal-acceptance.md) for the tested boundaries; the [backlog](../BACKLOG.md) owns open implementation work.
355
+ - Telegram shared inspection also awaits exclusion, read-only.
356
+ - Backup capture uses the awaited API too, with the no-signal settlement exception described above.
357
+ - Passive selection on an accepted runtime 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.
358
+ - Current-head Start similarly waits before enabling the mode, cancellable by Stop, selection, shutdown and any available native operation signal.
359
+ - Startup, tree, auto-start, fork and failed-Stop reload restoration (including Start's initial attachment and fork retry) also await exclusion. Until acceptance, the mode stays in the selected inactive policy and private memory reports the pending selection. Off stays Off; later inactive choices survive read-only recovery without cancelling it.
360
+
361
+ **Locks.** Interrupted, malformed or unreadable locks are never stolen. Reconcile the owner rather than deleting locks or state directories just 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.
362
+
363
+ **After a crash.** Fatal process termination can leave an incomplete canonical file cohort. Before repairing:
364
+
365
+ 1. Quiesce all store writers.
366
+ 2. Preserve the complete store plus the selected Pi retained-boundary references.
367
+ 3. Reconcile the exact files against the last complete checkpoint/tail/metadata cohort.
368
+
369
+ No automatic crash repair or power-loss durability is promised, and Git backup has no semantic recovery authority.
370
+
371
+ **Concurrent shared streams.** Independently valid shared streams may require a fresh composed origin, without inventing cross-writer history. Authored patches use that current basis; raw precomputed replay still refuses an advanced target instead of applying stale normalized changes. Rollback restores only bytes that still match that publisher's output and preserves detected external changes. See [performance evidence](performance.md) for measured contention and the [acceptance map](temporal-acceptance.md) for the tested boundaries; the [backlog](../BACKLOG.md) owns open implementation work.
147
372
 
148
373
  ## Lazy navigation and historical reading
149
374
 
150
- Lazy bodies require explicit reads. Automatic state and recent-transition projections omit them, including lazy deletions; bounded `lazy_navigation` can still show the current layer's presence, path and key types. Explicit `session.lazy.releasePlan` reads the current value, while `session[3].lazy.releasePlan` reads the exact older value only if that causal boundary remains available. Filtering automatic visibility does not renumber history or erase already communicated native/user/tool/response text.
375
+ Lazy bodies require explicit reads:
376
+
377
+ - Automatic state and recent-transition projections omit them, including lazy deletions. Bounded `lazy_navigation` can still show the current layer's presence, path and key types.
378
+ - Explicit `session.lazy.releasePlan` reads the current value; `session[3].lazy.releasePlan` reads the exact older value only if that causal boundary is still available.
379
+ - Filtering automatic visibility does not renumber history or erase already communicated native/user/tool/response text.
380
+
381
+ **Historical search is task-driven.** A missing path or runtime hint does not by itself require historical search.
151
382
 
152
- A missing path or runtime hint does not by itself require historical search. If the old value is unnecessary, continue without searching. If it can help the current task, the agent may choose a targeted historical read without separate user permission. Treat any found value as historical evidence, not automatically as current memory; do not restore deleted data without an independent reason. Do not scan all offsets or use repair inference or automatic hydration.
383
+ - If the old value is unnecessary, continue without searching.
384
+ - If it can help the current task, the agent may choose a targeted historical read without separate user permission.
385
+ - A found value is historical evidence, not automatically current memory; do not restore deleted data without an independent reason.
386
+ - Do not scan all offsets, and do not use repair inference or automatic hydration.
153
387
 
154
- A dangling-reference hint accompanies only an unresolved single value read with verified current reference sources. Its `paths` are the owners of those references, not verified new locations of the requested data. It does not prove that the target existed, remains retained or was moved. The bounded lookup searches current state only and emits no lazy bodies. A proven stale reference may be repaired within touched work without resurrecting its target. Without a match, ordinary missing-path errors remain; keys, patch and batch projections retain their existing contracts.
388
+ **Dangling-reference hints.** A hint accompanies only an unresolved single value read that has verified current reference sources.
155
389
 
156
- Artifact freshness/invalidations and optional Skill acquisition hints keep their exact source/scope targets. Hints expose possibilities and diagnostic evidence; the current task determines whether action is necessary.
390
+ - Its `paths` are the owners of those references, not verified new locations of the requested data.
391
+ - It does not prove that the target existed, is still retained or was moved.
392
+ - The bounded lookup searches current state only and emits no lazy bodies.
393
+ - A proven stale reference may be repaired within touched work, without resurrecting its target.
394
+ - Without a match, ordinary missing-path errors remain; keys, patch and batch projections keep their existing contracts.
395
+
396
+ Intent-owned lazy or working keys disappear when their owning intent is deleted, so a later missing path may be an expected cascade rather than a broken reference. The deletion appears in the accepted `patch_state` receipt and in the scope's retained patch history. See [intent ownership](lazy-state.md#intent-ownership).
397
+
398
+ Artifact freshness/invalidations and optional Skill acquisition hints keep their exact source/scope targets. Hints expose possibilities and diagnostic evidence; the current task decides whether action is necessary.
157
399
 
158
400
  ## Memory and source acquisition
159
401
 
160
- The agent should use sufficient materialized knowledge before rereading files. Read for a concrete gap, exact-source/edit operation, evidenced invalidation, contradiction/failure, explicit request, or bounded maintenance—not simply because a new session began.
402
+ The agent should use sufficient materialized knowledge before rereading files. It reads for a concrete gap, an exact-source/edit operation, an evidenced invalidation, a contradiction or failure, an explicit request, or bounded maintenance, not simply because a new session began.
403
+
404
+ **Artifact maintenance:**
405
+
406
+ - It inspects only exact paths already registered in global, CWD or session state, using `size + mtimeNs`, without directory traversal or generic content hashing.
407
+ - Proven-missing paths are pruned from their exact owning scopes. Unavailable, relative, directory and symlink paths are preserved.
408
+ - Changed sources keep their artifact value and receive a runtime-only model `hint` until a stable read and same-path compilation update the hidden provenance.
409
+ - Model patches cannot author or delete runtime provenance or hints.
410
+
411
+ **Skills.** Only exact registered Pi Skill reads enter the separate hash protocol. Public Pi source provenance maps user Skills to global, project Skills to CWD and temporary Skills to session. Matching compiled hashes need no update, and an uncompiled read stays volatile without blocking unrelated patches.
412
+
413
+ **Packaged Skills:**
161
414
 
162
- Artifact maintenance inspects only exact paths already registered in global, CWD, or session state, using `size + mtimeNs` without directory traversal or generic content hashing. Proven-missing paths are pruned from their exact owning scopes; unavailable, relative, directory, and symlink paths are preserved. Changed sources keep their artifact value and receive a runtime-only model `hint` until a stable read and same-path compilation updates hidden provenance. Only exact registered Pi Skill reads enter the separate hash protocol. Public Pi source provenance maps user Skills to global, project Skills to CWD and temporary Skills to session; matching compiled hashes require no update, and an uncompiled read remains volatile without blocking unrelated patches. Model patches cannot author or delete runtime provenance or hints.
415
+ - `state-flow-guide` answers concrete operational questions about reads, patches, inheritance, acquisition, completion and recovery, without starting cleanup.
416
+ - `state-flow-memory` handles explicitly requested bounded curation and externally verified transfers. External transfers use the destination's native receipt and keep the source whenever acceptance is uncertain.
417
+ - Feature/release/project boundaries may motivate recommending cleanup, not starting an audit. Ordinary handoffs reconcile touched state; neither Skill is a background maintenance loop.
163
418
 
164
- The packaged `state-flow-guide` Skill answers concrete operational questions about reads, patches, inheritance, acquisition, completion, and recovery without initiating cleanup. The separate `state-flow-memory` Skill handles explicitly requested bounded curation and externally verified transfers. Feature/release/project boundaries may motivate recommending cleanup, not starting an audit. Ordinary handoffs reconcile touched state; neither Skill is a background maintenance loop. External transfers use the destination's native receipt and preserve the source whenever acceptance is uncertain. Artifact/compiler details and model-tool contracts belong in the [architecture](architecture.md#artifact-routing).
419
+ Artifact/compiler details and model-tool contracts belong in the [architecture](architecture.md#artifact-routing).