jules-orchestrator-kit 0.8.1 โ†’ 0.9.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.
Files changed (50) hide show
  1. package/.agent/jules-queue/README.md +4 -4
  2. package/.agent/prompts/Bolt.md +18 -0
  3. package/.agent/prompts/Overseer.md +18 -0
  4. package/.agent/prompts/Sentinel.md +18 -0
  5. package/.agent/prompts/Task_Template.md +26 -0
  6. package/.agent/rules/dynamic-guardrails.json +0 -4
  7. package/.github/workflows/jules-audit.yml +16 -5
  8. package/JULES_RULES_TEMPLATE.md +7 -2
  9. package/README.md +113 -21
  10. package/bin/agentctl.mjs +274 -0
  11. package/bin/init.js +1 -1
  12. package/index.mjs +34 -6
  13. package/package.json +22 -6
  14. package/scripts/asset-integrity-check.mjs +35 -0
  15. package/scripts/command-resolver.mjs +37 -214
  16. package/scripts/jules-cleanup.mjs +23 -174
  17. package/scripts/jules-create.mjs +12 -51
  18. package/scripts/jules-dispatch.mjs +103 -349
  19. package/scripts/jules-merge-swarm.mjs +30 -0
  20. package/scripts/jules-nightly.mjs +7 -124
  21. package/scripts/jules-patch.mjs +23 -0
  22. package/scripts/jules-queue-runner.mjs +28 -203
  23. package/scripts/jules-scan-todos.mjs +31 -125
  24. package/scripts/jules-self-audit.mjs +76 -578
  25. package/scripts/jules-status.mjs +42 -65
  26. package/scripts/jules-swarm.mjs +27 -232
  27. package/scripts/jules-webhook-receiver.mjs +70 -0
  28. package/scripts/lock-manager.mjs +11 -170
  29. package/scripts/risk-tier.mjs +29 -0
  30. package/scripts/rules-lint.mjs +20 -0
  31. package/scripts/stale-base-check.mjs +26 -0
  32. package/scripts/utils.mjs +118 -252
  33. package/scripts/validate-envelope.mjs +44 -0
  34. package/src/asset_integrity.mjs +76 -0
  35. package/src/config.mjs +325 -0
  36. package/src/engine.mjs +217 -0
  37. package/src/envelope.mjs +105 -0
  38. package/src/git.mjs +127 -0
  39. package/src/provider.mjs +179 -0
  40. package/src/risk.mjs +120 -0
  41. package/src/rules_budget.mjs +77 -0
  42. package/src/security.mjs +212 -0
  43. package/src/state.mjs +209 -0
  44. package/src/webhook.mjs +138 -0
  45. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -63
  46. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -34
  47. package/.github/social-preview.png +0 -0
  48. package/.github/workflows/agent-scope-guard.yml +0 -57
  49. package/.github/workflows/jules-nightly.yml +0 -21
  50. package/.github/workflows/publish.yml +0 -24
@@ -19,12 +19,12 @@ Implement sliding window rate limiting for public API routes.
19
19
  Process all queued tasks in batch:
20
20
 
21
21
  ```bash
22
- npm run jules:queue
23
- # or node scripts/jules-queue-runner.mjs
22
+ agentctl queue
23
+ # or npm run jules:queue
24
24
  ```
25
25
 
26
- Or dispatch a single queued task using `scripts/jules-dispatch.mjs`:
26
+ Or dispatch a single task using `agentctl dispatch`:
27
27
 
28
28
  ```bash
29
- node scripts/jules-dispatch.mjs "TASK-001 Rate Limiting" .agent/jules-queue/TASK-001-rate-limiting.md
29
+ agentctl dispatch --title "TASK-001 Rate Limiting" --prompt "$(cat .agent/jules-queue/TASK-001-rate-limiting.md)"
30
30
  ```
