jules-orchestrator-kit 0.32.0 → 0.32.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.
package/README.md CHANGED
@@ -102,7 +102,7 @@ Autonomous coding agents can write software at 100× human speed—but unconstra
102
102
 
103
103
  * **🔒 Zero Runtime Dependencies:** Built exclusively on Node.js 20+ built-ins (`node:fs`, `node:child_process`, `node:crypto`, `node:path`, `node:http`, `node:tty`, `node:test`). Zero third-party npm packages mean zero supply-chain CVE risk.
104
104
 
105
- * **🛡️ Fail-Closed Security Gatekeeper:** Unconditionally evaluates explicit Deny rules *before* Allow rules, redacts high-entropy secrets and PII from dry-runs and git diffs, and rejects PRs exceeding the 75 KB Diff Payload governor.
105
+ * **🛡️ Fail-Closed Security Gatekeeper:** Unconditionally evaluates explicit Deny rules *before* Allow rules, redacts high-entropy secrets and PII from dry-runs and git diffs, blocks unsupported Node.js native module imports in Edge environments (Cloudflare Workers, Vercel Edge, Netlify Edge), and rejects PRs exceeding the 75 KB Diff Payload governor.
106
106
 
107
107
  * **🔄 Autonomous OODA Self-Healing:** Captures test stderr/stdout, normalizes failure fingerprints, and feeds structured error contexts back into repair iterations (up to 3 automatic attempts) before human escalation.
108
108
 
package/bin/agentctl.mjs CHANGED
@@ -14,7 +14,7 @@ const command = args[0];
14
14
 
