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.
- package/.agent/jules-queue/README.md +4 -4
- package/.agent/prompts/Bolt.md +18 -0
- package/.agent/prompts/Overseer.md +18 -0
- package/.agent/prompts/Sentinel.md +18 -0
- package/.agent/prompts/Task_Template.md +26 -0
- package/.agent/rules/dynamic-guardrails.json +0 -4
- package/.github/workflows/jules-audit.yml +16 -5
- package/JULES_RULES_TEMPLATE.md +7 -2
- package/README.md +113 -21
- package/bin/agentctl.mjs +274 -0
- package/bin/init.js +1 -1
- package/index.mjs +34 -6
- package/package.json +22 -6
- package/scripts/asset-integrity-check.mjs +35 -0
- package/scripts/command-resolver.mjs +37 -214
- package/scripts/jules-cleanup.mjs +23 -174
- package/scripts/jules-create.mjs +12 -51
- package/scripts/jules-dispatch.mjs +103 -349
- package/scripts/jules-merge-swarm.mjs +30 -0
- package/scripts/jules-nightly.mjs +7 -124
- package/scripts/jules-patch.mjs +23 -0
- package/scripts/jules-queue-runner.mjs +28 -203
- package/scripts/jules-scan-todos.mjs +31 -125
- package/scripts/jules-self-audit.mjs +76 -578
- package/scripts/jules-status.mjs +42 -65
- package/scripts/jules-swarm.mjs +27 -232
- package/scripts/jules-webhook-receiver.mjs +70 -0
- package/scripts/lock-manager.mjs +11 -170
- package/scripts/risk-tier.mjs +29 -0
- package/scripts/rules-lint.mjs +20 -0
- package/scripts/stale-base-check.mjs +26 -0
- package/scripts/utils.mjs +118 -252
- package/scripts/validate-envelope.mjs +44 -0
- package/src/asset_integrity.mjs +76 -0
- package/src/config.mjs +325 -0
- package/src/engine.mjs +217 -0
- package/src/envelope.mjs +105 -0
- package/src/git.mjs +127 -0
- package/src/provider.mjs +179 -0
- package/src/risk.mjs +120 -0
- package/src/rules_budget.mjs +77 -0
- package/src/security.mjs +212 -0
- package/src/state.mjs +209 -0
- package/src/webhook.mjs +138 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -63
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -34
- package/.github/social-preview.png +0 -0
- package/.github/workflows/agent-scope-guard.yml +0 -57
- package/.github/workflows/jules-nightly.yml +0 -21
- 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
|
-
|
|
23
|
-
# or
|
|
22
|
+
agentctl queue
|
|
23
|
+
# or npm run jules:queue
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Or dispatch a single
|
|
26
|
+
Or dispatch a single task using `agentctl dispatch`:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
|
|
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: ['
|
|
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:
|
|
27
|
-
|
|
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 == '
|
|
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"
|
package/JULES_RULES_TEMPLATE.md
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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 {
|
|
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
|
-
//
|
|
102
|
-
await
|
|
184
|
+
// Programmatically dispatch tasks
|
|
185
|
+
await dispatch({ title: "Refactor Auth", prompt: cleanPrompt });
|
|
103
186
|
|
|
104
|
-
//
|
|
105
|
-
const
|
|
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
|
|
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` | **
|
|
197
|
-
| `2` | **
|
|
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
|
|
201
|
-
| `6` | **Secret Leak Prevented** |
|
|
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
|
|
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.
|
package/bin/agentctl.mjs
ADDED
|
@@ -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/**", "
|
|
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");
|