@tickernelz/paperclip-pro-adapter-utils 2026.1006.0 → 2026.1006.2

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 (181) hide show
  1. package/README.md +13 -0
  2. package/dist/acpx-engine/ephemeral-session-environment.d.ts +4 -0
  3. package/dist/acpx-engine/ephemeral-session-environment.d.ts.map +1 -0
  4. package/dist/acpx-engine/ephemeral-session-environment.js +29 -0
  5. package/dist/acpx-engine/ephemeral-session-environment.js.map +1 -0
  6. package/dist/acpx-engine/ephemeral-session-environment.test.d.ts +2 -0
  7. package/dist/acpx-engine/ephemeral-session-environment.test.d.ts.map +1 -0
  8. package/dist/acpx-engine/ephemeral-session-environment.test.js +177 -0
  9. package/dist/acpx-engine/ephemeral-session-environment.test.js.map +1 -0
  10. package/dist/acpx-engine/execute.d.ts +2 -6
  11. package/dist/acpx-engine/execute.d.ts.map +1 -1
  12. package/dist/acpx-engine/execute.js +125 -62
  13. package/dist/acpx-engine/execute.js.map +1 -1
  14. package/dist/acpx-engine/execute.test.js +299 -3
  15. package/dist/acpx-engine/execute.test.js.map +1 -1
  16. package/dist/acpx-engine/session-codec.d.ts.map +1 -1
  17. package/dist/acpx-engine/session-codec.js +1 -0
  18. package/dist/acpx-engine/session-codec.js.map +1 -1
  19. package/dist/acpx-engine/settlement-characterization.test.js +105 -0
  20. package/dist/acpx-engine/settlement-characterization.test.js.map +1 -1
  21. package/dist/acpx-engine/spawn-smoke.test.js +16 -7
  22. package/dist/acpx-engine/spawn-smoke.test.js.map +1 -1
  23. package/dist/acpx-engine/startup-cancellation.d.ts +1 -0
  24. package/dist/acpx-engine/startup-cancellation.d.ts.map +1 -1
  25. package/dist/acpx-engine/startup-cancellation.js +7 -2
  26. package/dist/acpx-engine/startup-cancellation.js.map +1 -1
  27. package/dist/acpx-engine/terminal-session-failure.d.ts +18 -0
  28. package/dist/acpx-engine/terminal-session-failure.d.ts.map +1 -0
  29. package/dist/acpx-engine/terminal-session-failure.js +106 -0
  30. package/dist/acpx-engine/terminal-session-failure.js.map +1 -0
  31. package/dist/acpx-engine/terminal-session-failure.test.d.ts +2 -0
  32. package/dist/acpx-engine/terminal-session-failure.test.d.ts.map +1 -0
  33. package/dist/acpx-engine/terminal-session-failure.test.js +139 -0
  34. package/dist/acpx-engine/terminal-session-failure.test.js.map +1 -0
  35. package/dist/acpx-engine/turn-characterization.test.js +4 -3
  36. package/dist/acpx-engine/turn-characterization.test.js.map +1 -1
  37. package/dist/command-managed-runtime.d.ts +2 -0
  38. package/dist/command-managed-runtime.d.ts.map +1 -1
  39. package/dist/command-managed-runtime.js +2 -0
  40. package/dist/command-managed-runtime.js.map +1 -1
  41. package/dist/command-redaction.d.ts +2 -0
  42. package/dist/command-redaction.d.ts.map +1 -1
  43. package/dist/command-redaction.js +20 -10
  44. package/dist/command-redaction.js.map +1 -1
  45. package/dist/command-redaction.test.js +20 -1
  46. package/dist/command-redaction.test.js.map +1 -1
  47. package/dist/directory-merge-lock.test.d.ts +2 -0
  48. package/dist/directory-merge-lock.test.d.ts.map +1 -0
  49. package/dist/directory-merge-lock.test.js +166 -0
  50. package/dist/directory-merge-lock.test.js.map +1 -0
  51. package/dist/execution-phase.d.ts +10 -0
  52. package/dist/execution-phase.d.ts.map +1 -0
  53. package/dist/execution-phase.js +27 -0
  54. package/dist/execution-phase.js.map +1 -0
  55. package/dist/execution-phase.test.d.ts +2 -0
  56. package/dist/execution-phase.test.d.ts.map +1 -0
  57. package/dist/execution-phase.test.js +26 -0
  58. package/dist/execution-phase.test.js.map +1 -0
  59. package/dist/execution-target-sandbox.test.js +49 -7
  60. package/dist/execution-target-sandbox.test.js.map +1 -1
  61. package/dist/execution-target-stdin-race.test.js +245 -2
  62. package/dist/execution-target-stdin-race.test.js.map +1 -1
  63. package/dist/execution-target.d.ts +6 -0
  64. package/dist/execution-target.d.ts.map +1 -1
  65. package/dist/execution-target.js +74 -22
  66. package/dist/execution-target.js.map +1 -1
  67. package/dist/git-workspace-sync.d.ts +15 -5
  68. package/dist/git-workspace-sync.d.ts.map +1 -1
  69. package/dist/git-workspace-sync.js +267 -124
  70. package/dist/git-workspace-sync.js.map +1 -1
  71. package/dist/git-workspace-sync.test.js +296 -20
  72. package/dist/git-workspace-sync.test.js.map +1 -1
  73. package/dist/github-launcher.d.ts.map +1 -1
  74. package/dist/github-launcher.js +26 -11
  75. package/dist/github-launcher.js.map +1 -1
  76. package/dist/github-launcher.test.js +34 -1
  77. package/dist/github-launcher.test.js.map +1 -1
  78. package/dist/index.d.ts +1 -1
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/paperclip-runner-permissions.d.ts +28 -1
  83. package/dist/paperclip-runner-permissions.d.ts.map +1 -1
  84. package/dist/paperclip-runner-permissions.js +9 -1
  85. package/dist/paperclip-runner-permissions.js.map +1 -1
  86. package/dist/prompt-sections.test.d.ts +2 -0
  87. package/dist/prompt-sections.test.d.ts.map +1 -0
  88. package/dist/prompt-sections.test.js +53 -0
  89. package/dist/prompt-sections.test.js.map +1 -0
  90. package/dist/provider-stopped-boundary.d.ts +7 -0
  91. package/dist/provider-stopped-boundary.d.ts.map +1 -0
  92. package/dist/provider-stopped-boundary.js +22 -0
  93. package/dist/provider-stopped-boundary.js.map +1 -0
  94. package/dist/provider-stopped-boundary.test.d.ts +2 -0
  95. package/dist/provider-stopped-boundary.test.d.ts.map +1 -0
  96. package/dist/provider-stopped-boundary.test.js +76 -0
  97. package/dist/provider-stopped-boundary.test.js.map +1 -0
  98. package/dist/remote-managed-runtime.d.ts +2 -0
  99. package/dist/remote-managed-runtime.d.ts.map +1 -1
  100. package/dist/remote-managed-runtime.js +3 -1
  101. package/dist/remote-managed-runtime.js.map +1 -1
  102. package/dist/remote-managed-runtime.test.js +25 -0
  103. package/dist/remote-managed-runtime.test.js.map +1 -1
  104. package/dist/sandbox-callback-bridge.d.ts +2 -0
  105. package/dist/sandbox-callback-bridge.d.ts.map +1 -1
  106. package/dist/sandbox-callback-bridge.js +34 -10
  107. package/dist/sandbox-callback-bridge.js.map +1 -1
  108. package/dist/sandbox-callback-bridge.test.js +106 -3
  109. package/dist/sandbox-callback-bridge.test.js.map +1 -1
  110. package/dist/sandbox-managed-runtime.d.ts +3 -0
  111. package/dist/sandbox-managed-runtime.d.ts.map +1 -1
  112. package/dist/sandbox-managed-runtime.js +749 -718
  113. package/dist/sandbox-managed-runtime.js.map +1 -1
  114. package/dist/sandbox-managed-runtime.test.js +171 -2
  115. package/dist/sandbox-managed-runtime.test.js.map +1 -1
  116. package/dist/server-utils.d.ts +43 -1
  117. package/dist/server-utils.d.ts.map +1 -1
  118. package/dist/server-utils.js +103 -31
  119. package/dist/server-utils.js.map +1 -1
  120. package/dist/server-utils.test.js +235 -45
  121. package/dist/server-utils.test.js.map +1 -1
  122. package/dist/session-compaction.d.ts.map +1 -1
  123. package/dist/session-compaction.js +6 -0
  124. package/dist/session-compaction.js.map +1 -1
  125. package/dist/ssh-fixture.test.js +22 -0
  126. package/dist/ssh-fixture.test.js.map +1 -1
  127. package/dist/ssh.d.ts +2 -0
  128. package/dist/ssh.d.ts.map +1 -1
  129. package/dist/ssh.js +2 -2
  130. package/dist/ssh.js.map +1 -1
  131. package/dist/test-fixtures/prompt-context.d.ts +54 -0
  132. package/dist/test-fixtures/prompt-context.d.ts.map +1 -0
  133. package/dist/test-fixtures/prompt-context.js +55 -0
  134. package/dist/test-fixtures/prompt-context.js.map +1 -0
  135. package/dist/types.d.ts +12 -2
  136. package/dist/types.d.ts.map +1 -1
  137. package/dist/workspace-git-stream.d.ts +19 -0
  138. package/dist/workspace-git-stream.d.ts.map +1 -0
  139. package/dist/workspace-git-stream.js +99 -0
  140. package/dist/workspace-git-stream.js.map +1 -0
  141. package/dist/workspace-git-stream.test.d.ts +2 -0
  142. package/dist/workspace-git-stream.test.d.ts.map +1 -0
  143. package/dist/workspace-git-stream.test.js +71 -0
  144. package/dist/workspace-git-stream.test.js.map +1 -0
  145. package/dist/workspace-manifest.d.ts +61 -0
  146. package/dist/workspace-manifest.d.ts.map +1 -0
  147. package/dist/workspace-manifest.js +257 -0
  148. package/dist/workspace-manifest.js.map +1 -0
  149. package/dist/workspace-manifest.test.d.ts +2 -0
  150. package/dist/workspace-manifest.test.d.ts.map +1 -0
  151. package/dist/workspace-manifest.test.js +160 -0
  152. package/dist/workspace-manifest.test.js.map +1 -0
  153. package/dist/workspace-restore-diagnostics.d.ts +34 -0
  154. package/dist/workspace-restore-diagnostics.d.ts.map +1 -0
  155. package/dist/workspace-restore-diagnostics.js +238 -0
  156. package/dist/workspace-restore-diagnostics.js.map +1 -0
  157. package/dist/workspace-restore-diagnostics.test.d.ts +2 -0
  158. package/dist/workspace-restore-diagnostics.test.d.ts.map +1 -0
  159. package/dist/workspace-restore-diagnostics.test.js +258 -0
  160. package/dist/workspace-restore-diagnostics.test.js.map +1 -0
  161. package/dist/workspace-restore-merge.d.ts +47 -6
  162. package/dist/workspace-restore-merge.d.ts.map +1 -1
  163. package/dist/workspace-restore-merge.js +382 -114
  164. package/dist/workspace-restore-merge.js.map +1 -1
  165. package/dist/workspace-restore-merge.test.js +253 -4
  166. package/dist/workspace-restore-merge.test.js.map +1 -1
  167. package/dist/workspace-restore-result.d.ts +6 -0
  168. package/dist/workspace-restore-result.d.ts.map +1 -0
  169. package/dist/workspace-restore-result.js +72 -0
  170. package/dist/workspace-restore-result.js.map +1 -0
  171. package/dist/workspace-restore-result.test.d.ts +2 -0
  172. package/dist/workspace-restore-result.test.d.ts.map +1 -0
  173. package/dist/workspace-restore-result.test.js +74 -0
  174. package/dist/workspace-restore-result.test.js.map +1 -0
  175. package/dist/workspace-restore-teardown.d.ts.map +1 -1
  176. package/dist/workspace-restore-teardown.js +5 -3
  177. package/dist/workspace-restore-teardown.js.map +1 -1
  178. package/dist/workspace-restore-teardown.test.js +24 -0
  179. package/dist/workspace-restore-teardown.test.js.map +1 -1
  180. package/node_modules/acpx/dist/live-checkpoint-ClPCSdrW.js +4 -3
  181. package/package.json +2 -2
