jules-orchestrator-kit 0.73.1 → 0.74.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.
- package/CHANGELOG.md +10 -0
- package/README.md +25 -24
- package/bin/agentctl.mjs +96 -43
- package/bin/init.js +10 -13
- package/package.json +1 -1
- package/scripts/validate-envelope.mjs +23 -4
- package/src/dag-engine.mjs +14 -14
- package/src/engine.mjs +1 -0
- package/src/envelope.mjs +414 -13
- package/src/ops/command-registry.mjs +11 -17
- package/src/role-resolver.mjs +23 -16
- package/src/scaffold.mjs +69 -2
- package/src/wizard-init.mjs +16 -7
- package/src/wizard-task.mjs +123 -5
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.74.0] - 2026-09-19
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Native `agentctl.task/v1` Frontmatter Specification & Zero-Dependency Parser (`src/envelope.mjs`, `scripts/validate-envelope.mjs`)**: Added canonical YAML frontmatter envelope support for task files (`.md`) without third-party dependencies. Reconciles `scope.allow`, `scope.deny`, `verification.commands`, `invariants`, `mcp_directives`, and `flags` with 100% backward compatibility for legacy HTML comments (`<!-- JULES_TASK_ENVELOPE: ... -->`).
|
|
14
|
+
- **Taxonomy Delegation Lanes (Green / Amber / Orange / Red) (`src/envelope.mjs`, `src/wizard-task.mjs`)**: Formulated formal risk lane delegation. Red tasks are rejected at validation; Orange tasks warn for external execution only; Amber tasks allow protected path changes (e.g. dependency upgrades in `package.json`, migrations, auth) under explicit plan approval (`requirePlanApproval: true`). Green tasks prevent unapproved protected scope mutations.
|
|
15
|
+
- **Circuit Breaker & Verification Contract in Envelope (`src/envelope.mjs`)**: Added frontmatter declarations for `circuitBreaker` (`max_attempts`, `max_diff_lines`, `stop_if_same_failure_repeats`) and `verification` metadata (`require_nonzero_test_count`, `trusted_base`), alongside `constraints` alias support.
|
|
16
|
+
- **Stack Invariant & MCP Directive Ingestion (`src/wizard-task.mjs`)**: Automatically infers runtime constraints (Zero-JS for Astro, workerd edge runtime constraints for Cloudflare Wrangler) and injects mandatory pre-execution documentation lookup directives into task instructions.
|
|
17
|
+
- **Dependency Upgrade Scope Harmonization (`src/wizard-task.mjs`)**: Updated `buildGuardrailFooter` to exclude explicitly authorized paths (`opts.allowedPaths`) from forbidden path warnings, eliminating conflicting instructions for dependency upgrade workloads.
|
|
18
|
+
- **Diff Payload Governor Branch Base Comparison (`src/wizard-task.mjs`)**: Calculated diff payload sizes against `git diff origin/${baseBranch}...HEAD | wc -c` instead of local uncommitted diffs.
|
|
19
|
+
|
|
10
20
|
## [0.73.1] - 2026-09-17
|
|
11
21
|
|
|
12
22
|
### Changed
|
package/README.md
CHANGED
|
@@ -12,11 +12,12 @@ Use the kit to describe a scoped coding task, send it to Google Jules or an
|
|
|
12
12
|
installed Claude Code, Codex or Gemini CLI, and verify the resulting changes.
|
|
13
13
|
You can also run local checks without connecting an agent provider.
|
|
14
14
|
|
|
15
|
-
**Dispatch and
|
|
16
|
-
configured checks
|
|
17
|
-
|
|
15
|
+
**Dispatch, verification and repair are explicit.** Dispatch sends the task;
|
|
16
|
+
`gate` runs configured checks without mutating the working tree. Use
|
|
17
|
+
`agentctl repair` explicitly for repair workflows. Provider output and passing
|
|
18
|
+
checks still need review before merging.
|
|
18
19
|
|
|
19
|
-
The current release is **v0.
|
|
20
|
+
The current release is **v0.74.0**, a pre-1.0 release. A long-term stability policy is a
|
|
20
21
|
[v1.0 goal](https://github.com/FullThrottle83/jules-orchestrator-kit/blob/main/ROADMAP_V1.md).
|
|
21
22
|
|
|
22
23
|
## Quickstart
|
|
@@ -32,9 +33,16 @@ npx jules-orchestrator-kit init
|
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
The wizard detects the project and asks about provider and verification settings.
|
|
35
|
-
Use `init --yes` to accept defaults.
|
|
36
|
-
|
|
37
|
-
configuration and diff, especially the test
|
|
36
|
+
Use `init --yes` to accept defaults. By default it writes only the canonical
|
|
37
|
+
`.agent/config.yml` plus runtime-state entries in `.gitignore` when they are
|
|
38
|
+
missing. Inspect the generated configuration and diff, especially the test
|
|
39
|
+
command and protected paths. Use `init --dry-run` to preview the exact writes
|
|
40
|
+
without changing the repository.
|
|
41
|
+
|
|
42
|
+
The historical full scaffold (AGENTS.md, specialist prompts, rules, workflows and
|
|
43
|
+
contract templates) remains available through `agentctl init --force` and the
|
|
44
|
+
legacy `jules-init` entry point during the 0.x migration window; it is no longer
|
|
45
|
+
default-owned by `agentctl init`.
|
|
38
46
|
|
|
39
47
|
```bash
|
|
40
48
|
git diff
|
|
@@ -43,9 +51,9 @@ git status --short
|
|
|
43
51
|
|
|
44
52
|
Stage the generated files you reviewed, then commit them. The committed
|
|
45
53
|
configuration establishes the trusted base policy used by verification. On an
|
|
46
|
-
already initialized repository, back up and review `.agent/config.yml`
|
|
47
|
-
`.agent/jules.yml`
|
|
48
|
-
|
|
54
|
+
already initialized repository, back up and review `.agent/config.yml` before
|
|
55
|
+
rerunning `init`. Existing legacy `.agent/jules.yml` files are left untouched
|
|
56
|
+
by the default path. `--force` deliberately opts back into the legacy full scaffold.
|
|
49
57
|
|
|
50
58
|
### 2. Check provider readiness
|
|
51
59
|
|
|
@@ -107,7 +115,7 @@ For direct `agentctl` commands, install globally with
|
|
|
107
115
|
| Create a scoped task | `agentctl task create` |
|
|
108
116
|
| Preview queued work | `agentctl queue --dry-run` |
|
|
109
117
|
| Check changes locally | `agentctl gate` |
|
|
110
|
-
|
|
|
118
|
+
| Start an explicit repair workflow | `agentctl repair --input "<failure>" --task` |
|
|
111
119
|
| Diagnose setup | `agentctl doctor` |
|
|
112
120
|
| Inspect a command's flags | `agentctl help <command>` |
|
|
113
121
|
|
|
@@ -166,7 +174,7 @@ npm run package-integrity
|
|
|
166
174
|
npm run guard-reach
|
|
167
175
|
```
|
|
168
176
|
|
|
169
|
-
The recorded baseline is **
|
|
177
|
+
The recorded baseline is **1553 unit tests across 204 suites**. Doc-sync compares
|
|
170
178
|
that count with an actual run. Counts do not establish correctness for every
|
|
171
179
|
provider or project. See
|
|
172
180
|
[contributing](https://github.com/FullThrottle83/jules-orchestrator-kit/blob/main/CONTRIBUTING.md)
|
|
@@ -186,19 +194,12 @@ for the review process.
|
|
|
186
194
|
First identify which files setup created and which files already belonged to your
|
|
187
195
|
project. For shared files, remove only the kit's additions using Git history.
|
|
188
196
|
|
|
189
|
-
For
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
git rm -rf --ignore-unmatch .agent AGENTS.md SPEC.md CONSTRAINTS.md DESIGN.md \
|
|
195
|
-
.github/workflows/agent-gate.yml .gitlab-ci.agent-gate.yml .cursor/rules/jules.mdc
|
|
196
|
-
rm -rf .agent .agentctl
|
|
197
|
-
npm uninstall -g jules-orchestrator-kit
|
|
198
|
-
```
|
|
197
|
+
For the default minimal setup, remove `.agent/config.yml` and the kit's
|
|
198
|
+
runtime-state block from `.gitignore`. Repositories that previously used the
|
|
199
|
+
legacy full scaffold may also contain AGENTS.md, prompts, rules, workflows and
|
|
200
|
+
contract files; remove those only after confirming ownership.
|
|
199
201
|
|
|
200
|
-
|
|
201
|
-
See the uninstall guide for the complete inventory.
|
|
202
|
+
See the uninstall guide for the complete inventory and legacy cleanup steps.
|
|
202
203
|
|
|
203
204
|
## Limitations and attribution
|
|
204
205
|
|
package/bin/agentctl.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { readFileSync, existsSync, readdirSync, statSync, renameSync, mkdirSync } from "node:fs";
|
|
5
|
-
import { join, resolve } from "node:path";
|
|
5
|
+
import { join, resolve, relative } from "node:path";
|
|
6
6
|
import { applyEnvAliases } from "../src/env-aliases.mjs";
|
|
7
7
|
import { selectFailureOutput } from "../src/ops/verify-output.mjs";
|
|
8
8
|
import { loadConfig, resolveRoot, detectStack, bootstrapZeroTestRepo } from "../src/config.mjs";
|
|
@@ -22,7 +22,18 @@ import { COMMAND_REGISTRY } from "../src/ops/command-registry.mjs";
|
|
|
22
22
|
applyEnvAliases(process.env);
|
|
23
23
|
|
|
24
24
|
const args = process.argv.slice(2);
|
|
25
|
-
const
|
|
25
|
+
const requestedCommand = args[0] || "";
|
|
26
|
+
const gateCommands = new Set(["gate", "check", "audit"]);
|
|
27
|
+
|
|
28
|
+
if (gateCommands.has(requestedCommand) && args.includes("--fix")) {
|
|
29
|
+
console.error("Error: `agentctl gate` is non-mutating; `--fix` no longer dispatches automated repairs.");
|
|
30
|
+
console.error("Run the gate normally, then use `agentctl repair` explicitly with the failure trace you want repaired.");
|
|
31
|
+
process.exit(2);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// `repair` is the canonical spelling; `fix` remains a 0.x compatibility
|
|
35
|
+
// alias. Both route through the same existing implementation below.
|
|
36
|
+
const command = requestedCommand;
|
|
26
37
|
|
|
27
38
|
export const VERSION = KIT_VERSION;
|
|
28
39
|
|
|
@@ -294,8 +305,13 @@ async function main() {
|
|
|
294
305
|
}
|
|
295
306
|
|
|
296
307
|
const root = resolveRoot();
|
|
297
|
-
|
|
298
|
-
|
|
308
|
+
// Init is a configuration boundary, not an operational maintenance command.
|
|
309
|
+
// In particular, --dry-run must not create .agent/ indirectly by reaping
|
|
310
|
+
// journal intents or mutex directories before init itself gets control.
|
|
311
|
+
if (command !== "init") {
|
|
312
|
+
reapOrphanedIntents(root);
|
|
313
|
+
reapStaleMutexDirs(root);
|
|
314
|
+
}
|
|
299
315
|
const config = loadConfig(root);
|
|
300
316
|
|
|
301
317
|
switch (command) {
|
|
@@ -361,7 +377,7 @@ async function main() {
|
|
|
361
377
|
console.error(
|
|
362
378
|
`Error: Unknown agent role '${values.role}'. Expected matching prompt file in .agent/prompts/ (e.g. Auditor, Performance, Security, Hygiene, Testing).`
|
|
363
379
|
);
|
|
364
|
-
console.error(`
|
|
380
|
+
console.error(` Use a canonical shipped role name or add a repository override under .agent/prompts/.`);
|
|
365
381
|
process.exit(1);
|
|
366
382
|
}
|
|
367
383
|
}
|
|
@@ -676,7 +692,7 @@ async function main() {
|
|
|
676
692
|
} else if (failedPhase === "verify" || failedPhase === "evidence") {
|
|
677
693
|
console.log(`💡 Remediation Hint (Exit ${res.code} Verification Failed):`);
|
|
678
694
|
console.log(` • The stage above exited non-zero. Reproduce it locally, then re-run the gate.`);
|
|
679
|
-
console.log(` • To
|
|
695
|
+
console.log(` • To start an explicit repair workflow, pipe the failing command's output to: agentctl repair\n`);
|
|
680
696
|
} else if (res.code === 3) {
|
|
681
697
|
// The same violation has two very different causes. Right after
|
|
682
698
|
// `init`, every offending path is a file the tool itself just wrote
|
|
@@ -965,6 +981,7 @@ async function main() {
|
|
|
965
981
|
break;
|
|
966
982
|
}
|
|
967
983
|
|
|
984
|
+
case "repair":
|
|
968
985
|
case "fix": {
|
|
969
986
|
const { repair, planTaskCreate, resolveRoot, redactSecrets } = await import("../index.mjs");
|
|
970
987
|
const { values, positionals } = parseArgs({
|
|
@@ -996,7 +1013,7 @@ async function main() {
|
|
|
996
1013
|
}
|
|
997
1014
|
|
|
998
1015
|
if (!errorInput.trim()) {
|
|
999
|
-
console.error("❌ Error: No error log or failure input provided. Pipe stdout/stderr via `npm test 2>&1 | agentctl
|
|
1016
|
+
console.error("❌ Error: No error log or failure input provided. Pipe stdout/stderr via `npm test 2>&1 | agentctl repair` or provide --file/--input.");
|
|
1000
1017
|
process.exit(1);
|
|
1001
1018
|
}
|
|
1002
1019
|
|
|
@@ -1957,19 +1974,54 @@ async function main() {
|
|
|
1957
1974
|
provider: values.provider,
|
|
1958
1975
|
profile: values.profile,
|
|
1959
1976
|
allowDefaults: true,
|
|
1977
|
+
dryRun: values["dry-run"],
|
|
1978
|
+
// --force is retained as the explicit 0.x compatibility path: it
|
|
1979
|
+
// restores the legacy Jules manifest and full repository scaffold.
|
|
1980
|
+
legacyManifest: values.force,
|
|
1981
|
+
// JSON mode is a protocol surface: progress spinners must not prefix
|
|
1982
|
+
// the payload with human-readable status lines.
|
|
1983
|
+
stdout: values.json ? { write() {} } : process.stdout,
|
|
1960
1984
|
});
|
|
1961
1985
|
|
|
1962
|
-
//
|
|
1963
|
-
//
|
|
1964
|
-
//
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1986
|
+
// Default init deliberately owns only the canonical config plus the
|
|
1987
|
+
// runtime-state ignore block. The old full scaffold is opt-in via
|
|
1988
|
+
// --force (and remains available through the shipped jules-init binary).
|
|
1989
|
+
const {
|
|
1990
|
+
ensureGitignore,
|
|
1991
|
+
planGitignoreEntries,
|
|
1992
|
+
planScaffoldRepoAssets,
|
|
1993
|
+
scaffoldRepoAssets,
|
|
1994
|
+
} = await import("../src/scaffold.mjs");
|
|
1995
|
+
const plannedGitignore = planGitignoreEntries(root);
|
|
1996
|
+
const legacyPlan = values.force ? planScaffoldRepoAssets(root, { force: true }) : { created: [], gitignore: plannedGitignore };
|
|
1997
|
+
const scaffold =
|
|
1998
|
+
values.force && !values["dry-run"]
|
|
1999
|
+
? scaffoldRepoAssets(root, { force: true })
|
|
2000
|
+
: { created: legacyPlan.created, gitignore: plannedGitignore };
|
|
2001
|
+
const gitignore =
|
|
2002
|
+
values["dry-run"]
|
|
2003
|
+
? plannedGitignore
|
|
2004
|
+
: values.force
|
|
2005
|
+
? scaffold.gitignore
|
|
2006
|
+
: ensureGitignore(root);
|
|
2007
|
+
const writes = [
|
|
2008
|
+
...res.writes.map((p) => (relative(root, p) || p).replaceAll("\\", "/")),
|
|
2009
|
+
...legacyPlan.created,
|
|
2010
|
+
...(plannedGitignore.length > 0 ? [".gitignore"] : []),
|
|
2011
|
+
].filter((p, index, all) => all.indexOf(p) === index);
|
|
1968
2012
|
|
|
1969
2013
|
if (values.json) {
|
|
1970
|
-
console.log(JSON.stringify({ ...res,
|
|
2014
|
+
console.log(JSON.stringify({ ...res, writes, gitignore }, null, 2));
|
|
1971
2015
|
} else {
|
|
1972
|
-
console.log(
|
|
2016
|
+
console.log(
|
|
2017
|
+
values["dry-run"]
|
|
2018
|
+
? "🧪 Dry run — no files written."
|
|
2019
|
+
: `✅ Onboarding complete! Manifest generated at ${res.configPath}`
|
|
2020
|
+
);
|
|
2021
|
+
if (values["dry-run"]) {
|
|
2022
|
+
console.log(" Would write:");
|
|
2023
|
+
for (const path of writes) console.log(` - ${path}`);
|
|
2024
|
+
}
|
|
1973
2025
|
console.log(` Tier: ${res.plan.tier.toUpperCase()} (${res.plan.limits.concurrency} worker(s), ${res.plan.limits.daily_tasks} daily tasks)`);
|
|
1974
2026
|
{
|
|
1975
2027
|
const { probeProvider } = await import("../src/provider-readiness.mjs");
|
|
@@ -1988,34 +2040,35 @@ async function main() {
|
|
|
1988
2040
|
console.log(` Verification Test Command : None detected (run "agentctl bootstrap" to create a test oracle)`);
|
|
1989
2041
|
}
|
|
1990
2042
|
console.log(` Active Presets : ${res.plan.presets.join(", ")}`);
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
.filter((
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2043
|
+
if (values.force) {
|
|
2044
|
+
const verb = values["dry-run"] ? "Would scaffold (legacy)" : "Scaffolded (legacy)";
|
|
2045
|
+
for (const item of legacyPlan.created) {
|
|
2046
|
+
console.log(` ${verb.padEnd(26)}: ${item}`);
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
if (!values["dry-run"] && gitignore.length > 0) {
|
|
2050
|
+
console.log(` Ignored runtime state : ${gitignore.length} entries added to .gitignore`);
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
if (!values["dry-run"]) {
|
|
2054
|
+
// A fresh `npm install`/`npm init -y` may have created package
|
|
2055
|
+
// manifests the scope rules protect. Include only files that really
|
|
2056
|
+
// exist; minimal init itself owns .agent/config.yml and, when needed,
|
|
2057
|
+
// the .gitignore runtime-state block.
|
|
2058
|
+
const { addableOnboardingArtifacts } = await import("../src/git.mjs");
|
|
2059
|
+
const filesToAdd = [
|
|
2060
|
+
".agent/config.yml",
|
|
2061
|
+
...(values.force ? [".agent/jules.yml", ...legacyPlan.created] : []),
|
|
2062
|
+
...addableOnboardingArtifacts(root),
|
|
2063
|
+
".gitignore",
|
|
2064
|
+
].filter((p, index, all) => all.indexOf(p) === index && existsSync(join(root, p)));
|
|
2065
|
+
console.log(`\n Commit the config so the gate does not read it as an agent edit:`);
|
|
2066
|
+
console.log(` git add ${filesToAdd.join(" ")} && git commit -m "chore: add agent config"`);
|
|
2067
|
+
|
|
2068
|
+
const { resolveNextStep, renderNextStep } = await import("../src/ops/next-step.mjs");
|
|
2069
|
+
const next = resolveNextStep(root);
|
|
2070
|
+
console.log(renderNextStep({ version: VERSION, root, next, budgetLine: "" }));
|
|
2071
|
+
}
|
|
2019
2072
|
}
|
|
2020
2073
|
process.exit(0);
|
|
2021
2074
|
break;
|
package/bin/init.js
CHANGED
|
@@ -40,12 +40,14 @@ try {
|
|
|
40
40
|
|
|
41
41
|
if (isHelp) {
|
|
42
42
|
console.log(`
|
|
43
|
-
Google Jules Orchestration Kit -
|
|
43
|
+
Google Jules Orchestration Kit - Legacy Full Scaffold
|
|
44
44
|
|
|
45
45
|
Usage:
|
|
46
|
-
npx jules-orchestrator-kit [options]
|
|
47
46
|
npx jules-init [options]
|
|
48
47
|
|
|
48
|
+
For the minimal canonical setup, use:
|
|
49
|
+
npx jules-orchestrator-kit init
|
|
50
|
+
|
|
49
51
|
Options:
|
|
50
52
|
-f, --force Overwrite existing AGENTS.md, .agent/jules.yml, and orchestration scripts.
|
|
51
53
|
-i, --interactive Launch interactive wizard to prompt for repository and branch configuration.
|
|
@@ -119,10 +121,9 @@ if (detected.testCmd || detected.buildCmd) {
|
|
|
119
121
|
console.log(` - Build Command: ${detected.buildCmd || "(none)"}`);
|
|
120
122
|
}
|
|
121
123
|
|
|
122
|
-
// 2-3.
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
// quickstart pointing at the one that scaffolded less.
|
|
124
|
+
// 2-3. Legacy full scaffold: AGENTS.md, .agent/ role prompts, rules and
|
|
125
|
+
// workflows. The canonical `agentctl init` path is intentionally smaller now;
|
|
126
|
+
// this entry point remains for 0.x repositories that still want the full bundle.
|
|
126
127
|
const { scaffoldRepoAssets } = await import("../src/scaffold.mjs");
|
|
127
128
|
const scaffolded = scaffoldRepoAssets(targetDir, { force: isForce });
|
|
128
129
|
for (const item of scaffolded.created) {
|
|
@@ -133,11 +134,8 @@ const agentDir = path.join(targetDir, ".agent");
|
|
|
133
134
|
|
|
134
135
|
// Scaffold the manifest pair.
|
|
135
136
|
//
|
|
136
|
-
// This entry point
|
|
137
|
-
//
|
|
138
|
-
// which of the two scaffolders you happened to run decided whether the
|
|
139
|
-
// repository had a provider, a tier and a verification profile at all. Both
|
|
140
|
-
// now go through `planInit`.
|
|
137
|
+
// This compatibility entry point still writes both manifests, but derives them
|
|
138
|
+
// from the same `planInit` model as the canonical path so values cannot drift.
|
|
141
139
|
const { planInit } = await import("../src/wizard-init.mjs");
|
|
142
140
|
const initPlan = planInit(targetDir, {
|
|
143
141
|
testCmd: detected.testCmd,
|
|
@@ -226,8 +224,7 @@ if (fs.existsSync(targetPkgPath) && targetDir !== kitRoot) {
|
|
|
226
224
|
}
|
|
227
225
|
}
|
|
228
226
|
|
|
229
|
-
// 5b.
|
|
230
|
-
// two entry points cannot disagree about which runtime paths stay untracked.
|
|
227
|
+
// 5b. Reuse the same runtime ignore policy as canonical init.
|
|
231
228
|
if (scaffolded.gitignore.length > 0) {
|
|
232
229
|
console.log(`✅ Added ${scaffolded.gitignore.length} runtime state entries to .gitignore`);
|
|
233
230
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jules-orchestrator-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.0",
|
|
4
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.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { readFileSync, existsSync } from "node:fs";
|
|
4
|
-
import { validateEnvelope } from "../src/envelope.mjs";
|
|
4
|
+
import { validateEnvelope, parseEnvelopeHeader } from "../src/envelope.mjs";
|
|
5
5
|
|
|
6
6
|
const args = process.argv.slice(2);
|
|
7
7
|
const envelopeFile = args[0];
|
|
8
8
|
|
|
9
9
|
if (!envelopeFile) {
|
|
10
|
-
console.log("Usage: node scripts/validate-envelope.mjs <path-to-envelope.json>");
|
|
10
|
+
console.log("Usage: node scripts/validate-envelope.mjs <path-to-envelope.json|path-to-task.md>");
|
|
11
11
|
process.exit(1);
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -18,7 +18,26 @@ if (!existsSync(envelopeFile)) {
|
|
|
18
18
|
|
|
19
19
|
try {
|
|
20
20
|
const content = readFileSync(envelopeFile, "utf-8");
|
|
21
|
-
|
|
21
|
+
let payload = null;
|
|
22
|
+
if (envelopeFile.endsWith(".json")) {
|
|
23
|
+
payload = JSON.parse(content);
|
|
24
|
+
} else {
|
|
25
|
+
payload = parseEnvelopeHeader(content);
|
|
26
|
+
if (!payload) {
|
|
27
|
+
try {
|
|
28
|
+
payload = JSON.parse(content);
|
|
29
|
+
} catch {
|
|
30
|
+
payload = null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!payload || typeof payload !== "object") {
|
|
36
|
+
console.error("❌ TASK ENVELOPE PREMISE VALIDATION FAILED:");
|
|
37
|
+
console.error(" - File does not contain a valid JSON payload or task envelope frontmatter.");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
const res = validateEnvelope(payload);
|
|
23
42
|
|
|
24
43
|
if (!res.ok) {
|
|
@@ -39,6 +58,6 @@ try {
|
|
|
39
58
|
console.log("✅ Task envelope validated successfully.");
|
|
40
59
|
process.exit(0);
|
|
41
60
|
} catch (err) {
|
|
42
|
-
console.error(`❌ Invalid
|
|
61
|
+
console.error(`❌ Invalid envelope or execution error: ${err.message}`);
|
|
43
62
|
process.exit(1);
|
|
44
63
|
}
|
package/src/dag-engine.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { readFileSync, existsSync } from "node:fs";
|
|
3
3
|
import { appendTelemetry } from "./telemetry.mjs";
|
|
4
|
+
import { parseEnvelopeHeader } from "./envelope.mjs";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Custom error thrown when a circular dependency is detected in the DAG.
|
|
@@ -495,20 +496,19 @@ export async function executeQueueDag(root = process.cwd(), options = {}) {
|
|
|
495
496
|
|
|
496
497
|
let targetFiles = [];
|
|
497
498
|
|
|
498
|
-
// Check envelope header
|
|
499
|
-
const
|
|
500
|
-
if (
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
} catch (_) {}
|
|
499
|
+
// Check envelope header (supports agentctl.task/v1 YAML frontmatter and legacy HTML comment)
|
|
500
|
+
const header = parseEnvelopeHeader(content);
|
|
501
|
+
if (header) {
|
|
502
|
+
if (header.id || header.taskId) taskId = header.id || header.taskId;
|
|
503
|
+
if (header.title) title = header.title;
|
|
504
|
+
if (header.role) role = header.role;
|
|
505
|
+
if (header.tier) tier = header.tier;
|
|
506
|
+
if (Array.isArray(header.targetFiles)) targetFiles = header.targetFiles;
|
|
507
|
+
else if (Array.isArray(header.referenced_paths)) targetFiles = header.referenced_paths;
|
|
508
|
+
else if (Array.isArray(header.allowed_paths)) targetFiles = header.allowed_paths;
|
|
509
|
+
else if (header.scope && Array.isArray(header.scope.allow)) targetFiles = header.scope.allow;
|
|
510
|
+
if (Array.isArray(header.dependsOn)) dependsOn = header.dependsOn;
|
|
511
|
+
else if (typeof header.dependsOn === "string") dependsOn = header.dependsOn.split(",").map((s) => s.trim()).filter(Boolean);
|
|
512
512
|
} else if (file.endsWith(".json")) {
|
|
513
513
|
try {
|
|
514
514
|
const parsed = JSON.parse(content);
|
package/src/engine.mjs
CHANGED
|
@@ -143,6 +143,7 @@ export function fingerprintFailureState(failure = {}, root = process.cwd()) {
|
|
|
143
143
|
* FAILS CLOSED ON GIT OR CONFIG ERRORS.
|
|
144
144
|
*/
|
|
145
145
|
export async function gate(opts = {}) {
|
|
146
|
+
opts = opts && typeof opts === "object" ? { ...opts, fix: false } : { fix: false };
|
|
146
147
|
const root = opts.root || process.cwd();
|
|
147
148
|
const mode = opts.mode || (opts.workingTree ? "working-tree" : (process.env.JULES_GATE_MODE || "working-tree"));
|
|
148
149
|
const config = opts.config || (mode === "working-tree" ? loadConfig(root) : null);
|