@llblab/pi-kit 0.38.2 → 0.38.3

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 (36) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +2 -2
  3. package/node_modules/@llblab/pi-state-flow/AGENTS.md +1 -1
  4. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +11 -673
  5. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +18 -0
  6. package/node_modules/@llblab/pi-state-flow/README.md +8 -8
  7. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +3 -6
  8. package/node_modules/@llblab/pi-state-flow/dist/lib/model-interface.js +2 -3
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/semantic-module.d.ts +1 -1
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +2 -6
  11. package/node_modules/@llblab/pi-state-flow/dist/package.json +2 -1
  12. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +5 -5
  13. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +1 -1
  14. package/node_modules/@llblab/pi-state-flow/docs/README.md +7 -7
  15. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +11 -15
  16. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +12 -10
  17. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +18 -16
  18. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +13 -15
  19. package/node_modules/@llblab/pi-state-flow/docs/protocol-composition-decision.md +2 -2
  20. package/node_modules/@llblab/pi-state-flow/docs/public-module-contract.md +16 -6
  21. package/node_modules/@llblab/pi-state-flow/docs/scope-selection-contract.md +25 -23
  22. package/node_modules/@llblab/pi-state-flow/docs/semantic-compatibility-decision.md +14 -12
  23. package/node_modules/@llblab/pi-state-flow/docs/semantic-extensibility-decision.md +2 -2
  24. package/node_modules/@llblab/pi-state-flow/docs/semantic-handoff-contract.md +133 -15
  25. package/node_modules/@llblab/pi-state-flow/docs/semantic-memory-evaluation.md +5 -5
  26. package/node_modules/@llblab/pi-state-flow/docs/semantic-module-contract.md +5 -5
  27. package/node_modules/@llblab/pi-state-flow/docs/single-scope-interface-contract.md +2 -2
  28. package/node_modules/@llblab/pi-state-flow/docs/usage.md +33 -23
  29. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +3 -7
  30. package/node_modules/@llblab/pi-state-flow/lib/model-interface.ts +2 -3
  31. package/node_modules/@llblab/pi-state-flow/lib/semantic-module.ts +1 -1
  32. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +2 -6
  33. package/node_modules/@llblab/pi-state-flow/package.json +2 -1
  34. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +5 -5
  35. package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +1 -1
  36. package/package.json +2 -2
@@ -4,6 +4,24 @@
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.27.4: TypeScript Declaration Hotfix
8
+
9
+ - `Package type discovery`: Adds the top-level `types` entry pointing to `dist/index.d.ts` so TypeScript consumers and tools that do not read conditional exports can discover the built declarations. Existing conditional type exports remain unchanged. The tracked distribution manifest is rebuilt with matching metadata.
10
+
11
+ ## 0.27.3: Minimal Telegram inspection menu
12
+
13
+ - `Single participating-owner list`: Removes the duplicated Participating scopes summary and the Session-exclusion notice from the Telegram section. The Inspect participating memory list and its buttons are now the only statement of participating owners, so no line can disagree with the available actions.
14
+ - `Selection-independent Effective line`: Replaces the generated `global → cwd → session` enumeration and its three-owner variant with one fixed sentence about overlay order. A single selected owner shows only that owner, without an Effective line, button or explanatory tail.
15
+
16
+ ## 0.27.2: Consistency & Simplification
17
+
18
+ - `Documentation reconciliation`: Correct current release/public-module status to the published 0.27.0/0.27.1 behavior, including metadata v4 retention and external-root tools/context/producers. Distinguish the six-plane internal seam from public registration and mark M4/M5 deferrals as historical without upgrading their review verdicts. No production behavior or compatibility policy changed.
19
+ - `Current work and history`: Replace the completed evolution roadmap with an outstanding-work backlog. Retain the exact five-patch offline-bundle corpus in its semantic contract, keep historical decisions and acceptance evidence traceable, and separate unrun live-model and installed-client gates from consolidation work.
20
+ - `Operator and read contracts`: Reconcile wanted/available/excluded scopes, v2 policy records, v3/v4 storage, Session-excluded completion and deferred native forks. Correct the lazy `keys` example to structural-only metadata and guard it with an executable documentation regression. Replace duplicated architecture checkpoint narratives with existing contract references; clarify synchronous context and cancelable module production.
21
+ - `Implementation simplification`: Remove the obsolete native scope-validation wrapper and a private plane-name alias, reusing existing owners directly. All three validation calls retain their original conditions and positions; public signatures, storage admission, publication and cancellation fences are unchanged. Active/bootstrap/Passive protocol renderings remain byte-identical across all seven selections.
22
+ - `Packaged guidance`: Align Skills with explicit scope-command arguments, wanted-but-unavailable reads, single-owner relative cascade/deletion paths and the existing registered-mutable external-root boundary. Missing or incompatible definitions never permit discarding retained data or bypassing authoring restrictions.
23
+ - `Compatibility`: No configuration, public API semantics or storage format changes. Legacy conversion and retired-root reservations remain supported throughout State Flow 0.x. Existing publication, source-provenance and cancellation guarantees are unchanged; deterministic validation does not establish live-model quality, installed-client compatibility or stronger storage durability.
24
+
7
25
  ## 0.27.1: Selected Scope Read Diagnostics
8
26
 
9
27
  - `Read availability`: Explicit reads now distinguish a selected owner with no available read view from an excluded owner. In pre-runtime Passive sessions, an unacquired Session no longer incorrectly reports itself excluded. Reads still do not create private memory, widen the selection or return partial multi-path results; normal accepted writes retain their acquisition rules.
@@ -88,7 +88,7 @@ New sessions default to **Off**. Choose Passive for ordinary conversation with m
88
88
  - Choosing Passive or Active later acquires memory.
89
89
  - Stored memory and Pi's native trace stay intact.
90
90
 
