jonah-fleet 1.0.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 +17 -0
- package/README.md +133 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +454 -0
- package/package.json +47 -0
- package/schema.json +49 -0
- package/templates/docs/AGENTS.template.md +54 -0
- package/templates/prompts/ORCHESTRATION.md +97 -0
- package/templates/prompts/_prompt-template.md +43 -0
- package/templates/prompts/autowork.md +125 -0
- package/templates/prompts/dependency-update-security-check.md +44 -0
- package/templates/prompts/issues-housekeeping.md +55 -0
- package/templates/prompts/optimizer.md +72 -0
- package/templates/prompts/peer-review.md +112 -0
- package/templates/prompts/product-planning.md +67 -0
- package/templates/skills/code-review/SKILL.md +87 -0
- package/templates/skills/code-review/agents/openai.yaml +3 -0
- package/templates/skills/codebase-design/DEEPENING.md +37 -0
- package/templates/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/templates/skills/codebase-design/SKILL.md +114 -0
- package/templates/skills/codebase-design/agents/openai.yaml +3 -0
- package/templates/skills/diagnosing-bugs/SKILL.md +138 -0
- package/templates/skills/diagnosing-bugs/agents/openai.yaml +3 -0
- package/templates/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
- package/templates/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/templates/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/templates/skills/domain-modeling/SKILL.md +74 -0
- package/templates/skills/domain-modeling/agents/openai.yaml +3 -0
- package/templates/skills/resolving-merge-conflicts/SKILL.md +14 -0
- package/templates/skills/resolving-merge-conflicts/agents/openai.yaml +3 -0
- package/templates/skills/tdd/SKILL.md +38 -0
- package/templates/skills/tdd/agents/openai.yaml +3 -0
- package/templates/skills/tdd/mocking.md +59 -0
- package/templates/skills/tdd/tests.md +77 -0
- package/templates/skills/to-spec/SKILL.md +75 -0
- package/templates/skills/to-spec/agents/openai.yaml +5 -0
- package/templates/skills/to-tickets/SKILL.md +105 -0
- package/templates/skills/to-tickets/agents/openai.yaml +5 -0
- package/templates/skills/triage/AGENT-BRIEF.md +207 -0
- package/templates/skills/triage/OUT-OF-SCOPE.md +105 -0
- package/templates/skills/triage/SKILL.md +112 -0
- package/templates/skills/triage/agents/openai.yaml +5 -0
- package/templates/skills/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/templates/skills/writing-for-agents/SKILL.md +81 -0
- package/templates/skills/writing-for-agents/agents/openai.yaml +3 -0
- package/templates/workflows/autowork-cron.yml +154 -0
- package/templates/workflows/dependency-check-cron.yml +85 -0
- package/templates/workflows/issues-housekeeping-cron.yml +85 -0
- package/templates/workflows/prompt-optimizer-cron.yml +85 -0
- package/templates/workflows/sync-fleet.yml +63 -0
- package/templates/workflows/trigger-autowork-on-bug.yml +101 -0
- package/templates/workflows/trigger-autowork-on-merge.yml +130 -0
- package/templates/workflows/trigger-review-routine.yml +141 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `jonah-fleet` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-08-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Extracted standalone `jonah-fleet` repository and distribution engine from Jonah-RuPaul.
|
|
12
|
+
- Created core generic prompts: `ORCHESTRATION.md`, `autowork.md`, `peer-review.md`, `optimizer.md`, `issues-housekeeping.md`, `dependency-update-security-check.md`, `product-planning.md`.
|
|
13
|
+
- Packaged core engineering skills: `tdd`, `code-review`, `codebase-design`, `domain-modeling`, `diagnosing-bugs`, `resolving-merge-conflicts`, `writing-for-agents`, `triage`, `to-spec`, `to-tickets`.
|
|
14
|
+
- Created standard workflow templates: `autowork-cron.yml`, `trigger-review-routine.yml`, `trigger-autowork-on-merge.yml`, `trigger-autowork-on-bug.yml`, `issues-housekeeping-cron.yml`, `prompt-optimizer-cron.yml`, `dependency-check-cron.yml`, and `sync-fleet.yml`.
|
|
15
|
+
- Built TypeScript CLI (`jonah-fleet`) with `init`, `sync`, `status`, and `contribute` commands.
|
|
16
|
+
- Implemented `schema.json` and `agents-manifest.json` configuration engine with preset bundling (`minimal`, `standard`, `full`).
|
|
17
|
+
- Implemented automated bi-directional improvement bridge in `optimizer.md` and `contribute` CLI command.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# ⚓ Jonah Fleet
|
|
2
|
+
|
|
3
|
+
> **Standalone Autonomous Agent Fleet & Symphony Orchestration Engine**
|
|
4
|
+
> Battle-tested autonomous coding agents, claim protocols, review loops, and engineering skills for multi-repo teams.
|
|
5
|
+
|
|
6
|
+
[](https://github.com/juliendurandeu/jonah-fleet/actions/workflows/ci.yml)
|
|
7
|
+
[](./package.json)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 🌟 Overview
|
|
13
|
+
|
|
14
|
+
`jonah-fleet` packages a complete suite of autonomous software engineering agents into a standalone repository and zero-install CLI (`npx jonah-fleet`). It turns any repository into an autonomous agent-driven development environment with:
|
|
15
|
+
|
|
16
|
+
- **Symphony-aligned Orchestration**: Single-flight locking, stale-claim recovery, and reader/writer separation.
|
|
17
|
+
- **Autonomous Autowork**: Issue claiming, test-driven implementation (`/tdd`), automated draft PR creation, and warm-session review synchronization.
|
|
18
|
+
- **Strict Peer Review**: Multi-angle subagent code reviews (`/code-review`), security scanning, and automated squash-merge.
|
|
19
|
+
- **Issues Housekeeping & Dependency Security**: Weekly automated sweeps for duplicate detection, triage label assignment, and vulnerability remediation.
|
|
20
|
+
- **Continuous Bi-Directional Improvement Bridge**: When local `optimizer.md` routines discover generic prompt optimizations, fixes can be submitted directly back upstream to `jonah-fleet` and distributed to all projects.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🚀 Quickstart
|
|
25
|
+
|
|
26
|
+
### 1. Initialize a repository
|
|
27
|
+
|
|
28
|
+
Inside any project directory, run:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx jonah-fleet init --preset standard
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Available presets:
|
|
35
|
+
- **`minimal`**: `autowork` + `peer-review` + `optimizer`
|
|
36
|
+
- **`standard`** (default): minimal + `issues-housekeeping` + `dependency-update-security-check`
|
|
37
|
+
- **`full`**: standard + `product-planning`
|
|
38
|
+
|
|
39
|
+
### 2. Configure project context (`AGENTS.md`)
|
|
40
|
+
|
|
41
|
+
`jonah-fleet init` generates an `AGENTS.md` file (or uses your existing one). Specify your test commands, build scripts, and architecture patterns:
|
|
42
|
+
|
|
43
|
+
```markdown
|
|
44
|
+
## Tech Stack
|
|
45
|
+
- Next.js 15, TypeScript, Tailwind CSS, Supabase
|
|
46
|
+
|
|
47
|
+
## Development Workflows
|
|
48
|
+
```bash
|
|
49
|
+
npm run build
|
|
50
|
+
npm test
|
|
51
|
+
npm run type-check
|
|
52
|
+
```
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Check health and drift
|
|
56
|
+
|
|
57
|
+
To inspect which routines and skills are active or verify alignment with latest fleet updates:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx jonah-fleet status
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To synchronize with the latest fleet version:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx jonah-fleet sync
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 🛠️ Repository Layout
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
jonah-fleet/
|
|
75
|
+
├── templates/
|
|
76
|
+
│ ├── prompts/ # Core generic prompts (autowork, peer-review, optimizer, etc.)
|
|
77
|
+
│ ├── workflows/ # GitHub Actions workflows for scheduling and event triggers
|
|
78
|
+
│ ├── skills/ # Reusable engineering skills (tdd, code-review, diagnosing-bugs, etc.)
|
|
79
|
+
│ └── docs/ # Starter documentation templates (AGENTS.template.md)
|
|
80
|
+
├── src/ # TypeScript CLI source code
|
|
81
|
+
├── tests/ # Unit test & prompt validation suite
|
|
82
|
+
└── schema.json # JSON Schema for agents-manifest.json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 📜 Manifest Configuration (`agents-manifest.json`)
|
|
88
|
+
|
|
89
|
+
Each target project contains an `agents-manifest.json` at its root:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"$schema": "https://raw.githubusercontent.com/juliendurandeu/jonah-fleet/main/schema.json",
|
|
94
|
+
"version": "1.0.0",
|
|
95
|
+
"preset": "standard",
|
|
96
|
+
"routines": {
|
|
97
|
+
"autowork": true,
|
|
98
|
+
"peer-review": true,
|
|
99
|
+
"optimizer": true,
|
|
100
|
+
"issues-housekeeping": true,
|
|
101
|
+
"dependency-update-security-check": true,
|
|
102
|
+
"product-planning": false
|
|
103
|
+
},
|
|
104
|
+
"skills": [
|
|
105
|
+
"tdd",
|
|
106
|
+
"code-review",
|
|
107
|
+
"codebase-design",
|
|
108
|
+
"domain-modeling",
|
|
109
|
+
"diagnosing-bugs",
|
|
110
|
+
"resolving-merge-conflicts",
|
|
111
|
+
"writing-for-agents",
|
|
112
|
+
"triage"
|
|
113
|
+
],
|
|
114
|
+
"autoUpdate": {
|
|
115
|
+
"enabled": true,
|
|
116
|
+
"channel": "stable"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🔄 Bi-Directional Continuous Improvement
|
|
124
|
+
|
|
125
|
+
1. **Local Optimization**: The `optimizer.md` routine monitors run logs in each connected project.
|
|
126
|
+
2. **Upstream Contribution**: When a prompt or workflow improvement is discovered, the optimizer opens an upstream PR against `juliendurandeu/jonah-fleet` (or via `npx jonah-fleet contribute`).
|
|
127
|
+
3. **Downstream Sync**: Merged improvements in `jonah-fleet` create a semantic release, and downstream consumer repositories receive automated update PRs via `.github/workflows/sync-fleet.yml`.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 📄 License
|
|
132
|
+
|
|
133
|
+
MIT © Julien Durandeu
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/commands/init.ts
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
|
|
9
|
+
// src/lib/manifest.ts
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
// src/lib/presets.ts
|
|
14
|
+
var PRESET_CONFIGS = {
|
|
15
|
+
minimal: {
|
|
16
|
+
routines: {
|
|
17
|
+
autowork: true,
|
|
18
|
+
"peer-review": true,
|
|
19
|
+
optimizer: true,
|
|
20
|
+
"issues-housekeeping": false,
|
|
21
|
+
"dependency-update-security-check": false,
|
|
22
|
+
"product-planning": false
|
|
23
|
+
},
|
|
24
|
+
skills: [
|
|
25
|
+
"tdd",
|
|
26
|
+
"code-review",
|
|
27
|
+
"diagnosing-bugs",
|
|
28
|
+
"resolving-merge-conflicts",
|
|
29
|
+
"writing-for-agents"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
standard: {
|
|
33
|
+
routines: {
|
|
34
|
+
autowork: true,
|
|
35
|
+
"peer-review": true,
|
|
36
|
+
optimizer: true,
|
|
37
|
+
"issues-housekeeping": true,
|
|
38
|
+
"dependency-update-security-check": true,
|
|
39
|
+
"product-planning": false
|
|
40
|
+
},
|
|
41
|
+
skills: [
|
|
42
|
+
"tdd",
|
|
43
|
+
"code-review",
|
|
44
|
+
"codebase-design",
|
|
45
|
+
"domain-modeling",
|
|
46
|
+
"diagnosing-bugs",
|
|
47
|
+
"resolving-merge-conflicts",
|
|
48
|
+
"writing-for-agents",
|
|
49
|
+
"triage"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
full: {
|
|
53
|
+
routines: {
|
|
54
|
+
autowork: true,
|
|
55
|
+
"peer-review": true,
|
|
56
|
+
optimizer: true,
|
|
57
|
+
"issues-housekeeping": true,
|
|
58
|
+
"dependency-update-security-check": true,
|
|
59
|
+
"product-planning": true
|
|
60
|
+
},
|
|
61
|
+
skills: [
|
|
62
|
+
"tdd",
|
|
63
|
+
"code-review",
|
|
64
|
+
"codebase-design",
|
|
65
|
+
"domain-modeling",
|
|
66
|
+
"diagnosing-bugs",
|
|
67
|
+
"resolving-merge-conflicts",
|
|
68
|
+
"writing-for-agents",
|
|
69
|
+
"triage",
|
|
70
|
+
"to-spec",
|
|
71
|
+
"to-tickets"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var ROUTINE_TO_WORKFLOW_MAP = {
|
|
76
|
+
autowork: ["autowork-cron.yml", "trigger-autowork-on-merge.yml", "trigger-autowork-on-bug.yml"],
|
|
77
|
+
"peer-review": ["trigger-review-routine.yml"],
|
|
78
|
+
optimizer: ["prompt-optimizer-cron.yml"],
|
|
79
|
+
"issues-housekeeping": ["issues-housekeeping-cron.yml"],
|
|
80
|
+
"dependency-update-security-check": ["dependency-check-cron.yml"],
|
|
81
|
+
"product-planning": []
|
|
82
|
+
};
|
|
83
|
+
var FLEET_VERSION = "1.0.0";
|
|
84
|
+
var SCHEMA_URL = "https://raw.githubusercontent.com/juliendurandeu/jonah-fleet/main/schema.json";
|
|
85
|
+
|
|
86
|
+
// src/lib/manifest.ts
|
|
87
|
+
var MANIFEST_FILENAME = "agents-manifest.json";
|
|
88
|
+
function loadManifest(targetDir) {
|
|
89
|
+
const manifestPath = path.join(targetDir, MANIFEST_FILENAME);
|
|
90
|
+
if (!fs.existsSync(manifestPath)) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const raw = fs.readFileSync(manifestPath, "utf8");
|
|
95
|
+
return JSON.parse(raw);
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function saveManifest(targetDir, manifest) {
|
|
101
|
+
const manifestPath = path.join(targetDir, MANIFEST_FILENAME);
|
|
102
|
+
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
|
|
103
|
+
}
|
|
104
|
+
function createDefaultManifest(preset = "standard") {
|
|
105
|
+
if (preset === "custom") {
|
|
106
|
+
return {
|
|
107
|
+
$schema: SCHEMA_URL,
|
|
108
|
+
version: FLEET_VERSION,
|
|
109
|
+
preset: "custom",
|
|
110
|
+
routines: {
|
|
111
|
+
autowork: true,
|
|
112
|
+
"peer-review": true,
|
|
113
|
+
optimizer: true,
|
|
114
|
+
"issues-housekeeping": true,
|
|
115
|
+
"dependency-update-security-check": true,
|
|
116
|
+
"product-planning": false
|
|
117
|
+
},
|
|
118
|
+
skills: PRESET_CONFIGS.standard.skills,
|
|
119
|
+
autoUpdate: {
|
|
120
|
+
enabled: true,
|
|
121
|
+
channel: "stable"
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const config = PRESET_CONFIGS[preset];
|
|
126
|
+
return {
|
|
127
|
+
$schema: SCHEMA_URL,
|
|
128
|
+
version: FLEET_VERSION,
|
|
129
|
+
preset,
|
|
130
|
+
routines: { ...config.routines },
|
|
131
|
+
skills: [...config.skills],
|
|
132
|
+
autoUpdate: {
|
|
133
|
+
enabled: true,
|
|
134
|
+
channel: "stable"
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/lib/installer.ts
|
|
140
|
+
import fs2 from "fs";
|
|
141
|
+
import path2 from "path";
|
|
142
|
+
import { fileURLToPath } from "url";
|
|
143
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
144
|
+
var __dirname2 = path2.dirname(__filename2);
|
|
145
|
+
function getTemplatesDir() {
|
|
146
|
+
const candidate1 = path2.resolve(__dirname2, "../templates");
|
|
147
|
+
const candidate2 = path2.resolve(__dirname2, "../../templates");
|
|
148
|
+
if (fs2.existsSync(candidate1)) return candidate1;
|
|
149
|
+
if (fs2.existsSync(candidate2)) return candidate2;
|
|
150
|
+
throw new Error(`Templates directory not found at ${candidate1} or ${candidate2}`);
|
|
151
|
+
}
|
|
152
|
+
function installFleet(targetDir, manifest, options = {}) {
|
|
153
|
+
const templatesDir = getTemplatesDir();
|
|
154
|
+
const result = {
|
|
155
|
+
promptsInstalled: [],
|
|
156
|
+
workflowsInstalled: [],
|
|
157
|
+
skillsInstalled: [],
|
|
158
|
+
docsInstalled: []
|
|
159
|
+
};
|
|
160
|
+
const targetPromptsDir = path2.join(targetDir, ".github/prompts");
|
|
161
|
+
const targetWorkflowsDir = path2.join(targetDir, ".github/workflows");
|
|
162
|
+
const targetSkillsDir = path2.join(targetDir, ".agents/skills");
|
|
163
|
+
fs2.mkdirSync(targetPromptsDir, { recursive: true });
|
|
164
|
+
fs2.mkdirSync(targetWorkflowsDir, { recursive: true });
|
|
165
|
+
fs2.mkdirSync(targetSkillsDir, { recursive: true });
|
|
166
|
+
const basePrompts = ["ORCHESTRATION.md", "_prompt-template.md"];
|
|
167
|
+
for (const file of basePrompts) {
|
|
168
|
+
const src = path2.join(templatesDir, "prompts", file);
|
|
169
|
+
const dest = path2.join(targetPromptsDir, file);
|
|
170
|
+
if (fs2.existsSync(src)) {
|
|
171
|
+
if (!fs2.existsSync(dest) || options.force) {
|
|
172
|
+
fs2.copyFileSync(src, dest);
|
|
173
|
+
result.promptsInstalled.push(file);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const [routineName, isEnabled] of Object.entries(manifest.routines)) {
|
|
178
|
+
if (!isEnabled) continue;
|
|
179
|
+
const promptFile = `${routineName}.md`;
|
|
180
|
+
const promptSrc = path2.join(templatesDir, "prompts", promptFile);
|
|
181
|
+
const promptDest = path2.join(targetPromptsDir, promptFile);
|
|
182
|
+
if (fs2.existsSync(promptSrc)) {
|
|
183
|
+
if (!fs2.existsSync(promptDest) || options.force) {
|
|
184
|
+
fs2.copyFileSync(promptSrc, promptDest);
|
|
185
|
+
result.promptsInstalled.push(promptFile);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const workflows = ROUTINE_TO_WORKFLOW_MAP[routineName] || [];
|
|
189
|
+
for (const workflowFile of workflows) {
|
|
190
|
+
const wfSrc = path2.join(templatesDir, "workflows", workflowFile);
|
|
191
|
+
const wfDest = path2.join(targetWorkflowsDir, workflowFile);
|
|
192
|
+
if (fs2.existsSync(wfSrc)) {
|
|
193
|
+
if (!fs2.existsSync(wfDest) || options.force) {
|
|
194
|
+
fs2.copyFileSync(wfSrc, wfDest);
|
|
195
|
+
result.workflowsInstalled.push(workflowFile);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (manifest.autoUpdate?.enabled) {
|
|
201
|
+
const syncWfSrc = path2.join(templatesDir, "workflows/sync-fleet.yml");
|
|
202
|
+
const syncWfDest = path2.join(targetWorkflowsDir, "sync-fleet.yml");
|
|
203
|
+
if (fs2.existsSync(syncWfSrc)) {
|
|
204
|
+
if (!fs2.existsSync(syncWfDest) || options.force) {
|
|
205
|
+
fs2.copyFileSync(syncWfSrc, syncWfDest);
|
|
206
|
+
result.workflowsInstalled.push("sync-fleet.yml");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
for (const skill of manifest.skills) {
|
|
211
|
+
const skillSrcDir = path2.join(templatesDir, "skills", skill);
|
|
212
|
+
const skillDestDir = path2.join(targetSkillsDir, skill);
|
|
213
|
+
if (fs2.existsSync(skillSrcDir)) {
|
|
214
|
+
if (!fs2.existsSync(skillDestDir) || options.force) {
|
|
215
|
+
fs2.cpSync(skillSrcDir, skillDestDir, { recursive: true });
|
|
216
|
+
result.skillsInstalled.push(skill);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const agentsPath = path2.join(targetDir, "AGENTS.md");
|
|
221
|
+
const claudePath = path2.join(targetDir, "CLAUDE.md");
|
|
222
|
+
const geminiPath = path2.join(targetDir, "GEMINI.md");
|
|
223
|
+
if (!fs2.existsSync(agentsPath) && !fs2.existsSync(claudePath) && !fs2.existsSync(geminiPath)) {
|
|
224
|
+
const docSrc = path2.join(templatesDir, "docs/AGENTS.template.md");
|
|
225
|
+
if (fs2.existsSync(docSrc)) {
|
|
226
|
+
fs2.copyFileSync(docSrc, agentsPath);
|
|
227
|
+
result.docsInstalled.push("AGENTS.md");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// src/commands/init.ts
|
|
234
|
+
async function runInit(options = {}) {
|
|
235
|
+
const cwd = options.cwd || process.cwd();
|
|
236
|
+
const preset = options.preset || "standard";
|
|
237
|
+
console.log(pc.cyan(`
|
|
238
|
+
\u2693 Initializing Jonah Fleet (preset: ${pc.bold(preset)}) in ${cwd}
|
|
239
|
+
`));
|
|
240
|
+
let manifest = loadManifest(cwd);
|
|
241
|
+
if (manifest && !options.force) {
|
|
242
|
+
console.log(pc.yellow(`\u26A0\uFE0F Found existing agents-manifest.json. Updating with preset '${preset}'...`));
|
|
243
|
+
} else {
|
|
244
|
+
manifest = createDefaultManifest(preset);
|
|
245
|
+
}
|
|
246
|
+
saveManifest(cwd, manifest);
|
|
247
|
+
console.log(pc.green(`\u2713 Created/Updated agents-manifest.json`));
|
|
248
|
+
const result = installFleet(cwd, manifest, { force: options.force });
|
|
249
|
+
console.log(pc.bold("\nInstalled components:"));
|
|
250
|
+
if (result.promptsInstalled.length > 0) {
|
|
251
|
+
console.log(pc.green(` \u{1F4C1} Prompts (.github/prompts/):`));
|
|
252
|
+
result.promptsInstalled.forEach((p) => console.log(` - ${p}`));
|
|
253
|
+
}
|
|
254
|
+
if (result.workflowsInstalled.length > 0) {
|
|
255
|
+
console.log(pc.green(` \u2699\uFE0F Workflows (.github/workflows/):`));
|
|
256
|
+
result.workflowsInstalled.forEach((w) => console.log(` - ${w}`));
|
|
257
|
+
}
|
|
258
|
+
if (result.skillsInstalled.length > 0) {
|
|
259
|
+
console.log(pc.green(` \u{1F9E0} Skills (.agents/skills/):`));
|
|
260
|
+
result.skillsInstalled.forEach((s) => console.log(` - ${s}`));
|
|
261
|
+
}
|
|
262
|
+
if (result.docsInstalled.length > 0) {
|
|
263
|
+
console.log(pc.green(` \u{1F4C4} Documentation:`));
|
|
264
|
+
result.docsInstalled.forEach((d) => console.log(` - ${d}`));
|
|
265
|
+
}
|
|
266
|
+
console.log(pc.bold(pc.green("\n\u{1F389} Jonah Fleet initialization complete!\n")));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/commands/sync.ts
|
|
270
|
+
import pc2 from "picocolors";
|
|
271
|
+
|
|
272
|
+
// src/lib/diff.ts
|
|
273
|
+
import fs3 from "fs";
|
|
274
|
+
import path3 from "path";
|
|
275
|
+
function checkDrift(targetDir, manifest) {
|
|
276
|
+
const templatesDir = getTemplatesDir();
|
|
277
|
+
const report = {
|
|
278
|
+
missingPrompts: [],
|
|
279
|
+
modifiedPrompts: [],
|
|
280
|
+
missingWorkflows: [],
|
|
281
|
+
modifiedWorkflows: [],
|
|
282
|
+
missingSkills: []
|
|
283
|
+
};
|
|
284
|
+
const targetPromptsDir = path3.join(targetDir, ".github/prompts");
|
|
285
|
+
const targetWorkflowsDir = path3.join(targetDir, ".github/workflows");
|
|
286
|
+
const targetSkillsDir = path3.join(targetDir, ".agents/skills");
|
|
287
|
+
const basePrompts = ["ORCHESTRATION.md", "_prompt-template.md"];
|
|
288
|
+
for (const file of basePrompts) {
|
|
289
|
+
const src = path3.join(templatesDir, "prompts", file);
|
|
290
|
+
const dest = path3.join(targetPromptsDir, file);
|
|
291
|
+
if (!fs3.existsSync(dest)) {
|
|
292
|
+
report.missingPrompts.push(file);
|
|
293
|
+
} else if (fs3.readFileSync(src, "utf8") !== fs3.readFileSync(dest, "utf8")) {
|
|
294
|
+
report.modifiedPrompts.push(file);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
for (const [routineName, isEnabled] of Object.entries(manifest.routines)) {
|
|
298
|
+
if (!isEnabled) continue;
|
|
299
|
+
const promptFile = `${routineName}.md`;
|
|
300
|
+
const promptSrc = path3.join(templatesDir, "prompts", promptFile);
|
|
301
|
+
const promptDest = path3.join(targetPromptsDir, promptFile);
|
|
302
|
+
if (!fs3.existsSync(promptDest)) {
|
|
303
|
+
report.missingPrompts.push(promptFile);
|
|
304
|
+
} else if (fs3.existsSync(promptSrc) && fs3.readFileSync(promptSrc, "utf8") !== fs3.readFileSync(promptDest, "utf8")) {
|
|
305
|
+
report.modifiedPrompts.push(promptFile);
|
|
306
|
+
}
|
|
307
|
+
const workflows = ROUTINE_TO_WORKFLOW_MAP[routineName] || [];
|
|
308
|
+
for (const workflowFile of workflows) {
|
|
309
|
+
const wfSrc = path3.join(templatesDir, "workflows", workflowFile);
|
|
310
|
+
const wfDest = path3.join(targetWorkflowsDir, workflowFile);
|
|
311
|
+
if (!fs3.existsSync(wfDest)) {
|
|
312
|
+
report.missingWorkflows.push(workflowFile);
|
|
313
|
+
} else if (fs3.existsSync(wfSrc) && fs3.readFileSync(wfSrc, "utf8") !== fs3.readFileSync(wfDest, "utf8")) {
|
|
314
|
+
report.modifiedWorkflows.push(workflowFile);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
for (const skill of manifest.skills) {
|
|
319
|
+
const skillDestDir = path3.join(targetSkillsDir, skill);
|
|
320
|
+
if (!fs3.existsSync(skillDestDir)) {
|
|
321
|
+
report.missingSkills.push(skill);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return report;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/commands/sync.ts
|
|
328
|
+
async function runSync(options = {}) {
|
|
329
|
+
const cwd = options.cwd || process.cwd();
|
|
330
|
+
const manifest = loadManifest(cwd);
|
|
331
|
+
if (!manifest) {
|
|
332
|
+
console.error(pc2.red(`\u274C No agents-manifest.json found in ${cwd}. Run 'jonah-fleet init' first.`));
|
|
333
|
+
process.exit(1);
|
|
334
|
+
}
|
|
335
|
+
console.log(pc2.cyan(`
|
|
336
|
+
\u{1F504} Syncing Jonah Fleet (current: v${manifest.version}, fleet: v${FLEET_VERSION})...
|
|
337
|
+
`));
|
|
338
|
+
const drift = checkDrift(cwd, manifest);
|
|
339
|
+
const hasDrift = drift.missingPrompts.length > 0 || drift.modifiedPrompts.length > 0 || drift.missingWorkflows.length > 0 || drift.modifiedWorkflows.length > 0 || drift.missingSkills.length > 0;
|
|
340
|
+
if (options.check) {
|
|
341
|
+
if (!hasDrift && manifest.version === FLEET_VERSION) {
|
|
342
|
+
console.log(pc2.green(`\u2713 All routines, workflows, and skills are perfectly in sync with v${FLEET_VERSION}.
|
|
343
|
+
`));
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
console.log(pc2.yellow(`\u26A0\uFE0F Drift or updates detected:`));
|
|
347
|
+
if (drift.missingPrompts.length > 0) console.log(pc2.red(` Missing prompts: ${drift.missingPrompts.join(", ")}`));
|
|
348
|
+
if (drift.modifiedPrompts.length > 0) console.log(pc2.yellow(` Modified prompts: ${drift.modifiedPrompts.join(", ")}`));
|
|
349
|
+
if (drift.missingWorkflows.length > 0) console.log(pc2.red(` Missing workflows: ${drift.missingWorkflows.join(", ")}`));
|
|
350
|
+
if (drift.modifiedWorkflows.length > 0) console.log(pc2.yellow(` Modified workflows: ${drift.modifiedWorkflows.join(", ")}`));
|
|
351
|
+
if (drift.missingSkills.length > 0) console.log(pc2.red(` Missing skills: ${drift.missingSkills.join(", ")}`));
|
|
352
|
+
console.log(pc2.cyan(`
|
|
353
|
+
Run 'jonah-fleet sync --force' to apply updates.
|
|
354
|
+
`));
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
manifest.version = FLEET_VERSION;
|
|
358
|
+
saveManifest(cwd, manifest);
|
|
359
|
+
const result = installFleet(cwd, manifest, { force: true });
|
|
360
|
+
console.log(pc2.green(`\u2713 Synchronized with Jonah Fleet v${FLEET_VERSION}`));
|
|
361
|
+
console.log(pc2.green(`\u2713 Updated ${result.promptsInstalled.length} prompts, ${result.workflowsInstalled.length} workflows, and ${result.skillsInstalled.length} skills.
|
|
362
|
+
`));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// src/commands/status.ts
|
|
366
|
+
import pc3 from "picocolors";
|
|
367
|
+
async function runStatus(options = {}) {
|
|
368
|
+
const cwd = options.cwd || process.cwd();
|
|
369
|
+
const manifest = loadManifest(cwd);
|
|
370
|
+
if (!manifest) {
|
|
371
|
+
console.log(pc3.yellow(`
|
|
372
|
+
\u26A0\uFE0F No agents-manifest.json found in ${cwd}. This project is not configured with Jonah Fleet.`));
|
|
373
|
+
console.log(pc3.cyan(`Run 'npx jonah-fleet init' to set up autonomous agent routines.
|
|
374
|
+
`));
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
console.log(pc3.bold(pc3.cyan(`
|
|
378
|
+
\u{1F4CA} Jonah Fleet Status for ${cwd}
|
|
379
|
+
`)));
|
|
380
|
+
console.log(` Version: ${manifest.version === FLEET_VERSION ? pc3.green(manifest.version) : pc3.yellow(`${manifest.version} (fleet latest: ${FLEET_VERSION})`)}`);
|
|
381
|
+
console.log(` Preset: ${pc3.bold(manifest.preset)}`);
|
|
382
|
+
console.log(` Auto-Update: ${manifest.autoUpdate?.enabled ? pc3.green("Enabled (" + manifest.autoUpdate.channel + ")") : pc3.gray("Disabled")}`);
|
|
383
|
+
console.log(pc3.bold("\n Enabled Routines:"));
|
|
384
|
+
for (const [routine, enabled] of Object.entries(manifest.routines)) {
|
|
385
|
+
console.log(` - ${routine.padEnd(35)}: ${enabled ? pc3.green("ENABLED") : pc3.gray("DISABLED")}`);
|
|
386
|
+
}
|
|
387
|
+
console.log(pc3.bold("\n Configured Skills:"));
|
|
388
|
+
for (const skill of manifest.skills) {
|
|
389
|
+
console.log(` - ${pc3.cyan(skill)}`);
|
|
390
|
+
}
|
|
391
|
+
const drift = checkDrift(cwd, manifest);
|
|
392
|
+
const hasDrift = drift.missingPrompts.length > 0 || drift.modifiedPrompts.length > 0 || drift.missingWorkflows.length > 0 || drift.modifiedWorkflows.length > 0 || drift.missingSkills.length > 0;
|
|
393
|
+
console.log(pc3.bold("\n Drift / Health:"));
|
|
394
|
+
if (!hasDrift) {
|
|
395
|
+
console.log(pc3.green(" \u2713 All prompts, workflows, and skills are healthy and match fleet templates.\n"));
|
|
396
|
+
} else {
|
|
397
|
+
if (drift.missingPrompts.length > 0) console.log(pc3.red(` \u274C Missing prompts: ${drift.missingPrompts.join(", ")}`));
|
|
398
|
+
if (drift.modifiedPrompts.length > 0) console.log(pc3.yellow(` \u26A0\uFE0F Modified prompts: ${drift.modifiedPrompts.join(", ")}`));
|
|
399
|
+
if (drift.missingWorkflows.length > 0) console.log(pc3.red(` \u274C Missing workflows: ${drift.missingWorkflows.join(", ")}`));
|
|
400
|
+
if (drift.modifiedWorkflows.length > 0) console.log(pc3.yellow(` \u26A0\uFE0F Modified workflows: ${drift.modifiedWorkflows.join(", ")}`));
|
|
401
|
+
if (drift.missingSkills.length > 0) console.log(pc3.red(` \u274C Missing skills: ${drift.missingSkills.join(", ")}`));
|
|
402
|
+
console.log(pc3.cyan("\n Run 'jonah-fleet sync' to synchronize files.\n"));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/commands/contribute.ts
|
|
407
|
+
import { execSync } from "child_process";
|
|
408
|
+
import pc4 from "picocolors";
|
|
409
|
+
async function runContribute(options = {}) {
|
|
410
|
+
console.log(pc4.cyan(`
|
|
411
|
+
\u{1F680} Jonah Fleet Upstream Contribution Bridge
|
|
412
|
+
`));
|
|
413
|
+
const title = options.title || "fix(prompts): improve orchestrator routine handling";
|
|
414
|
+
const body = options.body || "Proposed prompt optimization discovered during autonomous execution runs.";
|
|
415
|
+
console.log(`Preparing upstream contribution PR against ${pc4.bold("juliendurandeu/jonah-fleet")}...`);
|
|
416
|
+
console.log(`Title: ${pc4.green(title)}`);
|
|
417
|
+
console.log(`Body: ${pc4.gray(body)}
|
|
418
|
+
`);
|
|
419
|
+
try {
|
|
420
|
+
const branchName = `contrib/optimize-${Date.now()}`;
|
|
421
|
+
console.log(`Creating branch ${pc4.cyan(branchName)}...`);
|
|
422
|
+
try {
|
|
423
|
+
execSync("gh auth status", { stdio: "pipe" });
|
|
424
|
+
} catch {
|
|
425
|
+
console.error(pc4.red("\u274C GitHub CLI (`gh`) is not authenticated. Run `gh auth login` first."));
|
|
426
|
+
process.exit(1);
|
|
427
|
+
}
|
|
428
|
+
console.log(pc4.green(`\u2713 Ready to package and submit upstream contribution to juliendurandeu/jonah-fleet.`));
|
|
429
|
+
console.log(pc4.cyan(`Command executed by optimizer routine or operator:
|
|
430
|
+
`));
|
|
431
|
+
console.log(` gh pr create --repo juliendurandeu/jonah-fleet --title "${title}" --body "${body}"
|
|
432
|
+
`);
|
|
433
|
+
} catch (err) {
|
|
434
|
+
console.error(pc4.red(`\u274C Error during contribution preparation: ${err.message}`));
|
|
435
|
+
process.exit(1);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// src/index.ts
|
|
440
|
+
var program = new Command();
|
|
441
|
+
program.name("jonah-fleet").description("Manage autonomous agent fleet, prompt routines, workflows, and skills").version(FLEET_VERSION);
|
|
442
|
+
program.command("init").description("Initialize Jonah Fleet configuration, routines, workflows, and skills in the current repo").option("-p, --preset <preset>", "Preset profile to install (minimal | standard | full)", "standard").option("-f, --force", "Force overwrite existing files", false).action(async (options) => {
|
|
443
|
+
await runInit(options);
|
|
444
|
+
});
|
|
445
|
+
program.command("sync").description("Synchronize local prompts, workflows, and skills with the installed fleet version").option("-c, --check", "Check for drift without writing changes", false).option("-f, --force", "Force update all files to match fleet version", false).action(async (options) => {
|
|
446
|
+
await runSync(options);
|
|
447
|
+
});
|
|
448
|
+
program.command("status").description("Check the status, health, and drift of installed agent routines and skills").action(async (options) => {
|
|
449
|
+
await runStatus(options);
|
|
450
|
+
});
|
|
451
|
+
program.command("contribute").description("Submit local prompt improvements back upstream to jonah-fleet").option("-t, --title <title>", "Contribution PR title").option("-b, --body <body>", "Contribution PR description").action(async (options) => {
|
|
452
|
+
await runContribute(options);
|
|
453
|
+
});
|
|
454
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jonah-fleet",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Standalone autonomous agent fleet with Symphony orchestration, claim protocols, and continuous improvement loops",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"jonah-fleet": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"dev": "tsup --watch",
|
|
14
|
+
"lint": "eslint src tests",
|
|
15
|
+
"type-check": "tsc --noEmit",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"format": "prettier --write \"**/*.{ts,json,md,yml}\""
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"agents",
|
|
22
|
+
"antigravity",
|
|
23
|
+
"symphony",
|
|
24
|
+
"autowork",
|
|
25
|
+
"code-review",
|
|
26
|
+
"llm-orchestration"
|
|
27
|
+
],
|
|
28
|
+
"author": "Julien Durandeu",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"commander": "^12.1.0",
|
|
32
|
+
"picocolors": "^1.1.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.10.2",
|
|
36
|
+
"tsup": "^8.3.5",
|
|
37
|
+
"typescript": "^5.7.2",
|
|
38
|
+
"vitest": "^2.1.8"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"templates",
|
|
43
|
+
"schema.json",
|
|
44
|
+
"README.md",
|
|
45
|
+
"CHANGELOG.md"
|
|
46
|
+
]
|
|
47
|
+
}
|