jules-orchestrator-kit 0.75.1 → 0.75.3

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/CHANGELOG.md CHANGED
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.75.3] - 2026-10-09
11
+
12
+ ### Added
13
+ - **`--oracle` Verification Alias (`bin/agentctl.mjs`, `src/ops/command-registry.mjs`)**: Added `--oracle` alias for `--verify` / `--verify-cmd` across `agentctl task create`, `task new`, `task template`, and `dispatch`, aligning CLI flags with prompt template terminology.
14
+ - **Explicit Lane Flag on Task Creation (`bin/agentctl.mjs`, `src/ops/command-registry.mjs`)**: Added `--lane` and `--risk-lane` flags to `agentctl task create` and `task new` to specify risk level directly (`green|amber|orange|red`) without manual frontmatter edits.
15
+
16
+ ### Fixed
17
+ - **Queue Fallback Isolation (`bin/agentctl.mjs`)**: Prevented automatic pending queue file selection during `task create` / `task new`, ensuring queue auto-selection is restricted to `dispatch` and `run`.
18
+ - **Envelope Comment Stripping in Entropy Scanner (`src/wizard-task.mjs`, `src/secret-scanner.mjs`)**: Stripped `<!-- JULES_TASK_ENVELOPE: ... -->` comments and YAML frontmatter prior to Shannon entropy calculation to prevent false-positive secret leak blocks on tasks carrying envelope metadata.
19
+ - **Word Boundaries on Credential Keywords (`src/secret-scanner.mjs`)**: Added word boundary assertions around credential keywords in `LOW_CONFIDENCE_PATTERNS` so identifiers like `hasHighEntropyToken` are not flagged as secret leaks.
20
+
21
+ ## [0.75.2] - 2026-10-09
22
+
23
+ ### Fixed
24
+ - **Committed Mode Snapshot Target (`src/engine.mjs`)**: Pointed `materializeSnapshot` to target commit `opts.head` (defaults to `HEAD`) instead of base commit when evaluating in committed mode.
25
+ - **Auto-Merge CI PR Head Checkout (`src/ci-templates.mjs`)**: Detached checkout to fetched PR head (`git checkout --detach refs/pr-head`) before gate evaluation so PR verification tests candidate changes rather than base.
26
+ - **TUI Interactive Fallback on Headless CI (`src/ops/tui-menu.mjs`)**: Allowed interactive terminal UI menu execution when custom mock streams are explicitly provided even if `process.env.CI` is defined.
27
+ - **Pure JSON Output in Task Queue (`bin/agentctl.mjs`)**: Suppressed decorative informational messages during `agentctl queue --json` execution for uncorrupted machine consumption.
28
+
29
+ ### Added
30
+ - **CLI Navigation Aliases & Gate Flags (`bin/agentctl.mjs`, `src/ops/command-registry.mjs`)**: Added `hub` alias for `menu`, `task new` alias for `task create`, and forwarded `--head` to `agentctl check` and verification gate.
31
+
32
+ ### Security
33
+ - **Task Envelope & Pre-Dispatch Secret Prevention (`src/envelope.mjs`, `src/engine.mjs`)**: Rejected prompts and task intents containing unredacted high-confidence credentials before queuing or agent dispatch.
34
+
10
35
  ## [0.75.1] - 2026-10-09
11
36
 
12
37
  ### Added
package/README.md CHANGED
@@ -17,7 +17,7 @@ You can also run local checks without connecting an agent provider.
17
17
  `agentctl repair` explicitly for repair workflows. Provider output and passing
18
18
  checks still need review before merging.
19
19
 