91
- Modes select agent behavior; they do not change disk persistence or fork copying. Final consolidation needs no empty ceremonial patch, and context projection does not delete native history. See [mode semantics and bootstrap terminology](docs/usage.md#active-passive-and-configured-off).
91
+ Modes select agent behavior, not different storage algorithms. Off defers memory acquisition; selected-scope policy independently determines whether a fork may copy private Session memory. Final consolidation needs no empty ceremonial patch, and context projection does not delete native history. See [mode semantics and bootstrap terminology](docs/usage.md#active-passive-and-configured-off).
92
92
 
93
93
  ## State model
94
94
 
@@ -100,7 +100,7 @@ Memory has three ownership scopes:
100
100
  - `cwd`: Knowledge shared by sessions in the same working directory.
101
101
  - `session`: State belonging to the current session and its selected branch.
102
102
 
103
- Participation is configured with a nonempty `scopes` array in [global configuration](docs/usage.md#configuration); omission selects all three. Each native branch captures that choice once, and forks inherit it. All seven nonempty selections use the same runtime. The existing mode commands accept optional whitespace-separated owners, for example `/state-flow-active session`, `/state-flow-passive cwd global`, or `/state-flow-off cwd`. Blank/mode-only commands and Telegram controls preserve the captured choice. Duplicate/unknown tokens reject before changing policy; Off records a new choice without canonical memory I/O. No settings chooser is required. Excluded owners receive no automatic memory contribution or semantic writes; new answers are stored only when Active and Session participates. Mode-only Telegram buttons retain that choice; explicit operator inspection is separate from model participation. See the [functional boundary and legacy proof dependencies](docs/scope-selection-contract.md#m2-functional-acceptance-boundary).
103
+ Participation is configured with a nonempty `scopes` array in [global configuration](docs/usage.md#configuration); omission selects all three. Wanted means selected by captured policy, available means a validated read view exists, and excluded means outside that policy; [usage](docs/usage.md#lifecycle-operations) owns the distinctions and the `selected, unavailable` read diagnostic. Selection never moves data between owners. Each native branch captures that choice once, and forks inherit it. All seven nonempty selections use the same runtime. The existing mode commands accept optional whitespace-separated owners, for example `/state-flow-active session`, `/state-flow-passive cwd global`, or `/state-flow-off cwd`. Blank/mode-only commands and Telegram controls preserve the captured choice. Duplicate/unknown tokens reject before changing policy; Off records a new choice without canonical memory I/O. No settings chooser is required. Excluded owners receive no automatic memory contribution or semantic writes; new answers are stored only when Active and Session participates. Mode-only Telegram buttons retain that choice; explicit operator inspection is separate from model participation. See the [functional boundary and legacy proof dependencies](docs/scope-selection-contract.md#m2-functional-acceptance-boundary).
104
104
 
105
105
  Participating owners compose recursively in **global → CWD → session** order:
106
106
 
@@ -125,8 +125,8 @@ Runtime views provide these documented planes:
125
125
  Every plane is optional on disk:
126
126
 
127
127
  - Stored checkpoints and patches may omit any documented plane, including `intents`, `lazy` or `response`.
128
- - Current and historical views assemble only the known fields actually present in the selected scopes; absent fields are not filled in. Empty `response` counts as absent.
129
- - Readers ignore unrelated unknown top-level fields, and writers emit only known fields. Retired `contract`/`working` roots explicitly reject in the target format; nested ordinary keys remain unrestricted.
128
+ - Current and historical views assemble present built-in fields and metadata v4-declared external roots from the selected scopes; absent fields are not filled in. Empty `response` counts as absent.
129
+ - Declared external roots and retained history survive missing or incompatible definitions under the [public module contract](docs/public-module-contract.md). Unrelated unknown roots are not supported semantic fields. Retired `contract`/`working` roots explicitly reject in the target format; nested ordinary keys remain unrestricted.
130
130
  - Reading or starting never rewrites data just to normalize it, and a missing field is not a storage-format error.
131
131
 
132
132
  These planes organize ordinary JSON; there is no project-specific schema. The model updates every plane except `response`, which is runtime-owned.
@@ -220,8 +220,8 @@ The default store is `~/.pi/agent/state-flow/`, independent of registered source
220
220
  **Resume, tree navigation and forks:**
221
221
 
222
222
  - **State Flow does not depend on the Pi step.** Memory is the current JSON state of each scope and changes only through accepted `patch_state` calls and run lifecycle. Resume and tree navigation restore the branch's mode, never an older memory revision; Off defers acquisition. Past values stay readable through `read_state` offsets within retained history.
223
- - A new session gets its own session layer.
224
- - Supported native forks copy the parent's **current** session memory into a new owner without changing the parent's private data.
223
+ - A new session gets its own private layer only when Session acquisition is admitted; shared-only selections create no hidden private semantics.
224
+ - Supported native forks inherit captured policy and copy parent-**current** Session memory into a fresh child owner when admitted, without changing parent-private data. Off or Session-excluded forks defer private acquisition; an acquired child never recopies.
225
225
  - Explicit Active or Passive accepts the validated current memory of that same session; modes stay stable.
226
226
  - Missing, malformed or contradictory current files, unsafe fork copying and concurrent writes remain fenced and are never replaced by empty or foreign memory.
227
227
 
@@ -239,7 +239,7 @@ How mode changes interact with storage:
239
239
  - Explicit Off inspection may read current stored values through a disposable validated reader. It does not activate memory, install cache or change pending fork acquisition. Missing private authority stays unavailable.
240
240
  - Active waits for a coherent capture and acceptance; another mode or selection can withdraw its wait.
241
241
 
242
- Canonical scope metadata v3 uses `strategy` and `tactics`. Supported v1/v2 checkpoint/tail cohorts are read through a declared translation and converted once on an owned semantic acceptance, after a verified exact-byte backup outside the canonical store. Upgrade/quiesce all writers first; unsupported layouts are not repaired. See the [format and backup boundary](docs/usage.md#moving-a-store-and-supported-formats) before upgrading or moving a store.
242
+ Core-only scope metadata v3 and external-module metadata v4 use `strategy` and `tactics`; v4 also retains declared external objects/descriptors independently of definition lifetimes. Supported v1/v2 cohorts read through declared translation; owned acceptance may convert supported formats only after a verified exact-byte backup outside canonical authority. Upgrade/quiesce all writers first; unsupported layouts are not repaired. See the [format and backup boundary](docs/usage.md#moving-a-store-and-supported-formats) before upgrading or moving a store.
243
243
 
244
244
  ## Operational boundaries
245
245
 
@@ -258,7 +258,7 @@ Treat state, diagnostic logs and backups as private data. Revalidate consequenti
258
258
  - [Acceptance map](docs/temporal-acceptance.md) — Properties tied to concrete tests.
259
259
  - [Documentation index](docs/README.md) — All maintained guides.
260
260
 
261
- The six built-in planes use an [internal semantic-module contract](docs/semantic-module-contract.md) for authoring policy and mode-aware context. It also supplies isolated context/producer executors. The candidate [public module entry](docs/public-module-contract.md) adds native-host-scoped registration/lifetime binding; metadata4 opaque-retention codecs have bounded local acceptance, and registered mutable external roots now use the existing read/patch tools in the local candidate; captured inputs and Active/Passive module context now execute with source and native-identity fences, and Active async producers commit complete replacements through the same atomic engine. Ordinary public consumers now have SOURCE/built-SDK acceptance evidence for current-only forks and opaque retention across folding, reload, absence and re-registration. This remains an unpublished local candidate, not a new independent activation approval. Neither contract implies a new loader or automatic background reasoning.
261
+ The six built-in planes use an [internal semantic-module contract](docs/semantic-module-contract.md) for authoring policy, mode-aware context and isolated producer evaluation. Since 0.27.0, the published [`@llblab/pi-state-flow/modules` entry](docs/public-module-contract.md) also supports trusted companion-extension registration, retained metadata v4 external roots, existing read/patch tools, Active/Passive context and atomic Active producer replacements. Pi remains the loader; callbacks are trusted JavaScript, not sandboxed plugins or autonomous background reasoning. The public contract owns registration, retention and currentness requirements; [compatibility](docs/compatibility.md) separates deterministic integration evidence from installed-client and live-model claims.
262
262
 
263
263
  For development, run `npm install` and `npm run validate`. `npm run benchmark` is opt-in and separate from the normal suite; see `benchmarks/README.md` in a source checkout.
264
264
 
@@ -171,16 +171,13 @@ export default function stateFlowExtension(pi, options = {}) {
171
171
  pi.appendEntry(PASSIVE_STOP_ENTRY_TYPE, captureSelectedNativeMarker({ version: 2,
172
172
  owner: ctx.sessionManager.getSessionId(), mode: snapshot.config.mode, scopes: nativeScopeSelection(ctx), ...value }));
173
173
  }
174
- function assertNativeMemoryScopes(scopes) {
175
- captureScopeSelection(scopes);
176
- }
177
174
  function branchPolicy(ctx, reason, memoryRequired = true) {
178
175
  const branch = ctx.sessionManager.getBranch();
179
176
  const policy = prepareSelectedBranchPolicy(branch, { owner: ctx.sessionManager.getSessionId(), markerEntryType: PASSIVE_STOP_ENTRY_TYPE,
180
177
  defaults: { mode: isNewSession(reason, branch) ? config.mode : config.inactiveMode, scopes: config.scopes },
181
178
  inactiveMode: config.inactiveMode, fork: reason === "fork" });
182
179
  if (memoryRequired)
183
- assertNativeMemoryScopes(policy.scopes);
180
+ captureScopeSelection(policy.scopes);
184
181
  return policy;
185
182
  }
186
183
  /** Failure-only denial evidence, never policy admission: inspect own known-epoch headers without getters or memory I/O. */
@@ -525,7 +522,7 @@ export default function stateFlowExtension(pi, options = {}) {
525
522
  if (nativePolicy.requiresCapture)
526
523
  pi.appendEntry(PASSIVE_STOP_ENTRY_TYPE, nativePolicy.capture);
527
524
  if (nativePolicy.mode !== "off")
528
- assertNativeMemoryScopes(nativePolicy.scopes);
525
+ captureScopeSelection(nativePolicy.scopes);
529
526
  }
530
527
  catch (error) {
531
528
  runtime = undefined;
@@ -1285,7 +1282,7 @@ export default function stateFlowExtension(pi, options = {}) {
1285
1282
  return { ok: false, message: active ? "State Flow activation was superseded" : "State Flow mode change was superseded", signal: pending.signal };
1286
1283
  };
1287
1284
  try {
1288
- assertNativeMemoryScopes(wanted);
1285
+ captureScopeSelection(wanted);
1289
1286
  const activation = createRuntime(ctx);
1290
1287
  const deferred = deferredBranch;
1291
1288
  if (deferred) {
@@ -5,7 +5,6 @@ import { DEFAULT_HISTORY_LIMIT } from "./history.js";
5
5
  import { parseStateReadPath, parseValuePath } from "./query.js";
6
6
  import { captureScopeSelection } from "./selection.js";
7
7
  import { MODEL_PLANE_NAMES } from "./planes.js";
8
- const PATCH_PLANES = MODEL_PLANE_NAMES;
9
8
  const SEMANTIC_ROOT = /^(?:intents|strategy|tactics|artifacts|response|lazy|x_[a-z][a-z0-9_]*)(?=\.|\[|$)/;
10
9
  const PATCH_PATH = /^(?:effective|global|cwd|session)\.patches(?:\[\d+\])?$/;
11
10
  function dense(value) {
@@ -66,7 +65,7 @@ function admitKeys(value, selected, external) {
66
65
  if (!keys.length)
67
66
  throw new Error("Model patch requires at least one supplied branch");
68
67
  if (selected.length === 1) {
69
- if (keys.some(key => !PATCH_PLANES.includes(key) && !external.includes(key)))
68
+ if (keys.some(key => !MODEL_PLANE_NAMES.includes(key) && !external.includes(key)))
70
69
  throw new Error("Single-owner model patches require flat semantic planes");
71
70
  }
72
71
  else
@@ -79,7 +78,7 @@ function planePatch(value, external) {
79
78
  if (!isObject(value) || !Object.keys(value).length)
80
79
  throw new Error("Model scope patch must be a nonempty object");
81
80
  for (const key of Object.keys(value)) {
82
- if (!PATCH_PLANES.includes(key) && !external.includes(key))
81
+ if (!MODEL_PLANE_NAMES.includes(key) && !external.includes(key))
83
82
  throw new Error(`Model patch does not accept semantic plane ${key}`);
84
83
  if (!isObject(value[key]))
85
84
  throw new Error(`Model patch plane ${key} must be a JSON object`);
@@ -35,7 +35,7 @@ export interface StateFlowModuleInput<Input extends JsonValue = JsonValue> {
35
35
  /** Verify only the captured source; throw if obsolete. No acquisition or async work. */
36
36
  assertCurrent(): void;
37
37
  }
38
- /** Candidate public v1 contract; durable activation requires matching retained metadata. */
38
+ /** Published public v1 contract; retained descriptors govern durable compatibility. */
39
39
  export interface StateFlowModule<Content extends JsonObject = JsonObject, Input extends JsonValue = JsonValue> {
40
40
  readonly immutable: boolean;
41
41
  readonly id: string;
@@ -57,7 +57,6 @@ export function buildStateFlowSectionView(snapshot, callbackData) {
57
57
  inspectionRows.push([]);
58
58
  inspectionRows.at(-1).push({ text: STATE_FLOW_SCOPE_LABELS[scope], callback_data: callbackData("inspect", scope) });
59
59
  }
60
- const named = scopes.map(scope => `<code>${scope}</code>`).join(" → ");
61
60
  const modes = STATE_FLOW_MODES.map((mode) => ({
62
61
  text: `${mode === snapshot.mode ? STATE_FLOW_SELECTED_MARKERS[mode] : "⚫️"} ${STATE_FLOW_MODE_LABELS[mode]}`,
63
62
  callback_data: callbackData(mode),
@@ -76,15 +75,12 @@ export function buildStateFlowSectionView(snapshot, callbackData) {
76
75
  `<code>-</code> <code>passive</code>: regular chat with memory tools; available memory from the selected ${scopes.length === 1 ? "scope" : "scopes"} enters the agent's context.`,
77
76
  "<code>-</code> <code>active</code>: same memory access; each completed answer closes a cycle, and the next request starts from saved state, not the full chat.",
78
77
  "",
79
- `<b>Participating scopes:</b> ${named}`,
80
- ...(!scopes.includes("session") ? ["New answers are delivered, not stored: Session is excluded."] : []),
81
- "",
82
78
  "<b>Inspect participating memory</b> — view available stored state even in Off:",
83
79
  "",
84
80
  ...scopes.map(scope => `<code>-</code> <code>${scope}</code>: ${STATE_FLOW_SCOPE_DESCRIPTIONS[scope]}`),
85
81
  ...(scopes.length > 1
86
- ? [`<code>-</code> <code>effective</code>: validated available ${named} overlay; excluded scopes do not contribute.`]
87
- : ["This single scope is also the agent's effective state; no separate overlay is needed."]),
82
+ ? ["<code>-</code> <code>effective</code>: merged state of the selected scopes in order from the general to the specific."]
83
+ : []),
88
84
  ].join("\n"),
89
85
  parseMode: "html",
90
86
  replyMarkup: { inline_keyboard: [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-state-flow",
3
- "version": "0.27.1",
3
+ "version": "0.27.4",
4
4
  "license": "MIT",
5
5
  "private": false,
6
6
  "description": "Incremental scoped state/context/memory compiler for Pi, inspired by SKILL.state",
@@ -18,6 +18,7 @@
18
18
  "url": "https://github.com/llblab/pi-state-flow/issues"
19
19
  },
20
20
  "type": "module",
21
+ "types": "./dist/index.d.ts",
21
22
  "files": [
22
23
  "index.ts",
23
24
  "api",
@@ -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-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.
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. Mode-only commands and Telegram preserve captured scopes. The existing mode commands also accept optional exact owner arguments to change the current branch's selection; duplicate/unknown owners reject before policy changes and Off remains memory-inert. Global `mode` defaults to Off for new sessions and never overrides retained choices. Do not change mode or scopes without operator authorization.
19
19
 
20
20
  ## Map
21
21
 
@@ -34,7 +34,7 @@ A proposal is not a commitment. Preserve an accepted plan's phases, dependencies
34
34
 
35
35
  ## Read
36
36
 
37
- Reuse sufficient visible state. The memory head and its recent transitions are frozen at projection start. Apply later `state_updates` only when their `projection` matches the head's `State Flow projection:` ID; older native results remain historical. Effective update paths are key/index arrays whose values replace that path, while `deleted: true` means absence. The optional `cascaded` array lists owner-scoped paths cleared in the intermediate ownership phase, even if later authored writes recreate them, including nested lazy keys; it contains no values, is never elided, and does not mean the effective path is absent if a broader-scope value remains. Current notices can replace invalidation lists or rehydration phase, including clearing them with `[]` or `null`; lazy bodies still require explicit reads.
37
+ Reuse sufficient visible state. The memory head and its recent transitions are frozen at projection start. Apply later `state_updates` only when their `projection` matches the head's `State Flow projection:` ID; older native results remain historical. Effective update paths are key/index arrays whose values replace that path, while `deleted: true` means absence. The optional `cascaded` array lists paths cleared in the intermediate ownership phase, relative for one WANTED owner and owner-scoped for multiple WANTED owners, even if later authored writes recreate them, including nested lazy keys; it contains no values, is never elided, and does not mean the effective path is absent if a broader-scope value remains. Current notices can replace invalidation lists or rehydration phase, including clearing them with `[]` or `null`; lazy bodies still require explicit reads.
38
38
 
39
39
  `read_state` accepts `path` or `paths`, never both. Multi-path reads succeed or fail together. Projections: `value` (default), `keys` (structure), `patch` (intersecting change at the selected boundary).
40
40
 
@@ -48,7 +48,7 @@ With exactly one WANTED owner, ordinary read paths are flat, with no scope token
48
48
  {"paths":["tactics","strategy"]}
49
49
  ```
50
50
 
51
- `effective[N].tactics` selects a temporal boundary; `tactics.items[N]` indexes a nested array. Sole-owner `patches[N]` is the scalar owner patch-history alias. With multiple WANTED owners, ordinary unscoped paths use effective state; explicit owner paths disambiguate ownership. Multi-owner example, requiring both CWD and Session to participate: `{"paths":["cwd.tactics","session.tactics"]}`. Arity follows WANTED selection, not whichever owners happen to have an available view.
51
+ `effective[N].tactics` selects a temporal boundary; `tactics.items[N]` indexes a nested array. Sole-owner `patches[N]` is the scalar owner patch-history alias. With multiple WANTED owners, ordinary unscoped paths use effective state; explicit owner paths disambiguate ownership. Multi-owner example, requiring both CWD and Session to participate: `{"paths":["cwd.tactics","session.tactics"]}`. Arity follows WANTED selection, not whichever owners happen to have an available view. Wanted but unacquired Session is `selected, unavailable`, not excluded; reads cannot acquire it or return partial mixed-owner results.
52
52
 
53
53
  Unscoped paths use the sole owner's current state or, with multiple owners, effective state. Optional explicit `cwd[1].tactics` reads the preceding causal boundary when CWD participates. Materialized-history and scope patch-history paths such as `cwd.patches[1]` share the configured `historyLimit` bound (default 7) and require actually retained history. Lowering the limit folds excess tails without erasing current state; increasing it does not reconstruct discarded history. Array ranges such as `cwd.lazy.checks[0..3]` exclude the endpoint and require existing elements. Missing paths are unavailable; inspect parent keys only when needed for the task. Missing history is not empty history. Read `lazy` explicitly. Treat structured `$ref` values and `$`-prefixed `read_state` paths inside ordinary strings, such as `$effective.lazy.memory[7]`, as semantic-state references. Other resources retain their native locators. Resolve any reference through the appropriate read/tool only when needed. Neither form proves authority or existence, hydrates, or executes anything; only intent ownership (see Write) has a deletion consequence. Never scan or resolve references merely to test them. A missing single value path with exact durable sources returns `{value:null, hint:[{type:"dangling-reference", message, paths}]}`. Treat `hint` as top-level diagnostic metadata, never as the requested state: its message is descriptive and conditional; its paths are runtime-verified current reference owners, not verified new locations of the target. The hint proves provenance rather than staleness and is absent when no current durable source matches; keys, patch, and batch reads keep all-or-error behavior. Only then inspect ownership as needed and patch a proven stale owning value while preserving its surrounding meaning. Effective absence, inaccessible external resources, and transient failures are not proof.
54
54
 
@@ -56,11 +56,11 @@ Missing paths or runtime hints alone do not require historical search. The agent
56
56
 
57
57
  ## Write
58
58
 
59
- Call `patch_state` alone per assistant response; await acceptance before dependent work. With exactly one WANTED owner, supply flat object planes (`intents`, `strategy`, `tactics`, `artifacts`, `lazy`), without an owner wrapper. With multiple WANTED owners, supply one or more explicit participating owners from `global`, `cwd`, and `session`; supplied scopes commit atomically. Arity follows WANTED selection, not available view; selection is not a grant of authority. Default to Session for current work only when it participates, CWD for reusable project knowledge, and Global for established cross-project knowledge. Preserve these meanings; an unavailable owner is not a reason to write its data into a broader one. Omit unchanged planes in a sole-owner patch and unchanged scopes in a multi-owner patch.
59
+ Call `patch_state` alone per assistant response; await acceptance before dependent work. With exactly one WANTED owner, supply built-in flat object planes (`intents`, `strategy`, `tactics`, `artifacts`, `lazy`), without an owner wrapper. Compatible registered mutable external roots may also be authored when advertised by the current `patch_state` schema; registration/schema alone grants no source or publication authority. Immutable or unavailable definitions do not permit model writes. With multiple WANTED owners, supply one or more explicit participating owners from `global`, `cwd`, and `session`; supplied scopes commit atomically. Arity follows WANTED selection, not available view; selection is not a grant of authority. Default to Session for current work only when it participates, CWD for reusable project knowledge, and Global for established cross-project knowledge. Preserve these meanings; an unavailable owner is not a reason to write its data into a broader one. Omit unchanged planes in a sole-owner patch and unchanged scopes in a multi-owner patch.
60
60
 
61
61
  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.
62
62
 
63
- When present, semantic planes `intents`, `strategy`, `tactics`, `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, and omitted nonempty fields persist. Accepted supplied scopes recursively omit empty object fields and planes, including explicit `{}`; the scope root remains `{}`. This also cleans legacy empty branches in that scope, which can advance its revision once. Array slots and empty arrays remain; empty object fields inside elements disappear without shifting indices. Model projection hides legacy empty branches, but exact current/historical reads and untouched scopes are not normalized. Nested `null` removes an owned object key; empty ancestors disappear and inherited content may reappear. Canonical `"[N]"` keys patch existing array elements; indexed deletion and out-of-bounds indices are forbidden. Replace the whole array to add/remove elements. Missing authored object-key deletions succeed with a nonfatal hint showing owner-scoped JSON Pointers for the target and first unavailable component. Hints are not state, do not advance revisions and do not prove a typo; check the address only when deletion was expected to change something. Never guess or automatically correct the target.
63
+ When present, semantic planes `intents`, `strategy`, `tactics`, `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. Known content includes metadata-declared external roots; missing or incompatible definitions never authorize discarding that retained data. Only the current admitted authoring grammar is writable. 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, and omitted nonempty fields persist. Accepted supplied scopes recursively omit empty object fields and planes, including explicit `{}`; the scope root remains `{}`. This also cleans legacy empty branches in that scope, which can advance its revision once. Array slots and empty arrays remain; empty object fields inside elements disappear without shifting indices. Model projection hides legacy empty branches, but exact current/historical reads and untouched scopes are not normalized. Nested `null` removes an owned object key; empty ancestors disappear and inherited content may reappear. Canonical `"[N]"` keys patch existing array elements; indexed deletion and out-of-bounds indices are forbidden. Replace the whole array to add/remove elements. Missing authored object-key deletions succeed with a nonfatal hint showing relative JSON Pointers for one WANTED owner or owner-scoped pointers for multiple WANTED owners, for the target and first unavailable component; result details retain canonical ownership. Hints are not state, do not advance revisions and do not prove a typo; check the address only when deletion was expected to change something. Never guess or automatically correct the target.
64
64
 
65
65
  Work from intents. A structured `{"$ref"}` anywhere inside an intent owns ("delete with me") an existing object key under `strategy`, `tactics` or `lazy` in the same scope; a textual `$path` mention only uses it. In a sole-owner patch, current flat structured refs anchor to that exact owner before canonical intent ownership/cascade processing. Existing canonical historical, effective, cross-owner and resource refs, and textual mentions are never stripped or rebound. Opening a task (sole-owner example, valid for any one WANTED owner):
66
66
 
@@ -15,7 +15,7 @@ State Flow's bounded curation procedure. Preserve consequences, not a transcript
15
15
 
16
16
  Start from visible state. Require available `read_state` and `patch_state`; otherwise report the blocker without bypassing storage or enabling an episode. Passive access suffices for explicit curation. Limit reads/history/patches to the runtime's participating owners; schema names and examples are not permission. Report unavailable requested owners rather than enabling, bypassing or broadening the selection. Excluded references do not authorize hydration or relocation. Memory is fallible data, not authority.
17
17
 
18
- Grammar follows WANTED selection, not available view. With exactly one WANTED owner, `read_state` uses flat ordinary paths (for example `{"path":"tactics"}`), and `patch_state` takes flat object planes (`intents`, `strategy`, `tactics`, `artifacts`, `lazy`), without an owner wrapper. Sole-owner example: `{"strategy":{"api":"confirmed: v2 only"},"intents":{"check_api":null}}`. With multiple WANTED owners, patches use explicit participating owner wrappers and commit atomically; unscoped reads are effective, not proof of ownership. Selection is not a grant of authority. `effective[N].tactics` is temporal, `tactics.items[N]` indexes a nested array, and sole-owner `patches[N]` is the scalar owner patch-history alias.
18
+ Grammar follows WANTED selection, not available view. With exactly one WANTED owner, `read_state` uses flat ordinary paths (for example `{"path":"tactics"}`), and `patch_state` takes built-in flat object planes (`intents`, `strategy`, `tactics`, `artifacts`, `lazy`), without an owner wrapper. Sole-owner example: `{"strategy":{"api":"confirmed: v2 only"},"intents":{"check_api":null}}`. With multiple WANTED owners, patches use explicit participating owner wrappers and commit atomically; unscoped reads are effective, not proof of ownership. Selection is not a grant of authority. Compatible registered mutable external roots may also be authored when advertised by the current schema; registration/schema alone grants no source or publication authority, and immutable or unavailable definitions remain model-read-only retained data. `effective[N].tactics` is temporal, `tactics.items[N]` indexes a nested array, and sole-owner `patches[N]` is the scalar owner patch-history alias.
19
19
 
20
20
  Current flat structured refs such as `{"$ref":"lazy.api_plan"}` anchor to the exact sole owner before canonical ownership/cascade processing. Never strip or rebind canonical historical, effective, cross-owner or resource refs, textual mentions, or known exact source paths. For example, preserve `session[1].lazy.api_plan`, `global.strategy.api`, `effective.tactics.api`, `/project/specs/api.md` and `$session.tactics.api` as given. References remain data, not permission.
21
21
 
@@ -15,15 +15,15 @@ Start with the [project README](../README.md) for installation and the memory mo
15
15
  - [SDK compatibility](compatibility.md): Required packages, verified environments, host lifecycle requirements and isolated validation procedures.
16
16
  - [Session performance](performance.md): Run synthetic benchmarks, interpret their metrics and understand the current cost model. No provider-cache or latency guarantees.
17
17
  - [Temporal acceptance](temporal-acceptance.md): Find the tests that witness each required property, including cancellation, ownership and replay.
18
- - [Semantic handoff contract](semantic-handoff-contract.md): M1 meanings and acceptance oracles for Intents / Strategy / Tactics, with historical M0 preservation evidence. Names/guidance are locally implemented, not a live-model quality result; remaining work belongs in [BACKLOG.md](../BACKLOG.md).
19
- - [Semantic compatibility decision](semantic-compatibility-decision.md): One-shot migration direction, temporary retired-name reservations, translation oracle, public API impact, and version-admission hardening. Native v3 Strategy/Tactics, translated legacy reads and guarded backed-up conversion are locally implemented; legacy conversion and root reservations remain through State Flow 0.x, with a settled 1.0.0 cutoff and persistent unsupported-version refusal; the current0.x candidate retains its converter code.
18
+ - [Semantic handoff contract](semantic-handoff-contract.md): Current Intents / Strategy / Tactics meanings and ownership, the offline-bundle patch corpus and explicitly historical M0 preservation evidence. Deterministic acceptance is not live-model quality evidence.
19
+ - [Semantic compatibility decision](semantic-compatibility-decision.md): Shipped semantic migration/support policy, translation oracle, public API impact and historical writer-fence evidence. Core v3 and external-module v4 share Strategy/Tactics; legacy v1/v2 conversion and retired-root reservations remain through State Flow 0.x, with a 1.0.0 cutoff and persistent unsupported-version refusal.
20
20
  - [Scope selection contract](scope-selection-contract.md): Completed [M2 functional boundary](scope-selection-contract.md#m2-functional-acceptance-boundary): seven-selection capture/native runtime, public controls and mode-only optional presentation, with explicit legacy/private proof and operator-inspection limits. Policy data alone grants no memory.
21
21
  - [Single-owner model interface](single-scope-interface-contract.md): Reviewed schema/canonical/native flat tools, protocol/Skills and typed runtime outputs; original-request/foreign-provenance counterexamples, deterministic linked-task/identity checkpoint and actual SDK byte measurements. No live model-quality, token/cache/cost or universal-access claim.
22
- - [Public semantic modules](public-module-contract.md): Candidate native-host registration/lifetime membrane and admitted-input contract; metadata4 codec/opaque retention has bounded local acceptance. Mutable external roots now participate in the existing read/patch tools in the local candidate; captured inputs and Active/Passive context now execute with source/native fences; Active producers now commit complete replacements through the same engine; local ordinary-consumer acceptance also covers current-only forks and opaque retention through folding/absence/incompatibility/reload/re-registration in SOURCE and the built SDK. Activation was audited inline, not independently approved or released.
23
- - [Internal semantic modules](semantic-module-contract.md): Executable five-member internal contract, six production bindings, main-agent immutability, Active/Passive contributions and detached asynchronous producer evaluation. No public ABI/loader, new stored planes or automatic background inference.
24
- - [Protocol composition decision](protocol-composition-decision.md): Historical accepted M4 retain/defer decision and producer/trust ownership; the later explicit internal-module request supersedes its no-extraction disposition only within the linked new contract.
25
- - [Semantic extensibility decision](semantic-extensibility-decision.md): Historical accepted M5 no-new-API/expansion-deferral decision, demand/alternatives and atomic-validation countercase. The later internal contract does not establish public manifests, sandboxing, production archives or model-quality claims.
26
- - [Semantic memory evaluation](semantic-memory-evaluation.md): Fixed linked-task trial, controlled fixture, independent rubric, isolation/measurement contract, and credential-safe preflight. Deferred until functional implementation; no live behavioral baseline has run.
22
+ - [Public semantic modules](public-module-contract.md): Published `./modules` API since 0.27.0: native-host registration, trusted callbacks, metadata v4 retention, external-root tools, Active/Passive context and atomic Active producers. Owns public integration and currentness boundaries, not dynamic loading or sandboxing.
23
+ - [Internal semantic modules](semantic-module-contract.md): Five-member package-owned contract, six built-in bindings, main-agent immutability and detached context/producer evaluation. Public registration uses the same evaluators under the separate public host contract.
24
+ - [Protocol composition decision](protocol-composition-decision.md): Historical accepted M4 retain/defer decision, producer/trust ownership and original review evidence. Later internal/public module work superseded only its bounded no-extraction disposition.
25
+ - [Semantic extensibility decision](semantic-extensibility-decision.md): Historical accepted M5 no-new-API decision and atomic-validation countercase. Later explicitly authorized internal/public module work shipped in 0.27.0; no dynamic loader, sandbox, production archive or quality claim follows.
26
+ - [Semantic memory evaluation](semantic-memory-evaluation.md): Fixed linked-task trial, controlled fixture, independent rubric, isolation/measurement contract and historical credential-safe preflight. Functional implementation has shipped; live-model comparison remains separately authorization-gated and unrun.
27
27
 
28
28
  ## Development policy
29
29
 
@@ -15,9 +15,11 @@ The extension owns durable memory while enabled. The native bridge admits all se
15
15
  - `selection`: pure immutable nonempty owner selections and command-token parsing. Value capture grants no mode, lifecycle authority, I/O or storage participation by itself; see the [selection boundary](scope-selection-contract.md#internal-value-boundary-and-lifecycle-encoding-direction).
16
16
  - `temporal`, `history`: causal boundaries, checkpoint/tail folding and hot history. Internal [selected temporal algebra](scope-selection-contract.md#selected-temporal-value-algebra) retains only participating streams and metadata-only excluded-step witnesses; algebra alone grants no native storage/runtime admission.
17
17
  - `migration`: temporary pure legacy-to-target conversion, root-name guards, reference translation and serialized preflight. `durable` consumes it before known-field filtering; `storage` alone owns backup and guarded conversion publication. It does not own I/O or lifecycle; see the [migration boundary](semantic-compatibility-decision.md#serialized-owner-cohort-preflight).
18
- - `durable`, `storage`, `git`: exact canonical files, file-cohort CAS, and optional settled-turn backup, including its due/permitted/cancellation state (`SettledTurnBackup`). Internal [selected admission](scope-selection-contract.md#read-only-selected-cohort-durable-admission) binds v2 owner witnesses and separates exact byte dependencies from private/layout presence. [Selected publication](scope-selection-contract.md#guarded-selected-cohort-publication) derives replay/witnesses and backs up lifecycle upgrades; the [explicit origin boundary](scope-selection-contract.md#explicit-new-shared-only-origins) and [first Session acquisition](scope-selection-contract.md#explicit-first-session-acquisition) can create/adopt selected storage; [child-owned fork deferral](scope-selection-contract.md#child-owned-selected-fork-deferral) avoids parent reads while Session is excluded. The [selected parent-current copy boundary](scope-selection-contract.md#selected-parent-current-private-copy) accepts independently proven eager/deferred copies; [selected current-session acceptance](scope-selection-contract.md#selected-current-session-acceptance) preserves aligned history or admits current shared drift. The [private reselection basis](scope-selection-contract.md#acquired-private-reselection-proof-boundary) retains acquired Session authority independently across shared-only origins without opening excluded private bodies; missing/false proof never becomes empty or foreign memory. [Accepted selected cache/reads](scope-selection-contract.md#accepted-selected-runtime-cache-and-reads) now use one discriminated memory slot. [Selected semantic transactions](scope-selection-contract.md#selected-semantic-transactions-and-provenance-publication) reuse one staging/commit and successor planner with guarded targets and opaque-preserving metadata deltas. [First authoring](scope-selection-contract.md#selected-first-authoring-origin-routing) captures the selection before waiting and chooses the existing shared/private origin path without an intermediate empty publication. [Selected source-facility admission](scope-selection-contract.md#selected-source-facility-admission) now filters acquisition/maintenance/rehydration and Skill evidence before disabled-source observation. [Complete native policy/marker admission](scope-selection-contract.md#complete-native-policy-and-marker-admission) now resolves scoped branch choices independently from fences/pending copy. [Default-all-three native turn/tool/answer correlation](scope-selection-contract.md#native-turn-and-tool-batch-request-correlation) is now installed using SDK turn/finalized-ID evidence, not provider payloads. [Native context/preparation leases](scope-selection-contract.md#native-context-and-preparation-request-admission) now gate store waits and available pre-provider checkpoints through public Abort, without coupling independent control work to model cancellation. The [default-all-three native bridge](scope-selection-contract.md#default-all-three-native-bridge) composes these owners and passes aggregate integration. [Nonfork policy binding](scope-selection-contract.md#guarded-nonfork-native-selection-binding) forwards captured scopes and shares atomic first authoring; [header-only fork disposition](scope-selection-contract.md#canonical-fork-disposition-before-native-copy) distinguishes deferred acquisition from acquired child-current without semantic observation. [Explicit first-Session Start](scope-selection-contract.md#explicit-native-first-session-activation) separately grants exact-base unacquired acceptance without losing known private denial; ordinary resume cannot. [First mutation over unacquired source](scope-selection-contract.md#native-first-mutation-over-an-unacquired-source) composes the same staging/commit engine under live physical-owner receipts. [Fresh shared-fork deferral](scope-selection-contract.md#guarded-fresh-shared-only-fork-deferral) uses a mode-only late sampler and child pending retention; [Native scope-only lifetime evidence](scope-selection-contract.md#native-scope-only-lifetime-evidence-and-future-control-duty) validates existing request epochs/operation slots without another holder. [Native seven-selection integration](scope-selection-contract.md#retained-native-seven-selection-integration) exercises these same ports, not a second engine; public scope overrides now compose the same restoration/Start/Off owners without another runtime.
19
- - `snapshot`, `session`, `runtime`, `recovery`, `episode`: Pi branch/runtime lifecycle, branch traversal, and passive-boundary interpretation. Snapshot/session also provide detached [lifecycle-v2 candidate preflight](scope-selection-contract.md#detached-policy-and-lifecycle-preflight) and [selected policy-bound request lifetimes](scope-selection-contract.md#selected-policy-bound-request-lifetime), reusing renewable cancellation and synchronous native rechecks without storage/acquisition authority. Lower policy candidates do not confer canonical admission/publication. [Accepted selected lifecycle ports](scope-selection-contract.md#accepted-selected-lifecycle-ports) capture accepted run/v2 checkpoints without I/O and persist strictly Passive mode changes without current-origin adoption, semantic conversion or run resets; they do not themselves install native selected attachment. [Read-only observation ports](scope-selection-contract.md#selected-read-only-observation-ports) share that same runtime slot without accepted/publication authority: shared inspection never reads Session/lifecycle, while owned current observation retains required epoch/private proof and omits planned absent owners. The same policy lifetime binds selected native requests/context/preparation/tools/answers across all seven selections, including withdrawal before held exclusion releases; native policy selection alone still confers no publication permission.
18
+ - `durable`, `storage`, `git`: canonical codecs and identity, exact file-cohort CAS/exclusion/guarded rollback, and optional settled-turn backup (`SettledTurnBackup`). Selected admission separates semantic bodies from required private/layout evidence; origin/current/fork publication remains explicitly authorized. The [scope contract](scope-selection-contract.md#m2-functional-acceptance-boundary) owns selected/private proof and its historical implementation checkpoints; the storage and backup sections below own transaction/durability limits.
19
+ - `snapshot`, `session`, `runtime`, `recovery`, `episode`: branch/run lifecycle, captured v2 policy, revocable native request receipts and accepted/read-only runtime views. Policy candidates and observation grant no private acquisition or publication. The same selection lifetime binds requests, context, tools and answers across all seven choices; current-memory attachment, private deferral and legacy dependencies follow the [scope contract](scope-selection-contract.md).
20
20
  - `transition`, `ownership`, `context`: inference barriers, turn resolution, intent-ownership cascades, passive projection, and response reconciliation. Internal [selected semantic staging/commit](scope-selection-contract.md#selected-semantic-staging-and-commit) reuses the same engine without disabled owners; native response/policy composition uses the same seven-selection bridge. Session-excluded completion finalizes lifecycle without a semantic response transition or hidden private owner.
21
+ - `semantic-module`, `planes`: detached internal context/producer evaluation and the six static built-in bindings; see the [internal contract](semantic-module-contract.md). They do not publish or acquire memory.
22
+ - `module-registry`: revocable native-host registration/catalog lifetimes for the published `./modules` entry. The [public contract](public-module-contract.md) owns trusted callback admission, retained external identities and runtime currentness; a catalog is not publication authority.
21
23
  - `query`: current/historical value projection and shared semantic-locator syntax; parsing alone resolves no target and confers no authority.
22
24
  - `model-interface`: Detached flat/canonical locator/ref and typed target/pointer presentation, consuming existing query/selection/JSON contracts, never storage/native authority. Actual native sole-flat/multi-explicit read/patch callers use it after original M2 admission. Arity-only schema refresh and fresh SDK definitions preserve old wrapper identity; the [deterministic functional interface](single-scope-interface-contract.md#deterministic-m3-checkpoint) is accepted, not live-model quality.
23
25
  - `compaction`: completed-history compaction planning and per-request marker state (`StateFlowCompactionRequests`).
@@ -26,13 +28,13 @@ The extension owns durable memory while enabled. The native bridge admits all se
26
28
  - `memory`: memory-bearing scope diagnostics; explicit selection returns only present selected flags while the legacy no-selection signature retains all-three behavior.
27
29
  - `continuation`: native-header discovery, runtime-provenance inspection, deterministic recommendation, and host startup precedence.
28
30
  - `protocol`, `logging`: Model/tool presentation and bounded diagnostic persistence. Existing trusted plain renderers/private snippets and their context/extension trust boundaries are evaluated in the [protocol composition decision](protocol-composition-decision.md), without moving semantic execution into prompt hooks.
29
- - `status`, `telegram`, `extension`: operator projection, the optional fail-open pi-telegram presentation adapter, and high-level Pi adapter wiring. Internal [selected observational diagnostics](scope-selection-contract.md#selected-observational-diagnostics-and-projector-admission) render exact sparse owners/revisions without disabled values or fabricated zeros. Existing context/cascade/handoff projectors need no second selection API when fed accepted selected read projections; native presentation uses the selected bridge. Status separates captured requested policy from exact available materialization, including an unacquired Session requested alongside observable shared owners. Neither status nor Off invents an owner/revision or performs acquisition; command scopes use the existing native policy/mode owners.
31
+ - `status`, `telegram`, `extension`: observational operator projection, optional fail-open Telegram presentation and native lifecycle composition. Status distinguishes wanted policy from available owners/revisions without fabricated values or acquisition; Telegram mode controls preserve scopes and inspection follows wanted targets. [Usage](usage.md#status-and-controls) owns operator behavior; the [scope acceptance map](scope-selection-contract.md#m2-functional-acceptance-boundary) records proof limits.
30
32
 
31
33
  Test placement is checked in both directions by `tests/invariants.test.ts`: LIB modules have same-named mirrors, and every suite has an exact production owner or a reasoned cross-domain exception. The benchmark suites mirror `benchmarks/benchmark.ts` and `benchmarks/benchmark-session.ts` rather than being exceptions. The four exception reasons live in the invariant itself. Shared fixture modules may set up, read and assert, but cannot be hidden suites: the source-hygiene check erases TypeScript types before checking literal test-runner/suite dependencies and direct registration forms. This is not an arbitrary-code sandbox or a proof of semantic case ownership; independent organization review remains necessary.
32
34
 
33
35
  ## Semantic state
34
36
 
35
- Runtime views select these documented semantic planes when present. Stored scope objects may omit any of them, and unrelated top-level fields are ignored:
37
+ Runtime views select these built-in semantic planes when present, plus metadata v4-declared external object roots under the [public contract](public-module-contract.md). Stored scope objects may omit any plane; unrelated undeclared roots are not supported semantic fields:
36
38
 
37
39
  ```json
38
40
  {
@@ -45,7 +47,7 @@ Runtime views select these documented semantic planes when present. Stored scope
45
47
  }
46
48
  ```
47
49
 
48
- - `intents` is the queue of chosen actions, not a planner, scheduler, task manager or execution loop. An intent may own same-scope `tactics`/`lazy` keys by structured reference; see [model tools](#model-tools).
50
+ - `intents` is the queue of chosen actions, not a planner, scheduler, task manager or execution loop. An intent may own same-scope `strategy`/`tactics`/`lazy` object keys by structured reference; see [model tools](#model-tools).
49
51
  - `strategy` retains binding requirements, accepted approaches/plans, decisions, interfaces and rejected alternatives. Proposals remain distinguishable from commitments; operational contradiction does not silently cancel a binding requirement.
50
52
  - `tactics` is the temporary working context of those actions: verified current facts, results and uncertainties.
51
53
  - `artifacts` maps exact source paths to compiled routing metadata.
@@ -65,7 +67,7 @@ Later scopes win. A scope-local `null` deletion removes only that scope's key an
65
67
 
66
68
  **Sparse state.** Missing planes are valid sparse semantics, not incomplete storage.
67
69
 
68
- - Checkpoint/tail codecs admit declared versions before interpreting fields. Legacy v1/v2 cohorts normalize to target v3 through raw collision-checked conversion; target retired roots reject. Candidate metadata4 adds retained external-plane descriptors outside semantic content: declared object values and still-retained history survive missing definitions, unrelated core writes, folding and fork. Legacy unknown roots are not silently adopted; explicit conversion to4 checks raw external-namespace collisions before filtering. Owned conversion first backs up exact original bytes outside canonical authority. Public external tool/context activation remains separate from codec retention.
70
+ - Checkpoint/tail codecs admit declared versions before interpreting fields. The [migration contract](semantic-compatibility-decision.md) owns v1/v2 translation, v3/v4 admission, raw collision refusal, retired-root support timing and backed-up owned conversion. The [public module contract](public-module-contract.md) owns metadata v4 descriptors and opaque retention through missing definitions, unrelated writes, folding and forks. Retention and callback activation are distinct responsibilities; both shipped in 0.27.0.
69
71
  - Retained record identities and positions survive even when filtering leaves an empty patch.
70
72
  - `readTemporalView` selects present known fields at the requested boundary, then overlays scopes without inventing fields.
71
73
  - Empty and absent responses mean the same for Active projection; clearing a nonempty response projects as a deletion. Passive omits the plane regardless of its value.
@@ -382,7 +384,7 @@ meta.json
382
384
  - Predecessor combined session metadata is unsupported; session `meta.json`, `config.json` and `runtime.json` must already satisfy their canonical ownership contracts.
383
385
  - Metadata writers replace only their owned leaves and preserve JSON-safe unknown siblings.
384
386
  - A scope without a revision counter initializes it from the still-retained semantic tail and persists that baseline on its next owned write; folded ancestry is not guessed.
385
- - Scope metadata v3 declares Strategy/Tactics; candidate v4 additionally carries retained module descriptors, including unavailable/deleted-content slots. Legacy1/2 and explicit upgrades to4 use the same complete-cohort backup/exclusion/CAS boundary; raw external namespace collisions reject. Core-only streams keep v3 output, while v4 writes cannot drop or alter retained schema/policy descriptors. Representation alone changes no revision or causal identity; runtime-only persistence and inspection never upgrade. Quiesce old writers: version refusal cannot retrofit unsafe deployed callers.
387
+ - Scope metadata v3 declares Strategy/Tactics; implemented v4 additionally carries retained module descriptors, including unavailable/deleted-content slots. Legacy1/2 and explicit upgrades to4 use the same complete-cohort backup/exclusion/CAS boundary; raw external namespace collisions reject. Core-only streams keep v3 output, while v4 writes cannot drop or alter retained schema/policy descriptors. Representation alone changes no revision or causal identity; runtime-only persistence and inspection never upgrade. Quiesce old writers: version refusal cannot retrofit unsafe deployed callers.
386
388
  - Supported flag-based settings and native `{disabled:true}` markers decode read-only. Mixed session `mode`/`enabled` representations are rejected, and no eager migration runs.
387
389
  - Revision-pointer checkpoints are unsupported and fail closed without Git restoration.
388
390
 
@@ -809,13 +811,7 @@ The pure `readTemporalState(view, offset, scope?)` accessor is exported separate
809
811
  - An SDK host disposing a standalone `AgentSession` instead should first `await session.extensionRunner.emit({ type: "session_shutdown", reason: "quit" })`. Ordinary Pi lifecycle owners already deliver the event.
810
812
  - Without shutdown, the adapter's queued Start, compaction-stop flags and optional presentation disposal are not notified.
811
813
 
812
- **Forks.** Native replacement teardown and State Flow adoption are separate responsibilities. On a native fork start, the adapter verifies the direct parent header and the selected retained source boundary, then copies only the session stream/provenance into a distinct child owner over the current live shared scopes.
813
-
814
- - The child has a fresh origin and its own checkpoint, never a UUID alias or a historical shared-state rewind.
815
- - A child-owned native reset marker fences inherited passive Stop projection across reload.
816
- - Parent-owned checkpoints selected later cannot fall through to an ordinary-disabled marker and reset child storage.
817
-
818
- See the [fork contract](fork-contract.md) and [operating limits](usage.md#fork-support-and-limits).
814
+ **Forks.** Native replacement teardown and State Flow adoption are separate responsibilities. The adapter composes selected shared-only deferral or admitted parent-current private copying under the [fork contract](fork-contract.md); Off remains native-only. Captured policy is not source/copy authority, and an acquired child always uses its own current memory rather than recopying a parent or rewinding history. See [operating limits](usage.md#fork-support-and-limits).
819
815
 
820
816
  **Configuration.** Agent configuration is read once per extension load; session runtime configuration stays branch-selected. See [configuration](usage.md#configuration) for settings and path precedence. Ownership meanings and relative precedence are stable, but participation is a captured validated nonempty subset of Global/CWD/Session; omission defaults to all three, Global is not mandatory. Global defaults and explicit native scope choices remain separate from mode and current/private/source admission; see the [functional scope boundary](scope-selection-contract.md#m2-functional-acceptance-boundary).
821
817
 
@@ -844,7 +840,7 @@ Status is a projection of the selected runtime and semantic view, not a second s
844
840
  **Telegram menu layout.** The optional Telegram leaf adapter shows, in order:
845
841
 
846
842
  1. the current mode as a monospace value in the submenu heading;
847
- 2. matching Mode and Inspect participating memory headings (a long-dash-separated description ending in a colon), with a captured Participating scopes line and selection-aware settings-style descriptions;
843
+ 2. matching Mode and Inspect participating memory headings (a long-dash-separated description ending in a colon), with selection-aware settings-style descriptions; the captured participating owners are named only by that Inspect list, with no separate scope-summary or Session-exclusion line;
848
844
  3. one radio row `Off | Passive | Active`, where selected Off uses 🟣, Passive 🟡 or Active 🟢, and inactive choices use ⚫️;
849
845
  4. only captured participating owner-inspection buttons, plus Effective for two or three owners. A sole owner is already effective. Inspection stays explicit and available in all three modes; unavailable memory is not invented.
850
846
 
@@ -4,21 +4,23 @@
4
4
 
5
5
  State Flow requires matching `pi-coding-agent`, `pi-agent-core`, `pi-ai` and `pi-tui` packages at `>=1.0.0`. Keep all four on the same release line. The open-ended peer range permits newer SDK releases; it does not certify them.
6
6
 
7
- **Verified environment:** Linux/x64, Node 26.8.1, Git 2.55.0 and matching Pi SDK 1.0.0 packages.
7
+ **Recorded published-baseline environment:** Linux/x64, Node 26.8.1, Git 2.55.0 and matching Pi SDK 1.0.0 packages.
8
+
9
+ **0.27.2 local candidate checks:** Linux/x64, Node 22.19.0 and 24.21.0, Git 2.56.0 and matching Pi SDK 1.0.0 packages; see the [0.27.2 release record](../CHANGELOG.md). These are local deterministic checks, not new exact-tag release CI or installed-client certification.
8
10
 
9
11
  - Repository validation covers tests, typecheck, build, compiled imports and package dry-run. Results apply to the exact source and dependency identities validated.
10
- - The release workflow uses Node 24; its result is a separate verification gate.
12
+ - The release workflow validates Node **22.19.0** and **24**, then publishes on Node 24. The recorded v0.27.1 release passed 1,696 tests per supported Node; this is baseline evidence, not a validation result for later edits.
11
13
  - Tests use isolated stores and scripted providers through the real Pi SDK. They do not certify installed Telegram/TUI reachability, live provider behavior, other operating systems, mixed SDK versions or untested newer SDK releases.
12
14
 
13
15
  Detailed behavioral witnesses live in [temporal acceptance](temporal-acceptance.md); benchmark methodology and source-bound results live in [performance](performance.md).
14
16
 
15
17
  ## Canonical scope format admission
16
18
 
17
- Core-only canonical scope metadata remains **version 3**, with `strategy` and `tactics` fields. The candidate **version 4** codec additionally retains external object-plane descriptors and opaque values independently of loaded definitions; absent internal `modules` metadata keeps existing v3 output. Declared legacy versions **1/2** translate before known-field filtering. Target-format `contract`/`working` roots reject; nested domain keys remain ordinary JSON. Unsupported versions fail closed. These scope versions are distinct from the unchanged Session lifecycle format and public module API version1. Public seventh-plane tool/context/producer activation remains separate open work; see the [public module boundary](public-module-contract.md).
19
+ Core-only canonical scope metadata remains **version 3**, with `strategy` and `tactics` fields. The implemented **version 4** codec additionally retains external object-plane descriptors and opaque values independently of loaded definitions; absent internal `modules` metadata keeps existing v3 output. Declared legacy versions **1/2** translate before known-field filtering. Target-format `contract`/`working` roots reject; nested domain keys remain ordinary JSON. Unsupported versions fail closed. These scope versions are distinct from selection-aware Session lifecycle v2 and public module API v1; supported legacy lifecycle-v1 admission retains its complete-cohort proof requirements. External-root tools, captured Active/Passive context and Active producers shipped in 0.27.0; see the [public module boundary](public-module-contract.md).
18
20
 
19
21
  Legacy inspection is observational. Owned semantic acceptance may convert only admitted owner scopes, after complete target-cohort/identity validation, exact source CAS and a verified private backup outside canonical authority. Missing legacy revisions credit retained records only; conversion itself adds no learning transition. Opaque capture/rollback preserves arbitrary original bytes while semantic interpretation requires valid UTF-8. See [migration proof and support limits](semantic-compatibility-decision.md#guarded-publication-and-support-boundary) and [backup/recovery guidance](usage.md#moving-a-store-and-supported-formats).
20
22
 
21
- This is a locally implemented, unreleased breaking semantic API/storage change. Existing exported names remain where applicable but their fields, callbacks, schemas and paths use Strategy/Tactics; no permanent old-field aliases are provided. Upgrade/quiesce old consumers before deployment: already-deployed unsafe low-level callers cannot be universally fenced. No active store was operated on during development.
23
+ This breaking semantic API/storage change shipped in **0.27.0** and is retained in **0.27.1**. Existing exported names remain where applicable but their fields, callbacks, schemas and paths use Strategy/Tactics; no permanent old-field aliases are provided. Upgrade/quiesce old consumers before deployment: already-deployed unsafe low-level callers cannot be universally fenced. No active store was operated on during development.
22
24
 
23
25
  ## Public host seams
24
26
 
@@ -69,11 +71,11 @@ Native tests prove no provider call before coherent acceptance, cancellation whi
69
71
 
70
72
  **Preferred representation:**
71
73
 
72
- - Global `config.json` accepts `mode: "active" | "passive" | "off"`. It defaults to Off when no mode policy is configured and supplies only the initial policy for new sessions.
73
- - Session `config.json` uses the same key for the concrete retained choice. Commands and Telegram never edit the global default.
74
- - Before semantic initialization, an inactive choice is retained in a native `{mode}` checkpoint instead.
74
+ - Global `config.json` accepts `mode: "active" | "passive" | "off"`, defaulting to Off, and a nonempty unique `scopes` array, defaulting to all three owners. These are initial defaults, not overrides of captured branch policy.
75
+ - Accepted Session lifecycle v2 configuration stores concrete `{mode, scopes}`. Before canonical acceptance, owner-bound native v2 policy records capture the same choice without semantic storage. Commands and Telegram do not edit global defaults; mode-only actions preserve captured scopes.
76
+ - [Usage](usage.md#lifecycle-operations) defines wanted, available and excluded owners and the 0.27.1 diagnostic. A wanted unacquired Session is unavailable, not excluded; inspection/observation never acquires it. [Scope selection](scope-selection-contract.md#m2-functional-acceptance-boundary) owns legacy proof, deferred forks and request-lifetime requirements.
75
77
 
76
- **Other readable representations.** Decoding is read-only; ordinary writers emit only mode, with no eager migration or semantic normalization.
78
+ **Legacy readable mode representations.** The following are compatibility inputs, not alternative current policy formats. Decoding is read-only; current accepted lifecycle writers use v2 concrete policy, without inspection-triggered conversion or semantic normalization. Malformed explicit scope evidence rejects rather than falling through to a wider mode-only fallback.
77
79
 
78
80
  - Without explicit global mode, absence of all flag-based mode settings means Off.
79
81
  - `autoStart: true` means Active. With any flag-based mode setting present, `passiveBootstrap: false` together with `passiveTools: false` means Off; otherwise the fallback is Passive.
@@ -84,7 +86,7 @@ Native tests prove no provider call before coherent acceptance, cancellation whi
84
86
 
85
87
  To use Passive, select it in the current session or set global `mode: "passive"` for new sessions.
86
88
 
87
- **SDK and Telegram controls.** The extension SDK accepts an optional `mode` default override. Both Telegram port variants use `snapshot.mode` plus `select(mode)`. The optional additive `snapshot.inferenceBlocked` diagnostic marks failed Active restoration; legacy ports may omit it. A stale callback keyboard may refresh the view without selecting a mode. Synchronous enum-based ports are supported; Start/Stop port signatures are not.
89
+ **SDK and Telegram controls.** The extension SDK accepts an optional `mode` default override. Both Telegram port variants use `snapshot.mode` plus `select(mode)` and preserve captured scopes. Optional `snapshot.scopes` supplies participation; legacy omission means all three, while malformed explicit scopes reject. The optional additive `snapshot.inferenceBlocked` diagnostic marks failed Active restoration; legacy ports may omit it. A stale callback keyboard may refresh the view without selecting a mode. Synchronous enum-based ports are supported; Start/Stop port signatures are not.
88
90
 
89
91
  ## Mode selection and memory restoration
90
92
 
@@ -141,7 +143,7 @@ This optional-backup policy does not apply to required semantic publication or r
141
143
 
142
144
  ## Telegram adapter
143
145
 
144
- The optional adapter presents one Off | Passive | Active row and uses the same mode-selection and inspection owners as native commands.
146
+ The optional adapter presents one Off | Passive | Active row and uses the same mode-selection and inspection owners as native commands. It is not a scope chooser: only wanted owners receive inspection buttons, and Effective is offered only for two or three wanted owners. Inspections read validated available memory without acquiring missing owners or clearing fences.
145
147
 
146
148
  - Inspection returns coherent state plus matching revisions, without publication.
147
149
  - Controls and inspections acknowledge callbacks before waiting, suppress revoked results and escape late failures in the current menu.