@llblab/pi-kit 0.28.0 → 0.29.1

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 (38) hide show
  1. package/BACKLOG.md +3 -1
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +3 -3
  4. package/node_modules/@llblab/pi-state-flow/AGENTS.md +2 -2
  5. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +1 -29
  6. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +12 -0
  7. package/node_modules/@llblab/pi-state-flow/README.md +7 -8
  8. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +94 -47
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +1 -1
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +2 -2
  11. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +8 -27
  12. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +16 -151
  13. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +3 -4
  14. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +4 -3
  15. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +1 -1
  16. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +4 -1
  17. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +2 -0
  18. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +6 -2
  19. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +0 -4
  20. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +0 -36
  21. package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
  22. package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +1 -1
  23. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +20 -31
  24. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +8 -9
  25. package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +4 -4
  26. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +18 -23
  27. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +19 -21
  28. package/node_modules/@llblab/pi-state-flow/docs/usage.md +26 -27
  29. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +89 -48
  30. package/node_modules/@llblab/pi-state-flow/lib/logging.ts +1 -1
  31. package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +2 -2
  32. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +22 -146
  33. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +6 -3
  34. package/node_modules/@llblab/pi-state-flow/lib/status.ts +4 -2
  35. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +8 -2
  36. package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +0 -36
  37. package/node_modules/@llblab/pi-state-flow/package.json +1 -1
  38. package/package.json +2 -2
@@ -9,8 +9,6 @@ const MAX_LEGACY_VALIDATION_ATTEMPT = 7;
9
9
  /** Missing operational capability is not evidence that a checkpoint target is invalid. */
10
10
  export class RevisionUnavailableError extends Error {}
11
11
 
12
- /** Expired history cannot be restored, but explicit activation may use validated current memory. */
13
- export class HistoryBoundaryExpiredError extends RevisionUnavailableError {}
14
12
 
15
13
  export type StateFlowMode = "active" | "passive" | "off";
16
14
  export type InactiveMode = Exclude<StateFlowMode, "active">;
