@jeger-ai/opengantry 3.6.0 → 3.7.1

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 (53) hide show
  1. package/README.md +21 -0
  2. package/dist/cli/cage-bin.d.ts +3 -0
  3. package/dist/cli/cage-bin.d.ts.map +1 -0
  4. package/dist/cli/cage-bin.js +11 -0
  5. package/dist/cli/cage-bin.js.map +1 -0
  6. package/dist/cli/commands/cage.d.ts +15 -0
  7. package/dist/cli/commands/cage.d.ts.map +1 -0
  8. package/dist/cli/commands/cage.js +71 -0
  9. package/dist/cli/commands/cage.js.map +1 -0
  10. package/dist/cli/lib/cage/cage-process.d.ts +18 -0
  11. package/dist/cli/lib/cage/cage-process.d.ts.map +1 -0
  12. package/dist/cli/lib/cage/cage-process.js +39 -0
  13. package/dist/cli/lib/cage/cage-process.js.map +1 -0
  14. package/dist/cli/lib/cage/cage-push-guard.d.ts +23 -0
  15. package/dist/cli/lib/cage/cage-push-guard.d.ts.map +1 -0
  16. package/dist/cli/lib/cage/cage-push-guard.js +116 -0
  17. package/dist/cli/lib/cage/cage-push-guard.js.map +1 -0
  18. package/dist/cli/lib/cage/cage-report.d.ts +71 -0
  19. package/dist/cli/lib/cage/cage-report.d.ts.map +1 -0
  20. package/dist/cli/lib/cage/cage-report.js +118 -0
  21. package/dist/cli/lib/cage/cage-report.js.map +1 -0
  22. package/dist/cli/lib/cage/cage-revert.d.ts +18 -0
  23. package/dist/cli/lib/cage/cage-revert.d.ts.map +1 -0
  24. package/dist/cli/lib/cage/cage-revert.js +56 -0
  25. package/dist/cli/lib/cage/cage-revert.js.map +1 -0
  26. package/dist/cli/lib/cage/cage-rules.d.ts +24 -0
  27. package/dist/cli/lib/cage/cage-rules.d.ts.map +1 -0
  28. package/dist/cli/lib/cage/cage-rules.js +94 -0
  29. package/dist/cli/lib/cage/cage-rules.js.map +1 -0
  30. package/dist/cli/lib/cage/cage-run.d.ts +34 -0
  31. package/dist/cli/lib/cage/cage-run.d.ts.map +1 -0
  32. package/dist/cli/lib/cage/cage-run.js +107 -0
  33. package/dist/cli/lib/cage/cage-run.js.map +1 -0
  34. package/dist/cli/lib/cage/cage-snapshot.d.ts +36 -0
  35. package/dist/cli/lib/cage/cage-snapshot.d.ts.map +1 -0
  36. package/dist/cli/lib/cage/cage-snapshot.js +128 -0
  37. package/dist/cli/lib/cage/cage-snapshot.js.map +1 -0
  38. package/dist/cli/lib/cage/cage-watch.d.ts +36 -0
  39. package/dist/cli/lib/cage/cage-watch.d.ts.map +1 -0
  40. package/dist/cli/lib/cage/cage-watch.js +92 -0
  41. package/dist/cli/lib/cage/cage-watch.js.map +1 -0
  42. package/dist/cli/lib/version.gen.d.ts +1 -1
  43. package/dist/cli/lib/version.gen.js +1 -1
  44. package/dist/cli/program-cage.d.ts +5 -0
  45. package/dist/cli/program-cage.d.ts.map +1 -0
  46. package/dist/cli/program-cage.js +29 -0
  47. package/dist/cli/program-cage.js.map +1 -0
  48. package/dist/cli/program.d.ts.map +1 -1
  49. package/dist/cli/program.js +2 -0
  50. package/dist/cli/program.js.map +1 -1
  51. package/package.json +3 -2
  52. package/templates/.gitagent/foreman/SUBSTRATE.version.json +1 -1
  53. package/templates/integrations/compatibility.json +1 -1
