@llblab/pi-kit 0.18.2 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +3 -1
  3. package/node_modules/@llblab/pi-state-flow/AGENTS.md +35 -37
  4. package/node_modules/@llblab/pi-state-flow/BACKLOG.md +5 -3
  5. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +19 -1
  6. package/node_modules/@llblab/pi-state-flow/README.md +102 -48
  7. package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +6 -9
  8. package/node_modules/@llblab/pi-state-flow/dist/index.js +6 -9
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +2 -2
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +21 -8
  11. package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.d.ts +40 -24
  12. package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.js +93 -63
  13. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +4 -3
  14. package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +9 -9
  15. package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +1 -1
  16. package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +6 -5
  17. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +8 -7
  18. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +56 -58
  19. package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +12 -24
  20. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +7 -18
  21. package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +47 -78
  22. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +4 -6
  23. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +241 -437
  24. package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +2 -72
  25. package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +120 -499
  26. package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +2 -1
  27. package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +4 -3
  28. package/node_modules/@llblab/pi-state-flow/dist/lib/json.d.ts +3 -0
  29. package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +43 -22
  30. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +1 -5
  31. package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +0 -2
  32. package/node_modules/@llblab/pi-state-flow/dist/lib/memory.d.ts +1 -14
  33. package/node_modules/@llblab/pi-state-flow/dist/lib/memory.js +5 -37
  34. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +1 -2
  35. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +13 -32
  36. package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +6 -6
  37. package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +25 -21
  38. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +3 -3
  39. package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +15 -12
  40. package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.d.ts +2 -4
  41. package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.js +5 -1
  42. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +26 -88
  43. package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +159 -255
  44. package/node_modules/@llblab/pi-state-flow/dist/lib/skills.d.ts +0 -3
  45. package/node_modules/@llblab/pi-state-flow/dist/lib/skills.js +1 -47
  46. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +16 -33
  47. package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +48 -137
  48. package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +16 -11
  49. package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +13 -14
  50. package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +1 -9
  51. package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +15 -43
  52. package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +5 -9
  53. package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +13 -45
  54. package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +1 -1
  55. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +15 -7
  56. package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +104 -24
  57. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +0 -2
  58. package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +11 -14
  59. package/node_modules/@llblab/pi-state-flow/dist/package.json +9 -6
  60. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +11 -17
  61. package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +8 -8
  62. package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -2
  63. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +64 -67
  64. package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +24 -6
  65. package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +12 -15
  66. package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +22 -27
  67. package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +25 -41
  68. package/node_modules/@llblab/pi-state-flow/docs/performance.md +38 -421
  69. package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +33 -46
  70. package/node_modules/@llblab/pi-state-flow/docs/usage.md +37 -61
  71. package/node_modules/@llblab/pi-state-flow/index.ts +7 -71
  72. package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +26 -11
  73. package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +116 -88
  74. package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +12 -10
  75. package/node_modules/@llblab/pi-state-flow/lib/config.ts +6 -6
  76. package/node_modules/@llblab/pi-state-flow/lib/context.ts +52 -59
  77. package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +11 -20
  78. package/node_modules/@llblab/pi-state-flow/lib/durable.ts +44 -86
  79. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +237 -460
  80. package/node_modules/@llblab/pi-state-flow/lib/git.ts +110 -552
  81. package/node_modules/@llblab/pi-state-flow/lib/history.ts +4 -3
  82. package/node_modules/@llblab/pi-state-flow/lib/json.ts +39 -23
  83. package/node_modules/@llblab/pi-state-flow/lib/logging.ts +1 -7
  84. package/node_modules/@llblab/pi-state-flow/lib/memory.ts +5 -44
  85. package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +14 -25
  86. package/node_modules/@llblab/pi-state-flow/lib/query.ts +26 -22
  87. package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +17 -11
  88. package/node_modules/@llblab/pi-state-flow/lib/rehydration.ts +7 -5
  89. package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +154 -254
  90. package/node_modules/@llblab/pi-state-flow/lib/skills.ts +1 -49
  91. package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +58 -142
  92. package/node_modules/@llblab/pi-state-flow/lib/state.ts +27 -19
  93. package/node_modules/@llblab/pi-state-flow/lib/status.ts +16 -54
  94. package/node_modules/@llblab/pi-state-flow/lib/storage.ts +12 -40
  95. package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +1 -1
  96. package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +104 -22
  97. package/node_modules/@llblab/pi-state-flow/lib/transition.ts +16 -26
  98. package/node_modules/@llblab/pi-state-flow/package.json +9 -6
  99. package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +11 -17
  100. package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +8 -8
  101. package/package.json +2 -2
  102. package/node_modules/@llblab/pi-state-flow/dist/lib/discovery.d.ts +0 -21
  103. package/node_modules/@llblab/pi-state-flow/dist/lib/discovery.js +0 -125
  104. package/node_modules/@llblab/pi-state-flow/dist/lib/maintenance.d.ts +0 -36
  105. package/node_modules/@llblab/pi-state-flow/dist/lib/maintenance.js +0 -98
  106. package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +0 -13
  107. package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +0 -167
  108. package/node_modules/@llblab/pi-state-flow/dist/lib/publication.d.ts +0 -86
  109. package/node_modules/@llblab/pi-state-flow/dist/lib/publication.js +0 -437
  110. package/node_modules/@llblab/pi-state-flow/lib/discovery.ts +0 -133
  111. package/node_modules/@llblab/pi-state-flow/lib/maintenance.ts +0 -147
  112. package/node_modules/@llblab/pi-state-flow/lib/migration.ts +0 -171
  113. package/node_modules/@llblab/pi-state-flow/lib/publication.ts +0 -458
