@esquadrao/cli 0.0.0-stage → 1.6.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/LICENSE +21 -0
- package/README.md +366 -2
- package/assets/fonts/Anton-Regular.ttf +0 -0
- package/assets/fonts/BebasNeue-Regular.ttf +0 -0
- package/assets/fonts/OFL.txt +93 -0
- package/assets/fonts/Poppins-Bold.ttf +0 -0
- package/assets/fonts/README.md +13 -0
- package/bin/cli.js +126 -0
- package/package.json +58 -4
- package/scripts/ast_slice.js +73 -0
- package/scripts/cutout.py +197 -0
- package/scripts/dag_validator.js +78 -0
- package/scripts/lint.js +43 -0
- package/scripts/merkle_verify.js +83 -0
- package/scripts/wcag_check.js +77 -0
- package/skill-audit/SKILL.md +42 -0
- package/skill-audit/references/merkle-ledger-spec.md +27 -0
- package/skill-audit/references/receipt-ed25519-verification.md +17 -0
- package/skill-audit/references/time-travel-replay.md +10 -0
- package/skill-code-reviewer/SKILL.md +40 -0
- package/skill-context/SKILL.md +44 -0
- package/skill-context/references/ast-virtualization.md +10 -0
- package/skill-context/references/openapi-contract-synthesis.md +10 -0
- package/skill-engineering-manager/SKILL.md +40 -0
- package/skill-media-producer/SKILL.md +328 -0
- package/skill-media-producer/references/caption-templates.md +194 -0
- package/skill-media-producer/references/composicoes-especiais.md +99 -0
- package/skill-media-producer/references/configuracao-inicial.md +239 -0
- package/skill-media-producer/references/corte-podcast-3-niveis.md +179 -0
- package/skill-media-producer/references/llm-agent-guide.md +231 -0
- package/skill-orchestrate/SKILL.md +49 -0
- package/skill-orchestrate/references/mission-lifecycle.md +36 -0
- package/skill-orchestrate/references/swarm-coordination.md +33 -0
- package/skill-pipeline/SKILL.md +42 -0
- package/skill-pipeline/references/auto-healing-patterns.md +17 -0
- package/skill-pipeline/references/dag-decomposition-rules.md +18 -0
- package/skill-pipeline/references/topological-waves.md +16 -0
- package/skill-product-manager/SKILL.md +40 -0
- package/skill-qa-engineer/SKILL.md +40 -0
- package/skill-review/SKILL.md +46 -0
- package/skill-review/references/anti-slop-patterns.md +17 -0
- package/skill-review/references/dual-blind-adjudication.md +15 -0
- package/skill-review/references/voice-calibration.md +10 -0
- package/skill-security-engineer/SKILL.md +40 -0
- package/skill-software-architect/SKILL.md +40 -0
- package/skill-software-engineer/SKILL.md +40 -0
- package/skill-sre-engineer/SKILL.md +40 -0
- package/skill-system-analyst/SKILL.md +40 -0
- package/skill-tech-lead/SKILL.md +40 -0
- package/skill-technical-writer/SKILL.md +40 -0
- package/skill-ui/SKILL.md +45 -0
- package/skill-ui/references/design-tokens-spec.md +19 -0
- package/skill-ui/references/visual-tdd-methodology.md +10 -0
- package/skill-ui/references/wcag-target-sizes.md +9 -0
- package/src/captionTemplates.js +285 -0
- package/src/commands/onboard.js +618 -0
- package/src/commands/role.js +119 -0
- package/src/commands/setup.js +174 -0
- package/src/commands/studio.js +1822 -0
- package/src/roles/authority.js +129 -0
- package/src/roles/codeReviewer.js +65 -0
- package/src/roles/engineeringManager.js +53 -0
- package/src/roles/index.js +80 -0
- package/src/roles/mediaProducer.js +223 -0
- package/src/roles/productManager.js +50 -0
- package/src/roles/qaEngineer.js +54 -0
- package/src/roles/securityEngineer.js +53 -0
- package/src/roles/softwareArchitect.js +58 -0
- package/src/roles/softwareEngineer.js +76 -0
- package/src/roles/sreEngineer.js +60 -0
- package/src/roles/systemAnalyst.js +45 -0
- package/src/roles/techLead.js +46 -0
- package/src/roles/technicalWriter.js +46 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// CLI command: esquadrao role [list|info|prompt|matrix]
|
|
2
|
+
import { listRoles, getRole, READ_ONLY_ROLES, FORBIDDEN_COMMAND_PATTERNS } from '../roles/index.js';
|
|
3
|
+
|
|
4
|
+
export async function run({ positionals = [], flags = {} } = {}) {
|
|
5
|
+
const sub = positionals[0] || 'list';
|
|
6
|
+
|
|
7
|
+
if (flags.help || sub === 'help') {
|
|
8
|
+
console.log(`Esquadrão Roles Command
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
esquadrao role [subcommand] [arguments] [options]
|
|
12
|
+
|
|
13
|
+
Subcommands:
|
|
14
|
+
list List all standard industry engineering roles (default)
|
|
15
|
+
info <id> Display role specification, capabilities, and authority
|
|
16
|
+
prompt <id> Generate calibrated prompt for an agent role
|
|
17
|
+
matrix Display structural authority matrix and permission boundaries
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--json Output results in JSON format
|
|
21
|
+
-h, --help Show this help message`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (sub === 'list') {
|
|
26
|
+
const roles = listRoles();
|
|
27
|
+
if (flags.json) {
|
|
28
|
+
console.log(JSON.stringify(roles, null, 2));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
console.log('Roles Matrix:\n');
|
|
32
|
+
for (const r of roles) {
|
|
33
|
+
const roTag = r.readOnly ? '[READ-ONLY]' : '[READ/WRITE]';
|
|
34
|
+
console.log(` ${r.id.padEnd(22)} ${roTag.padEnd(14)} ${r.title}`);
|
|
35
|
+
console.log(` Description: ${r.description}`);
|
|
36
|
+
console.log(` Capabilities: ${r.requiredCapabilities.join(', ')}`);
|
|
37
|
+
if (r.formerName) console.log(` Former name: ${r.formerName}`);
|
|
38
|
+
console.log('');
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (sub === 'info') {
|
|
44
|
+
const target = positionals[1];
|
|
45
|
+
if (!target) {
|
|
46
|
+
console.error('Error: Missing role identifier. Usage: esquadrao role info <role_id>');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const roleMod = getRole(target);
|
|
50
|
+
if (!roleMod) {
|
|
51
|
+
console.error(`Error: Unknown role '${target}'. Run 'esquadrao role list' to see available roles.`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
if (flags.json) {
|
|
55
|
+
console.log(JSON.stringify(roleMod.definition, null, 2));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const def = roleMod.definition;
|
|
59
|
+
console.log(`Role Specification: ${def.title} (${def.id})`);
|
|
60
|
+
console.log(`--------------------------------------------------`);
|
|
61
|
+
console.log(`Category: ${def.category}`);
|
|
62
|
+
console.log(`Access: ${def.readOnly ? 'Strictly Read-Only' : 'Read/Write'}`);
|
|
63
|
+
console.log(`Capabilities: ${def.requiredCapabilities.join(', ')}`);
|
|
64
|
+
console.log(`Allowed Outputs: ${def.allowedOutputPrefixes.join(', ')}`);
|
|
65
|
+
if (def.formerName) console.log(`Former Alias: ${def.formerName}`);
|
|
66
|
+
console.log(`\nDescription:\n ${def.description}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (sub === 'prompt') {
|
|
71
|
+
const target = positionals[1];
|
|
72
|
+
if (!target) {
|
|
73
|
+
console.error('Error: Missing role identifier. Usage: esquadrao role prompt <role_id> [intent]');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const roleMod = getRole(target);
|
|
77
|
+
if (!roleMod) {
|
|
78
|
+
console.error(`Error: Unknown role '${target}'.`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const intent = positionals.slice(2).join(' ') || 'Fulfill the primary engineering task.';
|
|
82
|
+
const prompt = roleMod.buildPrompt({ intent, objective: intent });
|
|
83
|
+
if (flags.json) {
|
|
84
|
+
console.log(JSON.stringify({ role: roleMod.definition.id, prompt }, null, 2));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(prompt);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (sub === 'matrix') {
|
|
92
|
+
const matrix = {
|
|
93
|
+
readOnlyRoles: Array.from(READ_ONLY_ROLES),
|
|
94
|
+
forbiddenPatterns: FORBIDDEN_COMMAND_PATTERNS.map((p) => p.source),
|
|
95
|
+
roles: listRoles().map((r) => ({
|
|
96
|
+
id: r.id,
|
|
97
|
+
title: r.title,
|
|
98
|
+
readOnly: r.readOnly,
|
|
99
|
+
allowedPrefixes: r.allowedOutputPrefixes,
|
|
100
|
+
})),
|
|
101
|
+
};
|
|
102
|
+
if (flags.json) {
|
|
103
|
+
console.log(JSON.stringify(matrix, null, 2));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log('Structural Authority Matrix:\n');
|
|
107
|
+
console.log(`Read-Only Roles: ${matrix.readOnlyRoles.join(', ')}`);
|
|
108
|
+
console.log(`Forbidden Command Patterns:\n${matrix.forbiddenPatterns.map((p) => ` - ${p}`).join('\n')}\n`);
|
|
109
|
+
for (const r of matrix.roles) {
|
|
110
|
+
console.log(`- ${r.id.padEnd(20)} ${r.readOnly ? 'RO' : 'RW'} (Outputs: ${r.allowedPrefixes.join(', ')})`);
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.error(`Unknown subcommand '${sub}'. Run 'esquadrao role --help' for usage.`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export default run;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { execSync } from 'node:child_process';
|
|
6
|
+
|
|
7
|
+
function checkBinary(name) {
|
|
8
|
+
try {
|
|
9
|
+
const cmd = process.platform === 'win32' ? `where ${name}` : `which ${name}`;
|
|
10
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
11
|
+
return true;
|
|
12
|
+
} catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function tryAutoInstallFfmpeg() {
|
|
18
|
+
if (checkBinary('ffmpeg') && checkBinary('ffprobe')) return true;
|
|
19
|
+
try {
|
|
20
|
+
if (process.platform === 'darwin') {
|
|
21
|
+
execSync('brew install ffmpeg', { stdio: 'ignore', timeout: 60000 });
|
|
22
|
+
} else if (process.platform === 'win32') {
|
|
23
|
+
execSync('winget install Gyan.FFmpeg --accept-package-agreements --accept-source-agreements', { stdio: 'ignore', timeout: 60000 });
|
|
24
|
+
} else {
|
|
25
|
+
execSync('which apt-get && (apt-get update -qq && apt-get install -y -qq ffmpeg) || sudo apt-get update -qq && sudo apt-get install -y -qq ffmpeg', { stdio: 'ignore', timeout: 60000 });
|
|
26
|
+
}
|
|
27
|
+
return checkBinary('ffmpeg') && checkBinary('ffprobe');
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const SKILLS = [
|
|
34
|
+
'skill-orchestrate',
|
|
35
|
+
'skill-pipeline',
|
|
36
|
+
'skill-review',
|
|
37
|
+
'skill-audit',
|
|
38
|
+
'skill-context',
|
|
39
|
+
'skill-ui',
|
|
40
|
+
'skill-product-manager',
|
|
41
|
+
'skill-system-analyst',
|
|
42
|
+
'skill-software-architect',
|
|
43
|
+
'skill-tech-lead',
|
|
44
|
+
'skill-security-engineer',
|
|
45
|
+
'skill-software-engineer',
|
|
46
|
+
'skill-code-reviewer',
|
|
47
|
+
'skill-sre-engineer',
|
|
48
|
+
'skill-qa-engineer',
|
|
49
|
+
'skill-technical-writer',
|
|
50
|
+
'skill-engineering-manager',
|
|
51
|
+
'skill-media-producer',
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// ponytail: synchronous copy; upgrade to async workers when syncing >50 skills
|
|
55
|
+
export async function run({ positionals = [], flags = {} } = {}) {
|
|
56
|
+
if (flags?.help) {
|
|
57
|
+
console.log('Usage: esquadrao setup [--dest <path>] [--json]');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const rootDir = fileURLToPath(new URL('../../', import.meta.url));
|
|
62
|
+
const cwd = process.cwd();
|
|
63
|
+
const destArg = typeof flags?.dest === 'string' ? flags.dest : (positionals[0] || null);
|
|
64
|
+
const destDir = destArg || path.join(cwd, '.agents', 'skills');
|
|
65
|
+
|
|
66
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
67
|
+
const installed = [];
|
|
68
|
+
for (const item of [...SKILLS, 'scripts']) {
|
|
69
|
+
const src = path.join(rootDir, item);
|
|
70
|
+
if (fs.existsSync(src)) {
|
|
71
|
+
fs.cpSync(src, path.join(destDir, item), { recursive: true });
|
|
72
|
+
installed.push(item);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const harnesses = [];
|
|
77
|
+
|
|
78
|
+
// If a custom destination was not explicitly passed, configure local project harnesses
|
|
79
|
+
if (!destArg) {
|
|
80
|
+
// 1. Grok Build / Agent Skills
|
|
81
|
+
if (fs.existsSync(path.join(cwd, '.agents'))) {
|
|
82
|
+
harnesses.push('.agents');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 2. Claude Code
|
|
86
|
+
const claudeDir = path.join(cwd, '.claude');
|
|
87
|
+
if (fs.existsSync(claudeDir)) {
|
|
88
|
+
harnesses.push('.claude');
|
|
89
|
+
const claudeSkillsDir = path.join(claudeDir, 'skills');
|
|
90
|
+
fs.mkdirSync(claudeSkillsDir, { recursive: true });
|
|
91
|
+
for (const item of [...SKILLS, 'scripts']) {
|
|
92
|
+
const src = path.join(rootDir, item);
|
|
93
|
+
if (fs.existsSync(src)) {
|
|
94
|
+
fs.cpSync(src, path.join(claudeSkillsDir, item), { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 3. Codex CLI (detects .codex or ~/.codex or AGENTS.md)
|
|
100
|
+
const codexDir = path.join(cwd, '.codex');
|
|
101
|
+
const userCodex = path.join(os.homedir(), '.codex');
|
|
102
|
+
if (fs.existsSync(codexDir) || fs.existsSync(userCodex) || fs.existsSync(path.join(cwd, 'AGENTS.md'))) {
|
|
103
|
+
harnesses.push('.codex');
|
|
104
|
+
const codexSkillsDir = path.join(codexDir, 'skills');
|
|
105
|
+
fs.mkdirSync(codexSkillsDir, { recursive: true });
|
|
106
|
+
for (const item of [...SKILLS, 'scripts']) {
|
|
107
|
+
const src = path.join(rootDir, item);
|
|
108
|
+
if (fs.existsSync(src)) {
|
|
109
|
+
fs.cpSync(src, path.join(codexSkillsDir, item), { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Ensure AGENTS.md references the skills
|
|
114
|
+
const agentsMdPath = path.join(cwd, 'AGENTS.md');
|
|
115
|
+
if (!fs.existsSync(agentsMdPath)) {
|
|
116
|
+
fs.writeFileSync(
|
|
117
|
+
agentsMdPath,
|
|
118
|
+
'# Agent Instructions\n\nSkills are installed in `.codex/skills/` and `.agents/skills/`.\n'
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 4. Cursor Rules (.cursor/rules/*.mdc)
|
|
124
|
+
const cursorDir = path.join(cwd, '.cursor');
|
|
125
|
+
if (fs.existsSync(cursorDir)) {
|
|
126
|
+
harnesses.push('.cursor');
|
|
127
|
+
const rulesDir = path.join(cursorDir, 'rules');
|
|
128
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
129
|
+
fs.writeFileSync(
|
|
130
|
+
path.join(rulesDir, 'esquadrao.mdc'),
|
|
131
|
+
'---\ndescription: Esquadrao Skills Rules\nglobs: *\n---\nUse esquadrao tools and CLI.\n'
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 5. VS Code
|
|
136
|
+
if (fs.existsSync(path.join(cwd, '.vscode'))) harnesses.push('.vscode');
|
|
137
|
+
|
|
138
|
+
// 6. Hermes
|
|
139
|
+
if (fs.existsSync(path.join(os.homedir(), '.hermes'))) harnesses.push('.hermes');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const nodeMajor = parseInt(process.versions.node.split('.')[0], 10);
|
|
143
|
+
const nodeOk = nodeMajor >= 18;
|
|
144
|
+
|
|
145
|
+
let hasFfmpeg = checkBinary('ffmpeg') && checkBinary('ffprobe');
|
|
146
|
+
let autoInstalledFfmpeg = false;
|
|
147
|
+
if (!hasFfmpeg) {
|
|
148
|
+
autoInstalledFfmpeg = tryAutoInstallFfmpeg();
|
|
149
|
+
hasFfmpeg = checkBinary('ffmpeg') && checkBinary('ffprobe');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const report = {
|
|
153
|
+
status: nodeOk ? 'ok' : 'degraded',
|
|
154
|
+
prerequisites: {
|
|
155
|
+
node: { version: process.version, valid: nodeOk },
|
|
156
|
+
ffmpeg: { valid: hasFfmpeg, auto_installed: autoInstalledFfmpeg }
|
|
157
|
+
},
|
|
158
|
+
installation: { destination: destDir, installed },
|
|
159
|
+
harnesses,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
if (flags?.json) {
|
|
163
|
+
console.log(JSON.stringify(report));
|
|
164
|
+
} else {
|
|
165
|
+
console.log(`Esquadrão Setup: ${report.status.toUpperCase()}`);
|
|
166
|
+
console.log(`- Node.js: ${process.version} (${nodeOk ? 'OK' : 'Requires >= 18'})`);
|
|
167
|
+
console.log(`- FFmpeg & ffprobe: ${hasFfmpeg ? (autoInstalledFfmpeg ? 'Instalado automaticamente com sucesso!' : 'OK') : 'Pendente (peça ao seu agente de IA: "instale o ffmpeg para mim")'}`);
|
|
168
|
+
console.log(`- Installed ${installed.length} items to ${destDir}`);
|
|
169
|
+
if (harnesses.length) console.log(`- Harnesses detected: ${harnesses.join(', ')}`);
|
|
170
|
+
}
|
|
171
|
+
return report;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export default run;
|