@llblab/pi-kit 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +6 -5
  4. package/node_modules/@llblab/pi-claude-usage/AGENTS.md +20 -0
  5. package/node_modules/@llblab/pi-claude-usage/BACKLOG.md +3 -0
  6. package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +13 -0
  7. package/node_modules/@llblab/pi-claude-usage/LICENSE +22 -0
  8. package/node_modules/@llblab/pi-claude-usage/README.md +110 -0
  9. package/node_modules/@llblab/pi-claude-usage/banner.jpg +0 -0
  10. package/node_modules/@llblab/pi-claude-usage/index.ts +1159 -0
  11. package/node_modules/@llblab/pi-claude-usage/package.json +60 -0
  12. package/node_modules/@llblab/pi-state-flow/AGENTS.md +42 -56
  13. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +16 -3
  14. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +19 -0
  15. package/node_modules/@llblab/pi-state-flow/README.md +15 -12
  16. package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +2 -2
  17. package/node_modules/@llblab/pi-state-flow/dist/index.js +2 -2
  18. package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +7 -3
  19. package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +16 -7
  20. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +9 -9
  21. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +5 -4
  22. package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +2 -2
  23. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +1 -1
  24. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +7 -4
  25. package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +3 -3
  26. package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +5 -5
  27. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +3 -5
  28. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +275 -199
  29. package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +11 -4
  30. package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +6 -7
  31. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +4 -1
  32. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +1 -0
  33. package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +4 -5
  34. package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +13 -13
  35. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +7 -6
  36. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +9 -9
  37. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +3 -2
  38. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +17 -12
  39. package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +4 -1
  40. package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +2 -1
  41. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +17 -8
  42. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +49 -20
  43. package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +22 -3
  44. package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +30 -10
  45. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +5 -3
  46. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +19 -28
  47. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +17 -15
  48. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +52 -52
  49. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +8 -4
  50. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +34 -18
  51. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +5 -5
  52. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +13 -19
  53. package/node_modules/@llblab/pi-state-flow/dist/package.json +3 -3
  54. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +2 -2
  55. package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -1
  56. package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +72 -0
  57. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +36 -32
  58. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +12 -4
  59. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +5 -5
  60. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +6 -6
  61. package/node_modules/@llblab/pi-state-flow/docs/performance.md +1 -1
  62. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +13 -12
  63. package/node_modules/@llblab/pi-state-flow/docs/usage.md +32 -29
  64. package/node_modules/@llblab/pi-state-flow/index.ts +3 -2
  65. package/node_modules/@llblab/pi-state-flow/lib/config.ts +20 -10
  66. package/node_modules/@llblab/pi-state-flow/lib/context.ts +15 -14
  67. package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +1 -1
  68. package/node_modules/@llblab/pi-state-flow/lib/durable.ts +8 -6
  69. package/node_modules/@llblab/pi-state-flow/lib/episode.ts +6 -6
  70. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +274 -197
  71. package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -11
  72. package/node_modules/@llblab/pi-state-flow/lib/logging.ts +5 -1
  73. package/node_modules/@llblab/pi-state-flow/lib/query.ts +16 -16
  74. package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +11 -11
  75. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +19 -13
  76. package/node_modules/@llblab/pi-state-flow/lib/session.ts +6 -3
  77. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +55 -22
  78. package/node_modules/@llblab/pi-state-flow/lib/state.ts +46 -13
  79. package/node_modules/@llblab/pi-state-flow/lib/status.ts +23 -32
  80. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +66 -65
  81. package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +39 -19
  82. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +19 -27
  83. package/node_modules/@llblab/pi-state-flow/package.json +3 -3
  84. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +2 -2
  85. package/node_modules/@llblab/pi-telegram/AGENTS.md +1 -1
  86. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +5 -0
  87. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +2 -0
  88. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +55 -2
  89. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +21 -0
  90. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +144 -1
  91. package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +9 -0
  92. package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +19 -0
  93. package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +13 -0
  94. package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +29 -6
  95. package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +16 -0
  96. package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +5 -1
  97. package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +6 -2
  98. package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +7 -0
  99. package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +13 -5
  100. package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
  101. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +2 -2
  102. package/node_modules/@llblab/pi-telegram/docs/public-api.md +1 -1
  103. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +79 -1
  104. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +197 -0
  105. package/node_modules/@llblab/pi-telegram/lib/bus.ts +33 -0
  106. package/node_modules/@llblab/pi-telegram/lib/commands.ts +38 -6
  107. package/node_modules/@llblab/pi-telegram/lib/extension.ts +15 -0
  108. package/node_modules/@llblab/pi-telegram/lib/locks.ts +6 -1
  109. package/node_modules/@llblab/pi-telegram/lib/polling.ts +10 -2
  110. package/node_modules/@llblab/pi-telegram/lib/threads.ts +19 -5
  111. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  112. package/package.json +7 -3
@@ -1,6 +1,6 @@
1
1
  import { type ArtifactCompilationUpdate, type ArtifactModelHints, type ArtifactRegistry } from "./artifact.ts";
2
2
  import { type JsonObject } from "./json.ts";