@@ -1,11 +1,8 @@
1
1
  import { type ArtifactProvenance, type ArtifactRegistry } from "./artifact.ts";
2
- import type { MaterializedState } from "./state.ts";
3
2
  export declare const SKILL_ARTIFACT_COMPILER = "skill-artifact-v1";
4
3
  export declare function hasCompiledSkillArtifact(artifacts: ArtifactRegistry, provenance: ArtifactProvenance | undefined, source: string, expectedHash?: string): boolean;
5
4
  export type SkillSourceHasher = (source: string) => string;
6
5
  export declare function hashSkillSource(source: string): string;
7
- /** Move the retired contract store into source-addressed Skill artifacts. */
8
- export declare function migrateLegacySkillCompilations(state: MaterializedState, hasher?: SkillSourceHasher): MaterializedState;
9
6
  export declare function skillPathFromRead(toolName: unknown, args: unknown): string | undefined;
10
7
  export interface SuccessfulSkillRead {
11
8
  path: string;
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { hashArtifactSource, isArtifactHash, } from "./artifact.js";
3
- import { canonicalJson, isObject } from "./json.js";
3
+ import { isObject } from "./json.js";
4
4
  export const SKILL_ARTIFACT_COMPILER = "skill-artifact-v1";
5
5
  function hasContent(value) {
6
6
  if (typeof value === "string")
@@ -31,52 +31,6 @@ export function hasCompiledSkillArtifact(artifacts, provenance, source, expected
31
31
  export function hashSkillSource(source) {
32
32
  return hashArtifactSource(readFileSync(source));
33
33
  }
34
- function legacyCompilation(value) {
35
- if (!hasContent(value))
36
- return undefined;
37
- return isObject(value) ? structuredClone(value) : { value: structuredClone(value) };
38
- }
39
- /** Move the retired contract store into source-addressed Skill artifacts. */
40
- export function migrateLegacySkillCompilations(state, hasher = hashSkillSource) {
41
- if (!isObject(state.contract.compiled_skills))
42
- return structuredClone(state);
43
- const legacy = state.contract.compiled_skills;
44
- const next = structuredClone(state);
45
- delete next.contract.compiled_skills;
46
- for (const [source, value] of Object.entries(legacy)) {
47
- const compilation = legacyCompilation(value);
48
- if (!compilation)
49
- continue;
50
- let hash;
51
- let verified = true;
52
- try {
53
- hash = hasher(source);
54
- if (!isArtifactHash(hash))
55
- throw new Error("invalid source hash");
56
- }
57
- catch {
58
- // Preserve useful legacy behavior while ensuring a later observable source
59
- // identity normally invalidates this explicitly unverified fallback.
60
- hash = hashArtifactSource(canonicalJson({ source, compilation }));
61
- verified = false;
62
- }
63
- const metadata = {
64
- description: `Compiled operational guidance for the Skill at ${source}`,
65
- hash,
66
- compiler: SKILL_ARTIFACT_COMPILER,
67
- kind: "skill",
68
- compilation,
69
- ...(verified ? {} : { source_hash_verified: false }),
70
- };
71
- Object.defineProperty(next.artifacts, source, {
72
- value: metadata,
73
- enumerable: true,
74
- configurable: true,
75
- writable: true,
76
- });
77
- }
78
- return next;
79
- }
80
34
  export function skillPathFromRead(toolName, args) {
81
35
  if (toolName !== "read" || !isObject(args) || typeof args.path !== "string")
82
36
  return undefined;
@@ -1,5 +1,4 @@
1
1
  import { type ArtifactProvenanceRegistry } from "./artifact.ts";
2
- import { type RemotePublicationPolicyDocument } from "./publication.ts";
3
2
  import { type JsonObject } from "./json.ts";
4
3
  import { type TransitionBoundary } from "./temporal.ts";
5
4
  /** Missing operational capability is not evidence that a checkpoint target is invalid. */
@@ -8,24 +7,17 @@ export declare class RevisionUnavailableError extends Error {
8
7
  export interface SnapshotConfig {
9
8
  enabled: boolean;
10
9
  }
11
- export interface PendingPublicationState {
12
- commit: string;
13
- error: string;
14
- }
15
10
  interface LegacyValidationFeedback {
16
11
  attempt: number;
17
12
  error: string;
18
13
  instruction: string;
19
14
  }
20
15
  export interface SnapshotMeta {
21
- durableBase?: string;
22
- pendingPublication?: PendingPublicationState;
23
16
  step: number;
24
17
  specification?: string;
25
18
  /** Read-only compatibility/recovery diagnostic; 0.7 never schedules terminal-envelope retries. */
26
19
  validation?: LegacyValidationFeedback;
27
20
  bootstrap?: boolean;
28
- remotePublication?: RemotePublicationPolicyDocument;
29
21
  }
30
22
  /** In-memory runtime config/provenance; durable config/meta and scope files own restoration. */
31
23
  export interface StateFlowSnapshot {
@@ -35,20 +27,15 @@ export interface StateFlowSnapshot {
35
27
  export type Snapshot = StateFlowSnapshot;
36
28
  export interface SessionRuntime {
37
29
  config: SnapshotConfig;
38
- meta: Omit<SnapshotMeta, "durableBase" | "pendingPublication"> & {
30
+ meta: SnapshotMeta & {
39
31
  version: 1;
40
32
  identity: {
41
33
  cwd: string;
42
34
  sessionId: string;
43
35
  };
44
36
  lineage: TransitionBoundary[];
45
- /** Runtime-owned artifact freshness evidence; never projected as semantic state. */
37
+ /** Runtime-owned artifact compilation evidence; never projected as semantic state. */
46
38
  artifacts?: ArtifactProvenanceRegistry;
47
- /** Resolved against the commit that last wrote this runtime record, not arbitrary HEAD. */
48
- revision: "self";
49
- temporalRevision?: "self" | string;
50
- /** Durable intent survives a crash before the push result can be observed. */
51
- publication: "unconfirmed" | "files";
52
39
  temporal?: {
53
40
  checkpoint: TransitionBoundary;
54
41
  patches: TransitionBoundary[];
@@ -57,32 +44,28 @@ export interface SessionRuntime {
57
44
  };
58
45
  }
59
46
  export declare function validateSessionRuntime(value: unknown, cwd: string, sessionId: string): asserts value is SessionRuntime;
60
- export declare function createSessionRuntime(snapshot: Snapshot, cwd: string, sessionId: string, lineage: readonly TransitionBoundary[], publication?: SessionRuntime["meta"]["publication"], _artifacts?: ArtifactProvenanceRegistry): SessionRuntime;
47
+ export declare function createSessionRuntime(snapshot: Snapshot, cwd: string, sessionId: string, lineage: readonly TransitionBoundary[], _artifacts?: ArtifactProvenanceRegistry): SessionRuntime;
61
48
  export declare function serializeSessionRuntime(runtime: SessionRuntime, cwd: string, sessionId: string): {
62
49
  config: string;
63
50
  runtime: string;
64
51
  };
65
- export declare function parseSessionRuntime(config: string | undefined, runtimeSource: string | undefined, cwd: string, sessionId: string, legacyMetaSource?: string): SessionRuntime | undefined;
66
- export declare function resolveSessionRuntime(runtime: SessionRuntime, revision: string): {
67
- snapshot: Snapshot;
68
- lineage: TransitionBoundary[];
69
- publicationTarget: string;
70
- artifacts: ArtifactProvenanceRegistry;
71
- };
72
- export declare function resolveFileSessionRuntime(runtime: SessionRuntime, revision: string): Snapshot;
52
+ export declare function parseSessionRuntime(config: string | undefined, runtimeSource: string | undefined, cwd: string, sessionId: string): SessionRuntime | undefined;
73
53
  export declare function emptySnapshot(enabled?: boolean): Snapshot;
74
- export type PiCheckpoint = {
75
- revision: string;
76
- } | {
54
+ export type RetainedBoundaryCheckpoint = {
55
+ boundary: string;
56
+ enabled: boolean;
57
+ step: number;
58
+ bootstrap?: true;
59
+ specification?: string;
60
+ };
61
+ export type RetainedPiCheckpoint = RetainedBoundaryCheckpoint | {
77
62
  disabled: true;
78
63
  };
79
64
  export type FileRevision = `file:${string}`;
80
65
  export declare function isFileRevision(value: unknown): value is FileRevision;
81
- export declare function isDurableRevision(value: unknown): value is string;
82
- export declare function isExactRevision(value: unknown): value is string;
83
- export declare function persistableSnapshot(snapshot: Snapshot): PiCheckpoint;
84
- /** Pi checkpoints admit only strict revision pointers or the disabled marker. */
85
- export declare function parsePiCheckpoint(value: unknown): PiCheckpoint;
66
+ /** Encode branch lifecycle against one retained temporal identity without semantic or backup data. */
67
+ export declare function retainedBoundaryCheckpoint(snapshot: Snapshot, boundary: string): RetainedBoundaryCheckpoint;
68
+ /** Decode the 0.17 retained-window checkpoint contract. */
69
+ export declare function parseRetainedPiCheckpoint(value: unknown): RetainedPiCheckpoint;
86
70
  export declare function migrationFailure(data: JsonObject, error: string): Snapshot;
87
- export declare function migrateSnapshot(value: unknown): Snapshot;
88
71
  export {};
@@ -1,6 +1,6 @@
1
1
  import { resolve } from "node:path";
2
2
  import { parseArtifactProvenanceRegistry } from "./artifact.js";
3
- import { parseRemotePublicationPolicyDocument, serializeRemotePublicationPolicyDocument } from "./publication.js";
3
+ import { MAX_HISTORY_LIMIT } from "./history.js";
4
4
  import { canonicalJson, isJsonValue, isObject } from "./json.js";
5
5
  import { validateTemporalLineage } from "./temporal.js";
6
6
  const MAX_RESTORED_STEP = Number.MAX_SAFE_INTEGER - 1;
@@ -12,38 +12,35 @@ export function validateSessionRuntime(value, cwd, sessionId) {
12
12
  if (!isJsonValue(value) || !isObject(value) || Object.keys(value).sort().join(",") !== "config,meta"
13
13
  || !isObject(value.config) || !isObject(value.meta))
14
14
  throw new Error("Invalid State Flow session runtime envelope");
15
- const { version, identity, lineage, revision, temporalRevision, publication, artifacts, temporal: _temporalScope, ...fields } = value.meta;
15
+ const { version, identity, lineage, artifacts, temporal: _temporalScope, ...fields } = value.meta;
16
16
  if (artifacts !== undefined)
17
17
  parseArtifactProvenanceRegistry(artifacts, "State Flow session artifact provenance");
18
- if (temporalRevision !== undefined && temporalRevision !== "self"
19
- && !isExactRevision(temporalRevision))
20
- throw new Error("Invalid temporal revision reference");
21
- if (version !== 1 || revision !== "self" || (publication !== "unconfirmed" && publication !== "files"))
18
+ if (version !== 1)
22
19
  throw new Error("Unsupported State Flow runtime provenance format");
23
- if (publication === "files" && temporalRevision !== undefined && temporalRevision !== "self")
24
- throw new Error("File runtime cannot select a historical temporal revision");
25
20
  if (!isObject(identity) || Object.keys(identity).sort().join(",") !== "cwd,sessionId"
26
21
  || identity.cwd !== resolve(cwd) || identity.sessionId !== sessionId || sessionId.trim().length === 0 || sessionId !== sessionId.trim()) {
27
22
  throw new Error("State Flow runtime scope identity mismatch");
28
23
  }
29
- validateTemporalLineage(lineage);
30
- const known = new Set(["step", "specification", "validation", "bootstrap", "remotePublication"]);
24
+ validateTemporalLineage(lineage, MAX_HISTORY_LIMIT);
25
+ const known = new Set(["step", "specification", "validation", "bootstrap"]);
31
26
  if (Object.keys(fields).some((key) => ["state", "contract", "working", "response"].includes(key))) {
32
27
  throw new Error("Semantic state does not belong in State Flow runtime metadata");
33
28
  }
34
29
  const runtimeFields = Object.fromEntries(Object.entries(fields).filter(([key]) => known.has(key)));
35
- const { transitionWindow: _retiredWindow, ...supportedConfig } = value.config;
36
- const normalized = migrateSnapshot({ config: supportedConfig, meta: runtimeFields });
30
+ const normalized = {
31
+ config: { enabled: value.config.enabled === true },
32
+ meta: restoredMeta(runtimeFields),
33
+ };
37
34
  if (runtimeFields.bootstrap === false)
38
35
  normalized.meta.bootstrap = false;
39
36
  if (runtimeFields.step === Number.MAX_SAFE_INTEGER)
40
37
  normalized.meta.step = Number.MAX_SAFE_INTEGER;
41
- if (canonicalJson({ config: normalized.config, meta: normalized.meta }) !== canonicalJson({ config: supportedConfig, meta: runtimeFields })) {
38
+ if (canonicalJson({ config: normalized.config, meta: normalized.meta }) !== canonicalJson({ config: value.config, meta: runtimeFields })) {
42
39
  throw new Error("Invalid State Flow runtime configuration or counters");
43
40
  }
44
41
  }
45
- export function createSessionRuntime(snapshot, cwd, sessionId, lineage, publication = "unconfirmed", _artifacts = {}) {
46
- const { durableBase: _base, pendingPublication: _publication, ...fields } = snapshot.meta;
42
+ export function createSessionRuntime(snapshot, cwd, sessionId, lineage, _artifacts = {}) {
43
+ const fields = snapshot.meta;
47
44
  const runtime = {
48
45
  config: structuredClone(snapshot.config),
49
46
  meta: {
@@ -51,8 +48,6 @@ export function createSessionRuntime(snapshot, cwd, sessionId, lineage, publicat
51
48
  version: 1,
52
49
  identity: { cwd: resolve(cwd), sessionId },
53
50
  lineage: structuredClone([...lineage]),
54
- revision: "self",
55
- publication,
56
51
  },
57
52
  };
58
53
  validateSessionRuntime(runtime, cwd, sessionId);
@@ -63,37 +58,14 @@ export function serializeSessionRuntime(runtime, cwd, sessionId) {
63
58
  const { temporal: _retiredTemporal, artifacts: _legacyArtifacts, ...runtimeMeta } = runtime.meta;
64
59
  return { config: `${canonicalJson(runtime.config)}\n`, runtime: `${canonicalJson(runtimeMeta)}\n` };
65
60
  }
66
- export function parseSessionRuntime(config, runtimeSource, cwd, sessionId, legacyMetaSource) {
67
- let selected = runtimeSource;
68
- if (selected === undefined && legacyMetaSource !== undefined) {
69
- let legacy;
70
- try {
71
- legacy = JSON.parse(legacyMetaSource);
72
- }
73
- catch {
74
- throw new Error("State Flow session runtime contains invalid JSON");
75
- }
76
- if (isObject(legacy) && (Object.hasOwn(legacy, "identity") || Object.hasOwn(legacy, "lineage")))
77
- selected = legacyMetaSource;
78
- }
79
- if (config === undefined && selected === undefined)
61
+ export function parseSessionRuntime(config, runtimeSource, cwd, sessionId) {
62
+ if (config === undefined && runtimeSource === undefined)
80
63
  return undefined;
81
- if (config === undefined && selected !== undefined) {
82
- let document;
83
- try {
84
- document = JSON.parse(selected);
85
- }
86
- catch {
87
- throw new Error("State Flow session runtime contains invalid JSON");
88
- }
89
- if (isObject(document) && !Object.hasOwn(document, "identity") && !Object.hasOwn(document, "lineage"))
90
- return undefined;
91
- }
92
- if (config === undefined || selected === undefined)
64
+ if (config === undefined || runtimeSource === undefined)
93
65
  throw new Error("Incomplete State Flow config/runtime pair");
94
66
  let runtime;
95
67
  try {
96
- runtime = { config: JSON.parse(config), meta: JSON.parse(selected) };
68
+ runtime = { config: JSON.parse(config), meta: JSON.parse(runtimeSource) };
97
69
  }
98
70
  catch {
99
71
  throw new Error("State Flow session runtime contains invalid JSON");
@@ -102,38 +74,6 @@ export function parseSessionRuntime(config, runtimeSource, cwd, sessionId, legac
102
74
  const { temporal: _legacyTemporal, ...runtimeMeta } = runtime.meta;
103
75
  return { config: { enabled: runtime.config.enabled }, meta: runtimeMeta };
104
76
  }
105
- export function resolveSessionRuntime(runtime, revision) {
106
- validateSessionRuntime(runtime, runtime.meta.identity.cwd, runtime.meta.identity.sessionId);
107
- if (!isExactRevision(revision) || runtime.meta.publication !== "unconfirmed")
108
- throw new Error("Runtime self reference requires its exact Git revision and Git publication provenance");
109
- const { version: _version, identity: _identity, lineage, revision: _self, temporalRevision: _temporal, publication: _intent, artifacts, ...fields } = runtime.meta;
110
- return {
111
- snapshot: { config: structuredClone(runtime.config), meta: { ...structuredClone(fields), durableBase: revision } },
112
- lineage: structuredClone(lineage),
113
- publicationTarget: revision,
114
- artifacts: structuredClone(artifacts ?? {}),
115
- };
116
- }
117
- export function resolveFileSessionRuntime(runtime, revision) {
118
- validateSessionRuntime(runtime, runtime.meta.identity.cwd, runtime.meta.identity.sessionId);
119
- if (!isFileRevision(revision) || runtime.meta.publication !== "files")
120
- throw new Error("File runtime requires its exact file revision and file publication provenance");
121
- const { version: _version, identity: _identity, lineage: _lineage, revision: _self, temporalRevision: _temporal, publication: _intent, ...fields } = runtime.meta;
122
- return { config: structuredClone(runtime.config), meta: { ...structuredClone(fields), durableBase: revision } };
123
- }
124
- function isLegacyTwoPartState(value) {
125
- return isObject(value)
126
- && isObject(value.contract)
127
- && isObject(value.working)
128
- && Object.keys(value).every((key) => key === "contract" || key === "working");
129
- }
130
- function isLegacyThreePartState(value) {
131
- return isObject(value)
132
- && isObject(value.contract)
133
- && isObject(value.working)
134
- && typeof value.response === "string"
135
- && Object.keys(value).every((key) => key === "contract" || key === "working" || key === "response");
136
- }
137
77
  function restoredStep(value) {
138
78
  return typeof value === "number"
139
79
  && Number.isSafeInteger(value)
@@ -156,37 +96,14 @@ function restoredValidation(value) {
156
96
  instruction: value.instruction,
157
97
  };
158
98
  }
159
- function restoredPendingPublication(value) {
160
- if (!isObject(value)
161
- || typeof value.commit !== "string"
162
- || !/^[0-9a-f]{40,64}$/.test(value.commit)
163
- || typeof value.error !== "string"
164
- || value.error.trim().length === 0)
165
- return undefined;
166
- return { commit: value.commit, error: value.error };
167
- }
168
99
  function restoredMeta(value, legacy = {}) {
169
100
  const meta = isObject(value) ? value : legacy;
170
- const pendingPublication = restoredPendingPublication(meta.pendingPublication);
171
101
  const validation = restoredValidation(meta.validation);
172
- let remotePublication;
173
- try {
174
- if (meta.remotePublication !== undefined)
175
- remotePublication = serializeRemotePublicationPolicyDocument(parseRemotePublicationPolicyDocument(meta.remotePublication, { legacyRuntime: false }));
176
- }
177
- catch {
178
- remotePublication = undefined;
179
- }
180
102
  return {
181
- ...(isDurableRevision(meta.durableBase)
182
- ? { durableBase: meta.durableBase }
183
- : {}),
184
- ...(pendingPublication === undefined ? {} : { pendingPublication }),
185
103
  step: restoredStep(meta.step),
186
104
  ...(typeof meta.specification === "string" ? { specification: meta.specification } : {}),
187
105
  ...(validation === undefined ? {} : { validation }),
188
106
  ...(meta.bootstrap === true ? { bootstrap: true } : {}),
189
- ...(remotePublication === undefined ? {} : { remotePublication }),
190
107
  };
191
108
  }
192
109
  function envelope(enabled, meta) {
@@ -198,36 +115,41 @@ export function emptySnapshot(enabled = false) {
198
115
  export function isFileRevision(value) {
199
116
  return typeof value === "string" && /^file:[0-9a-f]{64}$/.test(value);
200
117
  }
201
- export function isDurableRevision(value) {
202
- return isExactRevision(value) || isFileRevision(value);
203
- }
204
- export function isExactRevision(value) {
205
- return typeof value === "string" && /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(value);
206
- }
207
- export function persistableSnapshot(snapshot) {
208
- if (snapshot.meta.durableBase !== undefined) {
209
- if (!isDurableRevision(snapshot.meta.durableBase))
210
- throw new Error("Checkpoint requires an exact Git revision or file reference");
211
- return { revision: snapshot.meta.durableBase };
212
- }
213
- if (snapshot.config.enabled)
214
- throw new Error("Enabled checkpoint requires a durable runtime revision");
215
- return { disabled: true };
118
+ /** Encode branch lifecycle against one retained temporal identity without semantic or backup data. */
119
+ export function retainedBoundaryCheckpoint(snapshot, boundary) {
120
+ if (typeof boundary !== "string" || boundary.trim().length === 0)
121
+ throw new Error("Checkpoint requires a retained temporal boundary identity");
122
+ const checkpoint = {
123
+ boundary,
124
+ enabled: snapshot.config.enabled,
125
+ step: snapshot.meta.step,
126
+ ...(snapshot.meta.bootstrap === true ? { bootstrap: true } : {}),
127
+ ...(snapshot.meta.specification === undefined ? {} : { specification: snapshot.meta.specification }),
128
+ };
129
+ return parseRetainedPiCheckpoint(checkpoint);
216
130
  }
217
- /** Pi checkpoints admit only strict revision pointers or the disabled marker. */
218
- export function parsePiCheckpoint(value) {
131
+ /** Decode the 0.17 retained-window checkpoint contract. */
132
+ export function parseRetainedPiCheckpoint(value) {
219
133
  if (!isObject(value))
220
- throw new Error("Invalid State Flow checkpoint");
221
- if (Object.hasOwn(value, "revision") || Object.hasOwn(value, "disabled")) {
222
- if (Object.keys(value).length === 1) {
223
- if (isDurableRevision(value.revision))
224
- return { revision: value.revision };
225
- if (value.disabled === true)
226
- return { disabled: true };
227
- }
228
- throw new Error("Invalid State Flow checkpoint pointer or disabled marker");
134
+ throw new Error("Invalid State Flow retained-boundary checkpoint");
135
+ if (Object.keys(value).length === 1 && value.disabled === true)
136
+ return { disabled: true };
137
+ const allowed = new Set(["boundary", "enabled", "step", "bootstrap", "specification"]);
138
+ if (Object.keys(value).some((key) => !allowed.has(key))
139
+ || typeof value.boundary !== "string" || value.boundary.trim().length === 0
140
+ || typeof value.enabled !== "boolean"
141
+ || !Number.isSafeInteger(value.step) || value.step < 0 || value.step > MAX_RESTORED_STEP
142
+ || (value.bootstrap !== undefined && value.bootstrap !== true)
143
+ || (value.specification !== undefined && typeof value.specification !== "string")) {
144
+ throw new Error("Invalid State Flow retained-boundary checkpoint");
229
145
  }
230
- throw new Error("Unrecognized State Flow checkpoint");
146
+ return {
147
+ boundary: value.boundary,
148
+ enabled: value.enabled,
149
+ step: value.step,
150
+ ...(value.bootstrap === true ? { bootstrap: true } : {}),
151
+ ...(typeof value.specification === "string" ? { specification: value.specification } : {}),
152
+ };
231
153
  }
232
154
  export function migrationFailure(data, error) {
233
155
  const meta = restoredMeta(data.meta, data);
@@ -238,14 +160,3 @@ export function migrationFailure(data, error) {
238
160
  };
239
161
  return envelope(false, meta);
240
162
  }
241
- export function migrateSnapshot(value) {
242
- if (!isObject(value))
243
- return emptySnapshot();
244
- const isEnvelope = Object.hasOwn(value, "config") || Object.hasOwn(value, "meta");
245
- const config = isEnvelope && isObject(value.config) ? value.config : value;
246
- const meta = restoredMeta(isEnvelope ? value.meta : undefined, value);
247
- const enabled = config.enabled === true;
248
- if (Object.hasOwn(value, "state") || Object.hasOwn(value, "stateBasis") || Object.hasOwn(value, "previousStatePatch"))
249
- return envelope(false, meta);
250
- return envelope(enabled, meta);
251
- }
@@ -1,14 +1,13 @@
1
- import { type ArtifactCompilationUpdate, type ArtifactRegistry } from "./artifact.ts";
2
- import { type JsonObject, type JsonValue } from "./json.ts";
1
+ import { type ArtifactCompilationUpdate, type ArtifactModelHints, type ArtifactRegistry } from "./artifact.ts";
2
+ import { type JsonObject } from "./json.ts";
3
3
  /** The canonical semantic state shape shared by global, CWD, and session scopes. */
4
4
  export type MaterializedState = JsonObject & {
5
- artifacts: ArtifactRegistry;
5
+ intents: JsonObject;
6
6
  contract: JsonObject;
7
7
  working: JsonObject;
8
- intents: JsonObject;
8
+ artifacts: ArtifactRegistry;
9
9
  response: string;
10
- /** Absent is the canonical empty lazy plane and preserves predecessor-store compatibility. */
11
- lazy?: JsonValue;
10
+ lazy: JsonObject;
12
11
  };
13
12
  /** Compatibility name for callers that still treat materialized state as a document. */
14
13
  export type StateDocument = MaterializedState;
@@ -19,6 +18,7 @@ export interface StatePatch extends JsonObject {
19
18
  working: JsonObject;
20
19
  intents: JsonObject;
21
20
  response: string;
21
+ lazy: JsonObject;
22
22
  }
23
23
  export type StateScope = "global" | "cwd" | "session";
24
24
  /** A model-authored patch for one scope. Response is captured by the runtime in session state. */
@@ -27,7 +27,7 @@ export interface ScopePatch {
27
27
  contract?: JsonObject;
28
28
  working?: JsonObject;
29
29
  intents?: JsonObject;
30
- lazy?: JsonValue;
30
+ lazy?: JsonObject;
31
31
  }
32
32
  export interface ScopedPatch {
33
33
  scope: StateScope;
@@ -53,11 +53,16 @@ export interface ScopedStates {
53
53
  export declare function emptyState(): MaterializedState;
54
54
  export declare function isMaterializedState(value: unknown): value is MaterializedState;
55
55
  export declare const isStateDocument: typeof isMaterializedState;
56
- /** Upgrade one exact pre-intents materialized state without inferring commitments. */
57
- export declare function migratePreIntentState(value: unknown): MaterializedState | undefined;
58
56
  /** Atomically replace compiled and removed artifacts inside one materialized scope. */
59
57
  export declare function updateMaterializedArtifacts(state: MaterializedState, updates: readonly ArtifactCompilationUpdate[], removed?: readonly string[]): MaterializedState;
60
58
  /** Overlay lower-to-higher scopes without mutating any scope document. */
61
59
  export declare function overlayStates(...scopes: readonly MaterializedState[]): MaterializedState;
62
- /** Model-visible projection: runtime artifact bookkeeping never reaches ordinary context. */
63
- export declare function projectStateForModel(state: MaterializedState): MaterializedState;
60
+ export type ModelState = JsonObject & {
61
+ intents: JsonObject;
62
+ contract: JsonObject;
63
+ working: JsonObject;
64
+ artifacts: ArtifactRegistry;
65
+ response: string;
66
+ };
67
+ /** Model-visible projection: lazy bodies and runtime artifact bookkeeping stay out of ordinary context. */
68
+ export declare function projectStateForModel(state: MaterializedState, artifactHints?: ArtifactModelHints): ModelState;
@@ -1,7 +1,7 @@
1
1
  import { isArtifactRegistry, projectArtifactsForModel, updateArtifactRegistry, } from "./artifact.js";
2
- import { applyPatch, isJsonValue, isObject } from "./json.js";
2
+ import { applyPatch, isObject } from "./json.js";
3
3
  export function emptyState() {
4
- return { artifacts: {}, contract: {}, working: {}, intents: {}, response: "" };
4
+ return { intents: {}, contract: {}, working: {}, artifacts: {}, response: "", lazy: {} };
5
5
  }
6
6
  export function isMaterializedState(value) {
7
7
  return isObject(value)
@@ -10,17 +10,10 @@ export function isMaterializedState(value) {
10
10
  && isObject(value.working)
11
11
  && isObject(value.intents)
12
12
  && typeof value.response === "string"
13
- && (!Object.hasOwn(value, "lazy") || (isJsonValue(value.lazy) && value.lazy !== null))
13
+ && isObject(value.lazy)
14
14
  && Object.keys(value).every((key) => key === "artifacts" || key === "contract" || key === "working" || key === "intents" || key === "response" || key === "lazy");
15
15
  }
16
16
  export const isStateDocument = isMaterializedState;
17
- /** Upgrade one exact pre-intents materialized state without inferring commitments. */
18
- export function migratePreIntentState(value) {
19
- if (!isObject(value) || Object.hasOwn(value, "intents"))
20
- return undefined;
21
- const candidate = { ...structuredClone(value), intents: {} };
22
- return isMaterializedState(candidate) ? candidate : undefined;
23
- }
24
17
  /** Atomically replace compiled and removed artifacts inside one materialized scope. */
25
18
  export function updateMaterializedArtifacts(state, updates, removed = []) {
26
19
  if (!isMaterializedState(state))
@@ -34,8 +27,14 @@ export function overlayStates(...scopes) {
34
27
  return applyPatch(effective, scope);
35
28
  }, emptyState());
36
29
  }
37
- /** Model-visible projection: runtime artifact bookkeeping never reaches ordinary context. */
38
- export function projectStateForModel(state) {
39
- const { lazy: _lazy, ...hot } = structuredClone(state);
40
- return { ...hot, artifacts: projectArtifactsForModel(state.artifacts) };
30
+ /** Model-visible projection: lazy bodies and runtime artifact bookkeeping stay out of ordinary context. */
31
+ export function projectStateForModel(state, artifactHints = {}) {
32
+ const cloned = structuredClone(state);
33
+ return {
34
+ intents: cloned.intents,
35
+ contract: cloned.contract,
36
+ working: cloned.working,
37
+ artifacts: projectArtifactsForModel(cloned.artifacts, artifactHints),
38
+ response: cloned.response,
39
+ };
41
40
  }
@@ -1,6 +1,5 @@
1
1
  import type { ArtifactInvalidationReason } from "./artifact.ts";
2
2
  import { type RecentTransitionWindow } from "./history.ts";
3
- import type { PublicationQueueState } from "./publication.ts";
4
3
  import type { Snapshot } from "./snapshot.ts";
5
4
  import { type ScopedStates, type StateScope } from "./state.ts";
6
5
  import type { TransitionBoundary } from "./temporal.ts";
@@ -12,27 +11,20 @@ export interface StaleArtifactDiagnostic {
12
11
  path: string;
13
12
  reason: StaleArtifactReason;
14
13
  }
15
- export interface PendingPublicationDiagnostic {
16
- commit: string;
17
- error: string;
18
- }
19
14
  export interface StatusDiagnostics {
20
15
  repositoryRoot: string;
21
16
  cwdScopeKey: string;
22
17
  sessionScopeKey: string;
23
18
  scopeStates: ScopedStates;
24
19
  recent: RecentTransitionWindow;
20
+ historyLimit: number;
25
21
  temporal?: {
26
22
  head: TransitionBoundary;
27
23
  historyDepth: number;
28
24
  tailCounts: Record<StateScope, number>;
29
25
  };
30
26
  staleArtifacts: readonly StaleArtifactDiagnostic[];
31
- artifactFreshnessError?: string;
32
27
  durableStateError?: string;
33
- pendingPublication?: PendingPublicationDiagnostic;
34
- publicationQueue?: PublicationQueueState;
35
- publicationQueueError?: string;
36
28
  }
37
29
  export declare function compactStatus(snapshot: Snapshot, colorize: Colorize): string | undefined;
38
30
  export declare function detailedStatus(snapshot: Snapshot, diagnostics: StatusDiagnostics): string;