@jeger-ai/opengantry 3.7.0 → 3.8.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 (51) hide show
  1. package/README.md +15 -15
  2. package/dist/cli/commands/cage.d.ts +16 -0
  3. package/dist/cli/commands/cage.d.ts.map +1 -1
  4. package/dist/cli/commands/cage.js +77 -8
  5. package/dist/cli/commands/cage.js.map +1 -1
  6. package/dist/cli/lib/cage/cage-config.d.ts +29 -0
  7. package/dist/cli/lib/cage/cage-config.d.ts.map +1 -0
  8. package/dist/cli/lib/cage/cage-config.js +143 -0
  9. package/dist/cli/lib/cage/cage-config.js.map +1 -0
  10. package/dist/cli/lib/cage/cage-process.d.ts +1 -1
  11. package/dist/cli/lib/cage/cage-process.d.ts.map +1 -1
  12. package/dist/cli/lib/cage/cage-process.js +2 -2
  13. package/dist/cli/lib/cage/cage-process.js.map +1 -1
  14. package/dist/cli/lib/cage/cage-push-guard.d.ts +26 -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 +114 -0
  17. package/dist/cli/lib/cage/cage-push-guard.js.map +1 -0
  18. package/dist/cli/lib/cage/cage-report.d.ts +37 -2
  19. package/dist/cli/lib/cage/cage-report.d.ts.map +1 -1
  20. package/dist/cli/lib/cage/cage-report.js +50 -4
  21. package/dist/cli/lib/cage/cage-report.js.map +1 -1
  22. package/dist/cli/lib/cage/cage-revert.d.ts +1 -1
  23. package/dist/cli/lib/cage/cage-rules.d.ts +49 -3
  24. package/dist/cli/lib/cage/cage-rules.d.ts.map +1 -1
  25. package/dist/cli/lib/cage/cage-rules.js +145 -7
  26. package/dist/cli/lib/cage/cage-rules.js.map +1 -1
  27. package/dist/cli/lib/cage/cage-run.d.ts +22 -2
  28. package/dist/cli/lib/cage/cage-run.d.ts.map +1 -1
  29. package/dist/cli/lib/cage/cage-run.js +85 -17
  30. package/dist/cli/lib/cage/cage-run.js.map +1 -1
  31. package/dist/cli/lib/cage/cage-snapshot.d.ts +11 -0
  32. package/dist/cli/lib/cage/cage-snapshot.d.ts.map +1 -1
  33. package/dist/cli/lib/cage/cage-snapshot.js +60 -18
  34. package/dist/cli/lib/cage/cage-snapshot.js.map +1 -1
  35. package/dist/cli/lib/cage/cage-suggest.d.ts +28 -0
  36. package/dist/cli/lib/cage/cage-suggest.d.ts.map +1 -0
  37. package/dist/cli/lib/cage/cage-suggest.js +164 -0
  38. package/dist/cli/lib/cage/cage-suggest.js.map +1 -0
  39. package/dist/cli/lib/cage/cage-watch.d.ts +36 -0
  40. package/dist/cli/lib/cage/cage-watch.d.ts.map +1 -0
  41. package/dist/cli/lib/cage/cage-watch.js +92 -0
  42. package/dist/cli/lib/cage/cage-watch.js.map +1 -0
  43. package/dist/cli/lib/version.gen.d.ts +1 -1
  44. package/dist/cli/lib/version.gen.js +1 -1
  45. package/dist/cli/program-cage.d.ts +9 -2
  46. package/dist/cli/program-cage.d.ts.map +1 -1
  47. package/dist/cli/program-cage.js +50 -6
  48. package/dist/cli/program-cage.js.map +1 -1
  49. package/package.json +1 -1
  50. package/templates/.gitagent/foreman/SUBSTRATE.version.json +1 -1
  51. package/templates/integrations/compatibility.json +1 -1