3
- /** The canonical semantic state shape shared by global, CWD, and session scopes. */
3
+ /** Runtime defaults for documented semantic planes; stored objects may omit them or retain other fields. */
4
4
  export type MaterializedState = JsonObject & {
5
5
  intents: JsonObject;
6
6
  contract: JsonObject;
@@ -9,6 +9,16 @@ export type MaterializedState = JsonObject & {
9
9
  response: string;
10
10
  lazy: JsonObject;
11
11
  };
12
+ /** Sparse semantic state: documented planes may be absent. Disk codecs select only known fields. */
13
+ export type SemanticState = JsonObject & Partial<{
14
+ intents: JsonObject;
15
+ contract: JsonObject;
16
+ working: JsonObject;
17
+ artifacts: ArtifactRegistry;
18
+ response: string;
19
+ lazy: JsonObject;
20
+ }>;
21
+ export type ScopedSemanticStates = Record<StateScope, SemanticState>;
12
22
  /** Compatibility name for callers that still treat materialized state as a document. */
13
23
  export type StateDocument = MaterializedState;
14
24
  /** Model patch shape; artifact entries may be compiler outputs before trusted metadata is attached. */
@@ -52,11 +62,14 @@ export interface ScopedStates {
52
62
  }
53
63
  export declare function emptyState(): MaterializedState;
54
64
  export declare function isMaterializedState(value: unknown): value is MaterializedState;
65
+ /** Missing planes are valid storage, not missing authority. Present values retain their type checks. */
66
+ export declare function isSemanticState(value: unknown): value is SemanticState;
55
67
  export declare const isStateDocument: typeof isMaterializedState;
56
68
  /** Atomically replace compiled and removed artifacts inside one materialized scope. */
57
69
  export declare function updateMaterializedArtifacts(state: MaterializedState, updates: readonly ArtifactCompilationUpdate[], removed?: readonly string[]): MaterializedState;
58
70
  /** Overlay lower-to-higher scopes without mutating any scope document. */
59
- export declare function overlayStates(...scopes: readonly MaterializedState[]): MaterializedState;
71
+ export declare function overlayStates(...scopes: readonly JsonObject[]): MaterializedState;
72
+ /** Default-bearing SDK compatibility view; model transport uses sparse SemanticState instead. */
60
73
  export type ModelState = JsonObject & {
61
74
  intents: JsonObject;
62
75
  contract: JsonObject;
@@ -64,5 +77,11 @@ export type ModelState = JsonObject & {
64
77
  artifacts: ArtifactRegistry;
65
78
  response: string;
66
79
  };
80
+ /** Select only owned top-level fields, preserving nested data and replay deletion markers. */
81
+ export declare function selectSemanticFields(value: JsonObject): JsonObject;
82
+ /** Read only documented, present planes; empty responses carry no semantic value. */
83
+ export declare function projectSemanticState(state: JsonObject): SemanticState;
84
+ /** Preserve deletion meaning in visible history without exposing ignored fields or empty responses. */
85
+ export declare function projectSemanticPatch(patch: JsonObject): JsonObject;
67
86
  /** Model-visible projection: lazy bodies and runtime artifact bookkeeping stay out of ordinary context. */
68
- export declare function projectStateForModel(state: MaterializedState, artifactHints?: ArtifactModelHints): ModelState;
87
+ export declare function projectStateForModel(state: SemanticState, artifactHints?: ArtifactModelHints): SemanticState;
@@ -10,8 +10,11 @@ export function isMaterializedState(value) {
10
10
  && isObject(value.working)
11
11
  && isObject(value.intents)
12
12
  && typeof value.response === "string"
13
- && isObject(value.lazy)
14
- && Object.keys(value).every((key) => key === "artifacts" || key === "contract" || key === "working" || key === "intents" || key === "response" || key === "lazy");
13
+ && isObject(value.lazy);
14
+ }
15
+ /** Missing planes are valid storage, not missing authority. Present values retain their type checks. */
16
+ export function isSemanticState(value) {
17
+ return isObject(value) && isMaterializedState({ ...emptyState(), ...value });
15
18
  }
16
19
  export const isStateDocument = isMaterializedState;
17
20
  /** Atomically replace compiled and removed artifacts inside one materialized scope. */
@@ -27,14 +30,31 @@ export function overlayStates(...scopes) {
27
30
  return applyPatch(effective, scope);
28
31
  }, emptyState());
29
32
  }
33
+ /** Select only owned top-level fields, preserving nested data and replay deletion markers. */
34
+ export function selectSemanticFields(value) {
35
+ return structuredClone(Object.fromEntries(Object.keys(emptyState())
36
+ .filter((key) => Object.hasOwn(value, key))
37
+ .map((key) => [key, value[key]])));
38
+ }
39
+ /** Read only documented, present planes; empty responses carry no semantic value. */
40
+ export function projectSemanticState(state) {
41
+ const projected = selectSemanticFields(state);
42
+ if (projected.response === "")
43
+ delete projected.response;
44
+ return projected;
45
+ }
46
+ /** Preserve deletion meaning in visible history without exposing ignored fields or empty responses. */
47
+ export function projectSemanticPatch(patch) {
48
+ const projected = selectSemanticFields(patch);
49
+ if (projected.response === "")
50
+ projected.response = null;
51
+ return projected;
52
+ }
30
53
  /** Model-visible projection: lazy bodies and runtime artifact bookkeeping stay out of ordinary context. */
31
54
  export function projectStateForModel(state, artifactHints = {}) {
32
- const cloned = structuredClone(state);
33
- return {
34
- intents: cloned.intents,
35
- contract: cloned.contract,
36
- working: cloned.working,
37
- artifacts: projectArtifactsForModel(cloned.artifacts, artifactHints),
38
- response: cloned.response,
39
- };
55
+ const { lazy: _hidden, ...visible } = state;
56
+ const projected = projectSemanticState(visible);
57
+ if (projected.artifacts)
58
+ projected.artifacts = projectArtifactsForModel(projected.artifacts, artifactHints);
59
+ return projected;
40
60
  }
@@ -1,7 +1,7 @@
1
1
  import type { ArtifactInvalidationReason } from "./artifact.ts";
2
- import { type RecentTransitionWindow } from "./history.ts";
2
+ import type { RecentTransitionWindow } from "./history.ts";
3
3
  import type { Snapshot } from "./snapshot.ts";
4
- import { type ScopedStates, type StateScope } from "./state.ts";
4
+ import { type SemanticState, type ScopedStates, type StateScope } from "./state.ts";
5
5
  import type { ScopeRevisions, TransitionBoundary } from "./temporal.ts";
6
6
  export declare const STATUS_KEY = "state-flow";
7
7
  export type Colorize = (color: "accent" | "dim", text: string) => string;
