opencastle 0.32.5 → 0.32.7
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/README.md +13 -3
- package/bin/cli.mjs +2 -0
- package/dist/cli/convoy/engine.d.ts.map +1 -1
- package/dist/cli/convoy/engine.js +79 -4
- package/dist/cli/convoy/engine.js.map +1 -1
- package/dist/cli/convoy/engine.test.js +11 -9
- package/dist/cli/convoy/engine.test.js.map +1 -1
- package/dist/dashboard/scripts/etl.js +17 -2
- package/dist/dashboard/scripts/etl.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/convoy/engine.test.ts +11 -9
- package/src/cli/convoy/engine.ts +78 -4
- package/src/dashboard/dist/_astro/index.6xXNs4L2.css +1 -0
- package/src/dashboard/dist/data/convoy-list.json +27 -13
- package/src/dashboard/dist/data/convoys/demo-api-v2.json +16 -10
- package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +25 -15
- package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +35 -21
- package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +17 -11
- package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +8 -4
- package/src/dashboard/dist/data/convoys/demo-docs-update.json +13 -9
- package/src/dashboard/dist/data/convoys/demo-perf-opt.json +22 -14
- package/src/dashboard/dist/data/overall-stats.json +36 -2
- package/src/dashboard/dist/index.html +149 -93
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/dashboard/public/data/convoy-list.json +27 -13
- package/src/dashboard/public/data/convoys/demo-api-v2.json +16 -10
- package/src/dashboard/public/data/convoys/demo-auth-revamp.json +25 -15
- package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +35 -21
- package/src/dashboard/public/data/convoys/demo-data-pipeline.json +17 -11
- package/src/dashboard/public/data/convoys/demo-deploy-ci.json +8 -4
- package/src/dashboard/public/data/convoys/demo-docs-update.json +13 -9
- package/src/dashboard/public/data/convoys/demo-perf-opt.json +22 -14
- package/src/dashboard/public/data/overall-stats.json +36 -2
- package/src/dashboard/scripts/etl.ts +15 -3
- package/src/dashboard/scripts/generate-demo-db.ts +42 -34
- package/src/dashboard/src/pages/index.astro +159 -112
- package/src/dashboard/src/styles/dashboard.css +58 -3
- package/src/orchestrator/agents/api-designer.agent.md +25 -34
- package/src/orchestrator/agents/architect.agent.md +40 -84
- package/src/orchestrator/agents/content-engineer.agent.md +29 -31
- package/src/orchestrator/agents/copywriter.agent.md +35 -60
- package/src/orchestrator/agents/data-expert.agent.md +24 -30
- package/src/orchestrator/agents/database-engineer.agent.md +26 -31
- package/src/orchestrator/agents/developer.agent.md +32 -34
- package/src/orchestrator/agents/devops-expert.agent.md +31 -26
- package/src/orchestrator/agents/documentation-writer.agent.md +29 -29
- package/src/orchestrator/agents/performance-expert.agent.md +36 -33
- package/src/orchestrator/agents/release-manager.agent.md +25 -34
- package/src/orchestrator/agents/researcher.agent.md +41 -95
- package/src/orchestrator/agents/reviewer.agent.md +24 -34
- package/src/orchestrator/agents/security-expert.agent.md +35 -39
- package/src/orchestrator/agents/seo-specialist.agent.md +25 -32
- package/src/orchestrator/agents/session-guard.agent.md +20 -79
- package/src/orchestrator/agents/team-lead.agent.md +50 -254
- package/src/orchestrator/agents/testing-expert.agent.md +37 -49
- package/src/orchestrator/agents/ui-ux-expert.agent.md +33 -39
- package/src/orchestrator/customizations/KNOWN-ISSUES.md +0 -1
- package/src/orchestrator/customizations/agents/skill-matrix.json +12 -0
- package/src/orchestrator/instructions/general.instructions.md +24 -84
- package/src/orchestrator/plugins/astro/SKILL.md +23 -179
- package/src/orchestrator/plugins/convex/SKILL.md +38 -12
- package/src/orchestrator/plugins/netlify/SKILL.md +17 -13
- package/src/orchestrator/plugins/nextjs/SKILL.md +55 -261
- package/src/orchestrator/plugins/nx/SKILL.md +20 -72
- package/src/orchestrator/plugins/playwright/SKILL.md +5 -17
- package/src/orchestrator/plugins/slack/SKILL.md +28 -190
- package/src/orchestrator/plugins/teams/SKILL.md +10 -140
- package/src/orchestrator/plugins/vitest/SKILL.md +2 -2
- package/src/orchestrator/prompts/bug-fix.prompt.md +25 -63
- package/src/orchestrator/prompts/implement-feature.prompt.md +29 -66
- package/src/orchestrator/prompts/quick-refinement.prompt.md +31 -66
- package/src/orchestrator/skills/accessibility-standards/SKILL.md +50 -105
- package/src/orchestrator/skills/agent-hooks/SKILL.md +60 -110
- package/src/orchestrator/skills/agent-memory/SKILL.md +44 -93
- package/src/orchestrator/skills/api-patterns/SKILL.md +20 -68
- package/src/orchestrator/skills/code-commenting/SKILL.md +49 -101
- package/src/orchestrator/skills/context-map/SKILL.md +47 -88
- package/src/orchestrator/skills/data-engineering/SKILL.md +27 -74
- package/src/orchestrator/skills/decomposition/SKILL.md +50 -98
- package/src/orchestrator/skills/deployment-infrastructure/SKILL.md +44 -107
- package/src/orchestrator/skills/documentation-standards/SKILL.md +28 -89
- package/src/orchestrator/skills/fast-review/SKILL.md +51 -276
- package/src/orchestrator/skills/frontend-design/SKILL.md +53 -163
- package/src/orchestrator/skills/git-workflow/SKILL.md +18 -54
- package/src/orchestrator/skills/memory-merger/SKILL.md +51 -88
- package/src/orchestrator/skills/observability-logging/SKILL.md +29 -75
- package/src/orchestrator/skills/orchestration-protocols/SKILL.md +58 -117
- package/src/orchestrator/skills/panel-majority-vote/SKILL.md +65 -140
- package/src/orchestrator/skills/performance-optimization/SKILL.md +21 -85
- package/src/orchestrator/skills/project-consistency/SKILL.md +62 -281
- package/src/orchestrator/skills/react-development/SKILL.md +38 -86
- package/src/orchestrator/skills/security-hardening/SKILL.md +40 -84
- package/src/orchestrator/skills/self-improvement/SKILL.md +26 -60
- package/src/orchestrator/skills/seo-patterns/SKILL.md +40 -105
- package/src/orchestrator/skills/session-checkpoints/SKILL.md +26 -68
- package/src/orchestrator/skills/team-lead-reference/SKILL.md +66 -206
- package/src/orchestrator/skills/testing-workflow/SKILL.md +42 -112
- package/src/orchestrator/skills/validation-gates/SKILL.md +39 -170
- package/src/orchestrator/snippets/base-output-contract.md +14 -0
- package/src/orchestrator/snippets/discovered-issues-policy.md +15 -0
- package/src/orchestrator/snippets/logging-mandatory.md +11 -0
- package/src/orchestrator/snippets/never-expose-secrets.md +22 -0
- package/src/dashboard/dist/_astro/index.wyN9vmjZ.css +0 -1
- package/src/dashboard/dist/data/convoys/demo-convoy-1.json +0 -111
- package/src/dashboard/dist/data/convoys/demo-convoy-2.json +0 -72
- package/src/dashboard/dist/data/pipelines.ndjson +0 -5285
- package/src/dashboard/public/data/convoys/demo-convoy-1.json +0 -111
- package/src/dashboard/public/data/convoys/demo-convoy-2.json +0 -72
- package/src/dashboard/public/data/pipelines.ndjson +0 -5285
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ MCP servers are auto-configured for your stack in each IDE's native format.
|
|
|
65
65
|
|
|
66
66
|
<br>
|
|
67
67
|
|
|
68
|
-
### CLI
|
|
68
|
+
### Project CLI
|
|
69
69
|
|
|
70
70
|
| Command | Description |
|
|
71
71
|
|---------|-------------|
|
|
@@ -73,11 +73,23 @@ MCP servers are auto-configured for your stack in each IDE's native format.
|
|
|
73
73
|
| `opencastle update` | Update framework files (keeps your customizations) |
|
|
74
74
|
| `opencastle eject` | Remove the dependency, keep all files |
|
|
75
75
|
| `opencastle destroy` | Remove ALL OpenCastle files (reverse of init) |
|
|
76
|
+
| `opencastle skills` | Skill refinement and failure tracking |
|
|
77
|
+
| `opencastle package` | Package orchestrator as a plugin for IDE marketplaces |
|
|
78
|
+
|
|
79
|
+
### Convoy CLI
|
|
80
|
+
|
|
81
|
+
| Command | Description |
|
|
82
|
+
|---------|-------------|
|
|
76
83
|
| `opencastle start` | Go from idea to convoy spec in one command (PRD → validate → convoy → validate → fix) |
|
|
77
84
|
| `opencastle plan` | Run a single prompt template step (generate PRD, convoy spec, or validate) |
|
|
78
85
|
| `opencastle validate` | Validate a convoy YAML spec file without executing it |
|
|
79
86
|
| `opencastle run` | Run the Convoy Engine (deterministic, crash-recoverable orchestrator) |
|
|
80
87
|
| `opencastle dispute` | Manage convoy dispute resolution |
|
|
88
|
+
|
|
89
|
+
### Observability CLI
|
|
90
|
+
|
|
91
|
+
| Command | Description |
|
|
92
|
+
|---------|-------------|
|
|
81
93
|
| `opencastle dashboard` | Open the observability dashboard |
|
|
82
94
|
| `opencastle doctor` | Validate your setup and surface issues |
|
|
83
95
|
| `opencastle agents` | Manage persistent agent identities |
|
|
@@ -86,8 +98,6 @@ MCP servers are auto-configured for your stack in each IDE's native format.
|
|
|
86
98
|
| `opencastle lesson` | Append a structured lesson to LESSONS-LEARNED.md |
|
|
87
99
|
| `opencastle artifacts` | Manage filesystem artifact storage (prune old convoy artifacts) |
|
|
88
100
|
| `opencastle insights` | Analyze convoy execution history and generate recommendations |
|
|
89
|
-
| `opencastle skills` | Skill refinement and failure tracking |
|
|
90
|
-
| `opencastle package` | Package orchestrator as a plugin for IDE marketplaces |
|
|
91
101
|
|
|
92
102
|
Add `--dry-run` to any command to preview what it would change without writing files.
|
|
93
103
|
|
package/bin/cli.mjs
CHANGED
|
@@ -23,6 +23,8 @@ const HELP = `
|
|
|
23
23
|
eject Remove dependency, keep all files standalone
|
|
24
24
|
destroy Remove ALL OpenCastle files (reverse of init)
|
|
25
25
|
doctor Validate your OpenCastle setup
|
|
26
|
+
package Package your OpenCastle project for IDE marketplaces
|
|
27
|
+
skills Manage and analyze agent skills and failures
|
|
26
28
|
|
|
27
29
|
Convoy Commands:
|
|
28
30
|
start Run the full generate PRD → validate PRD → auto-fix PRD
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/cli/convoy/engine.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAQ,QAAQ,EAAE,YAAY,EAAiB,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChG,OAAO,EAA+C,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAG1F,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,EAAwC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAElF,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAoB,WAAW,EAAE,oBAAoB,EAAwD,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/cli/convoy/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,28 @@ import { getArtifactDir, extractArtifactRefs } from './artifacts.js';
|
|
|
29
29
|
import { shouldCompact, parseCompactionSummary, saveCompaction, canCompact, getMaxCompactions, generateCompactionPrompt, buildContinuationPrompt } from './compaction.js';
|
|
30
30
|
import { calculateCost } from './pricing.js';
|
|
31
31
|
const execFile = promisify(execFileCb);
|
|
32
|
+
/** Map agent names to their default model. Used when adapters don't report model. */
|
|
33
|
+
const AGENT_MODEL_MAP = {
|
|
34
|
+
'developer': 'claude-sonnet-4-6',
|
|
35
|
+
'ui-ux-expert': 'claude-sonnet-4-6',
|
|
36
|
+
'testing-expert': 'claude-sonnet-4-6',
|
|
37
|
+
'security-expert': 'claude-sonnet-4-6',
|
|
38
|
+
'performance-expert': 'claude-sonnet-4-6',
|
|
39
|
+
'devops-expert': 'claude-sonnet-4-6',
|
|
40
|
+
'data-expert': 'claude-sonnet-4-6',
|
|
41
|
+
'api-designer': 'claude-sonnet-4-6',
|
|
42
|
+
'copywriter': 'claude-sonnet-4-6',
|
|
43
|
+
'content-engineer': 'claude-sonnet-4-6',
|
|
44
|
+
'database-engineer': 'claude-sonnet-4-6',
|
|
45
|
+
'researcher': 'claude-sonnet-4-6',
|
|
46
|
+
'release-manager': 'claude-sonnet-4-6',
|
|
47
|
+
'architect': 'claude-opus-4-6',
|
|
48
|
+
'team-lead': 'claude-opus-4-6',
|
|
49
|
+
'reviewer': 'claude-haiku-3-5',
|
|
50
|
+
'documentation-writer': 'claude-haiku-3-5',
|
|
51
|
+
'seo-specialist': 'claude-haiku-3-5',
|
|
52
|
+
'session-guard': 'claude-haiku-3-5',
|
|
53
|
+
};
|
|
32
54
|
export class CircuitBreakerManager {
|
|
33
55
|
states = new Map();
|
|
34
56
|
threshold;
|
|
@@ -976,7 +998,7 @@ async function runConvoy(convoyId, spec, adapter, store, events, wtManager, merg
|
|
|
976
998
|
}
|
|
977
999
|
}
|
|
978
1000
|
process.stdout.write(` ${c.cyan('▶')} ${c.bold(`[${taskRecord.id}]`)} ${taskRecord.agent}${worktreePath ? c.dim(' (worktree)') : ''}\n`);
|
|
979
|
-
events.emit('task_started', { worker_id: workerId }, { convoy_id: convoyId, task_id: taskRecord.id, worker_id: workerId });
|
|
1001
|
+
events.emit('task_started', { worker_id: workerId, mechanism: worktreePath ? 'background' : 'sub-agent' }, { convoy_id: convoyId, task_id: taskRecord.id, worker_id: workerId });
|
|
980
1002
|
const taskStartTime = Date.now();
|
|
981
1003
|
// ── Outbound prompt scan — NEVER send a prompt containing secrets ─────────
|
|
982
1004
|
const promptScan = scanForSecrets(taskRecord.prompt, `task:${taskRecord.id}`);
|
|
@@ -1167,10 +1189,20 @@ async function runConvoy(convoyId, spec, adapter, store, events, wtManager, merg
|
|
|
1167
1189
|
process.stdout.write(` ${c.yellow('⟳')} ${c.bold(`[${taskRecord.id}]`)} timed out, retry ${freshRecord.retries + 1}/${freshRecord.max_retries}\n`);
|
|
1168
1190
|
}
|
|
1169
1191
|
else {
|
|
1192
|
+
// Estimate tokens even for timed-out tasks — you still paid for them
|
|
1193
|
+
const estimatedPrompt = Math.ceil(taskRecord.prompt.length / 4);
|
|
1194
|
+
const estimatedCompletion = Math.ceil((result.output?.length ?? 0) / 4);
|
|
1195
|
+
const timeoutModel = taskRecord.model ?? AGENT_MODEL_MAP[taskRecord.agent.toLowerCase()] ?? taskAdapter.name;
|
|
1196
|
+
const timeoutCost = calculateCost(timeoutModel, estimatedPrompt, estimatedCompletion);
|
|
1170
1197
|
store.withTransaction(() => {
|
|
1171
1198
|
store.updateTaskStatus(taskRecord.id, convoyId, 'timed-out', {
|
|
1172
1199
|
finished_at: finishedAt,
|
|
1173
1200
|
output: result.output,
|
|
1201
|
+
prompt_tokens: estimatedPrompt,
|
|
1202
|
+
completion_tokens: estimatedCompletion,
|
|
1203
|
+
total_tokens: estimatedPrompt + estimatedCompletion,
|
|
1204
|
+
model: timeoutModel,
|
|
1205
|
+
cost_usd: timeoutCost,
|
|
1174
1206
|
});
|
|
1175
1207
|
store.updateWorkerStatus(workerId, 'failed', { finished_at: finishedAt });
|
|
1176
1208
|
});
|
|
@@ -1977,8 +2009,16 @@ async function runConvoy(convoyId, spec, adapter, store, events, wtManager, merg
|
|
|
1977
2009
|
if (result.usage.total_tokens != null)
|
|
1978
2010
|
usageExtra.total_tokens = result.usage.total_tokens;
|
|
1979
2011
|
}
|
|
1980
|
-
else
|
|
1981
|
-
|
|
2012
|
+
else {
|
|
2013
|
+
// Estimate tokens from prompt/output text length (~4 chars per token)
|
|
2014
|
+
const estimatedPrompt = Math.ceil(taskRecord.prompt.length / 4);
|
|
2015
|
+
const estimatedCompletion = Math.ceil((result.output?.length ?? 0) / 4);
|
|
2016
|
+
usageExtra.prompt_tokens = estimatedPrompt;
|
|
2017
|
+
usageExtra.completion_tokens = estimatedCompletion;
|
|
2018
|
+
usageExtra.total_tokens = estimatedPrompt + estimatedCompletion;
|
|
2019
|
+
if (verbose) {
|
|
2020
|
+
process.stdout.write(` ${c.dim('ℹ')} Estimated ${usageExtra.total_tokens} tokens (adapter ${taskAdapter.name} returned no usage data)\n`);
|
|
2021
|
+
}
|
|
1982
2022
|
}
|
|
1983
2023
|
// ── Context compaction check (Phase 44) ─────────────────────────────
|
|
1984
2024
|
const compactionConfig = spec.defaults?.compaction;
|
|
@@ -2091,6 +2131,31 @@ async function runConvoy(convoyId, spec, adapter, store, events, wtManager, merg
|
|
|
2091
2131
|
catch (err) {
|
|
2092
2132
|
process.stderr.write(`[artifacts] Warning: extraction failed for task ${taskRecord.id}: ${err.message}\n`);
|
|
2093
2133
|
}
|
|
2134
|
+
// ── Create file artifacts from task file list ────────────────────────
|
|
2135
|
+
if (taskRecord.files && !taskRecord.outputs) {
|
|
2136
|
+
try {
|
|
2137
|
+
const fileList = JSON.parse(taskRecord.files);
|
|
2138
|
+
for (const filePath of fileList.slice(0, 20)) {
|
|
2139
|
+
try {
|
|
2140
|
+
store.insertArtifact({
|
|
2141
|
+
id: `artifact-${taskRecord.id}-file-${filePath.replace(/[^a-z0-9]/gi, '-')}-${Date.now()}`,
|
|
2142
|
+
convoy_id: convoyId,
|
|
2143
|
+
task_id: taskRecord.id,
|
|
2144
|
+
name: filePath,
|
|
2145
|
+
type: 'file',
|
|
2146
|
+
content: '',
|
|
2147
|
+
created_at: new Date().toISOString(),
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2150
|
+
catch (err) {
|
|
2151
|
+
if (err instanceof ConvoyArtifactLimitError)
|
|
2152
|
+
break;
|
|
2153
|
+
// Other errors are non-critical
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
catch { /* files not parseable */ }
|
|
2158
|
+
}
|
|
2094
2159
|
// ── Output contract validation ────────────────────────────────────────
|
|
2095
2160
|
const contractResult = validateOutput(taskRecord.agent, result.output);
|
|
2096
2161
|
if (!contractResult.valid) {
|
|
@@ -2153,7 +2218,7 @@ async function runConvoy(convoyId, spec, adapter, store, events, wtManager, merg
|
|
|
2153
2218
|
}
|
|
2154
2219
|
catch { /* non-critical */ }
|
|
2155
2220
|
}
|
|
2156
|
-
const taskModel = taskRecord.model ?? taskAdapter.name;
|
|
2221
|
+
const taskModel = taskRecord.model ?? AGENT_MODEL_MAP[taskRecord.agent.toLowerCase()] ?? taskAdapter.name;
|
|
2157
2222
|
const taskCost = calculateCost(taskModel, usageExtra.prompt_tokens, usageExtra.completion_tokens);
|
|
2158
2223
|
store.withTransaction(() => {
|
|
2159
2224
|
store.updateTaskStatus(taskRecord.id, convoyId, 'done', {
|
|
@@ -2236,11 +2301,21 @@ async function runConvoy(convoyId, spec, adapter, store, events, wtManager, merg
|
|
|
2236
2301
|
process.stdout.write(` ${c.yellow('⟳')} ${c.bold(`[${taskRecord.id}]`)} retry ${freshRecord.retries + 1}/${freshRecord.max_retries}\n`);
|
|
2237
2302
|
}
|
|
2238
2303
|
else {
|
|
2304
|
+
// Estimate tokens even for failed tasks — you still paid for them
|
|
2305
|
+
const estimatedPrompt = Math.ceil(taskRecord.prompt.length / 4);
|
|
2306
|
+
const estimatedCompletion = Math.ceil((result.output?.length ?? 0) / 4);
|
|
2307
|
+
const failModel = taskRecord.model ?? AGENT_MODEL_MAP[taskRecord.agent.toLowerCase()] ?? taskAdapter.name;
|
|
2308
|
+
const failCost = calculateCost(failModel, estimatedPrompt, estimatedCompletion);
|
|
2239
2309
|
store.withTransaction(() => {
|
|
2240
2310
|
store.updateTaskStatus(taskRecord.id, convoyId, 'failed', {
|
|
2241
2311
|
finished_at: finishedAt,
|
|
2242
2312
|
output: result.output,
|
|
2243
2313
|
exit_code: result.exitCode,
|
|
2314
|
+
prompt_tokens: estimatedPrompt,
|
|
2315
|
+
completion_tokens: estimatedCompletion,
|
|
2316
|
+
total_tokens: estimatedPrompt + estimatedCompletion,
|
|
2317
|
+
model: failModel,
|
|
2318
|
+
cost_usd: failCost,
|
|
2244
2319
|
});
|
|
2245
2320
|
store.updateWorkerStatus(workerId, 'failed', { finished_at: finishedAt });
|
|
2246
2321
|
});
|