@llblab/pi-kit 0.15.0 → 0.17.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/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +12 -12
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +2 -13
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +31 -0
- package/node_modules/@llblab/pi-state-flow/README.md +11 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +5 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +17 -16
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +8 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +24 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +15 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +4 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +7 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +124 -274
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +20 -23
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +8 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +29 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +18 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +44 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +55 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +7 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +65 -17
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.d.ts +17 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.js +102 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +43 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +268 -10
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +34 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +17 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +38 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +20 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +11 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +14 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +55 -20
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +9 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +10 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +8 -3
- package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +79 -0
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +23 -121
- package/node_modules/@llblab/pi-state-flow/docs/README.md +1 -0
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +27 -20
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +3 -2
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +513 -0
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +13 -10
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +18 -15
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +24 -0
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +14 -5
- package/node_modules/@llblab/pi-state-flow/lib/episode.ts +5 -0
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +119 -262
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +23 -22
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +8 -4
- package/node_modules/@llblab/pi-state-flow/lib/json.ts +31 -3
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +53 -1
- package/node_modules/@llblab/pi-state-flow/lib/migration.ts +51 -20
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +61 -17
- package/node_modules/@llblab/pi-state-flow/lib/publication.ts +96 -0
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +261 -9
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +32 -4
- package/node_modules/@llblab/pi-state-flow/lib/session.ts +45 -0
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +22 -25
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +22 -6
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +46 -18
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +20 -6
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +8 -3
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +79 -0
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +23 -121
- package/node_modules/@llblab/pi-telegram/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -0
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +7 -0
- package/node_modules/@llblab/pi-telegram/README.md +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +134 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +297 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +2 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +11 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +68 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +4 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +17 -13
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +55 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.d.ts +23 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.js +20 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +18 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +152 -6
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +5 -3
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +3 -3
- package/node_modules/@llblab/pi-telegram/docs/callback-namespaces.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +4 -3
- package/node_modules/@llblab/pi-telegram/docs/sections.md +2 -2
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +2 -1
- package/node_modules/@llblab/pi-telegram/docs/updates.md +1 -1
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +3 -0
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +466 -21
- package/node_modules/@llblab/pi-telegram/lib/delivery.ts +15 -0
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +77 -9
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +25 -10
- package/node_modules/@llblab/pi-telegram/lib/pi.ts +3 -0
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +84 -17
- package/node_modules/@llblab/pi-telegram/lib/thread-display.ts +30 -0
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +199 -6
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +5 -2
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +3 -3
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
// Domain:
|
|
1
|
+
// Domain: repository-global State Flow configuration, independent of session runtime and semantic state.
|
|
2
2
|
import { lstatSync, readFileSync } from "node:fs";
|
|
3
|
-
import {
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { join } from "node:path";
|
|
5
4
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
6
5
|
import { getDurableRepositoryRoot } from "./durable.ts";
|
|
7
6
|
import { isObject } from "./json.ts";
|
|
8
7
|
|
|
9
8
|
export interface StateFlowConfig {
|
|
9
|
+
/** Canonical State Flow repository. SDK callers may still override it explicitly. */
|
|
10
10
|
directory: string;
|
|
11
11
|
autoStart: boolean;
|
|
12
|
+
passiveBootstrap: boolean;
|
|
13
|
+
passiveTools: boolean;
|
|
12
14
|
/** Opt-in local capture of rejected patch attempts and unresolved terminal drafts. */
|
|
13
15
|
logging: boolean;
|
|
14
16
|
/** Show successful patch_state arguments in the interactive tool row. */
|
|
@@ -16,12 +18,15 @@ export interface StateFlowConfig {
|
|
|
16
18
|
remotePublication?: "off" | "turn-end" | "transition";
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
/** Read once at extension load/reload. Missing config uses defaults; invalid config never falls back. */
|
|
20
|
-
export function loadStateFlowConfig(agentDir = getAgentDir()): StateFlowConfig {
|
|
21
|
-
const
|
|
21
|
+
/** Read the repository-global config once at extension load/reload. Missing config uses defaults; invalid config never falls back. */
|
|
22
|
+
export function loadStateFlowConfig(agentDir = getAgentDir(), repositoryRoot = getDurableRepositoryRoot(agentDir)): StateFlowConfig {
|
|
23
|
+
const directory = repositoryRoot;
|
|
24
|
+
const path = join(directory, "config.json");
|
|
22
25
|
const defaults: StateFlowConfig = {
|
|
23
|
-
directory
|
|
26
|
+
directory,
|
|
24
27
|
autoStart: false,
|
|
28
|
+
passiveBootstrap: true,
|
|
29
|
+
passiveTools: true,
|
|
25
30
|
logging: false,
|
|
26
31
|
showSuccessfulPatches: true,
|
|
27
32
|
};
|
|
@@ -32,25 +37,23 @@ export function loadStateFlowConfig(agentDir = getAgentDir()): StateFlowConfig {
|
|
|
32
37
|
} catch (error) {
|
|
33
38
|
throw new Error(`Cannot read State Flow configuration: ${path}`, { cause: error });
|
|
34
39
|
}
|
|
35
|
-
const allowed = new Set(["
|
|
40
|
+
const allowed = new Set(["autoStart", "passiveBootstrap", "passiveTools", "logging", "showSuccessfulPatches", "remotePublication"]);
|
|
36
41
|
if (!isObject(value) || Object.keys(value).some((key) => !allowed.has(key))) {
|
|
37
42
|
throw new Error(`State Flow configuration contains unknown settings: ${path}`);
|
|
38
43
|
}
|
|
39
44
|
if (Object.hasOwn(value, "autoStart") && typeof value.autoStart !== "boolean") throw new Error(`State Flow autoStart must be a boolean: ${path}`);
|
|
45
|
+
if (Object.hasOwn(value, "passiveBootstrap") && typeof value.passiveBootstrap !== "boolean") throw new Error(`State Flow passiveBootstrap must be a boolean: ${path}`);
|
|
46
|
+
if (Object.hasOwn(value, "passiveTools") && typeof value.passiveTools !== "boolean") throw new Error(`State Flow passiveTools must be a boolean: ${path}`);
|
|
40
47
|
if (Object.hasOwn(value, "logging") && typeof value.logging !== "boolean") throw new Error(`State Flow logging must be a boolean: ${path}`);
|
|
41
48
|
if (Object.hasOwn(value, "showSuccessfulPatches") && typeof value.showSuccessfulPatches !== "boolean") throw new Error(`State Flow showSuccessfulPatches must be a boolean: ${path}`);
|
|
42
49
|
if (Object.hasOwn(value, "remotePublication") && value.remotePublication !== "off" && value.remotePublication !== "turn-end" && value.remotePublication !== "transition") {
|
|
43
50
|
throw new Error(`State Flow remotePublication must be off, turn-end, or transition: ${path}`);
|
|
44
51
|
}
|
|
45
|
-
if (Object.hasOwn(value, "directory") && (typeof value.directory !== "string" || !value.directory.trim() || value.directory.includes("\0"))) {
|
|
46
|
-
throw new Error(`State Flow directory must be a non-empty path: ${path}`);
|
|
47
|
-
}
|
|
48
|
-
const directory = value.directory as string | undefined;
|
|
49
|
-
if (directory?.startsWith("~") && directory !== "~" && !directory.startsWith("~/")) throw new Error(`State Flow directory supports ~ or ~/ paths, not named-user expansion: ${path}`);
|
|
50
|
-
const expanded = directory === "~" ? homedir() : directory?.startsWith("~/") ? resolve(homedir(), directory.slice(2)) : directory;
|
|
51
52
|
return {
|
|
52
|
-
directory
|
|
53
|
+
directory,
|
|
53
54
|
autoStart: value.autoStart === true,
|
|
55
|
+
passiveBootstrap: value.passiveBootstrap !== false,
|
|
56
|
+
passiveTools: value.passiveTools !== false,
|
|
54
57
|
logging: value.logging === true,
|
|
55
58
|
showSuccessfulPatches: value.showSuccessfulPatches !== false,
|
|
56
59
|
...(value.remotePublication === undefined ? {} : { remotePublication: value.remotePublication as "off" | "turn-end" | "transition" }),
|
|
@@ -7,6 +7,29 @@ import type { RehydrationPhase } from "./rehydration.ts";
|
|
|
7
7
|
import { projectStateForModel, type MaterializedState } from "./state.ts";
|
|
8
8
|
|
|
9
9
|
export const VALIDATION_MESSAGE_TYPE = "state-flow-validation";
|
|
10
|
+
const LAZY_HINT_PATH = "effective.lazy";
|
|
11
|
+
const LAZY_HINT_MAX_KEYS = 32;
|
|
12
|
+
const LAZY_HINT_MAX_JSON_CHARS = 1024;
|
|
13
|
+
|
|
14
|
+
type LazyValueKind = "array" | "boolean" | "null" | "number" | "object" | "string";
|
|
15
|
+
|
|
16
|
+
function lazyValueKind(value: Exclude<MaterializedState["lazy"], undefined>): LazyValueKind {
|
|
17
|
+
if (value === null) return "null";
|
|
18
|
+
if (Array.isArray(value)) return "array";
|
|
19
|
+
if (typeof value === "object") return "object";
|
|
20
|
+
return typeof value as Exclude<LazyValueKind, "array" | "object">;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Fixed-budget navigation only: never place lazy bodies or partial key catalogs in baseline context. */
|
|
24
|
+
export function lazyNavigationHint(state: MaterializedState): { available: boolean; path: string; keys?: Record<string, LazyValueKind> } {
|
|
25
|
+
const base = { available: Object.hasOwn(state, "lazy"), path: LAZY_HINT_PATH };
|
|
26
|
+
if (!base.available || typeof state.lazy !== "object" || state.lazy === null || Array.isArray(state.lazy)) return base;
|
|
27
|
+
const entries = Object.entries(state.lazy);
|
|
28
|
+
if (entries.length > LAZY_HINT_MAX_KEYS) return base;
|
|
29
|
+
const keys = Object.fromEntries(entries.map(([key, value]) => [key, lazyValueKind(value)]));
|
|
30
|
+
return JSON.stringify(keys).length <= LAZY_HINT_MAX_JSON_CHARS ? { ...base, keys } : base;
|
|
31
|
+
}
|
|
32
|
+
|
|
10
33
|
|
|
11
34
|
/** Bounded context retained after semantic State Flow is stopped in this physical session. */
|
|
12
35
|
export interface PassiveContinuation {
|
|
@@ -85,6 +108,7 @@ export function runtimeContextMessage(
|
|
|
85
108
|
const context = {
|
|
86
109
|
specification: snapshot.meta.specification,
|
|
87
110
|
state: projectStateForModel(state),
|
|
111
|
+
lazy_navigation: lazyNavigationHint(state),
|
|
88
112
|
...(rehydrationPhase === undefined ? {} : { knowledge_rehydration: { phase: rehydrationPhase } }),
|
|
89
113
|
...(artifactInvalidations.length === 0 ? {} : { artifact_invalidations: artifactInvalidations.map(({ path, reason }) => ({ path, reason })) }),
|
|
90
114
|
...(recentTransitions.length === 0 ? {} : { recent_transitions: projectRecentForModel(recentTransitions) }),
|
|
@@ -223,11 +223,12 @@ export function inspectStateFlowContinuationProvenance(
|
|
|
223
223
|
const paths = sessionRuntimePaths(header.cwd, header.id, repositoryRoot, sessionKey);
|
|
224
224
|
try {
|
|
225
225
|
const config = readRegular(paths.config);
|
|
226
|
+
const runtimeSource = readRegular(paths.runtime);
|
|
226
227
|
const meta = readRegular(paths.meta);
|
|
227
|
-
if (config === undefined && meta === undefined) {
|
|
228
|
+
if (config === undefined && runtimeSource === undefined && meta === undefined) {
|
|
228
229
|
return { stateFlow: { enabled: false, restorable: true }, reason: "no State Flow session runtime" };
|
|
229
230
|
}
|
|
230
|
-
const runtime = parseSessionRuntime(config,
|
|
231
|
+
const runtime = parseSessionRuntime(config, runtimeSource, header.cwd, header.id, meta);
|
|
231
232
|
if (!runtime) return { stateFlow: { enabled: false, restorable: true }, reason: "no State Flow session runtime" };
|
|
232
233
|
if (!runtime.config.enabled) return { stateFlow: { enabled: false, restorable: true }, reason: "State Flow stopped on selected runtime" };
|
|
233
234
|
if (runtime.meta.publication === "files") {
|
|
@@ -238,7 +239,7 @@ export function inspectStateFlowContinuationProvenance(
|
|
|
238
239
|
validateTemporalState({ lineage: runtime.meta.lineage, scopes: { global, cwd, session } });
|
|
239
240
|
return { stateFlow: { enabled: true, restorable: true }, reason: "exact file-only runtime cohort is restorable" };
|
|
240
241
|
}
|
|
241
|
-
const runtimePath = relative(resolve(repositoryRoot), paths.meta);
|
|
242
|
+
const runtimePath = relative(resolve(repositoryRoot), runtimeSource === undefined ? paths.meta : paths.runtime);
|
|
242
243
|
if (runtimePath.startsWith("..")) throw new Error("runtime provenance escapes repository");
|
|
243
244
|
const owner = execFileSync("git", ["-C", repositoryRoot, "log", "-1", "--format=%H", "--", runtimePath], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
244
245
|
if (!owner) throw new Error("runtime owner commit is unavailable");
|
|
@@ -20,13 +20,14 @@ import {
|
|
|
20
20
|
} from "./artifact.ts";
|
|
21
21
|
import { canonicalJson, isJsonValue, isObject } from "./json.ts";
|
|
22
22
|
import { validateScopeStream, validateTemporalState, type ScopeStream, type TemporalState } from "./temporal.ts";
|
|
23
|
-
import type
|
|
23
|
+
import { migratePreIntentState, type StateScope } from "./state.ts";
|
|
24
24
|
|
|
25
25
|
const SESSION_KEY_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
26
26
|
const STATE_FILE = "state.json";
|
|
27
27
|
const CHECKPOINT_FILE = "checkpoint.json";
|
|
28
28
|
const PATCHES_FILE = "patches.jsonl";
|
|
29
29
|
const META_FILE = "meta.json";
|
|
30
|
+
const RUNTIME_FILE = "runtime.json";
|
|
30
31
|
|
|
31
32
|
/** Canonical semantic sources plus runtime-owned temporal metadata. */
|
|
32
33
|
export interface ScopeStreamSources {
|
|
@@ -99,6 +100,7 @@ export function classifyScopeStream(
|
|
|
99
100
|
}
|
|
100
101
|
const temporal = meta?.temporal;
|
|
101
102
|
if (isObject(temporal) && Object.hasOwn(temporal, "checkpoint") && Array.isArray(temporal.patches)) {
|
|
103
|
+
checkpoint = migratePreIntentState(checkpoint) ?? checkpoint;
|
|
102
104
|
const owner = meta?.owner;
|
|
103
105
|
if (scope === "cwd" && expectedCwd !== undefined
|
|
104
106
|
&& (!isObject(owner) || Object.keys(owner).join(",") !== "cwd" || owner.cwd !== resolve(expectedCwd))) {
|
|
@@ -125,6 +127,10 @@ export function classifyScopeStream(
|
|
|
125
127
|
} else if (scope === "cwd" && expectedCwd !== undefined) {
|
|
126
128
|
throw new Error("State Flow CWD scope identity is missing");
|
|
127
129
|
}
|
|
130
|
+
if (isObject(legacyCheckpoint) && isObject(legacyCheckpoint.state)) {
|
|
131
|
+
const migrated = migratePreIntentState(legacyCheckpoint.state);
|
|
132
|
+
if (migrated) legacyCheckpoint = { ...legacyCheckpoint, state: migrated };
|
|
133
|
+
}
|
|
128
134
|
const stream = { checkpoint: legacyCheckpoint, patches };
|
|
129
135
|
validateScopeStream(stream, scope);
|
|
130
136
|
return { kind: "present", stream };
|
|
@@ -159,9 +165,9 @@ export function temporalScopePaths(cwd: string, sessionId: string, scope: StateS
|
|
|
159
165
|
return { directory, checkpoint: join(directory, CHECKPOINT_FILE), patches: join(directory, PATCHES_FILE), meta: join(directory, META_FILE) };
|
|
160
166
|
}
|
|
161
167
|
|
|
162
|
-
export function sessionRuntimePaths(cwd: string, sessionId: string, repositoryRoot: string, sessionKey = sessionId): { config: string; meta: string } {
|
|
168
|
+
export function sessionRuntimePaths(cwd: string, sessionId: string, repositoryRoot: string, sessionKey = sessionId): { config: string; runtime: string; meta: string } {
|
|
163
169
|
const directory = sessionScopePaths(cwd, sessionId, repositoryRoot, sessionKey).directory;
|
|
164
|
-
return { config: join(directory, "config.json"), meta: join(directory, META_FILE) };
|
|
170
|
+
return { config: join(directory, "config.json"), runtime: join(directory, RUNTIME_FILE), meta: join(directory, META_FILE) };
|
|
165
171
|
}
|
|
166
172
|
|
|
167
173
|
/** Unsupported state.json presence never becomes an anchored checkpoint. */
|
|
@@ -178,7 +184,7 @@ export function captureTemporalFileBases(cwd: string, sessionId: string, reposit
|
|
|
178
184
|
const paths = (["global", "cwd", "session"] as const).flatMap((scope) => {
|
|
179
185
|
const pair = temporalScopePaths(cwd, sessionId, scope, repositoryRoot, sessionKey);
|
|
180
186
|
const runtime = scope === "session" ? sessionRuntimePaths(cwd, sessionId, repositoryRoot, sessionKey) : undefined;
|
|
181
|
-
return [pair.checkpoint, pair.patches, join(pair.directory, STATE_FILE), ...(runtime === undefined ? [pair.meta] : [runtime.config, runtime.meta])];
|
|
187
|
+
return [pair.checkpoint, pair.patches, join(pair.directory, STATE_FILE), ...(runtime === undefined ? [pair.meta] : [runtime.config, runtime.runtime, runtime.meta])];
|
|
182
188
|
});
|
|
183
189
|
return captureOwnedFileBases(paths, repositoryRoot);
|
|
184
190
|
}
|
|
@@ -218,6 +224,9 @@ export function serializeScopeMetadata(
|
|
|
218
224
|
cwdIdentity?: string, existingSource?: string,
|
|
219
225
|
): string {
|
|
220
226
|
const existing = parseMetadataDocument(existingSource, `State Flow metadata`);
|
|
227
|
+
if (scope === "session") {
|
|
228
|
+
for (const key of ["identity", "lineage", "step", "specification", "validation", "bootstrap", "remotePublication", "revision", "temporalRevision", "publication"]) delete existing[key];
|
|
229
|
+
}
|
|
221
230
|
const sources = serializeScopeStream(stream, scope, cwdIdentity);
|
|
222
231
|
const value = {
|
|
223
232
|
...existing,
|
|
@@ -359,7 +368,7 @@ export function isStateFlowOwnedPath(candidate: string, repositoryRoot = getDura
|
|
|
359
368
|
return cwdKey(segments[0]!)
|
|
360
369
|
&& sessionKey(segments[1]!)
|
|
361
370
|
&& (segments[2] === STATE_FILE || segments[2] === CHECKPOINT_FILE || segments[2] === PATCHES_FILE
|
|
362
|
-
|| segments[2] === "config.json" || segments[2] === META_FILE);
|
|
371
|
+
|| segments[2] === "config.json" || segments[2] === RUNTIME_FILE || segments[2] === META_FILE);
|
|
363
372
|
}
|
|
364
373
|
return false;
|
|
365
374
|
}
|
|
@@ -27,3 +27,8 @@ export function prepareRun(snapshot: Snapshot, prompt: string): boolean {
|
|
|
27
27
|
snapshot.meta.validation = undefined;
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
/** Retain the full prompt only while its run remains recoverable and unfinished. */
|
|
32
|
+
export function completeRun(snapshot: Snapshot): void {
|
|
33
|
+
delete snapshot.meta.specification;
|
|
34
|
+
}
|