@llblab/pi-kit 0.24.1 → 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 (85) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +5 -4
  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/package.json +6 -2
@@ -2,6 +2,7 @@ import { compileArtifact, ORDINARY_ARTIFACT_COMPILER, validateArtifactMetadata,
2
2
  import { createAcceptedTransition } from "./history.js";
3
3
  import { applyPatch, containsNull, hashJson, isObject, validatePatch } from "./json.js";
4
4
  import { hasCompiledSkillArtifact, SKILL_ARTIFACT_COMPILER } from "./skills.js";
5
+ import { emptyState } from "./state.js";
5
6
  const SCOPES = new Set(["global", "cwd", "session"]);
6
7
  const PATCH_KEYS = new Set(["intents", "contract", "working", "artifacts", "lazy"]);
7
8
  function compileReadArtifacts(nextState, patch, successfulArtifactReads, provenance) {
@@ -82,7 +83,7 @@ function compileReadSkills(scope, nextState, patch, successfulSkillReads, proven
82
83
  }
83
84
  }
84
85
  function validateMaterializedTransition(nextState, scope) {
85
- if (containsNull(nextState)) {
86
+ if (Object.keys(emptyState()).some((key) => containsNull(nextState[key]))) {
86
87
  throw new Error("Materialized state cannot contain null; use null only as an object-key deletion marker");
87
88
  }
88
89
  validateArtifactRegistry(nextState.artifacts, `${scope}.artifacts`);
@@ -111,16 +112,6 @@ function validateScopePatch(scope, patch) {
111
112
  if (isObject(patch.artifacts))
112
113
  validateModelArtifactPatch(patch.artifacts, `${scope}.artifacts`);
113
114
  }
114
- function completePatch(patch, response) {
115
- return {
116
- artifacts: patch.artifacts ?? {},
117
- contract: patch.contract ?? {},
118
- working: patch.working ?? {},
119
- intents: patch.intents ?? {},
120
- response,
121
- lazy: structuredClone(patch.lazy ?? {}),
122
- };
123
- }
124
115
  /** Stage all scope updates against one immutable basis before any state is published. */
125
116
  function stageScopedSemanticTransition(currentStates, transition, successfulSkillReads, causalBasis, successfulArtifactReads, acceptedResponse) {
126
117
  if (!Array.isArray(transition.transitions))
@@ -146,14 +137,17 @@ function stageScopedSemanticTransition(currentStates, transition, successfulSkil
146
137
  const provenanceUpdates = { global: {}, cwd: {}, session: {} };
147
138
  for (const scope of SCOPES) {
148
139
  const authored = patches.get(scope) ?? {};
149
- const response = scope === "session" && acceptedResponse !== undefined
150
- ? acceptedResponse
151
- : currentStates[scope].response;
152
- const patch = completePatch(authored, response);
153
- const nextState = applyPatch(currentStates[scope], patch);
154
- compileReadArtifacts(nextState, { artifacts: authored.artifacts ?? {} }, artifactReads.filter((read) => (read.scope ?? "global") === scope), provenanceUpdates[scope]);
155
- compileReadSkills(scope, nextState, { artifacts: authored.artifacts ?? {} }, skillReads.filter((read) => read.scope === scope), provenanceUpdates[scope]);
156
- validateMaterializedTransition(nextState, scope);
140
+ const patch = { ...authored, ...(scope === "session" && acceptedResponse !== undefined ? { response: acceptedResponse } : {}) };
141
+ const materialized = applyPatch({ ...emptyState(), ...currentStates[scope] }, patch);
142
+ compileReadArtifacts(materialized, { artifacts: authored.artifacts ?? {} }, artifactReads.filter((read) => (read.scope ?? "global") === scope), provenanceUpdates[scope]);
143
+ compileReadSkills(scope, materialized, { artifacts: authored.artifacts ?? {} }, skillReads.filter((read) => read.scope === scope), provenanceUpdates[scope]);
144
+ validateMaterializedTransition(materialized, scope);
145
+ const nextState = materialized;
146
+ for (const key of Object.keys(emptyState())) {
147
+ if (!Object.hasOwn(currentStates[scope], key) && !Object.hasOwn(patch, key)
148
+ && !(key === "artifacts" && Object.keys(provenanceUpdates[scope]).length > 0))
149
+ delete nextState[key];
150
+ }
157
151
  nextStates[scope] = nextState;
158
152
  }
159
153
  return {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-state-flow",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "private": false,
5
5
  "description": "Incremental scoped state/context/memory compiler for Pi, inspired by SKILL.state",
6
6
  "keywords": [
@@ -76,7 +76,7 @@
76
76
  "@earendil-works/pi-ai": "0.87.0",
77
77
  "@earendil-works/pi-coding-agent": "0.87.0",
78
78
  "@earendil-works/pi-tui": "0.87.0",
79
- "@types/node": "latest",
80
- "typescript": "latest"
79
+ "@types/node": "^26.4.0",
80
+ "typescript": "^7.0.2"
81
81
  }
82
82
  }
@@ -15,7 +15,7 @@ State Flow's on-demand operational reference. Resolve the usage question or iden
15
15
 
16
16
  Passive tools access memory without starting an episode. Missing tools or storage are blockers, not permission to enable an episode or bypass storage; explanation alone remains possible.
17
17
 
18
- Operator commands: `/state-flow-status` inspects; `/state-flow-start` enables the current branch; `/state-flow-stop` ends active semantics without erasing memory or necessarily disabling passive tools.
18
+ Operator commands: `/state-flow-status` inspects; `/state-flow-active` selects state-driven episodes; `/state-flow-passive` selects ordinary conversation with both memory tools and existing-state projection; `/state-flow-off` removes both tools and all State Flow context, including frozen handoffs, without deleting memory. Commands and Telegram change only the current session's `mode`. Global `mode` defaults to Off for new sessions and never overrides retained choices. Do not change mode without operator authorization.
19
19
 
20
20
  ## Map
21
21
 
@@ -56,7 +56,7 @@ Call `patch_state` alone per assistant response; await acceptance before depende
56
56
 
57
57
  The runtime waits cancelably for publication ownership, then applies authored Global/CWD operations to current canonical values. Untouched fields survive; overlapping targets follow successful acceptance order. Correct repeats succeed as `State already current.` without another semantic revision. Do not repeat external actions during a memory wait, or rebuild an entire scope from an older snapshot. Session ownership/history fences remain private, not a universal merge.
58
58
 
59
- Semantic planes `intents`, `contract`, `working`, `artifacts`, and the required `lazy` root are objects; nested lazy values may contain ordinary JSON without stored nulls. Objects merge, arrays/scalars replace, omitted fields persist. Nested `null` removes an owned object key; inherited content may reappear. Canonical `"[N]"` keys patch array elements; indexed deletion is forbidden.
59
+ When present, semantic planes `intents`, `contract`, `working`, `artifacts`, and `lazy` are objects; nested lazy values may contain ordinary JSON without stored nulls. Stored checkpoints and patches may omit any documented plane. Current and historical views assemble only known fields present in the selected scopes. Absent fields and empty responses are omitted from views. Checkpoint/tail readers ignore unknown top-level fields, and writers emit only known fields. Nested data within known planes remains intact. Explicit value reads of an absent documented top-level field return `null`. Authored `patch_state` keeps its documented field grammar. Objects merge, arrays/scalars replace, omitted fields persist. Nested `null` removes an owned object key; inherited content may reappear. Canonical `"[N]"` keys patch array elements; indexed deletion is forbidden.
60
60
 
61
61
  Illustrative deletion, only for an actually completed intent and after satisfying pending acquisitions:
62
62
 
@@ -1,10 +1,11 @@
1
1
  # State Flow documentation
2
2
 
3
- - [Usage and recovery](usage.md): Configuration, new/resumed sessions, Start/Stop, diagnostics, privacy, and storage recovery.
3
+ - [Usage and recovery](usage.md): Configuration, new/resumed sessions, Active/Passive/Off controls, diagnostics, privacy, and storage recovery.
4
4
  - [Architecture](architecture.md): Semantic state, temporal algebra, Pi lifecycle, storage, publication, artifacts, and embedding contracts.
5
5
  - [Lazy state](lazy-state.md): Implemented ordinary-JSON lazy planes, an effective-by-default `lazy` read path, pure state/patch snapshots, narrow structural `meta` + `keys`, and recursive indexed array patches.
6
6
  - [Filesystem recovery](filesystem-recovery.md): Cohort-wide absence, partial-presence, malformed-evidence, repair-authority, and transaction rules.
7
7
  - [Temporal acceptance](temporal-acceptance.md): Required temporal properties and their executable witnesses.
8
8
  - [SDK compatibility](compatibility.md): Tested dependency stacks, public lifecycle seams, isolated validation, and host limits.
9
9
  - [Physical fork contract](fork-contract.md): Session-stream copying, live shared memory, child ownership/origin, and tested support boundaries.
10
+ - [Agent contract relocation ledger](agent-contract-relocation.md): Source-bound paragraph-to-owner parity map for the compact `AGENTS.md`, with transferred clauses and validation evidence.
10
11
  - [Session performance](performance.md): Reproducible native-Pi/stateful workloads, long-session resume measurements, two-process publication probes, and evidence limits.
@@ -0,0 +1,72 @@
1
+ # Agent contract relocation ledger
2
+
3
+ This is the source-bound **paragraph-to-owner parity map** for the 8,141-word pre-compaction `AGENTS.md` (SHA-256 `0d328eacc96d6b67c5eb036a51adc27e1dcd24d20bb6695f2fff6d5a3c87737b`; source lines 3–58, based on commit `70baecde` plus the Passive-footprint and `barrier-block` edits). Each `L##` identifies exactly one original bullet/paragraph. Its destination is the current owner of that paragraph's reusable contract; where necessary, a compact root rule or executable witness is also named. The root remains approximately 1,300 words; its 0.23.0 default-mode rule supersedes the original Passive-default clause. This is a reviewed documentation trace, not a claim that prose links alone prove runtime correctness.
4
+
5
+ ## Composition, semantics, and model access
6
+
7
+ - L03 domain ownership, entrypoint and mirrored tests → [composition](architecture.md#composition), [invariant tests](../tests/invariants.test.ts).
8
+ - L04 Active opt-in, former Passive default/conditional projection, Off → [configuration](usage.md#configuration), [mode behavior](usage.md#active-passive-and-configured-off).
9
+ - L05 three session-owned mode workflows and global default → [mode behavior](usage.md#active-passive-and-configured-off), [configuration](usage.md#configuration).
10
+ - L06 native trace, frozen head, run anchors and foreign context → [Pi lifecycle](architecture.md#pi-lifecycle), [context limits](performance.md#context-projection-and-trajectory-selection), [lifecycle witnesses](temporal-acceptance.md#required-properties-and-witnesses).
11
+ - L07 sparse planes, projection, lazy filtering and intents → [semantic state](architecture.md#semantic-state), [model tools](architecture.md#model-tools), [lazy state](lazy-state.md).
12
+ - L08 artifact entries and hidden provenance → [artifact routing](architecture.md#artifact-routing).
13
+ - L09 exact registered-path observation → [artifact routing](architecture.md#artifact-routing), [source acquisition](usage.md#memory-and-source-acquisition).
14
+ - L10 compilation classifier, fingerprints and Skill masking → [artifact routing](architecture.md#artifact-routing).
15
+ - L11 stable exact-path acquisition and fork provenance → [artifact routing](architecture.md#artifact-routing), [Git/restore provenance](architecture.md#optional-git-backup), [fork contract](fork-contract.md).
16
+ - L12 global config, legacy modes and limits → [configuration](usage.md#configuration), [mode compatibility](compatibility.md#mode-configuration-compatibility).
17
+ - L13 session runtime/config/checkpoints and continuation authority → [storage and identity](architecture.md#storage-and-identity), [session continuation](architecture.md#session-continuation), [mode restoration](compatibility.md#mode-selection-and-memory-restoration).
18
+ - L14 overlay, scope ownership and Skill routing → [semantic state](architecture.md#semantic-state), [artifact routing](architecture.md#artifact-routing).
19
+ - L17 composed historical offsets → [temporal model](architecture.md#temporal-model).
20
+ - L18 lazy historical reads and tool availability → [model tools](architecture.md#model-tools), [lazy navigation](usage.md#lazy-navigation-and-historical-reading).
21
+ - L27 patch grammar, shared-head staging and private ownership → [model tools](architecture.md#model-tools), [asynchronous transaction](architecture.md#asynchronous-storage-transaction).
22
+ - L28 barrier and minimal acceptance receipts → [Pi lifecycle](architecture.md#pi-lifecycle), [tool preflight evidence](performance.md#tool-preflight-parent-traversal).
23
+ - L29 accepted-response reconciliation and cancellation → [Pi lifecycle](architecture.md#pi-lifecycle), [session behavior](usage.md#session-behavior).
24
+ - L35 omission, empty-scope rejection and response equivalence → [model tools](architecture.md#model-tools), [temporal model](architecture.md#temporal-model).
25
+ - L37 public-boundary draft detachment → [storage and identity](architecture.md#storage-and-identity), [COW evidence](performance.md#memory-only-owned-draft-cow).
26
+ - L38 recursive patch/null and replay → [model tools](architecture.md#model-tools), [semantic state](architecture.md#semantic-state).
27
+ - L39 no project schemas or size/action ledgers → [model tools](architecture.md#model-tools), [operational boundaries](../README.md#operational-boundaries).
28
+ - L49 no strict boundedness claim → [operational boundaries](../README.md#operational-boundaries), [performance limits](performance.md#scope).
29
+ - L51 tool toggle and Passive read/write boundary → [mode behavior](usage.md#active-passive-and-configured-off), [model tools](architecture.md#model-tools).
30
+
31
+ ## Canonical storage, lifecycle, and backup
32
+
33
+ - L15 anchored checkpoints/tails and retention folding → [temporal model](architecture.md#temporal-model), [storage and identity](architecture.md#storage-and-identity).
34
+ - L16 opaque causal identity, origins and shared drift → [temporal model](architecture.md#temporal-model), [Pi lifecycle](architecture.md#pi-lifecycle).
35
+ - L19 canonical layout and identity → [storage and identity](architecture.md#storage-and-identity).
36
+ - L20 optimistic durability, optional backup and contention → [power-loss boundary](filesystem-recovery.md#power-loss-durability), [asynchronous transaction](architecture.md#asynchronous-storage-transaction), [optional Git backup](architecture.md#optional-git-backup).
37
+ - L21 cohort classification and missing shared pairs → [recovery](usage.md#missing-partial-and-malformed-storage), [transaction rule](filesystem-recovery.md#transaction-rule).
38
+ - L22 predecessor formats and no in-place migration → [format boundary](usage.md#moving-a-store-and-the-017-format-boundary), [optional Git backup](architecture.md#optional-git-backup).
39
+ - L23 exact-file CAS, awaited transaction and rollback → [asynchronous transaction](architecture.md#asynchronous-storage-transaction), [storage and identity](architecture.md#storage-and-identity), [transaction rule](filesystem-recovery.md#transaction-rule).
40
+ - L24 initialization and exact-source fork → [Pi lifecycle](architecture.md#pi-lifecycle), [fork contract](fork-contract.md).
41
+ - L25 retained-boundary restore, failed-Stop read-only recovery and selection races → [Pi lifecycle](architecture.md#pi-lifecycle), [mode restoration](compatibility.md#mode-selection-and-memory-restoration).
42
+ - L26 independent revisions, backup capture/index/push/shutdown → [temporal model](architecture.md#temporal-model), [optional Git backup](architecture.md#optional-git-backup).
43
+ - L40 first active context preparation, abort and specification authority → [Pi lifecycle](architecture.md#pi-lifecycle), [pre-inference cancellation](compatibility.md#pre-inference-cancellation).
44
+ - L41 one existing-session bootstrap run → [session behavior](usage.md#session-behavior).
45
+ - L42 selected-branch retained-boundary restoration → [Pi lifecycle](architecture.md#pi-lifecycle), [fork contract](fork-contract.md).
46
+ - L44 Start/current-head acceptance and Active default → [asynchronous transaction](architecture.md#asynchronous-storage-transaction), [mode behavior](usage.md#active-passive-and-configured-off).
47
+ - L45 Passive/Off persistence and frozen Stop handoff → [Pi lifecycle](architecture.md#pi-lifecycle), [mode operations](usage.md#lifecycle-operations), [mode restoration](compatibility.md#mode-selection-and-memory-restoration).
48
+ - L46 failed-Stop marker and fence → [storage recovery](usage.md#storage-and-recovery), [Pi lifecycle](architecture.md#pi-lifecycle).
49
+ - L47 settled native compaction boundary → [session behavior](usage.md#session-behavior), [SDK settlement](compatibility.md#settlement-cancellation), [lifecycle witnesses](temporal-acceptance.md#required-properties-and-witnesses).
50
+
51
+ ## Operator, agent, and development policy
52
+
53
+ - L30 terminal handoff plane routing → [operational guidance](architecture.md#operational-guidance-and-memory-curation), [semantic state](architecture.md#semantic-state).
54
+ - L31 consequential evidence, semantic references and dangling hints → [model tools](architecture.md#model-tools), [lazy navigation](usage.md#lazy-navigation-and-historical-reading), [memory curation](architecture.md#operational-guidance-and-memory-curation).
55
+ - L32 volatile observation and external-effects revalidation → [operational boundaries](../README.md#operational-boundaries), [memory guidance](usage.md#memory-and-source-acquisition).
56
+ - L33 registered Skill acquisition → [artifact routing](architecture.md#artifact-routing).
57
+ - L34 bounded curation and verified transfers → [operational guidance](architecture.md#operational-guidance-and-memory-curation), [memory Skill](../skills/state-flow-memory/SKILL.md).
58
+ - L36 logging categories, privacy and error elision → [diagnostic privacy](usage.md#diagnostic-logging-and-privacy), [barrier contract](architecture.md#pi-lifecycle).
59
+ - L43 terminal status and read-only scope inspection → [status and controls](usage.md#status-and-controls), [observability](architecture.md#observability).
60
+ - L48 system section, context refresh and foreign prompt precedence → [Pi lifecycle](architecture.md#pi-lifecycle), [host context compatibility](compatibility.md#context-tools-and-provider-input).
61
+ - L50 extension-agnostic core and Telegram controls/receipts → [composition](architecture.md#composition), [observability](architecture.md#observability), [Telegram compatibility](compatibility.md#telegram-adapter).
62
+ - L52 tag release authority and version alignment → [release workflow](../.github/workflows/release.yml), [release boundary](../BACKLOG.md#release-boundary). Retain the durable no-token constraint in compact `AGENTS.md` until a permanent developer contract owns it.
63
+ - L53 opt-in benchmark location and source identity → [benchmark guide](../benchmarks/README.md), [performance validation](performance.md#validation-and-reporting).
64
+ - L54 provider callback completion witness → [temporal acceptance](temporal-acceptance.md#required-properties-and-witnesses), [integration tests](../tests/integration.test.ts).
65
+ - L55 awaited fixture handlers and withdrawal witness → [temporal acceptance](temporal-acceptance.md#required-properties-and-witnesses), [extension tests](../tests/extension.test.ts).
66
+ - L56 tracked `dist/` and build/package parity → [release workflow](../.github/workflows/release.yml), [release invariant tests](../tests/invariants.test.ts). Retain the developer rule in compact `AGENTS.md` unless a durable release guide takes ownership.
67
+ - L57 current docs vs delivery history → [documentation index](README.md), compact `AGENTS.md` (durable documentation policy).
68
+ - L58 validation order → compact `AGENTS.md` (durable development rule), [validation procedure](compatibility.md#validation-procedure).
69
+
70
+ ## Verification evidence
71
+
72
+ The map names all 56 source paragraphs exactly once. Each was compared with its destinations; the highest-risk clause groups were checked explicitly: L06/L45 native run anchors and Stop context, L23–L26 CAS/backup/rollback, L28 receipt-elision bounds, L31 reference/epistemic limits, L36 diagnostic privacy, L47 native compaction and L50 callback revocation. An additional exact-code-token audit exposed otherwise easy-to-lose clauses: legacy `{disabled:true}`, in-memory header key derivation, materialization equality, `contract.compiled_skills` rejection, Skill compiler revision, runtime-origin null exception and normalized artifact replay. Those are now stated in architecture; terse `patches[n]` and `{value:null, hint:[...]}` from the source are represented there by the more precise scoped patch path and expanded dangling-reference sentinel. The remaining uniquely durable developer rules, including no live-store fixture edits, stay in the compact root. `tests/invariants.test.ts` is unchanged; native and domain-specific witnesses remain in their named test files. Package, context and domain-DAG validation establish the final checked boundary; they cannot substitute for semantic judgment about future models.
@@ -23,7 +23,7 @@ The extension owns durable memory while enabled. Global semantic memory is alway
23
23
 
24
24
  ## Semantic state
25
25
 
26
- Every materialized scope has exactly this shape:
26
+ Runtime views select these documented semantic planes when present; stored scope objects may omit any of them; unrelated top-level fields are ignored:
27
27
 
28
28
  ```json
29
29
  {
@@ -36,12 +36,12 @@ Every materialized scope has exactly this shape:
36
36
  }
37
37
  ```
38
38
 
39
- - `intents` retains only chosen active commitments.
39
+ - `intents` retains only chosen active commitments, not a planner, scheduler, task manager or execution loop.
40
40
  - `contract` retains durable requirements, decisions, interfaces and rejected approaches.
41
41
  - `working` retains verified current facts, unresolved work and exact continuation.
42
42
  - `artifacts` maps exact source paths to compiled routing metadata.
43
- - `response` is owned only by the session scope and stores the exact latest accepted assistant answer, including the empty string. Global and CWD retain the required key as an empty structural placeholder so canonical scopes keep one shape; the effective overlay receives `response` only from Session.
44
- - `lazy` is a required object root for ordinary JSON detail, omitted from baseline model state and read explicitly. Automatic recent-transition projection also removes each whole `patch.lazy`, including deletions. Empty scoped patches and transitions disappear; an empty projected window is omitted. Visible hot patches retain their original identities, order and positions. Canonical history and explicit current/historical reads are unchanged. Bounded lazy navigation remains available without bodies; previously communicated user/tool/response text is not redacted.
43
+ - `response` is owned only by the session scope and stores the exact latest accepted assistant answer, including the empty string. Global/CWD do not receive newly accepted answers; stored scopes may omit response entirely. An explicit nonempty Session answer overrides inherited values, while an empty or absent response contributes nothing to projection.
44
+ - `lazy` is an optional stored object root for ordinary JSON detail, defaulting to `{}` only in internal compatibility views, omitted from baseline model state and read explicitly. Automatic recent-transition projection also removes each whole `patch.lazy`, including deletions. Empty scoped patches and transitions disappear; an empty projected window is omitted. Visible hot patches retain their original identities, order and positions. Canonical history and explicit current/historical reads are unchanged. Bounded lazy navigation remains available without bodies; previously communicated user/tool/response text is not redacted.
45
45
 
46
46
  Effective state recursively overlays:
47
47
 
@@ -51,11 +51,13 @@ global → CWD → session
51
51
 
52
52
  Later scopes win. A scope-local `null` deletion removes only that scope's key and may reveal an inherited value. Scope represents applicability and ownership, never instruction authority.
53
53
 
54
+ Missing planes are valid sparse semantics, not incomplete storage. Checkpoint/tail codecs select only known top-level fields on read and write; unknown fields are not retained in runtime streams or carried into later writes. Nested data within known planes remains intact. Retained record identities and positions survive even when filtering leaves an empty patch. `readTemporalView` selects present known fields at the requested boundary, then overlays scopes without inventing fields. Empty and absent responses have the same projection meaning; clearing a nonempty response projects as deletion. Explicit reads of absent documented top-level fields return `null`. `readTemporalState` and the embedding callback retain default-bearing compatibility views for internal registry consumers; those defaults never become stored overrides or model context. Passive reads and Start do not fill checkpoint fields or create revisions for normalization; missing shared pairs initialize as empty objects. Authored staging uses raw scope presence and derives runtime-normalized replay from actual accepted writes, including complete artifact replacement; replay must reproduce accepted state exactly. Existing empty/no-op tail records retain their proven boundaries; new no-op writes still create none. Present documented fields retain usable object/string types, valid artifact entries and the no-stored-null rule; ignored fields may contain arbitrary JSON. Malformed JSON and invalid storage/history authority remain errors.
55
+
54
56
  State Flow is the memory owner while enabled. Cross-project/user/environment knowledge belongs in global state, project-only knowledge in CWD, and branch/run continuation in session. Global availability is not a feature switch and does not authorize secrets, raw history, transient progress, speculative clutter, or unsupported assertions. Explicitly uncertain hypotheses remain eligible only when they can affect an open decision.
55
57
 
56
58
  ## Temporal model
57
59
 
58
- All scopes participate in one active causal lineage. One accepted semantic transition receives one opaque identity shared by every changed scope. Sparse transitions do not create records for unchanged scopes.
60
+ All scopes participate in one active causal lineage. One accepted semantic transition receives one opaque identity shared by every changed scope. A branch-local position may order identities but never substitutes for a global counter or merges forks; origin adoption is not an invented semantic transition or retry loop. Sparse transitions do not create records for unchanged scopes.
59
61
 
60
62
  Each scope stores:
61
63
 
@@ -63,24 +65,26 @@ Each scope stores:
63
65
  checkpoint.json + patches.jsonl
64
66
  ```
65
67
 
66
- The checkpoint is an older anchored materialization. The tail contains at most the configured `historyLimit` effective patches. On overflow, the oldest tail patch folds into the checkpoint before the new patch is appended.
68
+ The checkpoint is an older anchored materialization. Current scope state is exactly `materialize(checkpoint.json, patches.jsonl, meta.json)` at the selected anchored boundary; the tail contains at most the configured `historyLimit` effective patches. On overflow, the oldest tail patch folds into the checkpoint before the new patch is appended; unapplied replay records are never truncated or replayed over an already-current snapshot.
67
69
 
68
70
  Persisted streams and lineage are validated against the format maximum before applying a newly configured lower limit. Restore/reload/fork accepts only boundaries inside the configured window, then folds excess scope tails during canonical origin acceptance. That representation-only folding preserves selected private state and current shared values/provenance; a fork never rewrites parent-private files. Zero keeps only current checkpoints, and a later increase does not reconstruct discarded records or lineage.
69
71
 
70
- `effective[n]`, `global[n]`, `cwd[n]`, and `session[n]` resolve the same nth previous causal boundary; the history index remains a composed-lineage offset, not a scope revision. Separately, each materially changed owner advances its persisted semantic revision once. Global and CWD counters remain shared across their canonical writers, Session remains private, and Effective is identified by the current `G#/C#/S#` revision vector. The retired top-level `state` segment is rejected; pre-origin history is unavailable rather than empty.
72
+ `effective[n]`, `global[n]`, `cwd[n]`, and `session[n]` resolve the same nth previous causal boundary; the history index remains a composed-lineage offset, not a scope revision. Separately, each materially changed owner advances its persisted semantic revision once. Global and CWD counters remain shared across their canonical writers, Session remains private, and Effective is identified by the current `g#c#s#` revision vector. The retired top-level `state` segment is rejected; pre-origin history is unavailable rather than empty. Once enough accepted transitions are proven, offsets zero through the configured `historyLimit` remain addressable at their shared causal boundaries.
71
73
 
72
- A changed accepted response is runtime-owned, session-only semantic state and advances history. An accepted empty answer becomes `""` and finalizes normally rather than producing a recovery error. Ordinary completion requires no `patch_state` call when durable semantic state is already correct.
74
+ A changed accepted response is runtime-owned, session-only semantic state and advances history. An accepted empty answer finalizes normally; it clears a previous nonempty response, but does not create a transition merely to replace an absent response with `""`. Ordinary completion requires no `patch_state` call when durable semantic state is already correct.
73
75
 
74
76
  ## Pi lifecycle
75
77
 
76
78
  `patch_state` is the sole mutation tool. It acquires store exclusion before selecting current Global/CWD, stages the authored operations while preserving private Session ownership, and validates/publishes one atomic cohort. Replay, history and revisions use that actual basis; correct repeats create no semantic transition. It then acts as an inference barrier. Pi executes no sibling tools from the same assistant response; the next inference sees the rematerialized current effective state. Its successful native tool result includes a `state_updates` block, separate from the compact acknowledgement used by interactive rendering. `effective` entries contain a `path` array of exact object keys/array indices plus either a replacing `value` or `deleted: true`. These are accepted effective values, not authored merge operations: scope-local deletion can reveal a lower value, and higher scopes can mask an accepted lower-scope write. Entries conservatively cover changed scope fallbacks, masked or overlapping multi-scope touches and projected changes since the last communicated view, including shared refreshes before or during the transaction. Predictable direct non-null leaf writes are omitted when the accepted effective value matches the authored value and no other authored scope touches that path or its ancestors/descendants; disjoint multi-scope writes are independent. Explicit Session scalar/array replacements also omit matching receipts despite lower-scope overlap; ambiguous object merges and deletions remain conservative. Coalesced object additions/replacements can likewise omit an exact authored object, without suppressing foreign sibling fields. Indexed-array patch selectors become numeric update paths only against a communicated in-bounds array basis; object keys with the same spelling are literal. Deletions are omitted only when the accepted effective value equals the previously communicated value and no other authored scope overlaps. An effective-only head cannot prove a hidden lower-scope fallback from its own basis, so changed fallbacks remain visible. Artifact card replacements or merges can be omitted when their projected authored fields applied to an already communicated card exactly match the accepted card after stripping retired provenance; an unchanged previously communicated hint remains part of that known card. New, removed or changed hints and unexpected semantic drift remain visible. Lazy navigation exposes only bounded key/kind summaries, never bodies. An accepted summary needs no receipt when the complete previously communicated catalog and non-deleting top-level writes predict the entire accepted catalog; deletions, overlapping keys, incomplete catalogs and drift remain conservative. Unrelated unchanged branches are omitted. A result with no remaining reconciliation has only the acknowledgement. Arrays with changed length are replaced as a unit, while equal-length changes may target indices. Artifact cards use the normal metadata filter and touched cards replace their whole projected entry. Lazy bodies never enter this block; changed bounded `lazy_navigation` may accompany it. Each update carries a volatile `projection` ID matching the head's `State Flow projection:` text block. The protocol applies only matching updates: retained native results with older IDs remain historical and cannot override a new head. Within that projection, the latest entry supersedes earlier context only at its path. The context domain owns this projection, not storage or the lifecycle composition root.
77
79
 
78
- `ContextProjection` freezes the whole initial head, including its timestamp, specification and recent transitions. Signal-less inspection before active preparation accepts uses a disposable projection, so it cannot freeze a stale specification or pre-maintenance state for the live inference. Active/bootstrap runs rebase on new input and accepted completion; a native continuation after completion gets a fresh head without resurrecting the completed specification. Passive runs keep their head across ordinary user turns. Both modes rebase on Start/Stop, selection/resume/reload, native compaction and a removed/replaced native prefix. No per-patch or size-threshold rebase exists. The volatile ID is not a semantic transition identity and enters neither canonical files nor runtime metadata.
80
+ `ContextProjection` freezes the whole initial head, including its timestamp, specification and recent transitions. Signal-less inspection before active preparation accepts uses a disposable projection, so it cannot freeze a stale specification or pre-maintenance state for the live inference. Active/bootstrap runs rebase on new input and accepted completion; a native continuation after completion gets a fresh head without resurrecting the completed specification. Passive runs keep their head across ordinary user turns. Both modes rebase on mode changes, selection/resume/reload, native compaction and a removed/replaced native prefix. No per-patch or size-threshold rebase exists. The volatile ID is not a semantic transition identity and enters neither canonical files nor runtime metadata.
79
81
 
80
82
  Unreported state changes, changing artifact hints, invalidation lists and rehydration phase append as synthetic tail notices at the native-message boundary where they first appeared. Later inference retains those exact messages at those positions before new native messages, rather than moving them to the latest tail. Empty invalidation lists and a null rehydration envelope explicitly clear earlier notices. Accepted patch receipts advance the communicated view; their state deltas are not redundantly emitted as synthetic notices. Stop handoff uses its captured state as the initial basis, including changes before its first projection. Skill acquisition guidance remains attached to native read results. The cache owns no persistence, publication authority or continuation scheduler, and does not redact native history.
81
83
 
82
84
  Tool preflight follows Pi's public `getLeafEntry()` / `getEntry(parentId)` links to the nearest assistant containing the current call ID. It inspects that response's complete tool batch without constructing the whole branch or caching a batch across calls/selections. Foreign custom entries and earlier sibling results remain in the native trace. A missing call ID still searches the selected ancestry and preserves the existing unmatched-call behavior; this is not an unconditional constant-time guarantee. See [measured traversal evidence](performance.md#tool-preflight-parent-traversal).
83
85
 
86
+ Opt-in local JSONL diagnostic categories are `invalid-patch`, `publication-conflict`, `finalization` and `barrier-block`. Active preflight records each blocked call when a batch has multiple `patch_state` calls or a sibling of its single `patch_state` call. A `barrier-block` record has the blocked tool name, call id, existing block reason and ordered batch tool names only: it does not capture sibling arguments, reasoning or draft content. Logging off creates no barrier record; Passive has no barrier. Diagnostic persistence is outside canonical state and cannot change the blocking decision. Asynchronous Git push failure detail is the separate logging-off exception; see [diagnostic privacy](usage.md#diagnostic-logging-and-privacy).
87
+
84
88
  `read_state` reads one cached effective or scoped projection at current index zero or a retained causal index through the configured `historyLimit`. It never publishes or advances history.
85
89
 
86
90
  Before answering, the model uses `patch_state` only when future-relevant durable state must change. The exact accepted ordinary answer is reconciled directly into runtime-owned `response` at `turn_end`, including `""` when the accepted answer is empty; no terminal eligibility latch, finalization patch, repair inference, or fallback budget exists. If required ordinary-artifact compilation prevents reconciliation, State Flow reports the failure without generating another inference. Optional Skill acquisition never blocks unrelated reconciliation. State Flow does not parse `state_flow` or generic HTML comments; historical comments are ordinary text and other extensions retain their own comment handling.
@@ -92,20 +96,20 @@ The always-injected protocol lists the six planes once, states scope ownership a
92
96
  ```text
93
97
  SEMANTIC STATE intents + contract + working + artifacts + response + lazy
94
98
  MUTATION BARRIER patch_state(scope patches) → rematerialized next inference
95
- CONTEXT PROJECTION active State Flow projection | passive post-stop handoff
99
+ CONTEXT PROJECTION Active state | Passive memory/handoff | Off: no injection
96
100
  ```
97
101
 
98
- Stopping State Flow ends active episode semantics, restores the configured passive tool policy, and switches projection to a frozen effective-state handoff, the active user-run trajectory if interrupted, and post-stop conversation. Paired tool results arriving after Stop remain visible. Foreign context-bearing custom messages survive; outside unfinished bootstrap, a proven active boundary excludes completed earlier ordinary conversation. Stop during bootstrap preserves its incoming context boundary instead of treating uncompiled conversation as completed: an initial bootstrap keeps all available native context, while a restart keeps its earlier passive boundary across repeated toggles. Direct completion persists no private validation feedback. This projection survives same-physical-session reload, resume, and tree restoration. Active restart uses it for one bootstrap run alongside active runtime context. New and forked physical sessions inherit neither projection. No semantic transition is created.
102
+ Selecting Passive after Active ends episode semantics, enables both memory tools, and switches projection to a frozen effective-state handoff, the active user-run trajectory if interrupted, and post-stop conversation. Paired tool results arriving after Stop remain visible. Foreign context-bearing custom messages survive; outside unfinished bootstrap, a proven active boundary excludes completed earlier ordinary conversation. Stop during bootstrap preserves its incoming context boundary instead of treating uncompiled conversation as completed: an initial bootstrap keeps all available native context, while a restart keeps its earlier passive boundary across repeated toggles. Direct completion persists no private validation feedback. This projection survives same-physical-session reload, resume, and tree restoration. Active restart uses it for one bootstrap run alongside active runtime context. New and forked physical sessions inherit neither projection. Off retains the boundary for later Passive/Active use, but injects neither State Flow context nor tools. No semantic transition is created.
99
103
 
100
- A proven pre-runtime branch has no accepted runtime to persist: Stop appends State Flow's existing `{disabled:true}` checkpoint in Pi without creating canonical files. Its cached passive view remains readable under the configured policy, but is not runtime authority. Accepted canonical publication, including a later Start or passive patch, ends this pre-runtime condition; failed selected-boundary recovery never qualifies for it.
104
+ A proven pre-runtime branch has no accepted runtime to persist: an inactive new-session default or explicit choice appends only `{mode:"off"}` or `{mode:"passive"}` in Pi, without creating canonical files. A first explicit choice matching an unretained fallback is recorded; repeating a retained choice is inert. Passive may load existing shared memory read-only, but that cache is not runtime publication authority. Installing its own loaded view preserves the control's successful receipt; replacement/selection/cancellation still revoke it. Accepted canonical publication, including later Active or a passive patch, ends the pre-runtime condition; failed selected-boundary recovery never qualifies for it.
101
105
 
102
106
  Explicit Start independently prepares the validated current same-session canonical cohort rather than replaying the selected Pi pointer. Active/passive or unfinished runtime metadata and expired/pre-runtime selections do not erase current private memory or block activation. `withStartTransaction` acquires exclusion before capture and binds private stream identity to current runtime lineage, with one synchronous, single-use exact-cohort acceptance before installation. Pending repeats share the same operation. Current branch/physical identity, initialization permission and bootstrap context are rechecked after waiting; Stop, selection and shutdown withdraw obsolete activation. Only acceptance enables the new mode, clears Stop fences and cancels older Stop persistence. Caches, preparation policy and one native checkpoint install before yielding without a second persistence call; a later failure cannot roll them back. Commands, deferred settled Start and Telegram await completion, and presentation receipts for both success and failure revoke with selection. It preserves private values, artifact provenance, independent revisions and step, discards the old unfinished specification, and retains available aligned history within the configured limit. Incompatible but independently valid live shared streams require a fresh origin rather than invented cross-writer history. An empty session origin is allowed only with wholly absent private authority and initialization-safe branch provenance; incomplete or contradictory evidence remains closed. Initial physical fork copying still requires its exact-source contract; an already accepted child can activate its own current memory without recopying its parent. Repeated Start while already active does not change the current run or pending response reconciliation.
103
107
 
104
108
  Lifecycle-only persistence for accepted runtimes reconciles valid live global/CWD drift before publishing the current session's config/runtime pair. Changed shared streams establish a fresh proven origin, not a semantic transition; the runtime adopts their already-advanced owner revisions without incrementing them, while semantic files and all provenance files remain unchanged. Cached reads may constrain wider tails left by another writer without rewriting them. Same-session file races and explicitly requested stale provenance writes still fail closed under CAS. The host refreshes its scope cache after adoption: Stop freezes the accepted view, and new-run registered-artifact maintenance runs against that view before inference.
105
109
 
106
- Local Stop disables active projection and response/compaction behavior before attempting canonical persistence. For accepted runtimes it freezes the passive handoff immediately, then awaits `withLifecycleTransaction` with Stop-owned cancellation and any available Pi operation signal. Repeated pending calls share one acceptance. After acquisition, recheck runtime/physical owner/policy and derive the snapshot from current lifecycle state, including an intervening same-instance passive patch. Successful publication installs the adopted shared cache, final handoff and native checkpoint before yielding. Session/tree selection, shutdown or accepted Start revoke obsolete Stop work; a failed Start leaves it pending. Shutdown drains the canceled operation. A post-acceptance lifecycle failure never restores old metadata or retries native writes. If persistence fails, it keeps accepted cached memory and all available native context, then records `owner`, `persistenceError` and `preserveContext: true` in the existing native passive-stop marker. This is a same-session policy override and write fence, not semantic authority or a substitute checkpoint. No canonical failure is repaired by resetting memory. Tree/reload/resume with that pending marker use `TemporalRuntime.refreshCurrentMemory()` to validate and read current memory without historical restoration or publication; unavailable evidence remains unavailable. A later accepted checkpoint supersedes the fence, while preserving the context boundary for bootstrap. Repeated degraded Stop is inert. Successful explicit Start uses the same detached validation path under CAS before clearing the fence. Status and inspection distinguish accepted cached/read-only memory from unavailable publication. If Pi's own trace is unwritable, the local disablement still precedes the error, but durable fallback cannot be guaranteed.
110
+ Passive/Off selection immediately applies the selected tools/context policy and disables active response/compaction behavior before attempting canonical persistence. For accepted runtimes it freezes the passive handoff immediately, then awaits `withLifecycleTransaction` with Stop-owned cancellation and any available Pi operation signal. Pending inactive choices share one acceptance of the latest mode. After acquisition, recheck runtime/physical owner/policy and derive the snapshot from current lifecycle state, including an intervening same-instance passive patch. Successful publication installs the adopted shared cache, final handoff and native checkpoint before yielding. Session/tree selection, shutdown or accepted Start revoke obsolete Stop work; a failed Start leaves it pending. Shutdown drains the canceled operation. A post-acceptance lifecycle failure never restores old metadata or retries native writes. If persistence fails, it keeps accepted cached memory and all available native context, then records `owner`, the selected inactive `mode`, `persistenceError` and `preserveContext: true` in the existing native passive-stop marker. This is a same-session policy override and write fence, not semantic authority or a substitute checkpoint. No canonical failure is repaired by resetting memory. Tree/reload/resume with that pending marker use `TemporalRuntime.refreshCurrentMemory()` to validate and read current memory without historical restoration or publication; unavailable evidence remains unavailable. A later accepted checkpoint supersedes the fence, while preserving the context boundary for bootstrap. Repeating the same degraded choice is inert; another inactive choice updates only native policy and preserves the fence. An in-flight read-only recovery applies the latest choice, never an older captured mode. Successful explicit Start uses the same detached validation path under CAS before clearing the fence. Status and inspection distinguish accepted cached/read-only memory from unavailable publication. If Pi's own trace is unwritable, the local disablement still precedes the error, but durable fallback cannot be guaranteed.
107
111
 
108
- The existing native passive-stop marker stores the stop timestamp and an optional `from` timestamp identifying the active run's first user message. Native user events are observed independently of State Flow enablement, so starting mid-tool and repeated Start/Stop retain the actual first-user timestamp. Native user-run preparation and session-start/tree events reset capture; semantic mode changes do not. The same marker accepts optional `preserveContext: true` when compilation is unfinished and no narrower incoming boundary is sufficient; omitted flags keep legacy selection behavior. This projection flag creates no semantic storage authority. Transcript bodies remain in Pi's trace rather than being copied into another state store. A recorded active anchor uses the same conservative selector as active inference: if native compaction removed it, or matching is ambiguous/nonfinite, retain the available native summary and tool trajectory without guessing a post-stop boundary or rereading discarded raw entries. An interrupted run keeps its captured anchor even after Pi becomes idle; if capture is unavailable, Stop preserves all available context. Completed idle runs and legacy markers without an active anchor or preservation flag retain only post-stop conversation plus foreign custom context. The initial system prompt is composed at `before_agent_start`; Stop does not rewrite an already-issued request, while the next provider request receives the current owned protocol section as described below.
112
+ The existing native passive-stop marker stores the stop timestamp and an optional `from` timestamp identifying the active run's first user message. Native user events are observed independently of State Flow enablement, so activating mid-tool and repeated mode changes retain the actual first-user timestamp. Native user-run preparation and session-start/tree events reset capture; semantic mode changes do not. The same marker accepts optional `preserveContext: true` when compilation is unfinished and no narrower incoming boundary is sufficient; omitted flags keep legacy selection behavior. This projection flag creates no semantic storage authority. Transcript bodies remain in Pi's trace rather than being copied into another state store. A recorded active anchor uses the same conservative selector as active inference: if native compaction removed it, or matching is ambiguous/nonfinite, retain the available native summary and tool trajectory without guessing a post-stop boundary or rereading discarded raw entries. An interrupted run keeps its captured anchor even after Pi becomes idle; if capture is unavailable, Stop preserves all available context. Completed idle runs and legacy markers without an active anchor or preservation flag retain only post-stop conversation plus foreign custom context. The initial system prompt is composed at `before_agent_start`; Stop does not rewrite an already-issued request, while the next provider request receives the current owned protocol section as described below.
109
113
 
110
114
  The current user specification stays at user authority and appears only in synthetic user runtime context. State is fallible assistant-produced data. Active/passive protocol contributes to Pi's native `state_flow` system-prompt section at `before_agent_start`, rather than forcing the entire prompt. Later companion sections and `context_with_system` transformations compose normally; explicit foreign forced prompts retain Pi's documented precedence. Native section diffs remove/reinstate the initial protocol across user requests. At `context_with_system`, the context domain also refreshes only the owned section from current enablement/bootstrap/passive policy, covering Stop/Start inside the same tool loop and accepted-boundary continuations. Unchanged effective protocol reuses the original array without relocating native deltas; a changed mode preserves foreign sections/content/tools and conversation identity/order without mutating native frames or creating missing system authority. Accepted completion removes the specification, not memory availability: a companion's actionable `turn_end` or `agent_before_settle` continuation can request another inference without `before_agent_start`. Every enabled request still gets one current-memory projection, omitting an absent specification and using the captured native anchor when available; no synthetic user run, persisted continuation field or State Flow scheduler is created. Completed trajectories leave model context at user-run boundaries, while Pi's full JSONL trace remains inspectable.
111
115
 
@@ -136,13 +140,13 @@ meta.json
136
140
  <cwd-key>/<session-key>/runtime.json
137
141
  ```
138
142
 
139
- CWD and session keys mirror Pi's native encoding. The Pi UUID remains authoritative; readable directory keys never replace identity validation.
143
+ CWD and session keys mirror Pi's native encoding, deriving the in-memory session key from `<header timestamp>_<UUID>` when no JSONL basename exists. The Pi UUID remains authoritative; readable directory keys never replace identity validation. Reject unsafe segments, mismatches and CWD-key ownership collisions rather than selecting a different scope.
140
144
 
141
- Root `config.json` is the read-only operator configuration shared by every session in the repository; it never participates in semantic overlay or State Flow-owned staging. Include operator configuration in operator-managed copies/versioning. `checkpoint.json` is only the canonical materialized semantic state, and each nonblank `patches.jsonl` line is only one semantic patch. Every scope's `meta.json` symmetrically owns its independent semantic revision, checkpoint/tail boundaries and artifact provenance, with CWD ownership added where applicable. Session `config.json` owns behavior; session `runtime.json` asymmetrically owns lineage, the internal branch step, session identity, and the full specification only while a run is unfinished. Predecessor combined session metadata is unsupported; session `meta.json`, `config.json`, and `runtime.json` must already satisfy their canonical ownership contracts. Metadata writers replace only their owned leaves and preserve JSON-safe unknown siblings. A pre-revision 0.17 scope initializes its counter from the still-retained semantic tail and persists that baseline on its next owned write; folded ancestry is not guessed. Revision-aware writes emit scope metadata version 2 while continuing to read version 1. The version fence makes an older writer refuse a scope after its first revision-aware write instead of silently dropping the counter; all cooperating instances should still upgrade together. Pi checkpoints retain only a semantic boundary plus lifecycle fields, or a proven ordinary-disabled marker. Revision-pointer checkpoints are unsupported and fail closed without Git restoration.
145
+ Root `config.json` is read-only operator configuration whose `mode` supplies the new-session default (Off when absent and no legacy mode flags are present); it never participates in semantic overlay or State Flow-owned staging. Include operator configuration in operator-managed copies/versioning. `checkpoint.json` is only the canonical materialized semantic state, and each nonblank `patches.jsonl` line is only one semantic patch. Every scope's `meta.json` symmetrically owns its independent semantic revision, checkpoint/tail boundaries and artifact provenance, with CWD ownership added where applicable. Session `config.json` serializes only its concrete `mode` (`active`, `passive`, `off`), independently of later global defaults; session `runtime.json` asymmetrically owns lineage, the internal branch step, session identity, and the full specification only while a run is unfinished. Runtime metadata stores no storage receipt, Git identity, temporal revision pointer, publication mode or push intent. Predecessor combined session metadata is unsupported; session `meta.json`, `config.json`, and `runtime.json` must already satisfy their canonical ownership contracts. Metadata writers replace only their owned leaves and preserve JSON-safe unknown siblings. A pre-revision 0.17 scope initializes its counter from the still-retained semantic tail and persists that baseline on its next owned write; folded ancestry is not guessed. Revision-aware writes emit scope metadata version 2 while continuing to read version 1. The version fence makes an older writer refuse a scope after its first revision-aware write instead of silently dropping the counter; all cooperating instances should still upgrade together. Pi checkpoints retain only a semantic boundary plus lifecycle fields, or a proven inactive pre-runtime `{mode}` marker. Supported legacy flags and native `{disabled:true}` markers decode read-only; mixed session `mode`/`enabled` representations are rejected, and no eager migration runs. Revision-pointer checkpoints are unsupported and fail closed without Git restoration.
142
146
 
143
147
  In-memory patching detaches one basis at its public boundary, then privately path-copies changed object/array containers while sharing untouched nodes only inside that owned draft. Incoming replacement values remain detached; staging no longer makes redundant cohort/per-scope pre-clones. Mutable staged responses and artifact registries stay isolated from accepted scopes, and commit/public temporal reads retain their detachment boundaries. This is not cross-version mutable sharing or a new disk generation format; see [copy-work evidence](performance.md#memory-only-owned-draft-cow).
144
148
 
145
- All owned writes use same-directory atomic replacement, regular-file and symlink checks, prepared byte receipts and CAS validation. Unrelated files and detected concurrent bytes are preserved. Rollback restores only bytes still matching the failed publisher's output.
149
+ All owned writes use same-directory atomic replacement, regular-file and symlink checks, prepared opaque source-byte receipts and CAS validation. Unrelated files and detected concurrent bytes are preserved. Rollback restores only bytes still matching the failed publisher's output. Use validated structural JSON equality for in-process semantic comparisons; cryptographic hashes are for compact identities crossing process or persistence boundaries.
146
150
 
147
151
  ### Asynchronous storage transaction
148
152
 
@@ -150,7 +154,7 @@ All owned writes use same-directory atomic replacement, regular-file and symlink
150
154
 
151
155
  By default, a live PID waits asynchronously until release or cancellation; there is no ordinary-contention deadline or automatic lock theft. Only the empty creation-to-PID window has a bounded two-second grace period. Malformed, non-regular, unreadable or interrupted ownership fails without repair. Recursive acquisition of an actively owned root is an error, not implicit reentrancy; inherited async context from a completed callback does not confer ownership or block a new transaction. Cancellation before acquisition or before publication leaves canonical bytes unchanged. Once a synchronous publication has accepted its cohort, later cancellation does not undo it. Cleanup checks lock identity/contents and preserves detected replacement ownership, retaining both action and release errors when necessary. No process/power-loss crash atomicity or kernel-atomic exclusion against nonparticipating writers is implied. The writer has no file/directory flush barrier. Optimistic persistence across abrupt shutdown is an [accepted limitation](filesystem-recovery.md#power-loss-durability), not a release gate; no crash-recovery journal or additional storage namespace is planned. Short capture/stage/publication exclusion remains necessary to preserve independent fields between cooperating writers; stale whole-state last-writer-wins replacement would lose unrelated work.
152
156
 
153
- `TemporalRuntime.withPatchTransaction` routes `patch_state` through this capability. Its synchronous callback receives detached current states, their causal basis and provenance, plus one single-use `publish` operation; it cannot access selection or raw storage methods. Shared drift is adopted before staging, not used to reject a stale agent. The exact accepted private cohort remains fenced against another physical writer or unselected history. A new owner prepares an empty private origin without writing it separately; validation failure leaves canonical files and accepted caches untouched. Compiled cards and evidence publish together, and an absent semantic pair cannot confer orphaned compilation evidence on a new registration. Host caches and the accepted native checkpoint update after publication, before yielding.
157
+ `TemporalRuntime.withPatchTransaction` routes `patch_state` through this capability. Its synchronous callback receives detached exact sparse scope semantics (without read defaults), their causal basis and provenance, plus one single-use `publish` operation; it cannot access selection or raw storage methods. Shared drift is adopted before staging, not used to reject a stale agent. The exact accepted private cohort remains fenced against another physical writer or unselected history. A new owner prepares an empty private origin without writing it separately; validation failure leaves canonical files and accepted caches untouched. Compiled cards and evidence publish together, and an absent semantic pair cannot confer orphaned compilation evidence on a new registration. Host caches and the accepted native checkpoint update after publication, before yielding.
154
158
 
155
159
  `TemporalRuntime.withLifecycleTransaction(action, signal?)` is the runtime-only counterpart. It requires already accepted private authority both before and after waiting; passive reads and unaccepted restore candidates cannot initialize or authorize it. Under one exclusion it captures current shared state and calls `action(publish)`, where the caller must recheck selection/policy and derive its current lifecycle snapshot before invoking `publish(snapshot)` synchronously once. Only that session's config/runtime may change: semantic files, scope provenance, scope revision counters and even wider foreign retained tails stay untouched. No-op acceptance returns `changed: false` after validating the captured cohort. Failed/canceled publication installs no candidate; cancellation after acceptance cannot undo it. The transaction APIs share the candidate/acceptance owner, without nested lock acquisition or a second persistence call. The patch transaction's existing `publish` also uses runtime-only acceptance when there is no transition/provenance update and its accepted file cohort is complete. New private authority or wholly absent shared pairs instead require ordinary atomic initialization from the staged current values. Partial/malformed evidence remains rejected. No extra publisher capability or caller-selected storage mode is needed.
156
160
 
@@ -172,7 +176,7 @@ Accepted-answer reconciliation also uses `withPatchTransaction`: `turn_end` awai
172
176
 
173
177
  `TemporalRuntime.refreshCurrentMemory(signal?)` supplies an awaited read-only recovery view of current same-session authority. It shares current-memory validation with Start, but neither publishes nor accepts write authority: returned policy is disabled and unfinished specifications are omitted. Current private values, step, revisions, bootstrap and provenance remain available beside independently validated shared streams; retention is constrained only in memory. Absence returns `undefined` without creation, and malformed evidence or cancellation (including during capture) leaves the prior cache unchanged. Lifecycle/patch publication still requires accepted authority or explicit Start. Native failed-Stop reload uses it and keeps the write fence.
174
178
 
175
- Native `session_start` and `session_tree` await one extension-owned branch restoration. Its synchronous prelude revokes older selection work, pins session id, file, header timestamp and CWD, and selects active-branch evidence through the recovery domain's pure `selectRetainedCheckpoint`: newer malformed envelopes are skipped, while revision pointers and every failure resolving the selected boundary fail closed. While it waits, mode is passive and private reads/publication report the pending selection. The selected boundary, exact-source fork, truly new auto-start origin (`withStartTransaction` with creation authority, rechecking branch evidence after waiting) or failed-Stop read-only recovery then use the awaited runtime API. Bootstrap/policy derive after waiting and publish in that single acceptance; only the current lifetime installs memory, checkpoint, continuation, tools and UI before yielding, and later native-write failure only warns. New selection revokes older work; shutdown drains current and superseded restoration operations. Stop selects passive policy without cancelling retained restoration, new-session initialization or fork copying, including attachment originally requested by a now-cancelled Start waiter. The pending publisher applies that policy inside its single acceptance; configured passive tools can then patch memory without an artificial error fence. Repeated Stop is inert with respect to that acceptance. Start after Stop joins the independent memory operation before activating current memory. Selection changes, shutdown and native operation cancellation still revoke obsolete work; real validation/publication failures remain unavailable rather than becoming empty memory. Start joins pending restoration, owns initial attachment and fork retry without cancelling itself, and is inert when the result is active. A cancelled Start withdraws its join without cancelling independently owned restoration or Stop persistence. Read-only recovery uses detached candidates and rechecks cancellation/physical identity before host installation; passive attachment cannot overwrite a newer cache established by an intervening patch or inspection. Six synchronous runtime methods remain supported for library consumers and local tests/benchmarks; production lifecycle wiring uses the awaited APIs. Their contracts and cancellation boundaries are documented in [library API compatibility](compatibility.md#state-flow-library-api-compatibility).
179
+ Native `session_start` and `session_tree` await one extension-owned branch restoration. Its synchronous prelude revokes older selection work, pins session id, file, header timestamp and CWD, and selects active-branch evidence through the recovery domain's pure `selectRetainedCheckpoint`: newer malformed envelopes are skipped, while revision pointers and every failure resolving the selected boundary fail closed. While it waits, mode is the selected inactive policy and private reads/publication report the pending selection. The selected boundary, exact-source fork, truly new auto-start origin (`withStartTransaction` with creation authority, rechecking branch evidence after waiting) or failed-Stop read-only recovery then use the awaited runtime API. Bootstrap/policy derive after waiting and publish in that single acceptance; only the current lifetime installs memory, checkpoint, continuation, tools and UI before yielding, and later native-write failure only warns. New selection revokes older work; shutdown drains current and superseded restoration operations. Passive/Off selection never cancels retained restoration, new-session initialization or fork copying, including attachment requested by a now-cancelled Active waiter. The pending publisher applies the latest inactive policy inside its single acceptance; Passive can then patch memory without an artificial error fence, while Off exposes no model access. Repeated selections are inert with respect to that acceptance. Start after Stop joins the independent memory operation before activating current memory. Selection changes, shutdown and native operation cancellation still revoke obsolete work; real validation/publication failures remain unavailable rather than becoming empty memory. Start joins pending restoration, owns initial attachment and fork retry without cancelling itself, and is inert when the result is active. A cancelled Start withdraws its join without cancelling independently owned restoration or Stop persistence. Read-only recovery uses detached candidates and rechecks cancellation/physical identity before host installation; passive attachment cannot overwrite a newer cache established by an intervening patch or inspection. Six synchronous runtime methods remain supported for library consumers and local tests/benchmarks; production lifecycle wiring uses the awaited APIs. Their contracts and cancellation boundaries are documented in [library API compatibility](compatibility.md#state-flow-library-api-compatibility).
176
180
 
177
181
  The advisory [continuation-candidate reader](#session-continuation) also awaits coherent capture. Current-head activation on an attached branch uses the awaited Start transaction. Raw precomputed replay keeps its selected-target guard, unlike current-head authored patch staging. Model inference, source acquisition and Git commands do not belong inside a canonical critical section; artifact freshness validation remains part of publication validation.
178
182
 
@@ -180,7 +184,7 @@ The advisory [continuation-candidate reader](#session-continuation) also awaits
180
184
 
181
185
  Canonical files always own semantic persistence, current materialization, and retained hot history. Installing Git beside the store does not change authority or enable cold semantic restoration. Retained-boundary restoration selects private session history from the current canonical lineage while global/CWD scopes remain live; expired boundaries fail closed.
182
186
 
183
- Scope artifact provenance records only current evidence. Restore/fork drops session provenance for paths touched by any retained session patch after the selected boundary, including a change-away-and-back; path existence or equal final values cannot substitute for that causal check. Selected artifact semantics remain intact with unavailable evidence until a stable explicit read and compilation. Untouched paths, provenance-only refreshes of unchanged semantics, and live shared provenance remain usable.
187
+ Scope artifact provenance records only current evidence. Restore/fork drops session provenance for paths touched by any retained session patch after the selected boundary, including a change-away-and-back or whole-artifacts-plane deletion; path existence or equal final values cannot substitute for that causal check. Selected artifact semantics remain intact with unavailable evidence until a stable explicit read and compilation. Untouched paths, provenance-only refreshes of unchanged semantics, and live shared provenance remain usable.
184
188
 
185
189
  After response reconciliation and Pi's retry/queue processing, `agent_before_settle` may commit the already-accepted State Flow-owned files once. `backupCurrentStateFlowFiles(root, signal?, waitForLock = true)` now returns `Promise<string | undefined>` and must be awaited. It awaits its own Git mutex and canonical exclusion to inventory the bounded root/CWD/session namespace and capture regular-file bytes, then releases canonical exclusion before every Git command or filter. `withFilePublicationLock` owns the shared acquisition/release mechanics: both mutexes retain exact ownership across awaits, refuse recursion and preserve replacement owners or combined action/cleanup failures. The backup mutex spans capture and Git completion; the branch/head is rechecked after waiting. It never descends into artifact sources, `.git`, or unrelated directory trees. A private temporary worktree/index stages the captured snapshot with Git ignore/filter policy preserved; concurrent writers may advance canonical files without changing that snapshot.
186
190
 
@@ -192,13 +196,13 @@ After a successful backup attempt, State Flow resolves only the attached branch'
192
196
 
193
197
  Durable push queues, publication workers, leases, retry generations, queue filesystem state, and publication-policy metadata remain absent. Git revision restore, immutable-revision fork APIs, and the legacy semantic Git backend have been removed from `TemporalRuntime`; all initialization, passive loading, model patches, runtime-only persistence, retained-boundary restoration, and retained-boundary forks use canonical files only.
194
198
 
195
- Predecessor checkpoint envelopes, combined session metadata, pre-intents checkpoints, `state.json`, hashed layouts, and semantic Pi checkpoints are unsupported and remain untouched.
199
+ Predecessor checkpoint envelopes, combined session metadata, `state.json`, hashed layouts, and semantic Pi checkpoints are unsupported and remain untouched. Missing documented planes, including `intents` and `lazy`, in canonical semantic objects are supported without migration.
196
200
 
197
201
  ## Artifact routing
198
202
 
199
203
  State Flow never discovers source directories. Before enabled inference it inspects only exact source paths already registered as artifacts in global, CWD, or session state. Observation uses regular non-symlink file metadata `{size, mtimeNs}` without reading bodies. Proven absence removes the artifact from each owning scope; unavailable, relative, directory, or symlink evidence is non-destructive. Unregistered files are never observed.
200
204
 
201
- A model-visible artifact entry requires only a description:
205
+ A model-visible artifact entry requires only a non-empty description:
202
206
 
203
207
  ```json
204
208
  {
@@ -207,21 +211,21 @@ A model-visible artifact entry requires only a description:
207
211
  }
208
212
  ```
209
213
 
210
- Runtime-owned compilation evidence is retained per scope in `meta.json`; current ordinary artifacts use `sourceFingerprint: {size, mtimeNs}` plus `compilerRevision`, while retained `sourceHash`/`compiledAt` are transitional compatibility evidence. At artifact-entry level, every model scope patch rejects authored `hash`, `compiler`, `compiled_at`, `sourceHash`, `sourceFingerprint`, `compilerRevision`, `compiledAt`, `source_hash_verified`, and `hint` fields, including field-deletion markers, even without a preceding read. Retained legacy evidence stays readable; ordinary semantic edits and whole-artifact deletion remain valid. Compiler output may add other finite non-null JSON metadata; known optional semantic fields include `kind`, `tags` and `compilation`. Tags are unique trimmed non-empty strings and support deterministic candidate filtering, but never authorize reading.
214
+ Runtime-owned compilation evidence is retained per scope in `meta.json`; current ordinary artifacts use `sourceFingerprint: {size, mtimeNs}` plus `compilerRevision`, while retained `sourceHash`/`compiledAt` are transitional compatibility evidence. At artifact-entry level, every model scope patch rejects authored `hash`, `compiler`, `compiled_at`, `sourceHash`, `sourceFingerprint`, `compilerRevision`, `compiledAt`, `source_hash_verified`, and `hint` fields, including field-deletion markers, even without a preceding read. Retained legacy evidence stays readable but its embedded `hash`/`compiler`/`compiled_at` fields are omitted from model projection; ordinary semantic edits and whole-artifact deletion remain valid. Compiler output may add other finite non-null JSON metadata; known optional semantic fields include `kind`, `tags` and `compilation`. Tags are unique trimmed non-empty strings and support deterministic candidate filtering, but never authorize reading.
211
215
 
212
- The public `classifyArtifactCompilationNeed` owns acquisition/rehydration and ordinary-artifact Pi decisions. An observed fingerprint needs matching valid retained fingerprint evidence; missing/malformed fingerprints, malformed compiler evidence, or a changed compiler request compilation without removing semantics. Changed size or signed nanosecond mtime (including pre-epoch dates) preserves the value and adds a runtime-only model `hint`. Fingerprint-only decisions ignore unused legacy hashes; explicit current-hash observations and the separate Skill hash protocol remain checked. Rehydration read plans carry detached fingerprints and optional hashes, never invented identities.
216
+ The retired `contract.compiled_skills` location is rejected; Skill compilations belong only in source-addressed artifacts, with no fabricated source hashes. The public `classifyArtifactCompilationNeed` owns acquisition/rehydration and ordinary-artifact Pi decisions. An observed fingerprint needs matching valid retained fingerprint evidence; missing/malformed fingerprints, malformed compiler evidence, or a changed compiler request compilation without removing semantics. Changed size or signed nanosecond mtime (including pre-epoch dates) preserves the value and adds a runtime-only model `hint`. Fingerprint-only decisions ignore unused legacy hashes; explicit current-hash observations and the separate Skill hash protocol remain checked. Rehydration read plans carry detached fingerprints and optional hashes, never invented identities.
213
217
 
214
218
  Invalidation notices identify the selected `global`, `cwd`, or `session` owner. Guidance and missing-output errors direct compilation to that exact scope/path, without relocating the entry or creating a global copy. Successful exact reads require stable fingerprints before/after acquisition and at publication, then publish compiler output and provenance to that owner under scope causal-basis CAS. Generic maintenance computes no content hash. Effective Skill entries mask lower ordinary entries and retain their separate hash protocol.
215
219
 
216
220
  Compilation is routing, not a substitute for source text. Full source is read only for a concrete unresolved gap, exact source/edit operation, fingerprint invalidation, contradiction/failure, or explicit request. The rehydration planner supports new-bootstrap, resume-bootstrap and later-step phases without hidden directory traversal.
217
221
 
218
- Skill acquisition applies only to exact registered Pi Skills. State Flow resolves identity and ownership through the public slash-command inventory rather than file-path conventions: Pi `user`, `project` and `temporary` source scopes map to State Flow `global`, `cwd` and `session`. A successful read with matching current source hash needs no new compilation. Otherwise the tool result names the exact optional target. Attempted durable output requires `kind: "skill"` and a non-empty compilation describing applicability, constraints and failure conditions; an omitted output leaves the read volatile and does not block unrelated patches or ordinary completion. Source bodies do not persist in state. Matching provenance proves source-version consistency, not semantic fidelity, truth, or higher instruction authority.
222
+ Skill acquisition applies only to exact registered Pi Skills. State Flow resolves identity and ownership through the public `getCommands()` inventory's `sourceInfo.scope`, rather than file-path conventions: Pi `user`, `project` and `temporary` source scopes map to State Flow `global`, `cwd` and `session`. A successful read with matching current source hash needs no new compilation. Otherwise the tool result names the exact optional target. Attempted durable output at the reported scope and path requires a non-empty description, `kind: "skill"` and a non-empty compilation describing applicability, constraints and failure conditions; an omitted output leaves the read volatile and does not block unrelated patches or ordinary completion. The accepted compilation replaces the complete prior Skill card and provenance, storing runtime-owned `sourceHash` and `skill-artifact-v1` `compilerRevision`; obsolete evidence cannot survive refresh. Source bodies do not persist in state. Matching provenance proves source-version consistency, not semantic fidelity, truth, or higher instruction authority.
219
223
 
220
224
  ## Operational guidance and memory curation
221
225
 
222
226
  The packaged Skills deliberately separate two responsibilities. `state-flow-guide` is the on-demand operational reference for concrete read, patch, inheritance, acquisition, completion, and recovery questions; it does not initiate memory audits or unsolicited cleanup. `state-flow-memory` performs one explicitly requested bounded curation over stale knowledge, commitments, continuation, ownership, and external handoffs; phase completion does not activate an audit.
223
227
 
224
- Curation may persist reusable guidance from a registered Skill at its provenance-derived scope. Within one store, a proven scope move inspects both owners, resolves conflicts, and commits destination/source changes through one atomic multi-scope patch, followed by ownership/overlay verification. Existing Skill artifacts written under the former CWD-only policy are not silently promoted: a later registered read identifies the current owner, while explicit curation may move proven reusable content and remove the old owner atomically.
228
+ Curation may persist reusable guidance from a registered Skill at its provenance-derived scope. Treat terminal state as a decision-relevant handoff rather than a progress transcript: retain operational knowledge in source-addressed artifacts, confirmed constraints/decisions and rejected approaches in contract, observations/failures/uncertainties and exact continuation in working, and only chosen active commitments in intents. Distinguish user requirements from assistant conclusions and hypotheses; preserve consequential negative evidence and reconsideration conditions. Do not silently overwrite established constraints when evidence conflicts, treat working observations as live external facts, or infer success/absence of external effects from restored memory. After interruption, inspect the relevant effects before repetition. These are model stewardship duties, not deterministic semantic gates. Within one store, a proven scope move inspects both owners, resolves conflicts, and commits destination/source changes through one atomic multi-scope patch, followed by ownership/overlay verification. Existing Skill artifacts written under the former CWD-only policy are not silently promoted: a later registered read identifies the current owner, while explicit curation may move proven reusable content and remove the old owner atomically.
225
229
 
226
230
  External transfers use the destination's native interface and receipts; accepted-copy verification precedes source deletion in a later State Flow patch. State Flow defines no promotion registry, status schema, record type, or dedicated promotion tool; destination uncertainty simply leaves the source intact.
227
231
 
@@ -248,7 +252,7 @@ The [tested Pi SDK baseline](compatibility.md) chooses or creates `SessionManage
248
252
 
249
253
  ### Model tools
250
254
 
251
- `patch_state` accepts one or more fixed `global`, `cwd`, and `session` semantic patches. Supplied scopes contain object-valued `artifacts`, `contract`, `working`, and `intents`, plus object-valued `lazy` whose nested values are ordinary JSON; omitted fields preserve their values, recursive object merge updates them, arrays/primitives replace, and nested object-key `null` deletes. Materialized null, empty supplied scopes, unknown top-level fields, model-authored `response`, and retired finalization or patch grammars are rejected. Correct repeated results succeed as `State already current.` without another semantic revision or history record; avoid gratuitous acknowledgment patches. Global/CWD overlap follows successful acceptance order, while unmentioned current fields survive. Session ownership is not a shared-memory merge.
255
+ `patch_state` accepts one or more fixed `global`, `cwd`, and `session` semantic patches. Supplied scopes contain object-valued `artifacts`, `contract`, `working`, and `intents`, plus object-valued `lazy` whose nested values are ordinary JSON; omitted fields preserve their values, recursive object merge updates them, arrays/primitives replace, and nested object-key `null` deletes. Materialized null within documented semantic planes, empty supplied scopes, unknown top-level fields, model-authored `response`, and retired finalization or `{scope, patch}` / `unchanged` grammars are rejected. The semantic null rule does not apply to runtime envelopes such as an origin's null parent. Correct repeated results succeed as `State already current.` without another semantic revision or history record; avoid gratuitous acknowledgment patches. Global/CWD overlap follows successful acceptance order, while unmentioned current fields survive. Session ownership is not a shared-memory merge.
252
256
 
253
257
  ```json
254
258
  {"session":{"intents":{"next":"Verify the corrected behavior"}}}
@@ -268,11 +272,11 @@ The [tested Pi SDK baseline](compatibility.md) chooses or creates `SessionManage
268
272
 
269
273
  Unscoped semantic paths such as `intents.next` alias the current effective overlay. `value`, `keys`, and `patch` projections plus ordered `paths` batches remain all-or-error.
270
274
 
271
- Both tools follow branch enablement and host restrictions. The patch barrier also blocks reader siblings. These tools do not impose project schemas or state-size caps; semantic usefulness, scope choice, and compression remain model responsibilities. Ordinary handoffs reconcile touched state. Dedicated cleanup and scope review require an explicit user request, including at feature/release/project boundaries. Global retains established cross-project/user/environment knowledge, CWD owns reusable project truth, and session owns branch/run continuation. Intra-store moves use targeted owner reads and one atomic multi-scope patch followed by verification; external moves require verified destination acceptance before source deletion.
275
+ Both tools are exposed in Active/Passive and withdrawn in Off, subject to host restrictions; mode toggles preserve unrelated active tools. Passive reads never initialize storage, but an explicit passive patch may initialize absent canonical storage without starting an episode. The patch barrier also blocks reader siblings. These tools do not impose project schemas or state-size caps; semantic usefulness, scope choice, and compression remain model responsibilities. Ordinary handoffs reconcile touched state. Dedicated cleanup and scope review require an explicit user request, including at feature/release/project boundaries. Global retains established cross-project/user/environment knowledge, CWD owns reusable project truth, and session owns branch/run continuation. Intra-store moves use targeted owner reads and one atomic multi-scope patch followed by verification; external moves require verified destination acceptance before source deletion.
272
276
 
273
277
  ### Embedding
274
278
 
275
- The default extension factory accepts `StateFlowExtensionOptions`: `agentDir` selects the profile and `repositoryRoot` overrides the configured state store. `onRuntime` receives a cached `read(offset?, scope?)` accessor; omitted scope means effective state. Use it only after runtime initialization/restoration. The pure `readTemporalState(view, offset, scope?)` accessor is exported separately. SDK hosts with an explicit tool allowlist must include both `patch_state` and `read_state` when they want model access.
279
+ The default extension factory accepts `StateFlowExtensionOptions`: `agentDir` selects the profile, `repositoryRoot` overrides the configured state store, and optional `mode` overrides the new-session default without changing retained session policy. `onRuntime` receives a cached `read(offset?, scope?)` accessor; omitted scope means effective state. Use it only after runtime initialization/restoration. The pure `readTemporalState(view, offset, scope?)` accessor is exported separately. SDK hosts with an explicit tool allowlist must include both `patch_state` and `read_state` when they want model access.
276
280
 
277
281
  Honor Pi's `session_shutdown` lifecycle before disposing an embedded session. On the [tested Pi SDK baseline](compatibility.md), `AgentSession.reload()` emits and awaits shutdown, but bare `AgentSession.dispose()` only invalidates/disconnects the session. `AgentSessionRuntime` owns native new/resume/fork replacement and its asynchronous `dispose()` delivers quit shutdown; rebind each newly created session's extensions. An SDK host instead disposing a standalone `AgentSession` should first `await session.extensionRunner.emit({ type: "session_shutdown", reason: "quit" })`; ordinary Pi lifecycle owners already deliver the event. Without shutdown, the adapter's queued Start, compaction-stop flags, and optional presentation disposal are not notified.
278
282
 
@@ -282,12 +286,12 @@ Agent configuration is read once per extension load; session runtime configurati
282
286
 
283
287
  ## Observability
284
288
 
285
- The inspection-capable Telegram port accepts synchronous or Promise-returning Start/Stop results with optional revocation signals, while the legacy `StateFlowTelegramPort` stays synchronous. Controls initiate callback acknowledgement alongside execution rather than waiting for a network round trip before local Stop. Final feedback follows completion, uses the current menu and escapes late failures without answering the callback twice. Revoked receipts, newer callback navigation and disposal suppress stale view writes; they never roll back canonical acceptance.
289
+ The inspection-capable Telegram port accepts synchronous or Promise-returning `select(mode)` results with optional revocation signals, while the legacy `StateFlowTelegramPort` stays synchronous. Controls initiate callback acknowledgement alongside execution rather than waiting for a network round trip before local Stop. Final feedback follows completion, uses the current menu and escapes late failures without answering the callback twice. Revoked receipts, newer callback navigation and disposal suppress stale view writes; they never roll back canonical acceptance. Obsolete start/stop callback keyboards may refresh the current view but never silently select a mode.
286
290
 
287
- Status is a projection of the selected runtime and semantic view, not a second store. Compact terminal and Telegram main-menu status render `G#/C#/S#` only while active; passive Telegram renders `State Flow: off`. Requested Global, CWD and Session Rich snapshots show their independent `#revision`, while Effective shows the vector. Global/CWD Rich views omit the empty structural response placeholder; Session and Effective expose the Session-owned response. Missing evidence stays unavailable instead of appearing empty. The optional Telegram leaf adapter calls the same Start/Stop owners, and its inspectors remain available in either mode. Inspection may refresh live Global/CWD streams in memory so foreign accepted revisions become visible, but never publishes or increments a revision. If model-facing passive access is disabled and no runtime is selected, inspection may lazily load existing canonical shared state under the same read-only rule. The awaited `StateFlowTelegramInspectionPort` returns a `StateFlowTelegramInspection` containing state and matching revisions, plus an optional revocation signal checked immediately before presentation. Stop, selection changes and shutdown cancel obsolete reads without altering newer memory or clearing write fences. The existing synchronous `StateFlowTelegramPort` contract remains supported. A callback is acknowledged before waiting; late failures appear escaped in the existing menu, without a second answer to an expired query. Registration is fail-open and disposal belongs to session shutdown. Local diagnostics stay outside semantic state and cannot change accepted state. Operator-facing fields and privacy boundaries are in [usage](usage.md#status-and-controls).
291
+ Status is a projection of the selected runtime and semantic view, not a second store. Compact terminal status uses accent `state-flow` with dim `active` or `passive`, and is hidden in Off. Telegram main-menu status uses `State Flow: active`, `State Flow: passive` or `State Flow: off`. `/state-flow-status` retains the `g#c#s#` vector beside concise diagnostics and blank-line-separated top-level semantic JSON. Mode is read directly from the session's selected enum, never derived from a pending patch or separate passive flags. Requested Global, CWD and Session Rich snapshots show their independent `#revision`, while Effective shows the vector. Global/CWD Rich views omit the empty structural response placeholder; Session and Effective expose the Session-owned response. Missing evidence stays unavailable instead of appearing empty. The optional Telegram leaf adapter presents the current mode as a monospace value in the submenu heading, followed by matching Mode and Inspect memory headings (long-dash-separated description ending in a colon), each separated by a blank line from its settings-style monospaced-key list, above one radio row `Off | Passive | Active`: selected Off uses 🟡, Passive 🟣 or Active 🟢, and inactive choices use ⚫️; four direct scope-inspection buttons follow, while inspection remains available in all three modes. Inspection may refresh live Global/CWD streams in memory so foreign accepted revisions become visible, but never publishes or increments a revision. If model-facing passive access is disabled and no runtime is selected, inspection may lazily load existing canonical shared state under the same read-only rule. The awaited `StateFlowTelegramInspectionPort` returns a `StateFlowTelegramInspection` containing state and matching revisions, plus an optional revocation signal checked immediately before presentation. Stop, selection changes and shutdown cancel obsolete reads without altering newer memory or clearing write fences. The existing synchronous `StateFlowTelegramPort` contract remains supported. A callback is acknowledged before waiting; late failures appear escaped in the existing menu, without a second answer to an expired query. Registration is fail-open and disposal belongs to session shutdown. Local diagnostics stay outside semantic state and cannot change accepted state. Operator-facing fields and privacy boundaries are in [usage](usage.md#status-and-controls).
288
292
 
289
293
  ## Validation boundaries
290
294
 
291
295
  Structural validation proves JSON shape, exact identity, causal lineage, compilation evidence, CAS and publication invariants. A valid state, receipt, source hash, or compiler revision cannot prove semantic importance, truth, sufficient compilation, correct scope, useful curation, or historical deletion. Those remain model-judgment concerns evaluated separately from deterministic transport checks.
292
296
 
293
- The deterministic continuity and temporal evidence map is in [temporal-acceptance.md](temporal-acceptance.md). Release-scoped open work is in [BACKLOG.md](../BACKLOG.md), and shipped outcomes belong in [CHANGELOG.md](../CHANGELOG.md).
297
+ The deterministic continuity and temporal evidence map is in [temporal-acceptance.md](temporal-acceptance.md). Release-scoped open work is in [BACKLOG.md](../BACKLOG.md), and shipped outcomes belong in [CHANGELOG.md](../CHANGELOG.md). The exact-tag [release workflow](../.github/workflows/release.yml) owns npm Trusted Publisher publication with provenance and creates a GitHub Release only after public-package verification. Keep `dist/` tracked and rebuild it from final sources and package metadata; Git tracking, source/build parity and npm `files` inventory are separate proofs. Never substitute a long-lived npm token. Native scripted-provider tests need a completion assertion outside the callback because Pi can turn an in-provider assertion failure into an assistant error. Await startup/tree fixture handlers, and in contention tests prove withdrawal while exclusion remains held before releasing storage and joining replacement selection.
@@ -40,13 +40,21 @@ Pi catches context-hook errors and may otherwise continue inference. State Flow
40
40
 
41
41
  Operation signals are not universal. Idle commands and session events can lack them. Do not infer native Abort cancellation from an extension-owned shutdown signal or generalize active-run tests to idle waits.
42
42
 
43
- ## Start, Stop and memory restoration
43
+ ## Mode configuration compatibility
44
+
45
+ Global `config.json` accepts `mode: "active" | "passive" | "off"`, defaulting to Off when no mode policy is configured, solely as the initial policy for new sessions. Session `config.json` uses the same key for the concrete retained choice; commands and Telegram never edit the global default. Before semantic initialization, an inactive choice is retained in a native `{mode}` checkpoint instead.
46
+
47
+ Legacy decoding is read-only. Without explicit global mode, the absence of all legacy mode flags means Off; `autoStart: true` means Active, while any present legacy mode flag retains its former mapping: `passiveBootstrap: false` together with `passiveTools: false` means Off, and otherwise the fallback is Passive. An operator who previously relied on an absent configuration for implicit Passive must now select Passive in that session or set global `mode: "passive"` for new sessions. Explicit global mode overrides valid legacy flags; invalid values still fail validation. Session `enabled:true` remains Active, and `enabled:false` is non-active. Native legacy inactive checkpoints use the configured inactive fallback, never an Active default. Session config and native checkpoints reject mixed `mode`/`enabled` representations, even when apparently consistent, rather than choosing between two stored policies. Ordinary writers emit only mode; no eager migration or semantic normalization runs.
48
+
49
+ The extension SDK uses an optional `mode` default override, and both Telegram port variants use `snapshot.mode` plus `select(mode)`. Old callback keyboards may refresh the view without selecting a mode. Synchronous enum-based ports remain supported; this does not promise the removed Start/Stop port signatures.
50
+
51
+ ## Mode selection and memory restoration
44
52
 
45
53
  Start activates current same-session authority under awaited exclusion. It rechecks physical identity and initialization permission after waiting, accepts once, then installs policy, memory and checkpoint. Explicit Start does not claim to restore an expired historical boundary. Native tests prove current shared plus local-private memory at the next provider and actual Abort withdrawal for in-run Start with an operation signal.
46
54
 
47
- Stop switches local policy and passive context before waiting for persistence. For accepted memory it publishes lifecycle metadata without rewriting semantic/provenance files. Repeated pending Stops share one acceptance. Selection, shutdown and accepted Start cancel obsolete Stop work; rejected Start does not. Genuine persistence failure retains readable memory and native context while fencing writes until accepted Start.
55
+ Passive/Off selects local tools/context policy before waiting for persistence; Off injects no State Flow context, including a frozen handoff. For accepted memory it publishes lifecycle metadata without rewriting semantic/provenance files. Pending inactive choices share one acceptance of the latest mode. Selection, shutdown and accepted Start cancel obsolete Stop work; rejected Start does not. Genuine persistence failure retains readable memory and native context while fencing writes until accepted Start.
48
56
 
49
- Start/Stop choose workflow policy, not whether canonical memory exists. Stop does not cancel retained restoration, auto-start initialization or fork copying: passive policy is applied at that operation's acceptance. Cancelling a Start waiter does not cancel independently owned restoration. Selection changes, shutdown and an available native operation signal can revoke obsolete restoration; post-acceptance ancillary failure cannot undo memory.
57
+ Mode choices select workflow policy, not whether canonical memory exists. Passive/Off never cancels retained restoration, Active-default initialization or fork copying: the latest inactive policy is applied at acceptance. Read-only recovery likewise preserves an intervening mode choice and its write fence. Cancelling a Start waiter does not cancel independently owned restoration. Selection changes, shutdown and an available native operation signal can revoke obsolete restoration; post-acceptance ancillary failure cannot undo memory.
50
58
 
51
59
  Native startup and tree handlers await restoration. Tests cover held-store tree/fork selection, exact private state over live shared streams, unchanged parent-private files, cold reopening, failed-Stop recovery and next-provider input without later-branch private values. A public SDK host can observe the child factory result before awaiting extension binding and send Stop or Stop→Start through the child's public `prompt` method while copying waits. This proves that embedding route, not that the installed CLI or Telegram exposes the child before runtime replacement finishes.
52
60
 
@@ -64,7 +72,7 @@ State Flow-owned compaction requires known sufficient context usage and a proven
64
72
 
65
73
  ## Telegram adapter
66
74
 
67
- The optional adapter uses the same Start/Stop and inspection owners as native commands. Inspection returns coherent state plus matching revisions without publication. Controls and inspections acknowledge callbacks before waiting, suppress revoked results and escape late failures in the current menu. Legacy synchronous presentation ports remain supported.
75
+ The optional adapter presents one Off | Passive | Active row and uses the same mode-selection and inspection owners as native commands. Inspection returns coherent state plus matching revisions without publication. Controls and inspections acknowledge callbacks before waiting, suppress revoked results and escape late failures in the current menu. Synchronous mode-selection ports remain supported. A first Passive selection may install a read-only shared cache without invalidating its own success receipt; later controls, branch changes and cancellation still revoke obsolete presentation.
68
76
 
69
77
  Adapter tests establish those contracts with isolated transport fixtures. They are not a live Telegram smoke test. Missing or unready transport remains fail-open and cannot change core memory behavior.
70
78