@rewind-ai/cli 0.6.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 (244) hide show
  1. package/.env.example +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +39 -0
  4. package/dist/src/action/capture.d.ts +15 -0
  5. package/dist/src/action/capture.js +215 -0
  6. package/dist/src/action/capture.js.map +1 -0
  7. package/dist/src/action/mediate.d.ts +28 -0
  8. package/dist/src/action/mediate.js +109 -0
  9. package/dist/src/action/mediate.js.map +1 -0
  10. package/dist/src/action/mutate.d.ts +11 -0
  11. package/dist/src/action/mutate.js +189 -0
  12. package/dist/src/action/mutate.js.map +1 -0
  13. package/dist/src/action/objects.d.ts +5 -0
  14. package/dist/src/action/objects.js +50 -0
  15. package/dist/src/action/objects.js.map +1 -0
  16. package/dist/src/action/store.d.ts +24 -0
  17. package/dist/src/action/store.js +149 -0
  18. package/dist/src/action/store.js.map +1 -0
  19. package/dist/src/action/types.d.ts +84 -0
  20. package/dist/src/action/types.js +3 -0
  21. package/dist/src/action/types.js.map +1 -0
  22. package/dist/src/action/undo.d.ts +11 -0
  23. package/dist/src/action/undo.js +42 -0
  24. package/dist/src/action/undo.js.map +1 -0
  25. package/dist/src/adapters/filesystem.d.ts +35 -0
  26. package/dist/src/adapters/filesystem.js +499 -0
  27. package/dist/src/adapters/filesystem.js.map +1 -0
  28. package/dist/src/adapters/index.d.ts +7 -0
  29. package/dist/src/adapters/index.js +19 -0
  30. package/dist/src/adapters/index.js.map +1 -0
  31. package/dist/src/adapters/types.d.ts +54 -0
  32. package/dist/src/adapters/types.js +7 -0
  33. package/dist/src/adapters/types.js.map +1 -0
  34. package/dist/src/api/server.d.ts +25 -0
  35. package/dist/src/api/server.js +786 -0
  36. package/dist/src/api/server.js.map +1 -0
  37. package/dist/src/approval/store.d.ts +35 -0
  38. package/dist/src/approval/store.js +113 -0
  39. package/dist/src/approval/store.js.map +1 -0
  40. package/dist/src/checkpoint.d.ts +9 -0
  41. package/dist/src/checkpoint.js +140 -0
  42. package/dist/src/checkpoint.js.map +1 -0
  43. package/dist/src/cli/v5.d.ts +15 -0
  44. package/dist/src/cli/v5.js +110 -0
  45. package/dist/src/cli/v5.js.map +1 -0
  46. package/dist/src/cli.d.ts +2 -0
  47. package/dist/src/cli.js +823 -0
  48. package/dist/src/cli.js.map +1 -0
  49. package/dist/src/clients/types.d.ts +90 -0
  50. package/dist/src/clients/types.js +239 -0
  51. package/dist/src/clients/types.js.map +1 -0
  52. package/dist/src/commercial/auth/provider.d.ts +61 -0
  53. package/dist/src/commercial/auth/provider.js +227 -0
  54. package/dist/src/commercial/auth/provider.js.map +1 -0
  55. package/dist/src/commercial/entitlement/provider.d.ts +27 -0
  56. package/dist/src/commercial/entitlement/provider.js +192 -0
  57. package/dist/src/commercial/entitlement/provider.js.map +1 -0
  58. package/dist/src/commercial/entitlement/signing.d.ts +61 -0
  59. package/dist/src/commercial/entitlement/signing.js +124 -0
  60. package/dist/src/commercial/entitlement/signing.js.map +1 -0
  61. package/dist/src/commercial/env.d.ts +10 -0
  62. package/dist/src/commercial/env.js +40 -0
  63. package/dist/src/commercial/env.js.map +1 -0
  64. package/dist/src/commercial/product.d.ts +26 -0
  65. package/dist/src/commercial/product.js +39 -0
  66. package/dist/src/commercial/product.js.map +1 -0
  67. package/dist/src/commercial/store.d.ts +46 -0
  68. package/dist/src/commercial/store.js +104 -0
  69. package/dist/src/commercial/store.js.map +1 -0
  70. package/dist/src/commercial/stripe/checkout.d.ts +104 -0
  71. package/dist/src/commercial/stripe/checkout.js +469 -0
  72. package/dist/src/commercial/stripe/checkout.js.map +1 -0
  73. package/dist/src/core/compatibility.d.ts +15 -0
  74. package/dist/src/core/compatibility.js +226 -0
  75. package/dist/src/core/compatibility.js.map +1 -0
  76. package/dist/src/core/engine.d.ts +33 -0
  77. package/dist/src/core/engine.js +432 -0
  78. package/dist/src/core/engine.js.map +1 -0
  79. package/dist/src/core/lifecycle.d.ts +17 -0
  80. package/dist/src/core/lifecycle.js +56 -0
  81. package/dist/src/core/lifecycle.js.map +1 -0
  82. package/dist/src/core/types.d.ts +140 -0
  83. package/dist/src/core/types.js +37 -0
  84. package/dist/src/core/types.js.map +1 -0
  85. package/dist/src/destroy.d.ts +21 -0
  86. package/dist/src/destroy.js +219 -0
  87. package/dist/src/destroy.js.map +1 -0
  88. package/dist/src/diff.d.ts +13 -0
  89. package/dist/src/diff.js +251 -0
  90. package/dist/src/diff.js.map +1 -0
  91. package/dist/src/enforcement/detect.d.ts +13 -0
  92. package/dist/src/enforcement/detect.js +75 -0
  93. package/dist/src/enforcement/detect.js.map +1 -0
  94. package/dist/src/enforcement/hook-policy.d.ts +38 -0
  95. package/dist/src/enforcement/hook-policy.js +111 -0
  96. package/dist/src/enforcement/hook-policy.js.map +1 -0
  97. package/dist/src/enforcement/index.d.ts +8 -0
  98. package/dist/src/enforcement/index.js +8 -0
  99. package/dist/src/enforcement/index.js.map +1 -0
  100. package/dist/src/enforcement/perf.d.ts +6 -0
  101. package/dist/src/enforcement/perf.js +18 -0
  102. package/dist/src/enforcement/perf.js.map +1 -0
  103. package/dist/src/enforcement/policy.d.ts +12 -0
  104. package/dist/src/enforcement/policy.js +84 -0
  105. package/dist/src/enforcement/policy.js.map +1 -0
  106. package/dist/src/enforcement/readonly.d.ts +17 -0
  107. package/dist/src/enforcement/readonly.js +124 -0
  108. package/dist/src/enforcement/readonly.js.map +1 -0
  109. package/dist/src/enforcement/sandbox-clone.d.ts +6 -0
  110. package/dist/src/enforcement/sandbox-clone.js +11 -0
  111. package/dist/src/enforcement/sandbox-clone.js.map +1 -0
  112. package/dist/src/enforcement/setup.d.ts +33 -0
  113. package/dist/src/enforcement/setup.js +168 -0
  114. package/dist/src/enforcement/setup.js.map +1 -0
  115. package/dist/src/enforcement/trust.d.ts +10 -0
  116. package/dist/src/enforcement/trust.js +71 -0
  117. package/dist/src/enforcement/trust.js.map +1 -0
  118. package/dist/src/enforcement/types.d.ts +40 -0
  119. package/dist/src/enforcement/types.js +3 -0
  120. package/dist/src/enforcement/types.js.map +1 -0
  121. package/dist/src/entitlement/provider.d.ts +48 -0
  122. package/dist/src/entitlement/provider.js +95 -0
  123. package/dist/src/entitlement/provider.js.map +1 -0
  124. package/dist/src/hash.d.ts +9 -0
  125. package/dist/src/hash.js +23 -0
  126. package/dist/src/hash.js.map +1 -0
  127. package/dist/src/ledger/query.d.ts +19 -0
  128. package/dist/src/ledger/query.js +158 -0
  129. package/dist/src/ledger/query.js.map +1 -0
  130. package/dist/src/manifest.d.ts +32 -0
  131. package/dist/src/manifest.js +242 -0
  132. package/dist/src/manifest.js.map +1 -0
  133. package/dist/src/mcp/server.d.ts +7 -0
  134. package/dist/src/mcp/server.js +364 -0
  135. package/dist/src/mcp/server.js.map +1 -0
  136. package/dist/src/paths.d.ts +94 -0
  137. package/dist/src/paths.js +354 -0
  138. package/dist/src/paths.js.map +1 -0
  139. package/dist/src/permission/engine.d.ts +15 -0
  140. package/dist/src/permission/engine.js +147 -0
  141. package/dist/src/permission/engine.js.map +1 -0
  142. package/dist/src/permission/types.d.ts +42 -0
  143. package/dist/src/permission/types.js +3 -0
  144. package/dist/src/permission/types.js.map +1 -0
  145. package/dist/src/product/setup.d.ts +35 -0
  146. package/dist/src/product/setup.js +300 -0
  147. package/dist/src/product/setup.js.map +1 -0
  148. package/dist/src/protect/audit.d.ts +5 -0
  149. package/dist/src/protect/audit.js +26 -0
  150. package/dist/src/protect/audit.js.map +1 -0
  151. package/dist/src/protect/capture.d.ts +7 -0
  152. package/dist/src/protect/capture.js +250 -0
  153. package/dist/src/protect/capture.js.map +1 -0
  154. package/dist/src/protect/fingerprint.d.ts +4 -0
  155. package/dist/src/protect/fingerprint.js +49 -0
  156. package/dist/src/protect/fingerprint.js.map +1 -0
  157. package/dist/src/protect/hook-cli.d.ts +2 -0
  158. package/dist/src/protect/hook-cli.js +107 -0
  159. package/dist/src/protect/hook-cli.js.map +1 -0
  160. package/dist/src/protect/index.d.ts +12 -0
  161. package/dist/src/protect/index.js +12 -0
  162. package/dist/src/protect/index.js.map +1 -0
  163. package/dist/src/protect/install.d.ts +34 -0
  164. package/dist/src/protect/install.js +293 -0
  165. package/dist/src/protect/install.js.map +1 -0
  166. package/dist/src/protect/intercept.d.ts +11 -0
  167. package/dist/src/protect/intercept.js +390 -0
  168. package/dist/src/protect/intercept.js.map +1 -0
  169. package/dist/src/protect/protect.d.ts +17 -0
  170. package/dist/src/protect/protect.js +194 -0
  171. package/dist/src/protect/protect.js.map +1 -0
  172. package/dist/src/protect/root-paths.d.ts +13 -0
  173. package/dist/src/protect/root-paths.js +140 -0
  174. package/dist/src/protect/root-paths.js.map +1 -0
  175. package/dist/src/protect/shell-policy.d.ts +17 -0
  176. package/dist/src/protect/shell-policy.js +269 -0
  177. package/dist/src/protect/shell-policy.js.map +1 -0
  178. package/dist/src/protect/status.d.ts +11 -0
  179. package/dist/src/protect/status.js +165 -0
  180. package/dist/src/protect/status.js.map +1 -0
  181. package/dist/src/protect/store.d.ts +20 -0
  182. package/dist/src/protect/store.js +170 -0
  183. package/dist/src/protect/store.js.map +1 -0
  184. package/dist/src/protect/types.d.ts +116 -0
  185. package/dist/src/protect/types.js +3 -0
  186. package/dist/src/protect/types.js.map +1 -0
  187. package/dist/src/protect/undo-session.d.ts +14 -0
  188. package/dist/src/protect/undo-session.js +182 -0
  189. package/dist/src/protect/undo-session.js.map +1 -0
  190. package/dist/src/restore.d.ts +39 -0
  191. package/dist/src/restore.js +141 -0
  192. package/dist/src/restore.js.map +1 -0
  193. package/dist/src/sandbox.d.ts +23 -0
  194. package/dist/src/sandbox.js +198 -0
  195. package/dist/src/sandbox.js.map +1 -0
  196. package/dist/src/session/ambient.d.ts +10 -0
  197. package/dist/src/session/ambient.js +53 -0
  198. package/dist/src/session/ambient.js.map +1 -0
  199. package/dist/src/session/attribution.d.ts +27 -0
  200. package/dist/src/session/attribution.js +201 -0
  201. package/dist/src/session/attribution.js.map +1 -0
  202. package/dist/src/session/index.d.ts +25 -0
  203. package/dist/src/session/index.js +472 -0
  204. package/dist/src/session/index.js.map +1 -0
  205. package/dist/src/session/process.d.ts +34 -0
  206. package/dist/src/session/process.js +234 -0
  207. package/dist/src/session/process.js.map +1 -0
  208. package/dist/src/session/store.d.ts +14 -0
  209. package/dist/src/session/store.js +125 -0
  210. package/dist/src/session/store.js.map +1 -0
  211. package/dist/src/session/types.d.ts +111 -0
  212. package/dist/src/session/types.js +3 -0
  213. package/dist/src/session/types.js.map +1 -0
  214. package/dist/src/session/watcher.d.ts +32 -0
  215. package/dist/src/session/watcher.js +186 -0
  216. package/dist/src/session/watcher.js.map +1 -0
  217. package/dist/src/timing.d.ts +7 -0
  218. package/dist/src/timing.js +19 -0
  219. package/dist/src/timing.js.map +1 -0
  220. package/dist/src/types.d.ts +101 -0
  221. package/dist/src/types.js +3 -0
  222. package/dist/src/types.js.map +1 -0
  223. package/dist/src/verify.d.ts +8 -0
  224. package/dist/src/verify.js +126 -0
  225. package/dist/src/verify.js.map +1 -0
  226. package/docs/ADAPTERS.md +37 -0
  227. package/docs/APPROVALS.md +32 -0
  228. package/docs/ARCHITECTURE.md +57 -0
  229. package/docs/ATTRIBUTION.md +179 -0
  230. package/docs/COMMERCIAL.md +51 -0
  231. package/docs/CURSOR-ENFORCEMENT.md +73 -0
  232. package/docs/ENFORCEMENT.md +134 -0
  233. package/docs/FUTURE.md +91 -0
  234. package/docs/HUMAN-SETUP.md +98 -0
  235. package/docs/IDENTITY-AUTHORITY.md +35 -0
  236. package/docs/MCP.md +107 -0
  237. package/docs/PACKAGING.md +77 -0
  238. package/docs/PERMISSIONS.md +53 -0
  239. package/docs/PRODUCT-V5.md +63 -0
  240. package/docs/PRODUCT-V6.md +69 -0
  241. package/docs/PROTECTED-SESSIONS.md +155 -0
  242. package/docs/THREAT-MODEL.md +84 -0
  243. package/docs/TRANSACTIONS.md +57 -0
  244. package/package.json +85 -0