@@ -0,0 +1,92 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { resolveCageChanges } from "./cage-revert.js";
6
+ import { diffCageSnapshots, takeCageSnapshot } from "./cage-snapshot.js";
7
+ /** Default live-check interval while the caged command runs. */
8
+ export const CAGE_DEFAULT_WATCH_INTERVAL_MS = 1000;
9
+ /** Live restores of one path before cage stops fighting the command and restores it only at exit. */
10
+ export const CAGE_CONTEST_LIMIT = 3;
11
+ const BELL = "\x07";
12
+ export function openCageSessionLog(dir = os.tmpdir()) {
13
+ const file = path.join(dir, `gantry-cage-${String(process.pid)}-${crypto.randomBytes(4).toString("hex")}.log`);
14
+ fs.writeFileSync(file, "", { mode: 0o600 });
15
+ return {
16
+ path: file,
17
+ append(event) {
18
+ fs.appendFileSync(file, `${JSON.stringify({ at: new Date().toISOString(), ...event })}\n`);
19
+ },
20
+ };
21
+ }
22
+ function noteEvent(log, bell, event) {
23
+ log.append(event);
24
+ bell();
25
+ }
26
+ function handleLiveChange(change, state, log, bell) {
27
+ const base = { path: change.rel, kind: change.kind, rule: change.rule };
28
+ if (change.outcome === "reverted" || change.outcome === "removed") {
29
+ state.liveRestores += 1;
30
+ state.restored.set(change.abs, change);
31
+ noteEvent(log, bell, { event: "restored", ...base, outcome: change.outcome });
32
+ return;
33
+ }
34
+ if (!state.unrestorable.has(change.abs)) {
35
+ state.unrestorable.add(change.abs);
36
+ noteEvent(log, bell, { event: change.outcome, ...base, error_code: change.errorCode });
37
+ }
38
+ }
39
+ function tick(plan, baseline, opts, state, log, bell) {
40
+ const current = takeCageSnapshot(plan, { ...opts, keepBytes: false });
41
+ const pending = diffCageSnapshots(baseline, current).filter((c) => {
42
+ if (c.mode !== "revert" || state.contested.has(c.abs))
43
+ return false;
44
+ const count = state.restoresByPath.get(c.abs) ?? 0;
45
+ if (count < CAGE_CONTEST_LIMIT)
46
+ return true;
47
+ state.contested.add(c.abs);
48
+ noteEvent(log, bell, { event: "contested", path: c.rel, rule: c.rule, live_restores: count });
49
+ return false;
50
+ });
51
+ for (const change of resolveCageChanges(pending, { reportOnly: false })) {
52
+ if (change.outcome === "reverted" || change.outcome === "removed") {
53
+ state.restoresByPath.set(change.abs, (state.restoresByPath.get(change.abs) ?? 0) + 1);
54
+ }
55
+ handleLiveChange(change, state, log, bell);
56
+ }
57
+ }
58
+ /**
59
+ * Re-snapshot the protected set on an interval while the command runs and restore revert-rule changes
60
+ * from the baseline bytes. Lockfiles stay report-only and are left for the exit report. A path restored
61
+ * {@link CAGE_CONTEST_LIMIT} times is marked contested and restored only at exit.
62
+ */
63
+ export function startCageWatch(input) {
64
+ const bell = input.bell ?? (() => process.stderr.write(BELL));
65
+ const state = {
66
+ restoresByPath: new Map(),
67
+ contested: new Set(),
68
+ unrestorable: new Set(),
69
+ restored: new Map(),
70
+ liveRestores: 0,
71
+ };
72
+ const timer = setInterval(() => {
73
+ try {
74
+ tick(input.plan, input.baseline, input.snapshotOptions, state, input.log, bell);
75
+ }
76
+ catch (err) {
77
+ input.log.append({ event: "watch_error", message: err instanceof Error ? err.message : String(err) });
78
+ }
79
+ }, input.intervalMs);
80
+ return {
81
+ stop() {
82
+ clearInterval(timer);
83
+ const rel = (abs) => state.restored.get(abs)?.rel ?? path.relative(input.plan.root, abs).split(path.sep).join("/");
84
+ return {
85
+ liveRestores: state.liveRestores,
86
+ contested: [...state.contested].map(rel).sort(),
87
+ restored: state.restored,
88
+ };
89
+ },
90
+ };
91
+ }
92
+ //# sourceMappingURL=cage-watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cage-watch.js","sourceRoot":"","sources":["../../../../src/cli/lib/cage/cage-watch.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  /** Generated by scripts/gen-version.mjs — do not edit */
2
- export declare const CLI_VERSION = "3.7.0";
2
+ export declare const CLI_VERSION = "3.8.0";
3
3
  export declare const NPM_PACKAGE_NAME = "@jeger-ai/opengantry";
4
4
  //# sourceMappingURL=version.gen.d.ts.map
@@ -1,4 +1,4 @@
1
1
  /** Generated by scripts/gen-version.mjs — do not edit */
2
- export const CLI_VERSION = "3.7.0";
2
+ export const CLI_VERSION = "3.8.0";
3
3
  export const NPM_PACKAGE_NAME = "@jeger-ai/opengantry";
4
4
  //# sourceMappingURL=version.gen.js.map
