@llblab/pi-kit 0.10.8 → 0.11.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 (27) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -1
  3. package/node_modules/@llblab/pi-state-flow/AGENTS.md +13 -10
  4. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +15 -1
  5. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +13 -0
  6. package/node_modules/@llblab/pi-state-flow/README.md +52 -261
  7. package/node_modules/@llblab/pi-state-flow/docs/README.md +5 -1
  8. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +47 -26
  9. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +97 -0
  10. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +47 -0
  11. package/node_modules/@llblab/pi-state-flow/docs/performance.md +459 -0
  12. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +35 -3
  13. package/node_modules/@llblab/pi-state-flow/docs/usage.md +134 -0
  14. package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +19 -3
  15. package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +74 -0
  16. package/node_modules/@llblab/pi-state-flow/lib/context.ts +12 -12
  17. package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +4 -2
  18. package/node_modules/@llblab/pi-state-flow/lib/discovery.ts +21 -5
  19. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +146 -37
  20. package/node_modules/@llblab/pi-state-flow/lib/git.ts +142 -42
  21. package/node_modules/@llblab/pi-state-flow/lib/publication.ts +80 -27
  22. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +109 -7
  23. package/node_modules/@llblab/pi-state-flow/lib/status.ts +7 -12
  24. package/node_modules/@llblab/pi-state-flow/lib/storage.ts +2 -1
  25. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +2 -3
  26. package/node_modules/@llblab/pi-state-flow/package.json +5 -4
  27. package/package.json +2 -2
@@ -1,303 +1,94 @@
1
1
  # Pi State Flow
2
2
 