15
15
  function printHelp() {
16
16
  console.log(`
17
- 🚀 agentctl v0.32.0 — Universal Agent Orchestrator & Safety Gatekeeper
17
+ 🚀 agentctl v0.32.1 — Universal Agent Orchestrator & Safety Gatekeeper
18
18
 
19
19
  Usage: agentctl <command> [options]
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jules-orchestrator-kit",
3
- "version": "0.32.0",
3
+ "version": "0.32.1",
4
4
  "description": "Orchestration kit for running Google Jules autonomous agents.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/security.mjs CHANGED
@@ -236,7 +236,58 @@ export function checkScope(files = [], scope = {}, opts = {}) {
236
236
  };
237
237
  }
238
238
 
239
- export function scanDiff(diffTextStr = "") {
239
+ export const FORBIDDEN_EDGE_MODULES = [
240
+ "fs", "node:fs",
241
+ "child_process", "node:child_process",
242
+ "cluster", "node:cluster",
243
+ "dgram", "node:dgram",
244
+ "net", "node:net",
245
+ "tls", "node:tls",
246
+ "v8", "node:v8",
247
+ "vm", "node:vm",
248
+ "worker_threads", "node:worker_threads",
249
+ ];
250
+
251
+ export function checkEdgeRuntimeImports(diffOrText = "", options = {}) {
252
+ if (!diffOrText || typeof diffOrText !== "string") return { ok: true, violations: [] };
253
+
254
+ const isEdgeExplicit = options.isEdgeRuntime === true;
255
+ const hasEdgeExport = /export\s+const\s+runtime\s*=\s*['"]edge['"]/i.test(diffOrText);
256
+ const isEdgeContext = isEdgeExplicit || hasEdgeExport;
257
+
258
+ if (!isEdgeContext) {
259
+ return { ok: true, violations: [] };
260
+ }
261
+
262
+ const lines = diffOrText.split("\n");
263
+ const targetLines = lines.filter((line) => {
264
+ if (diffOrText.includes("+++ b/")) {
265
+ return line.startsWith("+") && !line.startsWith("+++");
266
+ }
267
+ return true;
268
+ });
269
+
270
+ const edgeImportRegex = /(?:import\s+.*?\s+from\s+|require\s*\(\s*)['"](node:(?:fs|child_process|cluster|dgram|net|tls|v8|vm|worker_threads)|(?:fs|child_process|cluster|dgram|net|tls|v8|vm|worker_threads))(?:\/.*)?['"]/i;
271
+
272
+ const violations = [];
273
+ for (const line of targetLines) {
274
+ const match = line.match(edgeImportRegex);
275
+ if (match) {
276
+ violations.push({
277
+ module: match[1],
278
+ line: line.trim(),
279
+ reason: `Edge Runtime Violation: Native Node module "${match[1]}" is unsupported in Edge environments (Cloudflare Workers / Vercel Edge / Netlify Edge).`,
280
+ });
281
+ }
282
+ }
283
+
284
+ return {
285
+ ok: violations.length === 0,
286
+ violations,
287
+ };
288
+ }
289
+
290
+ export function scanDiff(diffTextStr = "", options = {}) {
240
291
  if (!diffTextStr) return { ok: true, findings: [] };
241
292
  const addedLines = diffTextStr
242
293
  .split("\n")
@@ -254,8 +305,15 @@ export function scanDiff(diffTextStr = "") {
254
305
  findings.push({ severity: "HIGH", type: "LOW_CONFIDENCE_SECRET", description: "Low-confidence secret or authorization token detected in added diff lines" });
255
306
  }
256
307
 
308
+ const edgeRes = checkEdgeRuntimeImports(diffTextStr, options);
309
+ if (!edgeRes.ok) {
310
+ for (const v of edgeRes.violations) {
311
+ findings.push({ severity: "HIGH", type: "EDGE_RUNTIME_VIOLATION", description: v.reason });
312
+ }
313
+ }
314
+
257
315
  return {
258
- ok: !hasHigh && !hasLow,
316
+ ok: !hasHigh && !hasLow && edgeRes.ok,
259
317
  findings,
260
318
  };
261
319
  }
@@ -26,10 +26,45 @@ test("Zero-Test Bootstrapped Smoke Verification", () => {
26
26
  return ".agent/smoke.test.mjs";
27
27
  }
28
28
 
29
+ export function detectEdgeRuntime(projectRoot = process.cwd()) {
30
+ const isCloudflare = existsSync(join(projectRoot, "wrangler.toml")) || existsSync(join(projectRoot, "wrangler.json"));
31
+ const isDeno = existsSync(join(projectRoot, "deno.json")) || existsSync(join(projectRoot, "deno.jsonc"));
32
+ const isNetlify = existsSync(join(projectRoot, "netlify.toml"));
33
+
34
+ let isPkgEdge = false;
35
+ let pkgEdgePlatform = null;
36
+
37
+ const pkgPath = join(projectRoot, "package.json");
38
+ if (existsSync(pkgPath)) {
39
+ try {
40
+ const content = readFileSync(pkgPath, "utf-8");
41
+ if (content.includes("@cloudflare/workers-types") || content.includes("@cloudflare/env")) {
42
+ isPkgEdge = true;
43
+ pkgEdgePlatform = "cloudflare";
44
+ } else if (content.includes("@vercel/edge") || content.includes("@vercel/functions")) {
45
+ isPkgEdge = true;
46
+ pkgEdgePlatform = "vercel";
47
+ } else if (content.includes("@netlify/edge-functions")) {
48
+ isPkgEdge = true;
49
+ pkgEdgePlatform = "netlify";
50
+ }
51
+ } catch (_) {}
52
+ }
53
+
54
+ const isEdge = isCloudflare || isDeno || isNetlify || isPkgEdge;
55
+ const platform = isCloudflare ? "cloudflare" : isDeno ? "deno" : isNetlify ? "netlify" : pkgEdgePlatform;
56
+
57
+ return {
58
+ isEdgeRuntime: isEdge,
59
+ edgePlatform: platform,
60
+ };
61
+ }
62
+
29
63
  /**
30
64
  * Detects 24+ polyglot stacks and container environments.
31
65
  */
32
66
  export function detectPolyglotStack(projectRoot = process.cwd()) {
67
+ const edgeInfo = detectEdgeRuntime(projectRoot);
33
68
  const isDevcontainer = existsSync(join(projectRoot, ".devcontainer", "devcontainer.json"));
34
69
  const isCompose =
35
70
  existsSync(join(projectRoot, "docker-compose.yml")) ||
@@ -38,6 +73,7 @@ export function detectPolyglotStack(projectRoot = process.cwd()) {
38
73
  existsSync(join(projectRoot, "compose.yaml"));
39
74
 
40
75
  const container = {
76
+ ...edgeInfo,
41
77
  containerized: isDevcontainer || isCompose,
42
78
  containerType: isDevcontainer ? "devcontainer" : isCompose ? "docker-compose" : null,
43
79
  containerCmd: isDevcontainer