@aksp/opencrew 1.4.0 → 1.4.2
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 +87 -0
- package/README.md +33 -17
- package/bin/opencrew.js +4 -4
- package/package.json +4 -3
- package/src/cli.js +93 -43
- package/src/commands/init.js +79 -53
- package/src/commands/update.js +44 -17
- package/src/lib/errors.js +12 -0
- package/src/lib/fsx.js +18 -9
- package/src/lib/ides.js +9 -34
- package/templates/AGENTS.md +42 -63
- package/templates/_opencrew/.opencrew-version +1 -1
- package/templates/_opencrew/core/prompts/build.prompt.md +21 -0
- package/templates/_opencrew/core/prompts/design.prompt.md +9 -5
- package/templates/_opencrew/core/runner.pipeline.md +14 -2
- package/templates/gitignore +3 -1
- package/templates/skills/image-ai-generator/SKILL.md +8 -4
- package/templates/skills/image-creator/SKILL.md +3 -1
- package/templates/skills/instagram-publisher/SKILL.md +34 -16
- package/templates/skills/instagram-publisher/scripts/publish.js +58 -27
package/src/commands/update.js
CHANGED
|
@@ -2,10 +2,12 @@ import path from 'node:path';
|
|
|
2
2
|
import { promises as fs } from 'node:fs';
|
|
3
3
|
import { templatesDir, packageJsonPath } from '../lib/paths.js';
|
|
4
4
|
import { copyDir, exists, writeFileSafe, readJson, writeBridgeFile, readFile } from '../lib/fsx.js';
|
|
5
|
+
import { AGENTS_BRIDGE, LEAKED_STATUS_SECTION, ideById } from '../lib/ides.js';
|
|
5
6
|
import { c, log, info, ok, warn, step } from '../lib/ui.js';
|
|
6
7
|
|
|
7
8
|
// Update refreshes ONLY the framework. It never touches:
|
|
8
|
-
// crews/, _opencrew/_memory/, _opencrew/_browser_profile/, .env, IDE bridges
|
|
9
|
+
// crews/, _opencrew/_memory/, _opencrew/_browser_profile/, .env, IDE bridges
|
|
10
|
+
// (one exception: the CLAUDE.md block leaked by 1.4.0/1.4.1 — see removeLeakedStatusSection).
|
|
9
11
|
// Note: catalog skills (skills/<name>/ that ship with the package) ARE fully
|
|
10
12
|
// overwritten below — user edits to a catalog skill's own files are not preserved.
|
|
11
13
|
// Only skill directories that don't exist in the package's templates/skills/ at all
|
|
@@ -72,24 +74,49 @@ export async function update(opts = {}) {
|
|
|
72
74
|
await writeFileSafe(path.join(target, '_opencrew', 'core', 'system.md'), systemContent);
|
|
73
75
|
ok('_opencrew/core/system.md refreshed');
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
+ 'Read that file and adopt the opencrew system role — follow all initialization,\n'
|
|
78
|
-
+ 'command routing, and workflow instructions defined there.\n\n'
|
|
79
|
-
+ 'Type `/opencrew` to open the main menu.\n';
|
|
80
|
-
|
|
81
|
-
// If AGENTS.md is a legacy full-system doc (pre-v1.3), replace it entirely with the thin bridge.
|
|
82
|
-
const agentsPath = path.join(target, 'AGENTS.md');
|
|
83
|
-
const existingAgents = await readFile(agentsPath);
|
|
84
|
-
if (existingAgents.includes('# opencrew Instructions') && !existingAgents.includes('<!-- opencrew:start -->')) {
|
|
85
|
-
await writeFileSafe(agentsPath, agentsBridge);
|
|
86
|
-
ok('AGENTS.md (migrated from legacy full-system to thin bridge)');
|
|
87
|
-
} else {
|
|
88
|
-
await writeBridgeFile(agentsPath, agentsBridge);
|
|
89
|
-
ok('AGENTS.md refreshed');
|
|
90
|
-
}
|
|
77
|
+
await refreshAgentsBridge(target);
|
|
78
|
+
await removeLeakedStatusSection(target);
|
|
91
79
|
|
|
80
|
+
// Stamp last: a crash above leaves the old version, so the next update retries.
|
|
92
81
|
await fs.writeFile(versionFile, version + '\n');
|
|
93
82
|
log(`\n${c.green(c.bold('Updated to v' + version))}.`);
|
|
94
83
|
log(c.dim('Your crews, memory, IDE bridges and .env were left untouched.\n'));
|
|
95
84
|
}
|
|
85
|
+
|
|
86
|
+
// Root AGENTS.md: create it if missing; a legacy full-system doc (pre-v1.3) is backed up
|
|
87
|
+
// byte for byte and replaced by the thin bridge; otherwise only the marked block changes.
|
|
88
|
+
async function refreshAgentsBridge(target) {
|
|
89
|
+
const agentsPath = path.join(target, 'AGENTS.md');
|
|
90
|
+
if (!(await exists(agentsPath))) {
|
|
91
|
+
await writeBridgeFile(agentsPath, AGENTS_BRIDGE);
|
|
92
|
+
ok('AGENTS.md (bridge created)');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const existing = await readFile(agentsPath);
|
|
96
|
+
if (existing.includes('# opencrew Instructions') && !existing.includes('<!-- opencrew:start -->')) {
|
|
97
|
+
const backup = await freeBackupPath(agentsPath);
|
|
98
|
+
await fs.copyFile(agentsPath, backup);
|
|
99
|
+
await writeFileSafe(agentsPath, AGENTS_BRIDGE);
|
|
100
|
+
ok(`AGENTS.md (migrated from legacy full-system to thin bridge — backed up to ${path.basename(backup)})`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
await writeBridgeFile(agentsPath, AGENTS_BRIDGE);
|
|
104
|
+
ok('AGENTS.md refreshed');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function freeBackupPath(file) {
|
|
108
|
+
const bak = `${file}.bak`;
|
|
109
|
+
if (!(await exists(bak))) return bak;
|
|
110
|
+
return `${file}.bak-${new Date().toISOString().replace(/[:.]/g, '-')}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 1.4.0/1.4.1 shipped the maintainer's STATUS.md workflow inside CLAUDE.md's opencrew
|
|
114
|
+
// block. Rewrite that block (only that block, only if the leak is there).
|
|
115
|
+
async function removeLeakedStatusSection(target) {
|
|
116
|
+
const claudePath = path.join(target, 'CLAUDE.md');
|
|
117
|
+
if (!(await exists(claudePath))) return;
|
|
118
|
+
if (!(await readFile(claudePath)).includes(LEAKED_STATUS_SECTION)) return;
|
|
119
|
+
const bridge = ideById('claude-code').files.find((f) => f.path === 'CLAUDE.md');
|
|
120
|
+
await writeBridgeFile(claudePath, bridge.content);
|
|
121
|
+
ok('CLAUDE.md (removed the STATUS.md section shipped by mistake in 1.4.0/1.4.1)');
|
|
122
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Error types the CLI turns into exit codes (see src/cli.js → exitCodeFor).
|
|
2
|
+
|
|
3
|
+
/** Wrong flags/arguments — reported in one line, exit 1, nothing written. */
|
|
4
|
+
export class UsageError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'UsageError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** @inquirer throws this when the user presses Ctrl+C on a prompt. */
|
|
12
|
+
export const isPromptCancel = (e) => e?.name === 'ExitPromptError';
|
package/src/lib/fsx.js
CHANGED
|
@@ -54,17 +54,21 @@ export async function writeFileSafe(p, content, { overwrite = true } = {}) {
|
|
|
54
54
|
* Write a bridge file using marked-block strategy.
|
|
55
55
|
* - File doesn't exist → creates with content wrapped in HTML markers
|
|
56
56
|
* - File exists with markers → replaces only the block between markers
|
|
57
|
-
* - File exists without markers →
|
|
57
|
+
* - File exists without markers → adds the marked block (prepend or append), preserving
|
|
58
|
+
* existing content byte for byte
|
|
58
59
|
*
|
|
59
60
|
* @param {string} p File path
|
|
60
61
|
* @param {string} block Content to place between markers
|
|
61
62
|
* @param {object} opts
|
|
62
|
-
* @param {string} opts.marker
|
|
63
|
+
* @param {string} opts.marker Marker name (default: 'opencrew')
|
|
64
|
+
* @param {'html'|'hash'} opts.comment `<!-- x:start -->` (markdown) or `# x:start` (.gitignore, .env)
|
|
65
|
+
* @param {'prepend'|'append'} opts.position Where a new block goes in an unmarked file
|
|
63
66
|
* @returns {Promise<{written: boolean, merged: boolean}>}
|
|
64
67
|
*/
|
|
65
|
-
export async function writeBridgeFile(p, block, { marker = 'opencrew' } = {}) {
|
|
66
|
-
const start =
|
|
67
|
-
|
|
68
|
+
export async function writeBridgeFile(p, block, { marker = 'opencrew', comment = 'html', position = 'prepend' } = {}) {
|
|
69
|
+
const [start, end] = comment === 'hash'
|
|
70
|
+
? [`# ${marker}:start`, `# ${marker}:end`]
|
|
71
|
+
: [`<!-- ${marker}:start -->`, `<!-- ${marker}:end -->`];
|
|
68
72
|
const marked = `${start}\n${block.trimEnd()}\n${end}`;
|
|
69
73
|
|
|
70
74
|
if (!(await exists(p))) {
|
|
@@ -77,9 +81,11 @@ export async function writeBridgeFile(p, block, { marker = 'opencrew' } = {}) {
|
|
|
77
81
|
|
|
78
82
|
// Already has markers → replace just the block, keep everything else
|
|
79
83
|
if (existing.includes(start) && existing.includes(end)) {
|
|
84
|
+
// Innermost block only: an orphan start marker (end deleted by hand) must never make
|
|
85
|
+
// the match swallow the user lines between it and the real block.
|
|
80
86
|
const updated = existing.replace(
|
|
81
|
-
new RegExp(escapeRx(start)
|
|
82
|
-
marked,
|
|
87
|
+
new RegExp(`${escapeRx(start)}(?:(?!${escapeRx(start)})[\\s\\S])*?${escapeRx(end)}`, 'g'),
|
|
88
|
+
() => marked,
|
|
83
89
|
);
|
|
84
90
|
if (updated !== existing) {
|
|
85
91
|
await fs.writeFile(p, updated);
|
|
@@ -88,8 +94,11 @@ export async function writeBridgeFile(p, block, { marker = 'opencrew' } = {}) {
|
|
|
88
94
|
return { written: false, merged: false };
|
|
89
95
|
}
|
|
90
96
|
|
|
91
|
-
// User content exists →
|
|
92
|
-
|
|
97
|
+
// User content exists → add the block, preserve everything
|
|
98
|
+
const merged = position === 'append'
|
|
99
|
+
? `${existing.trimEnd()}\n\n${marked}\n`
|
|
100
|
+
: `${marked}\n\n${existing.trimStart()}`;
|
|
101
|
+
await fs.writeFile(p, merged);
|
|
93
102
|
return { written: true, merged: true };
|
|
94
103
|
}
|
|
95
104
|
|
package/src/lib/ides.js
CHANGED
|
@@ -41,42 +41,17 @@ Type \`/opencrew\` to open the main menu.
|
|
|
41
41
|
- All checkpoint questions use \`AskUserQuestion\`.
|
|
42
42
|
- opencrew ships its own Playwright MCP (\`.mcp.json\`); disable the native Playwright plugin.
|
|
43
43
|
- Do not manually edit files under \`_opencrew/core/\` unless you know what you're doing.
|
|
44
|
+
`;
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- Report a 3-line summary: what was in progress, what's next, any blockers.
|
|
52
|
-
|
|
53
|
-
**During the session:**
|
|
54
|
-
- Move items from ⬜ Pendente to 🔄 Em andamento when you start working on them.
|
|
55
|
-
- Move items to ✅ Concluído when finished.
|
|
56
|
-
- Add new items that emerge during work.
|
|
57
|
-
|
|
58
|
-
**Before ending the session:**
|
|
59
|
-
- Ensure \`STATUS.md\` reflects the real state.
|
|
60
|
-
- Update \`Última sessão\` timestamp.
|
|
61
|
-
|
|
62
|
-
**Template:**
|
|
63
|
-
\`\`\`markdown
|
|
64
|
-
# STATUS — OpenCrew
|
|
65
|
-
|
|
66
|
-
> Última sessão: {today}
|
|
67
|
-
> Skill: /status
|
|
68
|
-
|
|
69
|
-
## 🔄 Em andamento
|
|
70
|
-
|
|
71
|
-
## ⬜ Pendente
|
|
72
|
-
|
|
73
|
-
## ✅ Concluído (esta sessão)
|
|
74
|
-
|
|
75
|
-
## 📋 Backlog
|
|
46
|
+
// Root AGENTS.md: thin bridge to the full system definition (written by init and update).
|
|
47
|
+
export const AGENTS_BRIDGE = '# opencrew\n\n'
|
|
48
|
+
+ 'The opencrew system definition lives at `_opencrew/core/system.md`.\n'
|
|
49
|
+
+ 'Read that file and adopt the opencrew system role — follow all initialization,\n'
|
|
50
|
+
+ 'command routing, and workflow instructions defined there.\n\n'
|
|
51
|
+
+ 'Type `/opencrew` to open the main menu.\n';
|
|
76
52
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
`;
|
|
53
|
+
// Marker that identifies the maintainer STATUS.md section leaked into CLAUDE.md by 1.4.0/1.4.1.
|
|
54
|
+
export const LEAKED_STATUS_SECTION = '## STATUS.md (gestão de sessão)';
|
|
80
55
|
|
|
81
56
|
const render = (title, extra = '') =>
|
|
82
57
|
`# ${title}\n\n${BRIDGE}${extra ? `\n\n${extra}` : ''}\n`;
|
package/templates/AGENTS.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# opencrew Instructions
|
|
2
2
|
|
|
3
|
-
You are
|
|
3
|
+
You are operating as the opencrew system. Your primary role is to help users
|
|
4
|
+
create, manage, and run AI agent crews.
|
|
4
5
|
|
|
5
6
|
## Initialization
|
|
6
7
|
|
|
@@ -8,55 +9,48 @@ On activation, perform these steps IN ORDER:
|
|
|
8
9
|
|
|
9
10
|
1. Read the company context file: `{project-root}/_opencrew/_memory/company.md`
|
|
10
11
|
2. Read the preferences file: `{project-root}/_opencrew/_memory/preferences.md`
|
|
11
|
-
3. Check if company.md is empty or contains only the template — if so, trigger ONBOARDING
|
|
12
|
+
3. Check if company.md is empty or contains only the template — if so, trigger ONBOARDING
|
|
12
13
|
4. Otherwise, display the MAIN MENU
|
|
13
14
|
|
|
14
15
|
## Onboarding Flow (first time only)
|
|
15
16
|
|
|
16
17
|
If `company.md` is empty or contains `<!-- NOT CONFIGURED -->`:
|
|
17
18
|
|
|
18
|
-
1. Welcome the user warmly to
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- Social media profiles found
|
|
28
|
-
6. Present the findings in a clean summary and ask the user to confirm or correct
|
|
29
|
-
7. Save the confirmed profile to `_opencrew/_memory/company.md`
|
|
30
|
-
8. Show the main menu
|
|
19
|
+
1. Welcome the user warmly; ask their name and preferred output language (save to
|
|
20
|
+
preferences.md)
|
|
21
|
+
2. Ask for company name/description and website URL
|
|
22
|
+
3. Use WebFetch on the URL + WebSearch on the company name to research:
|
|
23
|
+
description/sector, target audience, products/services, tone of voice,
|
|
24
|
+
social media profiles
|
|
25
|
+
4. Present findings in a clean summary, ask the user to confirm or correct,
|
|
26
|
+
save the profile to `_opencrew/_memory/company.md`
|
|
27
|
+
5. Show the main menu
|
|
31
28
|
|
|
32
29
|
## Main Menu
|
|
33
30
|
|
|
34
|
-
When the user types `/opencrew` or asks for the menu, present an interactive
|
|
31
|
+
When the user types `/opencrew` or asks for the menu, present an interactive
|
|
32
|
+
selector with these options (max 4 per question). Use your IDE's native
|
|
33
|
+
interactive-choice mechanism if it has one; otherwise present the options as a
|
|
34
|
+
numbered list and ask the user to reply with a number.
|
|
35
35
|
|
|
36
|
-
**Primary menu
|
|
37
|
-
|
|
38
|
-
- **Run an existing crew** — Execute a crew's pipeline
|
|
39
|
-
- **My crews** — View, edit, repair, or delete your crews
|
|
40
|
-
- **More options** — Skills, company profile, settings, and help
|
|
36
|
+
**Primary menu:** Create a new crew · Run an existing crew · My crews ·
|
|
37
|
+
More options
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
- **Skills** — Browse, install, create, and manage skills for your crews
|
|
44
|
-
- **Company profile** — View or update your company information
|
|
45
|
-
- **Settings & Help** — Language, preferences, configuration, and help
|
|
39
|
+
**More options:** Skills · Company profile · Settings & Help
|
|
46
40
|
|
|
47
41
|
## Command Routing
|
|
48
42
|
|
|
49
|
-
|
|
43
|
+
Route input to the matching action:
|
|
50
44
|
|
|
51
45
|
| Input Pattern | Action |
|
|
52
46
|
|---------------|--------|
|
|
53
47
|
| `/opencrew` or `/opencrew menu` | Show main menu |
|
|
54
48
|
| `/opencrew help` | Show help text |
|
|
55
49
|
| `/opencrew create <description>` | Load Architect → Create Crew flow |
|
|
56
|
-
| `/opencrew list` | List all crews in `crews/`
|
|
50
|
+
| `/opencrew list` | List all crews in `crews/` |
|
|
57
51
|
| `/opencrew run <name>` | Load Pipeline Runner → Execute crew |
|
|
58
52
|
| `/opencrew edit <name> <changes>` | Load Architect → Edit Crew flow |
|
|
59
|
-
| `/opencrew repair <name>` | Load `_opencrew/core/prompts/repair.prompt.md` → fix agent names / rebuild crew-party.csv
|
|
53
|
+
| `/opencrew repair <name>` | Load `_opencrew/core/prompts/repair.prompt.md` → fix agent names / rebuild crew-party.csv |
|
|
60
54
|
| `/opencrew skills` | Load Skills Engine → Show skills menu |
|
|
61
55
|
| `/opencrew install <name>` | Install a skill from the catalog |
|
|
62
56
|
| `/opencrew uninstall <name>` | Remove an installed skill |
|
|
@@ -74,7 +68,7 @@ When a specific agent needs to be activated:
|
|
|
74
68
|
1. Read the agent's `.agent.md` file completely
|
|
75
69
|
2. Adopt the agent's persona (role, identity, communication_style, principles)
|
|
76
70
|
3. Follow the agent's menu/workflow instructions
|
|
77
|
-
4. When the agent's task is complete, return to opencrew main context
|
|
71
|
+
4. When the agent's task is complete, return to the opencrew main context
|
|
78
72
|
|
|
79
73
|
## Loading the Pipeline Runner
|
|
80
74
|
|
|
@@ -82,37 +76,26 @@ When running a crew:
|
|
|
82
76
|
|
|
83
77
|
1. Read `crews/{name}/crew.yaml` to understand the pipeline
|
|
84
78
|
2. Read `crews/{name}/crew-party.csv` to load all agent personas
|
|
85
|
-
3. For each agent in the party CSV, also read their full `.agent.md` file
|
|
86
|
-
4. Load company context from `_opencrew/_memory/company.md`
|
|
79
|
+
3. For each agent in the party CSV, also read their full `.agent.md` file
|
|
80
|
+
4. Load company context from `_opencrew/_memory/company.md` and user preferences
|
|
81
|
+
from `_opencrew/_memory/preferences.md` (used to check the Dashboard toggle)
|
|
87
82
|
5. Load crew memory from `crews/{name}/_memory/memories.md`
|
|
88
|
-
6.
|
|
89
|
-
7.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
and run all agents.
|
|
96
|
-
8. Execute the pipeline step by step following runner instructions
|
|
83
|
+
6. Read the pipeline runner instructions from `_opencrew/core/runner.pipeline.md`
|
|
84
|
+
7. **Pre-Execution Agent Selection** — only when `crew.yaml` declares
|
|
85
|
+
`agent_dependencies:`. Analyze the user's request against the decision matrix,
|
|
86
|
+
present the agents as a numbered multi-select (IDE-neutral), let the user
|
|
87
|
+
confirm/adjust, warn about broken dependencies, and build the filtered step
|
|
88
|
+
list. Crews without the field skip this and run all agents.
|
|
89
|
+
8. Execute the pipeline step by step following the runner instructions
|
|
97
90
|
|
|
98
91
|
## Dashboard (Optional)
|
|
99
92
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
it
|
|
105
|
-
|
|
106
|
-
- To use: open `dashboard/index.html` in a browser and point it at the
|
|
107
|
-
`crews/{name}/state.json` written during a run.
|
|
108
|
-
- Toggle: `Dashboard: enabled` (or `disabled`) in `_opencrew/_memory/preferences.md`,
|
|
109
|
-
editable via `/opencrew settings`.
|
|
110
|
-
- When disabled (default): the runner never creates, writes, or deletes `state.json`.
|
|
111
|
-
- When enabled: the runner writes `crews/{name}/state.json` before each step and at
|
|
112
|
-
every handoff, exactly as described in `_opencrew/core/runner.pipeline.md`.
|
|
113
|
-
- The dashboard auto-polls `state.json` every 1.5 seconds when in live mode;
|
|
114
|
-
it also includes a built-in demo mode so you can see what it looks like
|
|
115
|
-
without running a real crew.
|
|
93
|
+
The dashboard is an optional animated view of a crew run (`dashboard/index.html`).
|
|
94
|
+
It is **disabled by default**; most installs never use it. Toggle it via
|
|
95
|
+
`Dashboard: enabled|disabled` in `_opencrew/_memory/preferences.md` (editable via
|
|
96
|
+
`/opencrew settings`). When disabled, the runner never writes `state.json`; when
|
|
97
|
+
enabled, it writes `crews/{name}/state.json` before each step and at every handoff
|
|
98
|
+
(see `_opencrew/core/runner.pipeline.md`).
|
|
116
99
|
|
|
117
100
|
## Language Handling
|
|
118
101
|
|
|
@@ -120,13 +103,9 @@ it on.
|
|
|
120
103
|
- All user-facing output should be in the user's preferred language
|
|
121
104
|
- Internal file names and code remain in English
|
|
122
105
|
- Agent personas communicate in the user's language
|
|
123
|
-
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
fixed structural labels, not generated prose — see `_opencrew/core/runner.pipeline.md`.
|
|
127
|
-
opencrew's primary supported audience is PT-BR (see README), so these are intentionally
|
|
128
|
-
not localized per-user. Only the *content* written into those sections follows the
|
|
129
|
-
user's Output Language.
|
|
106
|
+
- Exception: crew memory scaffolding (`memories.md` headers, `runs.md` columns)
|
|
107
|
+
keeps fixed PT-BR structural labels regardless of the user's language —
|
|
108
|
+
see `_opencrew/core/runner.pipeline.md`
|
|
130
109
|
|
|
131
110
|
## Critical Rules
|
|
132
111
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.4.
|
|
1
|
+
1.4.2
|
|
@@ -390,9 +390,16 @@ model_tier: fast # ONLY for execution: subagent. fast = lightweight model;
|
|
|
390
390
|
# Set fast for: investigator agents (data extraction, Sherlock subagents), researcher agents (web search, data gathering)
|
|
391
391
|
# Set powerful for: writer, creator, reviewer, strategy agents
|
|
392
392
|
# Omit model_tier for execution: inline steps
|
|
393
|
+
side_effects: irreversible # REQUIRED for any step that publishes, posts, sends email or otherwise
|
|
394
|
+
# distributes outside the project (it cannot be undone). The Pipeline
|
|
395
|
+
# Runner never retries these automatically, and Gate 2c places them last.
|
|
396
|
+
# Omit for every other step.
|
|
393
397
|
---
|
|
394
398
|
```
|
|
395
399
|
|
|
400
|
+
**Irreversible steps must run inline** (`execution: inline`), so the user sees the dry run and
|
|
401
|
+
gives the explicit go-ahead in the main conversation.
|
|
402
|
+
|
|
396
403
|
For **checkpoints**, use this frontmatter instead:
|
|
397
404
|
```yaml
|
|
398
405
|
---
|
|
@@ -572,6 +579,20 @@ If ANY check fails:
|
|
|
572
579
|
4. Generate a step file for the new checkpoint that asks the user to review and approve the preceding agent's output before the visual/publish step runs
|
|
573
580
|
5. Re-validate Gate 2b. Max 2 fix attempts — after that, present to user for manual decision.
|
|
574
581
|
|
|
582
|
+
### Gate 2c: Irreversible Steps Last (BLOCKING)
|
|
583
|
+
|
|
584
|
+
For EACH step that publishes, posts, sends email or distributes outside the project:
|
|
585
|
+
- [ ] Its frontmatter declares `side_effects: irreversible` and `execution: inline`
|
|
586
|
+
- [ ] It comes AFTER the Review step (the reviewer has already approved the final content)
|
|
587
|
+
- [ ] The IMMEDIATELY preceding step is a `type: checkpoint` (Final Approval) that itself comes after the Review
|
|
588
|
+
- [ ] Only other irreversible steps follow it (nothing is created, rendered or reviewed after publishing)
|
|
589
|
+
|
|
590
|
+
If ANY check fails:
|
|
591
|
+
1. Add the missing `side_effects: irreversible` / `execution: inline` fields
|
|
592
|
+
2. Move the irreversible step(s) to the end of the pipeline, after Review → Final Approval checkpoint
|
|
593
|
+
(create the Final Approval checkpoint if it does not exist), and renumber the steps
|
|
594
|
+
3. Re-validate Gate 2c. Max 2 fix attempts — after that, present to user for manual decision.
|
|
595
|
+
|
|
575
596
|
### Gate 3: Pipeline Coherence (ADVISORY)
|
|
576
597
|
|
|
577
598
|
Verify:
|
|
@@ -525,10 +525,14 @@ ERRADO: 5 noticias diferentes = NAO sao angulos, sao pautas distintas
|
|
|
525
525
|
|
|
526
526
|
#### Pipeline Patterns
|
|
527
527
|
|
|
528
|
-
- **Standard (fixed source):** Research → Angle Selection checkpoint → Creation → Content Approval checkpoint → [
|
|
529
|
-
- **News-based (multiple stories):** Research → News Selection checkpoint → Creator[generate-angles] → Angle Selection checkpoint → Creator[create+optimize] → Content Approval checkpoint → [
|
|
528
|
+
- **Standard (fixed source):** Research → Angle Selection checkpoint → Creation → Content Approval checkpoint → [Render Steps] → Review → Final Approval checkpoint → [Publish/Send Steps]
|
|
529
|
+
- **News-based (multiple stories):** Research → News Selection checkpoint → Creator[generate-angles] → Angle Selection checkpoint → Creator[create+optimize] → Content Approval checkpoint → [Render Steps] → Review → Final Approval checkpoint → [Publish/Send Steps]
|
|
530
530
|
|
|
531
|
-
**
|
|
531
|
+
**Render Steps** (image generation, visual rendering, slides) are reversible and run BEFORE the Review, so the reviewer sees the final visuals.
|
|
532
|
+
|
|
533
|
+
**Publish/Send Steps** (social media posting, email sending, any distribution outside the project) are IRREVERSIBLE: they ALWAYS come last — after the Review and immediately after the Final Approval checkpoint — and their step files declare `side_effects: irreversible` (see build.prompt.md, Pipeline Step Format and Gate 2c). Never place a publish/send step before the Review. Omit either bracket when the crew has no such step.
|
|
534
|
+
|
|
535
|
+
**Content Approval checkpoint is MANDATORY** whenever the pipeline includes any render step after content creation. Never place a render step immediately after a creation step without a checkpoint in between.
|
|
532
536
|
|
|
533
537
|
On reject: loop back to creation step (re-execute full creator, not individual tasks).
|
|
534
538
|
|
|
@@ -555,8 +559,8 @@ I'll create a crew with N agents:
|
|
|
555
559
|
Format: [format name, if applicable]
|
|
556
560
|
...
|
|
557
561
|
|
|
558
|
-
Pipeline (fixed source): [Research] → checkpoint Select Angle → [Creator] → checkpoint Approve Content → [
|
|
559
|
-
Pipeline (news-based): [Research] → checkpoint Select News → [Creator: generate angles] → checkpoint Select Angle → [Creator: create content] → checkpoint Approve Content → [
|
|
562
|
+
Pipeline (fixed source): [Research] → checkpoint Select Angle → [Creator] → checkpoint Approve Content → [Render] → [Review] → checkpoint Final Approval → [Publish/Send]
|
|
563
|
+
Pipeline (news-based): [Research] → checkpoint Select News → [Creator: generate angles] → checkpoint Select Angle → [Creator: create content] → checkpoint Approve Content → [Render] → [Review] → checkpoint Final Approval → [Publish/Send]
|
|
560
564
|
Formats: [list of selected formats, e.g., instagram-feed, twitter-thread]
|
|
561
565
|
|
|
562
566
|
Reference materials: [list of data files]
|
|
@@ -20,7 +20,8 @@ Before starting execution:
|
|
|
20
20
|
optional, opt-in feature that most installs never use (it requires running the
|
|
21
21
|
separate dashboard app from source — see README). Scan the already-loaded
|
|
22
22
|
`preferences.md` for a `Dashboard:` field:
|
|
23
|
-
- If
|
|
23
|
+
- If its value is `enabled` (as written by onboarding: `- **Dashboard:** enabled`, or the
|
|
24
|
+
plain form `Dashboard: enabled`) → set `dashboard_enabled = true` for this run.
|
|
24
25
|
- Otherwise (`disabled`, missing, or preferences.md not configured yet) →
|
|
25
26
|
set `dashboard_enabled = false`. This is the default.
|
|
26
27
|
Store `dashboard_enabled` in working memory for the rest of this run. Every
|
|
@@ -546,7 +547,12 @@ Use the **stored transformed path** (after Output Path Transformation Steps 1 an
|
|
|
546
547
|
|
|
547
548
|
**Rules:**
|
|
548
549
|
- If ALL output files return `VALIDATION:PASS` → proceed to Veto Condition Enforcement.
|
|
549
|
-
-
|
|
550
|
+
- **Irreversible step** (`side_effects: irreversible` — publish, post, send) with ANY
|
|
551
|
+
`VALIDATION:FAIL` → NEVER re-execute it. Tell the user: "⚠️ {Agent Name} did not save its
|
|
552
|
+
output, but the action may already have happened (post published / email sent). Check
|
|
553
|
+
before retrying." Then offer: 1. Retry step (only after the user checked) · 2. Mark as done
|
|
554
|
+
and continue · 3. Abort pipeline.
|
|
555
|
+
- If ANY output file returns `VALIDATION:FAIL` (any other step):
|
|
550
556
|
1. **Retry once**: re-execute the entire step with the same input and context.
|
|
551
557
|
2. After re-execution, run the validation again for all output files.
|
|
552
558
|
3. If second attempt returns `VALIDATION:PASS` for all files → proceed normally.
|
|
@@ -612,6 +618,9 @@ After an agent completes a step (before moving to the next step):
|
|
|
612
618
|
- Ask the agent to fix the specific issue (re-execute with targeted correction)
|
|
613
619
|
- Maximum 2 veto fix attempts per step
|
|
614
620
|
- After 2 failed attempts, present to user for manual decision
|
|
621
|
+
- **Never auto-fix an irreversible step** (`side_effects: irreversible`): re-executing it
|
|
622
|
+
would publish/send again. Report the veto, warn the user that
|
|
623
|
+
the action may already have happened, and let the user decide.
|
|
615
624
|
4. If no veto conditions triggered: proceed to next step
|
|
616
625
|
|
|
617
626
|
This creates an internal quality loop BEFORE the reviewer sees the content,
|
|
@@ -809,6 +818,9 @@ This archives the run state for the `runs` command while keeping crew history av
|
|
|
809
818
|
## Error Handling
|
|
810
819
|
|
|
811
820
|
- If a subagent fails, retry once. If it fails again, inform the user and offer to skip the step or abort.
|
|
821
|
+
- If an irreversible step (`side_effects: irreversible`) fails, NEVER retry it automatically:
|
|
822
|
+
the post/email may already have happened. Tell the user so, ask them to check, and let them
|
|
823
|
+
choose: retry, mark as done, or abort.
|
|
812
824
|
- If a step file is missing, inform the user and suggest running `/opencrew edit {crew}` to fix.
|
|
813
825
|
- If company.md is empty, stop and redirect to onboarding.
|
|
814
826
|
- Never continue past a checkpoint without user input.
|
package/templates/gitignore
CHANGED
|
@@ -14,7 +14,7 @@ type: script
|
|
|
14
14
|
version: "1.0.0"
|
|
15
15
|
script:
|
|
16
16
|
path: scripts/generate.py
|
|
17
|
-
runtime:
|
|
17
|
+
runtime: python
|
|
18
18
|
invoke: "python3 {skill_path}/scripts/generate.py --prompt \"{prompt}\" --output \"{output}\" --mode \"{mode}\""
|
|
19
19
|
env:
|
|
20
20
|
- OPENROUTER_API_KEY
|
|
@@ -52,10 +52,14 @@ Use the Image Generator when you need to create visual assets from text prompts.
|
|
|
52
52
|
|
|
53
53
|
## Instructions
|
|
54
54
|
|
|
55
|
+
`{skill_path}` is this skill's folder (normally `skills/image-ai-generator`). The commands below use
|
|
56
|
+
`python3` (macOS/Linux). **On Windows** use `py -3` instead (or `python` if the `py` launcher is
|
|
57
|
+
not installed).
|
|
58
|
+
|
|
55
59
|
### Single image generation
|
|
56
60
|
|
|
57
61
|
```bash
|
|
58
|
-
python3
|
|
62
|
+
python3 {skill_path}/scripts/generate.py \
|
|
59
63
|
--prompt "A detailed description of the image to generate" \
|
|
60
64
|
--output "crews/{crew}/output/{run_id}/assets/image-name.jpg" \
|
|
61
65
|
--mode test
|
|
@@ -66,7 +70,7 @@ python3 skills/image-generator/scripts/generate.py \
|
|
|
66
70
|
Use `--reference` to send a local image to the model as visual context. The model will incorporate the referenced image (e.g., a logo or mascot) into the generated output.
|
|
67
71
|
|
|
68
72
|
```bash
|
|
69
|
-
python3
|
|
73
|
+
python3 {skill_path}/scripts/generate.py \
|
|
70
74
|
--prompt "A social media banner featuring the company logo prominently in the center" \
|
|
71
75
|
--output "crews/{crew}/output/{run_id}/assets/banner.jpg" \
|
|
72
76
|
--reference "crews/{crew}/assets/logo.png" \
|
|
@@ -78,7 +82,7 @@ Supported reference formats: PNG, JPEG, WEBP, GIF.
|
|
|
78
82
|
### Batch generation
|
|
79
83
|
|
|
80
84
|
```bash
|
|
81
|
-
python3
|
|
85
|
+
python3 {skill_path}/scripts/generate.py \
|
|
82
86
|
--batch "crews/{crew}/output/{run_id}/assets/batch.json" \
|
|
83
87
|
--mode production
|
|
84
88
|
```
|
|
@@ -46,7 +46,8 @@ Use the Visual Renderer when you need to generate production-ready images from H
|
|
|
46
46
|
4. **Render** -- Use Playwright to:
|
|
47
47
|
- `browser_navigate` to `http://localhost:8765/slide-01.html` (filename only, not full path)
|
|
48
48
|
- `browser_resize` to target viewport dimensions
|
|
49
|
-
- `browser_take_screenshot` to save as PNG
|
|
49
|
+
- `browser_take_screenshot` to save as PNG — **except when the images will be published to
|
|
50
|
+
Instagram**: Instagram accepts JPEG only, so save with `type: "jpeg"` (`slide-01.jpg`)
|
|
50
51
|
|
|
51
52
|
5. **Verify** -- Read the screenshot to confirm quality. Re-render if needed.
|
|
52
53
|
|
|
@@ -103,6 +104,7 @@ For multi-image outputs like carousels:
|
|
|
103
104
|
3. Render each slide sequentially (step 4 repeated per slide)
|
|
104
105
|
4. Stop the HTTP server **once** after all slides are done (step 6 of Core Workflow)
|
|
105
106
|
5. Name output files with zero-padded numbers: slide-01.png, slide-02.png, slide-03.png
|
|
107
|
+
(`.jpg` when the destination is Instagram — see step 4)
|
|
106
108
|
6. Keep all slides at the same viewport dimensions
|
|
107
109
|
|
|
108
110
|
### Best Practices
|