@llblab/pi-kit 0.18.2 → 0.19.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.
- package/CHANGELOG.md +11 -0
- package/README.md +3 -1
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +35 -37
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +5 -3
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +23 -1
- package/node_modules/@llblab/pi-state-flow/README.md +102 -48
- package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +6 -9
- package/node_modules/@llblab/pi-state-flow/dist/index.js +6 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +21 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.d.ts +40 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.js +93 -63
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +9 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +6 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +8 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +56 -58
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +12 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +7 -18
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +47 -78
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +4 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +241 -437
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +2 -72
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +120 -499
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.d.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +43 -22
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +1 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +0 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/memory.d.ts +1 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/memory.js +5 -37
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +1 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +13 -32
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +25 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +3 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +15 -12
- package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.d.ts +2 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.js +5 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +26 -88
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +160 -255
- package/node_modules/@llblab/pi-state-flow/dist/lib/skills.d.ts +0 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/skills.js +1 -47
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +16 -33
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +48 -137
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +16 -11
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +13 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +1 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +15 -43
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +5 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +13 -45
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +15 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +104 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +0 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +11 -14
- package/node_modules/@llblab/pi-state-flow/dist/package.json +9 -6
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +11 -17
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +8 -8
- package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +64 -67
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +24 -6
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +12 -15
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +22 -27
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +25 -41
- package/node_modules/@llblab/pi-state-flow/docs/performance.md +38 -421
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +33 -46
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +37 -61
- package/node_modules/@llblab/pi-state-flow/index.ts +7 -71
- package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +26 -11
- package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +116 -88
- package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +12 -10
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +52 -59
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +11 -20
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +44 -86
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +237 -460
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +110 -552
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/lib/json.ts +39 -23
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +1 -7
- package/node_modules/@llblab/pi-state-flow/lib/memory.ts +5 -44
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +14 -25
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +26 -22
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +17 -11
- package/node_modules/@llblab/pi-state-flow/lib/rehydration.ts +7 -5
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +155 -254
- package/node_modules/@llblab/pi-state-flow/lib/skills.ts +1 -49
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +58 -142
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +27 -19
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +16 -54
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +12 -40
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +104 -22
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +16 -26
- package/node_modules/@llblab/pi-state-flow/package.json +9 -6
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +11 -17
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +8 -8
- package/package.json +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/discovery.d.ts +0 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/discovery.js +0 -125
- package/node_modules/@llblab/pi-state-flow/dist/lib/maintenance.d.ts +0 -36
- package/node_modules/@llblab/pi-state-flow/dist/lib/maintenance.js +0 -98
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +0 -13
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +0 -167
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.d.ts +0 -86
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.js +0 -437
- package/node_modules/@llblab/pi-state-flow/lib/discovery.ts +0 -133
- package/node_modules/@llblab/pi-state-flow/lib/maintenance.ts +0 -147
- package/node_modules/@llblab/pi-state-flow/lib/migration.ts +0 -171
- package/node_modules/@llblab/pi-state-flow/lib/publication.ts +0 -458
|
@@ -2,12 +2,10 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import {
|
|
3
3
|
hashArtifactSource,
|
|
4
4
|
isArtifactHash,
|
|
5
|
-
type ArtifactMetadata,
|
|
6
5
|
type ArtifactProvenance,
|
|
7
6
|
type ArtifactRegistry,
|
|
8
7
|
} from "./artifact.ts";
|
|
9
|
-
import {
|
|
10
|
-
import type { MaterializedState } from "./state.ts";
|
|
8
|
+
import { isObject } from "./json.ts";
|
|
11
9
|
|
|
12
10
|
export const SKILL_ARTIFACT_COMPILER = "skill-artifact-v1";
|
|
13
11
|
|
|
@@ -46,52 +44,6 @@ export function hashSkillSource(source: string): string {
|
|
|
46
44
|
return hashArtifactSource(readFileSync(source));
|
|
47
45
|
}
|
|
48
46
|
|
|
49
|
-
function legacyCompilation(value: JsonValue): JsonObject | undefined {
|
|
50
|
-
if (!hasContent(value)) return undefined;
|
|
51
|
-
return isObject(value) ? structuredClone(value) : { value: structuredClone(value) };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Move the retired contract store into source-addressed Skill artifacts. */
|
|
55
|
-
export function migrateLegacySkillCompilations(
|
|
56
|
-
state: MaterializedState,
|
|
57
|
-
hasher: SkillSourceHasher = hashSkillSource,
|
|
58
|
-
): MaterializedState {
|
|
59
|
-
if (!isObject(state.contract.compiled_skills)) return structuredClone(state);
|
|
60
|
-
const legacy = state.contract.compiled_skills;
|
|
61
|
-
const next = structuredClone(state);
|
|
62
|
-
delete next.contract.compiled_skills;
|
|
63
|
-
for (const [source, value] of Object.entries(legacy)) {
|
|
64
|
-
const compilation = legacyCompilation(value);
|
|
65
|
-
if (!compilation) continue;
|
|
66
|
-
let hash: string;
|
|
67
|
-
let verified = true;
|
|
68
|
-
try {
|
|
69
|
-
hash = hasher(source);
|
|
70
|
-
if (!isArtifactHash(hash)) throw new Error("invalid source hash");
|
|
71
|
-
} catch {
|
|
72
|
-
// Preserve useful legacy behavior while ensuring a later observable source
|
|
73
|
-
// identity normally invalidates this explicitly unverified fallback.
|
|
74
|
-
hash = hashArtifactSource(canonicalJson({ source, compilation }));
|
|
75
|
-
verified = false;
|
|
76
|
-
}
|
|
77
|
-
const metadata: ArtifactMetadata = {
|
|
78
|
-
description: `Compiled operational guidance for the Skill at ${source}`,
|
|
79
|
-
hash,
|
|
80
|
-
compiler: SKILL_ARTIFACT_COMPILER,
|
|
81
|
-
kind: "skill",
|
|
82
|
-
compilation,
|
|
83
|
-
...(verified ? {} : { source_hash_verified: false }),
|
|
84
|
-
};
|
|
85
|
-
Object.defineProperty(next.artifacts, source, {
|
|
86
|
-
value: metadata,
|
|
87
|
-
enumerable: true,
|
|
88
|
-
configurable: true,
|
|
89
|
-
writable: true,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return next;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
47
|
export function skillPathFromRead(toolName: unknown, args: unknown): string | undefined {
|
|
96
48
|
if (toolName !== "read" || !isObject(args) || typeof args.path !== "string") return undefined;
|
|
97
49
|
return /(^|[\\/])SKILL\.md$/.test(args.path) ? args.path : undefined;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { parseArtifactProvenanceRegistry, type ArtifactProvenanceRegistry } from "./artifact.ts";
|
|
3
|
-
import {
|
|
3
|
+
import { MAX_HISTORY_LIMIT } from "./history.ts";
|
|
4
4
|
import { applyPatch, canonicalJson, containsNull, isJsonValue, isObject, type JsonObject } from "./json.ts";
|
|
5
5
|
import { validateTemporalLineage, type TransitionBoundary } from "./temporal.ts";
|
|
6
|
-
import { migrateLegacySkillCompilations } from "./skills.ts";
|
|
7
6
|
import { isMaterializedState, type MaterializedState } from "./state.ts";
|
|
8
7
|
const MAX_RESTORED_STEP = Number.MAX_SAFE_INTEGER - 1;
|
|
9
8
|
const MAX_LEGACY_VALIDATION_ATTEMPT = 7;
|
|
@@ -15,11 +14,6 @@ export interface SnapshotConfig {
|
|
|
15
14
|
enabled: boolean;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
export interface PendingPublicationState {
|
|
19
|
-
commit: string;
|
|
20
|
-
error: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
17
|
interface LegacyValidationFeedback {
|
|
24
18
|
attempt: number;
|
|
25
19
|
error: string;
|
|
@@ -27,14 +21,11 @@ interface LegacyValidationFeedback {
|
|
|
27
21
|
}
|
|
28
22
|
|
|
29
23
|
export interface SnapshotMeta {
|
|
30
|
-
durableBase?: string;
|
|
31
|
-
pendingPublication?: PendingPublicationState;
|
|
32
24
|
step: number;
|
|
33
25
|
specification?: string;
|
|
34
26
|
/** Read-only compatibility/recovery diagnostic; 0.7 never schedules terminal-envelope retries. */
|
|
35
27
|
validation?: LegacyValidationFeedback;
|
|
36
28
|
bootstrap?: boolean;
|
|
37
|
-
remotePublication?: RemotePublicationPolicyDocument;
|
|
38
29
|
}
|
|
39
30
|
|
|
40
31
|
/** In-memory runtime config/provenance; durable config/meta and scope files own restoration. */
|
|
@@ -47,17 +38,12 @@ export type Snapshot = StateFlowSnapshot;
|
|
|
47
38
|
|
|
48
39
|
export interface SessionRuntime {
|
|
49
40
|
config: SnapshotConfig;
|
|
50
|
-
meta:
|
|
41
|
+
meta: SnapshotMeta & {
|
|
51
42
|
version: 1;
|
|
52
43
|
identity: { cwd: string; sessionId: string };
|
|
53
44
|
lineage: TransitionBoundary[];
|
|
54
|
-
/** Runtime-owned artifact
|
|
45
|
+
/** Runtime-owned artifact compilation evidence; never projected as semantic state. */
|
|
55
46
|
artifacts?: ArtifactProvenanceRegistry;
|
|
56
|
-
/** Resolved against the commit that last wrote this runtime record, not arbitrary HEAD. */
|
|
57
|
-
revision: "self";
|
|
58
|
-
temporalRevision?: "self" | string;
|
|
59
|
-
/** Durable intent survives a crash before the push result can be observed. */
|
|
60
|
-
publication: "unconfirmed" | "files";
|
|
61
47
|
temporal?: { checkpoint: TransitionBoundary; patches: TransitionBoundary[] };
|
|
62
48
|
[key: string]: unknown;
|
|
63
49
|
};
|
|
@@ -66,27 +52,26 @@ export interface SessionRuntime {
|
|
|
66
52
|
export function validateSessionRuntime(value: unknown, cwd: string, sessionId: string): asserts value is SessionRuntime {
|
|
67
53
|
if (!isJsonValue(value) || !isObject(value) || Object.keys(value).sort().join(",") !== "config,meta"
|
|
68
54
|
|| !isObject(value.config) || !isObject(value.meta)) throw new Error("Invalid State Flow session runtime envelope");
|
|
69
|
-
const { version, identity, lineage,
|
|
55
|
+
const { version, identity, lineage, artifacts, temporal: _temporalScope, ...fields } = value.meta;
|
|
70
56
|
if (artifacts !== undefined) parseArtifactProvenanceRegistry(artifacts, "State Flow session artifact provenance");
|
|
71
|
-
if (
|
|
72
|
-
&& !isExactRevision(temporalRevision)) throw new Error("Invalid temporal revision reference");
|
|
73
|
-
if (version !== 1 || revision !== "self" || (publication !== "unconfirmed" && publication !== "files")) throw new Error("Unsupported State Flow runtime provenance format");
|
|
74
|
-
if (publication === "files" && temporalRevision !== undefined && temporalRevision !== "self") throw new Error("File runtime cannot select a historical temporal revision");
|
|
57
|
+
if (version !== 1) throw new Error("Unsupported State Flow runtime provenance format");
|
|
75
58
|
if (!isObject(identity) || Object.keys(identity).sort().join(",") !== "cwd,sessionId"
|
|
76
59
|
|| identity.cwd !== resolve(cwd) || identity.sessionId !== sessionId || sessionId.trim().length === 0 || sessionId !== sessionId.trim()) {
|
|
77
60
|
throw new Error("State Flow runtime scope identity mismatch");
|
|
78
61
|
}
|
|
79
|
-
validateTemporalLineage(lineage);
|
|
80
|
-
const known = new Set(["step", "specification", "validation", "bootstrap"
|
|
62
|
+
validateTemporalLineage(lineage, MAX_HISTORY_LIMIT);
|
|
63
|
+
const known = new Set(["step", "specification", "validation", "bootstrap"]);
|
|
81
64
|
if (Object.keys(fields).some((key) => ["state", "contract", "working", "response"].includes(key))) {
|
|
82
65
|
throw new Error("Semantic state does not belong in State Flow runtime metadata");
|
|
83
66
|
}
|
|
84
67
|
const runtimeFields = Object.fromEntries(Object.entries(fields).filter(([key]) => known.has(key)));
|
|
85
|
-
const
|
|
86
|
-
|
|
68
|
+
const normalized: Snapshot = {
|
|
69
|
+
config: { enabled: value.config.enabled === true },
|
|
70
|
+
meta: restoredMeta(runtimeFields),
|
|
71
|
+
};
|
|
87
72
|
if (runtimeFields.bootstrap === false) normalized.meta.bootstrap = false;
|
|
88
73
|
if (runtimeFields.step === Number.MAX_SAFE_INTEGER) normalized.meta.step = Number.MAX_SAFE_INTEGER;
|
|
89
|
-
if (canonicalJson({ config: normalized.config, meta: normalized.meta }) !== canonicalJson({ config:
|
|
74
|
+
if (canonicalJson({ config: normalized.config, meta: normalized.meta }) !== canonicalJson({ config: value.config, meta: runtimeFields })) {
|
|
90
75
|
throw new Error("Invalid State Flow runtime configuration or counters");
|
|
91
76
|
}
|
|
92
77
|
}
|
|
@@ -96,19 +81,16 @@ export function createSessionRuntime(
|
|
|
96
81
|
cwd: string,
|
|
97
82
|
sessionId: string,
|
|
98
83
|
lineage: readonly TransitionBoundary[],
|
|
99
|
-
publication: SessionRuntime["meta"]["publication"] = "unconfirmed",
|
|
100
84
|
_artifacts: ArtifactProvenanceRegistry = {},
|
|
101
85
|
): SessionRuntime {
|
|
102
|
-
const
|
|
86
|
+
const fields = snapshot.meta;
|
|
103
87
|
const runtime: SessionRuntime = {
|
|
104
88
|
config: structuredClone(snapshot.config),
|
|
105
89
|
meta: {
|
|
106
|
-
...Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined)) as
|
|
90
|
+
...Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined)) as SnapshotMeta,
|
|
107
91
|
version: 1,
|
|
108
92
|
identity: { cwd: resolve(cwd), sessionId },
|
|
109
93
|
lineage: structuredClone([...lineage]),
|
|
110
|
-
revision: "self",
|
|
111
|
-
publication,
|
|
112
94
|
},
|
|
113
95
|
};
|
|
114
96
|
validateSessionRuntime(runtime, cwd, sessionId);
|
|
@@ -124,24 +106,13 @@ export function serializeSessionRuntime(
|
|
|
124
106
|
}
|
|
125
107
|
|
|
126
108
|
export function parseSessionRuntime(
|
|
127
|
-
config: string | undefined, runtimeSource: string | undefined, cwd: string, sessionId: string,
|
|
109
|
+
config: string | undefined, runtimeSource: string | undefined, cwd: string, sessionId: string,
|
|
128
110
|
): SessionRuntime | undefined {
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
let legacy: unknown;
|
|
132
|
-
try { legacy = JSON.parse(legacyMetaSource); } catch { throw new Error("State Flow session runtime contains invalid JSON"); }
|
|
133
|
-
if (isObject(legacy) && (Object.hasOwn(legacy, "identity") || Object.hasOwn(legacy, "lineage"))) selected = legacyMetaSource;
|
|
134
|
-
}
|
|
135
|
-
if (config === undefined && selected === undefined) return undefined;
|
|
136
|
-
if (config === undefined && selected !== undefined) {
|
|
137
|
-
let document: unknown;
|
|
138
|
-
try { document = JSON.parse(selected); } catch { throw new Error("State Flow session runtime contains invalid JSON"); }
|
|
139
|
-
if (isObject(document) && !Object.hasOwn(document, "identity") && !Object.hasOwn(document, "lineage")) return undefined;
|
|
140
|
-
}
|
|
141
|
-
if (config === undefined || selected === undefined) throw new Error("Incomplete State Flow config/runtime pair");
|
|
111
|
+
if (config === undefined && runtimeSource === undefined) return undefined;
|
|
112
|
+
if (config === undefined || runtimeSource === undefined) throw new Error("Incomplete State Flow config/runtime pair");
|
|
142
113
|
let runtime: unknown;
|
|
143
114
|
try {
|
|
144
|
-
runtime = { config: JSON.parse(config), meta: JSON.parse(
|
|
115
|
+
runtime = { config: JSON.parse(config), meta: JSON.parse(runtimeSource) };
|
|
145
116
|
} catch {
|
|
146
117
|
throw new Error("State Flow session runtime contains invalid JSON");
|
|
147
118
|
}
|
|
@@ -150,40 +121,6 @@ export function parseSessionRuntime(
|
|
|
150
121
|
return { config: { enabled: runtime.config.enabled }, meta: runtimeMeta };
|
|
151
122
|
}
|
|
152
123
|
|
|
153
|
-
export function resolveSessionRuntime(runtime: SessionRuntime, revision: string): { snapshot: Snapshot; lineage: TransitionBoundary[]; publicationTarget: string; artifacts: ArtifactProvenanceRegistry } {
|
|
154
|
-
validateSessionRuntime(runtime, runtime.meta.identity.cwd, runtime.meta.identity.sessionId);
|
|
155
|
-
if (!isExactRevision(revision) || runtime.meta.publication !== "unconfirmed") throw new Error("Runtime self reference requires its exact Git revision and Git publication provenance");
|
|
156
|
-
const { version: _version, identity: _identity, lineage, revision: _self, temporalRevision: _temporal, publication: _intent, artifacts, ...fields } = runtime.meta;
|
|
157
|
-
return {
|
|
158
|
-
snapshot: { config: structuredClone(runtime.config), meta: { ...structuredClone(fields), durableBase: revision } },
|
|
159
|
-
lineage: structuredClone(lineage),
|
|
160
|
-
publicationTarget: revision,
|
|
161
|
-
artifacts: structuredClone(artifacts ?? {}),
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function resolveFileSessionRuntime(runtime: SessionRuntime, revision: string): Snapshot {
|
|
166
|
-
validateSessionRuntime(runtime, runtime.meta.identity.cwd, runtime.meta.identity.sessionId);
|
|
167
|
-
if (!isFileRevision(revision) || runtime.meta.publication !== "files") throw new Error("File runtime requires its exact file revision and file publication provenance");
|
|
168
|
-
const { version: _version, identity: _identity, lineage: _lineage, revision: _self, temporalRevision: _temporal, publication: _intent, ...fields } = runtime.meta;
|
|
169
|
-
return { config: structuredClone(runtime.config), meta: { ...structuredClone(fields), durableBase: revision } };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function isLegacyTwoPartState(value: unknown): value is { contract: JsonObject; working: JsonObject } {
|
|
173
|
-
return isObject(value)
|
|
174
|
-
&& isObject(value.contract)
|
|
175
|
-
&& isObject(value.working)
|
|
176
|
-
&& Object.keys(value).every((key) => key === "contract" || key === "working");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function isLegacyThreePartState(value: unknown): value is { contract: JsonObject; working: JsonObject; response: string } {
|
|
180
|
-
return isObject(value)
|
|
181
|
-
&& isObject(value.contract)
|
|
182
|
-
&& isObject(value.working)
|
|
183
|
-
&& typeof value.response === "string"
|
|
184
|
-
&& Object.keys(value).every((key) => key === "contract" || key === "working" || key === "response");
|
|
185
|
-
}
|
|
186
|
-
|
|
187
124
|
function restoredStep(value: unknown): number {
|
|
188
125
|
return typeof value === "number"
|
|
189
126
|
&& Number.isSafeInteger(value)
|
|
@@ -207,37 +144,14 @@ function restoredValidation(value: unknown): LegacyValidationFeedback | undefine
|
|
|
207
144
|
};
|
|
208
145
|
}
|
|
209
146
|
|
|
210
|
-
function restoredPendingPublication(value: unknown): PendingPublicationState | undefined {
|
|
211
|
-
if (!isObject(value)
|
|
212
|
-
|| typeof value.commit !== "string"
|
|
213
|
-
|| !/^[0-9a-f]{40,64}$/.test(value.commit)
|
|
214
|
-
|| typeof value.error !== "string"
|
|
215
|
-
|| value.error.trim().length === 0) return undefined;
|
|
216
|
-
return { commit: value.commit, error: value.error };
|
|
217
|
-
}
|
|
218
|
-
|
|
219
147
|
function restoredMeta(value: unknown, legacy: JsonObject = {}): SnapshotMeta {
|
|
220
148
|
const meta = isObject(value) ? value : legacy;
|
|
221
|
-
const pendingPublication = restoredPendingPublication(meta.pendingPublication);
|
|
222
149
|
const validation = restoredValidation(meta.validation);
|
|
223
|
-
let remotePublication: RemotePublicationPolicyDocument | undefined;
|
|
224
|
-
try {
|
|
225
|
-
if (meta.remotePublication !== undefined) remotePublication = serializeRemotePublicationPolicyDocument(
|
|
226
|
-
parseRemotePublicationPolicyDocument(meta.remotePublication, { legacyRuntime: false }),
|
|
227
|
-
);
|
|
228
|
-
} catch {
|
|
229
|
-
remotePublication = undefined;
|
|
230
|
-
}
|
|
231
150
|
return {
|
|
232
|
-
...(isDurableRevision(meta.durableBase)
|
|
233
|
-
? { durableBase: meta.durableBase }
|
|
234
|
-
: {}),
|
|
235
|
-
...(pendingPublication === undefined ? {} : { pendingPublication }),
|
|
236
151
|
step: restoredStep(meta.step),
|
|
237
152
|
...(typeof meta.specification === "string" ? { specification: meta.specification } : {}),
|
|
238
153
|
...(validation === undefined ? {} : { validation }),
|
|
239
154
|
...(meta.bootstrap === true ? { bootstrap: true } : {}),
|
|
240
|
-
...(remotePublication === undefined ? {} : { remotePublication }),
|
|
241
155
|
};
|
|
242
156
|
}
|
|
243
157
|
|
|
@@ -249,41 +163,53 @@ export function emptySnapshot(enabled = false): Snapshot {
|
|
|
249
163
|
return envelope(enabled, { step: 0 });
|
|
250
164
|
}
|
|
251
165
|
|
|
252
|
-
export type
|
|
166
|
+
export type RetainedBoundaryCheckpoint = {
|
|
167
|
+
boundary: string;
|
|
168
|
+
enabled: boolean;
|
|
169
|
+
step: number;
|
|
170
|
+
bootstrap?: true;
|
|
171
|
+
specification?: string;
|
|
172
|
+
};
|
|
173
|
+
export type RetainedPiCheckpoint = RetainedBoundaryCheckpoint | { disabled: true };
|
|
253
174
|
export type FileRevision = `file:${string}`;
|
|
254
175
|
|
|
255
176
|
export function isFileRevision(value: unknown): value is FileRevision {
|
|
256
177
|
return typeof value === "string" && /^file:[0-9a-f]{64}$/.test(value);
|
|
257
178
|
}
|
|
258
179
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
throw new Error("Invalid State Flow checkpoint pointer or disabled marker");
|
|
180
|
+
/** Encode branch lifecycle against one retained temporal identity without semantic or backup data. */
|
|
181
|
+
export function retainedBoundaryCheckpoint(snapshot: Snapshot, boundary: string): RetainedBoundaryCheckpoint {
|
|
182
|
+
if (typeof boundary !== "string" || boundary.trim().length === 0) throw new Error("Checkpoint requires a retained temporal boundary identity");
|
|
183
|
+
const checkpoint: RetainedBoundaryCheckpoint = {
|
|
184
|
+
boundary,
|
|
185
|
+
enabled: snapshot.config.enabled,
|
|
186
|
+
step: snapshot.meta.step,
|
|
187
|
+
...(snapshot.meta.bootstrap === true ? { bootstrap: true as const } : {}),
|
|
188
|
+
...(snapshot.meta.specification === undefined ? {} : { specification: snapshot.meta.specification }),
|
|
189
|
+
};
|
|
190
|
+
return parseRetainedPiCheckpoint(checkpoint) as RetainedBoundaryCheckpoint;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Decode the 0.17 retained-window checkpoint contract. */
|
|
194
|
+
export function parseRetainedPiCheckpoint(value: unknown): RetainedPiCheckpoint {
|
|
195
|
+
if (!isObject(value)) throw new Error("Invalid State Flow retained-boundary checkpoint");
|
|
196
|
+
if (Object.keys(value).length === 1 && value.disabled === true) return { disabled: true };
|
|
197
|
+
const allowed = new Set(["boundary", "enabled", "step", "bootstrap", "specification"]);
|
|
198
|
+
if (Object.keys(value).some((key) => !allowed.has(key))
|
|
199
|
+
|| typeof value.boundary !== "string" || value.boundary.trim().length === 0
|
|
200
|
+
|| typeof value.enabled !== "boolean"
|
|
201
|
+
|| !Number.isSafeInteger(value.step) || (value.step as number) < 0 || (value.step as number) > MAX_RESTORED_STEP
|
|
202
|
+
|| (value.bootstrap !== undefined && value.bootstrap !== true)
|
|
203
|
+
|| (value.specification !== undefined && typeof value.specification !== "string")) {
|
|
204
|
+
throw new Error("Invalid State Flow retained-boundary checkpoint");
|
|
285
205
|
}
|
|
286
|
-
|
|
206
|
+
return {
|
|
207
|
+
boundary: value.boundary,
|
|
208
|
+
enabled: value.enabled,
|
|
209
|
+
step: value.step as number,
|
|
210
|
+
...(value.bootstrap === true ? { bootstrap: true } : {}),
|
|
211
|
+
...(typeof value.specification === "string" ? { specification: value.specification } : {}),
|
|
212
|
+
};
|
|
287
213
|
}
|
|
288
214
|
|
|
289
215
|
export function migrationFailure(data: JsonObject, error: string): Snapshot {
|
|
@@ -295,13 +221,3 @@ export function migrationFailure(data: JsonObject, error: string): Snapshot {
|
|
|
295
221
|
};
|
|
296
222
|
return envelope(false, meta);
|
|
297
223
|
}
|
|
298
|
-
|
|
299
|
-
export function migrateSnapshot(value: unknown): Snapshot {
|
|
300
|
-
if (!isObject(value)) return emptySnapshot();
|
|
301
|
-
const isEnvelope = Object.hasOwn(value, "config") || Object.hasOwn(value, "meta");
|
|
302
|
-
const config = isEnvelope && isObject(value.config) ? value.config : value;
|
|
303
|
-
const meta = restoredMeta(isEnvelope ? value.meta : undefined, value);
|
|
304
|
-
const enabled = config.enabled === true;
|
|
305
|
-
if (Object.hasOwn(value, "state") || Object.hasOwn(value, "stateBasis") || Object.hasOwn(value, "previousStatePatch")) return envelope(false, meta);
|
|
306
|
-
return envelope(enabled, meta);
|
|
307
|
-
}
|
|
@@ -3,19 +3,19 @@ import {
|
|
|
3
3
|
projectArtifactsForModel,
|
|
4
4
|
updateArtifactRegistry,
|
|
5
5
|
type ArtifactCompilationUpdate,
|
|
6
|
+
type ArtifactModelHints,
|
|
6
7
|
type ArtifactRegistry,
|
|
7
8
|
} from "./artifact.ts";
|
|
8
|
-
import { applyPatch,
|
|
9
|
+
import { applyPatch, isObject, type JsonObject } from "./json.ts";
|
|
9
10
|
|
|
10
11
|
/** The canonical semantic state shape shared by global, CWD, and session scopes. */
|
|
11
12
|
export type MaterializedState = JsonObject & {
|
|
12
|
-
|
|
13
|
+
intents: JsonObject;
|
|
13
14
|
contract: JsonObject;
|
|
14
15
|
working: JsonObject;
|
|
15
|
-
|
|
16
|
+
artifacts: ArtifactRegistry;
|
|
16
17
|
response: string;
|
|
17
|
-
|
|
18
|
-
lazy?: JsonValue;
|
|
18
|
+
lazy: JsonObject;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/** Compatibility name for callers that still treat materialized state as a document. */
|
|
@@ -28,6 +28,7 @@ export interface StatePatch extends JsonObject {
|
|
|
28
28
|
working: JsonObject;
|
|
29
29
|
intents: JsonObject;
|
|
30
30
|
response: string;
|
|
31
|
+
lazy: JsonObject;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export type StateScope = "global" | "cwd" | "session";
|
|
@@ -38,7 +39,7 @@ export interface ScopePatch {
|
|
|
38
39
|
contract?: JsonObject;
|
|
39
40
|
working?: JsonObject;
|
|
40
41
|
intents?: JsonObject;
|
|
41
|
-
lazy?:
|
|
42
|
+
lazy?: JsonObject;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
export interface ScopedPatch {
|
|
@@ -68,7 +69,7 @@ export interface ScopedStates {
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
export function emptyState(): MaterializedState {
|
|
71
|
-
return {
|
|
72
|
+
return { intents: {}, contract: {}, working: {}, artifacts: {}, response: "", lazy: {} };
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
export function isMaterializedState(value: unknown): value is MaterializedState {
|
|
@@ -78,19 +79,12 @@ export function isMaterializedState(value: unknown): value is MaterializedState
|
|
|
78
79
|
&& isObject(value.working)
|
|
79
80
|
&& isObject(value.intents)
|
|
80
81
|
&& typeof value.response === "string"
|
|
81
|
-
&& (
|
|
82
|
+
&& isObject(value.lazy)
|
|
82
83
|
&& Object.keys(value).every((key) => key === "artifacts" || key === "contract" || key === "working" || key === "intents" || key === "response" || key === "lazy");
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
export const isStateDocument = isMaterializedState;
|
|
86
87
|
|
|
87
|
-
/** Upgrade one exact pre-intents materialized state without inferring commitments. */
|
|
88
|
-
export function migratePreIntentState(value: unknown): MaterializedState | undefined {
|
|
89
|
-
if (!isObject(value) || Object.hasOwn(value, "intents")) return undefined;
|
|
90
|
-
const candidate = { ...structuredClone(value), intents: {} };
|
|
91
|
-
return isMaterializedState(candidate) ? candidate : undefined;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
88
|
/** Atomically replace compiled and removed artifacts inside one materialized scope. */
|
|
95
89
|
export function updateMaterializedArtifacts(
|
|
96
90
|
state: MaterializedState,
|
|
@@ -109,8 +103,22 @@ export function overlayStates(...scopes: readonly MaterializedState[]): Material
|
|
|
109
103
|
}, emptyState());
|
|
110
104
|
}
|
|
111
105
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
export type ModelState = JsonObject & {
|
|
107
|
+
intents: JsonObject;
|
|
108
|
+
contract: JsonObject;
|
|
109
|
+
working: JsonObject;
|
|
110
|
+
artifacts: ArtifactRegistry;
|
|
111
|
+
response: string;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** Model-visible projection: lazy bodies and runtime artifact bookkeeping stay out of ordinary context. */
|
|
115
|
+
export function projectStateForModel(state: MaterializedState, artifactHints: ArtifactModelHints = {}): ModelState {
|
|
116
|
+
const cloned = structuredClone(state);
|
|
117
|
+
return {
|
|
118
|
+
intents: cloned.intents,
|
|
119
|
+
contract: cloned.contract,
|
|
120
|
+
working: cloned.working,
|
|
121
|
+
artifacts: projectArtifactsForModel(cloned.artifacts, artifactHints),
|
|
122
|
+
response: cloned.response,
|
|
123
|
+
};
|
|
116
124
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ArtifactInvalidationReason } from "./artifact.ts";
|
|
2
|
-
import { projectRecentTransitionsWithLimit,
|
|
3
|
-
import {
|
|
4
|
-
import type { PublicationQueueState } from "./publication.ts";
|
|
2
|
+
import { projectRecentTransitionsWithLimit, type RecentTransitionWindow } from "./history.ts";
|
|
3
|
+
import { retainedMemoryScopes } from "./memory.ts";
|
|
5
4
|
import type { Snapshot } from "./snapshot.ts";
|
|
6
5
|
import { overlayStates, type ScopedStates, type StateScope } from "./state.ts";
|
|
7
6
|
import type { TransitionBoundary } from "./temporal.ts";
|
|
@@ -18,24 +17,16 @@ export interface StaleArtifactDiagnostic {
|
|
|
18
17
|
reason: StaleArtifactReason;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export interface PendingPublicationDiagnostic {
|
|
22
|
-
commit: string;
|
|
23
|
-
error: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
20
|
export interface StatusDiagnostics {
|
|
27
21
|
repositoryRoot: string;
|
|
28
22
|
cwdScopeKey: string;
|
|
29
23
|
sessionScopeKey: string;
|
|
30
24
|
scopeStates: ScopedStates;
|
|
31
25
|
recent: RecentTransitionWindow;
|
|
26
|
+
historyLimit: number;
|
|
32
27
|
temporal?: { head: TransitionBoundary; historyDepth: number; tailCounts: Record<StateScope, number> };
|
|
33
28
|
staleArtifacts: readonly StaleArtifactDiagnostic[];
|
|
34
|
-
artifactFreshnessError?: string;
|
|
35
29
|
durableStateError?: string;
|
|
36
|
-
pendingPublication?: PendingPublicationDiagnostic;
|
|
37
|
-
publicationQueue?: PublicationQueueState;
|
|
38
|
-
publicationQueueError?: string;
|
|
39
30
|
}
|
|
40
31
|
|
|
41
32
|
export function compactStatus(snapshot: Snapshot, colorize: Colorize): string | undefined {
|
|
@@ -47,13 +38,9 @@ function countArtifacts(states: ScopedStates, scope: StateScope): number {
|
|
|
47
38
|
return Object.keys(states[scope].artifacts).length;
|
|
48
39
|
}
|
|
49
40
|
|
|
50
|
-
function abbreviatedCommit(commit: string): string {
|
|
51
|
-
return commit.length > 12 ? commit.slice(0, 12) : commit;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
41
|
export function detailedStatus(snapshot: Snapshot, diagnostics: StatusDiagnostics): string {
|
|
55
42
|
const projectedRecent = projectRecentTransitionsWithLimit(
|
|
56
|
-
|
|
43
|
+
diagnostics.historyLimit,
|
|
57
44
|
diagnostics.recent,
|
|
58
45
|
);
|
|
59
46
|
const available = diagnostics.temporal !== undefined && diagnostics.durableStateError === undefined;
|
|
@@ -63,61 +50,36 @@ export function detailedStatus(snapshot: Snapshot, diagnostics: StatusDiagnostic
|
|
|
63
50
|
diagnostics.scopeStates.session,
|
|
64
51
|
);
|
|
65
52
|
const stateJson = materialized === undefined ? undefined : JSON.stringify(materialized, null, 2);
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
?
|
|
69
|
-
:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const staleLines = freshnessError !== undefined
|
|
74
|
-
? [`Artifact freshness unavailable: ${freshnessError}`]
|
|
75
|
-
: diagnostics.staleArtifacts.length === 0
|
|
76
|
-
? ["Stale artifacts: none"]
|
|
77
|
-
: [
|
|
78
|
-
"Stale artifacts:",
|
|
79
|
-
...diagnostics.staleArtifacts.map(({ scope, path, reason }) => `- [${scope}] ${path} — ${reason}`),
|
|
80
|
-
];
|
|
53
|
+
const invalidated = available ? String(diagnostics.staleArtifacts.length) : "unavailable";
|
|
54
|
+
const invalidationLines = diagnostics.staleArtifacts.length === 0
|
|
55
|
+
? ["Pending artifact invalidations: none"]
|
|
56
|
+
: [
|
|
57
|
+
"Pending artifact invalidations:",
|
|
58
|
+
...diagnostics.staleArtifacts.map(({ scope, path, reason }) => `- [${scope}] ${path} — ${reason}`),
|
|
59
|
+
];
|
|
81
60
|
const temporal = available ? diagnostics.temporal : undefined;
|
|
82
61
|
const temporalLines = temporal === undefined
|
|
83
62
|
? [`Temporal materialization unavailable: ${diagnostics.durableStateError ?? "no selected branch runtime"}`,
|
|
84
|
-
|
|
63
|
+
`Hot history: unavailable; configured maximum depth ${diagnostics.historyLimit}`,
|
|
85
64
|
"Retained patch tails: unavailable"]
|
|
86
65
|
: [`Temporal head: ${JSON.stringify(temporal.head.id)}; branch-local position ${temporal.head.position}`,
|
|
87
|
-
`Hot history: offsets 0..${temporal.historyDepth}; maximum depth
|
|
66
|
+
`Hot history: offsets 0..${temporal.historyDepth}; maximum depth ${diagnostics.historyLimit}`,
|
|
88
67
|
`Retained patch tails: global ${temporal.tailCounts.global}; CWD ${temporal.tailCounts.cwd}; session ${temporal.tailCounts.session}`];
|
|
89
68
|
const artifacts = (scope: StateScope) => available ? countArtifacts(diagnostics.scopeStates, scope) : "unknown";
|
|
90
|
-
const promotions = available ? inspectMemoryPromotions(diagnostics.scopeStates.global) : [];
|
|
91
|
-
const promotionCounts = Object.fromEntries(["pending", "accepted", "failed", "unknown", "invalid"].map((status) => [status, promotions.filter((entry) => entry.status === status).length]));
|
|
92
69
|
const memoryScopes = available ? retainedMemoryScopes(diagnostics.scopeStates) : undefined;
|
|
93
|
-
const oneLine = (value: string) => value.replace(/\s+/g, " ").slice(0, 240);
|
|
94
|
-
const promotionLines = !available || promotions.length === 0 ? [] : [
|
|
95
|
-
"Memory promotions:",
|
|
96
|
-
...promotions.map((entry) => `- ${oneLine(entry.id)} — ${entry.status}; owner ${oneLine(entry.owner ?? "unavailable")}${entry.pointer ? `; pointer ${oneLine(entry.pointer)}` : ""}${entry.revision ? `; revision ${oneLine(entry.revision)}` : ""}${entry.error ? `; error ${oneLine(entry.error)}` : ""}`),
|
|
97
|
-
];
|
|
98
70
|
|
|
99
71
|
return [
|
|
100
72
|
`State Flow diagnostics — config.enabled=${snapshot.config.enabled}; branch mode=${snapshot.config.enabled ? "active" : "inactive"}`,
|
|
101
73
|
`Repository: ${diagnostics.repositoryRoot}`,
|
|
102
74
|
`Scope keys: CWD ${diagnostics.cwdScopeKey}; session ${diagnostics.sessionScopeKey}`,
|
|
103
75
|
"Session files: config.json owns behavior; runtime.json owns branch recovery; meta.json owns scope provenance",
|
|
104
|
-
`Runtime metadata: step #${snapshot.meta.step};
|
|
105
|
-
`Remote publication policy: ${snapshot.meta.remotePublication?.mode ?? "legacy-transition"}`,
|
|
106
|
-
diagnostics.publicationQueueError !== undefined
|
|
107
|
-
? `Remote queue: unavailable; error ${diagnostics.publicationQueueError}`
|
|
108
|
-
: diagnostics.publicationQueue === undefined
|
|
109
|
-
? "Remote queue: idle"
|
|
110
|
-
: `Remote queue: ${diagnostics.publicationQueue.status}; target ${abbreviatedCommit(diagnostics.publicationQueue.target)}; confirmed ${diagnostics.publicationQueue.confirmed ? abbreviatedCommit(diagnostics.publicationQueue.confirmed) : "none"}; attempt ${diagnostics.publicationQueue.attempt}${diagnostics.publicationQueue.error ? `; error ${diagnostics.publicationQueue.error}` : ""}`,
|
|
76
|
+
`Runtime metadata: step #${snapshot.meta.step}; bootstrap ${snapshot.meta.bootstrap === true}`,
|
|
111
77
|
"Memory: owner state-flow; global retention enabled; global fallback active",
|
|
112
78
|
`Memory-bearing scopes: global ${memoryScopes?.global ?? "unknown"}; CWD ${memoryScopes?.cwd ?? "unknown"}; session ${memoryScopes?.session ?? "unknown"}`,
|
|
113
|
-
`Promotion status: pending ${promotionCounts.pending}; accepted ${promotionCounts.accepted}; failed ${promotionCounts.failed}; unknown ${promotionCounts.unknown}; invalid ${promotionCounts.invalid}`,
|
|
114
|
-
...promotionLines,
|
|
115
79
|
...temporalLines,
|
|
116
|
-
`Artifacts: global ${artifacts("global")}; CWD ${artifacts("cwd")}; session ${artifacts("session")};
|
|
80
|
+
`Artifacts: global ${artifacts("global")}; CWD ${artifacts("cwd")}; session ${artifacts("session")}; pending invalidations ${invalidated}`,
|
|
117
81
|
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",
|
|
118
|
-
|
|
119
|
-
`Publication: ${publication}`,
|
|
120
|
-
...staleLines,
|
|
82
|
+
...invalidationLines,
|
|
121
83
|
...(stateJson === undefined
|
|
122
84
|
? ["Effective memory: unavailable"]
|
|
123
85
|
: [`Effective memory (${Buffer.byteLength(stateJson, "utf8")} JSON bytes; global → CWD → session overlay):`, "", stateJson]),
|