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 +25 -0
- package/README.md +2 -2
- package/bin/agentctl.mjs +45 -31
- package/package.json +2 -2
- package/src/ci-templates.mjs +1 -0
- package/src/engine.mjs +9 -3
- package/src/envelope.mjs +17 -1
- package/src/ops/command-registry.mjs +7 -1
- package/src/ops/tui-menu.mjs +4 -2
- package/src/secret-scanner.mjs +5 -2
- package/src/wizard-task.mjs +5 -2
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.
|
|
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 **
|
|
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
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
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(
|
|
1415
|
+
process.exit(0);
|
|
1421
1416
|
}
|
|
1422
|
-
|
|
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.
|
|
4
|
-
"description": "Zero-dependency safety gatekeeper, test oracle generator, and multi-agent coordination protocol for autonomous coding agents
|
|
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"
|
package/src/ci-templates.mjs
CHANGED
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,
|
|
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(
|
|
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" },
|
package/src/ops/tui-menu.mjs
CHANGED
|
@@ -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
|
-
|
|
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) {
|
package/src/secret-scanner.mjs
CHANGED
|
@@ -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
|
|
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
|
|
package/src/wizard-task.mjs
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
}
|