@@ -1,5 +1,12 @@
1
- import type { Command } from "commander";
1
+ import { Command } from "commander";
2
+ /**
3
+ * `gantry cage suggest` was typed: `suggest` is the first operand and no `--` came before it.
4
+ * Commander drops `--` from operands, so read the raw argv; `gantry cage -- suggest` runs a command.
5
+ */
6
+ export declare function isSuggestInvocation(operands: readonly string[], argv?: readonly string[]): boolean;
2
7
  /** Shared by `gantry cage` and the standalone `opengantry-cage` bin so the two never drift. */
3
- export declare function configureCageCommand(cmd: Command): Command;
8
+ export declare function configureCageCommand(cmd: Command, opts?: {
9
+ suggest?: boolean;
10
+ }): Command;
4
11
  export declare function registerCageCommands(program: Command): void;
5
12
  //# sourceMappingURL=program-cage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"program-cage.d.ts","sourceRoot":"","sources":["../../src/cli/program-cage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAc1D;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE3D"}
1
+ {"version":3,"file":"program-cage.d.ts","sourceRoot":"","sources":["../../src/cli/program-cage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,GAAE,SAAS,MAAM,EAAiB,GAAG,OAAO,CAMhH;AAYD,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CA4C5F;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAW3D"}
@@ -1,19 +1,63 @@
1
- import { runCageCommand } from "./commands/cage.js";
1
+ import { Command } from "commander";
2
+ import { runCageCommand, runCageGuardPrePush, runCageSuggestCommand } from "./commands/cage.js";
3
+ function collect(value, previous) {
4
+ return [...previous, value];
5
+ }
6
+ /**
7
+ * `gantry cage suggest` was typed: `suggest` is the first operand and no `--` came before it.
8
+ * Commander drops `--` from operands, so read the raw argv; `gantry cage -- suggest` runs a command.
9
+ */
10
+ export function isSuggestInvocation(operands, argv = process.argv) {
11
+ if (operands[0] !== "suggest")
12
+ return false;
13
+ const raw = argv.slice(2);
14
+ const after = raw.slice(raw.indexOf("cage") + 1);
15
+ const dashes = after.indexOf("--");
16
+ return dashes === -1 || after.indexOf("suggest") < dashes;
17
+ }
18
+ async function runSuggestArgs(args, inherited) {
19
+ const sub = new Command("gantry cage suggest")
20
+ .description("Propose .cage.yaml protect entries for review (setup step; refused inside a cage session)")
21
+ .option("--write", "Write .cage.yaml.suggested instead of printing (never writes .cage.yaml)")
22
+ .option("--force", "Replace an existing .cage.yaml.suggested")
23
+ .option("--json", "Emit suggestions as JSON on stdout");
24
+ sub.parse(args, { from: "user" });
25
+ await runCageSuggestCommand({ json: inherited.json, ...sub.opts() });
26
+ }
2
27
  /** Shared by `gantry cage` and the standalone `opengantry-cage` bin so the two never drift. */
3
- export function configureCageCommand(cmd) {
28
+ export function configureCageCommand(cmd, opts = {}) {
29
+ if (opts.suggest) {
30
+ cmd.addHelpText("after", "\nSetup (run it yourself, outside a cage session):\n gantry cage suggest [--write] [--force] [--json] propose .cage.yaml rules for review\n");
31
+ }
4
32
  return cmd
5
- .description("Zero-config: run a command, then revert changes to CI configs, .env secrets, git hooks/config and manifest forbidden zones (lockfiles reported)")
33
+ .description("Zero-config: run a command and restore changes to CI configs, .env secrets, git hooks/config, manifest forbidden zones and .cage.yaml protect entries while it runs and at exit (lockfiles reported); refuses git pushes of protected paths from inside the session")
6
34
  .option("--json", "Emit the digest-only cage report as JSON on stdout")
7
35
  .option("--report-only", "Detect and report protected changes without reverting them")
36
+ .option("--no-watch", "Check only once, after the command exits (no live restore)")
37
+ .option("--watch-interval-ms <n>", "Live check interval while the command runs (default 1000)")
8
38
  .option("--max-file-bytes <n>", "Per-file in-memory snapshot cap; larger files are detect-only")
39
+ .option("--allow-override <path>", "Report instead of restore changes under <path> for this run (repeatable; never git hooks/config or .cage.yaml)", collect, [])
9
40
  .allowUnknownOption(true)
10
41
  .passThroughOptions()
11
42
  .argument("<command...>", "Command to run after --")
12
- .action(async (command, opts) => {
13
- await runCageCommand({ command, ...opts });
43
+ .action(async (command, cliOpts) => {
44
+ if (opts.suggest && isSuggestInvocation(command)) {
45
+ await runSuggestArgs(command.slice(1), { json: cliOpts.json });
46
+ return;
47
+ }
48
+ await runCageCommand({ command, ...cliOpts });
14
49
  });
15
50
  }
16
51
  export function registerCageCommands(program) {
17
- configureCageCommand(program.command("cage"));
52
+ configureCageCommand(program.command("cage"), { suggest: true });
53
+ program
54
+ .command("cage-guard", { hidden: true })
55
+ .description("Internal: checks run by the cage session git hooks")
56
+ .command("pre-push")
57
+ .requiredOption("--root <dir>", "Cage root (git work tree)")
58
+ .option("--plan <file>", "Session plan written by gantry cage")
59
+ .action(async (opts) => {
60
+ await runCageGuardPrePush(opts);
61
+ });
18
62
  }
19
63
  //# sourceMappingURL=program-cage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"program-cage.js","sourceRoot":"","sources":["../../src/cli/program-cage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,+FAA+F;AAC/F,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,OAAO,GAAG;SACP,WAAW,CACV,iJAAiJ,CAClJ;SACA,MAAM,CAAC,QAAQ,EAAE,oDAAoD,CAAC;SACtE,MAAM,CAAC,eAAe,EAAE,4DAA4D,CAAC;SACrF,MAAM,CAAC,sBAAsB,EAAE,+DAA+D,CAAC;SAC/F,kBAAkB,CAAC,IAAI,CAAC;SACxB,kBAAkB,EAAE;SACpB,QAAQ,CAAC,cAAc,EAAE,yBAAyB,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,OAAiB,EAAE,IAAqE,EAAE,EAAE;QACzG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"program-cage.js","sourceRoot":"","sources":["../../src/cli/program-cage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhG,SAAS,OAAO,CAAC,KAAa,EAAE,QAAkB;IAChD,OAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAA2B,EAAE,OAA0B,OAAO,CAAC,IAAI;IACrG,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,MAAM,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC;AAC5D,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAc,EAAE,SAA6B;IACzE,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,qBAAqB,CAAC;SAC3C,WAAW,CAAC,2FAA2F,CAAC;SACxG,MAAM,CAAC,SAAS,EAAE,0EAA0E,CAAC;SAC7F,MAAM,CAAC,SAAS,EAAE,0CAA0C,CAAC;SAC7D,MAAM,CAAC,QAAQ,EAAE,oCAAoC,CAAC,CAAC;IAC1D,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,MAAM,qBAAqB,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,OAA8B,EAAE;IACjF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,GAAG,CAAC,WAAW,CACb,OAAO,EACP,+IAA+I,CAChJ,CAAC;IACJ,CAAC;IACD,OAAO,GAAG;SACP,WAAW,CACV,qQAAqQ,CACtQ;SACA,MAAM,CAAC,QAAQ,EAAE,oDAAoD,CAAC;SACtE,MAAM,CAAC,eAAe,EAAE,4DAA4D,CAAC;SACrF,MAAM,CAAC,YAAY,EAAE,4DAA4D,CAAC;SAClF,MAAM,CAAC,yBAAyB,EAAE,2DAA2D,CAAC;SAC9F,MAAM,CAAC,sBAAsB,EAAE,+DAA+D,CAAC;SAC/F,MAAM,CACL,yBAAyB,EACzB,gHAAgH,EAChH,OAAO,EACP,EAAE,CACH;SACA,kBAAkB,CAAC,IAAI,CAAC;SACxB,kBAAkB,EAAE;SACpB,QAAQ,CAAC,cAAc,EAAE,yBAAyB,CAAC;SACnD,MAAM,CACL,KAAK,EACH,OAAiB,EACjB,OAOC,EACD,EAAE;QACF,IAAI,IAAI,CAAC,OAAO,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,MAAM,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QACD,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;AACN,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,OAAO;SACJ,OAAO,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACvC,WAAW,CAAC,oDAAoD,CAAC;SACjE,OAAO,CAAC,UAAU,CAAC;SACnB,cAAc,CAAC,cAAc,EAAE,2BAA2B,CAAC;SAC3D,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC;SAC9D,MAAM,CAAC,KAAK,EAAE,IAAqC,EAAE,EAAE;QACtD,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACP,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jeger-ai/opengantry",
3
- "version": "3.7.0",
3
+ "version": "3.8.0",
4
4
  "description": "Open Source Gantry — vendor-neutral GXT substrate and Gantry CLI for local git-native agent governance",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": "0.1.0",
3
- "opengantry_version": "3.7.0",
3
+ "opengantry_version": "3.8.0",
4
4
  "installed_at": "2026-01-01T00:00:00.000Z",
5
5
  "installed_by": "gantry init"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": "1",
3
- "opengantry_version": "3.7.0",
3
+ "opengantry_version": "3.8.0",
4
4
  "asset_catalog": "integrations/asset-catalog.json",
5
5
  "integrations": {
6
6
  "cursor": {