@llblab/pi-kit 0.24.0 → 0.25.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 (112) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +6 -5
  4. package/node_modules/@llblab/pi-claude-usage/AGENTS.md +20 -0
  5. package/node_modules/@llblab/pi-claude-usage/BACKLOG.md +3 -0
  6. package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +13 -0
  7. package/node_modules/@llblab/pi-claude-usage/LICENSE +22 -0
  8. package/node_modules/@llblab/pi-claude-usage/README.md +110 -0
  9. package/node_modules/@llblab/pi-claude-usage/banner.jpg +0 -0
  10. package/node_modules/@llblab/pi-claude-usage/index.ts +1159 -0
  11. package/node_modules/@llblab/pi-claude-usage/package.json +60 -0
  12. package/node_modules/@llblab/pi-state-flow/AGENTS.md +42 -56
  13. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +16 -3
  14. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +19 -0
  15. package/node_modules/@llblab/pi-state-flow/README.md +15 -12
  16. package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +2 -2
  17. package/node_modules/@llblab/pi-state-flow/dist/index.js +2 -2
  18. package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +7 -3
  19. package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +16 -7
  20. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +9 -9
  21. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +5 -4
  22. package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +2 -2
  23. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +1 -1
  24. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +7 -4
  25. package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +3 -3
  26. package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +5 -5
  27. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +3 -5
  28. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +275 -199
  29. package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +11 -4
  30. package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +6 -7
  31. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +4 -1
  32. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +1 -0
  33. package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +4 -5
  34. package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +13 -13
  35. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +7 -6
  36. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +9 -9
  37. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +3 -2
  38. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +17 -12
  39. package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +4 -1
  40. package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +2 -1
  41. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +17 -8
  42. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +49 -20
  43. package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +22 -3
  44. package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +30 -10
  45. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +5 -3
  46. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +19 -28
  47. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +17 -15
  48. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +52 -52
  49. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +8 -4
  50. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +34 -18
  51. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +5 -5
  52. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +13 -19
  53. package/node_modules/@llblab/pi-state-flow/dist/package.json +3 -3
  54. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +2 -2
  55. package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -1
  56. package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +72 -0
  57. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +36 -32
  58. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +12 -4
  59. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +5 -5
  60. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +6 -6
  61. package/node_modules/@llblab/pi-state-flow/docs/performance.md +1 -1
  62. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +13 -12
  63. package/node_modules/@llblab/pi-state-flow/docs/usage.md +32 -29
  64. package/node_modules/@llblab/pi-state-flow/index.ts +3 -2
  65. package/node_modules/@llblab/pi-state-flow/lib/config.ts +20 -10
  66. package/node_modules/@llblab/pi-state-flow/lib/context.ts +15 -14
  67. package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +1 -1
  68. package/node_modules/@llblab/pi-state-flow/lib/durable.ts +8 -6
  69. package/node_modules/@llblab/pi-state-flow/lib/episode.ts +6 -6
  70. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +274 -197
  71. package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -11
  72. package/node_modules/@llblab/pi-state-flow/lib/logging.ts +5 -1
  73. package/node_modules/@llblab/pi-state-flow/lib/query.ts +16 -16
  74. package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +11 -11
  75. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +19 -13
  76. package/node_modules/@llblab/pi-state-flow/lib/session.ts +6 -3
  77. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +55 -22
  78. package/node_modules/@llblab/pi-state-flow/lib/state.ts +46 -13
  79. package/node_modules/@llblab/pi-state-flow/lib/status.ts +23 -32
  80. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +66 -65
  81. package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +39 -19
  82. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +19 -27
  83. package/node_modules/@llblab/pi-state-flow/package.json +3 -3
  84. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +2 -2
  85. package/node_modules/@llblab/pi-telegram/AGENTS.md +1 -1
  86. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +5 -0
  87. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +2 -0
  88. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +55 -2
  89. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +21 -0
  90. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +144 -1
  91. package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +9 -0
  92. package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +19 -0
  93. package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +13 -0
  94. package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +29 -6
  95. package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +16 -0
  96. package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +5 -1
  97. package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +6 -2
  98. package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +7 -0
  99. package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +13 -5
  100. package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
  101. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +2 -2
  102. package/node_modules/@llblab/pi-telegram/docs/public-api.md +1 -1
  103. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +79 -1
  104. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +197 -0
  105. package/node_modules/@llblab/pi-telegram/lib/bus.ts +33 -0
  106. package/node_modules/@llblab/pi-telegram/lib/commands.ts +38 -6
  107. package/node_modules/@llblab/pi-telegram/lib/extension.ts +15 -0
  108. package/node_modules/@llblab/pi-telegram/lib/locks.ts +6 -1
  109. package/node_modules/@llblab/pi-telegram/lib/polling.ts +10 -2
  110. package/node_modules/@llblab/pi-telegram/lib/threads.ts +19 -5
  111. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  112. package/package.json +7 -3
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@llblab/pi-claude-usage",
3
+ "version": "0.1.1",
4
+ "private": false,
5
+ "description": "Minimal Pi extension that shows Anthropic Claude subscription usage limits using Pi OAuth auth",
6
+ "keywords": [
7
+ "pi-package",
8
+ "pi-extension",
9
+ "pi",
10
+ "claude",
11
+ "usage",
12
+ "status"
13
+ ],
14
+ "type": "module",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/llblab/pi-claude-usage.git"
19
+ },
20
+ "homepage": "https://github.com/llblab/pi-claude-usage",
21
+ "bugs": {
22
+ "url": "https://github.com/llblab/pi-claude-usage/issues"
23
+ },
24
+ "engines": {
25
+ "node": ">=22.19.0"
26
+ },
27
+ "scripts": {
28
+ "check": "node --experimental-strip-types -e \"await import('./index.ts'); console.log('pi-claude-usage: extension import ok')\"",
29
+ "test": "node --experimental-strip-types --test test/*.test.ts",
30
+ "typecheck": "tsc --noEmit",
31
+ "audit": "npm audit --omit=peer",
32
+ "pack:dry": "npm pack --dry-run",
33
+ "validate": "npm run typecheck && npm run test && npm run check && npm run audit && npm run pack:dry"
34
+ },
35
+ "files": [
36
+ "index.ts",
37
+ "README.md",
38
+ "AGENTS.md",
39
+ "BACKLOG.md",
40
+ "CHANGELOG.md",
41
+ "LICENSE",
42
+ "banner.jpg"
43
+ ],
44
+ "pi": {
45
+ "extensions": [
46
+ "./index.ts"
47
+ ],
48
+ "image": "https://github.com/llblab/pi-claude-usage/raw/main/banner.jpg"
49
+ },
50
+ "peerDependencies": {
51
+ "@earendil-works/pi-agent-core": "*",
52
+ "@earendil-works/pi-ai": "*",
53
+ "@earendil-works/pi-coding-agent": "*",
54
+ "@sinclair/typebox": "*"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "latest",
58
+ "typescript": "latest"
59
+ }
60
+ }
@@ -1,58 +1,44 @@
1
1
  # Agent Instructions
2
2
 