20
- The current release is **v0.75.1**, a pre-1.0 release. A long-term stability policy is a
20
+ The current release is **v0.75.3**, a pre-1.0 release. A long-term stability policy is a
21
21
  [v1.0 goal](https://github.com/FullThrottle83/jules-orchestrator-kit/blob/main/ROADMAP_V1.md).
22
22
 
23
23
  ## Quickstart
@@ -176,7 +176,7 @@ npm run package-integrity
176
176
  npm run guard-reach
177
177
  ```
178
178
 
179
- The recorded baseline is **1667 unit tests across 210 suites**. Doc-sync compares
179
+ The recorded baseline is **1672 unit tests across 210 suites**. Doc-sync compares
180
180
  that count with an actual run. Counts do not establish correctness for every
181
181
  provider or project. See
182
182
  [contributing](https://github.com/FullThrottle83/jules-orchestrator-kit/blob/main/CONTRIBUTING.md)
package/bin/agentctl.mjs CHANGED
@@ -127,7 +127,7 @@ export function printHelp() {
127
127
  * @param {string} [root] Repository root.
128
128
  * @returns {{ content: string, sourceFile: string | null }}
129
129
  */
130
- function resolvePromptDetails(values, positionals = [], root = process.cwd()) {
130
+ function resolvePromptDetails(values, positionals = [], root = process.cwd(), { allowQueueFallback = true } = {}) {
131
131
  const file = values["prompt-file"] || values.file;
132
132
  if (file) {
133
133
  if (!existsSync(file)) {
@@ -157,7 +157,7 @@ function resolvePromptDetails(values, positionals = [], root = process.cwd()) {
157
157
  }
158
158
  }
159
159
 
160
- if (positionals.length === 0) {
160
+ if (allowQueueFallback && positionals.length === 0) {
161
161
  const queueDir = getQueueDir(root);
162
162
  if (existsSync(queueDir)) {
163
163
  const candidates = readdirSync(queueDir)
@@ -176,8 +176,8 @@ function resolvePromptDetails(values, positionals = [], root = process.cwd()) {
176
176
  return { content: positionals.join(" ").trim(), sourceFile: null };
177
177
  }
178
178
 
179
- function resolvePromptInput(values, positionals = [], root = process.cwd()) {
180
- return resolvePromptDetails(values, positionals, root).content;
179
+ function resolvePromptInput(values, positionals = [], root = process.cwd(), options = {}) {
180
+ return resolvePromptDetails(values, positionals, root, options).content;
181
181
  }
182
182
 
183
183
  /**
@@ -272,8 +272,8 @@ async function main() {
272
272
  if (!command) {
273
273
  if (args.includes("-i") || args.includes("--interactive")) {
274
274
  const { runTuiMenu } = await import("../src/ops/tui-menu.mjs");
275
- await runTuiMenu(resolveRoot());
276
- process.exit(0);
275
+ const res = await runTuiMenu(resolveRoot());
276
+ process.exit(res?.code || (res?.headless ? 1 : 0));
277
277
  }
278
278
  const { resolveNextStep, renderNextStep } = await import("../src/ops/next-step.mjs");
279
279
  const cwd = process.cwd();
@@ -350,6 +350,7 @@ async function main() {
350
350
  author: { type: "string" },
351
351
  "verify-cmd": { type: "string", short: "v" },
352
352
  verify: { type: "string" },
353
+ oracle: { type: "string" },
353
354
  "dry-run": { type: "boolean", short: "d" },
354
355
  json: { type: "boolean", short: "j" },
355
356
  },
@@ -368,7 +369,7 @@ async function main() {
368
369
  values.title = values.title || envelopeMeta.title;
369
370
  values.role = values.role || envelopeMeta.role;
370
371
  values.tier = values.tier || envelopeMeta.tier;
371
- values["verify-cmd"] = values["verify-cmd"] || values.verify || envelopeMeta.verifyCmd;
372
+ values["verify-cmd"] = values.oracle || values["verify-cmd"] || values.verify || envelopeMeta.verifyCmd;
372
373
  if (values["auto-pr"] === undefined && envelopeMeta.flags?.autoPr !== undefined) {
373
374
  values["auto-pr"] = envelopeMeta.flags.autoPr;
374
375
  }
@@ -413,7 +414,7 @@ async function main() {
413
414
  checkPremise: values["check-premise"] || values.idempotent,
414
415
  goalCheck: values["goal-check"],
415
416
  author: values.author,
416
- verifyCmd: values["verify-cmd"] || values.verify,
417
+ verifyCmd: values.oracle || values["verify-cmd"] || values.verify,
417
418
  };
418
419
 
419
420
  try {
@@ -497,6 +498,7 @@ async function main() {
497
498
  args: args.slice(1),
498
499
  options: {
499
500
  base: { type: "string", short: "b" },
501
+ head: { type: "string" },
500
502
  mode: { type: "string", short: "m", default: "working-tree" },
501
503
  "working-tree": { type: "boolean" },
502
504
  staged: { type: "boolean" },
@@ -532,6 +534,7 @@ async function main() {
532
534
  root,
533
535
  config,
534
536
  base: values.base,
537
+ head: values.head,
535
538
  mode: selectedMode,
536
539
  fix: values.fix,
537
540
  allowProtected: values["allow-protected"],
@@ -1402,24 +1405,29 @@ async function main() {
1402
1405
  } else {
1403
1406
  files = queueEntries.filter((f) => isTaskFile(f, queueDir));
1404
1407
  }
1405
- console.log(`Found ${files.length} queued task(s) in .agent/jules-queue/`);
1406
- if (files.length > 0) {
1407
- const concurrency = values.concurrency ? Number(values.concurrency) : undefined;
1408
- const results = await run(null, {
1409
- root,
1410
- config,
1411
- dag: values.dag,
1412
- concurrency,
1413
- dryRun: values["dry-run"],
1414
- });
1408
+ if (!values.json) {
1409
+ console.log(`Found ${files.length} queued task(s) in .agent/jules-queue/`);
1410
+ }
1411
+ if (files.length === 0) {
1415
1412
  if (values.json) {
1416
- console.log(JSON.stringify(results, null, 2));
1417
- const anyFailed = (results.results || []).some((r) => r && r.ok === false);
1418
- process.exit(anyFailed ? 1 : 0);
1413
+ console.log(JSON.stringify({ ok: true, processed: 0, results: [], dryRun: Boolean(values["dry-run"]) }, null, 2));
1419
1414
  }
1420
- process.exit(reportRunOutcome(results));
1415
+ process.exit(0);
1421
1416
  }
1422
- process.exit(0);
1417
+ const concurrency = values.concurrency ? Number(values.concurrency) : undefined;
1418
+ const results = await run(null, {
1419
+ root,
1420
+ config,
1421
+ dag: values.dag,
1422
+ concurrency,
1423
+ dryRun: values["dry-run"],
1424
+ });
1425
+ if (values.json) {
1426
+ console.log(JSON.stringify(results, null, 2));
1427
+ const anyFailed = (results.results || []).some((r) => r && r.ok === false);
1428
+ process.exit(anyFailed ? 1 : 0);
1429
+ }
1430
+ process.exit(reportRunOutcome(results));
1423
1431
  break;
1424
1432
  }
1425
1433
 
@@ -2031,12 +2039,13 @@ async function main() {
2031
2039
  break;
2032
2040
  }
2033
2041
 
2042
+ case "hub":
2034
2043
  case "menu":
2035
2044
  case "tui":
2036
2045
  case "ui": {
2037
2046
  const { runTuiMenu } = await import("../src/ops/tui-menu.mjs");
2038
- await runTuiMenu(root);
2039
- process.exit(0);
2047
+ const res = await runTuiMenu(root);
2048
+ process.exit(res?.code || (res?.headless ? 1 : 0));
2040
2049
  break;
2041
2050
  }
2042
2051
 
@@ -2195,7 +2204,7 @@ async function main() {
2195
2204
 
2196
2205
  case "task": {
2197
2206
  const subCommand = args[1] || "create";
2198
- if (subCommand === "create") {
2207
+ if (subCommand === "create" || subCommand === "new") {
2199
2208
  const { values, positionals } = parseArgs({
2200
2209
  args: args.slice(2),
2201
2210
  options: {
@@ -2209,6 +2218,9 @@ async function main() {
2209
2218
  "depends-on": { type: "string" },
2210
2219
  verify: { type: "string" },
2211
2220
  "verify-cmd": { type: "string", short: "v" },
2221
+ oracle: { type: "string" },
2222
+ lane: { type: "string" },
2223
+ "risk-lane": { type: "string" },
2212
2224
  "auto-pr": { type: "boolean" },
2213
2225
  "require-plan-approval": { type: "boolean" },
2214
2226
  repoless: { type: "boolean" },
@@ -2232,18 +2244,19 @@ async function main() {
2232
2244
  isTTY: Boolean(process.stdin.isTTY),
2233
2245
  // A title and a prompt together state the whole task; there is
2234
2246
  // nothing left for the wizard to ask.
2235
- fullySpecified: Boolean(values.title && resolvePromptInput(values, positionals)),
2247
+ fullySpecified: Boolean(values.title && resolvePromptInput(values, positionals, root, { allowQueueFallback: false })),
2236
2248
  });
2237
2249
 
2238
2250
  const { runTaskCreateWizard } = await import("../src/wizard-task.mjs");
2239
2251
  const res = await runTaskCreateWizard(root, {
2240
2252
  title: values.title,
2241
- prompt: resolvePromptInput(values, positionals),
2253
+ prompt: resolvePromptInput(values, positionals, root, { allowQueueFallback: false }),
2242
2254
  role: values.role,
2243
2255
  tier: values.tier,
2244
2256
  template: values.template,
2257
+ lane: values.lane || values["risk-lane"],
2245
2258
  dependsOn: values["depends-on"] || values.depends,
2246
- verifyCmd: values["verify-cmd"] || values.verify,
2259
+ verifyCmd: values.oracle || values["verify-cmd"] || values.verify,
2247
2260
  autoPr: values["auto-pr"],
2248
2261
  requirePlanApproval: values["require-plan-approval"],
2249
2262
  repoless: values.repoless,
@@ -2276,6 +2289,7 @@ async function main() {
2276
2289
  json: { type: "boolean", short: "j" },
2277
2290
  verify: { type: "string" },
2278
2291
  "verify-cmd": { type: "string", short: "v" },
2292
+ oracle: { type: "string" },
2279
2293
  "dry-run": { type: "boolean", short: "d" },
2280
2294
  },
2281
2295
  allowPositionals: true,
@@ -2308,7 +2322,7 @@ async function main() {
2308
2322
  process.exit(1);
2309
2323
  }
2310
2324
 
2311
- const envelope = synthesizeWebEnvelope(templateName, {}, { verifyCmd: values["verify-cmd"] || values.verify });
2325
+ const envelope = synthesizeWebEnvelope(templateName, {}, { verifyCmd: values.oracle || values["verify-cmd"] || values.verify });
2312
2326
  if (values.json) {
2313
2327
  console.log(JSON.stringify({ ok: true, ...envelope }, null, 2));
2314
2328
  } else {
@@ -2456,7 +2470,7 @@ async function main() {
2456
2470
 
2457
2471
  process.exit(result.ok ? 0 : 1);
2458
2472
  } else {
2459
- console.error(`Unknown task subcommand '${subCommand}'. Supported: agentctl task create, agentctl task optimize, agentctl task template, agentctl task validate`);
2473
+ console.error(`Unknown task subcommand '${subCommand}'. Supported: agentctl task create (or task new), agentctl task optimize, agentctl task template, agentctl task validate`);
2460
2474
  process.exit(1);
2461
2475
  }
2462
2476
  break;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jules-orchestrator-kit",
3
- "version": "0.75.1",
4
- "description": "Zero-dependency safety gatekeeper, test oracle generator, and multi-agent coordination protocol for autonomous coding agents \u2014 Google Jules, Claude Code, Codex and Gemini CLI.",
3
+ "version": "0.75.3",
4
+ "description": "Zero-dependency safety gatekeeper, test oracle generator, and multi-agent coordination protocol for autonomous coding agents — Google Jules, Claude Code, Codex and Gemini CLI.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/FullThrottle83/jules-orchestrator-kit.git"
@@ -259,6 +259,7 @@ jobs:
259
259
  run: |
260
260
  set -euo pipefail
261
261
  git fetch --no-tags origin "+$HEAD_SHA:refs/pr-head"
262
+ git checkout --detach refs/pr-head
262
263
 
263
264
  - name: Set up Node.js
264
265
  if: steps.pr.outputs.found == 'true'
package/src/engine.mjs CHANGED
@@ -2,7 +2,7 @@ import { loadConfig, resolveTrustedPolicy, normalizePath } from "./config.mjs";
2
2
  import { isTestPath } from "./test-paths.mjs";
3
3
  import { isPlaceholderTestScript, isSrcLayout } from "./stack-detector.mjs";
4
4
  import { checkCollectionFloor } from "./ops/test-collection.mjs";
5
- import { checkScope, scanDiff, scanBinaryPayloads, redactSecrets } from "./security.mjs";
5
+ import { checkScope, scanDiff, scanBinaryPayloads, redactSecrets, hasHighConfidenceSecret } from "./security.mjs";
6
6
  import { changedFiles, diffBytes, diffText, binaryDiffEntries, symlinkChanges, showFromOrigin, runCmd, materializeSnapshot } from "./git.mjs";
7
7
  import { createProvider, ProviderRateLimitError, ProviderUnavailableError } from "./provider.mjs";
8
8
  import { resolveRoutedProvider } from "./router.mjs";
@@ -306,7 +306,7 @@ export async function gate(opts = {}) {
306
306
  let snapshot = { cwd: root, cleanup: () => {}, mode };
307
307
  try {
308
308
  if (mode === "staged" || mode === "committed") {
309
- snapshot = materializeSnapshot(root, mode, base);
309
+ snapshot = materializeSnapshot(root, mode, opts.head || "HEAD");
310
310
  }
311
311
  } catch (snapErr) {
312
312
  phases.push({ phase: "verify", ok: false, error: snapErr.message });
@@ -1482,8 +1482,14 @@ export async function dispatch(task = {}, opts = {}) {
1482
1482
  };
1483
1483
  }
1484
1484
 
1485
+ // Pre-dispatch secret leak prevention (unless explicitly allowed)
1486
+ const rawPrompt = task.prompt || "";
1487
+ if (!opts.allowSecrets && hasHighConfidenceSecret(rawPrompt)) {
1488
+ throw new Error("Pre-Dispatch Secret Leak Blocked: Task prompt contains unredacted high-confidence credentials.");
1489
+ }
1490
+
1485
1491
  // Redact secrets in prompt before dispatching
1486
- let cleanPrompt = redactSecrets(task.prompt || "");
1492
+ let cleanPrompt = redactSecrets(rawPrompt);
1487
1493
 
1488
1494
  // Specialist Role resolution (if role is set and not already present in prompt)
1489
1495
  if (task.role) {
package/src/envelope.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { git, runCmd, resolveBase } from "./git.mjs";
2
- import { checkScope } from "./security.mjs";
2
+ import { checkScope, scanDiff } from "./security.mjs";
3
3
  import { normalizeScope } from "./config.mjs";
4
4
  import { existsSync } from "node:fs";
5
5
  import { resolve, relative, isAbsolute } from "node:path";
@@ -185,6 +185,22 @@ export function validateEnvelope(envelope = {}, opts = {}) {
185
185
  }
186
186
  }
187
187
 
188
+ // 11. Secret Leak Scrubbing Preflight
189
+ const textToScan = [
190
+ typeof envelope.prompt === "string" ? envelope.prompt : "",
191
+ typeof envelope.intent === "string" ? envelope.intent : (envelope.intent?.outcome || ""),
192
+ typeof envelope.instructions === "string" ? envelope.instructions : "",
193
+ ].filter(Boolean).join("\n");
194
+
195
+ if (textToScan && !opts.allowSecrets) {
196
+ const multilineDiff = textToScan.split("\n").map((line) => `+${line}`).join("\n");
197
+ const secretScan = scanDiff(multilineDiff);
198
+ if (!secretScan.ok && secretScan.findings.length > 0) {
199
+ const types = secretScan.findings.map((f) => f.type || "SECRET_DETECTED").join(", ");
200
+ errors.push(`Secret leak detected in envelope prompt/intent (${types}). Scrub credentials before validation.`);
201
+ }
202
+ }
203
+
188
204
  return {
189
205
  ok: errors.length === 0,
190
206
  code: errors.length === 0 ? 0 : 1,
@@ -185,6 +185,9 @@ export const COMMAND_REGISTRY = [
185
185
  { name: "depends", type: "string", description: "Alias for --depends-on" },
186
186
  { name: "verify-cmd", type: "string", description: "Verification command override (-v)" },
187
187
  { name: "verify", type: "string", description: "Alias for --verify-cmd" },
188
+ { name: "oracle", type: "string", description: "Alias for --verify-cmd" },
189
+ { name: "lane", type: "string", description: "Risk lane assignment (green | amber | orange | red)" },
190
+ { name: "risk-lane", type: "string", description: "Alias for --lane" },
188
191
  { name: "auto-pr", type: "boolean", description: "Automatically create GitHub PR upon completion" },
189
192
  { name: "require-plan-approval", type: "boolean", description: "Require approval of agent plan before execution" },
190
193
  { name: "repoless", type: "boolean", description: "Execute in repoless sandbox mode" },
@@ -216,6 +219,7 @@ export const COMMAND_REGISTRY = [
216
219
  { name: "list", type: "boolean", description: "List available task templates (-l)" },
217
220
  { name: "verify-cmd", type: "string", description: "Verification command override (-v)" },
218
221
  { name: "verify", type: "string", description: "Alias for --verify-cmd" },
222
+ { name: "oracle", type: "string", description: "Alias for --verify-cmd" },
219
223
  { name: "dry-run", type: "boolean", description: "Simulate envelope synthesis (-d)" },
220
224
  { name: "json", type: "boolean", description: "Output structured JSON envelope (-j)" },
221
225
  ],
@@ -373,9 +377,10 @@ export const COMMAND_REGISTRY = [
373
377
  risk: "low",
374
378
  interactive: "always",
375
379
  requiresRepository: true,
376
- shortcuts: ["tui", "ui"],
380
+ shortcuts: ["hub", "tui", "ui"],
377
381
  examples: [
378
382
  "agentctl menu",
383
+ "agentctl hub",
379
384
  "agentctl tui",
380
385
  ],
381
386
  flags: [],
@@ -820,6 +825,7 @@ export const COMMAND_REGISTRY = [
820
825
  { name: "author", type: "string", description: "Attribution author for the dispatch" },
821
826
  { name: "verify-cmd", type: "string", description: "Verification command override (-v)" },
822
827
  { name: "verify", type: "string", description: "Alias for --verify-cmd" },
828
+ { name: "oracle", type: "string", description: "Alias for --verify-cmd" },
823
829
  { name: "source", type: "string", description: "Jules repository source identifier (-s)" },
824
830
  { name: "branch", type: "string", description: "Starting branch for task execution (-b)" },
825
831
  { name: "repoless", type: "boolean", description: "Dispatch task in repoless execution mode" },
@@ -27,9 +27,11 @@ export async function runTuiMenu(root = process.cwd(), options = {}) {
27
27
  const stdin = options.stdin || process.stdin;
28
28
  const stdout = options.stdout || process.stdout;
29
29
 
30
- if (!isTTY(stdin) && !options.allowHeadless) {
30
+ const hasCustomStreams = Boolean(options.stdin || options.stdout);
31
+ const isInteractive = isTTY(stdin) && isTTY(stdout) && (!process.env.CI || hasCustomStreams || options.allowInteractive);
32
+ if (!isInteractive && !options.allowHeadless) {
31
33
  stdout.write("Interactive terminal menu requires a TTY terminal. Use 'agentctl --help' for CLI commands.\n");
32
- return { ok: true, headless: true };
34
+ return { ok: true, headless: true, code: 1 };
33
35
  }
34
36
 
35
37
  while (true) {
@@ -49,7 +49,7 @@ export const LOW_CONFIDENCE_PATTERNS = [
49
49
  /Bearer\s+[A-Za-z0-9._~+/-]{10,255}/gi,
50
50
  /Authorization:\s*Bearer\s+[A-Za-z0-9._~+/-]{10,255}/gi,
51
51
  /\bsk_test_[0-9a-zA-Z]{24,99}\b/g,
52
- /(?:api[_-]?key|secret|password|passwd|token|auth[_-]?token)\s*[:=]\s*(?:['"`]([^'"`\n]{8,128})['"`]|([A-Za-z0-9._~+/-]{16,128}))/gi,
52
+ /(?:["'`]|\b)(?:api[_-]?key|secret|password|passwd|token|auth[_-]?token)(?:["'`]|\b)\s*[:=]\s*(?:['"`]([^'"`\n]{8,128})['"`]|([A-Za-z0-9._~+/-]{16,128}))/gi,
53
53
  ];
54
54
 
55
55
  export function shannonEntropy(str) {
@@ -499,7 +499,10 @@ export function hasHighEntropyToken(text = "", file = null) {
499
499
  return false;
500
500
  }
501
501
 
502
- const lines = text.split("\n");
502
+ const sanitizedText = text
503
+ .replace(/<!--\s*JULES_TASK_ENVELOPE:[\s\S]*?-->/gi, " ")
504
+ .replace(/^---\s*[\s\S]*?---\s*/m, " ");
505
+ const lines = sanitizedText.split("\n");
503
506
  for (const rawLine of lines) {
504
507
  const line = stripEntropyNoise(rawLine);
505
508
 
@@ -186,11 +186,14 @@ export function planTaskCreate(root = process.cwd(), inputObj = {}) {
186
186
  if (/[/\\][a-zA-Z0-9_.-]+\.[a-zA-Z0-9]+(:\d+(:\d+)?)?$/.test(clean)) return true;
187
187
  return false;
188
188
  };
189
- const hasHighEntropyToken = rawPrompt
189
+ const promptForEntropy = rawPrompt
190
+ .replace(/<!--\s*JULES_TASK_ENVELOPE:[\s\S]*?-->/gi, " ")
191
+ .replace(/^---\s*[\s\S]*?---\s*/m, " ");
192
+ const hasHighEntropyToken = promptForEntropy
190
193
  .split(/\s+/)
191
194
  .some((token) => !isPathOrUrlToken(token) && token.length >= 20 && shannonEntropy(token) > 4.3);
192
195
  const isShortHighEntropy =
193
- rawPrompt.length <= 120 && !isPathOrUrlToken(rawPrompt.trim()) && shannonEntropy(rawPrompt) > 4.5;
196
+ promptForEntropy.length <= 120 && !isPathOrUrlToken(promptForEntropy.trim()) && shannonEntropy(promptForEntropy) > 4.5;
194
197
  if ((hasHighEntropyToken || isShortHighEntropy) && !inputObj.allowHighEntropy) {
195
198
  secretFindings.push({ id: "HIGH_ENTROPY_PROMPT", line: 1 });
196
199
  }