@llblab/pi-kit 0.24.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +6 -0
- package/README.md +5 -4
- package/node_modules/@llblab/pi-claude-usage/AGENTS.md +20 -0
- package/node_modules/@llblab/pi-claude-usage/BACKLOG.md +3 -0
- package/node_modules/@llblab/pi-claude-usage/CHANGELOG.md +13 -0
- package/node_modules/@llblab/pi-claude-usage/LICENSE +22 -0
- package/node_modules/@llblab/pi-claude-usage/README.md +110 -0
- package/node_modules/@llblab/pi-claude-usage/banner.jpg +0 -0
- package/node_modules/@llblab/pi-claude-usage/index.ts +1159 -0
- package/node_modules/@llblab/pi-claude-usage/package.json +60 -0
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +42 -56
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +16 -3
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +19 -0
- package/node_modules/@llblab/pi-state-flow/README.md +15 -12
- package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/index.js +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +7 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +16 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +9 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +5 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +7 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +3 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +3 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +275 -199
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +11 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +6 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +4 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +1 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +4 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +13 -13
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +7 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +9 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +3 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +17 -12
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +4 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +17 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +49 -20
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +22 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +30 -10
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +5 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +19 -28
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +17 -15
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +52 -52
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +8 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +34 -18
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +13 -19
- package/node_modules/@llblab/pi-state-flow/dist/package.json +3 -3
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -1
- package/node_modules/@llblab/pi-state-flow/docs/agent-contract-relocation.md +72 -0
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +36 -32
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +12 -4
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +5 -5
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +6 -6
- package/node_modules/@llblab/pi-state-flow/docs/performance.md +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +13 -12
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +32 -29
- package/node_modules/@llblab/pi-state-flow/index.ts +3 -2
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +20 -10
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +15 -14
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +8 -6
- package/node_modules/@llblab/pi-state-flow/lib/episode.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +274 -197
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -11
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +5 -1
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +16 -16
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +11 -11
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +19 -13
- package/node_modules/@llblab/pi-state-flow/lib/session.ts +6 -3
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +55 -22
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +46 -13
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +23 -32
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +66 -65
- package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +39 -19
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +19 -27
- package/node_modules/@llblab/pi-state-flow/package.json +3 -3
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +2 -2
- package/package.json +6 -2
|
@@ -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
|
-
/**
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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 {
|
|
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,
|
|
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 `
|
|
5
|
+
return `g${revisions.global}c${revisions.cwd}s${revisions.session}`;
|
|
8
6
|
}
|
|
9
|
-
export function compactStatus(snapshot,
|
|
10
|
-
|
|
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",
|
|
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
|
-
|
|
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
|
-
? [
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
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
|
-
: [
|
|
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
|
-
|
|
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
|
|
16
|
-
contract
|
|
17
|
-
working
|
|
18
|
-
intents
|
|
19
|
-
response
|
|
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
|
-
|
|
97
|
-
|
|
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" | "
|
|
104
|
+
export interface StateFlowTelegramInspectionPort extends Omit<StateFlowTelegramPort, "state" | "revisions" | "select"> {
|
|
102
105
|
inspect(scope: StateFlowTelegramScope): StateFlowTelegramInspection | Promise<StateFlowTelegramInspection>;
|
|
103
|
-
|
|
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
|
|
112
|
+
/** Main-menu section label shows only the current session mode. */
|
|
111
113
|
export declare function formatStateFlowSectionLabel(snapshot: StateFlowTelegramSnapshot): string;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
export declare function
|
|
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
|
|
23
|
+
/** Main-menu section label shows only the current session mode. */
|
|
24
24
|
export function formatStateFlowSectionLabel(snapshot) {
|
|
25
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
/**
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
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: [
|
|
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
|
-
|
|
51
|
-
[
|
|
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
|
-
//
|
|
137
|
-
|
|
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
|
|
171
|
-
if (
|
|
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
|
-
//
|
|
174
|
+
// Apply the control immediately and acknowledge in parallel; neither promise can reject unobserved.
|
|
175
175
|
const [, result] = await Promise.all([
|
|
176
|
-
ctx.answerCallback(
|
|
177
|
-
Promise.resolve().then(() => port
|
|
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
|
|
181
|
+
notice = modeReceiptNotice(mode, result);
|
|
182
182
|
}
|
|
183
183
|
else
|
|
184
|
-
notice = port
|
|
184
|
+
notice = modeReceiptNotice(mode, port.select(mode));
|
|
185
185
|
}
|
|
186
|
-
else if (ctx.action === "
|
|
186
|
+
else if (ctx.action === "active") {
|
|
187
187
|
port.deferStart();
|
|
188
|
-
notice = "State Flow will
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">")}`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type RecentScopePatch } from "./history.ts";
|
|
2
|
-
import { type MaterializedState, type
|
|
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:
|
|
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:
|
|
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
|
-
/**
|
|
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 {
|
|
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
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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,
|
|
6
|
+
import type { AtomicScopePatches, ScopedSemanticStates, StateScope, TerminalTransition } from "./state.ts";
|
|
7
7
|
export interface StagedScopedTransition {
|
|
8
|
-
nextStates:
|
|
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:
|
|
17
|
-
export declare function stageScopedTransition(currentStates:
|
|
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:
|
|
23
|
+
export declare function commitScopedTransition(snapshot: Snapshot, states: ScopedSemanticStates, stage: StagedScopedTransition, publishDurable: (accepted: AcceptedTransition | undefined, nextSnapshot: Snapshot) => void, causalBasis: string, options?: CommitScopedTransitionOptions): boolean;
|