3
- - Keep independent domain modules under `lib/`, mirror every domain with a same-named file under `tests/`, place cross-domain architecture checks in `tests/invariants.test.ts`, and keep `index.ts` as a minimal public-export boundary. Keep `lib/extension.ts` as the Pi lifecycle composition root: it may wire configuration, domain capabilities, handlers, and event subscriptions, but low-level parsing, traversal, formatting, persistence, queue/worker mechanics, and diagnostic I/O belong to their existing owning domains.
4
- - Keep the extension opt-in and preserve clear attribution to SKILL.state wherever the inherited explicit-state approach is described.
5
- - Distinguish three model-facing states: active, passive, and configured off. Active and passive both expose `read_state` and `patch_state` when memory tools are permitted; both use the same canonical persistence, private ownership and fork-copy rules. The difference is the agent workflow, not whether memory is saved. Active iterations must consolidate future-relevant results into accepted state before completed context is replaced: make the final meaningful semantic patch when needed, then the next iteration starts from current state plus its new input rather than the previous completed reasoning. Passive mode keeps ordinary conversation continuity and allows on-demand reading/patching without that state-driven iteration boundary or the same mandatory consolidation pressure. Configured off exposes neither memory tool and injects no State Flow bootstrap/state context; it is not another name for passive. In the current configuration, off means an inactive branch with both `passiveTools` and `passiveBootstrap` false; `autoStart: false` alone is not off. The independent one-flag configurations remain supported partial integrations, not full passive or full off. Start/Stop govern active/passive workflow and must not be treated as switches for canonical storage or fork initialization. See [mode semantics](docs/usage.md#active-passive-and-configured-off) for completion and bootstrap terminology.
6
- - Preserve Pi's native tool loop and complete inspectable session trace; project completed-run history only at user-run boundaries. The context domain owns model projection of the raw scope overlay; callers must not pre-project it. Freeze the complete active/bootstrap head, including timestamp, specification and recent transitions, at the first accepted context. Reset the volatile projection at a new active run, accepted active completion, Start/Stop, selection/resume/reload, native compaction or a removed/replaced native prefix; passive user turns alone never reset it. Keep changing artifact hints, invalidations, rehydration and otherwise unreported shared drift in stable-position tail notices, never head rewrites. Successful patch receipts advance the last communicated view without redundant notices. Bind state updates to the head's volatile projection ID so retained results from an earlier head remain historical; never store this ID in canonical state or runtime metadata. Skill acquisition hints remain in native read results. This cache grants no publication, history, selection or compaction authority and adds no tail-size threshold. Retain persistent and current-run context-bearing custom messages from other extensions, plus the complete current-run trajectory. Select a unique captured native user timestamp independently of text decoration, including SDK image hints. Observe native user events even while disabled; Start/Stop must retain that observed run anchor. Reset it at native before-agent-start and session-start/tree boundaries, not semantic mode changes. Observation alone never enables state, publishes memory or authorizes compaction. Without a capture, a unique exact specification match may select only model projection. Missing, nonfinite or ambiguous matches retain available context; projection must never assign the lifecycle run anchor. Direct completion persists no private validation feedback.
7
- - Expose one canonical intent-first materialized state shape across global, CWD, and session scopes with exactly `intents`, `contract`, `working`, `artifacts`, `response`, and `lazy`; the first four and the required `lazy` root are flexible semantic objects, while `response` is the exact latest accepted assistant answer, including the empty string, and is owned only by session state. Global and CWD keep the required key as an empty structural placeholder; effective state inherits the session value. Automatic model-state and recent-transition projections omit lazy bodies. Remove whole `patch.lazy` entries and then empty scoped patches/transitions, omitting an empty recent window without renumbering retained identities or positions. Preserve hot-history projection, artifact metadata filtering and bounded lazy navigation. Canonical history, explicit value/patch reads and already communicated native/user/tool/response text remain unchanged. Preserve this plane order in model-facing projection and state presentation. `intents` contains only active commitments to future action, remains hot by default, and must not become a planner, scheduler, task manager, or execution loop.
8
- - Key artifacts directly by their source path. Model-visible artifact entries require only a non-empty `description` plus optional forward-compatible metadata; runtime-owned compilation evidence (`sourceFingerprint`, `sourceHash`, `compilerRevision`, `compiledAt`) belongs in the scope `meta.json` provenance registry. Reserve model-authored `hint`; runtime may add it only to effective/model projection and never to canonical scope state. Retired embedded `hash`/`compiler`/`compiled_at` fields remain readable compatibility evidence and are stripped from model projection. Validate provenance restrictions on every authored artifact entry, not on retained legacy state: individual runtime/legacy provenance fields cannot be set or deleted by model patches in any scope.
9
- - Inspect only exact artifact source paths already registered in global, CWD, or session state. Never scan directories, discover files, reserve a Knowledge root, interpret file extensions, or read unrelated source bodies. Observe regular non-symlink files through `size + mtimeNs`; proven absence removes the artifact and provenance from each exact owning scope, while relative, symlink, directory, inaccessible, or otherwise unavailable paths are non-destructive evidence.
10
- - Use `classifyArtifactCompilationNeed` for public acquisition/rehydration and ordinary-artifact Pi invalidations. Compare observed fingerprints with hidden provenance; missing/malformed retained fingerprints, malformed compiler evidence, and compiler changes request compilation without declaring semantic corruption. Fingerprint-only decisions ignore unused legacy hashes, while explicit current hashes retain their checks; never invent hashes in read plans. Accept signed filesystem `mtimeNs`, including pre-epoch sources. Preserve changed-source semantics and add `hint` only to model projection. Effective Skill entries mask lower ordinary entries and retain their separate hash protocol.
11
- - Correlate successful exact-path reads with the current registered-artifact invalidation plan. Accept compilation only when the fingerprint remains stable before and after acquisition and at final publication, then store the accepted fingerprint with current compiler revision in the owning scope's provenance in the same locked acceptance as its compiled card. Runtime/Skill guidance and rejection text must identify that exact reported scope and path, never direct an existing CWD/session artifact to global. Generic artifact maintenance never calculates content hashes; retained `sourceHash` is transitional compatibility evidence only. Restore/fork preserves current shared provenance, but drops session provenance for each artifact path touched by any retained session patch after the selected boundary, including change-away-and-back. Keep the selected semantic value usable with unavailable compilation evidence; untouched paths and current-head selections retain their proven evidence.
12
- - Load optional repository-global `config.json` from the canonical `<agentDir>/state-flow/` root once per extension load/reload. `autoStart` defaults false for genuinely new sessions, `passiveBootstrap` and `passiveTools` default true and remain independent of episode lifecycle, `showSuccessfulPatches` defaults true for interactive successful-call JSON rendering, and `historyLimit` defaults to 7 and accepts integers from 0 through 100. SDK embeddings may explicitly override the repository. State Flow always owns durable memory while enabled and global semantic memory is always available; these are invariants, not configuration switches. Keep global operator configuration, runtime configuration, and provenance outside model-patchable semantic state.
13
- - Keep runtime configuration and provenance separate from model-patchable semantic state. Persist session `config.json` for enablement/projection settings, session `runtime.json` for lineage, counters, and branch identity, and every scope's adjacent `meta.json` for temporal boundaries, ownership where applicable, and artifact provenance. None participates in scope overlay; predecessor combined metadata and checkpoint envelopes are unsupported. Pi checkpoints contain only a retained semantic boundary with lifecycle fields, or `{disabled:true}` from proven pre-runtime branch provenance. Before retained selection or origin adoption, bind the session stream's checkpoint/tail identities to its runtime lineage; a position alone never proves ownership. Permit sparse session records and proven inherited pre-origin streams. Global/CWD streams remain live and are validated independently, not against another session's historical lineage; continuation inspection follows the same ownership rule. Advisory continuation reads await one canonical cohort and carry host-owned cancellation through candidate building/recommendation; cancellation never becomes a new-session suggestion. Pin native header identity across waits, create no store or session, and leave actual branch restoration/policy to the host. Expired, contradictory, or revision-pointer targets fail closed during historical restoration without falling through. Explicit Start instead validates current same-session memory independently of the selected history or its previous mode; this is policy activation, not historical restoration. Corrupt, incomplete, conflicting or unaccepted fork evidence never authorizes substitution. Session runtime metadata contains no storage receipt, Git identity, temporal revision pointer, publication mode, or push intent.
14
- - Overlay materialized state recursively in `global → cwd → session` order. Scope-local deletion removes only that scope's key so a lower-scope value becomes visible again; scope never changes instruction authority. Route branch/run-local continuation to session, project-local reusable state to CWD, and cross-project reusable state to global. Registered Pi Skill artifacts follow public source provenance: user to global, project to CWD, and temporary to session.
15
- - Reserve `state` for the runtime materialized semantic view. `checkpoint.json` contains only the canonical materialized semantic state, each nonblank `patches.jsonl` line contains only one semantic patch, and adjacent `meta.json` owns their checkpoint/tail boundaries plus CWD identity. For each scope, current state is exactly `materialize(checkpoint.json, patches.jsonl, meta.json)`: an older anchored checkpoint plus its ordered tail of at most the configured `historyLimit` materially effective semantic patches. On overflow, apply the oldest patch into the checkpoint, advance its `through` boundary, remove it, and append the new patch. Never truncate unapplied replay records or replay patches over an already-current snapshot. Decode valid persisted retention against the format maximum before enforcing a smaller operator limit: restrict boundary selection to the configured window, then fold excess scope tails during canonical origin acceptance, including fork. Preserve current shared values/provenance and selected private state; raising the limit never reconstructs discarded history.
16
- - Give every accepted semantic transition one opaque identity shared by all affected scope records, with explicit active causal lineage. A branch-local position can order identities but never acts as a global counter, substitutes for identity, or merges forks. Unchanged scopes contribute no record and remain unchanged at that boundary. Adopt proven inherited streams at a new session origin without rewriting their checkpoints/tails except for configured retention folding; pre-origin coordinates are not one shared clock. Adopt independently valid live shared streams at a fresh origin when they cannot compose with the selected lineage, preserving the selected private layer. Authored model patches stage against current Global/CWD under exclusion; a raw precomputed replay still requires its selected target basis. Reconciliation adoption is not a fabricated semantic transition, parent link, or retry loop. True semantic no-ops and origin adoption do not advance semantic history.
17
- - Define `effective[n]`, `global[n]`, `cwd[n]`, and `session[n]` at the same nth previous accepted transition boundary in the active lineage, never the nth local patch of each scope. Guarantee offsets zero through the configured `historyLimit` once the lineage has enough proven transitions; report earlier-than-origin history as unavailable and reject offsets beyond that configured hot-history bound. Reconstruct scopes at one target before overlaying them.
18
- - Keep historical reads lazy through the smallest runtime/model read interface. Normal inference gets only current effective state and useful bounded compact transition context, never an eager window of full snapshots. `patch_state` is the sole semantic mutation tool. `read_state` treats unscoped semantic paths as current effective aliases, accepts explicit effective/scoped materializations and scope-local retained accepted patches, and rejects the retired top-level `state` segment; materialization indices share the composed causal lineage while `patches[n]` walks the selected scope's retained patch tail, with both paths enforcing the same configured `historyLimit`. The public reader accepts only `path` or `paths`; temporal offsets and scope selection are expressed in path syntax. Reads return the exact retained boundary and never publish, append a checkpoint, or advance history. Both tools are available in active mode or with configured passive tools, subject to host restrictions and memory-integrity fences; the patch barrier blocks reader siblings too. Canonical checkpoint plus tails own current and retained history; never use Git as semantic read authority.
19
- - Store runtime state in its own directory with optional Git backup, defaulting to `state-flow/` beneath Pi's configured agent directory (`~/.pi/agent/state-flow/` normally), independently from optional registered artifact sources. Use exactly these owned paths: `checkpoint.json`, `patches.jsonl`, and `meta.json` for global; `<cwd-key>/checkpoint.json`, `<cwd-key>/patches.jsonl`, and `<cwd-key>/meta.json` for CWD; `<cwd-key>/<session-key>/checkpoint.json`, `patches.jsonl`, `meta.json`, `config.json`, and `runtime.json` for session. Do not create `.state-flow`, `scopes`, or another storage/history namespace. Mirror Pi's native CWD session-directory encoding and JSONL-basename session key (deriving `<header timestamp>_<UUID>` for in-memory sessions), while retaining separately verifiable canonical identity provenance in owned state. Keep the UUID authoritative, reject unsafe segments and mismatches rather than selecting another scope, and use CWD `meta.json` ownership to fail closed on Pi-name collisions.
20
- - Prefer progressive enhancement and graceful degradation of optional capabilities, never fabricated success or degraded memory/ownership guarantees. Keep optional Git backup at `agent_before_settle`; busy backup/push may defer to a later eligible settled turn. Do not move it to `turn_end` or require an SDK extension solely for cancellable settlement waiting. Use optimistic persistence for ordinary operation; power-loss-safe acknowledgement is not a release requirement. Do not add a patch journal, temporary recovery store, flush protocol or new storage format solely for sudden power loss. Keep short asynchronously awaited publication exclusion/CAS so cooperating instances preserve independent shared fields and the last accepted write wins on overlap; no exclusion across inference, source acquisition or Git. Per-file rename/rollback does not promise crash-atomic recovery or even an at-most-one-patch loss bound. Do not claim physical durability from `writeFileSync`, a readback or passing ordinary tests. The accepted limitation and native Pi comparison live at [the persistence boundary](docs/filesystem-recovery.md#power-loss-durability).
21
- - Classify every filesystem cohort before recovery: complete valid evidence is usable; total absence is recoverable only from an explicit semantic default or exact surviving authority; partial, malformed, contradictory, or authority-losing evidence fails closed at the smallest dependent capability. A wholly absent global/CWD checkpoint-tail pair is current empty shared reality and must not resurrect selected cold values or orphaned compilation evidence. Authored patches apply to that empty basis; raw precomputed replay targeting a disappeared selected basis still fails closed. Missing provenance means unavailable freshness, not semantic corruption. Perform every repair through normal locked/CAS publication, never ad-hoc writes.
22
- - Accept only the canonical semantic checkpoint/tail plus temporal metadata and separate session config/runtime contract. Predecessor checkpoint/tail envelopes, combined session metadata, pre-`intents` checkpoints, `state.json`, pre-0.4 hashed layouts, and semantic Pi checkpoint envelopes are unsupported and must fail without rewriting existing bytes. No dedicated migration domain or explicit runtime migration phase exists. Exercise unsupported-format cases only in temporary repositories rather than modifying the user's active data during development.
23
- - Read and write only regular non-symlink State Flow-owned files at those exact paths, publish each file by same-directory atomic rename, preserve arbitrary repository contents, and classify ownership exactly. Retain opaque source bytes for file identity and rollback, not decoded-text reconstructions. Use validated structural JSON equality for in-process semantic comparisons; reserve cryptographic hashes for compact identities that cross persistence/process boundaries. Serialize cooperating canonical-file writers through file-cohort exclusion and CAS. Asynchronous storage callers use callback-scoped `withStorageTransaction` capture/publication operations under one store lock: acquire before reading the basis, await live ownership cancelably, and never reuse a capability after its callback ends or for a different root. Route model patches through `TemporalRuntime.withPatchTransaction`; stage and publish synchronously inside its awaited exclusion, retain the exact accepted private file basis, and install caches only after acceptance. Never publish empty initialization separately from a patch that may fail. Runtime-only callers can use `withLifecycleTransaction`: require already accepted private authority, recheck selection/policy and derive the lifecycle snapshot after waiting, then invoke its single-use publisher synchronously. Preserve semantic/provenance bytes and wider stored tails; an unchanged publication still validates its captured cohort. Read-only or prepared views cannot initialize through this API. For a complete accepted cohort, patch-transaction publication without a transition or provenance update is runtime-only and must not fold history or prune evidence. New private authority or wholly absent shared pairs still require ordinary atomic initialization; the explicit lifecycle-only API never repairs semantic storage. Keep model inference, source acquisition and Git commands outside canonical critical sections. Interrupted/malformed locks remain unavailable, never permission to steal a live owner's exclusion. Recheck prepared bases before each replacement/deletion and restore only bytes still matching the publisher's own output. Preserve detected concurrent changes and report unresolved rollback conflicts; do not claim kernel-atomic multi-file CAS against nonparticipating writers. Inspect only exact already-registered artifact paths; do not discover or own a Knowledge directory.
24
- - At instance initialization resolve the repository, CWD key, and session key; load each scope's anchored canonical checkpoint and tail, materialize at the selected retained boundary, then overlay `global → cwd → session`. Install cached view and file publication basis atomically only after successful restoration/initialization. Revalidate mutable file cohorts; never turn inspection into a long-lived publication-basis cache. Preserve selected retained-boundary evidence across transient restore failure for truthful diagnostics and exact-source fork retries; ordinary explicit Start uses independently validated current memory. A genuinely new session gets an empty session layer and inherits only global/CWD values; it must never reuse another same-CWD session layer. Explicit native fork adoption follows the [session-copy contract](docs/fork-contract.md): copy the proven retained source-session stream and provenance into a distinct fresh canonical origin over current shared streams, without modifying parent-private files. Reject occupied targets and checkpoint the child only after CAS acceptance. Awaited copies use `withForkTransaction`: pin parent identity/boundary before waiting, capture source and target under one exclusion, recheck caller policy, revalidate source evidence before child publication, and install only accepted child memory. Preserve live shared provenance and parent-private bytes; post-acceptance failure cannot authorize recopying. Inherited parent pointers never authorize an empty reset; fence parent passive Stop projection across child reload. Missing child files or a parent-session header alone never authorize a retry of parent copying.
25
- - Bind active Pi checkpoints to retained semantic boundaries in the current canonical lineage. Awaited runtime restoration uses `withRestoreTransaction`: detach the pointer before waiting, capture/select private history beside current shared streams under one exclusion, recheck caller policy, and publish once before installing the candidate. Expiry or malformed evidence cannot authorize current-head or empty fallback; origin acceptance retains configured folding and causal provenance rules. Resume and tree restoration select only retained private session history while global/CWD scopes remain live; every failure resolving a selected boundary fails closed without falling through to older checkpoints, disabled markers, Git revisions, or unrelated newer private state. Passive shared-memory availability does not prove the selected private layer: preserve the recovery failure and reject historical session reads and passive publication until it is resolved. Explicit Start may independently activate the validated live same-session canonical head. A same-owner failed-Stop marker permits read-only loading of validated current memory on reload, never historical substitution or publication; passive tools cannot clear its write fence. Awaited recovery uses `refreshCurrentMemory`: capture current authority under exclusion, reject cancellation before cache installation, never publish or initialize absence, and retain the prior cache on failure. Its disabled snapshot omits unfinished specifications and grants no write authority; native callers still own selection and Stop fences. Native startup/tree/fork/auto-start/failed-Stop restoration awaits one owned lifetime in the composition root: pending selection stays passive and unavailable, selection revokes older work, and shutdown drains current and superseded operations. Start/Stop select agent policy, not the existence of canonical memory. Stop must not cancel retained restoration, auto-start memory initialization or fork copying: apply passive policy inside the pending memory acceptance and keep configured passive patching available afterward. Start waiter cancellation must not cancel independently owned attachment or copying. Only selection changes, shutdown, native operation cancellation and actual authority/storage failures revoke that work; a mode change must not manufacture a storage-error fence. Start pins physical identity across cancelable joins without cancelling independently owned recovery or Stop persistence. Only current acceptance installs memory, checkpoint, tools and UI. Keep read-only candidates detached until cancellation, physical identity and any intervening accepted cache change are rechecked.
26
- - Every accepted semantic change, including session-only and response-only changes, atomically updates affected canonical checkpoint/tail pairs and temporal metadata without creating a Git commit. Each materially changed scope advances its own persisted revision exactly once; Global and CWD revisions are shared across their writers, Session is private, and Effective is represented by the `G#/C#/S#` revision vector rather than an invented scalar owner. After an accepted turn reconciles its response and reaches `agent_before_settle`, one best-effort backup may commit only State Flow-owned already-written files. Await the backup mutex before briefly locking canonical storage for bounded root/CWD/session namespace inventory and regular-file byte capture; hold the separate mutex through completion and never acquire it from a canonical writer. The Promise-returning backup API accepts cancellation. Combine a real Pi operation signal with shutdown cancellation and drain owned attempts before shutdown completes. Pi 0.87 provides no operation signal at settlement: refuse contention there with explicit diagnostic-only deferral until a later accepted turn, rather than trapping native Abort. Do not infer cancellation from an ended agent signal, steal locks, add a background owner, or apply this optional-backup fallback to semantic publication. Release the canonical lock before every Git command, filter, staging write, ref update, or index synchronization. Recheck the Git branch/head after capture waits. Stage only the captured snapshot through a private temporary worktree/index, preserve Git ignore/filter policy, and never inventory artifact sources or unrelated directory trees. Keep unrelated staged/index-only content and worktree edits intact; synchronize only exact owned index paths, include HEAD-owned deletions even when already absent from the caller index, and never create an unowned-only initial backup. Backup failure is diagnostic-only and never rolls back state, suppresses an answer, requests continuation, or blocks a later turn. After each successful backup attempt, asynchronously push the exact current commit to the attached branch's explicitly configured remote/ref without force. Permit at most one in-flight push per repository root in process; skip overlapping attempts, leaving a later accepted turn to push the latest HEAD. Session shutdown waits for the in-flight process to close, within the existing Git push timeout and termination behavior; suppress push-failure reporting after shutdown begins. Push failure has no semantic effect; while active, warn once per failure streak with a concise message and reset suppression after successful replication. Record the available redacted Git failure detail in the local diagnostic log even when general logging is off; if local recording fails, warn once with the available detail. A later accepted turn retries the latest backup. Durable push queues, publication workers, worker leases, and remote retry generations do not exist.
27
- - Register `patch_state` as the sole model-authored semantic mutation protocol. Its canonical grammar accepts one or more fixed `global`, `cwd`, and `session` semantic patches; reject unknown fields, empty supplied scopes, and retired finalization or `{scope, patch}` / `unchanged` grammar. Apply authored Global/CWD operations to the current canonical head, preserving untouched values; overlapping targets follow successful acceptance order, not stale agent snapshots. Validate and publish all supplied scopes as one durable cohort, deriving replay and revisions from that actual basis. Correct repeats succeed without another semantic identity, step or scope revision. Preserve private ownership/history fences and complete artifact/provenance units. Never accept model-authored `response`.
28
- - Treat every semantic `patch_state` as a strict inference barrier. Give it sequential execution mode; find the matching synchronized assistant through public parent traversal from the selected leaf without constructing a full branch during tool preflight; require exactly one `patch_state` call in that response and block every sibling tool call before execution. The next inference sees rematerialized state. Successful native patch results carry context-owned `state_updates` only when needed: exact projected effective replacements/deletions at key/index-segment path arrays. Predictable direct non-null leaf writes are not echoed when their accepted effective value matches the authored value and no other authored scope touches the same path, ancestor or descendant. Explicit Session scalar/array replacements may omit matching receipts despite lower-scope overlap because Session masks lower values; deletion and object-merge overlaps remain conservative. Indexed-array selectors map to numeric update segments only if the communicated effective basis proves that parent is an in-bounds array; literal object keys stay literal. A deletion is omitted only when the previously communicated effective value and accepted effective value are identical and no other authored scope overlaps; effective-only projection does not prove lower-scope ownership, so changed fallback remains conservative. Artifact card replacements or merges can omit their receipt only when the projected authored fields applied to the communicated card exactly match the accepted card after stripping retired provenance; a retained runtime hint is part of that known basis, while new/removed/changed hints and semantic drift remain visible. Lazy navigation receipts can be omitted only when a complete communicated key/kind catalog and non-deleting top-level writes predict the entire accepted catalog; hidden bodies remain invisible, and deletion, overlap or drift stays conservative. Retain reconciliation for masked writes, overlapping scope operations, and projected drift since the last communicated view, or the caller's pre-wait cache before any head exists. Keep effective scope masking/fallback, artifact metadata filtering and lazy-body omission; only changed bounded lazy navigation may accompany updates. Keep the compact interactive acknowledgement separate from this model-facing result block. Ordinary accepted answers require no finalization patch or fallback inference.
29
- - Reconcile `response` only from the actually accepted ordinary assistant answer at `turn_end`; it remains runtime-owned, and an accepted empty answer reconciles to `""` rather than causing a finalization failure. Await `withPatchTransaction` before staging against the current shared head; publish the response and completed-run lifecycle together, then install caches/checkpoint before yielding without a second persistence call. Combine Pi's operation signal with response-owned cancellation: run/selection changes, Stop, shutdown and superseding answers withdraw obsolete waits, whose completion must never clear newer pending work, restore a specification, update UI or erase a Stop fence. Cancellation before acceptance leaves the run unfinished; cancellation afterward cannot undo accepted memory. State Flow has no terminal HTML-comment mutation protocol and does not parse generic service comments. Other extensions retain ownership of their own comments and output handling.
30
- - Treat terminal state as a decision-relevant handoff, not narration: retain source-addressed reusable operational knowledge in `artifacts`; compile stable requirements, confirmed decisions, rejected approaches, and interface commitments into `contract`; retain observations, validation, failures, current domain state, unresolved work, interaction consequences, and exact continuation in `working`. Preserve relevant completed prerequisites and verified outcomes while removing obsolete progress narration; reconcile only information affected by the run and relevant existing commitments, not every scope or repository surface.
31
- - Preserve active constraints, unresolved questions, consequential negative results, and the next discriminating check before compression. Distinguish observations, user requirements, assistant decisions, and hypotheses; do not promote assistant conclusions to user requirements. Treat resource, document, memory, Skill, and agent locators as semantic references wherever context expresses them. Inside ordinary strings and prose, encode a semantic-state path as `$` immediately followed by one valid `read_state` path, for example `$effective.lazy.memory[7]`; the prefix distinguishes a reference from incidental path-like text and leaves room for future parsing. `{"$ref":"cwd.lazy.plan"}` remains the optional structured state-reference form; neither form is a runtime link type. External resource locators retain their native path, URI, Skill, or agent syntax. Resolve references explicitly through the appropriate read/tool when needed and infer no authority, existence, dependency, hydration, execution, or completion merely from their presence. Never scan, audit, or proactively resolve references merely to find broken ones. Only after one requested `read_state` value path is missing may the query domain perform one bounded reverse lookup over current model-patchable semantic planes for exact structured `$ref` and `$path` matches. When durable sources match, return a successful top-level `{value:null, hint:[...]}` diagnostic sentinel: every hint has `type:"dangling-reference"`, a descriptive conditional message, and at most three runtime-verified current reference-owner paths, never purported relocated targets or lazy bodies. The null sentinel is never presented without `hint` for this case; keys, patch, and multi-path reads retain ordinary all-or-error semantics. Never scan runtime-owned `response`, and retain the ordinary missing-path error when no durable source matches. A match proves durable semantic provenance, not staleness; no match does not prove invention. Missing paths or runtime hints alone never require historical search. The agent may choose targeted historical reads when a previous value is useful to the current task without separate user permission; otherwise continue without searching. Treat past values as historical evidence, not automatically current memory, and never automatically restore deleted data. Do not scan offsets, hydrate automatically, add repair inference or search historical reference owners. Hints do not prove prior existence, retained history or relocation. The agent may inspect ownership and patch a proven stale source within touched work while preserving surrounding meaning, without resurrecting its target. Effective-state absence does not identify ownership, and unavailable history, inaccessible external resources, or transient read failure do not prove a dangling reference. Retain useful source locators and validity conditions for consequential facts without mandatory per-value metadata. Keep rejection reasons and reconsideration conditions. Reconcile contradictions through evidence or user clarification instead of silently overwriting established constraints or observations; retain unresolved conflicts and decision-relevant hypotheses as uncertain. These are protocol obligations, not deterministic semantic validation gates.
32
- - Treat `working` as last observations, not a live workspace. Revalidate volatile facts before consequential actions; after interruption or branch navigation inspect relevant external effects before repeating operations. Failed state commits and restored memory do not undo tool effects. Missing evidence proves neither success nor absence of effects: retain uncertainty and the next check. Keep revalidation targeted, without action ledgers or runtime freshness/rollback guarantees.
33
- - Recognize Skill acquisition only when a successful finalized `read` path exactly matches a registered Pi Skill exposed by the public `getCommands()` resource metadata. Map `sourceInfo.scope` deterministically as user → global, project → CWD, and temporary → session; never infer ownership from path shape. Hash the executed source bytes. Matching current provenance creates no acquisition request. Otherwise append a concise tool-result hint naming the exact target, but keep the read volatile unless the model supplies durable compiler output; pending acquisition never blocks an unrelated semantic patch or ordinary completion. Validate an attempted compilation at the reported scope/path with non-empty `description`, `kind: "skill"`, and flexible non-empty `compilation`, then record runtime-owned `sourceHash` plus `skill-artifact-v1` `compilerRevision` in that scope's provenance. Replace the complete prior Skill artifact and provenance on refresh so obsolete evidence cannot survive. Unregistered `SKILL.md` reads have no acquisition semantics. `contract.compiled_skills` is retired and rejected; never fabricate hashes or bypass explicit source acquisition.
34
- - Make state stewardship an ordinary model responsibility without a background loop or gratuitous full-state rewrite. Every handoff curates touched and obviously stale or mis-scoped visible branches: place new knowledge at the narrowest valid scope, merge fragmented facts, compress history into conclusions, and delete stale, completed, redundant, or low-value keys while preserving active commitments and evidence. Dedicated cleanup and scope audits require an explicit user request; a feature/release/project boundary may motivate a recommendation, not an automatic audit. For a proven move within one store, inspect both owners, resolve conflicts, apply destination/source changes through one atomic multi-scope patch, and verify both owners plus the effective overlay. External transfers require destination-native acceptance verification before source deletion. Global is only established cross-project/user/environment knowledge, CWD is reusable project truth, and session is branch/run continuation.
35
- - Accept omitted semantic fields inside each supplied scope patch, but reject empty supplied scopes. When no state change is needed, do not call `patch_state`. Accept the exact ordinary answer, including an empty string, which runtime owns as session `response`. A changed response is a semantic transition; identical complete semantic state finalizes lifecycle without a patch, identity, or temporal step. Semantic usefulness and optimization remain protocol-owned because deterministic validation cannot prove them.
36
- - Agent-level opt-in `logging` appends local JSONL diagnostics for rejected `patch_state` attempts, inference-preparation failures and response-finalization failures; asynchronous Git push failures are logged there even without opt-in so terse interactive warnings retain local detail. Every rejected call retains its exact attempted arguments plus the precise error and, when available, tool identity and call id; successful patches and accepted answers are never logged. Preserve exact text blocks only where useful, reduce other blocks to structural identity, never duplicate reasoning bodies, and keep logging outside semantic state, scope metadata, checkpoints, and publication. Logging failure emits at most one warning and never changes enablement or accepted state. Every State Flow-authored user-facing error/warning is one short line: flatten nested/aggregate causes into text before transport, preserve the operation, exact offending scope and actionable cause, and elide long operands while retaining target basenames/suffixes before shortening prose. Never rely on transported `Error.cause`, split Unicode pairs, or mistake prose apostrophes for quoted paths. Full opted-in diagnostics keep original targets and rejected input. A retried Start emits only its final outcome, not a duplicate restoration warning; tool failures still keep one blank line between tool name and output.
37
- - Keep `applyPatch` results and staged mutable drafts detached from caller patches and accepted scopes. Detach once at the public patch boundary; private owned-draft COW may share untouched paths only within that isolated basis. Clone incoming replacements, detach inherited objects before preserving their merge behavior, and retain late-response/artifact mutation isolation. Do not trade CAS, publication rollback or public/historical read isolation for cross-boundary sharing.
38
- - Recursively materialize patches immediately; empty objects preserve, nested object-key `null` deletes, and `null` anywhere in semantic state including arrays is invalid. This prohibition does not apply to runtime envelopes such as an origin's null parent. Persist runtime-normalized replay patches that exactly reproduce accepted state, including complete artifact replacement; runtime-owned provenance is stored in scope `meta.json` and is not part of semantic replay.
39
- - Do not impose project schemas, state or patch byte caps, dynamic growth pressure, observation envelopes, action authorization, action ledgers, or state-size limits.
40
- - Capture the turn-stable specification at `before_agent_start`, without canonical persistence or maintenance there: Pi 0.87 has no operation signal at that hook. The first active `context` awaits one preparation/maintenance acceptance over current shared state with Pi's signal plus a preparation-owned cancellation lifetime. Derive the snapshot and exact-path missing-source removals only after waiting; no removals on a complete accepted cohort means runtime-only publication, while wholly absent shared pairs initialize atomically from current empty reality. Install caches/checkpoint before inference. New runs, selection changes, Stop and shutdown revoke obsolete work; completed preparation cannot replay its prompt at a later boundary. Preparation failures use public `ctx.abort()` because Pi swallows context-hook exceptions; do not infer from a rejected draft or request repair inference. Idle/no-signal projection remains read-only. Persist the full specification only while that run is unfinished, then remove it atomically with accepted terminal response reconciliation. Enabled provider requests still receive current memory when Pi's actionable turn/settle boundaries continue without another `before_agent_start`; omit an absent specification rather than resurrecting the completed prompt, inventing a user run, or taking over Pi's continuation scheduler. Keep user-controlled specification text at user authority: never interpolate it into the system prompt; repeat it only in synthetic user runtime context. Treat materialized state in that message as fallible assistant-produced data whose transport role does not elevate it into user instructions.
41
- - When enabled inside an existing session, retain Pi's active context for exactly one complete bootstrap run and require its `patch_state` resolution to compile all future-relevant context.
42
- - Restore extension state from the active Pi branch's retained-boundary checkpoint and current canonical lineage, not the full entry list, a storage receipt, or Git `HEAD`, on startup and successful tree navigation.
43
- - Render compact terminal status as accent `state-flow` plus dim `G#/C#/S#` only while active mode is enabled; passive changes still advance the affected scope revisions without exposing an active-status signal. `/state-flow-status` must remain observational: show CWD/session keys, internal step, independent scope revisions, active temporal head, available hot-history depth, per-scope artifact/tail counts, and already-known invalidations; render only the effective global → CWD → session materialization as semantic JSON; perform no source reads, scans, fingerprinting, or maintenance. When temporal materialization is unavailable, report unknown counts and unavailable state rather than inventing empty projections.
44
- - Explicit `/state-flow-start` returns after local runtime acceptance without initializing or consulting Git. Current-head activation uses `withStartTransaction` to capture, validate, stage and accept under one awaited exclusion; create a root/private origin only with explicit initialization authority and recheck current branch permission after waiting. Pending repeats share one operation; Stop, selection and shutdown cancel obsolete activation, and shutdown drains it. Derive bootstrap/current private lifecycle after acquisition, install only accepted memory, clear Stop fences only after acceptance, and never restore an old snapshot/specification after a later failure. Commands, deferred settled Start and Telegram await completion; success and failure presentation receipts revoke with selection. Initial attachment and exact-source fork recovery remain restoration-owned. It initializes missing global, CWD, and current-session checkpoint/tail pairs plus session config/runtime metadata through compare-and-swap publication, enables only the current branch, and bootstraps prior conversation when needed. Activation preserves the validated current same-session cohort, including private semantics, provenance, scope revisions, runtime step, and available aligned history, even when the selected pointer is expired, active, unfinished or pre-runtime. Bind the private stream to its runtime lineage and CAS the exact captured file cohort; rebase independently validated shared drift only when the old lineage cannot compose. Do not resurrect an unfinished specification or claim unavailable history was restored. Create an empty private origin only when all current-session authority is absent and branch provenance permits initialization. Unaccepted physical forks retain their exact-source copy contract. Repeated Start while already active is inert, including during response reconciliation. Malformed evidence or failed exact-cohort CAS prevents acceptance; ordinary cooperating contention waits instead of becoming a conflict. Ordinary new sessions remain manual unless repository-global `autoStart` is true; configured new sessions may initialize missing CWD state and receive distinct empty session layers while inheriting global/CWD values. Resumed and tree-selected branches restore their retained canonical lineage regardless of that flag.
45
- - `/state-flow-stop` returns to the configured passive bootstrap/tool combination before attempting canonical persistence; a rejected write never cancels local disablement. For an accepted runtime, await `withLifecycleTransaction` to persist only the current session/branch's `config.enabled = false` and necessary runtime provenance, preserving all semantic checkpoints/tails and creating no semantic transition. Freeze the passive handoff and switch local policy/tools/UI before waiting; derive lifecycle input and recheck selected runtime/owner/policy after acquisition. Repeated pending Stop calls share one operation. Selection, shutdown and successful Start cancel obsolete Stop work; a rejected Start must not cancel it. Combine an available Pi signal with Stop-owned cancellation, drain pending Stop on shutdown, and install caches/checkpoint inside acceptance before yielding. Pre-acceptance failure keeps mode off and fences writes; post-acceptance failure cannot roll back accepted memory or replay native writes. A proven pre-runtime branch instead appends only the existing `{disabled:true}` Pi checkpoint; a cached passive view never authorizes runtime publication or a retained-boundary checkpoint. Only accepted canonical publication ends that pre-runtime condition. Preserve failed-selection fences, passive access, and later explicit Start/passive patch behavior. Lifecycle-only writes adopt unrelated live shared drift at a fresh origin when needed, without touching semantic/provenance files or counters; same-session races and precomputed stale provenance writes still fail closed. Do not opportunistically fold tails or prune evidence during lifecycle persistence, even if another writer loaded a larger history limit. Refresh the host cache after adoption, freeze Stop's handoff from that accepted cache, and inspect newly adopted registered paths before the next enabled inference. Retain a frozen handoff plus the active user-run trajectory (including later tool results), post-stop conversation, and foreign context-bearing custom messages across same-physical-session reload/resume/tree. Exclude completed pre-run conversation only when the active boundary is proven. If a recorded active anchor is missing, nonfinite or ambiguous after native projection/compaction, reuse the active context selector and retain available summaries and tool trajectory; never fall back to the idle cutoff or reconstruct discarded raw entries. Only Stop after a completed idle run applies the post-stop cutoff. Unaccepted preparation and native conversation after the latest valid checkpoint also prevent an idle cutoff, even when a boundary continuation has no specification. Same-physical-session restoration conservatively retains such uncompiled context through the existing bootstrap flag; it neither invents a run anchor nor restores discarded raw entries. An unfinished bootstrap preserves all available native context unless an earlier passive boundary already bounded it; repeated mode toggles keep that earlier boundary until bootstrap completion. Persist this choice in the existing native Stop marker as optional `preserveContext: true`. After interruption, retain the captured native run anchor even when Pi is idle, or all available context when capture is absent. Active restart replaces passive mode but uses that bounded boundary for its one bootstrap run; new and forked physical sessions inherit neither projection. It does not rewrite agent-level `autoStart` or change its policy for future new sessions.
46
- - A failed Stop records only local policy and a write fence in the existing native passive-stop marker: exact session `owner`, non-empty `persistenceError`, and `preserveContext: true`. Never append a substitute semantic checkpoint or reset canonical state. Preserve accepted cached memory and all available native context; same-session reload reads validated current memory without restoring/publishing an older selection. Corrupt or missing evidence remains unavailable, never invented empty private memory. Keep the fence until a later accepted checkpoint from explicit Start; repeated degraded Stop is inert. Status distinguishes unavailable memory from unavailable publication, and inspection may show the accepted cache without attempting a conflicting refresh. Forks retain disabled source policy but inherit neither the parent's fence nor its projection. Durable fallback requires a writable native Pi trace.
47
- - After an accepted non-bootstrap run settles with no pending input, State Flow may request native manual compaction under a generation-private marker only when public `getContextUsage()` reports at least 24,000 tokens. Keep the complete latest accepted run from its already captured first-user anchor, including steering and tool results; never substitute the last user message. Require one matching native user timestamp before the final assistant, otherwise skip rather than guessing. Store only retained boundary/step identity in details, and never duplicate state in the summary. Unknown or smaller usage skips compaction; a benign native refusal releases the attempt for later work. Await the native compaction completion/error callback inside the settled handler before returning, so Pi's deferred companion prompt dispatch cannot race an in-flight manual compaction; do not add a timer, queue or continuation owner. Skip prefixes containing foreign custom metadata or native `custom_message` context. Never customize user manual or native threshold/overflow compaction, discard unfinished pre-patch work, create a State Flow origin, or rewrite Pi's append-only JSONL/tree.
48
- - Keep the injected runtime protocol compact and normative; put rationale and extended explanation in README rather than the model prompt. Contribute initial active/passive protocol through Pi's native `systemPromptOptions.sections.state_flow`, not a returned forced `systemPrompt`; refresh only that owned section at `context_with_system` from current mode so in-flight Stop/Start and boundary continuations do not retain stale instructions. Keep section projection pure in the context domain, preserve unchanged arrays/native deltas and non-system identities, and never invent missing system frames. Preserve companion sections, tool declarations, native trace and explicit foreign forced-prompt precedence. Foreign comment handling remains owned by other extensions.
49
- - Do not claim strict boundedness for state, the current run trajectory, the turn specification, or the external full trace.
50
- - Remain extension-agnostic in core semantics, storage, and inference: core modules never import, name, special-case, or encode policy for another extension or transport. One optional leaf presentation adapter (`lib/telegram.ts`) may import public `pi-telegram` membranes to show the live `G#/C#/S#` effective revision vector on exactly one main-menu section button only while active mode is enabled, expose the same start/stop affordances already owned by `state-flow-start` and `state-flow-stop`, and read global/CWD/session/effective snapshots in active or passive mode. Passive main-menu identity renders `State Flow: off`; requested owner-scope Rich snapshots show `#revision`, while Effective shows the vector. Inspection awaits `TemporalRuntime.refreshShared` for one coherent shared cohort, preserves the exact selected private basis, and never publishes or advances a revision. Telegram observation may lazily load existing shared canonical state even when passive model tools are disabled, but never initializes or mutates it; absent/invalid memory stays unavailable rather than becoming an invented empty Rich state. Return data and matching revisions together, revoke pending observations on Stop/selection/shutdown, and check their signal again before presentation. Acknowledge the callback before waiting; show escaped late diagnostics in the existing menu instead of answering an expired callback. The inspection-capable port also permits awaited Start/Stop results with optional revocation signals; acknowledge controls before waiting without delaying local Stop on the network response. Discard revoked results, superseded callback views and disposed-section work; render late failures escaped in the existing menu without a second callback answer. Keep legacy synchronous ports compatible. Registration must fail open when the transport is absent or its registry is unready and must never alter core behavior.
51
- - Activate State Flow model tools while an episode is enabled or passive tools are configured; preserve every unrelated active tool when toggling them. Passive reads never initialize storage, while an explicit passive patch may initialize absent canonical storage without enabling an episode, continuation, or compaction. Unsupported predecessor storage is never converted. Keep mutation confined to `patch_state` and historical observation read-only.
52
- - Keep `.github/workflows/release.yml` as the sole version-tag release owner: it validates immutable tag identity, publishes through npm Trusted Publisher with provenance, verifies the public package, and only then creates the GitHub Release. Keep package, lockfile, tag, and changelog versions aligned; never add a long-lived npm token fallback.
53
- - Keep opt-in performance executables and workers in top-level `benchmarks/`; their correctness regressions stay in `tests/`. Benchmark workloads may reuse synthetic test fixtures, remain excluded from runtime packaging, and retain source-bound measurement identities across relocations.
54
- - In native scripted-provider tests, assert callback completion outside the provider as well as checking input inside it: Pi may convert an assertion thrown by a provider into an assistant error rather than rejecting the test's prompt. Do not count swallowed provider assertions as successful evidence.
55
- - Await startup/tree lifecycle handlers in fixtures before inspecting their completed state. In contended-store cancellation tests, dispatch replacement selection without awaiting it, prove the obsolete operation withdraws while exclusion remains held, then release storage and join the replacement. Keep old-operation trace/notice checks distinct from legitimate replacement UI completion.
56
- - Keep generated `dist/` in the release Git tree; do not re-add it to `.gitignore`. Rebuild from final sources and package metadata before release, include the resulting files in the release commit, and verify source/build parity as well as npm inventory. Git inclusion and npm `files` inclusion are distinct obligations.
57
- - Keep maintained README/docs focused on current behavior, supported contracts and verification limits. Version comparisons, removed intermediates and implementation chronology belong in CHANGELOG, not current compatibility/architecture guidance.
58
- - Run `npm run validate` after retained code changes, then run the canonical ABCd context validator after context edits.
3
+ The [relocation ledger](docs/agent-contract-relocation.md) maps every pre-compaction paragraph to its owning contract or test. Keep this file as durable development policy, not a second copy of the product manuals.
4
+
5
+ ## Ownership and semantics
6
+
7
+ - Keep `index.ts` minimal, independent domains in `lib/` with same-named tests, architecture checks in `tests/invariants.test.ts`, and Pi lifecycle composition in `lib/extension.ts`; delegate low-level mechanics to their owners. See [composition](docs/architecture.md#composition).
8
+ - Keep Off the genuinely new-session default, with Passive and Active opt-in; Off removes State Flow model tools/context without deleting memory. Modes belong to the current session; global mode is only a new-session default. Passive declares both tools even without memory, but contributes protocol/projected state only with a validated view. See [mode behavior](docs/usage.md#active-passive-and-configured-off) and [configuration](docs/usage.md#configuration).
9
+ - Preserve Pi's native tool loop, trace and foreign context; the context domain alone projects the raw scope overlay. Freeze/rebase the head only at specified boundaries, retain current-run trajectory and stable-position tail notices, and never give projection IDs or guessed user anchors publication/compaction authority. See [Pi lifecycle](docs/architecture.md#pi-lifecycle) and [projection evidence](docs/performance.md#context-projection-and-trajectory-selection).
10
+ - Store only present known `intents`, `contract`, `working`, `artifacts`, `response`, `lazy` fields; preserve nested data and retained causal identities. Missing planes and empty response do not become fabricated stored defaults; malformed evidence fails closed. Keep lazy bodies out of automatic projection and Session as the sole author of new responses. See [semantic state](docs/architecture.md#semantic-state) and [temporal model](docs/architecture.md#temporal-model).
11
+ - Respect global → CWD → session ownership, scope-local deletion and inherited fallbacks; scope does not confer instruction authority. Registered Skill ownership follows Pi source provenance, not path shape. See [semantic state](docs/architecture.md#semantic-state) and [artifact routing](docs/architecture.md#artifact-routing).
12
+ - Artifacts name exact registered source paths; observe only regular non-symlink files, never discover directories or read unrelated bodies. Preserve hidden per-scope provenance, exact-owner compilation, stable fingerprint checks and separate Skill hashes; unavailable sources are not proof of deletion. See [artifact routing](docs/architecture.md#artifact-routing).
13
+ - Preserve session config/runtime, per-scope metadata, lineage and provenance outside model-patchable state; decode legacy mode evidence read-only, never mix representations or normalize storage eagerly. See [storage and identity](docs/architecture.md#storage-and-identity) and [mode compatibility](docs/compatibility.md#mode-configuration-compatibility).
14
+ - Keep one opaque composed causal lineage, anchored checkpoint/tail materialization, configured hot-history folding and independent owner revisions; never invent earlier history or rebuild discarded offsets. Historical reads are observational, and `effective[n]`/owner materializations select the same causal boundary. See [temporal model](docs/architecture.md#temporal-model) and [model tools](docs/architecture.md#model-tools).
15
+
16
+ ## Publication and lifecycle
17
+
18
+ - Treat canonical scope files as semantic authority and Git only as optional backup. Classify complete, wholly absent, partial and malformed cohorts before recovery; absent shared pairs may initialize only under accepted authority, while incomplete/private evidence fails closed. Never repair through ad-hoc writes. See [storage recovery](docs/usage.md#storage-and-recovery) and [transaction rule](docs/filesystem-recovery.md#transaction-rule).
19
+ - Keep exact regular-file, byte-CAS and lock-serialized publication with cancelable waits, single-use callback-scoped capabilities and guarded rollback. Never hold exclusion across inference, source acquisition or Git; do not steal interrupted locks, claim kernel-atomic multi-file publication or promise power-loss durability. See [asynchronous transaction](docs/architecture.md#asynchronous-storage-transaction) and [durability boundary](docs/filesystem-recovery.md#power-loss-durability).
20
+ - Restore selected private retained boundaries over live shared scopes and copy exact proven source-session history into a fresh fork owner; never substitute current, empty, Git or another branch on expiry/failure. Explicit Start instead validates current same-session authority. Only accepted candidates install cache, checkpoint and mode. See [Pi lifecycle](docs/architecture.md#pi-lifecycle) and [fork contract](docs/fork-contract.md).
21
+ - Persist each material semantic change and its affected revisions exactly once, including accepted Session responses. Optional settled-turn Git backup may capture only already-accepted owned files, leave unrelated index/worktree data intact and push without force or semantic side effects. Defer busy backup on Pi 0.87 rather than blocking Abort; never move it to `turn_end` or add a durable push queue. See [optional Git backup](docs/architecture.md#optional-git-backup).
22
+ - Accept one atomic `patch_state` cohort across supplied scopes against current shared memory; reject empty scopes, unknown/retired grammar and model-authored `response`. Correct no-ops create no transition. Enforce the single-call inference barrier before sibling tools execute and retain conservative model-facing reconciliation when a result cannot be predicted. See [model tools](docs/architecture.md#model-tools) and [Pi lifecycle](docs/architecture.md#pi-lifecycle).
23
+ - Reconcile the actual accepted ordinary answer at `turn_end` with response-owned cancellation and one accepted lifecycle publication; do not request private repair inference, ceremonial finalization patches or roll back accepted memory after cancellation. See [Pi lifecycle](docs/architecture.md#pi-lifecycle).
24
+ - Capture specifications without writes at `before_agent_start`, then await one cancellable preparation acceptance before active inference; abort failed context preparation through Pi's public hook. Keep user text at user authority and state as fallible data. Preserve an existing conversation for exactly one bootstrap run, not forever. See [Pi lifecycle](docs/architecture.md#pi-lifecycle) and [pre-inference cancellation](docs/compatibility.md#pre-inference-cancellation).
25
+ - Make Start await coherent current-head acceptance, and let Passive/Off select local policy before asynchronous runtime-only persistence. Preserve independently owned fork/restoration work and latest inactive choices; a failed Stop fences writes with a native marker, never a substitute semantic checkpoint. Off exposes no frozen handoff. See [lifecycle planes](docs/architecture.md#lifecycle-planes) and [lifecycle operations](docs/usage.md#lifecycle-operations).
26
+ - Request completed-history native compaction only after an accepted non-bootstrap settled run, public usage ≥24,000 tokens and a uniquely captured first-user anchor; retain the complete latest run and foreign context. Await its native callback before returning, and leave Pi manual/threshold compaction and append-only history alone. See [lifecycle planes](docs/architecture.md#lifecycle-planes).
27
+ - Contribute only State Flow's compact normative system-prompt section through Pi's section membrane; refresh it with current mode without overwriting foreign sections, forced-prompt precedence or native message identities. Never invent a continuation scheduler. See [lifecycle planes](docs/architecture.md#lifecycle-planes) and [host context compatibility](docs/compatibility.md#context-tools-and-provider-input).
28
+
29
+ ## Model and operator boundaries
30
+
31
+ - Treat state as a decision-relevant handoff, not a transcript: distinguish user requirements, confirmed decisions, observations, hypotheses, chosen intents and remaining checks. Revalidate volatile external effects before repeating actions; memory is neither an action ledger nor proof of current reality. See [operational guidance](docs/architecture.md#operational-guidance-and-memory-curation) and the [memory Skill](skills/state-flow-memory/SKILL.md).
32
+ - Resolve semantic `$` paths and structured references only when needed; never confer authority or existence by reference alone, scan to find broken references, automatically search all history or restore deleted values from hints. See [model tools](docs/architecture.md#model-tools) and [lazy navigation](docs/usage.md#lazy-navigation-and-historical-reading).
33
+ - Keep Skill acquisition optional and exact-path/provenance-derived; successful reads alone are volatile, and attempted durable compilations require scoped validated output plus runtime-owned hash evidence. See [artifact routing](docs/architecture.md#artifact-routing).
34
+ - Reconcile touched state without automatic whole-store audits. Dedicated curation needs a user request; intra-store moves use one verified multi-scope patch, and external transfers need verified destination acceptance before source deletion. See [operational guidance](docs/architecture.md#operational-guidance-and-memory-curation) and the [memory Skill](skills/state-flow-memory/SKILL.md).
35
+ - Keep opt-in diagnostic categories, failure elision/privacy and barrier-only names-only records outside canonical state; logging failures cannot change accepted state. Preserve a blank line between every tool name and its output. See [diagnostic privacy](docs/usage.md#diagnostic-logging-and-privacy) and [barrier diagnostics](docs/architecture.md#pi-lifecycle).
36
+ - Keep public patch outputs and staged drafts detached from caller/accepted values; private path-copying must not leak mutable objects or weaken CAS. Reject stored null in documented semantic planes while preserving valid nested object-key deletions. See [storage and identity](docs/architecture.md#storage-and-identity) and [model tools](docs/architecture.md#model-tools).
37
+ - Do not add project schemas, state/patch byte caps, dynamic growth pressure, action authorization, automatic reference hydration or strict boundedness claims for state, the turn specification, the current-run trajectory or Pi's external trace. See [model tools](docs/architecture.md#model-tools) and [operational boundaries](README.md#operational-boundaries).
38
+ - Keep terminal status observational and mode-derived; no source maintenance or invented empty view on inspection. Optional Git, Telegram and diagnostics degrade without fabricated success or weakened memory ownership. The optional `lib/telegram.ts` presentation leaf alone may consume pi-telegram's public membranes; core semantics/storage/inference remain transport-agnostic. See [status and controls](docs/usage.md#status-and-controls) and [observability](docs/architecture.md#observability).
39
+
40
+ ## Delivery discipline
41
+
42
+ - Keep the exact-tag [release workflow](.github/workflows/release.yml) as sole npm Trusted Publisher and GitHub Release owner; align version, lockfile, tag and changelog, with no long-lived npm-token fallback. Keep generated `dist/` tracked, rebuild after final source/package edits and verify source/build parity and npm inventory. See [validation boundaries](docs/architecture.md#validation-boundaries).
43
+ - Keep opt-in measurements under `benchmarks/`, excluded from normal tests/packaging, with source-bound workload identities. Native scripted-provider tests assert callback completion outside the provider; startup/tree and cancellation fixtures await the right ownership boundary. See [benchmark guide](benchmarks/README.md) and [temporal witnesses](docs/temporal-acceptance.md#required-properties-and-witnesses).
44
+ - Keep README/docs current rather than copying chronology out of CHANGELOG; preserve SKILL.state attribution for inherited explicit-state ideas. Exercise malformed/predecessor storage only in temporary repositories, never the user's active data. Run `npm run validate` after retained code changes and the canonical ABCd context validator after context edits. See [documentation index](docs/README.md) and [validation procedure](docs/compatibility.md#validation-procedure).
@@ -1,7 +1,20 @@
1
1
  # Backlog
2
2
 
3
- No open implementation items for the 0.21.0 Minimal Reconciliation scope. Completed outcomes are recorded in [CHANGELOG.md](CHANGELOG.md); current behavior and conservative reconciliation boundaries belong in [architecture](docs/architecture.md).
3
+ The **0.23.0** release scope is recorded in [CHANGELOG.md](CHANGELOG.md); this backlog keeps installed-client evidence and later decisions open. Canonical storage, CAS, `historyLimit`, temporal semantics, projection and the model-facing protocol remain unchanged; already retained session modes and explicit global/legacy policies stay authoritative. Current contracts live in [architecture](docs/architecture.md) and [usage](docs/usage.md).
4
4
 
5
- Release publication is owned by `.github/workflows/release.yml`. Verify the exact tag's successful workflow, published GitHub Release and matching npm package before reporting release completion. Installed-instance reload remains a separate operator action.
5
+ ## Carried gates
6
6
 
7
- Canonical storage, revisions, history, CAS and lifecycle formats are unchanged. Structural prefix evidence is described in the [benchmark guide](benchmarks/README.md); it does not claim provider cache-hit, token-cost or latency guarantees.
7
+ - **Installed 0.22.0 smoke (operator-owned):** Perform the carried check if it is not yet recorded, only against the exact released 0.22.0 installation; a reload of the modified 0.23.0 candidate cannot certify the old release. After an operator-authorized reload, confirm:
8
+ - terminal autocomplete exposes Active/Passive/Off and status;
9
+ - Telegram shows the single `off | passive | active` row plus the four inspection buttons;
10
+ - current-session mode agrees across tools, context and status, and survives reload.
11
+ Do not edit real global defaults or unrelated sessions.
12
+ - **Installed 0.23.0 smoke (operator-owned):** After separately authorized installation/reload, confirm an unconfigured *new* session is Off without semantic writes, retained choices and explicit global modes survive, and Telegram shows one `Off | Passive | Active` radio row with the selected 🟡/🟣/🟢 marker and ⚫️ inactive markers, followed by four direct scope inspections. Isolate test storage; do not use the live store as a fixture. SDK tests alone do not certify installed-client rendering.
13
+
14
+ ## Deferred beyond 0.23.0 (decision inputs, not commitments)
15
+ - **Compaction threshold:** `STATE_FLOW_COMPACTION_MIN_CONTEXT_TOKENS = 24_000` is documented as a margin above Pi's default 20,000-token retained suffix. Make it configurable only if a real workload or non-default Pi retention settings demonstrate a mismatch.
16
+ - **Lifecycle complexity review:** Measure how often cooperating-writer waits, Stop fences and fork/restore contention occur in real use before adding further awaited lifecycle layers. Use the result to decide whether any existing layer can be simplified.
17
+
18
+ ## Release boundary
19
+
20
+ Release publication is owned by `.github/workflows/release.yml`. Align package, lockfile, tag and changelog at the release version, rebuild `dist/` from final sources, and verify the exact tag's successful workflow, published GitHub Release and matching npm package before reporting release completion. Installed-instance reload remains a separate operator action.
@@ -2,6 +2,25 @@
2
2
 
3
3
  > Each release keeps at most 8 outcome records of at most 512 characters.
4
4
 
5
+ ## Unreleased
6
+
7
+ ## 0.23.0: Off by Default and Mode Controls
8
+
9
+ - `Passive footprint clarified`: When selected, Passive always declares both memory tools, but contributes protocol and projected memory only with a validated view; a source-bound empty/nonempty byte probe documents the distinction without claiming provider token costs. Off removes State Flow's model-facing tools and context.
10
+ - `Barrier diagnostics`: With opt-in logging, blocked Active tool calls now record `barrier-block` with the exact reason, call identity and batch tool names, never sibling arguments or reasoning. Passive has no barrier; logging-off blocks remain unrecorded. Blocking and canonical state behavior are unchanged.
11
+ - `Focused onboarding`: README keeps installation, three-mode behavior and state model; status and Telegram rendering details live in usage, including a concrete revision-vector example.
12
+ - `Toolchain ranges`: Declare `typescript` `^7.0.2` and `@types/node` `^26.4.0` in package and lockfile metadata, matching installed/locked versions instead of floating `latest` across major refreshes.
13
+ - `Contract map and compaction`: Reduce `AGENTS.md` from 8,141 to about 1,300 words, with one-line owner links; relocate missing normative detail to architecture/usage and map all 56 former paragraphs to current contracts or tests. Keep storage semantics and `tests/invariants.test.ts` unchanged.
14
+ - `Off by default`: New sessions without a configured mode now adopt Off without initializing semantic storage; explicit global modes and legacy flag mappings still apply, and resumed sessions keep their selected mode. Passive and Active remain opt-in; stored memory is not erased.
15
+ - `Telegram mode radios`: Replace the lowercase mode row and redundant list with `Off | Passive | Active` radio labels (⚫️ inactive; 🟡/🟣/🟢 selected). Matching Mode and Inspect memory headings and blank-line-separated settings-style lists explain the workflow progression and scope buttons, including inspection in Off. Callback routing and four direct scope buttons remain unchanged.
16
+
17
+ ## 0.22.0: Sparse State and Session Modes
18
+
19
+ - `Sparse semantic memory`: Checkpoints and retained patches may omit documented planes. Readers and writers select only known top-level fields while preserving nested data, causal identities and history boundaries. Current and historical views omit absent fields and empty responses; explicit reads of absent documented fields return `null`. Reads and activation do not normalize stored bytes; malformed data and unproven authority still fail closed.
20
+ - `Minimal updates`: Patches emit only actual known-field changes without filling absent planes. Empty and absent responses are projection-equivalent: clearing a nonempty response creates a transition, but replacing absence with an empty string does not. No-ops advance no scope revision; retained empty records retain their identities.
21
+ - `Session-owned modes`: `/state-flow-active`, `/state-flow-passive` and `/state-flow-off` replace Start/Stop. Active runs state-driven episodes; Passive (the new-session default) exposes memory tools and state context with ordinary conversation; Off exposes neither. Global `mode` affects only new sessions. Inactive choices persist in Pi before semantic initialization and leave semantic revisions and existing write fences unchanged; legacy flags remain readable.
22
+ - `Focused controls and inspection`: Terminal shows `state-flow active/passive` or hides in Off; revisions move to `/state-flow-status`, whose semantic JSON separates top-level planes. Telegram shows a lowercase mode value with four direct scope buttons and the revision vector in Effective inspection. Pending mode selections, read-only recovery and revoked receipts cannot overwrite a newer choice.
23
+
5
24
  ## 0.21.0: Minimal Reconciliation
6
25
 
7
26
  - `Sparse acceptance receipts`: Predictable direct/indexed writes, object replacements, disjoint scope writes, explicit Session scalar/array overrides, unchanged-effective deletions, artifact merges and complete lazy-navigation updates omit redundant semantic tails. Shared drift, changed hints, unknown fallback and ambiguous overlap still reconcile; lazy bodies and provenance stay hidden. Canonical storage, revisions and lifecycle formats are unchanged.
@@ -4,13 +4,13 @@
4
4
 
5
5
  **Incremental scoped context/memory compiler for Pi.**
6
6
 
7
- State Flow maintains explicit state across requests and sessions. The agent incrementally compiles requirements, decisions, findings and source knowledge into durable memory rather than carrying every completed exchange into the next request.
7
+ When enabled, State Flow maintains explicit state across requests and sessions. The agent incrementally compiles requirements, decisions, findings and source knowledge into durable memory rather than carrying every completed exchange into the next request.
8
8
 
9
9
  Drawing on the explicit-state approach of [SKILL.state](https://arxiv.org/html/2608.26263v2), State Flow combines durable state with Pi's native conversation context. In this hybrid, **state carries continuity between user runs; Pi's native context carries the working trajectory within a run.** The conversation is not reset after each model response or tool call. Pi retains ownership of execution, session navigation and the full inspectable trace.
10
10
 
11
11
  ## How it works
12
12
 
13
- A user run starts with effective memory and a new request. The agent works through Pi's ordinary inference/tool loop, updates memory when useful information changes, and returns an ordinary answer. The next run receives the accepted state and compact recent transitions instead of the completed ordinary conversation history.
13
+ In Active mode, a user run starts with effective memory and a new request. The agent works through Pi's ordinary inference/tool loop, updates memory when useful information changes, and returns an ordinary answer. The next run receives the accepted state and compact recent transitions instead of the completed ordinary conversation history.
14
14
 
15
15
  ```text
16
16
  Current state + Request
@@ -47,22 +47,23 @@ pi install git:github.com/llblab/pi-state-flow
47
47
  Enable active State Flow on the current branch:
48
48
 
49
49
  ```text
50
- /state-flow-start
50
+ /state-flow-active
51
51
  ```
52
52
 
53
53
  Starting in an existing conversation retains its context for one complete bootstrap run so the agent can compile what matters.
54
54
 
55
- - `/state-flow-start`: Enable the active, state-driven iteration workflow and memory-based context projection; passive mode can already save explicit patches.
55
+ - `/state-flow-active`: Select the active, state-driven iteration workflow.
56
+ - `/state-flow-passive`: Select ordinary conversation with both memory tools and existing-memory projection.
57
+ - `/state-flow-off`: Remove both memory tools and all State Flow model context, without deleting memory.
56
58
  - `/state-flow-status`: Inspect effective state, retained history and known recovery issues without scanning sources or changing state.
57
- - `/state-flow-stop`: End active episode semantics without deleting memory, even when canonical persistence fails. Interrupted work and uncompiled conversation remain available across toggles and reload; a failed write stays fenced until explicit Start safely reactivates current memory.
58
59
 
59
- Active mode is **opt-in**. Passive memory projection and the memory tools are enabled by default: existing state can be read or explicitly patched without an active episode or State Flow compaction. Every materially changed owner advances its independent scope revision even in passive mode, without displaying an active-mode status. When active, terminal and Telegram status render the Effective revision vector as `G15/C8/S31`; passive Telegram shows `State Flow: off`. Requested Global, CWD and Session snapshots show their own `#revision`, while Effective shows the vector. Inspection waits cancelably for a coherent shared view, with matching data and revisions, without publishing state or advancing a counter. Stop returns to the configured passive behavior. `autoStart` can enable active mode for genuinely new sessions; resumed branches restore their own enablement. See [configuration](docs/usage.md#configuration).
60
+ New sessions default to **Off**; select Passive for ordinary conversation with memory tools, or Active for state-driven episodes. Passive projects state only after a validated memory view is available. Off removes State Flow's model-facing tools and context without deleting memory. Mode changes affect only this session; the global default applies only to new sessions. See [mode semantics](docs/usage.md#active-passive-and-configured-off), [configuration](docs/usage.md#configuration) and [status and controls](docs/usage.md#status-and-controls).
60
61
 
61
62
  ### Active, passive, off
62
63
 
63
64
  - `Active`: Memory tools are available; the agent consolidates necessary final state changes before completing an iteration. Subsequent iterations use accepted state and new input rather than completed prior reasoning.
64
- - `Passive`: Memory tools and existing-state projection remain available by default. Patching is on demand, and ordinary conversation context continues without State Flow's active iteration reset.
65
- - `Configured off`: With the branch inactive and both `passiveTools` and `passiveBootstrap` false, neither memory tool nor bootstrap/state projection is exposed to the model. `autoStart: false` alone does not turn memory off.
65
+ - `Passive`: Both memory tools and existing-state projection remain available. Patching is on demand, and ordinary conversation context continues without State Flow's active iteration reset.
66
+ - `Off`: Neither memory tool nor State Flow context—including a frozen passive handoff—is exposed to the model. Stored memory and Pi's native trace remain intact.
66
67
 
67
68
  Modes select agent behavior, not a different disk persistence or fork-copy mechanism. Final consolidation does not require an empty ceremonial patch, and context projection does not delete native history. See [mode semantics and bootstrap terminology](docs/usage.md#active-passive-and-configured-off).
68
69
 
@@ -82,16 +83,18 @@ The agent receives the **effective view** of this composition, not three unrelat
82
83
 
83
84
  ### Semantic planes
84
85
 
85
- Every scope uses the same shape:
86
+ Runtime views provide these documented planes:
86
87
 
87
88
  - `intents`: Active commitments to future action.
88
89
  - `contract`: Requirements, decisions, constraints and interface commitments.
89
90
  - `working`: Observations, results, uncertainties and current continuation.
90
91
  - `artifacts`: Source-addressed descriptions and compiled knowledge.
91
- - `response`: The exact latest accepted answer, including an empty string, captured by the runtime only in Session. Global and CWD retain an empty structural slot; Effective inherits the Session value.
92
+ - `response`: The exact latest accepted answer, including an empty string, captured by the runtime only in Session. Global/CWD receive no newly accepted answers; stored scopes may omit response entirely. Effective uses the highest-priority nonempty value.
92
93
  - `lazy`: Supporting memory available through explicit reads, with its body omitted from baseline model context.
93
94
 
94
- These planes organize ordinary JSON rather than imposing a project-specific schema. The model updates the semantic planes except `response`, which is runtime-owned. Global and CWD revisions are shared by their canonical stores, Session has its own revision, and Effective has no scalar owner: its identity is the `G#/C#/S#` vector. One atomic patch advances each materially changed scope once. Memory remains fallible: storing an observation does not make it current or correct.
95
+ Stored checkpoints and patches may omit any documented plane, including `intents`, `lazy` or `response`. Current and historical views assemble only known fields actually present in the selected scopes, without filling absent fields. Empty `response` is treated as absent. Checkpoint and patch readers ignore unknown top-level fields; writers emit only known fields. Nested data within known planes is unrestricted. Reading or starting never rewrites data just to normalize it; missing fields are not a storage-format error.
96
+
97
+ These planes organize ordinary JSON rather than imposing a project-specific schema. The model updates the semantic planes except `response`, which is runtime-owned. Global and CWD revisions are shared by their canonical stores, Session has its own revision, and Effective has no scalar owner: its identity is the `g#c#s#` vector. One atomic patch advances each materially changed scope once. Memory remains fallible: storing an observation does not make it current or correct.
95
98
 
96
99
  Registered Pi Skills may be compiled into source-addressed artifacts when durable guidance is useful. Pi's resource provenance determines ownership: user Skills map to global, project Skills to CWD and temporary Skills to session. A matching source hash needs no update; an uncompiled read remains ordinary volatile context and does not block unrelated patches.
97
100
 
@@ -138,7 +141,7 @@ The default store is `~/.pi/agent/state-flow/`, independent of registered source
138
141
 
139
142
  Resume and tree navigation restore the selected retained session boundary over current shared global/CWD memory. A new session gets its own session layer. Supported native forks copy selected session state into a new owner without changing the parent's private data. Expired, incomplete or contradictory boundaries never silently substitute newer private state during restoration. Explicit Start is a mode change, not historical restoration: it activates validated **current** memory of that same session, including private state, even after expired active/passive, interrupted or pre-runtime selections. Available aligned history and revisions survive; unavailable history is not recreated. Malformed storage, unsafe fork copying and concurrent writes remain fenced. See [fork support](docs/usage.md#fork-support-and-limits) and [storage recovery](docs/usage.md#storage-and-recovery).
140
143
 
141
- SDK/launcher integrations can use [advisory continuation APIs](docs/architecture.md#session-continuation). Provenance inspection and candidate building are now asynchronous and accept host cancellation; they neither open native sessions nor install automatic resume. Run preparation and missing-artifact maintenance now wait cancelably before inference; embeddings can also use the [transaction APIs](docs/architecture.md#asynchronous-storage-transaction). Accepted-runtime Stop switches local policy/context immediately and awaits runtime-only persistence. Current-head Start also awaits coherent capture/acceptance before enabling mode; Stop or selection can cancel its wait. Telegram acknowledges controls early. Startup/recovery and exact restoration/fork still require migration, including Start's initial-attachment and unaccepted-fork paths.
144
+ SDK/launcher integrations can use [advisory continuation APIs](docs/architecture.md#session-continuation). Provenance inspection and candidate building are now asynchronous and accept host cancellation; they neither open native sessions nor install automatic resume. Run preparation and missing-artifact maintenance now wait cancelably before inference; embeddings can also use the [transaction APIs](docs/architecture.md#asynchronous-storage-transaction). Selecting Passive or Off switches local policy/context immediately and awaits runtime-only persistence. Active waits for coherent capture/acceptance; another mode or selection can withdraw its wait. Startup, recovery and exact restoration/fork also await their independently owned memory operation; mode changes never cancel required copying. A failed write preserves the selected inactive mode and fences publication until accepted activation.
142
145
 
143
146
  The canonical storage-format boundary introduced in 0.17 still applies: current versions accept only the canonical store contract and provide no in-place predecessor converter. Preserve existing data and check the [format boundary](docs/usage.md#moving-a-store-and-the-017-format-boundary) before changing versions or moving a store.
144
147
 
@@ -12,8 +12,8 @@ export { retainedMemoryScopes } from "./lib/memory.ts";
12
12
  export { planKnowledgeRehydration, type RehydrationOptions, type RehydrationPhase, type RehydrationPlan, type RehydrationRead, type RehydrationRoute } from "./lib/rehydration.ts";
13
13
  export { TemporalRuntime } from "./lib/runtime.ts";
14
14
  export { hasCompiledSkillArtifact, hashSkillSource, SKILL_ARTIFACT_COMPILER, type SuccessfulSkillRead } from "./lib/skills.ts";
15
- export { emptyState, isMaterializedState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts, type AtomicScopePatches, type MaterializedState, type ScopedPatch, type ScopedStates, type ScopePatch, type SemanticTransition, type StateDocument, type StatePatch, type StateScope, type TerminalTransition } from "./lib/state.ts";
15
+ export { emptyState, isMaterializedState, isSemanticState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts, type AtomicScopePatches, type MaterializedState, type ScopedPatch, type ScopedStates, type ScopedSemanticStates, type ScopePatch, type SemanticState, type SemanticTransition, type StateDocument, type StatePatch, type StateScope, type TerminalTransition } from "./lib/state.ts";
16
16
  export { PublicationBusyError } from "./lib/storage.ts";
17
17
  export { buildStateFlowSectionView, createStateFlowTelegramAdapter, formatStateFlowSectionLabel, loadStateFlowTelegramModules, STATE_FLOW_TELEGRAM_ID, type StateFlowTelegramAdapter, type StateFlowTelegramButton, type StateFlowTelegramCallbackContext, type StateFlowTelegramControlResult, type StateFlowTelegramInspection, type StateFlowTelegramInspectionPort, type StateFlowTelegramLoader, type StateFlowTelegramModules, type StateFlowTelegramPort, type StateFlowTelegramSectionContext, type StateFlowTelegramSectionModule, type StateFlowTelegramSnapshot, type StateFlowTelegramView } from "./lib/telegram.ts";
18
- export { advanceTemporalState, readTemporalState, temporalScopeRevisions, type ScopeRevisions, type TemporalState } from "./lib/temporal.ts";
18
+ export { advanceTemporalState, readTemporalState, readTemporalView, temporalScopeRevisions, type ScopeRevisions, type TemporalState } from "./lib/temporal.ts";
19
19
  export { parseStateReadPath, readStatePath, type StateReadQuery, type StateReadResult } from "./lib/query.ts";
@@ -11,8 +11,8 @@ export { retainedMemoryScopes } from "./lib/memory.js";
11
11
  export { planKnowledgeRehydration } from "./lib/rehydration.js";
12
12
  export { TemporalRuntime } from "./lib/runtime.js";
13
13
  export { hasCompiledSkillArtifact, hashSkillSource, SKILL_ARTIFACT_COMPILER } from "./lib/skills.js";
14
- export { emptyState, isMaterializedState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts } from "./lib/state.js";
14
+ export { emptyState, isMaterializedState, isSemanticState, isStateDocument, overlayStates, projectStateForModel, updateMaterializedArtifacts } from "./lib/state.js";
15
15
  export { PublicationBusyError } from "./lib/storage.js";
16
16
  export { buildStateFlowSectionView, createStateFlowTelegramAdapter, formatStateFlowSectionLabel, loadStateFlowTelegramModules, STATE_FLOW_TELEGRAM_ID } from "./lib/telegram.js";
17
- export { advanceTemporalState, readTemporalState, temporalScopeRevisions } from "./lib/temporal.js";
17
+ export { advanceTemporalState, readTemporalState, readTemporalView, temporalScopeRevisions } from "./lib/temporal.js";
18
18
  export { parseStateReadPath, readStatePath } from "./lib/query.js";
@@ -1,9 +1,11 @@
1
+ import { type InactiveMode, type StateFlowMode } from "./snapshot.ts";
1
2
  export interface StateFlowConfig {
2
3
  /** Canonical State Flow repository. SDK callers may still override it explicitly. */
3
4
  directory: string;
4
- autoStart: boolean;
5
- passiveBootstrap: boolean;
6
- passiveTools: boolean;
5
+ /** Default mode for genuinely new sessions only; each session owns its selected mode. */
6
+ mode: StateFlowMode;
7
+ /** Non-active fallback for legacy `enabled:false` evidence and unavailable selections; never serialized. */
8
+ inactiveMode: InactiveMode;
7
9
  /** Opt-in local capture of rejected patch attempts and unresolved terminal drafts. */
8
10
  logging: boolean;
9
11
  /** Show successful patch_state arguments in the interactive tool row. */
@@ -12,3 +14,5 @@ export interface StateFlowConfig {
12
14
  }
13
15
  /** Read the repository-global config once at extension load/reload. Missing config uses defaults; invalid config never falls back. */
14
16
  export declare function loadStateFlowConfig(agentDir?: string, repositoryRoot?: string): StateFlowConfig;
17
+ /** Explicit modes never carry a separate passive policy: only Off stays off when inactive. */
18
+ export declare function inactiveModeFor(mode: StateFlowMode): InactiveMode;