3
- > Inspired by [SKILL.state](https://arxiv.org/html/2608.26263v2)
4
-
5
3
  ![pi-state-flow banner](https://raw.githubusercontent.com/llblab/pi-state-flow/main/banner.jpg)
6
4
 
7
- State Flow exposes a **temporally indexed materialized state** for Pi:
8
-
9
- ```text
10
- state[0] = now
11
- state[1] = one accepted transition ago
12
- ...
13
- state[7] = seven accepted transitions ago
14
-
15
- state.global[n] state.cwd[n] state.session[n]
16
- projections at the SAME temporal boundary
17
- ```
18
-
19
- `patch_state` explicitly advances that stream. Optional Git preserves complete older history for Git-backed transitions; without Git, files retain current state and its proven hot window. State Flow compiles decision-relevant reality; it neither owns Knowledge semantics nor replaces Pi's native tool loop or inspectable session trace.
20
-
21
- ## Installation
22
-
23
- Requirements: Pi `0.84.4–0.84.x` and Node.js `22.19.0` or newer. Git is optional; when installed, it needs a configured commit identity. A remote is optional and operator-owned.
24
-
25
- ```bash
26
- pi install npm:@llblab/pi-state-flow
27
- # Or:
28
- pi install git:github.com/llblab/pi-state-flow
29
- ```
5
+ **Working memory for Pi, carried with the session.**
30
6
 
31
- Pi packages execute with full user permissions; review the source before installing. An installed published version may precede this working-tree architecture.
7
+ Keep decisions, constraints, verified findings, and next steps without sending every completed tool exchange back to the model. State Flow lets the agent maintain explicit state; Pi still owns the conversation, the native tool loop, and the complete inspectable trace.
32
8
 
33
- ## Configuration
9
+ > Inspired by [SKILL.state](https://arxiv.org/html/2608.26263v2).
34
10
 
35
- Optional `~/.pi/agent/state-flow.json` (or `state-flow.json` beneath `PI_CODING_AGENT_DIR`):
36
-
37
- ```json
38
- {
39
- "directory": "~/.pi/agent/state-flow",
40
- "autoStart": false,
41
- "logging": false,
42
- "remotePublication": "turn-end"
43
- }
44
- ```
45
-
46
- - `directory`: State storage location; omitted defaults to `state-flow/` beneath Pi's agent directory. Absolute paths, `~`/`~/` and relative paths are supported; relative paths resolve from the configuration directory, not the project CWD.
47
- - `autoStart`: Set to `true` to enable State Flow automatically for genuinely new sessions, including fresh CWDs. Omitted defaults to `false`: manual activation, even when previous CWD materialization exists.
48
- - `logging`: Set to `true` to append JSONL diagnostics for rejected `patch_state` calls and unresolved terminal drafts to `tmp/state-flow/logs.jsonl` beneath Pi's agent directory; omitted or `false` writes nothing. Rejected calls retain their exact attempted arguments, the precise error, and, when available, the tool identity, call id, resolution attempt, and terminal-eligibility state; successful patches are never logged. Exact text blocks are retained only when useful, while reasoning bodies are excluded. The file stays local unless you move it, deleting or rotating it is operator-owned, and logging never enters semantic state, metadata, checkpoints, or the state repository. If a custom state repository contains the diagnostic path, capture fails closed rather than committing the log. A write failure changes nothing except one local warning.
49
- - `remotePublication`: For new runtimes, `turn-end` (default) queues one newest target after local acceptance and pushes asynchronously; `off` keeps commits local; `transition` preserves legacy synchronous push behavior. A resumed branch keeps its persisted policy.
50
-
51
- Configuration is read at extension load; edit it and use `/reload` (or restart Pi) before opening a new session. Existing branches retain their stored enablement on resume/tree navigation. `/state-flow-stop` does not rewrite this file or disable automatic mode for later new sessions. Invalid JSON, unknown keys or invalid values fail extension loading rather than silently choosing another directory. A missing file uses defaults and is not generated automatically.
52
-
53
- The configuration file stays in Pi's agent directory when state storage moves. A directory override selects a store; it does not migrate old data or Git objects. SDK embedders can set `StateFlowExtensionOptions.agentDir` for the profile, `repositoryRoot` to override the configured state directory, and `knowledgeRoot` independently for Markdown sources.
54
-
55
- ## Usage and activation
11
+ ## The idea
56
12
 
57
13
  ```text
58
- /state-flow-start # Initialize missing materialization and enable this branch
59
- /state-flow-status # Inspect runtime, semantic, freshness, and publication diagnostics
60
- /state-flow-stop # Disable this branch without deleting semantic state
14
+ Current state + New request
15
+
16
+ Pi's native tool loop
17
+
18
+ Updated state + Answer
19
+
20
+ Next request
61
21
  ```
62
22
 
63
- A genuinely new session starts in ordinary Pi mode unless `autoStart` is enabled. Manual-mode startup is read-only with respect to storage initialization/migration. Configured automatic start uses the same optional-Git setup as explicit start and can create missing CWD materialization. Each enabled new session gets its own empty session layer and inherits only global/CWD state. It never borrows another session's values. Starting mid-conversation retains the active pre-Flow context for one complete bootstrap run; its `patch_state` resolution must migrate future-relevant context.
23
+ During a request, the model retains the current tool trajectory. Between requests, State Flow replaces completed ordinary conversation history in model context with the current state and recent transitions. It does not delete Pi's session history.
64
24
 
65
- Stopping changes the current session/branch configuration, preserves semantic checkpoints and tails, and creates no semantic history step. For the remainder of that physical session—including reload, resume, and `/tree` restoration—it retains a bounded passive projection: frozen effective state at the exit boundary plus messages created after stop. Semantic tools, protocol, resolution, and artifact maintenance are disabled, but pre-stop raw history cannot reappear in the next inference. Active restart replaces passive mode with active runtime context and uses that same bounded boundary for its one migration run; it does not resurrect the pre-stop transcript. A new or forked physical session does not inherit the handoff. Stop does not change agent-level `autoStart`. Resume and `/tree` restore selected branch provenance, not arbitrary repository `HEAD`.
66
-
67
- The compact status is an accent `state-flow` and dim `#<step>`. Detailed status distinguishes runtime config/meta from semantic materialization, reports scope keys, the selected temporal head and runtime revision, available hot offsets, per-scope retained patch tails, artifact counts, stale Markdown reasons, and pending publication. Retained tails may include inherited pre-origin records, so their counts are not active history depth. It labels global/CWD/session/effective state without dumping source bodies. Failed inspection means unavailable evidence, never a falsely clean count.
68
-
69
- When the optional `pi-telegram` extension is installed, State Flow appears exactly once in Telegram: the inline main menu places a `🌀 State Flow: #N` or `🌀 State Flow: off` section button directly before Settings, and that button's label carries the live status. The button opens a compact submenu whose header repeats the same state line with the live value in monospace, followed by a short explanation of what State Flow is; the only action is `Start` (or `Stop` while enabled), with the transport-owned `⬆️ Main menu` row above it. Starting while a run is active waits for that run to settle; stopping applies immediately. Registration fails open when the transport is absent, retries when the section registry becomes ready, and disposes on session shutdown; the `/state-flow-*` commands remain the authority and nothing changes for hosts without `pi-telegram`.
70
-
71
- ## State, scope, and time
72
-
73
- Every scope has exactly the same semantic shape:
74
-
75
- ```json
76
- {
77
- "artifacts": {},
78
- "contract": {},
79
- "working": {},
80
- "response": "Latest complete user-facing answer"
81
- }
82
- ```
25
+ The agent curates what matters; the extension validates, persists, and projects the accepted state. This is working memory, not automatic proof that a remembered fact is true.
83
26
 
84
- - `artifacts`: Source-path-keyed compiled routing metadata and reusable operational knowledge. Runtime-owned freshness evidence lives in the scope `meta.json` and never reaches this projected shape.
85
- - `contract`: Stable requirements, decisions, rejected approaches, and interface commitments.
86
- - `working`: Verified observations, validation, failures, unresolved questions, and exact continuation.
87
- - `response`: The complete answer captured by the runtime, normally in session state; models cannot patch it directly.
27
+ ## Quick start
88
28
 
89
- Effective state recursively overlays `global cwd session`; session wins. Scope is ownership, not instruction authority. Use session for branch/run-local continuation, CWD for project-local reusable state and Skill artifacts, and global for cross-project knowledge. Scope-local deletion reveals lower-scope values, including when reconstructing history.
29
+ Requires Pi `0.84.4–0.84.x` or `0.85.1–0.85.x` and Node.js `22.19.0` or newer. See the [SDK compatibility matrix](docs/compatibility.md) for exact tested stacks. Git is optional; using it requires a configured commit identity.
90
30
 
91
- Each accepted materially effective transition has one opaque identity and explicit parent lineage. Multi-scope patches share that identity. Unchanged scopes have no patch for that boundary and retain their values. Temporal position is not a count of local mutations or a timestamp sort. A branch-local ordinal may order parent-linked identities but cannot replace identity or merge forks.
92
-
93
- For example:
94
-
95
- ```text
96
- Boundary T181 T182 T183 T184
97
- Global G G G' G'
98
- CWD C C' C' C''
99
- Session S S' S'' S'''
100
-
101
- At T184:
102
- state[1] = overlay(G', C', S'')
103
- state.cwd[1] = C'
104
- state.cwd[2] = C'
105
- state.global[1] = G'
106
- ```
107
-
108
- `state.cwd[1]` is not the preceding CWD patch. Every projection first resolves the same target in the active lineage. Offsets zero through seven are the hot range; offsets before a new or migrated lineage's proven origin are explicitly unavailable until enough transitions exist. Offset eight is outside this read contract even when Git contains older history.
109
-
110
- ### Lazy historical reads
111
-
112
- Normal inference receives current effective `state[0]`, useful compact transition context, the current specification, and the complete current-run trajectory. It does not receive eight full snapshots. History is materialized only on a requested effective or scope read.
113
-
114
- The pure accessor is `readTemporalState(view, offset, scope?)` in `lib/temporal.ts`, with scope omitted for effective state. The live adapter exposes the same lazy read semantics to embedders through `StateFlowExtensionOptions.onRuntime`; the callback receives a cached-runtime `read(offset?, scope?)` accessor. The model tool `read_state` accepts optional `offset` (integer 0–7, default 0) and `scope` (`effective`, `global`, `cwd`, or `session`, default `effective`). For example:
115
-
116
- ```json
117
- {"offset": 1, "scope": "cwd"}
118
- ```
119
-
120
- It returns one `{offset, scope, boundary, state}` result from cached runtime, with no publication, checkpoint append, or history step. Unavailable pre-origin history is an error, not an empty state. Use it for a concrete historical or scope-specific gap, not routine rereading of current context. Both State Flow tools are active only while the selected branch is enabled; `patch_state` remains the sole mutator and blocks `read_state` siblings at its inference barrier. SDK embedders using an explicit tool allowlist must include `read_state` as well as `patch_state`. The model reasons about state, scope, time, and transitions, not checkpoint folding mechanics.
121
-
122
- ## Temporal storage
123
-
124
- State Flow owns a separate state directory at `~/.pi/agent/state-flow/`, optionally backed by Git. Knowledge remains an independent Markdown source at `~/.pi/agent/knowledge/`. Both defaults follow Pi's configured agent directory (`PI_CODING_AGENT_DIR`); [configuration](#configuration) can select a different state store. Changing the storage root does not redirect Markdown discovery.
125
-
126
- ```text
127
- state-flow/
128
- ├── .git/ # When Git-backed
129
- ├── checkpoint.json
130
- ├── patches.jsonl
131
- ├── meta.json
132
- └── <cwd-key>/
133
- ├── checkpoint.json
134
- ├── patches.jsonl
135
- ├── meta.json
136
- └── <session-key>/
137
- ├── checkpoint.json
138
- ├── patches.jsonl
139
- ├── config.json
140
- └── meta.json
141
- ```
142
-
143
- Directory names deliberately mirror Pi's native session layout. For example, `/home/llb/Repos/deos` is stored as `--home-llb-Repos-deos--`, and `2026-09-07T20-01-08-993Z_<uuid>.jsonl` uses `2026-09-07T20-01-08-993Z_<uuid>` as its session directory. In-memory sessions derive that same `<timestamp>_<uuid>` form from Pi's header. The UUID remains the authoritative runtime identity; session metadata and CWD checkpoint ownership reject foreign identities and CWD-name collisions without hiding another digest in the path.
144
-
145
- Explicit `/state-flow-start` creates a missing state directory and returns after establishing locally usable state. With Git available, start initializes an exact-root Git repository when needed, including a populated state directory, without deleting existing files; unrelated worktree content follows the complete-delta Git commit rule below. Normal `turn-end` and `off` activation never waits for remote push, canonical stores skip predecessor-format planning, and Markdown freshness discovery is deferred until the next enabled inference. An active file-backed branch must identify its exact current cohort before it can be adopted into Git. If the Git executable is absent, state persists directly to files without repository operations. Git command failures, corruption, or permission errors are not treated as executable absence. Manual-mode startup, status, and branch restoration do not initialize Git; configured automatic start for a new session may do so. The extension creates no GitHub account, external repository, or remote configuration, and does not invent a Git commit identity.
146
-
147
- For local debugging after Git-backed initialization:
31
+ From npm:
148
32
 
149
33
  ```bash
150
- git -C ~/.pi/agent/state-flow status --short
151
- git -C ~/.pi/agent/state-flow log --oneline -10
152
- git -C ~/.pi/agent/state-flow show <revision>:checkpoint.json
153
- ```
154
-
155
- `/state-flow-status` identifies the active scope keys and selected revision. Live files may belong to a later branch; use that selected revision for historical inspection rather than assuming the worktree represents the current Pi branch. State may include private session content; review it before configuring any remote.
156
-
157
- All three semantic scopes use one storage model:
158
-
159
- ```text
160
- current scope = materialize(anchored checkpoint, ordered patch tail)
161
- current effective = overlay(global current, CWD current, session current)
34
+ pi install npm:@llblab/pi-state-flow
162
35
  ```
163
36
 
164
- The checkpoint is an **older** materialized scope snapshot with an unambiguous `through` boundary. Its envelope is runtime-owned; its `state` contains only the four semantic fields. Each `patches.jsonl` holds at most seven scope-local replay records after that anchor. A record carries the shared transition identity/lineage and an effective semantic patch; runtime-observed artifact freshness remains in scope metadata, outside semantic replay.
165
-
166
- On an eighth scope patch, apply the oldest retained patch into the checkpoint, advance `through`, remove that patch, and append the new one. This deterministically preserves current state and the seven-transition hot window. Sparse scopes may keep older checkpoints; their values are still reconstructed at the same requested effective boundary. Never replay a tail over an already-current snapshot or silently drop an unapplied patch. The implemented `serializeScopeStream`/`parseScopeStream` codec emits deterministic checkpoint/JSONL bytes and validates complete replay input, including semantic results, before acceptance. `publishTemporalStateToGit` writes selected streams from one validated view through exact-output Git publication, rejects omitted changes and stale/wrong-session bases, and leaves unchanged scopes alone. `loadScopeStream` reads the live pair; `loadTemporalRevision` reads regular-file Git objects without moving the worktree. Neither invents missing runtime lineage; callers must supply the lineage belonging to the same revision. Oversized tails, invalid lineage, incomplete pairs, and no-op records are rejected; legacy current-state documents require explicit migration rather than implicit decoding.
167
-
168
- Accepted replay cohorts contain an identity and exact scope patches, without an independent timestamp clock or current-state publication DTO. Staging validates both semantic hashes and the active causal-boundary identity. Compact transition context derives directly from the selected lineage; the per-scope projection budget is the fixed shared seven-transition window and never changes the shared temporal target of `state[n]`. Legacy explanatory journals and Pi `recentTransitions` payloads are not semantic recovery inputs.
169
-
170
- Live files, or their branch-selected cached representation, serve hot materialization. When available, Git serves complete cold history for committed transitions, durable provenance, explicit historical inspection, and branch restoration; it is not queried to rebuild current state on every inference. There is no second unbounded event store, database, `.state-flow`, `scopes`, or parallel history directory.
171
-
172
- ### Runtime ownership and Git publication
173
-
174
- Session `config.json` owns runtime behavior such as `enabled`. Session `meta.json` owns temporal head/lineage, counters, durable base, Pi branch correlation, pending publication, and migration/version metadata. Global, CWD, and session scope `meta.json` files also own runtime artifact provenance (`sourceHash`, `compilerRevision`, `compiledAt`); the session file carries the session scope's provenance beside its runtime record. They are not model-patchable state and do not overlay into effective state. Pi checkpoints bind the selected branch to the corresponding durable runtime/temporal revision. The implemented runtime codec records version, canonical CWD/session identity, bounded active lineage, counters and run metadata, `revision: "self"`, and an unconfirmed publication intent. The self reference resolves to the last commit owning either member of the config/meta pair, so config-only changes advance runtime revision without semantic history, while unrelated commits in the state repository do not change its meaning. The commit hash is supplied during resolution rather than embedded in its own content; the resulting publication target identifies the existing commit to reconcile or retry. Unconfirmed means no durable confirmation is available, not proof that the push failed.
175
-
176
- Git-backed Pi checkpoint data is exactly `{"revision":"<full commit hash>"}`; file-only checkpoints use `{"revision":"file:<64 lowercase hex>"}` for an exact current-cohort reference. `{"disabled":true}` denotes an ordinary disabled branch without durable runtime. Configuration, counters, specification, lineage, and semantic state are not copied into these entries. Older config/meta and state-bearing checkpoints remain read-only compatibility input. Invalid immutable pointer targets fall back through the selected branch; transient publication-lock failure instead retains the selected revision for retry. Explicit start on a pre-runtime branch establishes an empty session origin, even if a later branch already created same-session files. Shared streams remain unchanged and the later session state remains recoverable from its Git revision; it is not imported into the new origin. Legacy checkpoint syntax and immutable targets undergo the same fallback checks, while an unanchored legacy semantic payload cannot be silently reduced to an ordinary-disabled marker. Stop on an unproven branch fails visibly instead of turning failed recovery into permission to replace existing runtime; select a valid checkpoint before retrying.
177
-
178
- Every materially effective semantic transition, including response-only and session-only changes, immediately publishes affected checkpoint/tail pairs and necessary lineage metadata. In Git mode each accepted cohort gets its own consistent local commit; `turn-end` queues the newest target for asynchronous replication, `off` stays local, and compatibility `transition` attempts the push synchronously. A reset or re-initialized journal rewrites the lineage; the queue then retargets the live commit and keeps the retired one in local history instead of blocking later turns. Intermediate patches are not batched until turn end. With no remote configured, Git persistence is intentionally local-only, not a pending publication error. With Git absent, persistence remains file-only and does not report fake commits or pending pushes. One model-authored call may update global, CWD, and session together; every supplied scope shares one validation basis, transition identity, temporal boundary, and durable commit. Config-only changes may persist runtime state but never invent semantic transitions.
179
-
180
- Writes use regular non-symlink owned files, same-directory atomic rename, isolated Git indexes, and compare-and-swap against the reconciled base. Cooperating State Flow Git publishers hold a common-Git-directory publication lock through capture, commit, and rollback. Raw bytes own file identity and recovery; non-UTF-8 explanatory journals are not reconstructed from decoded strings. Per-file publication checks catch changed bases. Both semantic and migration publishers retain exact prepared-output receipts: Git commits those bytes, not later worktree contents, and rollback requires the receipt to preserve detected external changes rather than replacing them. Low-level file helpers require caller exclusion; this is not kernel-atomic multi-file CAS against writers ignoring the protocol. An existing publication lock fails before writes and is not silently stolen; reconcile its active or interrupted owner before retrying. Scope keys mirror Pi's CWD/session directory names and retain separately verified canonical identity provenance inside owned state. Conflicts fail rather than silently selecting another scope or auto-merging semantic state. Every Git commit stages the complete non-ignored worktree delta — tracked edits, new files, and manual deletions, respecting `.gitignore` — then overlays the exact prepared State Flow outputs and synchronizes the caller-visible index to the committed tree, so no artificial staged or unstaged entries remain; unrelated user worktree changes may therefore be committed while ignored files stay untouched. With distinct roots, the Knowledge repository's files, index, HEAD, locks, and remote are not used for state publication; keep custom stores separate from sources to retain this isolation.
181
-
182
- A local commit accepts the transition. Push failure is pending publication, not a reason to regenerate the answer or repeat semantic state changes. Pending state survives restart; retries push the existing accepted commit. A restored branch reads its recorded revision without moving the shared worktree. On publication it adopts current proven live global/CWD streams it does not modify at a fresh proven origin while preserving its selected session layer, and fails closed with a named target-scope conflict if it would overwrite a shared scope that advanced. Adoption fabricates no parent ancestry and leaves older lineage available through Git.
183
-
184
- ### File-only recovery
185
-
186
- File-only mode keeps the same scoped materialization, hot temporal window, and separate config/meta. Its Pi checkpoint identifies the store root and exact current file cohort, including runtime metadata, not a Git commit. Restart can restore that pointer while the complete referenced cohort remains available. Old branches or replaced cohorts can be unavailable; current files must not be passed off as the selected past. Unavailable references and publication locks retain the selected pointer rather than falling through to an older disabled marker. A crash between file publication and Pi checkpoint append can leave the previous pointer unavailable: the files remain, but automatic branch restoration cannot assert they belong to that pointer. There is no second unbounded history store, and Git-linked cold recovery still requires Git and its original objects.
37
+ From git:
187
38
 
188
- If Git becomes available later, explicit start can adopt the selected current file cohort into Git. Adoption preserves semantic state, step, lineage, hot history and exact scope bytes; it changes runtime provenance, not semantic history. It commits the full current cohort rather than inheriting stale or missing HEAD blobs, preserves unrelated staging, and leaves file state recoverable if Git publication fails. A new session can also initialize Git over inherited file-only global/CWD scopes while retaining its own empty session layer. Git cold history begins at adoption and does not fabricate commits for earlier file-only transitions. An already-anchored identical Git cohort can reuse its owner revision.
189
-
190
- ### Existing stores and migration
191
-
192
- Changing the default directory does not import, move, or delete an old Knowledge-backed store. Existing Pi checkpoints name Git revisions: copying only the current checkpoint/tail files cannot preserve their recovery contract. An old session requires its original revision history in the selected repository; unavailable revisions must not be treated as permission to reset the session. Keep the old store intact until an explicit history-preserving relocation is performed, or use a genuinely new Pi session for an independent debug store. An SDK host can explicitly select the old `repositoryRoot` when accessing that history.
193
-
194
- The following is an **in-store format migration**, not a cross-repository relocation. Let State Flow perform it; manually renaming files is not a valid conversion.
195
-
196
- An existing current `state.json` becomes the initial checkpoint state, anchored at a proven current transition/base, with an empty tail. Its explanatory old journal is not replayed. Migration must preserve exact semantic state and remove obsolete `state.json` ownership only after successful publication, leaving one authoritative format. It must not fabricate seven historical patches. Git retains older evidence; the new hot window grows from the proven migration origin. The explicit internal migration primitive now plans without writes, publishes all converted scope files in one isolated-index commit, and restores exact old bytes after failure when its published files have not concurrently changed; conflicting external bytes remain preserved with an explicit recovery error. It rejects ambiguous dual snapshots and orphaned tails, does not depend on explanatory legacy journal validity, and retains legacy interpretation only for explicit migration. Production no longer exposes the predecessor current-state/journal writers; legacy fixture writers are test-only. Pi initialization now invokes this migration when establishing the temporal runtime, and revision-linked predecessor snapshots have a one-way restoration path. The untagged pre-0.4 development layout that appended SHA-256 suffixes remains readable at its historical Git revisions; if the selected layout is current `HEAD`, startup adopts its CWD/session files into Pi-native paths with compare-and-swap publication, rollback, and an immediate replacement revision pointer. Historical legacy restoration reads only the authoritative current snapshots, not explanatory journals. Cached view and publication basis are installed together after successful initialization/restoration; a transient restore failure preserves the selected revision for explicit start retry and cannot masquerade as a successful state transition. Independent rereview confirmed these three failure-path fixes. Stop also remains harmless in ordinary disabled sessions and retries a failed branch restoration before durably disabling that branch.
197
-
198
- ## Unified semantic mutation and terminal resolution
199
-
200
- Use `patch_state` only for established future-relevant state whose delayed persistence risks meaningful loss, never scratchpad, narration, routine progress, or speculative churn:
201
-
202
- ```json
203
- {"session":{"working":{"verified":"result"}},"final":true}
204
- ```
205
-
206
- ```text
207
- LLM(state[0] = Sn)
208
- → patch_state
209
- → validate, publish, materialize Sn+1
210
- → next LLM(state[0] = Sn+1, state[1] = Sn)
211
- → choose the next action
39
+ ```bash
40
+ pi install git:github.com/llblab/pi-state-flow
212
41
  ```
213
42
 
214
- The barrier executes alone. State Flow opts into sequential preflight, inspects Pi's synchronized assistant response, requires exactly one `patch_state` call, and blocks every sibling tool before execution. The next inference sees one rebuilt current-state projection; it must not reconstruct the update itself. Tool calls/results remain current-run causality, not duplicate full-state messages.
215
-
216
- `patch_state` is the only model-authored semantic mutation mechanism. Each invocation may supply any combination of fixed `global`, `cwd`, and `session` patches plus optional `final:true`. Supplied scopes are validated and published atomically; at least one scope or `final:true` is required. The retired `{scope, patch}` and `unchanged` forms are rejected.
43
+ In Pi:
217
44
 
218
45
  ```text
219
- patch_state({global?, cwd?, session?}) → atomic accepted state → further work
220
- patch_state({...?, final:true}) → atomic accepted state + terminal eligibility → later turn_end
221
- patch_state({final:true}) → terminal eligibility only, with no semantic transition
222
- ```
223
-
224
- Every enabled iteration begins terminal-ineligible. `final:true` latches eligibility for the next accepted `turn_end`; it does not terminate the turn, stop tools or reasoning, freeze state, or prevent later `patch_state` calls. A terminal draft that ends before eligibility, or an eligible draft whose final validation fails after a later acquisition, is preserved: it is reconciled as the runtime-owned `response` at that `turn_end` instead of being discarded, and State Flow starts at most two same-run fallback turns whose only purpose is to obtain the `final:true` patch. Fallback turns are never the response. A successful `final:true` during a fallback commits its patches and closes resolution with the preserved answer intact; when both fallbacks pass without it, the iteration closes with the preserved answer and current state, plus one bounded warning and a finalization diagnostic. Failed patch calls do not consume fallback turns. Only an accepted answer reaches `response`; aborted, length-limited, and provider-error endings never do.
225
-
226
- A semantic patch remains an inference barrier. The complete scope cohort is validated, durably accepted, and rematerialized before further reasoning. Empty supplied scopes and materially no-op scope cohorts are rejected; omit unchanged scopes and use `{final:true}` alone when no semantic update is needed. `response` is never accepted from the model. The final answer is ordinary assistant output, not a state transport. State Flow has no terminal `state_flow` HTML-comment protocol and does not parse generic service comments. Historical `state_flow` text is ordinary text. Other extensions retain ownership of their own comments such as `telegram_button`. Never put secrets in state.
227
-
228
- ## Artifact compilation and acquisition
229
-
230
- Artifacts use exact source paths as keys. A model-visible entry requires a non-empty description:
231
-
232
- ```json
233
- {"description":"What this source contains and when it is useful","compilation":{}}
234
- ```
235
-
236
- Optional `kind`, `compilation`, and `tags` are validated when present, while arbitrary unknown finite non-null JSON metadata remains forward-compatible. Tags are unique non-empty trimmed strings; `selectArtifactsByTags` provides deterministic all/any candidate filtering, but a tag match never authorizes source acquisition. Ordinary artifacts need no `kind` or tags.
237
-
238
- Runtime-owned freshness evidence is retained separately per scope in `meta.json`:
239
-
240
- ```json
241
- {"version":1,"artifacts":{"/path/to/source.md":{"sourceHash":"sha256:<64 lowercase hex characters>","compilerRevision":"artifact-v1","compiledAt":"optional timestamp"}}}
46
+ /state-flow-start
242
47
  ```
243
48
 
244
- Freshness derives capabilities from available evidence: a semantic artifact alone stays usable with unknown freshness, `sourceHash` enables source-change detection, `compilerRevision` enables compiler freshness detection, and `compiledAt` enables age-based maintenance. Missing metadata degrades gracefully instead of migrating; malformed present evidence fails closed only for the capability that depends on it. New sources require compilation, and `compiledAt` is never a correctness signal. Retired embedded `hash`/`compiler`/`compiled_at` fields remain readable compatibility evidence and are stripped from model projection.
245
-
246
- Before the first enabled inference, State Flow generically discovers regular lowercase `*.md` beneath the independent canonical Knowledge source root, normally `~/.pi/agent/knowledge` (or `knowledge/` beneath the agent directory selected by `PI_CODING_AGENT_DIR`). Discovery is deferred from activation's critical path but completes before runtime context is built. This source directory need not be a Git repository. Discovery hashes opaque bytes and retains byte counts without decoding or storing bodies; it skips symlinks and never escapes the root. A missing root means no candidates. Root and nested Markdown are treated alike, without reserved names, frontmatter parsing, validators, templates, or a `save_knowledge` implementation/call. Arbitrary repository files remain independent from State Flow.
49
+ Continue working normally. The agent receives the state protocol and uses `patch_state` to maintain memory.
247
50
 
248
- New, changed, compiler-stale, malformed, or explicitly refreshed artifacts enter the runtime-owned `artifact_invalidations` plan, projected to the model as `{path, reason}` only. Successful exact-path reads of stale ordinary sources require compact global compiler output at that path; State Flow rejects model-authored provenance fields and records the observed source hash plus `artifact-v1` in scope provenance in the same durable cohort. Removed sources create deterministic global removal transitions without reads or model compilation and prune their provenance. Runtime replay records must reproduce accepted semantic state exactly; runtime-owned provenance is not part of semantic replay.
51
+ - `/state-flow-status`: Inspect the selected state, history, artifact freshness, and publication status.
52
+ - `/state-flow-stop`: Disable updates on this branch without deleting retained state.
249
53
 
250
- Default compilation is a compact routing description, not raw Markdown or a full-file summary. Preserve uncertainty. Richer `compilation` is for reusable operational semantics. An artifact index is not proof that its body was read or understood.
54
+ State Flow is **opt-in**. Starting in an existing conversation keeps its active context for one migration run. To enable genuinely new sessions automatically, set `"autoStart": true` in the optional [configuration](docs/usage.md#configuration).
251
55
 
252
- ### Materialized-first policy
56
+ With `pi-telegram` installed, its main menu also exposes the same Start/Stop controls.
253
57
 
254
- Read a source only for a concrete relevant gap not covered by sufficient compilation, an exact-source operation including edits, evidenced invalidation, contradiction/failure reconciliation, explicit request, or bounded maintenance selection. The explicit rehydration planner binds scope, path, candidate hash, and reason, then reuses Pi's visible native `read`; State Flow does not register a duplicate artifact-reading tool. New sessions, routine recall/activation, reassurance, and a description/index alone are not reasons to reread. Changed hashes require reacquisition; prefer the smallest sufficient read. Semantic sufficiency is caller-assessed, not proven by the existence of a compilation field.
58
+ ## What carries forward
255
59
 
256
- Optional `planArtifactMaintenance` selects only otherwise-fresh old artifacts, ranking missing/unparseable provenance timestamps first, then oldest `compiledAt` and path. Defaults admit at most one source and 16 KiB after 30 days. Strict count/byte ceilings can be zero; source bytes conservatively bound tokenizer input. The planner never reads, compiles, or modifies sources. Correctness invalidation takes precedence; explicit full refresh is separate from maintenance budgets and never an automatic startup rebuild.
60
+ The same four fields exist at every scope:
257
61
 
258
- ### Skill compilation
62
+ - `contract`: Requirements, decisions, constraints, and interface commitments.
63
+ - `working`: Observations, results, unresolved questions, and what to do next.
64
+ - `artifacts`: Source-addressed descriptions and reusable compiled knowledge.
65
+ - `response`: The latest complete answer, captured by the runtime.
259
66
 
260
- Every successful `SKILL.md` read requires CWD compiler output at the exact executed path in the next `patch_state` barrier, with non-empty `description`, `kind: "skill"`, and a non-empty flexible `compilation` object. Compile applicability, routing, constraints, and failure conditions rather than source text. Runtime records the executed byte hash and `skill-artifact-v1` compiler revision in CWD scope provenance; missing/unhashable/forged freshness or missing compilation fails validation. Matching provenance proves source-version consistency, not semantic fidelity, truth, or higher instruction authority. Refresh replaces the complete old artifact and its provenance entry, including obsolete metadata.
67
+ Memory overlays **global project CWD session**. Put reusable cross-project knowledge in global, project knowledge in CWD, and private task continuation in session.
261
68
 
262
- Correlation follows finalized mutable `tool_call` arguments with execution-start compatibility fallback. Legacy `contract.compiled_skills` entries migrate into artifacts, preserving behavior and marking unavailable-source fallback hashes unverified. New patches cannot recreate the retired store.
69
+ **Resuming an existing Pi session restores its selected State Flow state and enablement.** A genuinely new session starts with an empty session layer and inherits only shared global/CWD memory; it does not resume another session's private work. Tree navigation follows the selected branch, not whichever state happens to be at Git `HEAD`.
263
70
 
264
- ### Optional memory curation
71
+ The agent can inspect `state[0]` through `state[7]`: now and up to seven prior accepted transitions. Every scope is read at the same causal boundary. Git-backed stores retain older committed history separately.
265
72
 
266
- The package includes the progressively disclosed `state-flow-memory` Skill for explicit audits, contradiction cleanup, scope narrowing, stale continuation review, and ownership migration. It is not part of routine retention and never runs as background maintenance. The Skill preserves useful uncertainty, confirmed decisions, bounded results, interaction consequences, and completed prerequisites without fixing provisional methods. Its compilation-first sequence writes and separately verifies a destination before source deletion, then inspects the effective overlay; it deliberately preserves that verification boundary even though one `patch_state` call can atomically update multiple scopes. External promotion cannot delete the only accepted copy without destination identity, content, and revision evidence. State Flow remains the memory owner and global memory remains available throughout.
73
+ ## Boundaries worth knowing
267
74
 
268
- External handoffs may use the generic global `working.memory_promotions` map. Each entry requires `status` (`pending`, `accepted`, `failed`, or `unknown`) and a non-empty `owner`; accepted entries additionally require an exact destination `pointer` and `revision`. Other fields remain forward-compatible and destination-specific. This bookkeeping does not replace the retained candidate: failures and uncertainty keep the accepted State Flow body plus exact continuation, while proven acceptance may remove the duplicate body and retain the compact pointer record. `/state-flow-status` reports owner mode, fallback activation, memory-bearing scopes, promotion counts, and bounded pointer/error details; malformed or incompletely evidenced accepted records appear as invalid rather than accepted.
75
+ - `Not a second agent loop`: State Flow adds memory to Pi; it does not run background reasoning or replace session controls.
76
+ - `Not a transcript archive in the prompt`: Prefer ordinary Pi when each request needs all historical exchanges verbatim.
77
+ - `Not live workspace truth`: Remembered observations can become stale; revalidate consequential facts before acting.
78
+ - `Physical forks copy private memory`: Native fork replacement copies the selected session checkpoint/tail into a new owner while retaining current shared memory. The child starts its own history; older parent checkpoints are not child history. See [fork support and limits](docs/usage.md#fork-support-and-limits).
79
+ - `Not a token or latency guarantee`: State and the current trajectory are not size-capped. Benefits depend on workload and memory quality; see [performance evidence](docs/performance.md).
80
+ - `Use a dedicated store`: By default state lives in `~/.pi/agent/state-flow/`, separately from Knowledge Markdown. Git commits include the store's complete non-ignored worktree delta. Do not point it at an unrelated working repository.
81
+ - `Treat memory as private`: State and diagnostic logs may contain session content. Keep secrets out, and review data before configuring a remote. Removing a value does not erase Git history or other copies.
269
82
 
270
- ## Handoff quality and external reality
83
+ Pi packages run with your user permissions. Without Git, current state and its proven hot history persist to files, but arbitrary older branches may be unavailable. See [storage and recovery](docs/usage.md#storage-and-recovery) before moving stores.
271
84
 
272
- A turn-resolution handoff is decision-relevant memory, not narration. Preserve active commitments, confirmed decisions, relevant interaction consequences, bounded results, unresolved questions, and the exact continuation. Keep user requirements, observations, assistant conclusions, provisional methods, and hypotheses distinct; silence is not acceptance. Retain useful evidence locators, validity conditions, exact rejection reasons, and known reconsideration conditions. A failed mechanism does not disprove every implementation, and one success does not establish unrestricted validity. Reconcile contradictions with evidence or user clarification; preserve decision-relevant conflicts and hypotheses explicitly as uncertain.
85
+ ## Read more
273
86
 
274
- At every handoff reconcile information affected by the run and relevant existing commitments, not every repository or scope. Merge fragmented facts and delete stale, redundant, unsupported, or obsolete progress narration without losing completed prerequisites, active commitments, or evidence. Do not invent bookkeeping merely to cause a transition. Structural validators cannot prove semantic usefulness or compilation fidelity; fresh-agent continuation tests provide behavioral evidence.
275
-
276
- `working` contains last observations, not live reality. Revalidate volatile facts before consequential actions. After interruption or branch restoration, inspect relevant external effects before repeating operations. A failed commit does not undo tools; restored memory does not restore the workspace. Missing evidence proves neither success nor absence of effects. Preserve uncertainty and the next check rather than adding action ledgers or claiming rollback/exactly-once guarantees.
277
-
278
- ## Context lifecycle and boundaries
279
-
280
- The current run retains its user prompt, assistant/tool trajectory, and persistent/current-run context-bearing custom messages from other extensions. Private State Flow resolution instructions are excluded from retained projections. Completed-run trajectories leave model context only at user-run boundaries; Pi's full trace remains inspectable. Mid-conversation bootstrap retains prior active context for one migration run; restart after stop instead bootstraps from the frozen exit handoff plus post-stop messages, never the earlier raw transcript.
281
-
282
- The normative runtime protocol stays stable through the tool loop and runtime-triggered resolution continuation. The current specification rotates on each user-initiated run and stays user-authority text, never interpolated into the system prompt. Synthetic user context repeats it with fallible assistant-produced state; the transport role does not elevate that state into instructions. Image-only specifications may be empty.
283
-
284
- State, the active specification, current trajectory, and external full trace have no strict size bound. There are no project schemas, growth-pressure gates, action authorization/observation envelopes, state-byte caps, or total-model-context guarantees. This mode is a poor fit when every new request must reason over complete historical trajectories. Token/cache/latency/success advantages still require controlled benchmarks.
285
-
286
- ## Architecture and validation
287
-
288
- See the [documentation index](docs/README.md) and [twenty temporal acceptance properties](docs/temporal-acceptance.md) for requirement-to-test maps and verification limits.
289
-
290
- `index.ts` remains composition/public exports only. Flat independent `lib/` domains own their responsibilities: `temporal` owns anchored streams, folding, active-lineage validation, and lazy historical algebra; `durable` owns exact files; `git` owns revision/CAS publication; `history` owns compact transition records; `state` owns semantic shape/overlay; `transition` coordinates accepted patches; `snapshot`, `session`, `recovery`, and `episode` own runtime/branch lifecycle; `context`, `status`, and `terminal` own projection and finalization; artifact domains own discovery/acquisition/compilation/maintenance; `extension` composes Pi integration. `runtime` caches branch-selected streams and their publication basis beneath the Pi adapter; `config` owns read-only agent-level settings independently from branch runtime configuration. Predecessor current-state/journal writers are test-only; production retains explicit migration readers, and Pi checkpoints carry revision pointers.
291
-
292
- Each domain has a same-named test, with cross-domain DAG/composition invariants in `tests/invariants.test.ts`. Real Pi SDK scenarios use `tests/pi-harness.ts`; ordinary fixtures use `tests/harness.ts`.
293
-
294
- ```bash
295
- npm install
296
- npm run validate
297
- ```
87
+ - [Usage and recovery](docs/usage.md): Configuration, session behavior, diagnostics, privacy, and storage recovery.
88
+ - [Architecture](docs/architecture.md): Semantic state, temporal history, barriers, artifacts, and integration contracts.
89
+ - [Performance](docs/performance.md): Reproducible workloads, measured costs, and what the measurements do not prove.
90
+ - [Documentation index](docs/README.md): All maintained guides, including the temporal acceptance map.
298
91
 
299
- Validation runs TypeScript checks, automated tests, and an import smoke check. Temporal algebra tests compare all available offsets with independently retained test snapshots through dense/sparse repeated folding, shared transitions, deletion overlays, no-ops, and forks. Temporary-repository tests also cover explicit migration, ten committed sparse transitions with folding and all hot offsets, cold Git scope recovery, and historical symlink rejection. Storage-level tests also prove atomic runtime/semantic publication, config-only stop without semantic history, runtime identity and lineage validation, self-reference resolution across unrelated commits, and exact accepted-commit retry. Real Pi tests also exercise configured automatic activation, deferred source discovery, strict draft → preserved answer and fallback resolution → accepted-answer continuation, temporal barriers and next-inference state, lazy runtime offset-one reads, unchanged shared-stream inheritance, old-branch stop/resume, and bounded passive stop/restart projection. The complete twenty-case temporal acceptance audit is documented in the property map; the canonical backlog identifies any subsequent open work.
92
+ For development, run `npm install` and `npm run validate`. `npm run benchmark` runs the opt-in synthetic workload in `benchmarks/`, separate from the normal test suite. In a source checkout, see `benchmarks/README.md` for lifecycle/publisher selection.
300
93
 
301
- - [Canonical open work](BACKLOG.md)
302
- - [Delivery history](CHANGELOG.md)
303
- - [Agent/contributor protocol](AGENTS.md)
94
+ Project context: [AGENTS.md](AGENTS.md) · [BACKLOG.md](BACKLOG.md) · [CHANGELOG.md](CHANGELOG.md).
@@ -1,4 +1,8 @@
1
1
  # State Flow documentation
2
2
 
3
- - [Architecture](architecture.md): Semantic state, temporal algebra, Pi lifecycle, storage, optional Git, asynchronous publication, artifact routing, durable memory, and session-continuation boundaries.
3
+ - [Usage and recovery](usage.md): Configuration, new/resumed sessions, Start/Stop, diagnostics, privacy, and storage recovery.
4
+ - [Architecture](architecture.md): Semantic state, temporal algebra, Pi lifecycle, storage, publication, artifacts, and embedding contracts.
4
5
  - [Temporal acceptance](temporal-acceptance.md): The twenty required temporal properties and their executable witnesses.
6
+ - [SDK compatibility](compatibility.md): Tested dependency stacks, public lifecycle seams, isolated validation, and host limits.
7
+ - [Physical fork contract](fork-contract.md): Session-stream copying, unchanged shared memory, child ownership/origin, and tested support boundaries.
8
+ - [Session performance](performance.md): Reproducible native-Pi/stateful workloads, long-session resume measurements, two-process publication probes, and evidence limits.