@@ -57,6 +55,11 @@ export interface StateFlowSnapshot {
57
55
 
58
56
  export type Snapshot = StateFlowSnapshot;
59
57
 
58
+ /** Failed Active selection retains its policy and fences inference until explicit recovery or an inactive choice. */
59
+ export function isActiveRestorationBlocked(snapshot: Snapshot): boolean {
60
+ return snapshot.config.mode === "active" && snapshot.meta.validation?.attempt === 0;
61
+ }
62
+
60
63
  export interface SessionRuntime {
61
64
  config: SnapshotConfig;
62
65
  meta: SnapshotMeta & {
@@ -249,7 +252,7 @@ export function parseRetainedPiCheckpoint(value: unknown, inactiveMode: Inactive
249
252
  };
250
253
  }
251
254
 
252
- export function migrationFailure(data: JsonObject, error: string, mode: InactiveMode = "passive"): Snapshot {
255
+ export function migrationFailure(data: JsonObject, error: string, mode: StateFlowMode = "passive"): Snapshot {
253
256
  const meta = restoredMeta(data.meta, data);
254
257
  meta.validation = {
255
258
  attempt: 0,
@@ -2,7 +2,7 @@ import type { ArtifactInvalidationReason } from "./artifact.ts";
2
2
  import type { RecentTransitionWindow } from "./history.ts";
3
3
  import { ownedTopLevelKeys } from "./ownership.ts";
4
4
  import { conciseDiagnostic } from "./protocol.ts";
5
- import type { Snapshot } from "./snapshot.ts";
5
+ import { isActiveRestorationBlocked, type Snapshot } from "./snapshot.ts";
6
6
  import { overlayStates, projectSemanticState, type SemanticState, type ScopedStates, type StateScope } from "./state.ts";
7
7
  import type { ScopeRevisions, TransitionBoundary } from "./temporal.ts";
8
8
 
@@ -40,7 +40,7 @@ export function formatScopeRevisionVector(revisions: ScopeRevisions): string {
40
40
  export function compactStatus(snapshot: Snapshot, _revisions: ScopeRevisions, colorize: Colorize): string | undefined {
41
41
  const { mode } = snapshot.config;
42
42
  if (mode === "off") return undefined;
43
- return `${colorize("accent", "state-flow")} ${colorize("dim", mode)}`;
43
+ return `${colorize("accent", "state-flow")} ${colorize("dim", isActiveRestorationBlocked(snapshot) ? "active (blocked)" : mode)}`;
44
44
  }
45
45
 
46
46
  function countArtifacts(states: ScopedStates, scope: StateScope): number {
@@ -101,6 +101,8 @@ export function detailedStatus(snapshot: Snapshot, diagnostics: StatusDiagnostic
101
101
  const hasArtifacts = available && (["global", "cwd", "session"] as const).some((scope) => artifacts(scope) > 0);
102
102
 
103
103
  return [
104
+ `Mode: ${snapshot.config.mode}`,
105
+ ...(isActiveRestorationBlocked(snapshot) ? ["Inference blocked: Active memory restoration failed. Use /state-flow-active for current memory or select Passive/Off for native context."] : []),
104
106
  `Repository: ${diagnostics.repositoryRoot}`,
105
107
  `Scope keys: CWD ${diagnostics.cwdScopeKey}; session ${diagnostics.sessionScopeKey}`,
106
108
  ...temporalLines,
@@ -21,6 +21,8 @@ export function stateFlowTelegramSectionSpecifiers(moduleUrl = import.meta.url):
21
21
  export interface StateFlowTelegramSnapshot {
22
22
  /** The current session's selected mode. */
23
23
  mode: StateFlowMode;
24
+ /** Failed Active restoration fences inference without silently selecting an inactive mode. */
25
+ inferenceBlocked?: boolean;
24
26
  /** Legacy branch step retained for existing adapter ports; current runtime ports also supply owner revisions. */
25
27
  step: number;
26
28
  revisions?: ScopeRevisions;
@@ -132,12 +134,12 @@ export interface StateFlowTelegramAdapter {
132
134
 
133
135
  /** Main-menu section label shows only the current session mode. */
134
136
  export function formatStateFlowSectionLabel(snapshot: StateFlowTelegramSnapshot): string {
135
- return `🌀 State Flow: ${snapshot.mode}`;
137
+ return `🌀 State Flow: ${snapshot.mode}${snapshot.mode === "active" && snapshot.inferenceBlocked ? " (blocked)" : ""}`;
136
138
  }
137
139
 
138
140
  export const STATE_FLOW_MODES = ["off", "passive", "active"] as const satisfies readonly StateFlowMode[];
139
141
  const STATE_FLOW_MODE_LABELS: Record<StateFlowMode, string> = { off: "Off", passive: "Passive", active: "Active" };
140
- const STATE_FLOW_SELECTED_MARKERS: Record<StateFlowMode, string> = { off: "🟡", passive: "🟣", active: "🟢" };
142
+ const STATE_FLOW_SELECTED_MARKERS: Record<StateFlowMode, string> = { off: "🟣", passive: "🟡", active: "🟢" };
141
143
 
142
144
  function isStateFlowModeAction(value: string): value is StateFlowMode {
143
145
  return (STATE_FLOW_MODES as readonly string[]).includes(value);
@@ -160,6 +162,10 @@ export function buildStateFlowSectionView(
160
162
  return {
161
163
  text: [
162
164
  `<b>🌀 State Flow:</b> <code>${snapshot.mode}</code>`,
165
+ ...(snapshot.mode === "active" && snapshot.inferenceBlocked ? [
166
+ "",
167
+ "<b>Inference blocked:</b> Active memory restoration failed. Select Active to accept current session memory, or Passive/Off to permit native context.",
168
+ ] : []),
163
169
  "",
164
170
  "<b>Mode</b> — choose a workflow (switching modes never erases stored memory):",
165
171
  "",
@@ -235,42 +235,6 @@ export function constrainTemporalState(view: TemporalState, historyLimit: number
235
235
  return next;
236
236
  }
237
237
 
238
- /** Select one scope at a proven retained boundary from its owning runtime lineage. */
239
- export function selectScopeStreamAtBoundary(stream: ScopeStream, scope: StateScope, boundary: TransitionBoundary, historyLimit = DEFAULT_HISTORY_LIMIT): ScopeStream {
240
- validateHistoryLimit(historyLimit);
241
- validateBoundary(boundary);
242
- validateScopeStream(stream, scope, historyLimit);
243
- if (boundary.position < stream.checkpoint.through.position) {
244
- throw new Error("Selected State Flow history boundary predates the retained scope checkpoint");
245
- }
246
- const selected = structuredClone(stream);
247
- const retained = selected.patches.filter(({ transition }) => transition.position <= boundary.position);
248
- selected.revision -= selected.patches.length - retained.length;
249
- selected.patches = retained;
250
- validateScopeStream(selected, scope, historyLimit);
251
- return selected;
252
- }
253
-
254
- /** Select one still-retained causal boundary without consulting an external history store. */
255
- export function selectTemporalStateBoundary(view: TemporalState, boundaryId: string, historyLimit = DEFAULT_HISTORY_LIMIT): TemporalState {
256
- validateHistoryLimit(historyLimit);
257
- validateTemporalState(view, historyLimit);
258
- if (typeof boundaryId !== "string" || boundaryId.trim().length === 0) throw new Error("State Flow temporal boundary identity must be non-empty");
259
- const index = view.lineage.findIndex(({ id }) => id === boundaryId);
260
- if (index < 0) throw new Error("Selected State Flow history boundary is outside the retained temporal window");
261
- const target = view.lineage[index]!;
262
- const selected = structuredClone(view);
263
- selected.lineage = selected.lineage.slice(0, index + 1);
264
- for (const scope of SCOPES) {
265
- const stream = selected.scopes[scope];
266
- const retained = stream.patches.filter(({ transition }) => transition.position <= target.position);
267
- stream.revision -= stream.patches.length - retained.length;
268
- stream.patches = retained;
269
- }
270
- validateTemporalState(selected, historyLimit);
271
- return selected;
272
- }
273
-
274
238
  /** Current independent scope revisions; Effective uses this vector rather than inventing a scalar owner. */
275
239
  export function temporalScopeRevisions(view: TemporalState): ScopeRevisions {
276
240
  const revisions = {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-state-flow",
3
- "version": "0.25.5",
3
+ "version": "0.26.1",
4
4
  "license": "MIT",
5
5
  "private": false,
6
6
  "description": "Incremental scoped state/context/memory compiler for Pi, inspired by SKILL.state",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-kit",
3
- "version": "0.28.0",
3
+ "version": "0.29.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -46,7 +46,7 @@
46
46
  "@llblab/pi-clean-room": "0.3.0",
47
47
  "@llblab/pi-codex-usage": "0.12.1",
48
48
  "@llblab/pi-grow-loop": "0.9.0",
49
- "@llblab/pi-state-flow": "0.25.5",
49
+ "@llblab/pi-state-flow": "0.26.1",
50
50
  "@llblab/pi-telegram": "0.52.0",
51
51
  "@llblab/skills": "1.15.0"
52
52
  },