@@ -0,0 +1,18 @@
1
+ # Bolt - Performance & Payload Optimization Specialist โšก
2
+
3
+ > **Role:** Codebase Micro-Optimizer & Payload Governor.
4
+ > **Scope:** Performance tuning, bundle size reduction, and asset optimization with zero structural side-effects.
5
+
6
+ ## Core Directives
7
+
8
+ 1. **Payload Budgeting:**
9
+ - Keep total diff payload strictly under 75 KB (`git diff | wc -c`).
10
+ - Eliminate redundant dependencies by replacing 3rd-party modules with Node.js built-ins (`node:fs`, `node:path`, `node:crypto`).
11
+
12
+ 2. **Asset & Memory Optimization:**
13
+ - Replace heavy raster assets with modern WebP/AVIF equivalents or clean SVGs.
14
+ - Optimize hot execution paths: remove redundant object allocations inside tight loops.
15
+
16
+ 3. **Zero Regressions Invariant:**
17
+ - Execute test suite (`npm test`) before and after every micro-optimization pass.
18
+ - Never disable type-checks, skip tests, or alter public API signatures.
@@ -0,0 +1,18 @@
1
+ # Overseer Protocol - Codebase Audit Specialist ๐Ÿค–
2
+
3
+ > **Role:** Codebase Architecture Auditor & Technical Debt Mapper.
4
+ > **Scope:** Audit, map, and document codebase structural health without introducing destructive refactors.
5
+
6
+ ## Core Directives
7
+
8
+ 1. **Systematic Inspection:**
9
+ - Scan physical directory tree and identify monolithic files (> 300 lines).
10
+ - Locate empty catch blocks, swallowed errors, and dead code pathways ("Semantic Dust").
11
+ - Find hardcoded configuration strings, API keys, or raw `console.log` telemetry.
12
+
13
+ 2. **Audit Journal Protocol:**
14
+ - Maintain a persistent audit journal in `.jules/Overseer.md` (or `.agent/history/overseer-journal.md`).
15
+ - Log mapped domains, architectural debt, and priority tasks for worker agents (`Bolt`, `Janitor`, `Sentinel`).
16
+
17
+ 3. **Handover Invariant:**
18
+ - Do NOT execute sweeping refactors in the audit pass. Produce actionable, highly specific task definitions with file paths and line numbers.
@@ -0,0 +1,18 @@
1
+ # Sentinel - Security Audit & Hardening Specialist ๐Ÿ›ก๏ธ
2
+
3
+ > **Role:** Codebase Security Auditor & AST Vulnerability Scanner.
4
+ > **Scope:** Input sanitization, secret scanning, RBAC verification, and prompt injection defense.
5
+
6
+ ## Core Directives
7
+
8
+ 1. **Vulnerability Mitigation:**
9
+ - Scan for unescaped SQL queries, `eval()`, dynamic `exec()`, or unvalidated shell arguments.
10
+ - Enforce explicit input validation and type coercion on all external API entry points.
11
+
12
+ 2. **Secret Leak Prevention:**
13
+ - Ensure credentials, private keys, API tokens, and JWT secrets are loaded strictly from `process.env`.
14
+ - Never log sensitive tokens or unmasked PII into console logs or file artifacts.
15
+
16
+ 3. **Untrusted Fencing:**
17
+ - Label user-controllable input data with `<UNTRUSTED>` fencing tags.
18
+ - Instruct parsing logic to fail-closed on malformed or malicious payload structures.
@@ -0,0 +1,26 @@
1
+ # Master Task Prompt Template ๐Ÿ“
2
+
3
+ > **Role:** You are Jules, an expert AI software engineer. Your purpose is to solve engineering tasks by autonomously exploring the codebase, creating a plan, executing it, and verifying your work.
4
+
5
+ ## Objective
6
+ [State the exact goal of the task clearly and concisely. E.g., "Implement JWT authentication middleware for REST API endpoints."]
7
+
8
+ ## Context
9
+ - **Project Goals:** [Describe key architectural or business goals.]
10
+ - **Key Files & Folders:** [List critical files, directories, or schemas, e.g. `src/auth.ts`, `schema.sql`.]
11
+ - **Tech Stack:** [List frameworks and libraries, e.g. Node.js, Express, TypeScript, Drizzle ORM.]
12
+
13
+ ## Requirements & Hard Constraints
14
+ - **Functional Requirements:** [List specific, non-negotiable functional requirements.]
15
+ - **Hard Constraints:**
16
+ - Do NOT introduce third-party npm dependencies without explicit authorization.
17
+ - Do NOT modify command files (`package.json`, `.github/`) or Agent Scope files.
18
+ - Keep total diff payload strictly under 75 KB (`git diff | wc -c`).
19
+
20
+ ## Verification Loop
21
+ - **Verification Command:** Execute automated verification tests: `npm test`.
22
+ - **Zero Errors Invariant:** Ensure 100% of tests pass cleanly with 0 errors before submitting.
23
+
24
+ ## Expected Artifacts
25
+ - **Code Changes:** Clean, production-grade implementation preserving existing symbol contracts.
26
+ - **Test Coverage:** Updated or new unit/integration test cases covering modified logic.
@@ -1,9 +1,5 @@
1
1
  {
2
2
  "rules": [
3
- {
4
- "trigger": "\\.astro",
5
- "guardrail": "## ๐ŸŸข ASTRO GUARDRAILS\n- DO NOT run `biome check --write --unsafe` on `.astro` files (destroys frontmatter).\n- DO NOT import 'sharp' into runtime bundles."
6
- },
7
3
  {
8
4
  "trigger": "\\b(db|database|drizzle|sql\\w*|postgres\\w*|sqlite\\w*|mysql\\w*)\\b",
9
5
  "guardrail": "## ๐Ÿ—„๏ธ DATABASE GUARDRAILS\n- Always batch multiple database statements.\n- DO NOT write destructive migrations (`DROP TABLE`) without explicit user consent."
@@ -11,7 +11,7 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- node-version: ['18.x', '20.x', '22.x', '24.x']
14
+ node-version: ['22.x', '24.x']
15
15
  steps:
16
16
  - name: Checkout repository
17
17
  uses: actions/checkout@v4
@@ -23,14 +23,25 @@ jobs:
23
23
  with:
24
24
  node-version: ${{ matrix.node-version }}
25
25
 
26
- - name: Syntax Check
27
- run: for f in scripts/*.mjs bin/*.js index.mjs; do node --check "$f" || exit 1; done
26
+ - name: Cache OODA state & ledgers
27
+ uses: actions/cache@v4
28
+ with:
29
+ path: .agent/state/
30
+ key: ooda-state-${{ runner.os }}-${{ github.run_id }}
31
+ restore-keys: |
32
+ ooda-state-${{ runner.os }}-
33
+
34
+ - name: Install dependencies
35
+ run: npm install
36
+
37
+ - name: Run Linter
38
+ run: npm run lint --if-present
28
39
 
29
40
  - name: Run Unit Tests
30
- run: npm test
41
+ run: npm test --if-present
31
42
 
32
43
  - name: Run Jules PR Self-Audit Gatekeeper
33
- if: matrix.node-version == '20.x' && github.event_name == 'pull_request' && (startsWith(github.actor, 'google-labs-jules') || contains(github.actor, 'jules'))
44
+ if: matrix.node-version == '22.x' && github.event_name == 'pull_request'
34
45
  run: node scripts/jules-self-audit.mjs
35
46
  env:
36
47
  CI: "true"
@@ -50,9 +50,12 @@ Jules automatically infers test and build verification commands via `scripts/com
50
50
 
51
51
  - **Read Before Write**: Always inspect target files and surrounding symbol signatures (via grep or view tools) before applying changes.
52
52
  - **Scope Locks**: Strictly adhere to designated file bounds. Do NOT modify files outside the explicit task scope or alter shared infrastructural components unless assigned.
53
+ - **Falsifiable Criteria**: Never use unfalsifiable goals ("utterly perfect", "complete refactor"). Define tasks with binary scoreable criteria (e.g. passing test counts, 0 lint errors, explicit hard-fails).
54
+ - **Carry Evidence with Claims**: "It works" means pasting terminal verification output. Exit code 0 alone proves only process survival; inspect outputs/artifacts to prove function.
55
+ - **No Test Weakening Rule**: Never make a test pass by deleting assertions, commenting out checks, or weakening requirements. Leave unmet requirements RED with clear fix rationale.
56
+ - **Explicit File Ownership**: Sequence parallel swarm agents with explicit non-overlapping file ownership to prevent concurrent drift.
53
57
  - **Rebase Before PR**: Fetch latest `main`, rebase onto `origin/main`, re-execute verification suite. If the resulting diff is empty, close/abort PR without pushing.
54
58
  - **Minimal Interference**: Preserve existing function signatures, comments, and style conventions.
55
- - **Falsifiable Claims**: Base all code changes on explicit error logs, file paths, line numbers, or test results.
56
59
  - **No Token Bloat**: Exclude lockfiles, minified bundles, and binary assets from diff representations.
57
60
 
58
61
  ---
@@ -99,8 +102,10 @@ Follow all rules strictly.
99
102
  TASK: <description>
100
103
 
101
104
  HARD CONSTRAINTS:
102
- - Do NOT modify package.json, pnpm-lock.yaml, tsconfig.json, astro.config.mjs, wrangler.jsonc, or .github/ files. Enforced in CI by Agent Scope Guard.
105
+ - Do NOT modify package.json, pnpm-lock.yaml, tsconfig.json, or .github/ files. Enforced in CI by Agent Scope Guard.
103
106
  - Diff Payload Governor: Keep total diff payload under 75 KB (`git diff | wc -c`) to prevent API truncation (~80 KB limit).
107
+ - Falsifiable & Evidence-Based: Attach full terminal verification output to PR. Never weaken assertions or delete failing tests to force a pass.
108
+ - Declare Scope Deviations: If modifying files outside task bounds, explicitly state rationale in PR.
104
109
  - Verify before finishing: Run full type-check, lint, and unit test suites.
105
110
  - BEFORE opening the PR: Run `git fetch origin main && git rebase origin/main`, then re-verify. If the rebase leaves an empty diff, the work already landed โ€” do NOT submit.
106
111
  - Delete ALL temporary files (.py, .sh, .patch, debug logs) before submitting.
package/README.md CHANGED
@@ -22,29 +22,109 @@ To use this kit, you will need:
22
22
  - A Google Jules REST API key (set as `JULES_API_KEY`) **OR** the native `jules` binary in your PATH.
23
23
 
24
24
  ## Quick Start
25
- Navigate to your project root and run:
25
+ Initialize your repository:
26
26
  ```bash
27
- npx jules-orchestrator-kit
28
- npm run jules:create "Refactor Auth"
29
- npm run jules:queue
27
+ npx jules-orchestrator-kit init
30
28
  ```
31
29
 
32
- > ๐Ÿ’ก **Vendored Scripts Architecture**:
33
- > `npx jules-orchestrator-kit` (or `npx jules-init`) copies zero-dependency orchestration scripts directly into your project's `./scripts/` directory. This ensures full code transparency, auditability, and zero external dependency risk in CI.
34
- > To update vendored scripts to the latest release, run `npx jules-orchestrator-kit --force`.
30
+ Dispatch a task or run the queue using `agentctl`:
31
+ ```bash
32
+ agentctl dispatch --title "Refactor Auth" --prompt "Implement JWT verification in auth handler"
33
+ agentctl queue
34
+ agentctl gate
35
+ ```
36
+
37
+ > ๐Ÿ’ก **Unified Engine CLI (`agentctl`)**:
38
+ > `agentctl` is the zero-dependency CLI executable that powers dispatching, safety gate auditing, mutex locks, and swarm management across all project types (Node, Rust, Go, Python, etc.).
39
+ > Legacy `scripts/jules-*.mjs` shims are preserved for backward compatibility.
35
40
 
36
41
  ---
37
42
 
38
43
  ## How It Works
39
44
 
40
- 1. **You Assign Task:** Define what needs fixing or building.
45
+ 1. **You Assign Task:** Define what needs fixing or building (supports text and multimodal image mockups).
41
46
  2. **Jules Writes Code:** Proposes changes in an isolated Git worktree sandbox.
42
47
  3. **Run Tests & Linters:** The Gatekeeper runs your test suite, linters, and type checks.
43
48
  4. **Self-Correction:** If anything fails, Jules automatically retries with fixes (OODA loop).
44
49
  5. **Safe Delivery:** Once tests pass, the PR is verified and ready for review.
45
50
 
51
+ ```mermaid
52
+ sequenceDiagram
53
+ autonumber
54
+
55
+ box "Client Edge" #F4F4F4
56
+ actor Trigger as Client (CLI / CI / SDK)
57
+ end
58
+
59
+ box "Control Plane" #E8F4F8
60
+ participant Orc as Orchestrator Core
61
+ participant Gate as Self-Audit Gatekeeper
62
+ end
63
+
64
+ box "Execution Sandbox" #F8E8E8
65
+ participant API as Google Jules API
66
+ participant Git as Git Worktree Sandbox
67
+ end
68
+
69
+ Trigger->>+Orc: Dispatch Task Payload
70
+
71
+ note over Orc,Git: Phase 1: Security Redaction & Provisioning
72
+ Orc->>Orc: Redact Secrets (Entropy > 3.6) & Enforce Dynamic Guardrails
73
+ Orc->>+Git: Provision Isolation Sandbox (git worktree)
74
+ Git-->>-Orc: Sandbox Ready
75
+
76
+ loop OODA Repair Cycle (Max 3 Retries)
77
+ note over Orc,Git: Phase 2: Agent Execution & Dispatch
78
+ Orc->>+API: Dispatch Task + <MCP_DIRECTIVE> & Target Scope
79
+ API->>+Git: Apply Proposed Code Changes
80
+ Git-->>-API: Changes Written
81
+ API-->>-Orc: Execution Complete
82
+
83
+ note over Orc,Gate: Phase 3: Tiered Verification & Gatekeeping
84
+ Orc->>+Gate: Trigger Self-Audit (trusted origin/main rules)
85
+
86
+ Gate->>+Git: Scope Audit (`git diff -z --name-only` vs forbidden_paths)
87
+ Git-->>-Gate: Diff Stats & File List
88
+
89
+ alt Scope Breach (Forbidden Path OR Diff Payload > 75 KB)
90
+ Gate-->>Orc: Security / Scope Violation Detected
91
+ Orc->>Orc: Record Telemetry (metrics.jsonl)
92
+ Orc-->>Trigger: Abort Execution (Exit 3)
93
+ break Fatal Security Error
94
+ Orc->>Git: Teardown Worktree Sandbox
95
+ end
96
+ else Scope Verification Passed
97
+ Gate->>+Git: Run Dynamic Verification (`testCmd` & `buildCmd`)
98
+ Git-->>-Gate: stdout / stderr verification results
99
+ end
100
+
101
+ alt 100% Verification Suite Passed
102
+ Gate-->>-Orc: Verification Success
103
+ Orc->>+Git: Commit & Push to Remote Branch / PR
104
+ Git-->>-Orc: PR Ready
105
+ Orc->>Orc: Record Telemetry (metrics.jsonl)
106
+ Orc-->>Trigger: Dispatch Succeeded (Exit 0)
107
+ break Task Completed
108
+ Orc->>Git: Teardown Worktree Sandbox
109
+ end
110
+ else Verification Failed
111
+ Gate-->>Orc: Verification Failed (Stderr Trace output)
112
+ Orc->>Orc: Record Failure Telemetry
113
+
114
+ alt Retries Remaining (< 3)
115
+ Orc->>Orc: Construct Repair Prompt with Stderr Trace
116
+ else Max Retries Exceeded (3/3)
117
+ Orc-->>-Trigger: Abort & Log Diagnostic Feedback (Exit 4)
118
+ Orc->>Git: Teardown Worktree Sandbox
119
+ end
120
+ end
121
+ end
122
+ ```
123
+
46
124
  > ๐Ÿ’ก **Core Architectural Invariants**:
47
125
  > - **Zero-Trust Base-Branch Security**: Security rules (`forbidden_paths`) are fetched exclusively from `origin/main` (never untrusted PR branches).
126
+ > - **Automatic PII & Secret Redaction**: Outbound task prompts are automatically sanitized to redact API secrets and mask sensitive PII (emails, IPs, phone numbers).
127
+ > - **Ledger Hash-Chain Integrity**: Hashing over JSONL event streams detects unauthorized log tampering or record deletions.
48
128
  > - **Dynamic Command Resolution (`command-resolver.mjs`)**: Auto-detects workspace boundaries (Turborepo, pnpm, Nx, Cargo, pytest, npm).
49
129
  >
50
130
  > ๐Ÿ” For a deep dive into the execution protocol, see the [Architecture & Pipeline Flow](docs/architecture.md).
@@ -96,13 +176,16 @@ If no API key is configured, the kit seamlessly falls back to invoking your loca
96
176
  **3. Programmatic Node.js SDK (`index.mjs`)**
97
177
  Downstream Node.js tools, MCP servers, and LLM orchestrators can import kit functions directly:
98
178
  ```js
99
- import { runSelfAudit, scanCodebaseForTodos, resolveProjectCommands } from "jules-orchestrator-kit";
179
+ import { gate, dispatch, validateEnvelope, classifyRiskTier, checkAssetIntegrity, checkRulesBudget, redactSecrets } from "jules-orchestrator-kit";
180
+
181
+ // Anonymize sensitive PII (emails, IPs, phone numbers) before sending prompts
182
+ const cleanPrompt = anonymizePii("Contact support at john@example.com");
100
183
 
101
- // Run pre-flight sandbox check
102
- await runPreflightSandbox();
184
+ // Programmatically dispatch tasks
185
+ await dispatch({ title: "Refactor Auth", prompt: cleanPrompt });
103
186
 
104
- // Scan codebase for TODO/FIXME tasks
105
- const tasks = scanCodebaseForTodos(process.cwd());
187
+ // Run 4-phase safety gate audit
188
+ const audit = await gate({ base: "main" });
106
189
  ```
107
190
 
108
191
  ---
@@ -149,13 +232,21 @@ All commands are registered in `package.json` and can be run via `npm run <comma
149
232
  | `npm run jules:dispatch` | Dispatches a single task directly to Jules |
150
233
  | `npm run jules:queue` | Runs the local queue processor (picks up tasks from `.agent/jules-queue`) |
151
234
  | `npm run jules:create` | Scaffolds a new boilerplate task markdown file |
152
- | `npm run jules:status` | Shows the real-time status of all queued and completed tasks |
235
+ | `npm run jules:status` | Shows real-time 3-bucket status (Action Required, In Progress, Completed) |
153
236
  | `npm run jules:audit` | Runs the self-audit gatekeeper (verifies tests, forbidden paths, and scope) |
154
237
  | `npm run jules:cleanup` | Audits and closes merged or stale REST sessions |
155
238
  | `npm run jules:scan` | Scans the codebase for TODO/FIXME comments and generates a suggested tasks file |
156
239
  | `npm run jules:swarm` | Launches a multi-agent swarm in parallel across isolated worktrees |
240
+ | `npm run jules:merge-swarm` | Autonomous PR merge engine with Safety Gate lock verification |
157
241
  | `npm run jules:nightly` | Nightly maintenance job (usually triggered in CI) |
158
242
 
243
+ ### Specialist Agent Prompts & Templates (`.agent/prompts/`)
244
+ The kit includes pre-configured single-responsibility prompt presets in `.agent/prompts/`:
245
+ - **`Overseer.md`**: Codebase architecture auditor & technical debt mapper.
246
+ - **`Bolt.md`**: Performance micro-optimizer and payload governor (enforces < 75 KB payload diff limits).
247
+ - **`Sentinel.md`**: Security audit specialist for input sanitization and secret scanning.
248
+ - **`Task_Template.md`**: Machine-readable master task prompt template schema.
249
+
159
250
  ### Environment Variables
160
251
 
161
252
  | Variable | Description |
@@ -167,6 +258,7 @@ All commands are registered in `package.json` and can be run via `npm run <comma
167
258
  | `JULES_REPOLESS` | Set to `true` or `1` to run in repoless/serverless mode |
168
259
  | `JULES_DRY_RUN` | Set to `true` or `1` to simulate dispatching without making API calls |
169
260
  | `JULES_DAILY_BUDGET` | Daily max session budget for autonomous dispatches (Default: `300`) |
261
+ | `JULES_MAX_DIFF_KB` | Maximum git diff payload size in KB before aborting with Exit Code 5 (Default: `50`) |
170
262
  | `JULES_ALLOW_COMMAND_FILE_CHANGES` | Set to `true` to allow PR changes to command/config files like `package.json`, `tsconfig.json`, `vite.config.ts` (Default: `false`) |
171
263
  | `JULES_ALLOW_AGENT_RULE_CHANGES` | Set to `true` to allow PR changes to agent rule files like `AGENTS.md`, `JULES_RULES_TEMPLATE.md` (Default: `false`) |
172
264
  | `BASE_BRANCH` | Base branch for PR Audits & Merge-Base calculations (Default: `main`) |
@@ -193,19 +285,19 @@ The Gatekeeper (`jules-self-audit.mjs` and related scripts) uses standard exit c
193
285
  | Code | Meaning | Action Taken |
194
286
  | ---- | ------- | ------------ |
195
287
  | `0` | **Success** | All tests and security checks passed. |
196
- | `1` | **General Error** | Missing dependencies, syntax error, or general failure. |
197
- | `2` | **Setup / Context Error** | Git not found, invalid `BASE_BRANCH`, or trusted base branch extraction failure. |
198
- | `3` | **Security Violation** | Modified file breached `forbidden_paths` or changed command-defining files (`package.json`, `Cargo.toml`). Fails closed immediately. |
199
- | `4` | **Verification Exhausted** | Tests failed and the OODA Auto-Repair loop either exhausted its max retries or is disabled. |
200
- | `5` | **Diff Payload Too Large** | Diff payload size exceeded 75 KB payload governor limit. Split task. |
201
- | `6` | **Secret Leak Prevented** | Secret-like pattern detected in diff. Aborted immediately. |
288
+ | `1` | **Pre-Dispatch / Arg Error** | Missing dependencies, prompt > 50 KB, syntax error, or pre-dispatch failure. |
289
+ | `2` | **API / Network / Quota Error** | REST API HTTP 429 rate limit, HTTP 400 `FAILED_PRECONDITION` quota (~30 active limit), or connection timeout. |
290
+ | `3` | **Security / Scope Violation** | Modified file breached `forbidden_paths` or changed command-defining files (`package.json`, `Cargo.toml`). Fails closed immediately. |
291
+ | `4` | **Verification Exhausted** | Tests failed and the OODA Auto-Repair loop either exhausted its max retries (3) or is disabled. |
292
+ | `5` | **Diff Payload Limit** | Diff payload size exceeded payload governor budget (`JULES_MAX_DIFF_KB`, default 50 KB). Split task. |
293
+ | `6` | **Secret Leak Prevented** | High-confidence secret or private key pattern detected in diff. Aborted immediately. |
202
294
  | `7` | **Budget Exhausted** | Daily session budget limit reached or budget state locked. |
203
295
 
204
296
  ---
205
297
 
206
298
  ## Contributing
207
299
  We welcome contributions! Please follow these core principles:
208
- 1. **Zero External Dependencies**: Use ONLY native Node.js built-in modules (`node:fs`, `node:path`, `node:child_process`, `node:crypto`, `node:util`).
300
+ 1. **Zero Runtime Dependencies**: Use ONLY native Node.js built-in modules (`node:fs`, `node:path`, `node:child_process`, `node:crypto`, `node:util`).
209
301
  2. **Verification Suite**: Ensure 100% of unit tests pass cleanly (`npm test`).
210
302
  3. **Conventional Commits**: Use standardized prefixes (`feat:`, `fix:`, `docs:`, `test:`, `chore:`).
211
303
  4. **Cross-Platform Compatibility**: Normalize Windows backslashes (`\`) to POSIX slashes (`/`) for glob patterns and paths.
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { parseArgs } from "node:util";
4
+ import { readFileSync, writeFileSync, existsSync, readdirSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { loadConfig, resolveRoot, detectStack } from "../src/config.mjs";
7
+ import { gate, dispatch, run } from "../src/engine.mjs";
8
+ import { acquireLock, releaseLock, lockStatus, checkDailyBudget, getQueueDir, ensureDir } from "../src/state.mjs";
9
+ import { worktreePrune } from "../src/git.mjs";
10
+
11
+ const args = process.argv.slice(2);
12
+ const command = args[0];
13
+
14
+ function printHelp() {
15
+ console.log(`
16
+ ๐Ÿš€ agentctl v0.9.0 โ€” Universal Agent Orchestrator & Safety Gatekeeper
17
+
18
+ Usage: agentctl <command> [options]
19
+
20
+ Commands:
21
+ dispatch Dispatch a single task to an AI agent
22
+ gate | audit Run CI security and verification gate against current branch
23
+ queue Run pending task queue
24
+ swarm Run parallel task swarm
25
+ clean Clean stale branches, worktrees, locks, and ledgers
26
+ lock <action> Manage mutex locks (acquire | release | status | cleanup)
27
+ doctor Run system diagnostics and stack resolution checks
28
+ init Scaffold .agent/ directory and config.yml
29
+ version Output agentctl version
30
+
31
+ Options:
32
+ --dry-run, -d Simulate action without making API calls or modifying git
33
+ --json, -j Emit machine-readable JSON output
34
+ --help, -h Show command help
35
+ `);
36
+ }
37
+
38
+ async function main() {
39
+ if (!command || command === "--help" || command === "-h") {
40
+ printHelp();
41
+ process.exit(0);
42
+ }
43
+
44
+ if (command === "version" || command === "--version" || command === "-v") {
45
+ console.log("agentctl v0.9.0");
46
+ process.exit(0);
47
+ }
48
+
49
+ const root = resolveRoot();
50
+ const config = loadConfig(root);
51
+
52
+ switch (command) {
53
+ case "dispatch": {
54
+ const { values } = parseArgs({
55
+ args: args.slice(1),
56
+ options: {
57
+ title: { type: "string", short: "t" },
58
+ prompt: { type: "string", short: "p" },
59
+ "prompt-file": { type: "string", short: "f" },
60
+ "dry-run": { type: "boolean", short: "d" },
61
+ json: { type: "boolean", short: "j" },
62
+ },
63
+ allowPositionals: true,
64
+ });
65
+
66
+ let promptContent = values.prompt || "";
67
+ if (values["prompt-file"] && existsSync(values["prompt-file"])) {
68
+ promptContent = readFileSync(values["prompt-file"], "utf-8");
69
+ }
70
+
71
+ if (!promptContent && args[1] && !args[1].startsWith("-")) {
72
+ promptContent = args.slice(1).join(" ");
73
+ }
74
+
75
+ if (!promptContent) {
76
+ console.error("Error: --prompt or --prompt-file is required.");
77
+ process.exit(1);
78
+ }
79
+
80
+ const task = {
81
+ title: values.title || "CLI Dispatch Task",
82
+ prompt: promptContent,
83
+ };
84
+
85
+ try {
86
+ const session = await dispatch(task, { root, config, dryRun: values["dry-run"] });
87
+ if (values.json) {
88
+ console.log(JSON.stringify({ ok: true, session }, null, 2));
89
+ } else {
90
+ console.log(`\nโœ… Task Dispatched Successfully!`);
91
+ console.log(` Session ID : ${session.id}`);
92
+ console.log(` Session URL : ${session.url || "N/A"}`);
93
+ }
94
+ process.exit(0);
95
+ } catch (err) {
96
+ if (values.json) {
97
+ console.log(JSON.stringify({ ok: false, error: err.message, code: err.code || 1 }, null, 2));
98
+ } else {
99
+ console.error(`โŒ Dispatch Failed: ${err.message}`);
100
+ }
101
+ process.exit(err.code || 1);
102
+ }
103
+ break;
104
+ }
105
+
106
+ case "gate":
107
+ case "audit": {
108
+ const { values } = parseArgs({
109
+ args: args.slice(1),
110
+ options: {
111
+ base: { type: "string", short: "b", default: config.baseBranch || "main" },
112
+ fix: { type: "boolean" },
113
+ "allow-protected": { type: "boolean" },
114
+ json: { type: "boolean", short: "j" },
115
+ },
116
+ allowPositionals: true,
117
+ });
118
+
119
+ const res = await gate({
120
+ root,
121
+ config,
122
+ base: values.base,
123
+ fix: values.fix,
124
+ allowProtected: values["allow-protected"],
125
+ });
126
+
127
+ if (values.json) {
128
+ console.log(JSON.stringify(res, null, 2));
129
+ } else {
130
+ console.log(`\n๐Ÿ›ก๏ธ agentctl Safety Gate Audit Results (Base: ${values.base})`);
131
+ console.log(`-----------------------------------------------------`);
132
+ for (const p of res.phases) {
133
+ const status = p.ok ? "โœ… PASS" : "โŒ FAIL";
134
+ console.log(` Phase [${p.phase.toUpperCase()}] : ${status}`);
135
+ if (p.violations) {
136
+ p.violations.forEach((v) => console.log(` - Violation: ${v.file} (Rule: ${v.rule})`));
137
+ }
138
+ if (p.findings) {
139
+ p.findings.forEach((f) => console.log(` - Finding: ${f.id} at line ${f.line}`));
140
+ }
141
+ }
142
+ console.log(`-----------------------------------------------------`);
143
+ console.log(`Overall Result: ${res.ok ? "APPROVED (Exit 0)" : `REJECTED (Exit ${res.code})`}\n`);
144
+ }
145
+
146
+ process.exit(res.code);
147
+ break;
148
+ }
149
+
150
+ case "queue": {
151
+ const queueDir = getQueueDir(root);
152
+ const files = readdirSync(queueDir).filter((f) => f.endsWith(".md"));
153
+ console.log(` Found ${files.length} queued task(s) in .agent/queue/`);
154
+ if (files.length > 0) {
155
+ const tasks = files.map((f) => ({
156
+ id: f,
157
+ title: f.replace(/\.md$/, ""),
158
+ prompt: readFileSync(join(queueDir, f), "utf-8"),
159
+ }));
160
+ const results = await run(tasks, { root, config });
161
+ console.log(`\nProcessed ${results.length} tasks.`);
162
+ }
163
+ process.exit(0);
164
+ break;
165
+ }
166
+
167
+ case "swarm": {
168
+ console.log("๐Ÿš€ Running Swarm Orchestrator...");
169
+ const queueDir = getQueueDir(root);
170
+ const files = readdirSync(queueDir).filter((f) => f.endsWith(".md"));
171
+ if (files.length === 0) {
172
+ console.log("No pending tasks found for swarm.");
173
+ process.exit(0);
174
+ }
175
+ const tasks = files.map((f) => ({
176
+ id: f,
177
+ title: f.replace(/\.md$/, ""),
178
+ prompt: readFileSync(join(queueDir, f), "utf-8"),
179
+ }));
180
+ const results = await run(tasks, { root, config, concurrency: config.limits.concurrency || 3 });
181
+ console.log(`Swarm completed ${results.length} tasks.`);
182
+ process.exit(0);
183
+ break;
184
+ }
185
+
186
+ case "clean": {
187
+ console.log("๐Ÿงน Running System Cleanup...");
188
+ worktreePrune(root);
189
+ console.log(" โœ… Pruned stale Git worktrees.");
190
+ process.exit(0);
191
+ break;
192
+ }
193
+
194
+ case "lock": {
195
+ const action = args[1];
196
+ if (action === "acquire") {
197
+ const agent = args[2] || "agent";
198
+ const taskId = args[3] || "task-1";
199
+ const filePaths = args.slice(4);
200
+ const res = acquireLock(agent, taskId, filePaths, root);
201
+ if (res.ok) {
202
+ console.log(`โœ… Acquired lock for ${taskId}`);
203
+ } else {
204
+ console.log(`โŒ Lock conflict detected: held by ${res.holder}`);
205
+ process.exit(1);
206
+ }
207
+ } else if (action === "release") {
208
+ const taskId = args[2] || "task-1";
209
+ const ok = releaseLock(taskId, root);
210
+ if (ok) {
211
+ console.log(`โœ… Released lock for ${taskId}`);
212
+ } else {
213
+ console.log(`โŒ Lock for ${taskId} not found or release failed`);
214
+ process.exit(1);
215
+ }
216
+ } else {
217
+ const locks = lockStatus(root);
218
+ console.log(`Active Locks (${locks.length}):`, locks);
219
+ }
220
+ process.exit(0);
221
+ break;
222
+ }
223
+
224
+ case "doctor": {
225
+ console.log(`\n๐Ÿ” agentctl System Diagnostics (v0.9.0)`);
226
+ console.log(`--------------------------------------------------`);
227
+ console.log(` Project Root : ${root}`);
228
+ console.log(` Config File : ${config._file || "None (Using defaults)"}`);
229
+ console.log(` Detected Stack : ${detectStack(root).stack}`);
230
+ console.log(` Test Command : ${config.verify.test || "(None)"}`);
231
+ console.log(` Build Command : ${config.verify.build || "(None)"}`);
232
+ const budget = checkDailyBudget(root, config.limits.dailyTasks);
233
+ console.log(` Daily Budget : ${budget.used} / ${budget.budget} sessions used`);
234
+ console.log(`--------------------------------------------------\n`);
235
+ process.exit(0);
236
+ break;
237
+ }
238
+
239
+ case "init": {
240
+ const agentDir = join(root, ".agent");
241
+ ensureDir(agentDir);
242
+ const configPath = join(agentDir, "config.yml");
243
+ if (!existsSync(configPath)) {
244
+ writeFileSync(
245
+ configPath,
246
+ `version: 1
247
+ provider: jules
248
+ limits:
249
+ diff_kb: 75
250
+ daily_tasks: 300
251
+ branch_prefix: agent/
252
+ base_branch: main
253
+ `,
254
+ "utf-8"
255
+ );
256
+ console.log(`โœ… Created .agent/config.yml`);
257
+ } else {
258
+ console.log(`โ„น๏ธ .agent/config.yml already exists.`);
259
+ }
260
+ process.exit(0);
261
+ break;
262
+ }
263
+
264
+ default:
265
+ console.error(`Unknown command: ${command}`);
266
+ printHelp();
267
+ process.exit(1);
268
+ }
269
+ }
270
+
271
+ main().catch((err) => {
272
+ console.error(`[FATAL ERROR] ${err.message}`);
273
+ process.exit(err.code || 1);
274
+ });
package/bin/init.js CHANGED
@@ -157,7 +157,7 @@ if (!fs.existsSync(yamlConfigPath) || isForce) {
157
157
  version: 2
158
158
  test_cmd: "${detected.testCmd || "npm test"}"
159
159
  build_cmd: "${detected.buildCmd || "npm run build"}"
160
- forbidden_paths: [".github/**", "**/secrets/**", "**/*.pem", "**/lock-manager/**"]
160
+ forbidden_paths: [".github/**", "**/.env*", "**/*.pem", "**/lock-manager*"]
161
161
  `;
162
162
  fs.writeFileSync(yamlConfigPath, yamlContent, "utf-8");
163
163
  console.log("โœ… Created: .agent/jules.yml");