@llblab/pi-kit 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +21 -21
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +3 -122
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +11 -0
- package/node_modules/@llblab/pi-state-flow/README.md +41 -35
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +36 -16
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +4 -4
- package/node_modules/@llblab/pi-state-flow/index.ts +23 -1
- package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +191 -29
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +6 -1
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +42 -7
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +38 -8
- package/node_modules/@llblab/pi-state-flow/lib/episode.ts +1 -13
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +290 -134
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +32 -16
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +41 -0
- package/node_modules/@llblab/pi-state-flow/lib/maintenance.ts +12 -6
- package/node_modules/@llblab/pi-state-flow/lib/migration.ts +16 -0
- package/node_modules/@llblab/pi-state-flow/lib/rehydration.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +167 -31
- package/node_modules/@llblab/pi-state-flow/lib/skills.ts +15 -6
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +40 -34
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +6 -0
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +4 -9
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +25 -5
- package/node_modules/@llblab/pi-state-flow/lib/terminal.ts +17 -147
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +49 -27
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/package.json +2 -2
- package/node_modules/@llblab/pi-state-flow/lib/validation.ts +0 -27
|
@@ -38,12 +38,14 @@ Optional `~/.pi/agent/state-flow.json` (or `state-flow.json` beneath `PI_CODING_
|
|
|
38
38
|
{
|
|
39
39
|
"directory": "~/.pi/agent/state-flow",
|
|
40
40
|
"autoStart": false,
|
|
41
|
+
"logging": false,
|
|
41
42
|
"remotePublication": "turn-end"
|
|
42
43
|
}
|
|
43
44
|
```
|
|
44
45
|
|
|
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.
|
|
46
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. 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.
|
|
47
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.
|
|
48
50
|
|
|
49
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.
|
|
@@ -58,11 +60,11 @@ The configuration file stays in Pi's agent directory when state storage moves. A
|
|
|
58
60
|
/state-flow-stop # Disable this branch without deleting semantic state
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
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
|
|
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.
|
|
62
64
|
|
|
63
|
-
Stopping changes the current session/branch configuration, preserves semantic checkpoints and tails, and creates no semantic history step.
|
|
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`.
|
|
64
66
|
|
|
65
|
-
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, pending publication
|
|
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.
|
|
66
68
|
|
|
67
69
|
## State, scope, and time
|
|
68
70
|
|
|
@@ -77,7 +79,7 @@ Every scope has exactly the same semantic shape:
|
|
|
77
79
|
}
|
|
78
80
|
```
|
|
79
81
|
|
|
80
|
-
- `artifacts`: Source-path-keyed compiled routing metadata and reusable operational knowledge.
|
|
82
|
+
- `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.
|
|
81
83
|
- `contract`: Stable requirements, decisions, rejected approaches, and interface commitments.
|
|
82
84
|
- `working`: Verified observations, validation, failures, unresolved questions, and exact continuation.
|
|
83
85
|
- `response`: The complete answer captured by the runtime, normally in session state; models cannot patch it directly.
|
|
@@ -124,9 +126,11 @@ state-flow/
|
|
|
124
126
|
├── .git/ # When Git-backed
|
|
125
127
|
├── checkpoint.json
|
|
126
128
|
├── patches.jsonl
|
|
129
|
+
├── meta.json
|
|
127
130
|
└── <cwd-key>/
|
|
128
131
|
├── checkpoint.json
|
|
129
132
|
├── patches.jsonl
|
|
133
|
+
├── meta.json
|
|
130
134
|
└── <session-key>/
|
|
131
135
|
├── checkpoint.json
|
|
132
136
|
├── patches.jsonl
|
|
@@ -136,7 +140,7 @@ state-flow/
|
|
|
136
140
|
|
|
137
141
|
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.
|
|
138
142
|
|
|
139
|
-
Explicit `/state-flow-start` creates a missing state directory. With Git available, start initializes an exact-root Git repository when needed, including a populated state directory, without deleting existing files
|
|
143
|
+
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.
|
|
140
144
|
|
|
141
145
|
For local debugging after Git-backed initialization:
|
|
142
146
|
|
|
@@ -155,25 +159,25 @@ current scope = materialize(anchored checkpoint, ordered patch tail)
|
|
|
155
159
|
current effective = overlay(global current, CWD current, session current)
|
|
156
160
|
```
|
|
157
161
|
|
|
158
|
-
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
|
|
162
|
+
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.
|
|
159
163
|
|
|
160
164
|
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.
|
|
161
165
|
|
|
162
|
-
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;
|
|
166
|
+
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.
|
|
163
167
|
|
|
164
168
|
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.
|
|
165
169
|
|
|
166
170
|
### Runtime ownership and Git publication
|
|
167
171
|
|
|
168
|
-
Session `config.json` owns runtime behavior such as `enabled
|
|
172
|
+
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.
|
|
169
173
|
|
|
170
174
|
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.
|
|
171
175
|
|
|
172
|
-
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
|
|
176
|
+
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. 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 accepted cohort can share one identity and commit across its affected scopes; model-authored multi-scope work uses sequential one-scope barriers. Config-only changes may persist runtime state but never invent semantic transitions.
|
|
173
177
|
|
|
174
|
-
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.
|
|
178
|
+
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.
|
|
175
179
|
|
|
176
|
-
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 and
|
|
180
|
+
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.
|
|
177
181
|
|
|
178
182
|
### File-only recovery
|
|
179
183
|
|
|
@@ -189,7 +193,7 @@ The following is an **in-store format migration**, not a cross-repository reloca
|
|
|
189
193
|
|
|
190
194
|
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.
|
|
191
195
|
|
|
192
|
-
##
|
|
196
|
+
## Unified semantic mutation and terminal resolution
|
|
193
197
|
|
|
194
198
|
Use `patch_state` only for established future-relevant state whose delayed persistence risks meaningful loss, never scratchpad, narration, routine progress, or speculative churn:
|
|
195
199
|
|
|
@@ -207,35 +211,37 @@ LLM(state[0] = Sn)
|
|
|
207
211
|
|
|
208
212
|
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.
|
|
209
213
|
|
|
210
|
-
|
|
214
|
+
`patch_state` is the only model-authored semantic mutation mechanism. Every enabled turn begins with resolution pending and needs at least one successful call before a visible final answer. Each invocation has exactly one of two exclusive forms: `patch_state({ scope, patch })` or `patch_state({ unchanged: true })`. The latter records an explicit no-change judgment only: it creates no patch, transition identity, temporal step, or Git commit.
|
|
211
215
|
|
|
212
|
-
|
|
216
|
+
```text
|
|
217
|
+
patch_state(patch or unchanged) → accepted state → visible answer → runtime records response
|
|
218
|
+
```
|
|
213
219
|
|
|
214
|
-
|
|
215
|
-
<!-- state_flow {"transitions":[{"scope":"session","patch":{"working":{"verified":true}}}]} -->
|
|
220
|
+
An unresolved visible draft is not accepted as a response. State Flow replaces it with a hidden same-run resolution instruction, accepts a successful `patch_state`, then permits the final ordinary answer. This continuation remains in the same unfinished assistant run; only its accepted final answer reaches `response`. Aborted, length-limited, and provider-error endings never become the accepted response.
|
|
216
221
|
|
|
217
|
-
|
|
218
|
-
```
|
|
222
|
+
A real patch remains an inference barrier. It is validated, durably accepted, and rematerialized before further reasoning. Multiple scopes require explicit sequential calls. Empty and materially no-op patches are rejected; they are not an unchanged acknowledgement. `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.
|
|
219
223
|
|
|
220
|
-
|
|
224
|
+
## Artifact compilation and acquisition
|
|
221
225
|
|
|
222
|
-
|
|
226
|
+
Artifacts use exact source paths as keys. A model-visible entry requires a non-empty description:
|
|
223
227
|
|
|
224
|
-
|
|
228
|
+
```json
|
|
229
|
+
{"description":"What this source contains and when it is useful","compilation":{}}
|
|
230
|
+
```
|
|
225
231
|
|
|
226
|
-
|
|
232
|
+
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.
|
|
227
233
|
|
|
228
|
-
|
|
234
|
+
Runtime-owned freshness evidence is retained separately per scope in `meta.json`:
|
|
229
235
|
|
|
230
236
|
```json
|
|
231
|
-
{"
|
|
237
|
+
{"version":1,"artifacts":{"/path/to/source.md":{"sourceHash":"sha256:<64 lowercase hex characters>","compilerRevision":"artifact-v1","compiledAt":"optional timestamp"}}}
|
|
232
238
|
```
|
|
233
239
|
|
|
234
|
-
|
|
240
|
+
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.
|
|
235
241
|
|
|
236
|
-
|
|
242
|
+
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.
|
|
237
243
|
|
|
238
|
-
New, changed, compiler-stale, malformed,
|
|
244
|
+
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.
|
|
239
245
|
|
|
240
246
|
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.
|
|
241
247
|
|
|
@@ -243,11 +249,11 @@ Default compilation is a compact routing description, not raw Markdown or a full
|
|
|
243
249
|
|
|
244
250
|
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.
|
|
245
251
|
|
|
246
|
-
Optional `planArtifactMaintenance` selects only otherwise-fresh old artifacts, ranking missing/unparseable timestamps first, then oldest `
|
|
252
|
+
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.
|
|
247
253
|
|
|
248
254
|
### Skill compilation
|
|
249
255
|
|
|
250
|
-
Every successful `SKILL.md` read requires CWD compiler output at the exact executed path
|
|
256
|
+
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.
|
|
251
257
|
|
|
252
258
|
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.
|
|
253
259
|
|
|
@@ -259,7 +265,7 @@ External handoffs may use the generic global `working.memory_promotions` map. Ea
|
|
|
259
265
|
|
|
260
266
|
## Handoff quality and external reality
|
|
261
267
|
|
|
262
|
-
A
|
|
268
|
+
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.
|
|
263
269
|
|
|
264
270
|
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.
|
|
265
271
|
|
|
@@ -267,17 +273,17 @@ At every handoff reconcile information affected by the run and relevant existing
|
|
|
267
273
|
|
|
268
274
|
## Context lifecycle and boundaries
|
|
269
275
|
|
|
270
|
-
The current run retains its user prompt, assistant/tool trajectory, and persistent/current-run context-bearing custom messages from other extensions. State Flow
|
|
276
|
+
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.
|
|
271
277
|
|
|
272
|
-
The normative runtime protocol stays
|
|
278
|
+
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.
|
|
273
279
|
|
|
274
280
|
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.
|
|
275
281
|
|
|
276
282
|
## Architecture and validation
|
|
277
283
|
|
|
278
|
-
See the [documentation index](docs/README.md)
|
|
284
|
+
See the [documentation index](docs/README.md) and [twenty temporal acceptance properties](docs/temporal-acceptance.md) for requirement-to-test maps and verification limits.
|
|
279
285
|
|
|
280
|
-
`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`,
|
|
286
|
+
`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.
|
|
281
287
|
|
|
282
288
|
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`.
|
|
283
289
|
|
|
@@ -286,7 +292,7 @@ npm install
|
|
|
286
292
|
npm run validate
|
|
287
293
|
```
|
|
288
294
|
|
|
289
|
-
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, temporal barriers and next-inference state, lazy runtime offset-one reads, unchanged shared-stream inheritance,
|
|
295
|
+
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 → 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.
|
|
290
296
|
|
|
291
297
|
- [Canonical open work](BACKLOG.md)
|
|
292
298
|
- [Delivery history](CHANGELOG.md)
|
|
@@ -14,7 +14,7 @@ The extension owns durable memory while enabled. Global semantic memory is alway
|
|
|
14
14
|
- `temporal`, `history`: causal boundaries, checkpoint/tail folding and hot history.
|
|
15
15
|
- `durable`, `storage`, `git`: exact files, CAS publication, Git commits and restoration.
|
|
16
16
|
- `snapshot`, `session`, `runtime`, `recovery`, `episode`: Pi branch/runtime lifecycle.
|
|
17
|
-
- `transition`, `terminal`, `
|
|
17
|
+
- `transition`, `terminal`, `context`: inference barriers, turn resolution, passive projection, and response reconciliation.
|
|
18
18
|
- `artifact`, `acquisition`, `maintenance`, `skills`, `rehydration`: source routing and compilation.
|
|
19
19
|
- `memory`: external promotion records and memory diagnostics.
|
|
20
20
|
- `continuation`: native-header discovery, runtime-provenance inspection, deterministic recommendation, and host startup precedence.
|
|
@@ -63,7 +63,7 @@ The checkpoint is an older anchored materialization. The tail contains at most s
|
|
|
63
63
|
|
|
64
64
|
`state[n]`, `state.global[n]`, `state.cwd[n]` and `state.session[n]` resolve the same nth previous causal boundary. They are not independent per-scope patch counters. Pre-origin history is unavailable rather than empty.
|
|
65
65
|
|
|
66
|
-
True semantic no-ops create no identity, commit or history step. A changed
|
|
66
|
+
True semantic no-ops and explicit `patch_state({"unchanged":true})` acknowledgements create no identity, commit or history step. A changed accepted response is runtime-owned semantic state and advances history.
|
|
67
67
|
|
|
68
68
|
## Pi lifecycle
|
|
69
69
|
|
|
@@ -71,7 +71,17 @@ True semantic no-ops create no identity, commit or history step. A changed final
|
|
|
71
71
|
|
|
72
72
|
`read_state` reads one cached effective or scoped projection at offsets zero through seven. It never publishes or advances history.
|
|
73
73
|
|
|
74
|
-
Every
|
|
74
|
+
Every enabled assistant turn starts with turn resolution pending. A real `patch_state({scope,patch})` or `patch_state({unchanged:true})` satisfies it; real patches remain immediate one-scope inference barriers, so multi-scope work uses sequential calls. If terminal prose arrives while resolution is pending, State Flow replaces that draft with a hidden same-run instruction. The draft is not a final response, and a following patch is legal; only the later accepted ordinary answer is reconciled into runtime-owned `response` at `turn_end`. State Flow no longer parses `state_flow` or generic HTML comments; historical comments are ordinary text and other extensions retain their own comment handling.
|
|
75
|
+
|
|
76
|
+
## Lifecycle planes
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
SEMANTIC STATE artifacts + contract + working
|
|
80
|
+
TURN RESOLUTION pending → patch | unchanged → satisfied
|
|
81
|
+
CONTEXT PROJECTION active State Flow projection | passive post-stop handoff
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Stopping State Flow disables semantic tools and protocol, but retains a frozen effective-state handoff plus post-stop trajectory for the same physical session across reload, resume, and tree restoration. Active restart uses that bounded boundary for one migration run alongside active runtime context; it never reintroduces the pre-stop raw transcript. New and forked physical sessions inherit neither projection. This creates no semantic transition or second durable state format.
|
|
75
85
|
|
|
76
86
|
The current user specification stays at user authority and appears only in synthetic user runtime context. State is fallible assistant-produced data. Completed trajectories leave model context at user-run boundaries, while Pi's full JSONL trace remains inspectable.
|
|
77
87
|
|
|
@@ -84,8 +94,10 @@ Owned paths are:
|
|
|
84
94
|
```text
|
|
85
95
|
checkpoint.json
|
|
86
96
|
patches.jsonl
|
|
97
|
+
meta.json
|
|
87
98
|
<cwd-key>/checkpoint.json
|
|
88
99
|
<cwd-key>/patches.jsonl
|
|
100
|
+
<cwd-key>/meta.json
|
|
89
101
|
<cwd-key>/<session-key>/checkpoint.json
|
|
90
102
|
<cwd-key>/<session-key>/patches.jsonl
|
|
91
103
|
<cwd-key>/<session-key>/config.json
|
|
@@ -94,7 +106,7 @@ patches.jsonl
|
|
|
94
106
|
|
|
95
107
|
CWD and session keys mirror Pi's native encoding. The Pi UUID remains authoritative; readable directory keys never replace identity validation.
|
|
96
108
|
|
|
97
|
-
`config.json` owns branch runtime behavior. `meta.json` owns lineage, counters, identity, publication provenance and remote-publication policy. Pi checkpoints retain only an exact Git revision, an exact `file:<hash>` cohort reference, or a proven ordinary-disabled marker.
|
|
109
|
+
Session `config.json` owns branch runtime behavior. Scope `meta.json` owns runtime artifact provenance for its scope; the session file additionally owns lineage, counters, identity, publication provenance and remote-publication policy. Pi checkpoints retain only an exact Git revision, an exact `file:<hash>` cohort reference, or a proven ordinary-disabled marker.
|
|
98
110
|
|
|
99
111
|
All owned writes use same-directory atomic replacement, regular-file and symlink checks, prepared byte receipts and CAS validation. Unrelated files, staging and concurrent bytes are preserved. Rollback restores only bytes still matching the failed publisher's output.
|
|
100
112
|
|
|
@@ -102,7 +114,9 @@ All owned writes use same-directory atomic replacement, regular-file and symlink
|
|
|
102
114
|
|
|
103
115
|
If Git is unavailable specifically through executable `ENOENT`, State Flow uses file-only persistence. File mode retains exact current materialization and proven hot history but offers no arbitrary cold revisions.
|
|
104
116
|
|
|
105
|
-
With Git, each effective semantic cohort creates one local commit immediately through an isolated index. Git supplies cold history and exact branch restoration. Runtime `revision: "self"` resolves to the commit that owns the runtime record, never arbitrary `HEAD`. Runtime-only writes may use `temporalRevision` to select older semantic streams without rewinding live shared files.
|
|
117
|
+
With Git, each effective semantic cohort creates one local commit immediately through an isolated index that stages the complete non-ignored worktree delta before overlaying the exact prepared State Flow outputs; the caller-visible index is synchronized to the committed tree afterward. Activation returns after local runtime acceptance for normal `turn-end`/`off` policy, skips full predecessor migration planning when the three legacy snapshot names are absent, and defers Markdown discovery until the next enabled inference. State Flow-owned active files keep compare-and-swap protection, and `.gitignore` stays authoritative. Git supplies cold history and exact branch restoration. Runtime `revision: "self"` resolves to the commit that owns the runtime record, never arbitrary `HEAD`. Runtime-only writes may use `temporalRevision` to select older semantic streams without rewinding live shared files.
|
|
118
|
+
|
|
119
|
+
Publishing from a restored branch reconciles shared state by adoption rather than rejection: an untouched global/CWD scope whose live stream advanced is adopted at a fresh proven origin together with the selected session stream, while a shared scope the accepted transition actually changes must still match its selected basis or fail closed naming that scope. Adoption preserves causal validity, invents no parent links or semantic transitions, never rewinds live shared files, and leaves older lineage available through Git. Publication CAS rejects any change made after the reconciliation capture.
|
|
106
120
|
|
|
107
121
|
Installing Git over a file-only store adopts the exact current cohort without fabricating earlier history. Legacy layouts remain read-only historical inputs until explicitly migrated.
|
|
108
122
|
|
|
@@ -120,33 +134,36 @@ A destination is identified by canonical Git common directory, remote and full r
|
|
|
120
134
|
|
|
121
135
|
The queue uses exact commit targets, strict versioned JSON, symlink-safe atomic writes, CAS receipts and exclusive writer locks. A proven descendant may supersede an older target; divergent targets and changed destinations fail closed.
|
|
122
136
|
|
|
123
|
-
After
|
|
137
|
+
After accepted response reconciliation, an asynchronous non-interactive worker pushes the newest target. Queue failure never rolls back semantic state or regenerates an answer. Failed and interrupted attempts remain retryable across restart. Destination-scoped worker leases prevent cross-process overlap, preserve live owners, recover proven-dead owners and use exact release tokens. Confirmation removes only the exact completed target; a newer descendant remains queued.
|
|
138
|
+
|
|
139
|
+
### 0.7 activation evidence
|
|
140
|
+
|
|
141
|
+
A local Node 26.8.1 temporary-repository harness compared five wall-clock samples from the 0.6.0 tree to the 0.7.0 candidate. Medians in milliseconds were: fresh store `298 → 296`, stopped canonical reactivation `394 → 371`, configured local remote `406 → 409`, file-only `13 → 11`, and actual predecessor `state.json` layout `631 → 587`. These machine-local timings are observational, not thresholds. Git Trace2 on stopped reactivation recorded `56 → 46` processes; the 0.7 `off` path contained no remote inspection or push. Structural tests, rather than timing, enforce local-first activation, one activation commit, deferred discovery, and the legacy-name fast path.
|
|
124
142
|
|
|
125
143
|
## Artifact routing
|
|
126
144
|
|
|
127
|
-
Markdown discovery recursively finds regular lowercase `*.md` beneath the configured Knowledge root, rejects symlinks, hashes opaque bytes and never injects source bodies.
|
|
145
|
+
Markdown discovery runs after activation and before its next enabled inference. It recursively finds regular lowercase `*.md` beneath the configured Knowledge root, rejects symlinks, hashes opaque bytes and never injects source bodies.
|
|
128
146
|
|
|
129
|
-
|
|
147
|
+
A model-visible artifact entry requires only a description:
|
|
130
148
|
|
|
131
149
|
```json
|
|
132
150
|
{
|
|
133
151
|
"description": "routing summary",
|
|
134
|
-
"
|
|
135
|
-
"compiler": "artifact-v1"
|
|
152
|
+
"compilation": {}
|
|
136
153
|
}
|
|
137
154
|
```
|
|
138
155
|
|
|
139
|
-
Compiler output may add arbitrary finite non-null JSON metadata
|
|
156
|
+
Runtime-owned freshness evidence is retained per scope in `meta.json` as `{sourceHash, compilerRevision, compiledAt}`. Compiler output may add arbitrary finite non-null JSON metadata; known optional semantic fields include `kind`, `tags` and `compilation`. Tags are unique trimmed non-empty strings and support deterministic candidate filtering, but never authorize reading.
|
|
140
157
|
|
|
141
|
-
Freshness
|
|
158
|
+
Freshness derives capabilities from available evidence: new sources require compilation, `sourceHash` detects source changes, `compilerRevision` detects compiler changes, and `compiledAt` drives age-based maintenance. Missing provenance degrades to unknown freshness instead of forcing migration; malformed present evidence fails closed only for the capability that depends on it. Exact successful native Pi reads are correlated with current candidates; stale reads require same-path compiler output before provenance is recorded in the same durable cohort.
|
|
142
159
|
|
|
143
160
|
Compilation is routing, not a substitute for source text. Full source is read only for a concrete unresolved gap, exact source/edit operation, invalidation, contradiction/failure, explicit request or bounded maintenance. The rehydration planner supports new-bootstrap, resume-bootstrap and later-step phases while limiting read count and source bytes without performing hidden I/O.
|
|
144
161
|
|
|
145
|
-
Skills are CWD artifacts with stricter compilation: `kind: "skill"` and a non-empty compilation describing applicability, constraints and failure conditions. Their source bodies do not persist in state. Matching
|
|
162
|
+
Skills are CWD artifacts with stricter compilation: `kind: "skill"` and a non-empty compilation describing applicability, constraints and failure conditions. Their source bodies do not persist in state. Matching provenance proves source-version consistency, not semantic fidelity, truth, or higher instruction authority.
|
|
146
163
|
|
|
147
164
|
## Memory curation and promotion
|
|
148
165
|
|
|
149
|
-
The optional packaged `state-flow-memory` Skill performs bounded explicit audits, scope narrowing, contradiction cleanup and external handoffs. It is not part of ordinary retention or background maintenance. Curation compiles a read Skill at CWD before accumulating global compilation obligations, writes and separately reads a migration destination before source deletion, then verifies the changed scope and effective overlay. Simultaneously pending CWD/global acquisitions use
|
|
166
|
+
The optional packaged `state-flow-memory` Skill performs bounded explicit audits, scope narrowing, contradiction cleanup and external handoffs. It is not part of ordinary retention or background maintenance. Curation compiles a read Skill at CWD before accumulating global compilation obligations, writes and separately reads a migration destination before source deletion, then verifies the changed scope and effective overlay. Simultaneously pending CWD/global acquisitions use explicit sequential `patch_state` calls; separate calls are not an atomic migration.
|
|
150
167
|
|
|
151
168
|
External promotion remains a semantic two-phase handoff, not a memory-owner mode. Optional global `working.memory_promotions` entries record `pending`, `accepted`, `failed` or `unknown` status plus owner. Accepted records additionally require destination pointer and revision. Failed or uncertain promotion preserves the State Flow candidate; the only accepted copy is never deleted.
|
|
152
169
|
|
|
@@ -171,6 +188,7 @@ Pi 0.84.4 chooses or creates `SessionManager` before package resources and exten
|
|
|
171
188
|
{
|
|
172
189
|
"directory": "~/.pi/agent/state-flow",
|
|
173
190
|
"autoStart": false,
|
|
191
|
+
"logging": false,
|
|
174
192
|
"remotePublication": "turn-end"
|
|
175
193
|
}
|
|
176
194
|
```
|
|
@@ -179,10 +197,12 @@ Unknown keys fail loading. State Flow memory ownership and global availability a
|
|
|
179
197
|
|
|
180
198
|
## Observability
|
|
181
199
|
|
|
182
|
-
`/state-flow-status` reports branch mode, runtime revision, temporal head/history depth, scope keys, patch tails, artifact freshness, memory-bearing scopes, external-promotion summaries, remote policy/queue state, pending publication
|
|
200
|
+
`/state-flow-status` reports branch mode, runtime revision, temporal head/history depth, scope keys, patch tails, artifact freshness, memory-bearing scopes, external-promotion summaries, remote policy/queue state, and pending publication. Unavailable materialization is reported as unavailable, never fabricated as empty. Artifact source bodies are not read for status.
|
|
201
|
+
|
|
202
|
+
Opt-in `logging` appends local JSONL diagnostics for rejected `patch_state` calls and terminal drafts intercepted while turn resolution is pending. Records preserve useful exact text blocks and reduce other blocks to structural identity without duplicating reasoning. They are never semantic state, scope `meta.json`, Pi checkpoints, or repository input. Write failure changes no resolution, enablement, or accepted state and reports at most one bounded local warning.
|
|
183
203
|
|
|
184
204
|
## Validation boundaries
|
|
185
205
|
|
|
186
206
|
Structural validation proves JSON shape, exact identity, causal lineage, freshness, CAS and publication invariants. A valid state, receipt, source hash, or compiler revision cannot prove semantic importance, truth, sufficient compilation, correct scope, useful curation, or historical deletion. Those remain model-judgment concerns evaluated separately from deterministic transport checks.
|
|
187
207
|
|
|
188
|
-
The
|
|
208
|
+
The deterministic continuity and temporal evidence map is in [temporal-acceptance.md](temporal-acceptance.md). Release-scoped open work is in [BACKLOG.md](../BACKLOG.md), and shipped outcomes belong in [CHANGELOG.md](../CHANGELOG.md).
|
|
@@ -17,12 +17,12 @@ The numbering below follows the twenty required tests in the temporal design cor
|
|
|
17
17
|
11. **Barrier shifts current to offset 1:** `tests/integration.test.ts` — “real Pi patch_state barriers rematerialize every scope before the next inference” observes the predecessor immediately after a barrier.
|
|
18
18
|
12. **Next inference sees new current state:** The same real-Pi test inspects actual model-input projections after session, CWD, and global barriers. “real Pi reads prior scoped state lazily after a barrier and rejects offset eight without a transition” adds model-tool access to the predecessor.
|
|
19
19
|
13. **No automatic old full-state duplication:** `tests/context.test.ts` — “projects only the latest seven compact accepted transitions” rejects full-state records in transition context. The real-Pi barrier test requires exactly one current runtime projection per inference. Explicitly requested history remains ordinary tool-result trajectory, not eager snapshot injection.
|
|
20
|
-
14. **
|
|
21
|
-
15. **
|
|
20
|
+
14. **Accepted response changes are transitions:** `tests/resolution.test.ts` verifies that only the ordinary answer after successful patch/unchanged resolution enters runtime-owned `response`; intercepted drafts never do.
|
|
21
|
+
15. **Explicit unchanged creates no fake history:** `tests/resolution.test.ts` checks that `{unchanged:true}` satisfies turn resolution without changing semantic lineage, tails, step, or Git. A later changed accepted response remains a runtime-owned transition.
|
|
22
22
|
16. **Offset eight is outside hot history:** `tests/temporal.test.ts` — “hot range and unproven pre-migration history are explicit read boundaries”; the real-Pi history-reader test also exercises native tool rejection without a transition.
|
|
23
23
|
17. **Cold Git history remains recoverable:** `tests/git.test.ts` — “temporal Git writer preserves all hot states through sparse folding and cold revision reads” loads older committed states without moving the worktree.
|
|
24
24
|
18. **Tree/resume select the correct lineage:** `tests/integration.test.ts` — “real Pi preserves branch-local state through compaction, tree navigation, stop, and restart” and “real Pi old tree branch stop and resume preserve selected semantics without rewinding shared files”.
|
|
25
|
-
19. **Stop changes config, not semantic history:** `tests/git.test.ts`
|
|
25
|
+
19. **Stop changes config, not semantic history:** `tests/git.test.ts` verifies config-only persistence; `tests/runtime.test.ts` verifies old-branch stop without semantic writes; `tests/passive-stop.test.ts` proves semantic tools/protocol stop while bounded same-session continuation survives reload/resume/tree selection, excludes large pre-stop history, and bounds active restart bootstrap to the exit handoff plus post-stop messages.
|
|
26
26
|
20. **Lossless current-state migration:** `tests/migration.test.ts` — “migration anchors exact current materializations and never replays explanatory journals”; `tests/git.test.ts` — “migrates all three current snapshots in one isolated commit without losing semantic or cold history”; runtime tests cover revision-linked migration with malformed explanatory history.
|
|
27
27
|
|
|
28
28
|
## Additional preservation boundaries
|
|
@@ -33,7 +33,7 @@ The numbering below follows the twenty required tests in the temporal design cor
|
|
|
33
33
|
- `tests/status.test.ts` distinguishes selected temporal history depth from retained per-scope tails and unavailable materialization from an empty state.
|
|
34
34
|
- `tests/storage.test.ts` covers Git absence, exact file-cohort references, file CAS/rollback and shared writer exclusion. `tests/runtime.test.ts` and the native Pi Git-absent lifecycle test cover file-pointer restart, immediate barriers, finalized response, config-only stop, and unavailable-reference provenance. File-only mode supplies current/hot state; Git-dependent cold and arbitrary branch recovery require Git and the original committed objects.
|
|
35
35
|
- File-to-Git tests in `tests/storage.test.ts`, `tests/runtime.test.ts` and the native Pi lifecycle cover full-cohort adoption over unborn/stale HEAD, exact inherited bytes, unchanged semantic step/hot history, rollback, staging preservation and subsequent configured-remote publication. `tests/git.test.ts` rejects omitted uncommitted streams; working-tree equality alone cannot prove a Git commit contains the selected state.
|
|
36
|
-
- `tests/config.test.ts` covers optional agent configuration, path precedence/expansion, invalid input, load-time caching and read-only behavior. Session tests and native Pi distinguish configured new-session auto-start from branch-local resume/tree/stop. The global default is manual; CWD materialization alone no longer grants automatic activation.
|
|
36
|
+
- `tests/config.test.ts` covers optional agent configuration, path precedence/expansion, invalid input, load-time caching and read-only behavior. Session tests and native Pi distinguish configured new-session auto-start from branch-local resume/tree/stop. `tests/extension.test.ts` proves activation defers Markdown discovery until the next enabled inference. The global default is manual; CWD materialization alone no longer grants automatic activation.
|
|
37
37
|
|
|
38
38
|
## Validation and limits
|
|
39
39
|
|
|
@@ -9,26 +9,37 @@ export {
|
|
|
9
9
|
} from "./lib/acquisition.ts";
|
|
10
10
|
export {
|
|
11
11
|
classifyArtifactFreshness,
|
|
12
|
+
compileArtifact,
|
|
12
13
|
hashArtifactSource,
|
|
13
14
|
isArtifactHash,
|
|
14
15
|
isArtifactMetadata,
|
|
15
16
|
isArtifactRegistry,
|
|
16
17
|
ORDINARY_ARTIFACT_COMPILER,
|
|
18
|
+
parseArtifactProvenanceRegistry,
|
|
17
19
|
planArtifactInvalidation,
|
|
20
|
+
projectArtifactForModel,
|
|
21
|
+
projectArtifactsForModel,
|
|
22
|
+
pruneArtifactProvenance,
|
|
18
23
|
selectArtifactsByTags,
|
|
24
|
+
serializeArtifactProvenanceRegistry,
|
|
25
|
+
updateArtifactProvenance,
|
|
19
26
|
updateArtifactRegistry,
|
|
20
27
|
validateArtifactMetadata,
|
|
21
28
|
validateArtifactRegistry,
|
|
22
29
|
type ArtifactCompilationUpdate,
|
|
23
30
|
type ArtifactCompilerOutput,
|
|
24
31
|
type ArtifactFreshness,
|
|
32
|
+
type ArtifactInvalidationNotice,
|
|
25
33
|
type ArtifactInvalidationOptions,
|
|
26
34
|
type ArtifactInvalidationPlan,
|
|
27
35
|
type ArtifactInvalidationReason,
|
|
28
36
|
type ArtifactInvalidationRequest,
|
|
29
37
|
type ArtifactMetadata,
|
|
38
|
+
type ArtifactProvenance,
|
|
39
|
+
type ArtifactProvenanceRegistry,
|
|
30
40
|
type ArtifactRegistry,
|
|
31
|
-
type ArtifactSourceIdentity
|
|
41
|
+
type ArtifactSourceIdentity,
|
|
42
|
+
type CompiledArtifact
|
|
32
43
|
} from "./lib/artifact.ts";
|
|
33
44
|
export {
|
|
34
45
|
buildContinuationCandidates,
|
|
@@ -62,7 +73,9 @@ export {
|
|
|
62
73
|
getDurableRepositoryRoot,
|
|
63
74
|
isStateFlowOwnedPath,
|
|
64
75
|
loadScopeStream,
|
|
76
|
+
parseScopeProvenance,
|
|
65
77
|
parseScopeStream,
|
|
78
|
+
serializeScopeProvenance,
|
|
66
79
|
serializeScopeStream, sessionRuntimePaths, sessionScopeKey,
|
|
67
80
|
sessionStorageKey, temporalScopePaths,
|
|
68
81
|
temporalStateFileUpdates, type ScopeStreamSources, type TemporalScopePaths
|
|
@@ -88,6 +101,14 @@ export {
|
|
|
88
101
|
} from "./lib/history.ts";
|
|
89
102
|
export { applyPatch, canonicalJson, hashJson, isObject, validatePatch } from "./lib/json.ts";
|
|
90
103
|
export type { JsonObject, JsonValue } from "./lib/json.ts";
|
|
104
|
+
export {
|
|
105
|
+
appendStateFlowDiagnostic,
|
|
106
|
+
projectDiagnosticContent,
|
|
107
|
+
stateFlowLogPath,
|
|
108
|
+
type StateFlowDiagnosticBlock,
|
|
109
|
+
type StateFlowDiagnosticCategory,
|
|
110
|
+
type StateFlowDiagnosticRecord
|
|
111
|
+
} from "./lib/logging.ts";
|
|
91
112
|
export {
|
|
92
113
|
DEFAULT_ARTIFACT_MAINTENANCE_MAX_READS,
|
|
93
114
|
DEFAULT_ARTIFACT_MAINTENANCE_MAX_SOURCE_BYTES,
|
|
@@ -155,6 +176,7 @@ export {
|
|
|
155
176
|
isMaterializedState,
|
|
156
177
|
isStateDocument,
|
|
157
178
|
overlayStates,
|
|
179
|
+
projectStateForModel,
|
|
158
180
|
updateMaterializedArtifacts,
|
|
159
181
|
type MaterializedState, type ScopedPatch,
|
|
160
182
|
type ScopedStates, type ScopePatch, type SemanticTransition,
|
|
@@ -35,6 +35,8 @@ export interface ArtifactAcquisitionOptions {
|
|
|
35
35
|
/** Caller-assessed semantic sufficiency; only relevant to a concrete relevant gap. */
|
|
36
36
|
materializedSufficient?: boolean;
|
|
37
37
|
explicitRefresh?: boolean;
|
|
38
|
+
/** Runtime-owned freshness evidence retained beside the semantic artifact. */
|
|
39
|
+
provenance?: unknown;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
/** A successful read correlated to a runtime-observed invalidation candidate. */
|
|
@@ -111,6 +113,7 @@ export function decideArtifactAcquisition(
|
|
|
111
113
|
metadata,
|
|
112
114
|
compiler,
|
|
113
115
|
options.explicitRefresh ?? false,
|
|
116
|
+
options.provenance,
|
|
114
117
|
);
|
|
115
118
|
if (freshness.kind === "requires-compilation") {
|
|
116
119
|
return { kind: "read-source", reason: freshness.reason };
|