agentrinse 0.0.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 (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/adapters/artifacts/adapter.d.ts +24 -0
  4. package/dist/adapters/artifacts/adapter.d.ts.map +1 -0
  5. package/dist/adapters/artifacts/adapter.js +342 -0
  6. package/dist/adapters/artifacts/adapter.js.map +1 -0
  7. package/dist/adapters/docker/adapter.d.ts +15 -0
  8. package/dist/adapters/docker/adapter.d.ts.map +1 -0
  9. package/dist/adapters/docker/adapter.js +121 -0
  10. package/dist/adapters/docker/adapter.js.map +1 -0
  11. package/dist/adapters/git/adapter.d.ts +15 -0
  12. package/dist/adapters/git/adapter.d.ts.map +1 -0
  13. package/dist/adapters/git/adapter.js +156 -0
  14. package/dist/adapters/git/adapter.js.map +1 -0
  15. package/dist/adapters/git/porcelain.d.ts +11 -0
  16. package/dist/adapters/git/porcelain.d.ts.map +1 -0
  17. package/dist/adapters/git/porcelain.js +54 -0
  18. package/dist/adapters/git/porcelain.js.map +1 -0
  19. package/dist/adapters/provider-adapter.d.ts +22 -0
  20. package/dist/adapters/provider-adapter.d.ts.map +1 -0
  21. package/dist/adapters/provider-adapter.js +178 -0
  22. package/dist/adapters/provider-adapter.js.map +1 -0
  23. package/dist/adapters/provider-specs.d.ts +16 -0
  24. package/dist/adapters/provider-specs.d.ts.map +1 -0
  25. package/dist/adapters/provider-specs.js +157 -0
  26. package/dist/adapters/provider-specs.js.map +1 -0
  27. package/dist/adapters/registry.d.ts +4 -0
  28. package/dist/adapters/registry.d.ts.map +1 -0
  29. package/dist/adapters/registry.js +28 -0
  30. package/dist/adapters/registry.js.map +1 -0
  31. package/dist/cli.d.ts +3 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +8 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/commands/adapters.d.ts +2 -0
  36. package/dist/commands/adapters.d.ts.map +1 -0
  37. package/dist/commands/adapters.js +17 -0
  38. package/dist/commands/adapters.js.map +1 -0
  39. package/dist/commands/apply.d.ts +15 -0
  40. package/dist/commands/apply.d.ts.map +1 -0
  41. package/dist/commands/apply.js +63 -0
  42. package/dist/commands/apply.js.map +1 -0
  43. package/dist/commands/audit.d.ts +13 -0
  44. package/dist/commands/audit.d.ts.map +1 -0
  45. package/dist/commands/audit.js +22 -0
  46. package/dist/commands/audit.js.map +1 -0
  47. package/dist/commands/plan.d.ts +12 -0
  48. package/dist/commands/plan.d.ts.map +1 -0
  49. package/dist/commands/plan.js +19 -0
  50. package/dist/commands/plan.js.map +1 -0
  51. package/dist/config/defaults.d.ts +3 -0
  52. package/dist/config/defaults.d.ts.map +1 -0
  53. package/dist/config/defaults.js +29 -0
  54. package/dist/config/defaults.js.map +1 -0
  55. package/dist/config/load.d.ts +3 -0
  56. package/dist/config/load.d.ts.map +1 -0
  57. package/dist/config/load.js +31 -0
  58. package/dist/config/load.js.map +1 -0
  59. package/dist/config/schema.d.ts +84 -0
  60. package/dist/config/schema.d.ts.map +1 -0
  61. package/dist/config/schema.js +108 -0
  62. package/dist/config/schema.js.map +1 -0
  63. package/dist/contracts/action.d.ts +109 -0
  64. package/dist/contracts/action.d.ts.map +1 -0
  65. package/dist/contracts/action.js +37 -0
  66. package/dist/contracts/action.js.map +1 -0
  67. package/dist/contracts/adapter.d.ts +21 -0
  68. package/dist/contracts/adapter.d.ts.map +1 -0
  69. package/dist/contracts/adapter.js +2 -0
  70. package/dist/contracts/adapter.js.map +1 -0
  71. package/dist/contracts/diagnostic.d.ts +21 -0
  72. package/dist/contracts/diagnostic.d.ts.map +1 -0
  73. package/dist/contracts/diagnostic.js +11 -0
  74. package/dist/contracts/diagnostic.js.map +1 -0
  75. package/dist/contracts/finding.d.ts +123 -0
  76. package/dist/contracts/finding.d.ts.map +1 -0
  77. package/dist/contracts/finding.js +35 -0
  78. package/dist/contracts/finding.js.map +1 -0
  79. package/dist/contracts/plan.d.ts +53 -0
  80. package/dist/contracts/plan.d.ts.map +1 -0
  81. package/dist/contracts/plan.js +56 -0
  82. package/dist/contracts/plan.js.map +1 -0
  83. package/dist/contracts/report.d.ts +177 -0
  84. package/dist/contracts/report.d.ts.map +1 -0
  85. package/dist/contracts/report.js +29 -0
  86. package/dist/contracts/report.js.map +1 -0
  87. package/dist/contracts/resource.d.ts +72 -0
  88. package/dist/contracts/resource.d.ts.map +1 -0
  89. package/dist/contracts/resource.js +33 -0
  90. package/dist/contracts/resource.js.map +1 -0
  91. package/dist/contracts/run.d.ts +108 -0
  92. package/dist/contracts/run.d.ts.map +1 -0
  93. package/dist/contracts/run.js +35 -0
  94. package/dist/contracts/run.js.map +1 -0
  95. package/dist/core/apply.d.ts +29 -0
  96. package/dist/core/apply.d.ts.map +1 -0
  97. package/dist/core/apply.js +120 -0
  98. package/dist/core/apply.js.map +1 -0
  99. package/dist/core/artifact-executor.d.ts +39 -0
  100. package/dist/core/artifact-executor.d.ts.map +1 -0
  101. package/dist/core/artifact-executor.js +200 -0
  102. package/dist/core/artifact-executor.js.map +1 -0
  103. package/dist/core/artifact-revalidation.d.ts +22 -0
  104. package/dist/core/artifact-revalidation.d.ts.map +1 -0
  105. package/dist/core/artifact-revalidation.js +113 -0
  106. package/dist/core/artifact-revalidation.js.map +1 -0
  107. package/dist/core/audit.d.ts +12 -0
  108. package/dist/core/audit.d.ts.map +1 -0
  109. package/dist/core/audit.js +41 -0
  110. package/dist/core/audit.js.map +1 -0
  111. package/dist/core/digest.d.ts +7 -0
  112. package/dist/core/digest.d.ts.map +1 -0
  113. package/dist/core/digest.js +21 -0
  114. package/dist/core/digest.js.map +1 -0
  115. package/dist/core/measure.d.ts +16 -0
  116. package/dist/core/measure.d.ts.map +1 -0
  117. package/dist/core/measure.js +79 -0
  118. package/dist/core/measure.js.map +1 -0
  119. package/dist/core/mount-boundaries.d.ts +21 -0
  120. package/dist/core/mount-boundaries.d.ts.map +1 -0
  121. package/dist/core/mount-boundaries.js +72 -0
  122. package/dist/core/mount-boundaries.js.map +1 -0
  123. package/dist/core/plan-verification.d.ts +10 -0
  124. package/dist/core/plan-verification.d.ts.map +1 -0
  125. package/dist/core/plan-verification.js +42 -0
  126. package/dist/core/plan-verification.js.map +1 -0
  127. package/dist/core/plan.d.ts +6 -0
  128. package/dist/core/plan.d.ts.map +1 -0
  129. package/dist/core/plan.js +40 -0
  130. package/dist/core/plan.js.map +1 -0
  131. package/dist/core/process-ownership.d.ts +27 -0
  132. package/dist/core/process-ownership.d.ts.map +1 -0
  133. package/dist/core/process-ownership.js +140 -0
  134. package/dist/core/process-ownership.js.map +1 -0
  135. package/dist/core/safety.d.ts +7 -0
  136. package/dist/core/safety.d.ts.map +1 -0
  137. package/dist/core/safety.js +50 -0
  138. package/dist/core/safety.js.map +1 -0
  139. package/dist/index.d.ts +9 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +9 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/main.d.ts +4 -0
  144. package/dist/main.d.ts.map +1 -0
  145. package/dist/main.js +59 -0
  146. package/dist/main.js.map +1 -0
  147. package/dist/output.d.ts +4 -0
  148. package/dist/output.d.ts.map +1 -0
  149. package/dist/output.js +35 -0
  150. package/dist/output.js.map +1 -0
  151. package/dist/state/json-file.d.ts +4 -0
  152. package/dist/state/json-file.d.ts.map +1 -0
  153. package/dist/state/json-file.js +36 -0
  154. package/dist/state/json-file.js.map +1 -0
  155. package/dist/state/layout.d.ts +12 -0
  156. package/dist/state/layout.d.ts.map +1 -0
  157. package/dist/state/layout.js +20 -0
  158. package/dist/state/layout.js.map +1 -0
  159. package/dist/state/lock.d.ts +9 -0
  160. package/dist/state/lock.d.ts.map +1 -0
  161. package/dist/state/lock.js +93 -0
  162. package/dist/state/lock.js.map +1 -0
  163. package/dist/state/run-journal.d.ts +10 -0
  164. package/dist/state/run-journal.d.ts.map +1 -0
  165. package/dist/state/run-journal.js +57 -0
  166. package/dist/state/run-journal.js.map +1 -0
  167. package/dist/version.d.ts +2 -0
  168. package/dist/version.d.ts.map +1 -0
  169. package/dist/version.js +2 -0
  170. package/dist/version.js.map +1 -0
  171. package/package.json +73 -0
  172. package/schemas/audit.schema.json +424 -0
  173. package/schemas/plan.schema.json +184 -0
  174. package/schemas/run.schema.json +161 -0
@@ -0,0 +1,39 @@
1
+ import { type Stats } from "node:fs";
2
+ import type { ArtifactRemoveAction } from "../contracts/action.js";
3
+ import { type Measurement } from "./measure.js";
4
+ import { type MountBoundaryResult } from "./mount-boundaries.js";
5
+ import { type ProcessOwnershipResult } from "./process-ownership.js";
6
+ export type ArtifactExecutionOutcome = "skipped-stale" | "failed" | "rolled-back" | "partially-applied";
7
+ export declare class ArtifactExecutionError extends Error {
8
+ readonly outcome: ArtifactExecutionOutcome;
9
+ readonly isolationPath?: string | undefined;
10
+ readonly name = "ArtifactExecutionError";
11
+ constructor(message: string, outcome: ArtifactExecutionOutcome, isolationPath?: string | undefined, options?: ErrorOptions & {
12
+ diagnosticCode?: string;
13
+ });
14
+ readonly diagnosticCode: string | undefined;
15
+ }
16
+ export type ArtifactExecutionResult = {
17
+ reclaimedBytes: number;
18
+ isolationPath: string;
19
+ };
20
+ export type ArtifactExecutorDependencies = {
21
+ id?: () => string;
22
+ inspect?: (path: string) => Promise<Stats>;
23
+ finalInspect?: (path: string) => Stats;
24
+ move?: (source: string, destination: string) => Promise<void>;
25
+ remove?: (path: string) => Promise<void>;
26
+ measure?: (path: string, options: {
27
+ maxEntries: number;
28
+ }) => Promise<Measurement>;
29
+ processProbe?: (path: string) => Promise<ProcessOwnershipResult>;
30
+ mountProbe?: (path: string) => Promise<MountBoundaryResult>;
31
+ maxEntries?: number;
32
+ authorization?: {
33
+ expiresAtMs: number;
34
+ now: () => Date;
35
+ };
36
+ };
37
+ export declare function artifactIsolationPath(action: ArtifactRemoveAction, id: string): string;
38
+ export declare function executeArtifactRemove(action: ArtifactRemoveAction, dependencies?: ArtifactExecutorDependencies): Promise<ArtifactExecutionResult>;
39
+ //# sourceMappingURL=artifact-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-executor.d.ts","sourceRoot":"","sources":["../../src/core/artifact-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAIxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,MAAM,MAAM,wBAAwB,GAChC,eAAe,GACf,QAAQ,GACR,aAAa,GACb,mBAAmB,CAAC;AAExB,qBAAa,sBAAuB,SAAQ,KAAK;IAK7C,QAAQ,CAAC,OAAO,EAAE,wBAAwB;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM;IALjC,SAAkB,IAAI,4BAA4B;IAElD,YACE,OAAO,EAAE,MAAM,EACN,OAAO,EAAE,wBAAwB,EACjC,aAAa,CAAC,EAAE,MAAM,YAAA,EAC/B,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,EAIrD;IAED,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,CAAC,EAAE,MAAM,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;IACvC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAClF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,GAAG,EAAE,MAAM,IAAI,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAEtF;AAoCD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,oBAAoB,EAC5B,YAAY,GAAE,4BAAiC,GAC9C,OAAO,CAAC,uBAAuB,CAAC,CAsQlC"}
@@ -0,0 +1,200 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { lstatSync, rmSync } from "node:fs";
3
+ import { lstat, rename } from "node:fs/promises";
4
+ import { dirname, join } from "node:path";
5
+ import { measurePath } from "./measure.js";
6
+ import { findMountBoundaries } from "./mount-boundaries.js";
7
+ import { findProcessesUsingPath } from "./process-ownership.js";
8
+ export class ArtifactExecutionError extends Error {
9
+ outcome;
10
+ isolationPath;
11
+ name = "ArtifactExecutionError";
12
+ constructor(message, outcome, isolationPath, options) {
13
+ super(message, options);
14
+ this.outcome = outcome;
15
+ this.isolationPath = isolationPath;
16
+ this.diagnosticCode = options?.diagnosticCode;
17
+ }
18
+ diagnosticCode;
19
+ }
20
+ export function artifactIsolationPath(action, id) {
21
+ return join(dirname(action.target.path), `.agentrinse-${id}.tombstone`);
22
+ }
23
+ function isMissing(error) {
24
+ return (error instanceof Error && "code" in error && error.code === "ENOENT");
25
+ }
26
+ function matchesIdentity(stats, action) {
27
+ return matchesFilesystemObject(stats, action) && stats.mtimeMs === action.target.mtimeMs;
28
+ }
29
+ function matchesFilesystemObject(stats, action) {
30
+ return (stats.isDirectory() &&
31
+ !stats.isSymbolicLink() &&
32
+ stats.dev === action.target.device &&
33
+ stats.ino === action.target.inode);
34
+ }
35
+ async function pathExists(path, inspect) {
36
+ try {
37
+ await inspect(path);
38
+ return true;
39
+ }
40
+ catch (error) {
41
+ if (isMissing(error)) {
42
+ return false;
43
+ }
44
+ throw error;
45
+ }
46
+ }
47
+ export async function executeArtifactRemove(action, dependencies = {}) {
48
+ const inspect = dependencies.inspect ?? lstat;
49
+ const move = dependencies.move ?? rename;
50
+ const measure = dependencies.measure ?? measurePath;
51
+ const processProbe = dependencies.processProbe ?? findProcessesUsingPath;
52
+ const mountProbe = dependencies.mountProbe ?? findMountBoundaries;
53
+ const isolationPath = artifactIsolationPath(action, dependencies.id?.() ?? randomUUID());
54
+ if (await pathExists(isolationPath, inspect)) {
55
+ throw new ArtifactExecutionError(`refusing to overwrite existing isolation path ${isolationPath}`, "failed", isolationPath);
56
+ }
57
+ let before;
58
+ try {
59
+ before = await inspect(action.target.path);
60
+ }
61
+ catch (error) {
62
+ throw new ArtifactExecutionError("artifact disappeared before isolation", isMissing(error) ? "skipped-stale" : "failed", isolationPath, {
63
+ cause: error,
64
+ ...(isMissing(error) ? { diagnosticCode: "ARTIFACT_IDENTITY_CHANGED" } : {}),
65
+ });
66
+ }
67
+ if (!matchesIdentity(before, action)) {
68
+ throw new ArtifactExecutionError("artifact identity changed before isolation", "skipped-stale", isolationPath, { diagnosticCode: "ARTIFACT_IDENTITY_CHANGED" });
69
+ }
70
+ if (dependencies.authorization !== undefined &&
71
+ dependencies.authorization.now().getTime() >= dependencies.authorization.expiresAtMs) {
72
+ throw new ArtifactExecutionError("cleanup plan authorization expired before artifact isolation", "skipped-stale", isolationPath, { diagnosticCode: "PLAN_EXPIRED_DURING_APPLY" });
73
+ }
74
+ try {
75
+ await move(action.target.path, isolationPath);
76
+ }
77
+ catch (error) {
78
+ throw new ArtifactExecutionError("artifact could not be atomically isolated", isMissing(error) ? "skipped-stale" : "failed", isolationPath, {
79
+ cause: error,
80
+ ...(isMissing(error) ? { diagnosticCode: "ARTIFACT_IDENTITY_CHANGED" } : {}),
81
+ });
82
+ }
83
+ let isolated;
84
+ try {
85
+ isolated = await inspect(isolationPath);
86
+ }
87
+ catch (error) {
88
+ throw new ArtifactExecutionError(`isolated artifact cannot be inspected; recovery path: ${isolationPath}`, "partially-applied", isolationPath, { cause: error });
89
+ }
90
+ if (!matchesIdentity(isolated, action)) {
91
+ await rollbackBeforeRemoval("artifact identity changed during isolation", action, isolationPath, inspect, move);
92
+ }
93
+ try {
94
+ const measurement = await measure(isolationPath, {
95
+ maxEntries: dependencies.maxEntries ?? 100_000,
96
+ });
97
+ if (measurement.truncated ||
98
+ measurement.specialEntries > 0 ||
99
+ measurement.mountBoundaries > 0 ||
100
+ measurement.bytes !== action.target.measuredBytes ||
101
+ measurement.newestMtimeMs !== action.target.newestMtimeMs ||
102
+ measurement.fingerprint !== action.target.fingerprint) {
103
+ await rollbackBeforeRemoval("artifact contents changed during isolation", action, isolationPath, inspect, move);
104
+ }
105
+ const ownership = await processProbe(isolationPath);
106
+ if (ownership.status !== "idle") {
107
+ await rollbackBeforeRemoval(ownership.status === "busy"
108
+ ? "a process acquired the artifact during isolation"
109
+ : "process ownership became unknown during isolation", action, isolationPath, inspect, move);
110
+ }
111
+ const mounts = await mountProbe(isolationPath);
112
+ if (mounts.status !== "clear") {
113
+ await rollbackBeforeRemoval(mounts.status === "blocked"
114
+ ? "artifact contains a mount boundary during isolation"
115
+ : "mount boundaries became unknown during isolation", action, isolationPath, inspect, move);
116
+ }
117
+ }
118
+ catch (error) {
119
+ if (error instanceof ArtifactExecutionError) {
120
+ throw error;
121
+ }
122
+ await rollbackBeforeRemoval("artifact could not be revalidated after isolation", action, isolationPath, inspect, move, error);
123
+ }
124
+ const finalMounts = await mountProbe(isolationPath).catch((error) => rollbackBeforeRemoval("mount boundaries could not be rechecked before removal", action, isolationPath, inspect, move, error));
125
+ if (finalMounts.status !== "clear") {
126
+ await rollbackBeforeRemoval(finalMounts.status === "blocked"
127
+ ? "artifact gained a mount boundary before removal"
128
+ : "mount boundaries became unknown before removal", action, isolationPath, inspect, move);
129
+ }
130
+ if (dependencies.authorization !== undefined &&
131
+ dependencies.authorization.now().getTime() >= dependencies.authorization.expiresAtMs) {
132
+ await rollbackBeforeRemoval("cleanup plan authorization expired during artifact isolation", action, isolationPath, inspect, move);
133
+ }
134
+ try {
135
+ const finalStats = (dependencies.finalInspect ?? lstatSync)(isolationPath);
136
+ if (!matchesFilesystemObject(finalStats, action)) {
137
+ throw new ArtifactExecutionError(`isolated artifact identity changed before removal; inspect ${isolationPath}`, "partially-applied", isolationPath);
138
+ }
139
+ if (finalStats.mtimeMs !== action.target.mtimeMs) {
140
+ await rollbackBeforeRemoval("artifact metadata changed before removal", action, isolationPath, inspect, move);
141
+ }
142
+ if (dependencies.remove === undefined) {
143
+ rmSync(isolationPath, {
144
+ recursive: true,
145
+ force: false,
146
+ maxRetries: 3,
147
+ retryDelay: 100,
148
+ });
149
+ }
150
+ else {
151
+ await dependencies.remove(isolationPath);
152
+ }
153
+ }
154
+ catch (error) {
155
+ if (error instanceof ArtifactExecutionError) {
156
+ throw error;
157
+ }
158
+ let recoveryPath = isolationPath;
159
+ try {
160
+ if (!(await pathExists(action.target.path, inspect)) &&
161
+ (await pathExists(isolationPath, inspect))) {
162
+ await move(isolationPath, action.target.path);
163
+ recoveryPath = action.target.path;
164
+ }
165
+ }
166
+ catch {
167
+ // The durable journal records the last known isolation path below.
168
+ }
169
+ throw new ArtifactExecutionError(`artifact removal failed after isolation; inspect recovery path ${recoveryPath}`, "partially-applied", recoveryPath, { cause: error });
170
+ }
171
+ try {
172
+ if ((await pathExists(action.target.path, inspect)) ||
173
+ (await pathExists(isolationPath, inspect))) {
174
+ throw new ArtifactExecutionError(`artifact removal postcondition failed; inspect ${isolationPath}`, "partially-applied", isolationPath);
175
+ }
176
+ }
177
+ catch (error) {
178
+ if (error instanceof ArtifactExecutionError) {
179
+ throw error;
180
+ }
181
+ throw new ArtifactExecutionError(`artifact removal completed but postconditions could not be verified; inspect ${isolationPath}`, "partially-applied", isolationPath, { cause: error });
182
+ }
183
+ return {
184
+ reclaimedBytes: action.target.measuredBytes,
185
+ isolationPath,
186
+ };
187
+ }
188
+ async function rollbackBeforeRemoval(reason, action, isolationPath, inspect, move, cause) {
189
+ try {
190
+ if (await pathExists(action.target.path, inspect)) {
191
+ throw new Error("original path reappeared before rollback");
192
+ }
193
+ await move(isolationPath, action.target.path);
194
+ }
195
+ catch (error) {
196
+ throw new ArtifactExecutionError(`${reason} and rollback failed; recovery path: ${isolationPath}`, "partially-applied", isolationPath, { cause: error });
197
+ }
198
+ throw new ArtifactExecutionError(`${reason}; original path restored`, "rolled-back", action.target.path, cause === undefined ? undefined : { cause });
199
+ }
200
+ //# sourceMappingURL=artifact-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-executor.js","sourceRoot":"","sources":["../../src/core/artifact-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AgentRinseConfig } from "../config/schema.js";
2
+ import type { ArtifactRemoveAction } from "../contracts/action.js";
3
+ import type { Diagnostic } from "../contracts/diagnostic.js";
4
+ import { measurePath, type Measurement } from "./measure.js";
5
+ import { type MountBoundaryResult } from "./mount-boundaries.js";
6
+ import { type ProcessOwnershipResult } from "./process-ownership.js";
7
+ export type ArtifactRevalidationResult = {
8
+ status: "valid";
9
+ measurement: Measurement;
10
+ } | {
11
+ status: "stale";
12
+ diagnostic: Diagnostic;
13
+ };
14
+ export type ArtifactRevalidationDependencies = {
15
+ cwd?: string;
16
+ now?: () => Date;
17
+ measure?: typeof measurePath;
18
+ processProbe?: (path: string) => Promise<ProcessOwnershipResult>;
19
+ mountProbe?: (path: string) => Promise<MountBoundaryResult>;
20
+ };
21
+ export declare function revalidateArtifactRemove(action: ArtifactRemoveAction, home: string, config: AgentRinseConfig, dependencies?: ArtifactRevalidationDependencies): Promise<ArtifactRevalidationResult>;
22
+ //# sourceMappingURL=artifact-revalidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-revalidation.d.ts","sourceRoot":"","sources":["../../src/core/artifact-revalidation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAA0B,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAG7F,MAAM,MAAM,0BAA0B,GAClC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,WAAW,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC;AAEhD,MAAM,MAAM,gCAAgC,GAAG;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,WAAW,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC7D,CAAC;AA0BF,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,YAAY,GAAE,gCAAqC,GAClD,OAAO,CAAC,0BAA0B,CAAC,CAgKrC"}
@@ -0,0 +1,113 @@
1
+ import { lstat, realpath } from "node:fs/promises";
2
+ import { isAbsolute, join, resolve } from "node:path";
3
+ import { measurePath } from "./measure.js";
4
+ import { findMountBoundaries } from "./mount-boundaries.js";
5
+ import { findProcessesUsingPath } from "./process-ownership.js";
6
+ import { isPathInside } from "./safety.js";
7
+ function stale(action, code, message) {
8
+ return {
9
+ status: "stale",
10
+ diagnostic: {
11
+ severity: "warning",
12
+ code,
13
+ message,
14
+ adapter: action.adapter,
15
+ resourceId: action.resourceId,
16
+ },
17
+ };
18
+ }
19
+ function isConfigured(action, config) {
20
+ const targetRoot = resolve(action.target.projectRoot);
21
+ return config.artifacts.projects.some((project) => resolve(project.root) === targetRoot && project.names.includes(action.target.name));
22
+ }
23
+ export async function revalidateArtifactRemove(action, home, config, dependencies = {}) {
24
+ const projectRoot = resolve(action.target.projectRoot);
25
+ const targetPath = resolve(action.target.path);
26
+ const expectedPath = resolve(join(projectRoot, action.target.name));
27
+ if (!isAbsolute(action.target.projectRoot) ||
28
+ !isAbsolute(action.target.path) ||
29
+ targetPath !== expectedPath ||
30
+ !isPathInside(home, projectRoot) ||
31
+ !isPathInside(projectRoot, targetPath) ||
32
+ !isConfigured(action, config)) {
33
+ return stale(action, "ARTIFACT_SCOPE_CHANGED", "artifact path is no longer within the exact configured cleanup scope");
34
+ }
35
+ const cwd = resolve(dependencies.cwd ?? process.cwd());
36
+ if (isPathInside(targetPath, cwd)) {
37
+ return stale(action, "ARTIFACT_OWNS_CWD", "artifact is the current working directory or one of its ancestors");
38
+ }
39
+ try {
40
+ const [homeStats, projectStats, targetStats] = await Promise.all([
41
+ lstat(resolve(home)),
42
+ lstat(projectRoot),
43
+ lstat(targetPath),
44
+ ]);
45
+ if (!homeStats.isDirectory() ||
46
+ homeStats.isSymbolicLink() ||
47
+ !projectStats.isDirectory() ||
48
+ projectStats.isSymbolicLink() ||
49
+ !targetStats.isDirectory() ||
50
+ targetStats.isSymbolicLink() ||
51
+ projectStats.dev !== targetStats.dev) {
52
+ return stale(action, "ARTIFACT_TYPE_CHANGED", "home, project root, and artifact must remain real directories");
53
+ }
54
+ const [homeReal, projectReal, targetReal, cwdReal] = await Promise.all([
55
+ realpath(resolve(home)),
56
+ realpath(projectRoot),
57
+ realpath(targetPath),
58
+ realpath(cwd),
59
+ ]);
60
+ if (homeReal !== resolve(home) ||
61
+ projectReal !== projectRoot ||
62
+ targetReal !== targetPath ||
63
+ !isPathInside(homeReal, projectReal) ||
64
+ targetReal !== resolve(join(projectReal, action.target.name))) {
65
+ return stale(action, "ARTIFACT_REALPATH_CHANGED", "artifact realpath no longer matches its planned project root");
66
+ }
67
+ if (isPathInside(targetReal, cwdReal)) {
68
+ return stale(action, "ARTIFACT_OWNS_CWD", "artifact is the physical current working directory or one of its ancestors");
69
+ }
70
+ if (targetStats.dev !== action.target.device ||
71
+ targetStats.ino !== action.target.inode ||
72
+ targetStats.mtimeMs !== action.target.mtimeMs) {
73
+ return stale(action, "ARTIFACT_IDENTITY_CHANGED", "artifact filesystem identity changed after planning");
74
+ }
75
+ const mounts = await (dependencies.mountProbe ?? findMountBoundaries)(targetPath);
76
+ if (mounts.status !== "clear") {
77
+ return stale(action, mounts.status === "blocked"
78
+ ? "ARTIFACT_MOUNT_BOUNDARY"
79
+ : "ARTIFACT_MOUNT_INSPECTION_UNKNOWN", mounts.status === "blocked"
80
+ ? "artifact contains a filesystem mount boundary"
81
+ : "filesystem mount boundaries could not be proven absent");
82
+ }
83
+ const measurement = await (dependencies.measure ?? measurePath)(targetPath, {
84
+ maxEntries: config.audit.maxEntries,
85
+ });
86
+ if (measurement.truncated ||
87
+ measurement.bytes !== action.target.measuredBytes ||
88
+ measurement.newestMtimeMs !== action.target.newestMtimeMs ||
89
+ measurement.fingerprint !== action.target.fingerprint ||
90
+ measurement.mountBoundaries > 0) {
91
+ return stale(action, "ARTIFACT_CONTENT_CHANGED", "artifact contents changed or could not be measured completely");
92
+ }
93
+ if (measurement.specialEntries > 0) {
94
+ return stale(action, "ARTIFACT_SPECIAL_ENTRY", "artifact contains a socket, pipe, device, or another unsupported filesystem entry");
95
+ }
96
+ const ageMs = (dependencies.now?.() ?? new Date()).getTime() - measurement.newestMtimeMs;
97
+ if (measurement.bytes < config.artifacts.minBytes ||
98
+ ageMs < config.artifacts.minAgeMinutes * 60_000) {
99
+ return stale(action, "ARTIFACT_POLICY_CHANGED", "artifact no longer meets the configured size and age retention policy");
100
+ }
101
+ const ownership = await (dependencies.processProbe ?? findProcessesUsingPath)(targetPath);
102
+ if (ownership.status !== "idle") {
103
+ return stale(action, ownership.status === "busy" ? "ARTIFACT_PROCESS_ACTIVE" : "ARTIFACT_PROCESS_UNKNOWN", ownership.status === "busy"
104
+ ? "a same-user process currently owns the artifact"
105
+ : "process ownership could not be proven idle");
106
+ }
107
+ return { status: "valid", measurement };
108
+ }
109
+ catch (error) {
110
+ return stale(action, "ARTIFACT_REVALIDATION_FAILED", error instanceof Error ? error.message : String(error));
111
+ }
112
+ }
113
+ //# sourceMappingURL=artifact-revalidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-revalidation.js","sourceRoot":"","sources":["../../src/core/artifact-revalidation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { AgentRinseConfig } from "../config/schema.js";
2
+ import type { AuditAdapter } from "../contracts/adapter.js";
3
+ import { type AuditReport } from "../contracts/report.js";
4
+ export type RunAuditOptions = {
5
+ home: string;
6
+ config: AgentRinseConfig;
7
+ adapters: AuditAdapter[];
8
+ now?: () => Date;
9
+ signal?: AbortSignal;
10
+ };
11
+ export declare function runAudit(options: RunAuditOptions): Promise<AuditReport>;
12
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/core/audit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG7E,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAwC7E"}
@@ -0,0 +1,41 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { auditReportSchema } from "../contracts/report.js";
3
+ import { assertAuditRoot } from "./safety.js";
4
+ export async function runAudit(options) {
5
+ const clock = options.now ?? (() => new Date());
6
+ const startedAt = clock();
7
+ const home = await assertAuditRoot(options.home);
8
+ const context = {
9
+ home,
10
+ now: startedAt,
11
+ auditId: randomUUID(),
12
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
13
+ };
14
+ const probes = [];
15
+ const findings = [];
16
+ const diagnostics = [];
17
+ for (const adapter of options.adapters) {
18
+ options.signal?.throwIfAborted();
19
+ const probe = await adapter.probe(context);
20
+ probes.push(probe);
21
+ diagnostics.push(...probe.diagnostics);
22
+ const collection = await adapter.collect(context, probe);
23
+ diagnostics.push(...collection.diagnostics);
24
+ for (const resource of collection.resources) {
25
+ findings.push(await adapter.classify(context, resource));
26
+ }
27
+ }
28
+ probes.sort((left, right) => left.adapter.localeCompare(right.adapter));
29
+ findings.sort((left, right) => left.resource.id.localeCompare(right.resource.id));
30
+ return auditReportSchema.parse({
31
+ schemaVersion: 1,
32
+ auditId: context.auditId,
33
+ startedAt: startedAt.toISOString(),
34
+ completedAt: clock().toISOString(),
35
+ home,
36
+ probes,
37
+ findings,
38
+ diagnostics,
39
+ });
40
+ }
41
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/core/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAU9C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB;IACrD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,OAAO,GAAiB;QAC5B,IAAI;QACJ,GAAG,EAAE,SAAS;QACd,OAAO,EAAE,UAAU,EAAE;QACrB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KACpE,CAAC;IACF,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,MAAM,QAAQ,GAAG,EAAE,CAAC;IACpB,MAAM,WAAW,GAAG,EAAE,CAAC;IAEvB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;QAEvC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzD,WAAW,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;QAC5C,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACxE,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAElF,OAAO,iBAAiB,CAAC,KAAK,CAAC;QAC7B,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,SAAS,CAAC,WAAW,EAAE;QAClC,WAAW,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE;QAClC,IAAI;QACJ,MAAM;QACN,QAAQ;QACR,WAAW;KACZ,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type JsonValue = null | boolean | number | string | JsonValue[] | {
2
+ [key: string]: JsonValue;
3
+ };
4
+ export declare function canonicalJson(value: JsonValue): string;
5
+ export declare function sha256(value: JsonValue | string): string;
6
+ export declare function sha256Json(value: unknown): string;
7
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../src/core/digest.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GACjB,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAatD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,21 @@
1
+ import { createHash } from "node:crypto";
2
+ export function canonicalJson(value) {
3
+ if (value === null || typeof value !== "object") {
4
+ return JSON.stringify(value);
5
+ }
6
+ if (Array.isArray(value)) {
7
+ return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
8
+ }
9
+ const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
10
+ return `{${entries
11
+ .map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`)
12
+ .join(",")}}`;
13
+ }
14
+ export function sha256(value) {
15
+ const input = typeof value === "string" ? value : canonicalJson(value);
16
+ return createHash("sha256").update(input).digest("hex");
17
+ }
18
+ export function sha256Json(value) {
19
+ return sha256(JSON.parse(JSON.stringify(value)));
20
+ }
21
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../../src/core/digest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAUzC,MAAM,UAAU,aAAa,CAAC,KAAgB;IAC5C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACnE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3F,OAAO,IAAI,OAAO;SACf,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;SACrE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAyB;IAC9C,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAc,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,16 @@
1
+ export type Measurement = {
2
+ bytes: number;
3
+ entries: number;
4
+ symlinksSkipped: number;
5
+ specialEntries: number;
6
+ truncated: boolean;
7
+ newestMtimeMs: number;
8
+ fingerprint: string;
9
+ mountBoundaries: number;
10
+ };
11
+ export type MeasureOptions = {
12
+ maxEntries: number;
13
+ signal?: AbortSignal;
14
+ };
15
+ export declare function measurePath(root: string, options: MeasureOptions): Promise<Measurement>;
16
+ //# sourceMappingURL=measure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../../src/core/measure.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAqF7F"}
@@ -0,0 +1,79 @@
1
+ import { createHash } from "node:crypto";
2
+ import { lstat, opendir, readlink } from "node:fs/promises";
3
+ import { join, relative } from "node:path";
4
+ export async function measurePath(root, options) {
5
+ const result = {
6
+ bytes: 0,
7
+ entries: 0,
8
+ symlinksSkipped: 0,
9
+ specialEntries: 0,
10
+ truncated: false,
11
+ newestMtimeMs: 0,
12
+ fingerprint: "",
13
+ mountBoundaries: 0,
14
+ };
15
+ const pending = [root];
16
+ const fingerprint = createHash("sha256");
17
+ let rootDevice;
18
+ while (pending.length > 0) {
19
+ options.signal?.throwIfAborted();
20
+ const path = pending.pop();
21
+ if (path === undefined) {
22
+ break;
23
+ }
24
+ if (result.entries >= options.maxEntries) {
25
+ result.truncated = true;
26
+ break;
27
+ }
28
+ const stats = await lstat(path);
29
+ rootDevice ??= stats.dev;
30
+ result.entries += 1;
31
+ result.newestMtimeMs = Math.max(result.newestMtimeMs, stats.mtimeMs);
32
+ const identity = {
33
+ path: relative(root, path),
34
+ device: stats.dev,
35
+ inode: stats.ino,
36
+ mode: stats.mode,
37
+ size: stats.size,
38
+ mtimeMs: stats.mtimeMs,
39
+ ...(path === root ? {} : { ctimeMs: stats.ctimeMs }),
40
+ type: stats.isSymbolicLink()
41
+ ? "symlink"
42
+ : stats.isDirectory()
43
+ ? "directory"
44
+ : stats.isFile()
45
+ ? "file"
46
+ : "special",
47
+ ...(stats.isSymbolicLink() ? { link: await readlink(path) } : {}),
48
+ };
49
+ fingerprint.update(`${JSON.stringify(identity)}\n`);
50
+ if (path !== root && stats.dev !== rootDevice) {
51
+ result.mountBoundaries += 1;
52
+ continue;
53
+ }
54
+ if (stats.isSymbolicLink()) {
55
+ result.symlinksSkipped += 1;
56
+ continue;
57
+ }
58
+ if (stats.isFile()) {
59
+ result.bytes += stats.size;
60
+ continue;
61
+ }
62
+ if (!stats.isDirectory()) {
63
+ result.specialEntries += 1;
64
+ continue;
65
+ }
66
+ const directory = await opendir(path);
67
+ const names = [];
68
+ for await (const entry of directory) {
69
+ names.push(entry.name);
70
+ }
71
+ names.sort((left, right) => right.localeCompare(left));
72
+ for (const name of names) {
73
+ pending.push(join(path, name));
74
+ }
75
+ }
76
+ result.fingerprint = fingerprint.digest("hex");
77
+ return result;
78
+ }
79
+ //# sourceMappingURL=measure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.js","sourceRoot":"","sources":["../../src/core/measure.ts"],"names":[],"mappings":"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"}