youmd 0.10.2 → 0.12.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 (205) hide show
  1. package/dist/commands/brain.d.ts.map +1 -1
  2. package/dist/commands/brain.js +91 -28
  3. package/dist/commands/brain.js.map +1 -1
  4. package/dist/commands/chat.d.ts.map +1 -1
  5. package/dist/commands/chat.js +6 -1
  6. package/dist/commands/chat.js.map +1 -1
  7. package/dist/commands/conversations.d.ts +5 -0
  8. package/dist/commands/conversations.d.ts.map +1 -0
  9. package/dist/commands/conversations.js +116 -0
  10. package/dist/commands/conversations.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +1 -0
  12. package/dist/commands/doctor.d.ts.map +1 -1
  13. package/dist/commands/doctor.js +16 -1
  14. package/dist/commands/doctor.js.map +1 -1
  15. package/dist/commands/founder.d.ts +13 -0
  16. package/dist/commands/founder.d.ts.map +1 -0
  17. package/dist/commands/founder.js +189 -0
  18. package/dist/commands/founder.js.map +1 -0
  19. package/dist/commands/handoff.d.ts +5 -0
  20. package/dist/commands/handoff.d.ts.map +1 -0
  21. package/dist/commands/handoff.js +432 -0
  22. package/dist/commands/handoff.js.map +1 -0
  23. package/dist/commands/orchestrate.d.ts +15 -0
  24. package/dist/commands/orchestrate.d.ts.map +1 -1
  25. package/dist/commands/orchestrate.js +294 -0
  26. package/dist/commands/orchestrate.js.map +1 -1
  27. package/dist/commands/project.d.ts.map +1 -1
  28. package/dist/commands/project.js +8 -1
  29. package/dist/commands/project.js.map +1 -1
  30. package/dist/commands/reconcile.d.ts +15 -0
  31. package/dist/commands/reconcile.d.ts.map +1 -0
  32. package/dist/commands/reconcile.js +260 -0
  33. package/dist/commands/reconcile.js.map +1 -0
  34. package/dist/commands/session.d.ts +28 -0
  35. package/dist/commands/session.d.ts.map +1 -0
  36. package/dist/commands/session.js +895 -0
  37. package/dist/commands/session.js.map +1 -0
  38. package/dist/commands/stack.d.ts +2 -0
  39. package/dist/commands/stack.d.ts.map +1 -1
  40. package/dist/commands/stack.js +26 -0
  41. package/dist/commands/stack.js.map +1 -1
  42. package/dist/commands/sync.d.ts.map +1 -1
  43. package/dist/commands/sync.js +11 -0
  44. package/dist/commands/sync.js.map +1 -1
  45. package/dist/commands/tasks.d.ts +57 -0
  46. package/dist/commands/tasks.d.ts.map +1 -1
  47. package/dist/commands/tasks.js +236 -31
  48. package/dist/commands/tasks.js.map +1 -1
  49. package/dist/generated/capability-registry.d.ts +311 -71
  50. package/dist/generated/capability-registry.d.ts.map +1 -1
  51. package/dist/generated/capability-registry.js +346 -71
  52. package/dist/generated/capability-registry.js.map +1 -1
  53. package/dist/index.js +113 -2
  54. package/dist/index.js.map +1 -1
  55. package/dist/lib/api.d.ts +362 -1
  56. package/dist/lib/api.d.ts.map +1 -1
  57. package/dist/lib/api.js +171 -0
  58. package/dist/lib/api.js.map +1 -1
  59. package/dist/lib/brain/adapters.d.ts +20 -1
  60. package/dist/lib/brain/adapters.d.ts.map +1 -1
  61. package/dist/lib/brain/adapters.js +113 -2
  62. package/dist/lib/brain/adapters.js.map +1 -1
  63. package/dist/lib/brain/approval-key-trust.d.ts +29 -0
  64. package/dist/lib/brain/approval-key-trust.d.ts.map +1 -0
  65. package/dist/lib/brain/approval-key-trust.js +139 -0
  66. package/dist/lib/brain/approval-key-trust.js.map +1 -0
  67. package/dist/lib/brain/cache.d.ts +2 -2
  68. package/dist/lib/brain/cache.d.ts.map +1 -1
  69. package/dist/lib/brain/cache.js +4 -4
  70. package/dist/lib/brain/cache.js.map +1 -1
  71. package/dist/lib/brain/content.d.ts +56 -0
  72. package/dist/lib/brain/content.d.ts.map +1 -0
  73. package/dist/lib/brain/content.js +362 -0
  74. package/dist/lib/brain/content.js.map +1 -0
  75. package/dist/lib/brain/descriptor-validator.d.ts +11 -0
  76. package/dist/lib/brain/descriptor-validator.d.ts.map +1 -0
  77. package/dist/lib/brain/descriptor-validator.js +185 -0
  78. package/dist/lib/brain/descriptor-validator.js.map +1 -0
  79. package/dist/lib/brain/discovery.d.ts.map +1 -1
  80. package/dist/lib/brain/discovery.js +103 -60
  81. package/dist/lib/brain/discovery.js.map +1 -1
  82. package/dist/lib/brain/index.d.ts +2 -0
  83. package/dist/lib/brain/index.d.ts.map +1 -1
  84. package/dist/lib/brain/index.js +8 -2
  85. package/dist/lib/brain/index.js.map +1 -1
  86. package/dist/lib/brain/proposal.d.ts +53 -5
  87. package/dist/lib/brain/proposal.d.ts.map +1 -1
  88. package/dist/lib/brain/proposal.js +341 -64
  89. package/dist/lib/brain/proposal.js.map +1 -1
  90. package/dist/lib/brain/safe-file.d.ts +25 -1
  91. package/dist/lib/brain/safe-file.d.ts.map +1 -1
  92. package/dist/lib/brain/safe-file.js +250 -30
  93. package/dist/lib/brain/safe-file.js.map +1 -1
  94. package/dist/lib/brain/safe-open.d.ts +2 -0
  95. package/dist/lib/brain/safe-open.d.ts.map +1 -0
  96. package/dist/lib/brain/safe-open.js +77 -0
  97. package/dist/lib/brain/safe-open.js.map +1 -0
  98. package/dist/lib/brain/safety.d.ts.map +1 -1
  99. package/dist/lib/brain/safety.js +5 -0
  100. package/dist/lib/brain/safety.js.map +1 -1
  101. package/dist/lib/brain/staged-apply.d.ts +2 -1
  102. package/dist/lib/brain/staged-apply.d.ts.map +1 -1
  103. package/dist/lib/brain/staged-apply.js +6 -3
  104. package/dist/lib/brain/staged-apply.js.map +1 -1
  105. package/dist/lib/brain/store.d.ts +3 -0
  106. package/dist/lib/brain/store.d.ts.map +1 -1
  107. package/dist/lib/brain/store.js +68 -0
  108. package/dist/lib/brain/store.js.map +1 -1
  109. package/dist/lib/brain/sync.d.ts +87 -0
  110. package/dist/lib/brain/sync.d.ts.map +1 -0
  111. package/dist/lib/brain/sync.js +238 -0
  112. package/dist/lib/brain/sync.js.map +1 -0
  113. package/dist/lib/brain/types.d.ts +23 -0
  114. package/dist/lib/brain/types.d.ts.map +1 -1
  115. package/dist/lib/config.d.ts +7 -0
  116. package/dist/lib/config.d.ts.map +1 -1
  117. package/dist/lib/config.js +3 -0
  118. package/dist/lib/config.js.map +1 -1
  119. package/dist/lib/daemon.js +1 -1
  120. package/dist/lib/daemon.js.map +1 -1
  121. package/dist/lib/goalRegistryFile.d.ts +169 -0
  122. package/dist/lib/goalRegistryFile.d.ts.map +1 -0
  123. package/dist/lib/goalRegistryFile.js +518 -0
  124. package/dist/lib/goalRegistryFile.js.map +1 -0
  125. package/dist/lib/goalsFile.d.ts +101 -0
  126. package/dist/lib/goalsFile.d.ts.map +1 -0
  127. package/dist/lib/goalsFile.js +413 -0
  128. package/dist/lib/goalsFile.js.map +1 -0
  129. package/dist/lib/handoff.d.ts +170 -0
  130. package/dist/lib/handoff.d.ts.map +1 -0
  131. package/dist/lib/handoff.js +316 -0
  132. package/dist/lib/handoff.js.map +1 -0
  133. package/dist/lib/machine-identity.d.ts +2 -0
  134. package/dist/lib/machine-identity.d.ts.map +1 -1
  135. package/dist/lib/machine-identity.js +13 -6
  136. package/dist/lib/machine-identity.js.map +1 -1
  137. package/dist/lib/onboarding.d.ts +4 -1
  138. package/dist/lib/onboarding.d.ts.map +1 -1
  139. package/dist/lib/onboarding.js +11 -3
  140. package/dist/lib/onboarding.js.map +1 -1
  141. package/dist/lib/orchestrator/loop.d.ts +7 -0
  142. package/dist/lib/orchestrator/loop.d.ts.map +1 -1
  143. package/dist/lib/orchestrator/loop.js +53 -0
  144. package/dist/lib/orchestrator/loop.js.map +1 -1
  145. package/dist/lib/orchestrator/run-journal.d.ts +178 -0
  146. package/dist/lib/orchestrator/run-journal.d.ts.map +1 -0
  147. package/dist/lib/orchestrator/run-journal.js +912 -0
  148. package/dist/lib/orchestrator/run-journal.js.map +1 -0
  149. package/dist/lib/orchestrator/supervisor.d.ts +11 -0
  150. package/dist/lib/orchestrator/supervisor.d.ts.map +1 -1
  151. package/dist/lib/orchestrator/supervisor.js +304 -116
  152. package/dist/lib/orchestrator/supervisor.js.map +1 -1
  153. package/dist/lib/orchestrator/tools.d.ts +2 -0
  154. package/dist/lib/orchestrator/tools.d.ts.map +1 -1
  155. package/dist/lib/orchestrator/tools.js +214 -1
  156. package/dist/lib/orchestrator/tools.js.map +1 -1
  157. package/dist/lib/redact.d.ts.map +1 -1
  158. package/dist/lib/redact.js +31 -6
  159. package/dist/lib/redact.js.map +1 -1
  160. package/dist/lib/remote-agent-event.d.ts +19 -0
  161. package/dist/lib/remote-agent-event.d.ts.map +1 -0
  162. package/dist/lib/remote-agent-event.js +85 -0
  163. package/dist/lib/remote-agent-event.js.map +1 -0
  164. package/dist/lib/remote-command.d.ts.map +1 -1
  165. package/dist/lib/remote-command.js +19 -0
  166. package/dist/lib/remote-command.js.map +1 -1
  167. package/dist/lib/remote-executor.d.ts +7 -1
  168. package/dist/lib/remote-executor.d.ts.map +1 -1
  169. package/dist/lib/remote-executor.js +391 -0
  170. package/dist/lib/remote-executor.js.map +1 -1
  171. package/dist/lib/sessionCheckpoint.d.ts +104 -0
  172. package/dist/lib/sessionCheckpoint.d.ts.map +1 -0
  173. package/dist/lib/sessionCheckpoint.js +191 -0
  174. package/dist/lib/sessionCheckpoint.js.map +1 -0
  175. package/dist/lib/sessionHandoff.d.ts +47 -0
  176. package/dist/lib/sessionHandoff.d.ts.map +1 -0
  177. package/dist/lib/sessionHandoff.js +305 -0
  178. package/dist/lib/sessionHandoff.js.map +1 -0
  179. package/dist/lib/stream.d.ts +3 -1
  180. package/dist/lib/stream.d.ts.map +1 -1
  181. package/dist/lib/stream.js +8 -3
  182. package/dist/lib/stream.js.map +1 -1
  183. package/dist/lib/taskLedgerProposal.d.ts +102 -0
  184. package/dist/lib/taskLedgerProposal.d.ts.map +1 -0
  185. package/dist/lib/taskLedgerProposal.js +408 -0
  186. package/dist/lib/taskLedgerProposal.js.map +1 -0
  187. package/dist/lib/tasksFile.d.ts +23 -2
  188. package/dist/lib/tasksFile.d.ts.map +1 -1
  189. package/dist/lib/tasksFile.js +122 -10
  190. package/dist/lib/tasksFile.js.map +1 -1
  191. package/dist/mcp/registry.d.ts.map +1 -1
  192. package/dist/mcp/registry.js +110 -0
  193. package/dist/mcp/registry.js.map +1 -1
  194. package/native/prebuilds/darwin-universal/youmd_safe_open.node +0 -0
  195. package/native/safe-open/youmd_safe_open.c +224 -0
  196. package/package.json +11 -3
  197. package/scripts/build-safe-open.mjs +63 -0
  198. package/scripts/skillstack-sync/com.you.context-sync.plist +1 -1
  199. package/scripts/skillstack-sync/com.you.identity-sync.plist +1 -1
  200. package/scripts/skillstack-sync/com.you.orchestrator-watch.plist +1 -1
  201. package/scripts/skillstack-sync/com.you.realtime-sync.plist +7 -1
  202. package/scripts/skillstack-sync/com.you.skillstack-sync.plist +1 -1
  203. package/scripts/skillstack-sync/context-sync.sh +19 -7
  204. package/scripts/skillstack-sync/install-daemons-linux.sh +6 -0
  205. package/scripts/smoke-safe-open-node.cjs +50 -0