@@ -0,0 +1,141 @@
1
+ import path from "node:path";
2
+ import { rm, lstat, readdir } from "node:fs/promises";
3
+ import { getProjectRoot, getSandboxPath, assertApprovedSandbox, isPathInside, PathSafetyError, } from "./paths.js";
4
+ import { loadCheckpoint } from "./checkpoint.js";
5
+ import { buildManifest, materializeFromCheckpoint, walkTree, toRelativePosix, } from "./manifest.js";
6
+ import { verifyAgainstCheckpoint } from "./verify.js";
7
+ import { Timer } from "./timing.js";
8
+ /**
9
+ * Restore sandbox to checkpoint state.
10
+ *
11
+ * Strategy (correctness-first):
12
+ * 1. Validate target is approved sandbox.
13
+ * 2. Load checkpoint.
14
+ * 3. Remove all current sandbox contents.
15
+ * 4. Materialize files/dirs/symlinks from checkpoint object store.
16
+ * 5. Verify byte-for-byte against checkpoint manifest.
17
+ *
18
+ * If verification fails, throw — never report success.
19
+ */
20
+ export async function restoreSandbox(checkpointId = "latest", projectRoot = getProjectRoot(), options = {}) {
21
+ const totalTimer = new Timer();
22
+ const shouldVerify = options.verify !== false;
23
+ const sandbox = getSandboxPath(projectRoot);
24
+ await assertApprovedSandbox(sandbox, projectRoot);
25
+ const checkpoint = await loadCheckpoint(checkpointId, projectRoot);
26
+ // Ensure checkpoint was taken for this sandbox path
27
+ if (path.resolve(checkpoint.meta.targetPath) !== path.resolve(sandbox)) {
28
+ throw new PathSafetyError(`Checkpoint target mismatch.\n` +
29
+ ` Checkpoint: ${checkpoint.meta.targetPath}\n` +
30
+ ` Sandbox: ${sandbox}`);
31
+ }
32
+ // Validate every manifest path stays inside sandbox when joined
33
+ for (const entry of checkpoint.manifest.entries) {
34
+ const abs = path.join(sandbox, entry.path);
35
+ if (!isPathInside(sandbox, abs)) {
36
+ throw new PathSafetyError(`Checkpoint entry would escape sandbox: ${entry.path}`);
37
+ }
38
+ }
39
+ const clearTimer = new Timer();
40
+ await clearSandboxContents(sandbox, projectRoot);
41
+ const clearMs = clearTimer.elapsedMs();
42
+ const matTimer = new Timer();
43
+ try {
44
+ await materializeFromCheckpoint(checkpoint.directory, checkpoint.manifest, sandbox);
45
+ }
46
+ catch (err) {
47
+ throw new Error(`Restore failed during materialization: ${err instanceof Error ? err.message : String(err)}`);
48
+ }
49
+ const materializeMs = matTimer.elapsedMs();
50
+ let verification;
51
+ const verifyTimer = new Timer();
52
+ if (shouldVerify) {
53
+ verification = await verifyAgainstCheckpoint(checkpoint, projectRoot);
54
+ if (!verification.ok) {
55
+ const details = verification.mismatches
56
+ .slice(0, 20)
57
+ .map((m) => ` - ${m.path}: ${m.reason}`)
58
+ .join("\n");
59
+ throw new Error(`RESTORE FAILED — verification mismatch\n` +
60
+ `Expected: ${verification.expectedFingerprint}\n` +
61
+ `Actual: ${verification.actualFingerprint}\n` +
62
+ `Mismatches:\n${details}`);
63
+ }
64
+ }
65
+ else {
66
+ verification = {
67
+ ok: false,
68
+ filesChecked: 0,
69
+ expectedFingerprint: checkpoint.manifest.fingerprint,
70
+ actualFingerprint: "",
71
+ mismatches: [],
72
+ timingsMs: { manifest: 0, compare: 0, total: 0 },
73
+ };
74
+ }
75
+ const verifyMs = verifyTimer.elapsedMs();
76
+ return {
77
+ checkpoint,
78
+ verification,
79
+ timingsMs: {
80
+ clear: clearMs,
81
+ materialize: materializeMs,
82
+ verify: verifyMs,
83
+ total: totalTimer.elapsedMs(),
84
+ },
85
+ };
86
+ }
87
+ /**
88
+ * Delete everything inside the sandbox without deleting the sandbox root.
89
+ * Refuses if any entry resolves outside the sandbox.
90
+ */
91
+ export async function clearSandboxContents(sandbox, projectRoot = getProjectRoot()) {
92
+ await assertApprovedSandbox(sandbox, projectRoot);
93
+ let entries;
94
+ try {
95
+ entries = await readdir(sandbox);
96
+ }
97
+ catch (err) {
98
+ throw new Error(`Cannot read sandbox for clear: ${err instanceof Error ? err.message : String(err)}`);
99
+ }
100
+ for (const name of entries) {
101
+ const abs = path.join(sandbox, name);
102
+ if (!isPathInside(sandbox, abs)) {
103
+ throw new PathSafetyError(`Refusing to delete outside sandbox: ${abs}`);
104
+ }
105
+ // Symlink escape check: if it's a symlink pointing out, still only rm the link itself.
106
+ await rm(abs, { recursive: true, force: true });
107
+ }
108
+ // Confirm empty
109
+ const left = await readdir(sandbox);
110
+ if (left.length > 0) {
111
+ throw new Error(`Failed to clear sandbox; remaining: ${left.join(", ")}`);
112
+ }
113
+ }
114
+ /**
115
+ * Incremental restore alternative used for analysis — not the primary path.
116
+ * Kept for potential future use / tests of selective apply.
117
+ */
118
+ export async function listExtraneousPaths(sandbox, checkpointPaths) {
119
+ const all = await walkTree(sandbox);
120
+ const extra = [];
121
+ for (const abs of all) {
122
+ const rel = toRelativePosix(sandbox, abs);
123
+ if (!checkpointPaths.has(rel)) {
124
+ extra.push(rel);
125
+ }
126
+ }
127
+ // Delete deepest paths first when applying
128
+ extra.sort((a, b) => b.length - a.length || b.localeCompare(a));
129
+ return extra;
130
+ }
131
+ export async function sandboxExists(projectRoot = getProjectRoot()) {
132
+ try {
133
+ const st = await lstat(getSandboxPath(projectRoot));
134
+ return st.isDirectory();
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ export { buildManifest };
141
+ //# sourceMappingURL=restore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore.js","sourceRoot":"","sources":["../../src/restore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Deterministic disposable sandbox generator.
3
+ * Same seed → same tree (paths + contents).
4
+ */
5
+ export declare const SANDBOX_SEED = "rewind-v0-sandbox-v1";
6
+ export interface SandboxCreateResult {
7
+ root: string;
8
+ fileCount: number;
9
+ directoryCount: number;
10
+ symlinkCount: number;
11
+ totalEntries: number;
12
+ }
13
+ /**
14
+ * Create (or recreate) the disposable sandbox deterministically.
15
+ */
16
+ export declare function createSandbox(projectRoot?: string): Promise<SandboxCreateResult>;
17
+ /**
18
+ * Materialize a planned sandbox tree at an absolute root.
19
+ * Caller must have already validated the root identity.
20
+ */
21
+ export declare function materializeSandbox(root: string, seed: string): Promise<SandboxCreateResult>;
22
+ /** Expected file count for tests (stable for current seed plan). */
23
+ export declare function expectedSandboxFileCount(): number;
@@ -0,0 +1,198 @@
1
+ import path from "node:path";
2
+ import { mkdir, writeFile, symlink, chmod, rm } from "node:fs/promises";
3
+ import { createHash } from "node:crypto";
4
+ import { getProjectRoot, getSandboxPath, assertSafeRelativePath, isPathInside, PathSafetyError, } from "./paths.js";
5
+ /**
6
+ * Deterministic disposable sandbox generator.
7
+ * Same seed → same tree (paths + contents).
8
+ */
9
+ export const SANDBOX_SEED = "rewind-v0-sandbox-v1";
10
+ function seededBytes(seed, n) {
11
+ const out = Buffer.alloc(n);
12
+ let block = seed;
13
+ let offset = 0;
14
+ while (offset < n) {
15
+ const digest = createHash("sha256").update(block).digest();
16
+ const take = Math.min(digest.length, n - offset);
17
+ digest.copy(out, offset, 0, take);
18
+ offset += take;
19
+ block = digest.toString("hex");
20
+ }
21
+ return out;
22
+ }
23
+ function textFromSeed(seed, lines) {
24
+ const parts = [];
25
+ for (let i = 0; i < lines; i++) {
26
+ const h = createHash("sha256").update(`${seed}:${i}`).digest("hex");
27
+ parts.push(`// line ${i}: ${h.slice(0, 32)}`);
28
+ }
29
+ return parts.join("\n") + "\n";
30
+ }
31
+ function planSandbox(seed) {
32
+ const dirs = new Set();
33
+ const files = [];
34
+ const symlinks = [];
35
+ const addDir = (rel) => {
36
+ const clean = assertSafeRelativePath(rel);
37
+ const parts = clean.split("/");
38
+ let acc = "";
39
+ for (const p of parts) {
40
+ acc = acc ? `${acc}/${p}` : p;
41
+ dirs.add(acc);
42
+ }
43
+ };
44
+ const addFile = (rel, content, mode = 0o644) => {
45
+ const clean = assertSafeRelativePath(rel);
46
+ const dir = path.posix.dirname(clean);
47
+ if (dir !== ".") {
48
+ addDir(dir);
49
+ }
50
+ files.push({ rel: clean, content, mode });
51
+ };
52
+ // Base structure
53
+ const baseDirs = [
54
+ "src",
55
+ "src/components",
56
+ "src/utils",
57
+ "src/hooks",
58
+ "data",
59
+ "data/fixtures",
60
+ "public",
61
+ "public/assets",
62
+ "config",
63
+ "docs",
64
+ "nested/level1/level2/level3/level4",
65
+ "empty-dir",
66
+ "unicode",
67
+ "with spaces/sub folder",
68
+ ];
69
+ for (const d of baseDirs)
70
+ addDir(d);
71
+ // ~120 text/code/json/md/css files
72
+ for (let i = 0; i < 40; i++) {
73
+ addFile(`src/components/Component${String(i).padStart(3, "0")}.tsx`, Buffer.from(textFromSeed(`${seed}:component:${i}`, 8) +
74
+ `export const Component${i} = () => null;\n`, "utf8"));
75
+ }
76
+ for (let i = 0; i < 30; i++) {
77
+ addFile(`src/utils/util_${String(i).padStart(3, "0")}.ts`, Buffer.from(textFromSeed(`${seed}:util:${i}`, 5) +
78
+ `export function util${i}(x: number): number { return x + ${i}; }\n`, "utf8"));
79
+ }
80
+ for (let i = 0; i < 20; i++) {
81
+ const obj = {
82
+ id: i,
83
+ seed,
84
+ values: Array.from({ length: 5 }, (_, j) => createHash("sha256").update(`${seed}:json:${i}:${j}`).digest("hex").slice(0, 16)),
85
+ };
86
+ addFile(`data/fixtures/data-${String(i).padStart(3, "0")}.json`, Buffer.from(JSON.stringify(obj, null, 2) + "\n", "utf8"));
87
+ }
88
+ for (let i = 0; i < 15; i++) {
89
+ addFile(`docs/note-${String(i).padStart(3, "0")}.md`, Buffer.from(`# Note ${i}\n\n${textFromSeed(`${seed}:md:${i}`, 4)}\n`, "utf8"));
90
+ }
91
+ for (let i = 0; i < 10; i++) {
92
+ addFile(`public/assets/style-${String(i).padStart(2, "0")}.css`, Buffer.from(`/* ${seed} style ${i} */\n.block-${i} { color: #${createHash("sha256").update(`${seed}:css:${i}`).digest("hex").slice(0, 6)}; }\n`, "utf8"));
93
+ }
94
+ // Config files
95
+ addFile("config/app.json", Buffer.from(JSON.stringify({ name: "sandbox-test-project", seed, version: 1 }, null, 2) +
96
+ "\n", "utf8"));
97
+ addFile("config/settings.ini", Buffer.from(`[app]\nseed=${seed}\ndebug=false\n`, "utf8"));
98
+ addFile("README.md", Buffer.from(`# Sandbox\n\nSeed: ${seed}\n`, "utf8"));
99
+ addFile("src/index.ts", Buffer.from(`export const SEED = "${seed}";\n`, "utf8"));
100
+ // Empty files
101
+ for (let i = 0; i < 5; i++) {
102
+ addFile(`data/empty-${i}.txt`, Buffer.alloc(0));
103
+ }
104
+ // Filenames with spaces
105
+ addFile("with spaces/hello world.txt", Buffer.from(`hello from spaced path\n${seed}\n`, "utf8"));
106
+ addFile("with spaces/sub folder/nested file.ts", Buffer.from(`export const spaced = true;\n`, "utf8"));
107
+ // Unicode filenames (NFC normalized, safe on macOS APFS)
108
+ addFile("unicode/café-notes.txt", Buffer.from("café contents\n", "utf8"));
109
+ addFile("unicode/日本語.txt", Buffer.from("日本語テスト\n", "utf8"));
110
+ addFile("unicode/emoji-📁-name.txt", Buffer.from("emoji filename ok\n", "utf8"));
111
+ // Deeply nested
112
+ addFile("nested/level1/level2/level3/level4/deep.txt", Buffer.from(textFromSeed(`${seed}:deep`, 3), "utf8"));
113
+ // Small binary fixtures
114
+ for (let i = 0; i < 8; i++) {
115
+ addFile(`data/fixtures/bin-${String(i).padStart(2, "0")}.bin`, seededBytes(`${seed}:bin:${i}`, 256 + i * 17), 0o644);
116
+ }
117
+ // Executable-ish script (permission 755)
118
+ addFile("src/utils/run-tool.sh", Buffer.from(`#!/bin/sh\necho "${seed}"\n`, "utf8"), 0o755);
119
+ // Internal symlink (safe, stays inside sandbox)
120
+ addDir("links");
121
+ symlinks.push({
122
+ rel: "links/to-readme.md",
123
+ target: "../README.md",
124
+ });
125
+ symlinks.push({
126
+ rel: "links/to-config",
127
+ target: "../config/app.json",
128
+ });
129
+ // Ensure empty-dir exists with no files (dirs set already)
130
+ return {
131
+ dirs: [...dirs].sort((a, b) => a.localeCompare(b)),
132
+ files,
133
+ symlinks,
134
+ };
135
+ }
136
+ /**
137
+ * Create (or recreate) the disposable sandbox deterministically.
138
+ */
139
+ export async function createSandbox(projectRoot = getProjectRoot()) {
140
+ const root = getSandboxPath(projectRoot);
141
+ // Safety: only ever wipe the exact sandbox path under project root.
142
+ if (path.basename(root) !== "sandbox-test-project") {
143
+ throw new PathSafetyError("Refusing to create sandbox with unexpected name");
144
+ }
145
+ if (path.dirname(root) !== path.resolve(projectRoot)) {
146
+ throw new PathSafetyError("Sandbox is not directly under project root");
147
+ }
148
+ return materializeSandbox(root, SANDBOX_SEED);
149
+ }
150
+ /**
151
+ * Materialize a planned sandbox tree at an absolute root.
152
+ * Caller must have already validated the root identity.
153
+ */
154
+ export async function materializeSandbox(root, seed) {
155
+ await rm(root, { recursive: true, force: true });
156
+ await mkdir(root, { recursive: true });
157
+ const plan = planSandbox(seed);
158
+ for (const d of plan.dirs) {
159
+ const abs = path.join(root, d);
160
+ if (!isPathInside(root, abs)) {
161
+ throw new PathSafetyError(`Planned dir escapes: ${d}`);
162
+ }
163
+ await mkdir(abs, { recursive: true });
164
+ }
165
+ for (const f of plan.files) {
166
+ const abs = path.join(root, f.rel);
167
+ if (!isPathInside(root, abs)) {
168
+ throw new PathSafetyError(`Planned file escapes: ${f.rel}`);
169
+ }
170
+ await mkdir(path.dirname(abs), { recursive: true });
171
+ await writeFile(abs, f.content, { mode: f.mode });
172
+ await chmod(abs, f.mode);
173
+ }
174
+ for (const s of plan.symlinks) {
175
+ const abs = path.join(root, s.rel);
176
+ if (!isPathInside(root, abs)) {
177
+ throw new PathSafetyError(`Planned symlink escapes: ${s.rel}`);
178
+ }
179
+ const resolved = path.resolve(path.dirname(abs), s.target);
180
+ if (!isPathInside(root, resolved)) {
181
+ throw new PathSafetyError(`Symlink target escapes: ${s.rel}`);
182
+ }
183
+ await mkdir(path.dirname(abs), { recursive: true });
184
+ await symlink(s.target, abs);
185
+ }
186
+ return {
187
+ root,
188
+ fileCount: plan.files.length,
189
+ directoryCount: plan.dirs.length,
190
+ symlinkCount: plan.symlinks.length,
191
+ totalEntries: plan.files.length + plan.dirs.length + plan.symlinks.length,
192
+ };
193
+ }
194
+ /** Expected file count for tests (stable for current seed plan). */
195
+ export function expectedSandboxFileCount() {
196
+ return planSandbox(SANDBOX_SEED).files.length;
197
+ }
198
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Known ambient / OS / editor noise patterns.
3
+ * Filename patterns are EVIDENCE of ambient likelihood — not proof of actor.
4
+ */
5
+ export interface AmbientMatch {
6
+ ambient: boolean;
7
+ label: string;
8
+ evidence: string;
9
+ }
10
+ export declare function matchAmbientPath(relPath: string): AmbientMatch;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Known ambient / OS / editor noise patterns.
3
+ * Filename patterns are EVIDENCE of ambient likelihood — not proof of actor.
4
+ */
5
+ const AMBIENT_BASENAMES = new Set([
6
+ ".ds_store",
7
+ "thumbs.db",
8
+ "desktop.ini",
9
+ ".localized",
10
+ ]);
11
+ const AMBIENT_EXACT = new Set([
12
+ ".ds_store",
13
+ ]);
14
+ export function matchAmbientPath(relPath) {
15
+ const base = relPath.split("/").pop()?.toLowerCase() ?? "";
16
+ const lower = relPath.toLowerCase();
17
+ if (AMBIENT_BASENAMES.has(base) || AMBIENT_EXACT.has(lower)) {
18
+ return {
19
+ ambient: true,
20
+ label: "AMBIENT",
21
+ evidence: `known ambient basename: ${base}`,
22
+ };
23
+ }
24
+ // Editor / tooling temp patterns (still only MEDIUM confidence ambient)
25
+ if (base.endsWith("~") ||
26
+ base.endsWith(".swp") ||
27
+ base.endsWith(".swo") ||
28
+ /^\.#/.test(base) ||
29
+ /^#.*#$/.test(base)) {
30
+ return {
31
+ ambient: true,
32
+ label: "AMBIENT",
33
+ evidence: `editor temp filename pattern: ${base}`,
34
+ };
35
+ }
36
+ if (base.startsWith(".tmp") || base.endsWith(".tmp") || base.includes(".tmp.")) {
37
+ return {
38
+ ambient: true,
39
+ label: "AMBIENT",
40
+ evidence: `temp filename pattern: ${base}`,
41
+ };
42
+ }
43
+ // Cursor / VS Code sometimes writes these inside workspaces
44
+ if (lower.includes("/.vscode/") || lower.startsWith(".vscode/")) {
45
+ return {
46
+ ambient: true,
47
+ label: "AMBIENT",
48
+ evidence: "editor metadata path (.vscode)",
49
+ };
50
+ }
51
+ return { ambient: false, label: "", evidence: "" };
52
+ }
53
+ //# sourceMappingURL=ambient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ambient.js","sourceRoot":"","sources":["../../../src/session/ambient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,WAAW;IACX,WAAW;IACX,aAAa;IACb,YAAY;CACb,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,WAAW;CACZ,CAAC,CAAC;AAEH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEpC,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,2BAA2B,IAAI,EAAE;SAC5C,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,IACE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EACnB,CAAC;QACD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,iCAAiC,IAAI,EAAE;SAClD,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/E,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,0BAA0B,IAAI,EAAE;SAC3C,CAAC;IACJ,CAAC;IAED,4DAA4D;IAC5D,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChE,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,gCAAgC;SAC3C,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { Change } from "../types.js";
2
+ import type { AttributedChange, AttributionConfidence, AttributionSummary, ObservedEvent, ProcessSnapshot } from "./types.js";
3
+ /**
4
+ * Correlate authoritative manifest diffs with watcher signals + weak process hints.
5
+ *
6
+ * Honesty rules:
7
+ * - Do NOT label AGENT just because Cursor is running.
8
+ * - Ambient filename patterns → SYSTEM / MEDIUM with explicit evidence.
9
+ * - Watcher-only correlation → UNKNOWN / NONE or LOW if temporally near events.
10
+ * - lsof open-handle matches (if provided via evidence on events) can raise LOW→MEDIUM.
11
+ * - Without Endpoint Security / responsible-PID metadata, HIGH agent confidence is unreachable.
12
+ */
13
+ export declare function attributeChanges(options: {
14
+ changes: Change[];
15
+ events: ObservedEvent[];
16
+ processSnapshots: ProcessSnapshot[];
17
+ /** Optional human-marked paths from concurrent-change test fixtures. */
18
+ knownHumanPaths?: string[];
19
+ /** Optional paths known to be written by REWIND's own chaos/tools during a controlled demo. */
20
+ knownSelfWritePaths?: string[];
21
+ }): {
22
+ attributed: AttributedChange[];
23
+ summary: AttributionSummary;
24
+ overall: AttributionConfidence;
25
+ notes: string[];
26
+ };
27
+ export declare function printAttributionReport(summary: AttributionSummary, durationLabel: string): void;