@@ -16,6 +16,8 @@ export interface StatusDiagnostics {
16
16
  cwdScopeKey: string;
17
17
  sessionScopeKey: string;
18
18
  scopeStates: ScopedStates;
19
+ /** Overlay raw scopes before defaults so absent scalar planes cannot mask lower scopes. */
20
+ effectiveState?: SemanticState;
19
21
  recent: RecentTransitionWindow;
20
22
  historyLimit: number;
21
23
  temporal?: {
@@ -29,5 +31,5 @@ export interface StatusDiagnostics {
29
31
  publicationError?: string;
30
32
  }
31
33
  export declare function formatScopeRevisionVector(revisions: ScopeRevisions): string;
32
- export declare function compactStatus(snapshot: Snapshot, revisions: ScopeRevisions, colorize: Colorize): string | undefined;
34
+ export declare function compactStatus(snapshot: Snapshot, _revisions: ScopeRevisions, colorize: Colorize): string | undefined;
33
35
  export declare function detailedStatus(snapshot: Snapshot, diagnostics: StatusDiagnostics): string;
@@ -1,27 +1,26 @@
1
- import { projectRecentTransitionsWithLimit } from "./history.js";
2
- import { retainedMemoryScopes } from "./memory.js";
3
1
  import { conciseDiagnostic } from "./protocol.js";
4
- import { overlayStates } from "./state.js";
2
+ import { overlayStates, projectSemanticState } from "./state.js";
5
3
  export const STATUS_KEY = "state-flow";
6
4
  export function formatScopeRevisionVector(revisions) {
7
- return `G${revisions.global}/C${revisions.cwd}/S${revisions.session}`;
5
+ return `g${revisions.global}c${revisions.cwd}s${revisions.session}`;
8
6
  }
9
- export function compactStatus(snapshot, revisions, colorize) {
10
- if (!snapshot.config.enabled)
7
+ export function compactStatus(snapshot, _revisions, colorize) {
8
+ const { mode } = snapshot.config;
9
+ if (mode === "off")
11
10
  return undefined;
12
- return `${colorize("accent", "state-flow")} ${colorize("dim", formatScopeRevisionVector(revisions))}`;
11
+ return `${colorize("accent", "state-flow")} ${colorize("dim", mode)}`;
13
12
  }
14
13
  function countArtifacts(states, scope) {
15
14
  return Object.keys(states[scope].artifacts).length;
16
15
  }
17
16
  export function detailedStatus(snapshot, diagnostics) {
18
- const projectedRecent = projectRecentTransitionsWithLimit(diagnostics.historyLimit, diagnostics.recent);
19
17
  const available = diagnostics.temporal !== undefined && diagnostics.durableStateError === undefined;
20
- const materialized = !available ? undefined : overlayStates(diagnostics.scopeStates.global, diagnostics.scopeStates.cwd, diagnostics.scopeStates.session);
21
- const stateJson = materialized === undefined ? undefined : JSON.stringify(materialized, null, 2);
18
+ const materialized = !available ? undefined : diagnostics.effectiveState ?? projectSemanticState(overlayStates(diagnostics.scopeStates.global, diagnostics.scopeStates.cwd, diagnostics.scopeStates.session));
19
+ // Only top-level plane boundaries gain whitespace; nested user JSON stays unchanged.
20
+ const stateJson = materialized === undefined ? undefined : JSON.stringify(materialized, null, 2).replace(/,\n(?= ")/g, ",\n\n");
22
21
  const invalidated = available ? String(diagnostics.staleArtifacts.length) : "unavailable";
23
22
  const invalidationLines = diagnostics.staleArtifacts.length === 0
24
- ? ["Pending artifact invalidations: none"]
23
+ ? []
25
24
  : [
26
25
  "Pending artifact invalidations:",
27
26
  ...diagnostics.staleArtifacts.map(({ scope, path, reason }) => `- [${scope}] ${path} — ${reason}`),
@@ -29,29 +28,21 @@ export function detailedStatus(snapshot, diagnostics) {
29
28
  const temporal = available ? diagnostics.temporal : undefined;
30
29
  const temporalLines = temporal === undefined
31
30
  ? [`Temporal materialization unavailable: ${conciseDiagnostic(diagnostics.durableStateError ?? "no selected branch runtime")}`,
32
- `Hot history: unavailable; configured maximum depth ${diagnostics.historyLimit}`,
33
- "Retained patch tails: unavailable"]
34
- : [`Temporal head: ${JSON.stringify(temporal.head.id)}; branch-local position ${temporal.head.position}`,
35
- `Scope revisions: global #${temporal.revisions.global}; CWD #${temporal.revisions.cwd}; session #${temporal.revisions.session}; effective ${formatScopeRevisionVector(temporal.revisions)}`,
36
- `Hot history: offsets 0..${temporal.historyDepth}; maximum depth ${diagnostics.historyLimit}`,
37
- `Retained patch tails: global ${temporal.tailCounts.global}; CWD ${temporal.tailCounts.cwd}; session ${temporal.tailCounts.session}`];
38
- const artifacts = (scope) => available ? countArtifacts(diagnostics.scopeStates, scope) : "unknown";
39
- const memoryScopes = available ? retainedMemoryScopes(diagnostics.scopeStates) : undefined;
31
+ `Hot history: unavailable; configured maximum depth ${diagnostics.historyLimit}`]
32
+ : [`Scope revisions: ${formatScopeRevisionVector(temporal.revisions)}`,
33
+ `Runtime metadata: step #${snapshot.meta.step}${snapshot.meta.bootstrap ? "; bootstrap" : ""}`,
34
+ `Hot history: offsets 0..${temporal.historyDepth}; maximum depth ${diagnostics.historyLimit}`];
35
+ const artifacts = (scope) => countArtifacts(diagnostics.scopeStates, scope);
36
+ const hasArtifacts = available && ["global", "cwd", "session"].some((scope) => artifacts(scope) > 0);
40
37
  return [
41
- `State Flow diagnostics — config.enabled=${snapshot.config.enabled}; branch mode=${snapshot.config.enabled ? "active" : "inactive"}`,
42
38
  `Repository: ${diagnostics.repositoryRoot}`,
43
39
  `Scope keys: CWD ${diagnostics.cwdScopeKey}; session ${diagnostics.sessionScopeKey}`,
44
- "Session files: config.json owns behavior; runtime.json owns branch recovery; meta.json owns scope provenance",
45
- `Runtime metadata: step #${snapshot.meta.step}; bootstrap ${snapshot.meta.bootstrap === true}`,
46
- "Memory: owner state-flow; global retention enabled; global fallback active",
47
- `Memory-bearing scopes: global ${memoryScopes?.global ?? "unknown"}; CWD ${memoryScopes?.cwd ?? "unknown"}; session ${memoryScopes?.session ?? "unknown"}`,
48
40
  ...temporalLines,
49
- ...(diagnostics.publicationError === undefined ? [] : [`Memory writes paused after Stop: ${conciseDiagnostic(diagnostics.publicationError)}`]),
50
- `Artifacts: global ${artifacts("global")}; CWD ${artifacts("cwd")}; session ${artifacts("session")}; pending invalidations ${invalidated}`,
51
- available ? `Recent transitions: global ${diagnostics.recent.filter(({ transitions }) => transitions.some(({ scope }) => scope === "global")).length}; CWD ${diagnostics.recent.filter(({ transitions }) => transitions.some(({ scope }) => scope === "cwd")).length}; session ${diagnostics.recent.filter(({ transitions }) => transitions.some(({ scope }) => scope === "session")).length}; active ${projectedRecent.length}` : "Recent transitions: unavailable",
41
+ ...(diagnostics.publicationError === undefined ? [] : [`Memory writes paused after mode change: ${conciseDiagnostic(diagnostics.publicationError)}`]),
42
+ ...(hasArtifacts ? [`Artifacts: global ${artifacts("global")}; CWD ${artifacts("cwd")}; session ${artifacts("session")}; pending invalidations ${invalidated}`] : []),
52
43
  ...invalidationLines,
53
44
  ...(stateJson === undefined
54
45
  ? ["Effective memory: unavailable"]
55
- : [`Effective memory (${Buffer.byteLength(stateJson, "utf8")} JSON bytes; global → CWD → session overlay):`, "", stateJson]),
46
+ : ["Effective memory:", "", stateJson]),
56
47
  ].join("\n");
57
48
  }
@@ -1,9 +1,11 @@
1
+ import type { StateFlowMode } from "./snapshot.ts";
1
2
  import type { ScopeRevisions } from "./temporal.ts";
2
3
  export declare const STATE_FLOW_TELEGRAM_ID = "@llblab/pi-state-flow";
3
4
  /** Resolve the package export or the compiled sibling-extension layout used in local development. */
4
5
  export declare function stateFlowTelegramSectionSpecifiers(moduleUrl?: string): string[];
5
6
  export interface StateFlowTelegramSnapshot {
6
- enabled: boolean;
7
+ /** The current session's selected mode. */
8
+ mode: StateFlowMode;
7
9
  /** Legacy branch step retained for existing adapter ports; current runtime ports also supply owner revisions. */
8
10
  step: number;
9
11
  revisions?: ScopeRevisions;
@@ -12,11 +14,11 @@ export interface StateFlowTelegramSnapshot {
12
14
  }
13
15
  export type StateFlowTelegramScope = "global" | "cwd" | "session" | "effective";
14
16
  export interface StateFlowTelegramState {
15
- artifacts: Record<string, unknown>;
16
- contract: Record<string, unknown>;
17
- working: Record<string, unknown>;
18
- intents: Record<string, unknown>;
19
- response: string;
17
+ artifacts?: Record<string, unknown>;
18
+ contract?: Record<string, unknown>;
19
+ working?: Record<string, unknown>;
20
+ intents?: Record<string, unknown>;
21
+ response?: string;
20
22
  lazy?: unknown;
21
23
  }
22
24
  export type StateFlowTelegramRichText = string | StateFlowTelegramRichText[] | {
@@ -92,26 +94,26 @@ export interface StateFlowTelegramPort {
92
94
  state(scope: StateFlowTelegramScope): StateFlowTelegramState;
93
95
  /** Optional additive capability; absent legacy ports retain their branch-step presentation. */
94
96
  revisions?(): ScopeRevisions;
97
+ /** Active may need a settled native boundary; inactive modes apply immediately. */
95
98
  canStartNow(): boolean;
96
- start(): StateFlowTelegramControlResult;
97
- stop(): StateFlowTelegramControlResult;
99
+ /** Select the current session's mode through the same lifecycle owners as the terminal commands. */
100
+ select(mode: StateFlowMode): StateFlowTelegramControlResult;
98
101
  deferStart(): void;
99
102
  cancelStart(): void;
100
103
  }
101
- export interface StateFlowTelegramInspectionPort extends Omit<StateFlowTelegramPort, "state" | "revisions" | "start" | "stop"> {
104
+ export interface StateFlowTelegramInspectionPort extends Omit<StateFlowTelegramPort, "state" | "revisions" | "select"> {
102
105
  inspect(scope: StateFlowTelegramScope): StateFlowTelegramInspection | Promise<StateFlowTelegramInspection>;
103
- start(): StateFlowTelegramControlResult | Promise<StateFlowTelegramControlResult>;
104
- stop(): StateFlowTelegramControlResult | Promise<StateFlowTelegramControlResult>;
106
+ select(mode: StateFlowMode): StateFlowTelegramControlResult | Promise<StateFlowTelegramControlResult>;
105
107
  }
106
108
  export interface StateFlowTelegramAdapter {
107
109
  ensure(): Promise<boolean>;
108
110
  dispose(): void;
109
111
  }
110
- /** Main-menu section label doubles as the live status value: the spiral identity is constant, the value is not. */
112
+ /** Main-menu section label shows only the current session mode. */
111
113
  export declare function formatStateFlowSectionLabel(snapshot: StateFlowTelegramSnapshot): string;
112
- /** The submenu header repeats the button's state line; the single action matches the current state. */
113
- export declare function buildStateFlowSectionView(snapshot: StateFlowTelegramSnapshot, callbackData: (action: string) => string): StateFlowTelegramView;
114
- export declare function buildStateFlowScopeChooser(callbackData: (action: string, payload?: string) => string): StateFlowTelegramView;
114
+ export declare const STATE_FLOW_MODES: readonly ["off", "passive", "active"];
115
+ /** One radio-style mode row followed directly by read-only scope actions. */
116
+ export declare function buildStateFlowSectionView(snapshot: StateFlowTelegramSnapshot, callbackData: (action: string, payload?: string) => string): StateFlowTelegramView;
115
117
  export declare function renderStateFlowRichState(scope: StateFlowTelegramScope, revisions: ScopeRevisions, state: StateFlowTelegramState): StateFlowTelegramRichMessage;
116
118
  /** Default loader; injectable so tests and embedded hosts can control transport presence. */
117
119
  export declare function loadStateFlowTelegramModules(): Promise<StateFlowTelegramModules>;
@@ -20,35 +20,50 @@ export function stateFlowTelegramSectionSpecifiers(moduleUrl = import.meta.url)
20
20
  new URL("../../../pi-telegram/dist/api/sections.js", moduleUrl).href,
21
21
  ];
22
22
  }
23
- /** Main-menu section label doubles as the live status value: the spiral identity is constant, the value is not. */
23
+ /** Main-menu section label shows only the current session mode. */
24
24
  export function formatStateFlowSectionLabel(snapshot) {
25
- if (!snapshot.enabled)
26
- return "🌀 State Flow: off";
27
- return `🌀 State Flow: ${snapshot.revisions ? formatScopeRevisionVector(snapshot.revisions) : `#${snapshot.step}`}`;
25
+ return `🌀 State Flow: ${snapshot.mode}`;
28
26
  }
29
- /** Shared live value: plain in the button label, monospaced in the submenu state line. */
30
- function stateFlowLabelValue(snapshot) {
31
- if (!snapshot.enabled)
32
- return "off";
33
- return snapshot.revisions ? formatScopeRevisionVector(snapshot.revisions) : `#${snapshot.step}`;
27
+ export const STATE_FLOW_MODES = ["off", "passive", "active"];
28
+ const STATE_FLOW_MODE_LABELS = { off: "Off", passive: "Passive", active: "Active" };
29
+ const STATE_FLOW_SELECTED_MARKERS = { off: "🟡", passive: "🟣", active: "🟢" };
30
+ function isStateFlowModeAction(value) {
31
+ return STATE_FLOW_MODES.includes(value);
34
32
  }
35
- /** Submenu state line: the same identity as the button label, with the live value in monospace. */
36
- function formatStateFlowSectionHeader(snapshot) {
37
- return `<b>🌀 State Flow: <code>${stateFlowLabelValue(snapshot)}</code></b>`;
33
+ function modeReceiptNotice(mode, result) {
34
+ if (result.ok && (result.message === `State Flow ${mode}` || result.message === `State Flow is already ${mode}`))
35
+ return undefined;
36
+ return result.message;
38
37
  }
39
- /** Short help under the state line: what State Flow is and why its action button exists. */
40
- const STATE_FLOW_SECTION_HELP = "Accepted memory remains visible in active and passive modes. Start or Stop changes episode behavior, not state access.";
41
- /** The submenu header repeats the button's state line; the single action matches the current state. */
38
+ /** One radio-style mode row followed directly by read-only scope actions. */
42
39
  export function buildStateFlowSectionView(snapshot, callbackData) {
43
- const action = snapshot.enabled
44
- ? { text: "⏹ Stop", callback_data: callbackData("stop") }
45
- : { text: "▶️ Start", callback_data: callbackData("start") };
40
+ const modes = STATE_FLOW_MODES.map((mode) => ({
41
+ text: `${mode === snapshot.mode ? STATE_FLOW_SELECTED_MARKERS[mode] : "⚫️"} ${STATE_FLOW_MODE_LABELS[mode]}`,
42
+ callback_data: callbackData(mode),
43
+ }));
46
44
  return {
47
- text: [formatStateFlowSectionHeader(snapshot), "", STATE_FLOW_SECTION_HELP].join("\n"),
45
+ text: [
46
+ `<b>🌀 State Flow:</b> <code>${snapshot.mode}</code>`,
47
+ "",
48
+ "<b>Mode</b> — choose a workflow (switching modes never erases stored memory):",
49
+ "",
50
+ "<code>-</code> <code>off</code> (default): regular chat without State Flow memory tools or context.",
51
+ "<code>-</code> <code>passive</code>: regular chat with memory tools; available combined memory enters the agent's context.",
52
+ "<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.",
53
+ "",
54
+ "<b>Inspect memory</b> — view stored state even in Off:",
55
+ "",
56
+ "<code>-</code> <code>global</code>: memory shared across projects and sessions.",
57
+ "<code>-</code> <code>cwd</code>: memory shared by sessions in this directory.",
58
+ "<code>-</code> <code>session</code>: private memory for this session, kept on resume.",
59
+ "<code>-</code> <code>effective</code>: merged Global, CWD and Session state; the agent can use it when memory is enabled and available.",
60
+ ].join("\n"),
48
61
  parseMode: "html",
49
62
  replyMarkup: { inline_keyboard: [
50
- [action],
51
- [{ text: "👁 Show state", callback_data: callbackData("show-state") }],
63
+ modes,
64
+ ...[["global", "cwd"], ["session", "effective"]].map((row) => row.map((scope) => ({
65
+ text: STATE_FLOW_SCOPE_LABELS[scope], callback_data: callbackData("inspect", scope),
66
+ }))),
52
67
  ] },
53
68
  };
54
69
  }
@@ -58,17 +73,6 @@ const STATE_FLOW_SCOPE_LABELS = {
58
73
  session: "💬 Session",
59
74
  effective: "🧬 Effective",
60
75
  };
61
- export function buildStateFlowScopeChooser(callbackData) {
62
- return {
63
- text: "<b>👁 Show state:</b>",
64
- parseMode: "html",
65
- replyMarkup: { inline_keyboard: [
66
- ...["global", "cwd", "session", "effective"].map((scope) => [
67
- { text: STATE_FLOW_SCOPE_LABELS[scope], callback_data: callbackData("inspect", scope) },
68
- ]),
69
- ] },
70
- };
71
- }
72
76
  // The complete message serializes each preformatted field one additional time;
73
77
  // 3,000 leaves safe headroom for worst-case JSON escaping across all four fields.
74
78
  const STATE_FLOW_TELEGRAM_FIELD_MAX_CHARS = 3_000;
@@ -113,10 +117,10 @@ export function renderStateFlowRichState(scope, revisions, state) {
113
117
  text: [`${STATE_FLOW_SCOPE_LABELS[scope]}: `, { type: "code", text: revision }],
114
118
  size: 3,
115
119
  },
116
- ...fields.map((field) => ({
120
+ ...fields.filter((field) => state[field] !== undefined && state[field] !== "").map((field) => ({
117
121
  type: "details",
118
122
  summary: { type: "code", text: field },
119
- blocks: [{ type: "pre", language: "json", text: renderStateFlowTelegramField(state[field] ?? {}) }],
123
+ blocks: [{ type: "pre", language: "json", text: renderStateFlowTelegramField(state[field]) }],
120
124
  })),
121
125
  ],
122
126
  skip_entity_detection: true,
@@ -131,20 +135,16 @@ function buildStateFlowTelegramSection(port, isActive) {
131
135
  id: STATE_FLOW_TELEGRAM_ID,
132
136
  label: "🌀 State Flow",
133
137
  getLabel: () => formatStateFlowSectionLabel(port.snapshot()),
134
- render: (ctx) => buildStateFlowSectionView(port.snapshot(), (action) => ctx.callbackData(action)),
138
+ render: (ctx) => buildStateFlowSectionView(port.snapshot(), (action, payload) => ctx.callbackData(action, payload)),
135
139
  handleCallback: async (ctx) => {
136
- // cancel/refresh remain routable for keyboards sent by earlier versions.
137
- if (ctx.action !== "start" && ctx.action !== "stop" && ctx.action !== "cancel" && ctx.action !== "refresh" && ctx.action !== "show-state" && ctx.action !== "inspect" && ctx.action !== "back")
140
+ // Keyboards sent by earlier versions re-render (start/stop/refresh) or withdraw deferral (cancel); they change no mode.
141
+ const legacy = ctx.action === "start" || ctx.action === "stop" || ctx.action === "cancel" || ctx.action === "refresh";
142
+ if (!isStateFlowModeAction(ctx.action) && !legacy && ctx.action !== "show-state" && ctx.action !== "inspect" && ctx.action !== "back")
138
143
  return "pass";
139
144
  const request = ++interaction;
140
145
  let notice;
141
146
  let acknowledged = false;
142
147
  try {
143
- if (ctx.action === "show-state") {
144
- await ctx.answerCallback();
145
- await ctx.edit(buildStateFlowScopeChooser((action, payload) => ctx.callbackData(action, payload)));
146
- return "handled";
147
- }
148
148
  if (ctx.action === "inspect") {
149
149
  if (!isStateFlowTelegramScope(ctx.payload))
150
150
  throw new Error("Unknown State Flow scope");
@@ -167,25 +167,25 @@ function buildStateFlowTelegramSection(port, isActive) {
167
167
  await ctx.answerCallback();
168
168
  return "handled";
169
169
  }
170
- const action = ctx.action === "stop" || (ctx.action === "start" && port.canStartNow()) ? ctx.action : undefined;
171
- if (action) {
170
+ const mode = isStateFlowModeAction(ctx.action) && (ctx.action !== "active" || port.canStartNow()) ? ctx.action : undefined;
171
+ if (mode) {
172
172
  if ("inspect" in port) {
173
173
  acknowledged = true;
174
- // Start the control immediately and acknowledge in parallel; neither promise can reject unobserved.
174
+ // Apply the control immediately and acknowledge in parallel; neither promise can reject unobserved.
175
175
  const [, result] = await Promise.all([
176
- ctx.answerCallback(action === "stop" ? "Stopping State Flow" : "Starting State Flow"),
177
- Promise.resolve().then(() => port[action]()),
176
+ ctx.answerCallback(`Switching State Flow to ${mode}`),
177
+ Promise.resolve().then(() => port.select(mode)),
178
178
  ]);
179
179
  if (result.signal?.aborted)
180
180
  return "handled";
181
- notice = result.message;
181
+ notice = modeReceiptNotice(mode, result);
182
182
  }
183
183
  else
184
- notice = port[action]().message;
184
+ notice = modeReceiptNotice(mode, port.select(mode));
185
185
  }
186
- else if (ctx.action === "start") {
186
+ else if (ctx.action === "active") {
187
187
  port.deferStart();
188
- notice = "State Flow will start after the current turn";
188
+ notice = "State Flow will become active after the current turn";
189
189
  }
190
190
  else if (ctx.action === "cancel") {
191
191
  port.cancelStart();
@@ -198,7 +198,7 @@ function buildStateFlowTelegramSection(port, isActive) {
198
198
  if (request !== interaction || !isActive())
199
199
  return "handled";
200
200
  const summary = notice === undefined ? undefined : conciseDiagnostic(notice, 200);
201
- const view = buildStateFlowSectionView(port.snapshot(), (action) => ctx.callbackData(action));
201
+ const view = buildStateFlowSectionView(port.snapshot(), (action, payload) => ctx.callbackData(action, payload));
202
202
  if (acknowledged && summary !== undefined) {
203
203
  // Callback queries can expire during storage waits; retain errors in the existing menu instead.
204
204
  view.text += `\n\n${summary.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")}`;
@@ -1,5 +1,5 @@
1
1
  import { type RecentScopePatch } from "./history.ts";
2
- import { type MaterializedState, type ScopedStates, type StateScope } from "./state.ts";
2
+ import { type MaterializedState, type SemanticState, type ScopedSemanticStates, type StateScope } from "./state.ts";
3
3
  /** Owns hot temporal algebra; excludes filesystem, Git, identity allocation, and Pi lifecycle. */
4
4
  export interface TransitionBoundary {
5
5
  id: string;
@@ -9,7 +9,7 @@ export interface TransitionBoundary {
9
9
  }
10
10
  export interface ScopeCheckpoint {
11
11
  through: TransitionBoundary;
12
- state: MaterializedState;
12
+ state: SemanticState;
13
13
  }
14
14
  export interface TemporalPatch {
15
15
  transition: TransitionBoundary;
@@ -37,7 +37,7 @@ export declare function validateTemporalState(view: TemporalState, historyLimit?
37
37
  /** Adopt revision-proven inherited streams without rewriting their checkpoints or tails. */
38
38
  export declare function adoptTemporalStreams(scopes: Record<StateScope, ScopeStream>, id: string, historyLimit?: number): TemporalState;
39
39
  /** New or migrated state starts at a proven current boundary, with no invented past. */
40
- export declare function createTemporalState(states: ScopedStates, id: string, historyLimit?: number): TemporalState;
40
+ export declare function createTemporalState(states: ScopedSemanticStates, id: string, historyLimit?: number): TemporalState;
41
41
  /** Fold retained tails to a lower configured limit without inventing history. */
42
42
  export declare function constrainTemporalState(view: TemporalState, historyLimit: number): TemporalState;
43
43
  /** Select one scope at a proven retained boundary from its owning runtime lineage. */
@@ -46,7 +46,11 @@ export declare function selectScopeStreamAtBoundary(stream: ScopeStream, scope:
46
46
  export declare function selectTemporalStateBoundary(view: TemporalState, boundaryId: string, historyLimit?: number): TemporalState;
47
47
  /** Current independent scope revisions; Effective uses this vector rather than inventing a scalar owner. */
48
48
  export declare function temporalScopeRevisions(view: TemporalState): ScopeRevisions;
49
- /** Lazy scope/effective read at one shared transition boundary, never by local patch count. */
49
+ /** Exact scope semantics for authored staging; defaults must never become implicit writes. */
50
+ export declare function readTemporalScopes(view: TemporalState, offset?: number, historyLimit?: number): ScopedSemanticStates;
51
+ /** Sparse current/historical view: unknown planes and absent values never become effective data. */
52
+ export declare function readTemporalView(view: TemporalState, offset?: number, scope?: StateScope, historyLimit?: number): SemanticState;
53
+ /** Internal defaulted materialization for consumers that require object registries. */
50
54
  export declare function readTemporalState(view: TemporalState, offset?: number, scope?: StateScope, historyLimit?: number): MaterializedState;
51
55
  /** Allocate the identity outside this algebra; only materially effective patches accept it. */
52
56
  export declare function advanceTemporalState(view: TemporalState, transitions: readonly RecentScopePatch[], id: string, historyLimit?: number): TemporalState;
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_HISTORY_LIMIT, MAX_HISTORY_LIMIT, validateRecentTransition } from "./history.js";
2
2
  import { applyPatch, containsNull, isJsonValue, isObject, sameJson } from "./json.js";
3
- import { isMaterializedState, overlayStates } from "./state.js";
3
+ import { emptyState, isSemanticState, overlayStates, projectSemanticState } from "./state.js";
4
4
  const SCOPES = ["global", "cwd", "session"];
5
5
  function validateHistoryLimit(limit) {
6
6
  if (!Number.isSafeInteger(limit) || limit < 0 || limit > MAX_HISTORY_LIMIT) {
@@ -16,14 +16,20 @@ function validateBoundary(boundary) {
16
16
  throw new Error("Invalid State Flow temporal boundary");
17
17
  }
18
18
  }
19
- function validateState(state) {
20
- if (!isJsonValue(state) || !isMaterializedState(state) || containsNull(state)) {
21
- throw new Error("Invalid temporal materialized semantic state");
22
- }
19
+ function validateState(state, location) {
20
+ const json = isJsonValue(state);
21
+ const hasNull = json && isObject(state) && Object.keys(emptyState()).some((key) => containsNull(state[key]));
22
+ if (json && isSemanticState(state) && !hasNull)
23
+ return;
24
+ const reason = !json ? "expected finite, acyclic JSON data"
25
+ : !isObject(state) ? "expected a semantic object"
26
+ : hasNull ? "null is not allowed"
27
+ : "invalid semantic fields or artifact metadata";
28
+ throw new Error(`Invalid temporal materialized semantic state${location ? ` in ${location}` : ""}: ${reason}`);
23
29
  }
24
- function apply(state, patch) {
30
+ function apply(state, patch, location) {
25
31
  const next = applyPatch(state, patch);
26
- validateState(next);
32
+ validateState(next, location);
27
33
  return next;
28
34
  }
29
35
  function sameBoundary(left, right) {
@@ -42,7 +48,7 @@ export function validateScopeStream(value, scope, historyLimit = DEFAULT_HISTORY
42
48
  }
43
49
  const stream = value;
44
50
  validateBoundary(stream.checkpoint.through);
45
- validateState(stream.checkpoint.state);
51
+ validateState(stream.checkpoint.state, `${scope} checkpoint`);
46
52
  if (stream.patches.length > historyLimit)
47
53
  throw new Error(`Temporal scope tail exceeds configured history limit ${historyLimit}`);
48
54
  if (stream.revision < stream.patches.length)
@@ -62,9 +68,7 @@ export function validateScopeStream(value, scope, historyLimit = DEFAULT_HISTORY
62
68
  throw new Error("Disconnected State Flow temporal ancestry");
63
69
  }
64
70
  validateRecentTransition({ id: record.transition.id, at: 0, transitions: [{ scope, patch: record.patch }] });
65
- const next = apply(state, record.patch);
66
- if (sameJson(next, state))
67
- throw new Error("Temporal scope tail contains a semantic no-op");
71
+ const next = apply(state, record.patch, `${scope} tail`);
68
72
  state = next;
69
73
  previous = record.transition;
70
74
  identities.add(previous.id);
@@ -244,21 +248,33 @@ export function temporalScopeRevisions(view) {
244
248
  }
245
249
  return revisions;
246
250
  }
247
- /** Lazy scope/effective read at one shared transition boundary, never by local patch count. */
248
- export function readTemporalState(view, offset = 0, scope, historyLimit = DEFAULT_HISTORY_LIMIT) {
251
+ function readBoundary(view, offset, historyLimit) {
249
252
  validateHistoryLimit(historyLimit);
250
253
  if (!Number.isSafeInteger(offset) || offset < 0 || offset > historyLimit) {
251
254
  throw new Error(`State Flow hot-history offset must be an integer from 0 to ${historyLimit}`);
252
255
  }
253
- if (scope !== undefined && !SCOPES.includes(scope))
254
- throw new Error("Unknown temporal scope");
255
256
  validateTemporalState(view, historyLimit);
256
257
  const boundary = view.lineage[view.lineage.length - 1 - offset];
257
258
  if (!boundary)
258
259
  throw new Error("Requested history predates the proven temporal origin");
259
- if (scope !== undefined)
260
- return scopeAt(view.scopes[scope], boundary);
261
- return overlayStates(...SCOPES.map((owner) => scopeAt(view.scopes[owner], boundary)));
260
+ return boundary;
261
+ }
262
+ /** Exact scope semantics for authored staging; defaults must never become implicit writes. */
263
+ export function readTemporalScopes(view, offset = 0, historyLimit = DEFAULT_HISTORY_LIMIT) {
264
+ const boundary = readBoundary(view, offset, historyLimit);
265
+ return { global: scopeAt(view.scopes.global, boundary), cwd: scopeAt(view.scopes.cwd, boundary), session: scopeAt(view.scopes.session, boundary) };
266
+ }
267
+ /** Sparse current/historical view: unknown planes and absent values never become effective data. */
268
+ export function readTemporalView(view, offset = 0, scope, historyLimit = DEFAULT_HISTORY_LIMIT) {
269
+ if (scope !== undefined && !SCOPES.includes(scope))
270
+ throw new Error("Unknown temporal scope");
271
+ const boundary = readBoundary(view, offset, historyLimit);
272
+ const owners = scope === undefined ? SCOPES : [scope];
273
+ return owners.reduce((state, owner) => applyPatch(state, projectSemanticState(scopeAt(view.scopes[owner], boundary))), {});
274
+ }
275
+ /** Internal defaulted materialization for consumers that require object registries. */
276
+ export function readTemporalState(view, offset = 0, scope, historyLimit = DEFAULT_HISTORY_LIMIT) {
277
+ return overlayStates(readTemporalView(view, offset, scope, historyLimit));
262
278
  }
263
279
  /** Allocate the identity outside this algebra; only materially effective patches accept it. */
264
280
  export function advanceTemporalState(view, transitions, id, historyLimit = DEFAULT_HISTORY_LIMIT) {
@@ -3,9 +3,9 @@ import type { SuccessfulArtifactRead } from "./acquisition.ts";
3
3
  import { type AcceptedTransition } from "./history.ts";
4
4
  import { type SuccessfulSkillRead } from "./skills.ts";
5
5
  import type { Snapshot } from "./snapshot.ts";
6
- import type { AtomicScopePatches, ScopedStates, StateScope, TerminalTransition } from "./state.ts";
6
+ import type { AtomicScopePatches, ScopedSemanticStates, StateScope, TerminalTransition } from "./state.ts";
7
7
  export interface StagedScopedTransition {
8
- nextStates: ScopedStates;
8
+ nextStates: ScopedSemanticStates;
9
9
  stateHashes: Record<StateScope, string>;
10
10
  /** Fresh runtime-owned provenance for artifacts compiled in this transition. */
11
11
  provenanceUpdates: Record<StateScope, Record<string, ArtifactProvenance>>;
@@ -13,11 +13,11 @@ export interface StagedScopedTransition {
13
13
  committed: boolean;
14
14
  }
15
15
  /** Stage one canonical atomic scope cohort without changing the finalized response. */
16
- export declare function stageAtomicScopePatches(currentStates: ScopedStates, patches: AtomicScopePatches, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedScopedTransition;
17
- export declare function stageScopedTransition(currentStates: ScopedStates, transition: TerminalTransition, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedScopedTransition;
16
+ export declare function stageAtomicScopePatches(currentStates: ScopedSemanticStates, patches: AtomicScopePatches, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedScopedTransition;
17
+ export declare function stageScopedTransition(currentStates: ScopedSemanticStates, transition: TerminalTransition, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedScopedTransition;
18
18
  /** Commit one accepted transition; durable publication receives all changed scopes as one cohort. */
19
19
  export interface CommitScopedTransitionOptions {
20
20
  /** Runtime response reconciliation finalizes bootstrap lifecycle state. */
21
21
  finalizeRun?: boolean;
22
22
  }
23
- export declare function commitScopedTransition(snapshot: Snapshot, states: ScopedStates, stage: StagedScopedTransition, publishDurable: (accepted: AcceptedTransition | undefined, nextSnapshot: Snapshot) => void, causalBasis: string, options?: CommitScopedTransitionOptions): boolean;
23
+ export declare function commitScopedTransition(snapshot: Snapshot, states: ScopedSemanticStates, stage: StagedScopedTransition, publishDurable: (accepted: AcceptedTransition | undefined, nextSnapshot: Snapshot) => void, causalBasis: string, options?: CommitScopedTransitionOptions): boolean;