@llblab/pi-kit 0.24.1 → 0.26.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 (162) hide show
  1. package/AGENTS.md +1 -1
  2. package/BACKLOG.md +5 -1
  3. package/CHANGELOG.md +12 -0
  4. package/README.md +11 -8
  5. package/node_modules/@llblab/pi-actors/AGENTS.md +2 -0
  6. package/node_modules/@llblab/pi-actors/CHANGELOG.md +4 -1
  7. package/node_modules/@llblab/pi-actors/LICENSE +21 -0
  8. package/node_modules/@llblab/pi-actors/README.md +1 -1
  9. package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +1 -1
  10. package/node_modules/@llblab/pi-actors/package.json +4 -3
  11. package/node_modules/@llblab/pi-claude-usage/AGENTS.md +23 -0
  12. package/node_modules/@llblab/pi-claude-usage/BACKLOG.md +4 -0
  13. package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +21 -0
  14. package/node_modules/@llblab/pi-claude-usage/LICENSE +22 -0
  15. package/node_modules/@llblab/pi-claude-usage/README.md +155 -0
  16. package/node_modules/@llblab/pi-claude-usage/banner.jpg +0 -0
  17. package/node_modules/@llblab/pi-claude-usage/index.ts +8 -0
  18. package/node_modules/@llblab/pi-claude-usage/lib/extension.ts +30 -0
  19. package/node_modules/@llblab/pi-claude-usage/lib/fast.ts +24 -0
  20. package/node_modules/@llblab/pi-claude-usage/lib/query.ts +146 -0
  21. package/node_modules/@llblab/pi-claude-usage/lib/status-format.ts +297 -0
  22. package/node_modules/@llblab/pi-claude-usage/lib/status.ts +366 -0
  23. package/node_modules/@llblab/pi-claude-usage/lib/telegram.ts +44 -0
  24. package/node_modules/@llblab/pi-claude-usage/lib/usage-store.ts +221 -0
  25. package/node_modules/@llblab/pi-claude-usage/lib/usage.ts +128 -0
  26. package/node_modules/@llblab/pi-claude-usage/package.json +64 -0
  27. package/node_modules/@llblab/pi-clean-room/AGENTS.md +1 -0
  28. package/node_modules/@llblab/pi-clean-room/CHANGELOG.md +5 -0
  29. package/node_modules/@llblab/pi-clean-room/LICENSE +21 -0
  30. package/node_modules/@llblab/pi-clean-room/README.md +1 -1
  31. package/node_modules/@llblab/pi-clean-room/package.json +3 -2
  32. package/node_modules/@llblab/pi-codex-usage/AGENTS.md +9 -6
  33. package/node_modules/@llblab/pi-codex-usage/BACKLOG.md +2 -1
  34. package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +17 -0
  35. package/node_modules/@llblab/pi-codex-usage/README.md +75 -17
  36. package/node_modules/@llblab/pi-codex-usage/index.ts +8 -1602
  37. package/node_modules/@llblab/pi-codex-usage/lib/extension.ts +25 -0
  38. package/node_modules/@llblab/pi-codex-usage/lib/fast.ts +23 -0
  39. package/node_modules/@llblab/pi-codex-usage/lib/query.ts +368 -0
  40. package/node_modules/@llblab/pi-codex-usage/lib/status-format.ts +347 -0
  41. package/node_modules/@llblab/pi-codex-usage/lib/status.ts +435 -0
  42. package/node_modules/@llblab/pi-codex-usage/lib/telegram.ts +45 -0
  43. package/node_modules/@llblab/pi-codex-usage/lib/usage-store.ts +229 -0
  44. package/node_modules/@llblab/pi-codex-usage/lib/usage.ts +425 -0
  45. package/node_modules/@llblab/pi-codex-usage/package.json +11 -6
  46. package/node_modules/@llblab/pi-command-fast/AGENTS.md +7 -0
  47. package/node_modules/@llblab/pi-command-fast/BACKLOG.md +9 -0
  48. package/node_modules/@llblab/pi-command-fast/CHANGELOG.md +7 -0
  49. package/node_modules/@llblab/pi-command-fast/LICENSE +21 -0
  50. package/node_modules/@llblab/pi-command-fast/README.md +42 -0
  51. package/node_modules/@llblab/pi-command-fast/dist/command.d.ts +8 -0
  52. package/node_modules/@llblab/pi-command-fast/dist/command.js +52 -0
  53. package/node_modules/@llblab/pi-command-fast/dist/index.d.ts +3 -0
  54. package/node_modules/@llblab/pi-command-fast/dist/index.js +3 -0
  55. package/node_modules/@llblab/pi-command-fast/dist/models-json.d.ts +10 -0
  56. package/node_modules/@llblab/pi-command-fast/dist/models-json.js +81 -0
  57. package/node_modules/@llblab/pi-command-fast/package.json +49 -0
  58. package/node_modules/@llblab/pi-grow-loop/AGENTS.md +1 -0
  59. package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +4 -1
  60. package/node_modules/@llblab/pi-grow-loop/LICENSE +21 -0
  61. package/node_modules/@llblab/pi-grow-loop/README.md +1 -1
  62. package/node_modules/@llblab/pi-grow-loop/package.json +3 -2
  63. package/node_modules/@llblab/pi-state-flow/AGENTS.md +43 -56
  64. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +17 -3
  65. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +25 -0
  66. package/node_modules/@llblab/pi-state-flow/LICENSE +21 -0
  67. package/node_modules/@llblab/pi-state-flow/README.md +18 -15
  68. package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +2 -2
  69. package/node_modules/@llblab/pi-state-flow/dist/index.js +2 -2
  70. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +1 -1
  71. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +1 -1
  72. package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +7 -3
  73. package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +16 -7
  74. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +9 -9
  75. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +5 -4
  76. package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +2 -2
  77. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +1 -1
  78. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +7 -4
  79. package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +3 -3
  80. package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +5 -5
  81. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +3 -5
  82. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +503 -235
  83. package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +2 -2
  84. package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +16 -5
  85. package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +11 -4
  86. package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +6 -7
  87. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +4 -1
  88. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +1 -0
  89. package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +4 -5
  90. package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +13 -13
  91. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +7 -6
  92. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +9 -9
  93. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +3 -2
  94. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +17 -12
  95. package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +13 -1
  96. package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +62 -2
  97. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +23 -8
  98. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +52 -20
  99. package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +22 -3
  100. package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +30 -10
  101. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +5 -3
  102. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +19 -28
  103. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +17 -15
  104. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +52 -52
  105. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +8 -4
  106. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +34 -18
  107. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +5 -5
  108. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +13 -19
  109. package/node_modules/@llblab/pi-state-flow/dist/package.json +12 -11
  110. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +2 -2
  111. package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -1
  112. package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +72 -0
  113. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +44 -36
  114. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +14 -6
  115. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +7 -5
  116. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +6 -6
  117. package/node_modules/@llblab/pi-state-flow/docs/performance.md +1 -1
  118. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +13 -12
  119. package/node_modules/@llblab/pi-state-flow/docs/usage.md +37 -33
  120. package/node_modules/@llblab/pi-state-flow/index.ts +3 -2
  121. package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +2 -2
  122. package/node_modules/@llblab/pi-state-flow/lib/config.ts +20 -10
  123. package/node_modules/@llblab/pi-state-flow/lib/context.ts +15 -14
  124. package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +1 -1
  125. package/node_modules/@llblab/pi-state-flow/lib/durable.ts +8 -6
  126. package/node_modules/@llblab/pi-state-flow/lib/episode.ts +6 -6
  127. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +484 -232
  128. package/node_modules/@llblab/pi-state-flow/lib/git.ts +14 -5
  129. package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -11
  130. package/node_modules/@llblab/pi-state-flow/lib/logging.ts +5 -1
  131. package/node_modules/@llblab/pi-state-flow/lib/query.ts +16 -16
  132. package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +11 -11
  133. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +19 -13
  134. package/node_modules/@llblab/pi-state-flow/lib/session.ts +57 -3
  135. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +57 -22
  136. package/node_modules/@llblab/pi-state-flow/lib/state.ts +46 -13
  137. package/node_modules/@llblab/pi-state-flow/lib/status.ts +23 -32
  138. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +66 -65
  139. package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +39 -19
  140. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +19 -27
  141. package/node_modules/@llblab/pi-state-flow/package.json +12 -11
  142. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +2 -2
  143. package/node_modules/jsonc-parser/CHANGELOG.md +76 -0
  144. package/node_modules/jsonc-parser/LICENSE.md +21 -0
  145. package/node_modules/jsonc-parser/README.md +364 -0
  146. package/node_modules/jsonc-parser/SECURITY.md +41 -0
  147. package/node_modules/jsonc-parser/lib/esm/impl/edit.js +185 -0
  148. package/node_modules/jsonc-parser/lib/esm/impl/format.js +261 -0
  149. package/node_modules/jsonc-parser/lib/esm/impl/parser.js +659 -0
  150. package/node_modules/jsonc-parser/lib/esm/impl/scanner.js +443 -0
  151. package/node_modules/jsonc-parser/lib/esm/impl/string-intern.js +29 -0
  152. package/node_modules/jsonc-parser/lib/esm/main.d.ts +351 -0
  153. package/node_modules/jsonc-parser/lib/esm/main.js +178 -0
  154. package/node_modules/jsonc-parser/lib/umd/impl/edit.js +201 -0
  155. package/node_modules/jsonc-parser/lib/umd/impl/format.js +275 -0
  156. package/node_modules/jsonc-parser/lib/umd/impl/parser.js +682 -0
  157. package/node_modules/jsonc-parser/lib/umd/impl/scanner.js +456 -0
  158. package/node_modules/jsonc-parser/lib/umd/impl/string-intern.js +42 -0
  159. package/node_modules/jsonc-parser/lib/umd/main.d.ts +351 -0
  160. package/node_modules/jsonc-parser/lib/umd/main.js +194 -0
  161. package/node_modules/jsonc-parser/package.json +37 -0
  162. package/package.json +10 -6