@@ -0,0 +1,104 @@
1
+ export declare const SESSION_CHECKPOINT_SCHEMA_VERSION: "you-md/session-checkpoint/v1";
2
+ export type SessionRuntime = "codex" | "claude-code" | "cursor" | "you-agent" | (string & {});
3
+ export interface SessionArtifactRef {
4
+ artifactRef: string;
5
+ mimeType?: string;
6
+ title?: string;
7
+ provider?: string;
8
+ sourceSessionRef?: string;
9
+ storageRef?: string;
10
+ availability?: "available" | "missing" | "permission-required" | "unknown";
11
+ permission?: "owner-private" | "shared" | "public" | "unknown";
12
+ }
13
+ export interface SessionGitState {
14
+ dirtyFiles?: number;
15
+ ahead?: number;
16
+ behind?: number;
17
+ lastCommit?: string;
18
+ statusDigest?: string;
19
+ }
20
+ /**
21
+ * The portable session continuation contract.
22
+ *
23
+ * Raw transcript paths, workspace paths, native runtime ids, and native resume
24
+ * commands are intentionally absent. Those values are machine-local hints, not
25
+ * cross-machine identity or authority.
26
+ */
27
+ export interface PortableSessionCheckpoint {
28
+ schemaVersion: typeof SESSION_CHECKPOINT_SCHEMA_VERSION;
29
+ checkpointRef: string;
30
+ sessionRef: string;
31
+ previousCheckpointRef?: string;
32
+ runtime: SessionRuntime;
33
+ machineRef: string;
34
+ projectRef?: string;
35
+ projectSlug?: string;
36
+ businessRef?: string;
37
+ goalRefs: string[];
38
+ taskRefs: string[];
39
+ runRef?: string;
40
+ sourceRevision: string;
41
+ branch?: string;
42
+ worktreeRef?: string;
43
+ repoRef?: string;
44
+ now: string;
45
+ recent: string[];
46
+ next: string[];
47
+ blockers: string[];
48
+ decisions: string[];
49
+ artifactRefs: SessionArtifactRef[];
50
+ gitState?: SessionGitState;
51
+ eventAt: number;
52
+ secretValuesExposed: false;
53
+ }
54
+ export interface SessionCheckpointInput {
55
+ runtime: SessionRuntime;
56
+ machineRef: string;
57
+ /**
58
+ * Adapter-local entropy used only inside a one-way hash. It disambiguates
59
+ * concurrent native sessions without publishing the vendor's private id.
60
+ */
61
+ localSessionAnchor?: string;
62
+ /** Inherited portable identity when a different machine resumes the task. */
63
+ sessionRef?: string;
64
+ /** Prior accepted portable checkpoint; never inferred from local scan order. */
65
+ previousCheckpointRef?: string;
66
+ projectRef?: string;
67
+ projectSlug?: string;
68
+ businessRef?: string;
69
+ goalRefs?: string[];
70
+ taskRefs?: string[];
71
+ runRef?: string;
72
+ sourceRevision: string;
73
+ branch?: string;
74
+ worktreeRef?: string;
75
+ repoRef?: string;
76
+ now?: string;
77
+ recent?: string[];
78
+ next?: string[];
79
+ blockers?: string[];
80
+ decisions?: string[];
81
+ artifactRefs?: SessionArtifactRef[];
82
+ gitState?: SessionGitState;
83
+ eventAt: number;
84
+ }
85
+ export interface RuntimeCheckpointAdapterInput extends Omit<SessionCheckpointInput, "runtime"> {
86
+ /** Local-only command. Returned beside the checkpoint, never inside it. */
87
+ nativeResumeHint?: string;
88
+ }
89
+ export interface RuntimeCheckpointAdapterResult {
90
+ checkpoint: PortableSessionCheckpoint;
91
+ nativeResumeHint?: string;
92
+ }
93
+ export declare function stableCheckpointHash(value: unknown): string;
94
+ /**
95
+ * Builds a stable checkpoint. `eventAt` is retained as provenance but omitted
96
+ * from checkpoint identity, so polling the same semantic input at a later time
97
+ * dedupes without a new model call or append-only row.
98
+ */
99
+ export declare function buildPortableSessionCheckpoint(input: SessionCheckpointInput): PortableSessionCheckpoint;
100
+ export declare function adaptCodexCheckpoint(input: RuntimeCheckpointAdapterInput): RuntimeCheckpointAdapterResult;
101
+ export declare function adaptClaudeCheckpoint(input: RuntimeCheckpointAdapterInput): RuntimeCheckpointAdapterResult;
102
+ /** Preserve first-seen event provenance while dropping unchanged checkpoints. */
103
+ export declare function dedupeUnchangedCheckpoints(checkpoints: PortableSessionCheckpoint[]): PortableSessionCheckpoint[];
104
+ //# sourceMappingURL=sessionCheckpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionCheckpoint.d.ts","sourceRoot":"","sources":["../../src/lib/sessionCheckpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SESSION_CHECKPOINT_SCHEMA_VERSION = void 0;
4
+ exports.stableCheckpointHash = stableCheckpointHash;
5
+ exports.buildPortableSessionCheckpoint = buildPortableSessionCheckpoint;
6
+ exports.adaptCodexCheckpoint = adaptCodexCheckpoint;
7
+ exports.adaptClaudeCheckpoint = adaptClaudeCheckpoint;
8
+ exports.dedupeUnchangedCheckpoints = dedupeUnchangedCheckpoints;
9
+ const node_crypto_1 = require("node:crypto");
10
+ const redact_1 = require("./redact");
11
+ exports.SESSION_CHECKPOINT_SCHEMA_VERSION = "you-md/session-checkpoint/v1";
12
+ const MAX_TEXT_LENGTH = 500;
13
+ const MAX_LIST_ITEMS = 8;
14
+ const MAX_ARTIFACTS = 12;
15
+ function sha256(value) {
16
+ return (0, node_crypto_1.createHash)("sha256").update(value, "utf8").digest("hex");
17
+ }
18
+ function stableValue(value) {
19
+ if (Array.isArray(value))
20
+ return value.map(stableValue);
21
+ if (value && typeof value === "object") {
22
+ return Object.fromEntries(Object.entries(value)
23
+ .filter(([, child]) => child !== undefined)
24
+ .sort(([a], [b]) => a.localeCompare(b))
25
+ .map(([key, child]) => [key, stableValue(child)]));
26
+ }
27
+ return value;
28
+ }
29
+ function stableCheckpointHash(value) {
30
+ return sha256(JSON.stringify(stableValue(value)));
31
+ }
32
+ function cleanText(value) {
33
+ if (!value)
34
+ return "";
35
+ const normalized = value.replace(/\s+/g, " ").trim().slice(0, MAX_TEXT_LENGTH);
36
+ return (0, redact_1.redactText)(normalized).text;
37
+ }
38
+ function cleanList(values) {
39
+ if (!values)
40
+ return [];
41
+ const seen = new Set();
42
+ const out = [];
43
+ for (const value of values) {
44
+ const clean = cleanText(value);
45
+ if (!clean || seen.has(clean))
46
+ continue;
47
+ seen.add(clean);
48
+ out.push(clean);
49
+ if (out.length >= MAX_LIST_ITEMS)
50
+ break;
51
+ }
52
+ return out;
53
+ }
54
+ function cleanRef(value) {
55
+ const clean = cleanText(value);
56
+ if (!clean)
57
+ return undefined;
58
+ // Refs are compact identifiers, never local filesystem paths or URLs with
59
+ // embedded credentials.
60
+ return clean.slice(0, 240);
61
+ }
62
+ function cleanArtifact(artifact) {
63
+ const artifactRef = cleanRef(artifact.artifactRef);
64
+ if (!artifactRef)
65
+ return null;
66
+ return {
67
+ artifactRef,
68
+ ...(cleanRef(artifact.mimeType) ? { mimeType: cleanRef(artifact.mimeType) } : {}),
69
+ ...(cleanText(artifact.title) ? { title: cleanText(artifact.title) } : {}),
70
+ ...(cleanRef(artifact.provider) ? { provider: cleanRef(artifact.provider) } : {}),
71
+ ...(cleanRef(artifact.sourceSessionRef)
72
+ ? { sourceSessionRef: cleanRef(artifact.sourceSessionRef) }
73
+ : {}),
74
+ ...(cleanRef(artifact.storageRef) ? { storageRef: cleanRef(artifact.storageRef) } : {}),
75
+ ...(artifact.availability ? { availability: artifact.availability } : {}),
76
+ ...(artifact.permission ? { permission: artifact.permission } : {}),
77
+ };
78
+ }
79
+ function cleanGitState(value) {
80
+ if (!value)
81
+ return undefined;
82
+ const result = {};
83
+ if (Number.isSafeInteger(value.dirtyFiles) && (value.dirtyFiles ?? -1) >= 0) {
84
+ result.dirtyFiles = value.dirtyFiles;
85
+ }
86
+ if (Number.isSafeInteger(value.ahead) && (value.ahead ?? -1) >= 0)
87
+ result.ahead = value.ahead;
88
+ if (Number.isSafeInteger(value.behind) && (value.behind ?? -1) >= 0) {
89
+ result.behind = value.behind;
90
+ }
91
+ const lastCommit = cleanRef(value.lastCommit);
92
+ if (lastCommit)
93
+ result.lastCommit = lastCommit;
94
+ const statusDigest = cleanRef(value.statusDigest);
95
+ if (statusDigest)
96
+ result.statusDigest = statusDigest;
97
+ return Object.keys(result).length > 0 ? result : undefined;
98
+ }
99
+ /**
100
+ * Builds a stable checkpoint. `eventAt` is retained as provenance but omitted
101
+ * from checkpoint identity, so polling the same semantic input at a later time
102
+ * dedupes without a new model call or append-only row.
103
+ */
104
+ function buildPortableSessionCheckpoint(input) {
105
+ const runtime = cleanRef(input.runtime) ?? "unknown";
106
+ const machineRef = cleanRef(input.machineRef);
107
+ const sourceRevision = cleanRef(input.sourceRevision);
108
+ if (!machineRef)
109
+ throw new Error("machineRef is required");
110
+ if (!sourceRevision)
111
+ throw new Error("sourceRevision is required");
112
+ if (!Number.isFinite(input.eventAt) || input.eventAt <= 0) {
113
+ throw new Error("eventAt must be a positive timestamp");
114
+ }
115
+ const projectRef = cleanRef(input.projectRef);
116
+ const projectSlug = cleanRef(input.projectSlug);
117
+ const repoRef = cleanRef(input.repoRef);
118
+ const localAnchorDigest = input.localSessionAnchor
119
+ ? stableCheckpointHash(cleanText(input.localSessionAnchor))
120
+ : undefined;
121
+ const inheritedSessionRef = cleanRef(input.sessionRef);
122
+ const sessionRef = inheritedSessionRef || `session:${stableCheckpointHash({
123
+ runtime,
124
+ machineRef,
125
+ projectRef,
126
+ projectSlug,
127
+ repoRef,
128
+ localAnchorDigest,
129
+ })}`;
130
+ const artifactRefs = (input.artifactRefs ?? [])
131
+ .slice(0, MAX_ARTIFACTS)
132
+ .map(cleanArtifact)
133
+ .filter((artifact) => artifact !== null);
134
+ const withoutIdentity = {
135
+ schemaVersion: exports.SESSION_CHECKPOINT_SCHEMA_VERSION,
136
+ sessionRef,
137
+ previousCheckpointRef: cleanRef(input.previousCheckpointRef),
138
+ runtime,
139
+ machineRef,
140
+ projectRef,
141
+ projectSlug,
142
+ businessRef: cleanRef(input.businessRef),
143
+ goalRefs: cleanList(input.goalRefs),
144
+ taskRefs: cleanList(input.taskRefs),
145
+ runRef: cleanRef(input.runRef),
146
+ sourceRevision,
147
+ branch: cleanRef(input.branch),
148
+ worktreeRef: cleanRef(input.worktreeRef),
149
+ repoRef,
150
+ now: cleanText(input.now),
151
+ recent: cleanList(input.recent),
152
+ next: cleanList(input.next),
153
+ blockers: cleanList(input.blockers),
154
+ decisions: cleanList(input.decisions),
155
+ artifactRefs,
156
+ gitState: cleanGitState(input.gitState),
157
+ secretValuesExposed: false,
158
+ };
159
+ const checkpointRef = `checkpoint:${stableCheckpointHash(withoutIdentity)}`;
160
+ if (withoutIdentity.previousCheckpointRef === checkpointRef) {
161
+ throw new Error("previousCheckpointRef cannot self-reference");
162
+ }
163
+ return {
164
+ ...withoutIdentity,
165
+ checkpointRef,
166
+ eventAt: Math.round(input.eventAt),
167
+ };
168
+ }
169
+ function adaptCodexCheckpoint(input) {
170
+ return {
171
+ checkpoint: buildPortableSessionCheckpoint({ ...input, runtime: "codex" }),
172
+ ...(input.nativeResumeHint ? { nativeResumeHint: input.nativeResumeHint } : {}),
173
+ };
174
+ }
175
+ function adaptClaudeCheckpoint(input) {
176
+ return {
177
+ checkpoint: buildPortableSessionCheckpoint({ ...input, runtime: "claude-code" }),
178
+ ...(input.nativeResumeHint ? { nativeResumeHint: input.nativeResumeHint } : {}),
179
+ };
180
+ }
181
+ /** Preserve first-seen event provenance while dropping unchanged checkpoints. */
182
+ function dedupeUnchangedCheckpoints(checkpoints) {
183
+ const seen = new Set();
184
+ return checkpoints.filter((checkpoint) => {
185
+ if (seen.has(checkpoint.checkpointRef))
186
+ return false;
187
+ seen.add(checkpoint.checkpointRef);
188
+ return true;
189
+ });
190
+ }
191
+ //# sourceMappingURL=sessionCheckpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionCheckpoint.js","sourceRoot":"","sources":["../../src/lib/sessionCheckpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { PortableSessionCheckpoint, SessionRuntime } from "./sessionCheckpoint";
2
+ export declare const SESSION_HANDOFF_SCHEMA_VERSION: "you-md/session-handoff/v1";
3
+ export declare const SESSION_HANDOFF_REGISTRY_VERSION: "you-md/session-handoff-registry/v1";
4
+ export interface SessionHandoffBinding {
5
+ sessionRef: string;
6
+ previousCheckpointRef: string;
7
+ }
8
+ export interface CreateSessionHandoffInput {
9
+ checkpoint: PortableSessionCheckpoint;
10
+ projectDir: string;
11
+ baseDir?: string;
12
+ now?: number;
13
+ ttlMs?: number;
14
+ /** Origin-local vendor id, accepted only so it can be scrubbed. */
15
+ originNativeSessionId?: string;
16
+ }
17
+ export interface CreatedSessionHandoff {
18
+ schemaVersion: typeof SESSION_HANDOFF_SCHEMA_VERSION;
19
+ checkpointRef: string;
20
+ sessionRef: string;
21
+ briefPath: string;
22
+ runtime: "codex" | "claude-code";
23
+ command: string;
24
+ expiresAt: number;
25
+ secretValuesExposed: false;
26
+ }
27
+ export interface ConsumeSessionHandoffInput {
28
+ runtime: SessionRuntime;
29
+ projectSlug?: string;
30
+ repoRef?: string;
31
+ workspacePath?: string;
32
+ localSessionAnchor?: string;
33
+ sessionStartedAt: number;
34
+ baseDir?: string;
35
+ now?: number;
36
+ }
37
+ export interface SessionOrigin {
38
+ machineHostname?: string | null;
39
+ machineRef?: string | null;
40
+ }
41
+ export declare function isSameMachineSession(origin: SessionOrigin, local: {
42
+ hostname: string;
43
+ machineRef?: string;
44
+ }): boolean;
45
+ export declare function createPortableSessionHandoff(input: CreateSessionHandoffInput): CreatedSessionHandoff;
46
+ export declare function consumeSessionHandoffBinding(input: ConsumeSessionHandoffInput): SessionHandoffBinding | undefined;
47
+ //# sourceMappingURL=sessionHandoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionHandoff.d.ts","sourceRoot":"","sources":["../../src/lib/sessionHandoff.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErF,eAAO,MAAM,8BAA8B,EAAG,2BAAoC,CAAC;AACnF,eAAO,MAAM,gCAAgC,EAAG,oCAA6C,CAAC;AAO9F,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAkBD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,yBAAyB,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,OAAO,8BAA8B,CAAC;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,KAAK,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAuLD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,OAAO,CAGT;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,yBAAyB,GAC/B,qBAAqB,CA6DvB;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,0BAA0B,GAChC,qBAAqB,GAAG,SAAS,CAuCnC"}
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SESSION_HANDOFF_REGISTRY_VERSION = exports.SESSION_HANDOFF_SCHEMA_VERSION = void 0;
37
+ exports.isSameMachineSession = isSameMachineSession;
38
+ exports.createPortableSessionHandoff = createPortableSessionHandoff;
39
+ exports.consumeSessionHandoffBinding = consumeSessionHandoffBinding;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const node_crypto_1 = require("node:crypto");
43
+ const node_child_process_1 = require("node:child_process");
44
+ const config_1 = require("./config");
45
+ const redact_1 = require("./redact");
46
+ exports.SESSION_HANDOFF_SCHEMA_VERSION = "you-md/session-handoff/v1";
47
+ exports.SESSION_HANDOFF_REGISTRY_VERSION = "you-md/session-handoff-registry/v1";
48
+ const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
49
+ const START_TIME_SLOP_MS = 2000;
50
+ const MAX_TEXT = 500;
51
+ const MAX_ITEMS = 8;
52
+ function sha256(value) {
53
+ return (0, node_crypto_1.createHash)("sha256").update(value, "utf8").digest("hex");
54
+ }
55
+ function handoffDir(baseDir) {
56
+ return baseDir ?? path.join((0, config_1.getWritableHomeBundleDir)(), "session-handoffs");
57
+ }
58
+ function registryPath(baseDir) {
59
+ return path.join(handoffDir(baseDir), "registry.json");
60
+ }
61
+ function ensurePrivateDir(dir) {
62
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
63
+ fs.chmodSync(dir, 0o700);
64
+ }
65
+ function writePrivateJson(filePath, value) {
66
+ ensurePrivateDir(path.dirname(filePath));
67
+ const tempPath = `${filePath}.${process.pid}.tmp`;
68
+ fs.writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
69
+ fs.chmodSync(tempPath, 0o600);
70
+ fs.renameSync(tempPath, filePath);
71
+ fs.chmodSync(filePath, 0o600);
72
+ }
73
+ function readRegistry(baseDir, now) {
74
+ try {
75
+ const parsed = JSON.parse(fs.readFileSync(registryPath(baseDir), "utf8"));
76
+ if (parsed.schemaVersion !== exports.SESSION_HANDOFF_REGISTRY_VERSION || !Array.isArray(parsed.entries)) {
77
+ return { schemaVersion: exports.SESSION_HANDOFF_REGISTRY_VERSION, entries: [] };
78
+ }
79
+ return {
80
+ schemaVersion: exports.SESSION_HANDOFF_REGISTRY_VERSION,
81
+ entries: parsed.entries.filter((entry) => entry
82
+ && typeof entry === "object"
83
+ && typeof entry.checkpointRef === "string"
84
+ && typeof entry.sessionRef === "string"
85
+ && typeof entry.previousCheckpointRef === "string"
86
+ && (entry.runtime === "codex" || entry.runtime === "claude-code")
87
+ && typeof entry.projectDirDigest === "string"
88
+ && typeof entry.createdAt === "number"
89
+ && typeof entry.expiresAt === "number"
90
+ && entry.expiresAt > now),
91
+ };
92
+ }
93
+ catch {
94
+ return { schemaVersion: exports.SESSION_HANDOFF_REGISTRY_VERSION, entries: [] };
95
+ }
96
+ }
97
+ function runtimeForCheckpoint(runtime) {
98
+ if (runtime === "codex")
99
+ return "codex";
100
+ if (runtime === "claude-code")
101
+ return "claude-code";
102
+ throw new Error(`unsupported handoff runtime: ${runtime}`);
103
+ }
104
+ function requirePortableCheckpoint(checkpoint) {
105
+ if (!checkpoint
106
+ || checkpoint.schemaVersion !== "you-md/session-checkpoint/v1"
107
+ || checkpoint.secretValuesExposed !== false
108
+ || !/^checkpoint:[a-f0-9]{64}$/.test(checkpoint.checkpointRef)
109
+ || !/^session:[a-f0-9]{64}$/.test(checkpoint.sessionRef)
110
+ || typeof checkpoint.machineRef !== "string"
111
+ || typeof checkpoint.sourceRevision !== "string"
112
+ || typeof checkpoint.now !== "string"
113
+ || !Array.isArray(checkpoint.recent)
114
+ || !Array.isArray(checkpoint.next)
115
+ || !Array.isArray(checkpoint.blockers)
116
+ || !Array.isArray(checkpoint.decisions)
117
+ || !Array.isArray(checkpoint.artifactRefs)
118
+ || !Number.isFinite(checkpoint.eventAt)) {
119
+ throw new Error("portable checkpoint is missing or malformed");
120
+ }
121
+ }
122
+ function safeText(value, forbiddenValues = []) {
123
+ if (typeof value !== "string")
124
+ return "";
125
+ const normalized = value.replace(/\s+/g, " ").trim().slice(0, MAX_TEXT);
126
+ if (!normalized)
127
+ return "";
128
+ let safe = (0, redact_1.redactText)(normalized).text;
129
+ for (const forbidden of forbiddenValues.filter(Boolean)) {
130
+ safe = safe.split(forbidden).join("[local-session]");
131
+ }
132
+ return safe
133
+ .replace(/(?:^|\s)(?:\/Users\/|\/home\/|\/var\/|\/tmp\/|~\/|[A-Za-z]:\\)\S*/g, " [local-path]")
134
+ .replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi, "[opaque-ref]")
135
+ .replace(/\b(?:origin|local|native|vendor)(?:[-_](?:private|opaque))?[-_](?:id|session)(?:[-_][A-Za-z0-9]+)*\b/gi, "[native-session-ref]")
136
+ .trim();
137
+ }
138
+ function safeList(value, forbiddenValues = []) {
139
+ if (!Array.isArray(value))
140
+ return [];
141
+ return value
142
+ .slice(0, MAX_ITEMS)
143
+ .map((item) => safeText(item, forbiddenValues))
144
+ .filter(Boolean);
145
+ }
146
+ function canonicalRepoRef(remote) {
147
+ const normalized = remote
148
+ .replace(/^(https?:\/\/)[^/@]+@/i, "$1")
149
+ .replace(/^git@([^:]+):/i, "$1/")
150
+ .replace(/^ssh:\/\/git@/i, "")
151
+ .replace(/^https?:\/\//i, "")
152
+ .replace(/\.git$/i, "")
153
+ .replace(/\/+$/, "");
154
+ return normalized && !normalized.startsWith("/")
155
+ ? `repo:${normalized.toLowerCase()}`
156
+ : undefined;
157
+ }
158
+ function localRepoRef(projectDir) {
159
+ try {
160
+ return canonicalRepoRef((0, node_child_process_1.execFileSync)("git", ["remote", "get-url", "origin"], {
161
+ cwd: projectDir,
162
+ stdio: ["ignore", "pipe", "ignore"],
163
+ timeout: 3000,
164
+ encoding: "utf8",
165
+ }).trim());
166
+ }
167
+ catch {
168
+ return undefined;
169
+ }
170
+ }
171
+ function projectDirDigest(projectDir) {
172
+ const real = fs.realpathSync(projectDir);
173
+ return `sha256:${sha256(real)}`;
174
+ }
175
+ function shellQuote(value) {
176
+ return `'${value.replace(/'/g, `'\\''`)}'`;
177
+ }
178
+ function renderBrief(checkpoint, forbiddenValues) {
179
+ return {
180
+ schemaVersion: exports.SESSION_HANDOFF_SCHEMA_VERSION,
181
+ checkpointRef: checkpoint.checkpointRef,
182
+ sessionRef: checkpoint.sessionRef,
183
+ runtime: checkpoint.runtime,
184
+ projectRef: safeText(checkpoint.projectRef, forbiddenValues),
185
+ projectSlug: safeText(checkpoint.projectSlug, forbiddenValues),
186
+ businessRef: safeText(checkpoint.businessRef, forbiddenValues),
187
+ goalRefs: safeList(checkpoint.goalRefs, forbiddenValues),
188
+ taskRefs: safeList(checkpoint.taskRefs, forbiddenValues),
189
+ runRef: safeText(checkpoint.runRef, forbiddenValues),
190
+ sourceRevision: safeText(checkpoint.sourceRevision, forbiddenValues),
191
+ branch: safeText(checkpoint.branch, forbiddenValues),
192
+ repoRef: safeText(checkpoint.repoRef, forbiddenValues),
193
+ now: safeText(checkpoint.now, forbiddenValues),
194
+ recent: safeList(checkpoint.recent, forbiddenValues),
195
+ next: safeList(checkpoint.next, forbiddenValues),
196
+ blockers: safeList(checkpoint.blockers, forbiddenValues),
197
+ decisions: safeList(checkpoint.decisions, forbiddenValues),
198
+ artifactRefs: checkpoint.artifactRefs.slice(0, 12).map((artifact) => ({
199
+ artifactRef: safeText(artifact.artifactRef, forbiddenValues),
200
+ mimeType: safeText(artifact.mimeType, forbiddenValues),
201
+ title: safeText(artifact.title, forbiddenValues),
202
+ availability: artifact.availability,
203
+ permission: artifact.permission,
204
+ })),
205
+ eventAt: checkpoint.eventAt,
206
+ secretValuesExposed: false,
207
+ };
208
+ }
209
+ function isSameMachineSession(origin, local) {
210
+ if (origin.machineRef && local.machineRef)
211
+ return origin.machineRef === local.machineRef;
212
+ return Boolean(origin.machineHostname && origin.machineHostname === local.hostname);
213
+ }
214
+ function createPortableSessionHandoff(input) {
215
+ requirePortableCheckpoint(input.checkpoint);
216
+ const runtime = runtimeForCheckpoint(input.checkpoint.runtime);
217
+ const projectDir = fs.realpathSync(input.projectDir);
218
+ const slug = path.basename(projectDir);
219
+ const repoRef = localRepoRef(projectDir);
220
+ const checkpointSlug = safeText(input.checkpoint.projectSlug);
221
+ const checkpointRepoRef = safeText(input.checkpoint.repoRef);
222
+ if (checkpointRepoRef
223
+ ? !repoRef || repoRef !== checkpointRepoRef
224
+ : checkpointSlug && checkpointSlug !== slug) {
225
+ throw new Error("current project does not match the portable checkpoint");
226
+ }
227
+ const now = input.now ?? Date.now();
228
+ const ttlMs = Math.max(60000, Math.min(input.ttlMs ?? DEFAULT_TTL_MS, 7 * 24 * 60 * 60 * 1000));
229
+ const expiresAt = now + ttlMs;
230
+ const dir = handoffDir(input.baseDir);
231
+ ensurePrivateDir(dir);
232
+ const digest = input.checkpoint.checkpointRef.slice("checkpoint:".length);
233
+ const briefPath = path.join(dir, `${digest}.json`);
234
+ writePrivateJson(briefPath, renderBrief(input.checkpoint, input.originNativeSessionId ? [input.originNativeSessionId] : []));
235
+ const registry = readRegistry(input.baseDir, now);
236
+ const entry = {
237
+ checkpointRef: input.checkpoint.checkpointRef,
238
+ sessionRef: input.checkpoint.sessionRef,
239
+ previousCheckpointRef: input.checkpoint.checkpointRef,
240
+ runtime,
241
+ ...(checkpointSlug ? { projectSlug: checkpointSlug } : {}),
242
+ ...(repoRef ? { repoRef } : {}),
243
+ projectDirDigest: projectDirDigest(projectDir),
244
+ createdAt: now,
245
+ expiresAt,
246
+ };
247
+ registry.entries = [
248
+ ...registry.entries.filter((candidate) => candidate.checkpointRef !== entry.checkpointRef),
249
+ entry,
250
+ ].slice(-24);
251
+ writePrivateJson(registryPath(input.baseDir), registry);
252
+ const binary = runtime === "codex" ? "codex" : "claude";
253
+ const prompt = `Continue this You.md session from the portable handoff at ${briefPath}. `
254
+ + "Treat it as context, inspect the current repository state, and verify before changing anything.";
255
+ const command = `cd ${shellQuote(projectDir)} && ${binary} ${shellQuote(prompt)}`;
256
+ return {
257
+ schemaVersion: exports.SESSION_HANDOFF_SCHEMA_VERSION,
258
+ checkpointRef: input.checkpoint.checkpointRef,
259
+ sessionRef: input.checkpoint.sessionRef,
260
+ briefPath,
261
+ runtime,
262
+ command,
263
+ expiresAt,
264
+ secretValuesExposed: false,
265
+ };
266
+ }
267
+ function consumeSessionHandoffBinding(input) {
268
+ if (!input.workspacePath
269
+ || !input.localSessionAnchor
270
+ || !Number.isFinite(input.sessionStartedAt))
271
+ return undefined;
272
+ const now = input.now ?? Date.now();
273
+ const registry = readRegistry(input.baseDir, now);
274
+ let digest;
275
+ try {
276
+ digest = projectDirDigest(input.workspacePath);
277
+ }
278
+ catch {
279
+ return undefined;
280
+ }
281
+ const localSessionDigest = `sha256:${sha256(input.localSessionAnchor)}`;
282
+ let index = registry.entries.findIndex((entry) => entry.runtime === input.runtime
283
+ && entry.projectDirDigest === digest
284
+ && (!entry.projectSlug || entry.projectSlug === input.projectSlug)
285
+ && (!entry.repoRef || entry.repoRef === input.repoRef)
286
+ && entry.boundLocalSessionDigest === localSessionDigest);
287
+ if (index < 0)
288
+ index = registry.entries.findIndex((entry) => entry.runtime === input.runtime
289
+ && entry.projectDirDigest === digest
290
+ && (!entry.projectSlug || entry.projectSlug === input.projectSlug)
291
+ && (!entry.repoRef || entry.repoRef === input.repoRef)
292
+ && !entry.boundLocalSessionDigest
293
+ && input.sessionStartedAt >= entry.createdAt - START_TIME_SLOP_MS
294
+ && input.sessionStartedAt <= entry.expiresAt);
295
+ if (index < 0)
296
+ return undefined;
297
+ const entry = registry.entries[index];
298
+ entry.boundLocalSessionDigest = localSessionDigest;
299
+ writePrivateJson(registryPath(input.baseDir), registry);
300
+ return {
301
+ sessionRef: entry.sessionRef,
302
+ previousCheckpointRef: entry.previousCheckpointRef,
303
+ };
304
+ }
305
+ //# sourceMappingURL=sessionHandoff.js.map