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,21 @@
1
+ export type MountBoundaryResult = {
2
+ status: "clear";
3
+ paths: [];
4
+ } | {
5
+ status: "blocked";
6
+ paths: string[];
7
+ } | {
8
+ status: "unknown";
9
+ paths: [];
10
+ reason: string;
11
+ };
12
+ export type MountBoundaryOptions = {
13
+ platform?: NodeJS.Platform;
14
+ linuxMountInfo?: string;
15
+ runMount?: () => Promise<{
16
+ stdout: string;
17
+ stderr: string;
18
+ }>;
19
+ };
20
+ export declare function findMountBoundaries(target: string, options?: MountBoundaryOptions): Promise<MountBoundaryResult>;
21
+ //# sourceMappingURL=mount-boundaries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount-boundaries.d.ts","sourceRoot":"","sources":["../../src/core/mount-boundaries.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,EAAE,CAAA;CAAE,GAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9D,CAAC;AAyBF,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA+C9B"}
@@ -0,0 +1,72 @@
1
+ import { execFile } from "node:child_process";
2
+ import { readFile, realpath } from "node:fs/promises";
3
+ import { resolve } from "node:path";
4
+ import { promisify } from "node:util";
5
+ import { isPathInside } from "./safety.js";
6
+ const execFileAsync = promisify(execFile);
7
+ function decodeMountPath(value) {
8
+ return value.replace(/\\([0-7]{3})/g, (_match, octal) => String.fromCharCode(Number.parseInt(octal, 8)));
9
+ }
10
+ function linuxMountPaths(input) {
11
+ return input
12
+ .split("\n")
13
+ .filter((line) => line !== "")
14
+ .map((line) => line.split(" ")[4])
15
+ .filter((path) => path !== undefined)
16
+ .map(decodeMountPath);
17
+ }
18
+ function darwinMountPaths(input) {
19
+ return input
20
+ .split("\n")
21
+ .map((line) => line.match(/ on (.+) \(/)?.[1])
22
+ .filter((path) => path !== undefined)
23
+ .map(decodeMountPath);
24
+ }
25
+ export async function findMountBoundaries(target, options = {}) {
26
+ const platform = options.platform ?? process.platform;
27
+ try {
28
+ const physicalTarget = await realpath(resolve(target));
29
+ let mountPaths;
30
+ if (platform === "linux") {
31
+ const input = options.linuxMountInfo ?? (await readFile("/proc/self/mountinfo", "utf8"));
32
+ mountPaths = linuxMountPaths(input);
33
+ }
34
+ else if (platform === "darwin") {
35
+ const result = options.runMount === undefined
36
+ ? await execFileAsync("/sbin/mount", [], {
37
+ encoding: "utf8",
38
+ maxBuffer: 4 * 1024 * 1024,
39
+ timeout: 10_000,
40
+ })
41
+ : await options.runMount();
42
+ if (result.stderr !== "") {
43
+ return {
44
+ status: "unknown",
45
+ paths: [],
46
+ reason: `mount reported an incomplete scan: ${result.stderr.trim()}`,
47
+ };
48
+ }
49
+ mountPaths = darwinMountPaths(result.stdout);
50
+ }
51
+ else {
52
+ return {
53
+ status: "unknown",
54
+ paths: [],
55
+ reason: `mount inspection is unsupported on ${platform}`,
56
+ };
57
+ }
58
+ const paths = mountPaths
59
+ .map((path) => resolve(path))
60
+ .filter((path) => isPathInside(physicalTarget, path))
61
+ .sort((left, right) => left.localeCompare(right));
62
+ return paths.length === 0 ? { status: "clear", paths: [] } : { status: "blocked", paths };
63
+ }
64
+ catch (error) {
65
+ return {
66
+ status: "unknown",
67
+ paths: [],
68
+ reason: error instanceof Error ? error.message : String(error),
69
+ };
70
+ }
71
+ }
72
+ //# sourceMappingURL=mount-boundaries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount-boundaries.js","sourceRoot":"","sources":["../../src/core/mount-boundaries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { AgentRinseConfig } from "../config/schema.js";
2
+ import { type CleanupPlan } from "../contracts/plan.js";
3
+ export type PlanVerificationCode = "PLAN_INVALID" | "PLAN_TAMPERED" | "PLAN_CONFIG_CHANGED" | "PLAN_EXPIRED" | "PLAN_TIME_INVALID";
4
+ export declare class PlanVerificationError extends Error {
5
+ readonly code: PlanVerificationCode;
6
+ readonly name = "PlanVerificationError";
7
+ constructor(code: PlanVerificationCode, message: string, options?: ErrorOptions);
8
+ }
9
+ export declare function verifyCleanupPlan(input: unknown, config: AgentRinseConfig, now?: Date): CleanupPlan;
10
+ //# sourceMappingURL=plan-verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-verification.d.ts","sourceRoot":"","sources":["../../src/core/plan-verification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAI3E,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,eAAe,GACf,qBAAqB,GACrB,cAAc,GACd,mBAAmB,CAAC;AAExB,qBAAa,qBAAsB,SAAQ,KAAK;IAI5C,QAAQ,CAAC,IAAI,EAAE,oBAAoB;IAHrC,SAAkB,IAAI,2BAA2B;IAEjD,YACW,IAAI,EAAE,oBAAoB,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,EAGvB;CACF;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,gBAAgB,EACxB,GAAG,OAAa,GACf,WAAW,CAqDb"}
@@ -0,0 +1,42 @@
1
+ import { cleanupPlanSchema } from "../contracts/plan.js";
2
+ import { sha256Json } from "./digest.js";
3
+ import { cleanupPlanId } from "./plan.js";
4
+ export class PlanVerificationError extends Error {
5
+ code;
6
+ name = "PlanVerificationError";
7
+ constructor(code, message, options) {
8
+ super(message, options);
9
+ this.code = code;
10
+ }
11
+ }
12
+ export function verifyCleanupPlan(input, config, now = new Date()) {
13
+ const parsed = cleanupPlanSchema.safeParse(input);
14
+ if (!parsed.success) {
15
+ throw new PlanVerificationError("PLAN_INVALID", "cleanup plan does not match the supported schema", { cause: parsed.error });
16
+ }
17
+ const plan = parsed.data;
18
+ const { planId, ...content } = plan;
19
+ if (cleanupPlanId(content) !== planId) {
20
+ throw new PlanVerificationError("PLAN_TAMPERED", "cleanup plan content does not match its planId");
21
+ }
22
+ if (sha256Json(config) !== plan.configDigest) {
23
+ throw new PlanVerificationError("PLAN_CONFIG_CHANGED", "configuration changed after this cleanup plan was created");
24
+ }
25
+ const createdAt = Date.parse(plan.createdAt);
26
+ const expiresAt = Date.parse(plan.expiresAt);
27
+ if (!Number.isFinite(createdAt) ||
28
+ !Number.isFinite(expiresAt) ||
29
+ createdAt > expiresAt ||
30
+ createdAt > now.getTime()) {
31
+ throw new PlanVerificationError("PLAN_TIME_INVALID", "cleanup plan has an invalid authorization window");
32
+ }
33
+ const maximumLifetime = config.plan.ttlMinutes * 60_000;
34
+ if (expiresAt - createdAt > maximumLifetime) {
35
+ throw new PlanVerificationError("PLAN_TIME_INVALID", "cleanup plan exceeds the configured authorization lifetime");
36
+ }
37
+ if (now.getTime() >= expiresAt) {
38
+ throw new PlanVerificationError("PLAN_EXPIRED", `cleanup plan expired at ${plan.expiresAt}`);
39
+ }
40
+ return plan;
41
+ }
42
+ //# sourceMappingURL=plan-verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-verification.js","sourceRoot":"","sources":["../../src/core/plan-verification.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAS1C,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAInC,IAAI;IAHG,IAAI,GAAG,uBAAuB,CAAC;IAEjD,YACW,IAA0B,EACnC,OAAe,EACf,OAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBAJf,IAAI;IAKf,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAc,EACd,MAAwB,EACxB,GAAG,GAAG,IAAI,IAAI,EAAE;IAEhB,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,qBAAqB,CAC7B,cAAc,EACd,kDAAkD,EAClD,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CACxB,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;IACpC,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC;QACtC,MAAM,IAAI,qBAAqB,CAC7B,eAAe,EACf,gDAAgD,CACjD,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;QAC7C,MAAM,IAAI,qBAAqB,CAC7B,qBAAqB,EACrB,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,IACE,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,SAAS,GAAG,SAAS;QACrB,SAAS,GAAG,GAAG,CAAC,OAAO,EAAE,EACzB,CAAC;QACD,MAAM,IAAI,qBAAqB,CAC7B,mBAAmB,EACnB,kDAAkD,CACnD,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;IACxD,IAAI,SAAS,GAAG,SAAS,GAAG,eAAe,EAAE,CAAC;QAC5C,MAAM,IAAI,qBAAqB,CAC7B,mBAAmB,EACnB,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,qBAAqB,CAAC,cAAc,EAAE,2BAA2B,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { AgentRinseConfig } from "../config/schema.js";
2
+ import { type CleanupPlan } from "../contracts/plan.js";
3
+ import type { AuditReport } from "../contracts/report.js";
4
+ export declare function cleanupPlanId(plan: Omit<CleanupPlan, "planId">): string;
5
+ export declare function createCleanupPlan(audit: AuditReport, config: AgentRinseConfig, now?: Date): CleanupPlan;
6
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/core/plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAU1D,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,MAAM,CAEvE;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,gBAAgB,EACxB,GAAG,OAAa,GACf,WAAW,CA4Bb"}
@@ -0,0 +1,40 @@
1
+ import { cleanupPlanSchema } from "../contracts/plan.js";
2
+ import { sha256Json } from "./digest.js";
3
+ const RISK_ORDER = {
4
+ safe: 0,
5
+ recoverable: 1,
6
+ destructive: 2,
7
+ experimental: 3,
8
+ };
9
+ export function cleanupPlanId(plan) {
10
+ return sha256Json(plan);
11
+ }
12
+ export function createCleanupPlan(audit, config, now = new Date()) {
13
+ const createdAt = now.toISOString();
14
+ const expiresAt = new Date(now.getTime() + config.plan.ttlMinutes * 60_000).toISOString();
15
+ const configDigest = sha256Json(config);
16
+ const auditDigest = sha256Json(audit);
17
+ const actions = audit.findings
18
+ .filter((finding) => finding.state === "eligible")
19
+ .flatMap((finding) => finding.candidateActions)
20
+ .filter((action) => RISK_ORDER[action.risk] <= RISK_ORDER[config.plan.maxRisk])
21
+ .sort((left, right) => left.actionId.localeCompare(right.actionId));
22
+ const planWithoutId = {
23
+ schemaVersion: 1,
24
+ auditId: audit.auditId,
25
+ home: audit.home,
26
+ createdAt,
27
+ expiresAt,
28
+ policyVersion: 1,
29
+ riskCeiling: config.plan.maxRisk,
30
+ configDigest,
31
+ auditDigest,
32
+ actions,
33
+ expectedReclaimBytes: actions.reduce((total, action) => total + action.expectedReclaimBytes, 0),
34
+ };
35
+ return cleanupPlanSchema.parse({
36
+ ...planWithoutId,
37
+ planId: cleanupPlanId(planWithoutId),
38
+ });
39
+ }
40
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/core/plan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,GAA+B;IAC7C,IAAI,EAAE,CAAC;IACP,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;IACd,YAAY,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAAiC;IAC7D,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAkB,EAClB,MAAwB,EACxB,GAAG,GAAG,IAAI,IAAI,EAAE;IAEhB,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1F,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ;SAC3B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,UAAU,CAAC;SACjD,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC;SAC9C,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SAC9E,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG;QACpB,aAAa,EAAE,CAAU;QACzB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,SAAS;QACT,SAAS;QACT,aAAa,EAAE,CAAU;QACzB,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;QAChC,YAAY;QACZ,WAAW;QACX,OAAO;QACP,oBAAoB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;KAChG,CAAC;IAEF,OAAO,iBAAiB,CAAC,KAAK,CAAC;QAC7B,GAAG,aAAa;QAChB,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC;KACrC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,27 @@
1
+ export type ProcessPathMatch = {
2
+ pid: number;
3
+ source: "cwd" | "fd";
4
+ path: string;
5
+ };
6
+ export type ProcessOwnershipResult = {
7
+ status: "idle";
8
+ matches: [];
9
+ } | {
10
+ status: "busy";
11
+ matches: ProcessPathMatch[];
12
+ } | {
13
+ status: "unknown";
14
+ matches: ProcessPathMatch[];
15
+ reason: string;
16
+ };
17
+ export type ProcessOwnershipOptions = {
18
+ platform?: NodeJS.Platform;
19
+ procRoot?: string;
20
+ uid?: number;
21
+ runLsof?: (target: string) => Promise<{
22
+ stdout: string;
23
+ stderr: string;
24
+ }>;
25
+ };
26
+ export declare function findProcessesUsingPath(target: string, options?: ProcessOwnershipOptions): Promise<ProcessOwnershipResult>;
27
+ //# sourceMappingURL=process-ownership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-ownership.d.ts","sourceRoot":"","sources":["../../src/core/process-ownership.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,EAAE,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAAE,GAC/C;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3E,CAAC;AAqJF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAajC"}
@@ -0,0 +1,140 @@
1
+ import { execFile } from "node:child_process";
2
+ import { readdir, readFile, readlink } from "node:fs/promises";
3
+ import { isAbsolute, relative, resolve } from "node:path";
4
+ import { promisify } from "node:util";
5
+ const execFileAsync = promisify(execFile);
6
+ function isInside(root, candidate) {
7
+ const result = relative(resolve(root), resolve(candidate));
8
+ return result === "" || (!result.startsWith("..") && !isAbsolute(result));
9
+ }
10
+ function cleanProcLink(value) {
11
+ return value.endsWith(" (deleted)") ? value.slice(0, -" (deleted)".length) : value;
12
+ }
13
+ function isGone(error) {
14
+ return (error instanceof Error &&
15
+ "code" in error &&
16
+ ["ENOENT", "ESRCH"].includes(error.code ?? ""));
17
+ }
18
+ async function readProcessUid(statusPath) {
19
+ const status = await readFile(statusPath, "utf8");
20
+ const uidLine = status.split("\n").find((line) => line.startsWith("Uid:"));
21
+ const uid = uidLine?.split(/\s+/)[1];
22
+ return uid === undefined ? undefined : Number.parseInt(uid, 10);
23
+ }
24
+ async function inspectLinux(target, options) {
25
+ const procRoot = options.procRoot ?? "/proc";
26
+ const uid = options.uid ?? process.getuid?.();
27
+ if (uid === undefined) {
28
+ return {
29
+ status: "unknown",
30
+ matches: [],
31
+ reason: "current user identity is unavailable",
32
+ };
33
+ }
34
+ const matches = [];
35
+ let incomplete = false;
36
+ const entries = await readdir(procRoot, { withFileTypes: true });
37
+ for (const entry of entries) {
38
+ if (!entry.isDirectory() || !/^\d+$/.test(entry.name)) {
39
+ continue;
40
+ }
41
+ const pid = Number.parseInt(entry.name, 10);
42
+ const processRoot = resolve(procRoot, entry.name);
43
+ try {
44
+ const processUid = await readProcessUid(resolve(processRoot, "status"));
45
+ if (processUid !== uid) {
46
+ continue;
47
+ }
48
+ const cwd = cleanProcLink(await readlink(resolve(processRoot, "cwd")));
49
+ if (isInside(target, cwd)) {
50
+ matches.push({ pid, source: "cwd", path: cwd });
51
+ }
52
+ const descriptors = await readdir(resolve(processRoot, "fd"));
53
+ for (const descriptor of descriptors) {
54
+ try {
55
+ const path = cleanProcLink(await readlink(resolve(processRoot, "fd", descriptor)));
56
+ if (isAbsolute(path) && isInside(target, path)) {
57
+ matches.push({ pid, source: "fd", path });
58
+ }
59
+ }
60
+ catch (error) {
61
+ if (!isGone(error)) {
62
+ incomplete = true;
63
+ }
64
+ }
65
+ }
66
+ }
67
+ catch (error) {
68
+ if (!isGone(error)) {
69
+ incomplete = true;
70
+ }
71
+ }
72
+ }
73
+ if (matches.length > 0) {
74
+ return { status: "busy", matches };
75
+ }
76
+ if (incomplete) {
77
+ return inspectWithLsof(target, options);
78
+ }
79
+ return { status: "idle", matches: [] };
80
+ }
81
+ async function inspectWithLsof(target, options) {
82
+ try {
83
+ const result = options.runLsof === undefined
84
+ ? await execFileAsync("lsof", ["-nP", "+D", target, "-Fpcfn"], {
85
+ encoding: "utf8",
86
+ maxBuffer: 4 * 1024 * 1024,
87
+ timeout: 10_000,
88
+ })
89
+ : await options.runLsof(target);
90
+ if (result.stderr !== "") {
91
+ return {
92
+ status: "unknown",
93
+ matches: [],
94
+ reason: `lsof reported an incomplete scan: ${result.stderr.trim()}`,
95
+ };
96
+ }
97
+ const matches = [];
98
+ let pid;
99
+ for (const line of result.stdout.split("\n")) {
100
+ if (line.startsWith("p")) {
101
+ pid = Number.parseInt(line.slice(1), 10);
102
+ }
103
+ else if (line.startsWith("n") && pid !== undefined) {
104
+ const path = line.slice(1);
105
+ if (isInside(target, path)) {
106
+ matches.push({ pid, source: "fd", path });
107
+ }
108
+ }
109
+ }
110
+ return matches.length > 0 ? { status: "busy", matches } : { status: "idle", matches: [] };
111
+ }
112
+ catch (error) {
113
+ const commandError = error;
114
+ if (Number(commandError.code) === 1 &&
115
+ (commandError.stdout ?? "") === "" &&
116
+ (commandError.stderr ?? "") === "") {
117
+ return { status: "idle", matches: [] };
118
+ }
119
+ return {
120
+ status: "unknown",
121
+ matches: [],
122
+ reason: error instanceof Error ? error.message : String(error),
123
+ };
124
+ }
125
+ }
126
+ export async function findProcessesUsingPath(target, options = {}) {
127
+ const platform = options.platform ?? process.platform;
128
+ if (platform === "linux") {
129
+ return inspectLinux(resolve(target), options);
130
+ }
131
+ if (platform === "darwin") {
132
+ return inspectWithLsof(resolve(target), options);
133
+ }
134
+ return {
135
+ status: "unknown",
136
+ matches: [],
137
+ reason: `process ownership is unsupported on ${platform}`,
138
+ };
139
+ }
140
+ //# sourceMappingURL=process-ownership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-ownership.js","sourceRoot":"","sources":["../../src/core/process-ownership.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare class UnsafeAuditRootError extends Error {
2
+ readonly name = "UnsafeAuditRootError";
3
+ }
4
+ export declare function isPathInside(root: string, candidate: string): boolean;
5
+ export declare function resolvePhysicalPath(candidate: string): Promise<string>;
6
+ export declare function assertAuditRoot(candidate: string, realHome?: string): Promise<string>;
7
+ //# sourceMappingURL=safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/core/safety.ts"],"names":[],"mappings":"AAIA,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAkB,IAAI,0BAA0B;CACjD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAGrE;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B5E;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB9F"}
@@ -0,0 +1,50 @@
1
+ import { homedir } from "node:os";
2
+ import { realpath } from "node:fs/promises";
3
+ import { basename, dirname, isAbsolute, parse, relative, resolve } from "node:path";
4
+ export class UnsafeAuditRootError extends Error {
5
+ name = "UnsafeAuditRootError";
6
+ }
7
+ export function isPathInside(root, candidate) {
8
+ const result = relative(resolve(root), resolve(candidate));
9
+ return result === "" || (!result.startsWith("..") && !isAbsolute(result));
10
+ }
11
+ export async function resolvePhysicalPath(candidate) {
12
+ let cursor = resolve(candidate);
13
+ const missing = [];
14
+ while (true) {
15
+ try {
16
+ const existing = await realpath(cursor);
17
+ return resolve(existing, ...missing.reverse());
18
+ }
19
+ catch (error) {
20
+ if (!(error instanceof Error &&
21
+ "code" in error &&
22
+ error.code === "ENOENT")) {
23
+ throw error;
24
+ }
25
+ const parent = dirname(cursor);
26
+ if (parent === cursor) {
27
+ throw error;
28
+ }
29
+ missing.push(basename(cursor));
30
+ cursor = parent;
31
+ }
32
+ }
33
+ }
34
+ export async function assertAuditRoot(candidate, realHome = homedir()) {
35
+ if (!isAbsolute(candidate)) {
36
+ throw new UnsafeAuditRootError("audit home must be an absolute path");
37
+ }
38
+ const [resolvedCandidate, resolvedHome] = await Promise.all([
39
+ realpath(resolve(candidate)),
40
+ realpath(resolve(realHome)),
41
+ ]);
42
+ if (resolvedCandidate === parse(resolvedCandidate).root) {
43
+ throw new UnsafeAuditRootError("refusing to use the filesystem root");
44
+ }
45
+ if (resolvedCandidate !== resolvedHome && isPathInside(resolvedCandidate, resolvedHome)) {
46
+ throw new UnsafeAuditRootError("refusing to use an ancestor of the real home directory");
47
+ }
48
+ return resolvedCandidate;
49
+ }
50
+ //# sourceMappingURL=safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.js","sourceRoot":"","sources":["../../src/core/safety.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpF,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC3B,IAAI,GAAG,sBAAsB,CAAC;CACjD;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,SAAiB;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3D,OAAO,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,SAAiB;IACzD,IAAI,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxC,OAAO,OAAO,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IACE,CAAC,CACC,KAAK,YAAY,KAAK;gBACtB,MAAM,IAAI,KAAK;gBACd,KAA+B,CAAC,IAAI,KAAK,QAAQ,CACnD,EACD,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,MAAM,KAAK,CAAC;YACd,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/B,MAAM,GAAG,MAAM,CAAC;QAClB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB,EAAE,QAAQ,GAAG,OAAO,EAAE;IAC3E,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,oBAAoB,CAAC,qCAAqC,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1D,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5B,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KAC5B,CAAC,CAAC;IAEH,IAAI,iBAAiB,KAAK,KAAK,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC;QACxD,MAAM,IAAI,oBAAoB,CAAC,qCAAqC,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,iBAAiB,KAAK,YAAY,IAAI,YAAY,CAAC,iBAAiB,EAAE,YAAY,CAAC,EAAE,CAAC;QACxF,MAAM,IAAI,oBAAoB,CAAC,wDAAwD,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { agentRinseConfigSchema, adapterIdSchema, type AdapterId, type AgentRinseConfig, } from "./config/schema.js";
2
+ export { artifactNameSchema, artifactRemoveActionSchema, pathIdentitySchema, plannedActionSchema, type ArtifactName, type ArtifactRemoveAction, type PathIdentity, type PlannedAction, } from "./contracts/action.js";
3
+ export { cleanupPlanSchema, type CleanupPlan } from "./contracts/plan.js";
4
+ export { auditReportSchema, type AdapterProbe, type AuditReport } from "./contracts/report.js";
5
+ export { actionExecutionSchema, cleanupRunSchema, type ActionExecution, type CleanupRun, } from "./contracts/run.js";
6
+ export { runAudit, type RunAuditOptions } from "./core/audit.js";
7
+ export { applyCleanupPlan, type ApplyCleanupPlanOptions, type ApplyResult } from "./core/apply.js";
8
+ export { createCleanupPlan } from "./core/plan.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { agentRinseConfigSchema, adapterIdSchema, } from "./config/schema.js";
2
+ export { artifactNameSchema, artifactRemoveActionSchema, pathIdentitySchema, plannedActionSchema, } from "./contracts/action.js";
3
+ export { cleanupPlanSchema } from "./contracts/plan.js";
4
+ export { auditReportSchema } from "./contracts/report.js";
5
+ export { actionExecutionSchema, cleanupRunSchema, } from "./contracts/run.js";
6
+ export { runAudit } from "./core/audit.js";
7
+ export { applyCleanupPlan } from "./core/apply.js";
8
+ export { createCleanupPlan } from "./core/plan.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,eAAe,GAGhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,GAKpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAuC,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GAGjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAwB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAkD,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ export declare function buildProgram(): Command;
3
+ export declare function main(argv?: string[]): Promise<void>;
4
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,YAAY,IAAI,OAAO,CA6DtC;AAED,wBAAsB,IAAI,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7D"}
package/dist/main.js ADDED
@@ -0,0 +1,59 @@
1
+ import { Command } from "commander";
2
+ import { executeAuditCommand } from "./commands/audit.js";
3
+ import { renderAdapters } from "./commands/adapters.js";
4
+ import { executeApplyCommand } from "./commands/apply.js";
5
+ import { executePlanCommand } from "./commands/plan.js";
6
+ import { VERSION } from "./version.js";
7
+ export function buildProgram() {
8
+ const program = new Command()
9
+ .name("agentrinse")
10
+ .description("Safe cleanup for agentic development.")
11
+ .version(VERSION);
12
+ program
13
+ .command("audit")
14
+ .description("Inventory a home without mutating it.")
15
+ .requiredOption("--home <path>", "home directory to audit")
16
+ .option("--config <path>", "explicit JSON config")
17
+ .option("--json", "emit the versioned JSON report", false)
18
+ .option("--output <path>", "write the JSON report atomically")
19
+ .action(async (options) => {
20
+ const result = await executeAuditCommand(options);
21
+ process.stdout.write(result.output);
22
+ });
23
+ program
24
+ .command("plan")
25
+ .description("Create a dry-run cleanup plan from a saved audit.")
26
+ .requiredOption("--audit <path>", "saved audit JSON")
27
+ .option("--config <path>", "explicit JSON config")
28
+ .option("--output <path>", "write the plan atomically")
29
+ .action(async (options) => {
30
+ const result = await executePlanCommand(options);
31
+ process.stdout.write(result.output);
32
+ });
33
+ program
34
+ .command("apply")
35
+ .description("Apply an authorized cleanup plan after revalidation.")
36
+ .requiredOption("--plan <path>", "saved cleanup plan JSON")
37
+ .option("--config <path>", "same explicit JSON config used to create the plan")
38
+ .option("--state-dir <path>", "override the AgentRinse state directory")
39
+ .option("--yes", "authorize non-interactive apply", false)
40
+ .option("--json", "emit the versioned run journal", false)
41
+ .action(async (options) => {
42
+ const result = await executeApplyCommand(options);
43
+ process.stdout.write(result.output);
44
+ if (["failed", "partial"].includes(result.run.status)) {
45
+ process.exitCode = 2;
46
+ }
47
+ });
48
+ program
49
+ .command("adapters")
50
+ .description("List adapter maturity and ownership.")
51
+ .action(() => {
52
+ process.stdout.write(renderAdapters());
53
+ });
54
+ return program;
55
+ }
56
+ export async function main(argv = process.argv) {
57
+ await buildProgram().parseAsync(argv);
58
+ }
59
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AuditReport } from "./contracts/report.js";
2
+ export declare function formatBytes(bytes: number): string;
3
+ export declare function renderAudit(report: AuditReport): string;
4
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIzD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWjD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAkCvD"}
package/dist/output.js ADDED
@@ -0,0 +1,35 @@
1
+ const UNITS = ["B", "KiB", "MiB", "GiB", "TiB"];
2
+ export function formatBytes(bytes) {
3
+ let value = bytes;
4
+ let unit = 0;
5
+ while (value >= 1024 && unit < UNITS.length - 1) {
6
+ value /= 1024;
7
+ unit += 1;
8
+ }
9
+ const precision = unit === 0 || value >= 10 ? 0 : 1;
10
+ return `${value.toFixed(precision)} ${UNITS[unit]}`;
11
+ }
12
+ export function renderAudit(report) {
13
+ const actionCount = report.findings.reduce((total, finding) => total + finding.candidateActions.length, 0);
14
+ const lines = [
15
+ "AgentRinse audit",
16
+ "",
17
+ `Home: ${report.home}`,
18
+ `Adapters: ${report.probes.length}`,
19
+ `Resources: ${report.findings.length}`,
20
+ `Eligible actions: ${actionCount}`,
21
+ "",
22
+ ];
23
+ for (const probe of report.probes) {
24
+ lines.push(`${probe.adapter.padEnd(10)} ${probe.status.padEnd(10)} ${probe.detail}`);
25
+ }
26
+ for (const finding of report.findings) {
27
+ const bytes = finding.measuredBytes === undefined ? "unknown" : formatBytes(finding.measuredBytes);
28
+ lines.push(`${finding.state.padEnd(10)} ${bytes.padStart(10)} ${finding.resource.adapter}/${finding.resource.displayName}`);
29
+ }
30
+ lines.push("", actionCount === 0
31
+ ? "No cleanup actions are eligible."
32
+ : "Save this audit and create a plan before applying.");
33
+ return `${lines.join("\n")}\n`;
34
+ }
35
+ //# sourceMappingURL=output.js.map