@@ -0,0 +1,257 @@
1
+ import { createHash } from "node:crypto";
2
+ import { constants, promises as fs } from "node:fs";
3
+ import nodeFs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { DatabaseSync } from "node:sqlite";
7
+ // Limits apply to one record and to SQLite's page cache, never to the list.
8
+ export const WORKSPACE_PATH_MAX_BYTES = 64 * 1024;
9
+ export const WORKSPACE_STREAM_CHUNK_BYTES = 64 * 1024;
10
+ const DISK_CHECK_INTERVAL_BYTES = 1024 * 1024;
11
+ /** A capacity floor, not a total filename budget. Leave room for the host. */
12
+ export function assertWorkspaceManifestDiskSpace(directory, requiredBytes = 0) {
13
+ const configured = Number(process.env.PAPERCLIP_WORKSPACE_MANIFEST_MIN_FREE_BYTES);
14
+ const minimum = Number.isSafeInteger(configured) && configured >= 64 * 1024 * 1024
15
+ ? configured : 256 * 1024 * 1024;
16
+ const stat = nodeFs.statfsSync(directory, { bigint: true });
17
+ if (stat.bavail * stat.bsize < BigInt(minimum) + BigInt(requiredBytes)) {
18
+ throw Object.assign(new Error("Workspace manifest storage is below its free-space reserve"), {
19
+ code: "workspace_git_scan_failed",
20
+ });
21
+ }
22
+ return Number(stat.bavail * stat.bsize - BigInt(minimum));
23
+ }
24
+ export function assertWorkspaceRelativePath(value) {
25
+ if (!value || value.includes("\0") || path.posix.isAbsolute(value) || path.win32.isAbsolute(value)
26
+ || value.split(/[\\/]/).some((part) => part === ".." || part === ".")
27
+ || Buffer.byteLength(value) > WORKSPACE_PATH_MAX_BYTES) {
28
+ throw new Error("Invalid workspace manifest path");
29
+ }
30
+ }
31
+ export function isPathManifest(value) {
32
+ return !Array.isArray(value);
33
+ }
34
+ function openDatabase(filePath, readOnly = true) {
35
+ const db = new DatabaseSync(filePath, { readOnly, allowExtension: false });
36
+ try {
37
+ db.exec("PRAGMA trusted_schema=OFF; PRAGMA cache_size=-1024; PRAGMA temp_store=FILE; PRAGMA mmap_size=0;");
38
+ return db;
39
+ }
40
+ catch (error) {
41
+ db.close();
42
+ throw error;
43
+ }
44
+ }
45
+ /** One private database, sealed before it is published. Consumers open read-only. */
46
+ export class WorkspaceManifestWriter {
47
+ filePath;
48
+ db;
49
+ insert;
50
+ closed = false;
51
+ bytesSinceDiskCheck = 0;
52
+ constructor(filePath) {
53
+ this.filePath = filePath;
54
+ const availableBytes = assertWorkspaceManifestDiskSpace(path.dirname(filePath));
55
+ this.db = openDatabase(filePath, false);
56
+ try {
57
+ // Admission follows current storage capacity, not filename-list length.
58
+ // SQLite enforces this before allocating pages, including within a chunk.
59
+ const pageSize = Number(this.db.prepare("PRAGMA page_size").get().page_size);
60
+ const pageAllowance = Math.floor(availableBytes / 4 / pageSize);
61
+ if (pageAllowance < 2)
62
+ throw new Error("Insufficient workspace manifest disk allowance");
63
+ this.db.exec(`PRAGMA max_page_count=${Math.min(pageAllowance, 4_294_967_294)}`);
64
+ this.db.exec("PRAGMA journal_mode=DELETE; CREATE TABLE records(category TEXT, path TEXT, value TEXT NOT NULL, PRIMARY KEY(category,path)) WITHOUT ROWID;");
65
+ this.insert = this.db.prepare("INSERT OR REPLACE INTO records VALUES(?,?,?)");
66
+ this.db.exec("BEGIN");
67
+ }
68
+ catch (error) {
69
+ this.db.close();
70
+ throw error;
71
+ }
72
+ }
73
+ add(category, relative, value = "") {
74
+ assertWorkspaceRelativePath(relative);
75
+ if (Buffer.byteLength(value) > WORKSPACE_PATH_MAX_BYTES)
76
+ throw new Error("Workspace manifest value exceeds record limit");
77
+ this.bytesSinceDiskCheck += Buffer.byteLength(relative) + Buffer.byteLength(value);
78
+ if (this.bytesSinceDiskCheck >= DISK_CHECK_INTERVAL_BYTES) {
79
+ assertWorkspaceManifestDiskSpace(path.dirname(this.filePath));
80
+ this.bytesSinceDiskCheck = 0;
81
+ }
82
+ this.insert.run(category, relative, value);
83
+ }
84
+ batch(work) {
85
+ this.db.exec("SAVEPOINT chunk");
86
+ try {
87
+ work();
88
+ this.db.exec("RELEASE chunk");
89
+ }
90
+ catch (error) {
91
+ // SQLITE_FULL can roll back the transaction itself.
92
+ if (this.db.isTransaction)
93
+ this.db.exec("ROLLBACK TO chunk; RELEASE chunk");
94
+ throw error;
95
+ }
96
+ }
97
+ paths(category) {
98
+ const row = this.db.prepare("SELECT count(*) AS count FROM records WHERE category=?").get(category);
99
+ return { kind: "path_manifest", version: 1, filePath: this.filePath, category, count: Number(row.count) };
100
+ }
101
+ close(commit = true) {
102
+ if (this.closed)
103
+ return;
104
+ this.closed = true;
105
+ try {
106
+ if (this.db.isTransaction)
107
+ this.db.exec(commit ? "COMMIT" : "ROLLBACK");
108
+ }
109
+ finally {
110
+ this.db.close();
111
+ }
112
+ }
113
+ }
114
+ export class WorkspaceManifestMap {
115
+ manifest;
116
+ parse;
117
+ db = null;
118
+ lookup = null;
119
+ constructor(manifest, parse) {
120
+ this.manifest = manifest;
121
+ this.parse = parse;
122
+ }
123
+ get size() { return this.manifest.count; }
124
+ get(relative) {
125
+ this.db ??= openDatabase(this.manifest.filePath);
126
+ this.lookup ??= this.db.prepare("SELECT value FROM records WHERE category=? AND path=?");
127
+ const row = this.lookup.get(this.manifest.category, relative);
128
+ return row ? this.parse(String(row.value)) : undefined;
129
+ }
130
+ has(relative) { return this.get(relative) !== undefined; }
131
+ *entries(reverse = false) {
132
+ for (const [relative, value] of readManifestRecords(this.manifest, reverse))
133
+ yield [relative, this.parse(value)];
134
+ }
135
+ [Symbol.iterator]() { return this.entries(); }
136
+ close() { this.db?.close(); this.db = null; this.lookup = null; }
137
+ }
138
+ export async function createWorkspaceManifest(prefix = "paperclip-workspace-manifest-") {
139
+ const directory = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
140
+ try {
141
+ return new WorkspaceManifestWriter(path.join(directory, "paths.sqlite"));
142
+ }
143
+ catch (error) {
144
+ await fs.rm(directory, { recursive: true, force: true });
145
+ throw error;
146
+ }
147
+ }
148
+ export function* readManifestRecords(manifest, reverse = false) {
149
+ const db = openDatabase(manifest.filePath);
150
+ let count = 0;
151
+ try {
152
+ for (const row of db.prepare(`SELECT path,value FROM records WHERE category=? ORDER BY path ${reverse ? "DESC" : "ASC"}`).iterate(manifest.category)) {
153
+ const relative = String(row.path);
154
+ const value = String(row.value);
155
+ assertWorkspaceRelativePath(relative);
156
+ if (Buffer.byteLength(value) > WORKSPACE_PATH_MAX_BYTES)
157
+ throw new Error("Invalid workspace manifest record");
158
+ count++;
159
+ yield [relative, value];
160
+ }
161
+ if (count !== manifest.count)
162
+ throw new Error("Incomplete workspace manifest");
163
+ }
164
+ finally {
165
+ db.close();
166
+ }
167
+ }
168
+ export function* workspacePaths(paths) {
169
+ if (isPathManifest(paths)) {
170
+ for (const [relative] of readManifestRecords(paths))
171
+ yield relative;
172
+ }
173
+ else {
174
+ for (const relative of paths) {
175
+ assertWorkspaceRelativePath(relative);
176
+ yield relative;
177
+ }
178
+ }
179
+ }
180
+ /** Exact paths and their descendants; Git ignore output is literal, not a glob. */
181
+ export function workspacePathMatcher(paths) {
182
+ const db = paths && isPathManifest(paths) ? openDatabase(paths.filePath) : null;
183
+ const lookup = db?.prepare("SELECT 1 FROM records WHERE category=? AND path=?");
184
+ return {
185
+ matches(relative) {
186
+ let current = relative;
187
+ while (current) {
188
+ if (lookup && paths && isPathManifest(paths)
189
+ ? Boolean(lookup.get(paths.category, current))
190
+ : paths?.includes(current))
191
+ return true;
192
+ const slash = current.lastIndexOf("/");
193
+ if (slash < 0)
194
+ break;
195
+ current = current.slice(0, slash);
196
+ }
197
+ return false;
198
+ },
199
+ close() { db?.close(); },
200
+ };
201
+ }
202
+ /** Incremental NUL parser: one bounded record, strict UTF-8, no partial success. */
203
+ export class WorkspaceNulParser {
204
+ record;
205
+ pending = Buffer.alloc(WORKSPACE_PATH_MAX_BYTES);
206
+ length = 0;
207
+ decoder = new TextDecoder("utf-8", { fatal: true });
208
+ constructor(record) {
209
+ this.record = record;
210
+ }
211
+ write(chunk) {
212
+ let start = 0;
213
+ while (start < chunk.length) {
214
+ const end = chunk.indexOf(0, start);
215
+ const stop = end < 0 ? chunk.length : end;
216
+ const size = stop - start;
217
+ if (this.length + size > this.pending.length)
218
+ throw new Error("Workspace filename exceeds per-record limit");
219
+ chunk.copy(this.pending, this.length, start, stop);
220
+ this.length += size;
221
+ if (end < 0)
222
+ return;
223
+ if (!this.length)
224
+ throw new Error("Empty workspace filename record");
225
+ this.record(this.decoder.decode(this.pending.subarray(0, this.length)));
226
+ this.length = 0;
227
+ start = end + 1;
228
+ }
229
+ }
230
+ finish() { if (this.length)
231
+ throw new Error("Incomplete NUL-delimited workspace scan"); }
232
+ }
233
+ export async function writeWorkspacePaths(paths, target) {
234
+ const file = await fs.open(target, "wx", 0o600);
235
+ try {
236
+ for (const relative of workspacePaths(paths))
237
+ await file.writeFile(`${relative}\0`);
238
+ }
239
+ finally {
240
+ await file.close();
241
+ }
242
+ }
243
+ export async function manifestFileSha256(filePath) {
244
+ const file = await fs.open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW);
245
+ try {
246
+ if (!(await file.stat()).isFile())
247
+ throw new Error("Invalid workspace manifest file");
248
+ const digest = createHash("sha256");
249
+ for await (const chunk of file.createReadStream({ autoClose: false }))
250
+ digest.update(chunk);
251
+ return digest.digest("hex");
252
+ }
253
+ finally {
254
+ await file.close();
255
+ }
256
+ }
257
+ //# sourceMappingURL=workspace-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-manifest.js","sourceRoot":"","sources":["../src/workspace-manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=workspace-manifest.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-manifest.test.d.ts","sourceRoot":"","sources":["../src/workspace-manifest.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,160 @@
1
+ import fs from "node:fs/promises";
2
+ import nodeFs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { afterEach, expect, it, vi } from "vitest";
6
+ import { createWorkspaceManifest, readManifestRecords, WorkspaceNulParser, WORKSPACE_PATH_MAX_BYTES, workspacePaths } from "./workspace-manifest.js";
7
+ import { readGitWorkspaceSnapshot, disposeGitWorkspaceSnapshot, runLocalGit, setExpensiveWorkspaceGitExecutor } from "./git-workspace-sync.js";
8
+ const cleanup = [];
9
+ afterEach(async () => {
10
+ setExpensiveWorkspaceGitExecutor(null);
11
+ vi.restoreAllMocks();
12
+ vi.unstubAllEnvs();
13
+ for (const dir of cleanup.splice(0))
14
+ await fs.rm(dir, { recursive: true, force: true });
15
+ });
16
+ it("parses split UTF-8 and NUL records while rejecting truncation and oversized records", () => {
17
+ const names = [];
18
+ const parser = new WorkspaceNulParser((value) => names.push(value));
19
+ const bytes = Buffer.from(" 雪\n\t \0-option\0");
20
+ for (const byte of bytes)
21
+ parser.write(Buffer.from([byte]));
22
+ parser.finish();
23
+ expect(names).toEqual([" 雪\n\t ", "-option"]);
24
+ parser.write(Buffer.from("unfinished"));
25
+ expect(() => parser.finish()).toThrow("Incomplete");
26
+ expect(() => parser.write(Buffer.alloc(WORKSPACE_PATH_MAX_BYTES, 97))).toThrow("per-record");
27
+ expect(() => new WorkspaceNulParser(() => { }).write(Buffer.from([255, 0]))).toThrow();
28
+ });
29
+ it("deduplicates paths on disk and rejects incomplete manifest metadata", async () => {
30
+ const writer = await createWorkspaceManifest();
31
+ cleanup.push(path.dirname(writer.filePath));
32
+ writer.batch(() => { writer.add("overlay", "b"); writer.add("overlay", "a"); writer.add("overlay", "b"); });
33
+ const manifest = writer.paths("overlay");
34
+ writer.close();
35
+ expect([...workspacePaths(manifest)]).toEqual(["a", "b"]);
36
+ expect(() => [...readManifestRecords({ ...manifest, count: 3 })]).toThrow("Incomplete");
37
+ expect(() => [...workspacePaths(["../escape"])]).toThrow("Invalid");
38
+ });
39
+ it("refuses new manifests and fails ongoing writes when the disk reserve is exhausted", async () => {
40
+ const writer = await createWorkspaceManifest();
41
+ cleanup.push(path.dirname(writer.filePath));
42
+ const available = nodeFs.statfsSync(os.tmpdir(), { bigint: true });
43
+ vi.spyOn(nodeFs, "statfsSync").mockReturnValue({ ...available, bavail: 0n });
44
+ try {
45
+ for (let attempt = 0; attempt < 4; attempt++) {
46
+ await expect(createWorkspaceManifest()).rejects.toMatchObject({ code: "workspace_git_scan_failed" });
47
+ }
48
+ expect(() => {
49
+ for (let index = 0; index < 1024; index++)
50
+ writer.add("overlay", `${index}-${"x".repeat(2048)}`);
51
+ }).toThrow("free-space reserve");
52
+ }
53
+ finally {
54
+ writer.close(false);
55
+ }
56
+ });
57
+ it("admits each snapshot against current disk capacity and rejects growth at its page allowance", async () => {
58
+ const available = nodeFs.statfsSync(os.tmpdir(), { bigint: true });
59
+ const reserve = 256 * 1024 * 1024;
60
+ vi.stubEnv("PAPERCLIP_WORKSPACE_MANIFEST_MIN_FREE_BYTES", String(reserve));
61
+ const capacity = reserve + 128 * 1024;
62
+ vi.spyOn(nodeFs, "statfsSync").mockReturnValue({ ...available, bsize: 1n, bavail: BigInt(capacity) });
63
+ for (let attempt = 0; attempt < 3; attempt++) {
64
+ const writer = await createWorkspaceManifest();
65
+ cleanup.push(path.dirname(writer.filePath));
66
+ try {
67
+ expect(() => writer.batch(() => {
68
+ for (let index = 0; index < 100; index++)
69
+ writer.add("overlay", `${index}-${"x".repeat(2048)}`);
70
+ })).toThrow(/full/i);
71
+ expect((await fs.stat(writer.filePath)).size).toBeLessThanOrEqual(32 * 1024);
72
+ }
73
+ finally {
74
+ writer.close(false);
75
+ }
76
+ }
77
+ });
78
+ it("fails a real Git scan at its disk allowance and removes the incomplete manifest", async () => {
79
+ const repo = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-scan-quota-"));
80
+ cleanup.push(repo);
81
+ await runLocalGit(repo, ["init"]);
82
+ await runLocalGit(repo, ["commit", "--allow-empty", "-qm", "fixture"], {
83
+ env: { ...process.env, GIT_AUTHOR_NAME: "Test", GIT_COMMITTER_NAME: "Test", GIT_AUTHOR_EMAIL: "test@example.test", GIT_COMMITTER_EMAIL: "test@example.test" },
84
+ });
85
+ for (let index = 0; index < 500; index++)
86
+ await fs.writeFile(path.join(repo, `${index}-${"x".repeat(200)}`), "");
87
+ const available = nodeFs.statfsSync(os.tmpdir(), { bigint: true });
88
+ const reserve = 256 * 1024 * 1024;
89
+ vi.stubEnv("PAPERCLIP_WORKSPACE_MANIFEST_MIN_FREE_BYTES", String(reserve));
90
+ vi.spyOn(nodeFs, "statfsSync").mockReturnValue({ ...available, bsize: 1n, bavail: BigInt(reserve + 128 * 1024) });
91
+ const temporary = [];
92
+ const mkdtemp = fs.mkdtemp.bind(fs);
93
+ vi.spyOn(fs, "mkdtemp").mockImplementation(async (prefix, options) => {
94
+ const directory = await mkdtemp(prefix, options);
95
+ temporary.push(String(directory));
96
+ return directory;
97
+ });
98
+ await expect(readGitWorkspaceSnapshot(repo)).rejects.toMatchObject({ code: "workspace_git_scan_failed" });
99
+ expect(temporary).toHaveLength(1);
100
+ await expect(fs.stat(temporary[0])).rejects.toMatchObject({ code: "ENOENT" });
101
+ });
102
+ it("settles a late producer before removing shared storage after another scan fails", async () => {
103
+ const repo = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-scan-barrier-"));
104
+ cleanup.push(repo);
105
+ await runLocalGit(repo, ["init"]);
106
+ await runLocalGit(repo, ["-c", "user.name=Test", "-c", "user.email=test@example.test", "commit", "--allow-empty", "-qm", "fixture"], {
107
+ env: { ...process.env, GIT_AUTHOR_NAME: "Test", GIT_COMMITTER_NAME: "Test", GIT_AUTHOR_EMAIL: "test@example.test", GIT_COMMITTER_EMAIL: "test@example.test" },
108
+ });
109
+ let release;
110
+ const gate = new Promise((resolve) => { release = resolve; });
111
+ let lateFinished = false;
112
+ let settled = false;
113
+ const removed = [];
114
+ const originalRm = fs.rm.bind(fs);
115
+ vi.spyOn(fs, "rm").mockImplementation(async (target, options) => {
116
+ if (String(target).includes("paperclip-workspace-manifest-")) {
117
+ expect(lateFinished).toBe(true);
118
+ removed.push(String(target));
119
+ }
120
+ return originalRm(target, options);
121
+ });
122
+ const failure = Object.assign(new Error("scan failed"), { code: "workspace_git_scan_failed" });
123
+ setExpensiveWorkspaceGitExecutor(async (input) => {
124
+ if (input.operation.endsWith("ignored_files"))
125
+ throw failure;
126
+ if (input.operation.endsWith("untracked_files")) {
127
+ await gate;
128
+ await input.onStdout(Buffer.from("late-producer\0"));
129
+ lateFinished = true;
130
+ }
131
+ return { stdout: "", stderr: "" };
132
+ });
133
+ const result = readGitWorkspaceSnapshot(repo).catch((error) => { settled = true; return error; });
134
+ await new Promise((resolve) => setTimeout(resolve, 30));
135
+ expect(settled).toBe(false);
136
+ expect(removed).toEqual([]);
137
+ release();
138
+ expect(await result).toBe(failure);
139
+ expect(removed).toHaveLength(1);
140
+ await expect(fs.stat(removed[0])).rejects.toMatchObject({ code: "ENOENT" });
141
+ });
142
+ it("fails a malformed completed scan instead of publishing a partial snapshot", async () => {
143
+ const repo = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-truncated-scan-"));
144
+ cleanup.push(repo);
145
+ await runLocalGit(repo, ["init"]);
146
+ await runLocalGit(repo, ["-c", "user.name=Test", "-c", "user.email=test@example.test", "commit", "--allow-empty", "-qm", "fixture"], {
147
+ env: { ...process.env, GIT_AUTHOR_NAME: "Test", GIT_COMMITTER_NAME: "Test", GIT_AUTHOR_EMAIL: "test@example.test", GIT_COMMITTER_EMAIL: "test@example.test" },
148
+ });
149
+ setExpensiveWorkspaceGitExecutor(async (input) => {
150
+ if (input.operation.endsWith("untracked_files"))
151
+ await input.onStdout(Buffer.from("complete\0partial"));
152
+ return { stdout: "", stderr: "" };
153
+ });
154
+ await expect(readGitWorkspaceSnapshot(repo)).rejects.toThrow("Incomplete NUL");
155
+ setExpensiveWorkspaceGitExecutor(null);
156
+ const recovered = await readGitWorkspaceSnapshot(repo);
157
+ expect(recovered).not.toBeNull();
158
+ await disposeGitWorkspaceSnapshot(recovered);
159
+ });
160
+ //# sourceMappingURL=workspace-manifest.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-manifest.test.js","sourceRoot":"","sources":["../src/workspace-manifest.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { RuntimeProgressSink } from "./runtime-progress.js";
2
+ type RestorePhase = "workspace" | "asset";
3
+ declare const RESTORE_STEPS: Set<"asset_restore" | "directory_merge" | "git_export" | "git_import" | "git_integration" | "git_ref_cleanup" | "index_reset" | "workspace_extract" | "workspace_transfer">;
4
+ export type WorkspaceRestoreStep = typeof RESTORE_STEPS extends Set<infer T> ? T : never;
5
+ declare const GIT_COMMANDS: Set<"commit_tree" | "log" | "merge_base" | "merge_tree" | "rev_parse" | "symbolic_ref" | "update_ref">;
6
+ export type WorkspaceRestoreGitCommand = typeof GIT_COMMANDS extends Set<infer T> ? T : never;
7
+ declare const GIT_FAILURE_KINDS: Set<"invalid_object" | "merge_conflict" | "permission_denied" | "ref_conflict" | "unknown">;
8
+ type GitFailureKind = typeof GIT_FAILURE_KINDS extends Set<infer T> ? T : never;
9
+ export interface WorkspaceRestoreDiagnostic {
10
+ phase: RestorePhase;
11
+ step?: WorkspaceRestoreStep;
12
+ errorCode: string;
13
+ httpStatus?: number;
14
+ exitCode?: number;
15
+ gitCommand?: WorkspaceRestoreGitCommand;
16
+ gitFailureKind?: GitFailureKind;
17
+ }
18
+ /** Keep each settlement's diagnostic receipt isolated across asynchronous work. */
19
+ export declare function withWorkspaceRestoreDiagnosticCapture<T>(operation: () => Promise<T>): Promise<T>;
20
+ /** Annotate the original thrown error in its restore scope; never change it. */
21
+ export declare function withWorkspaceRestoreGitCommand<T>(command: WorkspaceRestoreGitCommand, operation: () => Promise<T>): Promise<T>;
22
+ /** Retain bounded fields across an existing error wrapper, without a raw cause. */
23
+ export declare function preserveWorkspaceRestoreErrorDiagnostic<T extends object>(wrapper: T, source: unknown): T;
24
+ /** Decode persisted adapter metadata; never copy arbitrary properties or text. */
25
+ export declare function sanitizeWorkspaceRestoreDiagnostic(value: unknown): WorkspaceRestoreDiagnostic | undefined;
26
+ export declare function getWorkspaceRestoreDiagnostic(error: unknown): WorkspaceRestoreDiagnostic | undefined;
27
+ /** Preserve the scheduler-selected task's snapshot when errors share identity. */
28
+ export declare function recordWorkspaceRestoreDiagnostic(error: unknown, diagnostic: WorkspaceRestoreDiagnostic | undefined): void;
29
+ /** Record only the failing step. Successful cleanup must not replace evidence. */
30
+ export declare function withWorkspaceRestoreStep<T>(step: WorkspaceRestoreStep, operation: () => Promise<T>): Promise<T>;
31
+ /** Add evidence without changing the thrown error, restore policy, or task ordering. */
32
+ export declare function withWorkspaceRestoreDiagnostics<T>(phase: RestorePhase, operation: () => Promise<T>, onProgress?: RuntimeProgressSink, onDiagnostic?: (diagnostic: WorkspaceRestoreDiagnostic) => void): Promise<T>;
33
+ export {};
34
+ //# sourceMappingURL=workspace-restore-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-restore-diagnostics.d.ts","sourceRoot":"","sources":["../src/workspace-restore-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,KAAK,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAC1C,QAAA,MAAM,aAAa,6KAGR,CAAC;AACZ,MAAM,MAAM,oBAAoB,GAAG,OAAO,aAAa,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AACzF,QAAA,MAAM,YAAY,wGAEP,CAAC;AACZ,MAAM,MAAM,0BAA0B,GAAG,OAAO,YAAY,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAC9F,QAAA,MAAM,iBAAiB,6FAEZ,CAAC;AACZ,KAAK,cAAc,GAAG,OAAO,iBAAiB,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAChF,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAuBD,mFAAmF;AACnF,wBAAgB,qCAAqC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEhG;AAmCD,gFAAgF;AAChF,wBAAsB,8BAA8B,CAAC,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAcpI;AA6BD,mFAAmF;AACnF,wBAAgB,uCAAuC,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,CAMxG;AAED,kFAAkF;AAClF,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,GAAG,SAAS,CA0BzG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,GAAG,SAAS,CAGpG;AAED,kFAAkF;AAClF,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,0BAA0B,GAAG,SAAS,GAAG,IAAI,CAezH;AAED,kFAAkF;AAClF,wBAAsB,wBAAwB,CAAC,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmBrH;AAED,wFAAwF;AACxF,wBAAsB,+BAA+B,CAAC,CAAC,EACrD,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,UAAU,CAAC,EAAE,mBAAmB,EAChC,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,0BAA0B,KAAK,IAAI,GAC9D,OAAO,CAAC,CAAC,CAAC,CAgCZ"}