@@ -0,0 +1,56 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ function errnoCode(err) {
5
+ const code = err?.code;
6
+ return typeof code === "string" ? code : "ERROR";
7
+ }
8
+ /** Write to a sibling temp file and rename over the target so a failed restore never truncates it. */
9
+ function restoreFile(abs, entry, bytes) {
10
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
11
+ const tmp = `${abs}.gantry-cage-${String(process.pid)}-${crypto.randomBytes(4).toString("hex")}`;
12
+ try {
13
+ fs.writeFileSync(tmp, bytes, { mode: entry.fileMode });
14
+ fs.chmodSync(tmp, entry.fileMode);
15
+ fs.renameSync(tmp, abs);
16
+ }
17
+ catch (err) {
18
+ fs.rmSync(tmp, { force: true });
19
+ throw err;
20
+ }
21
+ }
22
+ function restoreSymlink(abs, target) {
23
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
24
+ fs.rmSync(abs, { force: true });
25
+ fs.symlinkSync(target, abs);
26
+ }
27
+ function revertChange(change) {
28
+ if (change.kind === "added") {
29
+ fs.rmSync(change.abs, { force: true });
30
+ return "removed";
31
+ }
32
+ const before = change.before;
33
+ if (before.type === "symlink") {
34
+ restoreSymlink(change.abs, before.linkTarget);
35
+ return "reverted";
36
+ }
37
+ if (!before.bytes)
38
+ return "detect_only";
39
+ restoreFile(change.abs, before, before.bytes);
40
+ return "reverted";
41
+ }
42
+ export function resolveCageChanges(changes, opts) {
43
+ return changes.map((change) => {
44
+ if (change.mode === "report")
45
+ return { ...change, outcome: "kept", errorCode: null };
46
+ if (opts.reportOnly)
47
+ return { ...change, outcome: "reported", errorCode: null };
48
+ try {
49
+ return { ...change, outcome: revertChange(change), errorCode: null };
50
+ }
51
+ catch (err) {
52
+ return { ...change, outcome: "revert_failed", errorCode: errnoCode(err) };
53
+ }
54
+ });
55
+ }
56
+ //# sourceMappingURL=cage-revert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-revert.js","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-revert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Zero-config protected set for `gantry cage`. Paths are matched without any
3
+ * manifest; manifest `forbidden_zones` are unioned in when the repo has one.
4
+ */
5
+ export type CageRuleId = "ci_config" | "secrets" | "git_control" | "lockfile" | "manifest_forbidden_zone";
6
+ /** `revert`: restore baseline bytes and fail. `report`: list the change but keep it. */
7
+ export type CageRuleMode = "revert" | "report";
8
+ export declare const CAGE_RULE_MODES: Readonly<Record<CageRuleId, CageRuleMode>>;
9
+ /** Directory names skipped by the whole-tree basename scan (dependency and VCS bulk). */
10
+ export declare const CAGE_SCAN_SKIP_DIRS: ReadonlySet<string>;
11
+ /** A file or directory tree protected by absolute path. */
12
+ export interface CageTarget {
13
+ abs: string;
14
+ rule: CageRuleId;
15
+ }
16
+ export interface CagePlan {
17
+ root: string;
18
+ targets: CageTarget[];
19
+ manifestZoneCount: number;
20
+ }
21
+ /** Rule for a file found by the whole-tree scan, keyed on its basename. */
22
+ export declare function cageBasenameRule(name: string): CageRuleId | null;
23
+ export declare function buildCagePlan(root: string): CagePlan;
24
+ //# sourceMappingURL=cage-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-rules.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-rules.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,yBAAyB,CAAC;AAE1G,wFAAwF;AACxF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/C,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAOtE,CAAC;AAqBF,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAMlD,CAAC;AAEH,2DAA2D;AAC3D,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAIhE;AAwCD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAQpD"}
@@ -0,0 +1,94 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { REL_MANIFEST } from "../constants.js";
4
+ import { gitRun } from "../git/git.js";
5
+ import { loadManifest } from "../manifest.js";
6
+ export const CAGE_RULE_MODES = {
7
+ ci_config: "revert",
8
+ secrets: "revert",
9
+ git_control: "revert",
10
+ // Package managers legitimately rewrite lockfiles; surface the change, never undo it.
11
+ lockfile: "report",
12
+ manifest_forbidden_zone: "revert",
13
+ };
14
+ /** Root-anchored CI paths (files or directory trees). */
15
+ const CI_CONFIG_PATHS = [".github/workflows", ".gitlab-ci.yml", ".circleci", "azure-pipelines.yml"];
16
+ const LOCKFILE_NAMES = new Set([
17
+ "package-lock.json",
18
+ "npm-shrinkwrap.json",
19
+ "pnpm-lock.yaml",
20
+ "yarn.lock",
21
+ "bun.lock",
22
+ "bun.lockb",
23
+ "Cargo.lock",
24
+ "poetry.lock",
25
+ "Pipfile.lock",
26
+ "uv.lock",
27
+ "go.sum",
28
+ "Gemfile.lock",
29
+ "composer.lock",
30
+ ]);
31
+ /** Directory names skipped by the whole-tree basename scan (dependency and VCS bulk). */
32
+ export const CAGE_SCAN_SKIP_DIRS = new Set([
33
+ "node_modules",
34
+ ".git",
35
+ ".venv",
36
+ "venv",
37
+ "__pycache__",
38
+ ]);
39
+ /** Rule for a file found by the whole-tree scan, keyed on its basename. */
40
+ export function cageBasenameRule(name) {
41
+ if (name === ".env" || (name.startsWith(".env.") && name !== ".env.example"))
42
+ return "secrets";
43
+ if (LOCKFILE_NAMES.has(name))
44
+ return "lockfile";
45
+ return null;
46
+ }
47
+ function rootJoin(root, posixRel) {
48
+ return path.join(root, ...posixRel.split("/"));
49
+ }
50
+ function gitPathAbs(root, args) {
51
+ const r = gitRun(root, ["rev-parse", "--path-format=absolute", ...args]);
52
+ const out = r.stdout.trim();
53
+ return r.ok && out ? out : null;
54
+ }
55
+ /** `.git/config`, `.git/hooks/`, and the active `core.hooksPath` when it differs. */
56
+ function gitControlTargets(root) {
57
+ const common = gitPathAbs(root, ["--git-common-dir"]);
58
+ if (!common)
59
+ return [];
60
+ const out = [path.join(common, "config"), path.join(common, "hooks")];
61
+ const activeHooks = gitPathAbs(root, ["--git-path", "hooks"]);
62
+ if (activeHooks)
63
+ out.push(activeHooks);
64
+ return [...new Set(out.map((p) => path.resolve(p)))];
65
+ }
66
+ /**
67
+ * Union of every skill's `forbidden_zones` when a manifest exists. An unreadable or
68
+ * invalid manifest throws so cage fails closed before the wrapped command runs.
69
+ */
70
+ function manifestZoneTargets(root) {
71
+ if (!fs.existsSync(rootJoin(root, REL_MANIFEST)))
72
+ return [];
73
+ const manifest = loadManifest(root);
74
+ const zones = new Set();
75
+ for (const skill of Object.values(manifest.skills)) {
76
+ for (const raw of skill.forbidden_zones ?? []) {
77
+ const norm = raw.trim().replace(/\\/g, "/").replace(/\/+$/, "");
78
+ if (!norm || norm.startsWith("/") || norm.split("/").includes(".."))
79
+ continue;
80
+ zones.add(norm);
81
+ }
82
+ }
83
+ return [...zones].sort().map((z) => rootJoin(root, z));
84
+ }
85
+ export function buildCagePlan(root) {
86
+ const zones = manifestZoneTargets(root);
87
+ const targets = [
88
+ ...CI_CONFIG_PATHS.map((rel) => ({ abs: rootJoin(root, rel), rule: "ci_config" })),
89
+ ...gitControlTargets(root).map((abs) => ({ abs, rule: "git_control" })),
90
+ ...zones.map((abs) => ({ abs, rule: "manifest_forbidden_zone" })),
91
+ ];
92
+ return { root, targets, manifestZoneCount: zones.length };
93
+ }
94
+ //# sourceMappingURL=cage-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-rules.js","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type CageReport } from "./cage-report.js";
2
+ /** Per-file in-memory snapshot cap; larger revert-mode files are detect-only. */
3
+ export declare const CAGE_DEFAULT_MAX_FILE_BYTES: number;
4
+ /** Total in-memory snapshot budget across all protected files. */
5
+ export declare const CAGE_DEFAULT_MAX_TOTAL_BYTES: number;
6
+ export interface CageRunOptions {
7
+ command: readonly string[];
8
+ /** Working directory for the command; the cage root is its git top-level, else this dir. */
9
+ cwd?: string;
10
+ reportOnly?: boolean;
11
+ maxFileBytes?: number;
12
+ maxTotalBytes?: number;
13
+ /** Live restore while the command runs (default true). */
14
+ watch?: boolean;
15
+ watchIntervalMs?: number;
16
+ /** Session pre-push guard for git run by the caged command (default true inside a git work tree). */
17
+ pushGuard?: boolean;
18
+ /** Called once before the command starts, e.g. to print where the session log is. */
19
+ onStart?: (info: {
20
+ sessionLog: string | null;
21
+ protectedFiles: number;
22
+ watch: boolean;
23
+ }) => void;
24
+ bell?: () => void;
25
+ }
26
+ /** Zero-config root: the enclosing git work tree when there is one, otherwise the directory itself. */
27
+ export declare function resolveCageRoot(cwd: string): string;
28
+ /**
29
+ * Snapshot the protected set, run the command (restoring protected changes live unless `watch: false`),
30
+ * diff once more at exit, and restore what is left. Bytes stay in memory; the session log and the
31
+ * temporary hooks dir live in the OS temp dir, never in the repository.
32
+ */
33
+ export declare function runCage(opts: CageRunOptions): Promise<CageReport>;
34
+ //# sourceMappingURL=cage-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-run.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-run.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAcpE,iFAAiF;AACjF,eAAO,MAAM,2BAA2B,QAAkB,CAAC;AAC3D,kEAAkE;AAClE,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,4FAA4F;IAC5F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qGAAqG;IACrG,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAChG,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMnD;AA2ED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA8BvE"}
@@ -0,0 +1,107 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { getRepoRoot } from "../git/git.js";
4
+ import { buildCageReport } from "./cage-report.js";
5
+ import { resolveCageChanges } from "./cage-revert.js";
6
+ import { buildCagePlan } from "./cage-rules.js";
7
+ import { diffCageSnapshots, takeCageSnapshot } from "./cage-snapshot.js";
8
+ import { signalExitCode, spawnCaged } from "./cage-process.js";
9
+ import { createCagePushGuard } from "./cage-push-guard.js";
10
+ import { CAGE_DEFAULT_WATCH_INTERVAL_MS, openCageSessionLog, startCageWatch, } from "./cage-watch.js";
11
+ /** Per-file in-memory snapshot cap; larger revert-mode files are detect-only. */
12
+ export const CAGE_DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
13
+ /** Total in-memory snapshot budget across all protected files. */
14
+ export const CAGE_DEFAULT_MAX_TOTAL_BYTES = 64 * 1024 * 1024;
15
+ /** Zero-config root: the enclosing git work tree when there is one, otherwise the directory itself. */
16
+ export function resolveCageRoot(cwd) {
17
+ try {
18
+ return getRepoRoot(cwd);
19
+ }
20
+ catch {
21
+ return path.resolve(cwd);
22
+ }
23
+ }
24
+ function countRefusedPushes(log) {
25
+ if (!log || !fs.existsSync(log.path))
26
+ return 0;
27
+ return fs.readFileSync(log.path, "utf8").split("\n").filter((l) => l.includes('"event":"push_refused"')).length;
28
+ }
29
+ /** Live-restored changes first, then the final diff; a path changed again at exit takes the exit outcome. */
30
+ function mergeChanges(live, final) {
31
+ const byPath = new Map(live ? live.restored : []);
32
+ for (const c of final) {
33
+ const earlier = byPath.get(c.abs);
34
+ byPath.set(c.abs, earlier ? { ...c, kind: earlier.kind, before: earlier.before } : c);
35
+ }
36
+ return [...byPath.values()].sort((a, b) => a.rel.localeCompare(b.rel));
37
+ }
38
+ function resolveSettings(opts) {
39
+ const cwd = path.resolve(opts.cwd ?? process.cwd());
40
+ const reportOnly = opts.reportOnly === true;
41
+ return {
42
+ cwd,
43
+ root: resolveCageRoot(cwd),
44
+ reportOnly,
45
+ watch: opts.watch !== false && !reportOnly,
46
+ intervalMs: opts.watchIntervalMs ?? CAGE_DEFAULT_WATCH_INTERVAL_MS,
47
+ pushGuard: opts.pushGuard !== false,
48
+ snap: {
49
+ keepBytes: !reportOnly,
50
+ maxFileBytes: opts.maxFileBytes ?? CAGE_DEFAULT_MAX_FILE_BYTES,
51
+ maxTotalBytes: opts.maxTotalBytes ?? CAGE_DEFAULT_MAX_TOTAL_BYTES,
52
+ },
53
+ };
54
+ }
55
+ /** Run the command with the session log, live watcher and push guard; always tear the guard down. */
56
+ async function runSession(opts, s, plan, before) {
57
+ const log = s.watch || s.pushGuard ? openCageSessionLog() : null;
58
+ const guard = s.pushGuard ? createCagePushGuard(s.root, log?.path ?? null) : null;
59
+ opts.onStart?.({ sessionLog: log?.path ?? null, protectedFiles: before.entries.size, watch: s.watch });
60
+ const watcher = s.watch && log
61
+ ? startCageWatch({ plan, baseline: before, snapshotOptions: s.snap, intervalMs: s.intervalMs, log, bell: opts.bell })
62
+ : null;
63
+ try {
64
+ const proc = await spawnCaged(opts.command, s.cwd, guard?.env ?? {});
65
+ return { proc, live: watcher?.stop() ?? null, log, guarded: guard !== null };
66
+ }
67
+ finally {
68
+ watcher?.stop();
69
+ guard?.dispose();
70
+ }
71
+ }
72
+ /**
73
+ * Snapshot the protected set, run the command (restoring protected changes live unless `watch: false`),
74
+ * diff once more at exit, and restore what is left. Bytes stay in memory; the session log and the
75
+ * temporary hooks dir live in the OS temp dir, never in the repository.
76
+ */
77
+ export async function runCage(opts) {
78
+ const s = resolveSettings(opts);
79
+ // Plan before spawning: an invalid manifest fails closed and the command never runs.
80
+ const plan = buildCagePlan(s.root);
81
+ const before = takeCageSnapshot(plan, s.snap);
82
+ const { proc, live, log, guarded } = await runSession(opts, s, plan, before);
83
+ const after = takeCageSnapshot(plan, { ...s.snap, keepBytes: false });
84
+ const changes = mergeChanges(live, resolveCageChanges(diffCageSnapshots(before, after), { reportOnly: s.reportOnly }));
85
+ return buildCageReport({
86
+ command: opts.command[0] ?? "",
87
+ commandExitCode: proc.code,
88
+ commandSignal: proc.signal,
89
+ runtimeError: proc.spawnError,
90
+ root: s.root,
91
+ reportOnly: s.reportOnly,
92
+ maxFileBytes: s.snap.maxFileBytes,
93
+ protectedFiles: before.entries.size,
94
+ manifestZones: plan.manifestZoneCount,
95
+ changes,
96
+ watch: {
97
+ enabled: s.watch,
98
+ interval_ms: s.watch ? s.intervalMs : null,
99
+ live_restores: live?.liveRestores ?? 0,
100
+ contested: live?.contested ?? [],
101
+ session_log: log?.path ?? null,
102
+ },
103
+ pushGuard: { enabled: guarded, refused_pushes: countRefusedPushes(log) },
104
+ signalExitCode,
105
+ });
106
+ }
107
+ //# sourceMappingURL=cage-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-run.js","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type CagePlan, type CageRuleId, type CageRuleMode } from "./cage-rules.js";
2
+ export interface CageEntry {
3
+ abs: string;
4
+ /** POSIX path relative to the cage root (may start with `../` for a linked worktree git dir). */
5
+ rel: string;
6
+ rule: CageRuleId;
7
+ mode: CageRuleMode;
8
+ type: "file" | "symlink";
9
+ sha256: string;
10
+ size: number;
11
+ fileMode: number;
12
+ /** Baseline bytes for revert; null when over the size cap, budget, or report-only. */
13
+ bytes: Buffer | null;
14
+ linkTarget: string | null;
15
+ }
16
+ export interface CageSnapshot {
17
+ entries: Map<string, CageEntry>;
18
+ }
19
+ export interface CageSnapshotOptions {
20
+ /** Keep file bytes in memory so the snapshot can restore them. */
21
+ keepBytes: boolean;
22
+ maxFileBytes: number;
23
+ maxTotalBytes: number;
24
+ }
25
+ export interface CageChange {
26
+ abs: string;
27
+ rel: string;
28
+ kind: "added" | "modified" | "deleted";
29
+ rule: CageRuleId;
30
+ mode: CageRuleMode;
31
+ before: CageEntry | null;
32
+ after: CageEntry | null;
33
+ }
34
+ export declare function takeCageSnapshot(plan: CagePlan, opts: CageSnapshotOptions): CageSnapshot;
35
+ export declare function diffCageSnapshots(before: CageSnapshot, after: CageSnapshot): CageChange[];
36
+ //# sourceMappingURL=cage-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-snapshot.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-snapshot.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB;AA+FD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,GAAG,YAAY,CAQxF;AAOD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,UAAU,EAAE,CAezF"}
@@ -0,0 +1,128 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { toPosixRel } from "../cli-io.js";
5
+ import { CAGE_RULE_MODES, CAGE_SCAN_SKIP_DIRS, cageBasenameRule, } from "./cage-rules.js";
6
+ const HASH_CHUNK_BYTES = 1024 * 1024;
7
+ function sha256Hex(data) {
8
+ return crypto.createHash("sha256").update(data).digest("hex");
9
+ }
10
+ /** Streamed hash so files over the in-memory cap are still change-detected. */
11
+ function hashFileChunked(abs) {
12
+ const hash = crypto.createHash("sha256");
13
+ const fd = fs.openSync(abs, "r");
14
+ try {
15
+ const buf = Buffer.alloc(HASH_CHUNK_BYTES);
16
+ let n;
17
+ while ((n = fs.readSync(fd, buf, 0, buf.length, null)) > 0) {
18
+ hash.update(buf.subarray(0, n));
19
+ }
20
+ }
21
+ finally {
22
+ fs.closeSync(fd);
23
+ }
24
+ return hash.digest("hex");
25
+ }
26
+ function readEntry(abs, rule, ctx) {
27
+ const st = fs.lstatSync(abs);
28
+ const mode = CAGE_RULE_MODES[rule];
29
+ const base = { abs, rel: toPosixRel(ctx.root, abs), rule, mode, fileMode: st.mode & 0o7777 };
30
+ if (st.isSymbolicLink()) {
31
+ const target = fs.readlinkSync(abs);
32
+ return { ...base, type: "symlink", sha256: sha256Hex(`symlink\0${target}`), size: 0, bytes: null, linkTarget: target };
33
+ }
34
+ if (!st.isFile())
35
+ return null;
36
+ const keep = ctx.opts.keepBytes && mode === "revert" && st.size <= ctx.opts.maxFileBytes && st.size <= ctx.budget;
37
+ if (!keep) {
38
+ return { ...base, type: "file", sha256: hashFileChunked(abs), size: st.size, bytes: null, linkTarget: null };
39
+ }
40
+ // One read for hash and bytes, so the restored content is exactly what was hashed.
41
+ const bytes = fs.readFileSync(abs);
42
+ ctx.budget -= bytes.length;
43
+ return { ...base, type: "file", sha256: sha256Hex(bytes), size: bytes.length, bytes, linkTarget: null };
44
+ }
45
+ function captureEntry(abs, rule, ctx) {
46
+ const existing = ctx.entries.get(abs);
47
+ // A path matched by several rules keeps the strictest one (revert beats report).
48
+ if (existing && (existing.mode === "revert" || CAGE_RULE_MODES[rule] === "report"))
49
+ return;
50
+ try {
51
+ const entry = readEntry(abs, rule, ctx);
52
+ if (entry)
53
+ ctx.entries.set(abs, entry);
54
+ }
55
+ catch {
56
+ // Vanished or unreadable between listing and reading: not part of this snapshot.
57
+ }
58
+ }
59
+ /** Visit files and symlinks under `absDir` without following directory symlinks. */
60
+ function walkTree(absDir, skipDirs, visit) {
61
+ let dirents;
62
+ try {
63
+ dirents = fs.readdirSync(absDir, { withFileTypes: true });
64
+ }
65
+ catch {
66
+ return;
67
+ }
68
+ for (const d of dirents) {
69
+ const child = path.join(absDir, d.name);
70
+ if (d.isDirectory()) {
71
+ if (!skipDirs?.has(d.name))
72
+ walkTree(child, skipDirs, visit);
73
+ continue;
74
+ }
75
+ if (d.isFile() || d.isSymbolicLink())
76
+ visit(child);
77
+ }
78
+ }
79
+ function captureTarget(abs, rule, ctx) {
80
+ let st;
81
+ try {
82
+ st = fs.lstatSync(abs);
83
+ }
84
+ catch {
85
+ return;
86
+ }
87
+ if (st.isDirectory()) {
88
+ walkTree(abs, null, (child) => captureEntry(child, rule, ctx));
89
+ return;
90
+ }
91
+ captureEntry(abs, rule, ctx);
92
+ }
93
+ export function takeCageSnapshot(plan, opts) {
94
+ const ctx = { root: plan.root, opts, budget: opts.maxTotalBytes, entries: new Map() };
95
+ for (const target of plan.targets)
96
+ captureTarget(target.abs, target.rule, ctx);
97
+ walkTree(plan.root, CAGE_SCAN_SKIP_DIRS, (abs) => {
98
+ const rule = cageBasenameRule(path.basename(abs));
99
+ if (rule)
100
+ captureEntry(abs, rule, ctx);
101
+ });
102
+ return { entries: ctx.entries };
103
+ }
104
+ function entryChanged(a, b) {
105
+ // mtime is ignored on purpose: a bare `touch` is not a mutation.
106
+ return a.sha256 !== b.sha256 || a.type !== b.type || a.fileMode !== b.fileMode;
107
+ }
108
+ export function diffCageSnapshots(before, after) {
109
+ const keys = new Set([...before.entries.keys(), ...after.entries.keys()]);
110
+ const changes = [];
111
+ for (const abs of keys) {
112
+ const b = before.entries.get(abs) ?? null;
113
+ const a = after.entries.get(abs) ?? null;
114
+ let kind = null;
115
+ if (b && !a)
116
+ kind = "deleted";
117
+ else if (!b && a)
118
+ kind = "added";
119
+ else if (b && a && entryChanged(b, a))
120
+ kind = "modified";
121
+ if (!kind)
122
+ continue;
123
+ const ref = (b ?? a);
124
+ changes.push({ abs, rel: ref.rel, kind, rule: ref.rule, mode: ref.mode, before: b, after: a });
125
+ }
126
+ return changes.sort((x, y) => x.rel.localeCompare(y.rel));
127
+ }
128
+ //# sourceMappingURL=cage-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-snapshot.js","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type CageResolvedChange } from "./cage-revert.js";
2
+ import type { CagePlan } from "./cage-rules.js";
3
+ import { type CageSnapshot, type CageSnapshotOptions } from "./cage-snapshot.js";
4
+ /** Default live-check interval while the caged command runs. */
5
+ export declare const CAGE_DEFAULT_WATCH_INTERVAL_MS = 1000;
6
+ /** Live restores of one path before cage stops fighting the command and restores it only at exit. */
7
+ export declare const CAGE_CONTEST_LIMIT = 3;
8
+ /** Append-only session event log in the OS temp dir: one JSON object per line, never file bodies. */
9
+ export interface CageSessionLog {
10
+ path: string;
11
+ append(event: Record<string, unknown>): void;
12
+ }
13
+ export declare function openCageSessionLog(dir?: string): CageSessionLog;
14
+ export interface CageWatchSummary {
15
+ liveRestores: number;
16
+ contested: string[];
17
+ /** Live-resolved revert-rule changes, by path; the exit report merges these with the final diff. */
18
+ restored: Map<string, CageResolvedChange>;
19
+ }
20
+ export interface CageWatcher {
21
+ stop(): CageWatchSummary;
22
+ }
23
+ /**
24
+ * Re-snapshot the protected set on an interval while the command runs and restore revert-rule changes
25
+ * from the baseline bytes. Lockfiles stay report-only and are left for the exit report. A path restored
26
+ * {@link CAGE_CONTEST_LIMIT} times is marked contested and restored only at exit.
27
+ */
28
+ export declare function startCageWatch(input: {
29
+ plan: CagePlan;
30
+ baseline: CageSnapshot;
31
+ snapshotOptions: CageSnapshotOptions;
32
+ intervalMs: number;
33
+ log: CageSessionLog;
34
+ bell?: () => void;
35
+ }): CageWatcher;
36
+ //# sourceMappingURL=cage-watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-watch.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-watch.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAuC,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEtH,gEAAgE;AAChE,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAIpC,qGAAqG;AACrG,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9C;AAED,wBAAgB,kBAAkB,CAAC,GAAG,SAAc,GAAG,cAAc,CASpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oGAAoG;IACpG,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,IAAI,gBAAgB,CAAC;CAC1B;AA+CD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,cAAc,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;CACnB,GAAG,WAAW,CA4Bd"}