@@ -2,10 +2,10 @@ import { randomUUID } from "node:crypto";
2
2
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
3
3
  import { projectArtifactForModel, type ArtifactInvalidationNotice, type ArtifactModelHints } from "./artifact.ts";
4
4
  import type { RecentTransitionWindow } from "./history.ts";
5
- import { applyPatch, isObject, presentationJson, sameJson, type JsonValue } from "./json.ts";
5
+ import { applyPatch, isObject, presentationJson, sameJson, type JsonObject, type JsonValue } from "./json.ts";
6
6
  import type { Snapshot } from "./snapshot.ts";
7
7
  import type { RehydrationPhase } from "./rehydration.ts";
8
- import { projectStateForModel, type AtomicScopePatches, type MaterializedState, type ModelState, type StateScope } from "./state.ts";
8
+ import { projectSemanticPatch, projectStateForModel, type AtomicScopePatches, type SemanticState, type StateScope } from "./state.ts";
9
9
 
10
10
  /** Refresh only our section; Pi owns system frames, tools and forced-prompt precedence. */
11
11
  export function projectSystemProtocol(messages: AgentMessage[], protocol: string | undefined): AgentMessage[] {
@@ -44,7 +44,7 @@ function lazyValueKind(value: JsonValue): LazyValueKind {
44
44
  }
45
45
 
46
46
  /** Fixed-budget navigation only: never place lazy bodies or partial key catalogs in baseline context. */
47
- export function lazyNavigationHint(state: MaterializedState): { available: boolean; path: string; keys?: Record<string, LazyValueKind> } {
47
+ export function lazyNavigationHint(state: SemanticState): { available: boolean; path: string; keys?: Record<string, LazyValueKind> } {
48
48
  const entries = isObject(state.lazy) ? Object.entries(state.lazy) : [];
49
49
  const base = { available: entries.length > 0, path: LAZY_HINT_PATH };
50
50
  if (!base.available) return base;
@@ -57,11 +57,11 @@ export function lazyNavigationHint(state: MaterializedState): { available: boole
57
57
  export type ModelStateUpdate = { path: (string | number)[] } & ({ value: JsonValue } | { deleted: true });
58
58
 
59
59
  /** Exact projected replacements, not authored merge patches; paths are unambiguous key/index segments. */
60
- export function acceptedStateUpdates(before: MaterializedState, after: MaterializedState, patches: AtomicScopePatches) {
60
+ export function acceptedStateUpdates(before: SemanticState, after: SemanticState, patches: AtomicScopePatches) {
61
61
  return projectedStateUpdates(projectStateForModel(before), projectStateForModel(after), patches, lazyNavigationHint(before), lazyNavigationHint(after));
62
62
  }
63
63
 
64
- function projectedStateUpdates(previous: ModelState, current: ModelState, patches: AtomicScopePatches,
64
+ function projectedStateUpdates(previous: SemanticState, current: SemanticState, patches: AtomicScopePatches,
65
65
  beforeNavigation: ReturnType<typeof lazyNavigationHint> | undefined, navigation: ReturnType<typeof lazyNavigationHint> | undefined) {
66
66
  const effective: ModelStateUpdate[] = [];
67
67
  const prefix = (parent: readonly (string | number)[], child: readonly (string | number)[]) =>
@@ -78,8 +78,8 @@ function projectedStateUpdates(previous: ModelState, current: ModelState, patche
78
78
  ? (value as Record<string | number, JsonValue>)[key] : undefined;
79
79
  const diff = (left: JsonValue | undefined, right: JsonValue | undefined, path: (string | number)[]) => {
80
80
  if (left === undefined && right === undefined || left !== undefined && right !== undefined && sameJson(left, right)) return;
81
- if (isObject(left) && isObject(right)) {
82
- for (const key of new Set([...Object.keys(left), ...Object.keys(right)])) diff(child(left, key), child(right, key), [...path, key]);
81
+ if (isObject(right) && (isObject(left) || left === undefined && path.length === 1 && Object.keys(right).length > 0)) {
82
+ for (const key of new Set([...Object.keys(left ?? {}), ...Object.keys(right)])) diff(child(left, key), child(right, key), [...path, key]);
83
83
  } else if (Array.isArray(left) && Array.isArray(right) && left.length === right.length) {
84
84
  for (let index = 0; index < right.length; index++) diff(left[index], right[index], [...path, index]);
85
85
  } else put(path, right);
@@ -110,13 +110,13 @@ function projectedStateUpdates(previous: ModelState, current: ModelState, patche
110
110
  }
111
111
 
112
112
  export interface ContextView {
113
- state: ModelState;
113
+ state: SemanticState;
114
114
  lazy_navigation?: ReturnType<typeof lazyNavigationHint>;
115
115
  artifact_invalidations: readonly ArtifactInvalidationNotice[];
116
116
  knowledge_rehydration: { phase: RehydrationPhase } | null;
117
117
  }
118
118
 
119
- export function contextView(state: MaterializedState, hints: ArtifactModelHints, invalidations: readonly ArtifactInvalidationNotice[], phase?: RehydrationPhase): ContextView {
119
+ export function contextView(state: SemanticState, hints: ArtifactModelHints, invalidations: readonly ArtifactInvalidationNotice[], phase?: RehydrationPhase): ContextView {
120
120
  return { state: projectStateForModel(state, hints), lazy_navigation: lazyNavigationHint(state),
121
121
  artifact_invalidations: structuredClone(invalidations), knowledge_rehydration: phase === undefined ? null : { phase } };
122
122
  }
@@ -138,7 +138,7 @@ export class ContextProjection {
138
138
  }
139
139
 
140
140
  /** Called only after successful publication and ancillary acceptance, immediately before returning the native result. */
141
- acceptPatch(before: MaterializedState, after: MaterializedState, patches: AtomicScopePatches, hints: ArtifactModelHints) {
141
+ acceptPatch(before: SemanticState, after: SemanticState, patches: AtomicScopePatches, hints: ArtifactModelHints) {
142
142
  const state = projectStateForModel(after, hints);
143
143
  const navigation = lazyNavigationHint(after);
144
144
  const beforeNavigation = this.view?.lazy_navigation ?? lazyNavigationHint(before);
@@ -269,7 +269,7 @@ export interface PassiveContinuation {
269
269
  activeRunStartedAt?: number;
270
270
  preserveContext?: true;
271
271
  handoff: AgentMessage;
272
- state: ModelState;
272
+ state: SemanticState;
273
273
  }
274
274
 
275
275
  export function syntheticUser(text: string): AgentMessage {
@@ -290,7 +290,7 @@ function messageText(message: AgentMessage): string {
290
290
  return contentText((message as { content?: unknown }).content);
291
291
  }
292
292
 
293
- export function createPassiveContinuation(state: ModelState, startedAt = Date.now(), activeRunStartedAt?: number, preserveContext = false): PassiveContinuation {
293
+ export function createPassiveContinuation(state: SemanticState, startedAt = Date.now(), activeRunStartedAt?: number, preserveContext = false): PassiveContinuation {
294
294
  return {
295
295
  startedAt,
296
296
  state: structuredClone(state),
@@ -319,8 +319,9 @@ export function passiveContinuationMessages(messages: AgentMessage[], continuati
319
319
  function projectRecentForModel(recent: RecentTransitionWindow): RecentTransitionWindow {
320
320
  const projected = structuredClone(recent);
321
321
  for (const record of projected) for (const transition of record.transitions) {
322
+ transition.patch = projectSemanticPatch(transition.patch as JsonObject);
322
323
  delete transition.patch.lazy;
323
- if (transition.patch.artifacts === undefined) continue;
324
+ if (!isObject(transition.patch.artifacts)) continue;
324
325
  for (const [path, entry] of Object.entries(transition.patch.artifacts)) {
325
326
  Object.defineProperty(transition.patch.artifacts, path, {
326
327
  value: projectArtifactForModel(entry), enumerable: true, configurable: true, writable: true,
@@ -333,7 +334,7 @@ function projectRecentForModel(recent: RecentTransitionWindow): RecentTransition
333
334
 
334
335
  export function runtimeContextMessage(
335
336
  snapshot: Snapshot,
336
- state: MaterializedState,
337
+ state: SemanticState,
337
338
  recentTransitions: RecentTransitionWindow = [],
338
339
  artifactInvalidations: readonly ArtifactInvalidationNotice[] = [],
339
340
  rehydrationPhase?: RehydrationPhase,
@@ -234,7 +234,7 @@ export async function inspectStateFlowContinuationProvenance(
234
234
  if ([paths.config, paths.runtime, privatePaths.meta, privatePaths.checkpoint, privatePaths.patches].every((path) => files.get(path) === undefined)) return absent;
235
235
  const runtime = parseSessionRuntime(files.get(paths.config), files.get(paths.runtime), selected.cwd, selected.id);
236
236
  if (!runtime) throw new Error("incomplete canonical session runtime");
237
- if (!runtime.config.enabled) return { stateFlow: { enabled: false, restorable: true }, reason: "State Flow stopped on selected runtime" };
237
+ if (runtime.config.mode !== "active") return { stateFlow: { enabled: false, restorable: true }, reason: "State Flow is not active on selected runtime" };
238
238
  const streams = (["global", "cwd", "session"] as const).map((scope) => {
239
239
  const owned = temporalScopePaths(selected.cwd, selected.id, scope, root, sessionKey);
240
240
  return parseScopeStream(files.get(owned.checkpoint), files.get(owned.patches), scope,
@@ -19,9 +19,9 @@ import {
19
19
  type ArtifactProvenanceRegistry,
20
20
  } from "./artifact.ts";
21
21
  import { MAX_HISTORY_LIMIT } from "./history.ts";
22
- import { canonicalJson, isJsonValue, isObject } from "./json.ts";
22
+ import { canonicalJson, isJsonValue, isObject, type JsonObject } from "./json.ts";
23
23
  import { validateScopeStream, validateTemporalState, type ScopeStream, type TemporalState } from "./temporal.ts";
24
- import type { StateScope } from "./state.ts";
24
+ import { selectSemanticFields, type StateScope } from "./state.ts";
25
25
 
26
26
  const SESSION_KEY_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
27
27
  const STATE_FILE = "state.json";
@@ -66,8 +66,8 @@ export function serializeScopeStream(stream: ScopeStream, scope: StateScope, cwd
66
66
  if (scope === "cwd" && cwdIdentity === undefined) throw new Error("State Flow CWD scope serialization requires its canonical identity");
67
67
  if (scope !== "cwd" && cwdIdentity !== undefined) throw new Error("Only State Flow CWD scope serialization accepts a CWD identity");
68
68
  return {
69
- checkpoint: `${canonicalJson(stream.checkpoint.state)}\n`,
70
- patches: stream.patches.map((record) => `${canonicalJson(record.patch)}\n`).join(""),
69
+ checkpoint: `${canonicalJson(selectSemanticFields(stream.checkpoint.state))}\n`,
70
+ patches: stream.patches.map((record) => `${canonicalJson(selectSemanticFields(record.patch as JsonObject))}\n`).join(""),
71
71
  temporal: {
72
72
  revision: stream.revision,
73
73
  checkpoint: structuredClone(stream.checkpoint.through),
@@ -129,8 +129,10 @@ export function classifyScopeStream(
129
129
  // 0.17.4 and earlier did not persist scope revisions. Credit only their still-retained
130
130
  // semantic tail; discarded ancestry cannot be reconstructed without inventing history.
131
131
  revision: temporal.revision === undefined ? patches.length : temporal.revision,
132
- checkpoint: { through: temporal.checkpoint, state: checkpoint },
133
- patches: patches.map((patch, index) => ({ transition: boundaries[index], patch })),
132
+ checkpoint: { through: temporal.checkpoint, state: isObject(checkpoint) ? selectSemanticFields(checkpoint) : checkpoint },
133
+ patches: patches.map((patch, index) => ({
134
+ transition: boundaries[index], patch: isObject(patch) ? selectSemanticFields(patch) : patch,
135
+ })),
134
136
  };
135
137
  validateScopeStream(stream, scope, MAX_HISTORY_LIMIT);
136
138
  return { kind: "present", stream };
@@ -1,7 +1,7 @@
1
- import { emptySnapshot, type Snapshot } from "./snapshot.ts";
1
+ import { emptySnapshot, type InactiveMode, type Snapshot } from "./snapshot.ts";
2
2
 
3
3
  export function startEpisode(bootstrap: boolean): Snapshot {
4
- const snapshot = emptySnapshot(true);
4
+ const snapshot = emptySnapshot("active");
5
5
  if (bootstrap) snapshot.meta.bootstrap = true;
6
6
  return snapshot;
7
7
  }
@@ -9,15 +9,15 @@ export function startEpisode(bootstrap: boolean): Snapshot {
9
9
  /** Re-enable a branch checkpoint without discarding its runtime config or provenance. */
10
10
  export function resumeEpisode(snapshot: Snapshot, bootstrap: boolean): Snapshot {
11
11
  const next = structuredClone(snapshot);
12
- next.config.enabled = true;
12
+ next.config.mode = "active";
13
13
  if (bootstrap) next.meta.bootstrap = true;
14
14
  return next;
15
15
  }
16
16
 
17
- /** Disable only this branch; durable defaults and session history remain intact. */
18
- export function stopEpisode(snapshot: Snapshot): Snapshot {
17
+ /** Select an inactive mode for only this branch; durable defaults and session history remain intact. */
18
+ export function deactivateEpisode(snapshot: Snapshot, mode: InactiveMode): Snapshot {
19
19
  const next = structuredClone(snapshot);
20
- next.config.enabled = false;
20
+ next.config.mode = mode;
21
21
  return next;
22
22
  }
23
23