oxe-cc 0.6.2 → 0.6.5
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/.cursor/commands/oxe-execute.md +1 -1
- package/.cursor/commands/oxe-session.md +11 -0
- package/.github/prompts/oxe-execute.prompt.md +1 -1
- package/.github/prompts/oxe-loop.prompt.md +12 -12
- package/.github/prompts/oxe-project.prompt.md +12 -12
- package/.github/prompts/oxe-retro.prompt.md +12 -12
- package/.github/prompts/oxe-security.prompt.md +12 -12
- package/.github/prompts/oxe-session.prompt.md +12 -0
- package/.github/prompts/oxe.prompt.md +12 -12
- package/AGENTS.md +75 -8
- package/CHANGELOG.md +74 -0
- package/README.md +81 -60
- package/bin/banner.txt +1 -1
- package/bin/lib/oxe-project-health.cjs +82 -0
- package/bin/oxe-cc.js +13 -1
- package/commands/oxe/loop.md +17 -17
- package/commands/oxe/oxe.md +16 -16
- package/commands/oxe/project.md +16 -16
- package/commands/oxe/retro.md +16 -16
- package/commands/oxe/review-pr.md +16 -0
- package/commands/oxe/security.md +16 -16
- package/commands/oxe/session.md +16 -0
- package/commands/oxe/update.md +16 -0
- package/lib/sdk/index.cjs +22 -1
- package/lib/sdk/index.d.ts +28 -2
- package/oxe/schemas/plan-agents.schema.json +15 -4
- package/oxe/templates/CONFIG.md +6 -1
- package/oxe/templates/LESSONS.template.md +43 -43
- package/oxe/templates/SECURITY.template.md +72 -72
- package/oxe/templates/SESSION.template.md +32 -0
- package/oxe/templates/STATE.md +29 -6
- package/oxe/templates/config.template.json +2 -0
- package/oxe/templates/plan-agents.template.json +1 -0
- package/oxe/workflows/checkpoint.md +10 -9
- package/oxe/workflows/debug.md +6 -5
- package/oxe/workflows/discuss.md +8 -7
- package/oxe/workflows/execute.md +14 -12
- package/oxe/workflows/forensics.md +6 -6
- package/oxe/workflows/help.md +21 -4
- package/oxe/workflows/loop.md +57 -57
- package/oxe/workflows/milestone.md +12 -13
- package/oxe/workflows/next.md +9 -5
- package/oxe/workflows/obs.md +19 -8
- package/oxe/workflows/oxe.md +115 -115
- package/oxe/workflows/plan-agent.md +4 -3
- package/oxe/workflows/plan.md +17 -16
- package/oxe/workflows/project.md +50 -50
- package/oxe/workflows/quick.md +6 -5
- package/oxe/workflows/references/session-path-resolution.md +71 -0
- package/oxe/workflows/research.md +9 -8
- package/oxe/workflows/retro.md +62 -62
- package/oxe/workflows/security.md +59 -58
- package/oxe/workflows/session.md +153 -0
- package/oxe/workflows/spec.md +26 -20
- package/oxe/workflows/ui-review.md +3 -3
- package/oxe/workflows/ui-spec.md +3 -3
- package/oxe/workflows/validate-gaps.md +5 -4
- package/oxe/workflows/verify.md +12 -9
- package/oxe/workflows/workstream.md +16 -15
- package/package.json +2 -2
|
@@ -12,12 +12,14 @@ const ALLOWED_CONFIG_KEYS = [
|
|
|
12
12
|
'default_verify_command',
|
|
13
13
|
'scan_max_age_days',
|
|
14
14
|
'compact_max_age_days',
|
|
15
|
+
'lessons_max_age_days',
|
|
15
16
|
'scan_focus_globs',
|
|
16
17
|
'scan_ignore_globs',
|
|
17
18
|
'spec_required_sections',
|
|
18
19
|
'plan_max_tasks_per_wave',
|
|
19
20
|
'profile',
|
|
20
21
|
'verification_depth',
|
|
22
|
+
'security_in_verify',
|
|
21
23
|
'install',
|
|
22
24
|
'plugins',
|
|
23
25
|
'workstreams',
|
|
@@ -279,6 +281,18 @@ function parseLastCompactDate(stateText) {
|
|
|
279
281
|
return null;
|
|
280
282
|
}
|
|
281
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Data do último `/oxe-retro` em STATE.md (campo `last_retro: YYYY-MM-DD`).
|
|
286
|
+
* @param {string} stateText
|
|
287
|
+
* @returns {Date | null}
|
|
288
|
+
*/
|
|
289
|
+
function parseLastRetroDate(stateText) {
|
|
290
|
+
const m = stateText.match(/\blast_retro\s*:\s*(\d{4}-\d{2}-\d{2})/i);
|
|
291
|
+
if (!m) return null;
|
|
292
|
+
const iso = Date.parse(m[1]);
|
|
293
|
+
return Number.isNaN(iso) ? null : new Date(iso);
|
|
294
|
+
}
|
|
295
|
+
|
|
282
296
|
/**
|
|
283
297
|
* @param {Date | null} scanDate
|
|
284
298
|
* @param {number} maxAgeDays 0 = desligado
|
|
@@ -289,6 +303,16 @@ function isStaleScan(scanDate, maxAgeDays) {
|
|
|
289
303
|
return { stale: days > maxAgeDays, days: Math.floor(days) };
|
|
290
304
|
}
|
|
291
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Alias semântico para verificar se LESSONS.md está desatualizado.
|
|
308
|
+
* Reutiliza a lógica de isStaleScan.
|
|
309
|
+
* @param {Date | null} retroDate
|
|
310
|
+
* @param {number} maxAgeDays 0 = desligado
|
|
311
|
+
*/
|
|
312
|
+
function isStaleLessons(retroDate, maxAgeDays) {
|
|
313
|
+
return isStaleScan(retroDate, maxAgeDays);
|
|
314
|
+
}
|
|
315
|
+
|
|
292
316
|
/**
|
|
293
317
|
* @param {string} target
|
|
294
318
|
*/
|
|
@@ -304,9 +328,45 @@ function oxePaths(target) {
|
|
|
304
328
|
discuss: path.join(oxe, 'DISCUSS.md'),
|
|
305
329
|
summary: path.join(oxe, 'SUMMARY.md'),
|
|
306
330
|
codebase: path.join(oxe, 'codebase'),
|
|
331
|
+
lessons: path.join(oxe, 'LESSONS.md'),
|
|
332
|
+
planAgents: path.join(oxe, 'plan-agents.json'),
|
|
307
333
|
};
|
|
308
334
|
}
|
|
309
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Valida o arquivo plan-agents.json (se existir) e retorna avisos.
|
|
338
|
+
* @param {string} target
|
|
339
|
+
* @returns {string[]}
|
|
340
|
+
*/
|
|
341
|
+
function planAgentsWarnings(target) {
|
|
342
|
+
const p = oxePaths(target);
|
|
343
|
+
if (!fs.existsSync(p.planAgents)) return [];
|
|
344
|
+
/** @type {string[]} */
|
|
345
|
+
const warns = [];
|
|
346
|
+
let json;
|
|
347
|
+
try {
|
|
348
|
+
json = JSON.parse(fs.readFileSync(p.planAgents, 'utf8'));
|
|
349
|
+
} catch {
|
|
350
|
+
warns.push('plan-agents.json existe mas não é JSON válido');
|
|
351
|
+
return warns;
|
|
352
|
+
}
|
|
353
|
+
const schema = json.oxePlanAgentsSchema;
|
|
354
|
+
if (schema === 1) {
|
|
355
|
+
warns.push('plan-agents.json usa schema 1 (legado) — regere com /oxe-plan-agent para schema 3');
|
|
356
|
+
}
|
|
357
|
+
if (Array.isArray(json.agents)) {
|
|
358
|
+
const VALID_HINTS = new Set(['fast', 'balanced', 'powerful']);
|
|
359
|
+
for (const agent of json.agents) {
|
|
360
|
+
if (agent.model_hint && !VALID_HINTS.has(agent.model_hint)) {
|
|
361
|
+
warns.push(
|
|
362
|
+
`plan-agents.json agente "${agent.id || '?'}": model_hint "${agent.model_hint}" inválido — use fast | balanced | powerful`
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return warns;
|
|
368
|
+
}
|
|
369
|
+
|
|
310
370
|
/**
|
|
311
371
|
* @param {string} phase
|
|
312
372
|
* @param {ReturnType<typeof oxePaths>} p
|
|
@@ -537,6 +597,20 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
537
597
|
};
|
|
538
598
|
}
|
|
539
599
|
|
|
600
|
+
// Após verify_complete, sugerir retro se LESSONS.md não existe ou last_retro ausente no STATE
|
|
601
|
+
if (phaseLow === 'verify_complete' || /\bverify_complete\b/i.test(stateText)) {
|
|
602
|
+
const lessonsExist = has(path.join(target, '.oxe', 'LESSONS.md'));
|
|
603
|
+
const hasRetroInState = /\blast_retro\s*:/i.test(stateText);
|
|
604
|
+
if (!lessonsExist || !hasRetroInState) {
|
|
605
|
+
return {
|
|
606
|
+
step: 'retro',
|
|
607
|
+
cursorCmd: '/oxe-retro',
|
|
608
|
+
reason: 'Verify completo — capture as lições do ciclo em .oxe/LESSONS.md para orientar o próximo spec/plan',
|
|
609
|
+
artifacts: ['.oxe/LESSONS.md'],
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
540
614
|
return {
|
|
541
615
|
step: 'next',
|
|
542
616
|
cursorCmd: '/oxe-next',
|
|
@@ -565,6 +639,8 @@ function buildHealthReport(target) {
|
|
|
565
639
|
const stale = isStaleScan(scanDate, Number(config.scan_max_age_days) || 0);
|
|
566
640
|
const compactDate = parseLastCompactDate(stateText);
|
|
567
641
|
const staleCompact = isStaleScan(compactDate, Number(config.compact_max_age_days) || 0);
|
|
642
|
+
const retroDate = parseLastRetroDate(stateText);
|
|
643
|
+
const staleLessons = isStaleLessons(retroDate, Number(config.lessons_max_age_days) || 0);
|
|
568
644
|
const phaseWarn = phase ? phaseCoherenceWarnings(phase, p) : [];
|
|
569
645
|
const sumWarn = verifyGapsWithoutSummaryWarning(p.verify, p.summary);
|
|
570
646
|
const specReq = Array.isArray(config.spec_required_sections) ? config.spec_required_sections : [];
|
|
@@ -572,6 +648,7 @@ function buildHealthReport(target) {
|
|
|
572
648
|
const planWarn = [
|
|
573
649
|
...planWaveWarningsFixed(p.plan, Number(config.plan_max_tasks_per_wave) || 0),
|
|
574
650
|
...planTaskAceiteWarnings(p.plan),
|
|
651
|
+
...planAgentsWarnings(target),
|
|
575
652
|
];
|
|
576
653
|
const next = suggestNextStep(target, { discuss_before_plan: config.discuss_before_plan });
|
|
577
654
|
|
|
@@ -585,6 +662,8 @@ function buildHealthReport(target) {
|
|
|
585
662
|
stale,
|
|
586
663
|
compactDate,
|
|
587
664
|
staleCompact,
|
|
665
|
+
retroDate,
|
|
666
|
+
staleLessons,
|
|
588
667
|
phaseWarn,
|
|
589
668
|
summaryGapWarn: sumWarn,
|
|
590
669
|
specWarn,
|
|
@@ -609,7 +688,10 @@ module.exports = {
|
|
|
609
688
|
parseStatePhase,
|
|
610
689
|
parseLastScanDate,
|
|
611
690
|
parseLastCompactDate,
|
|
691
|
+
parseLastRetroDate,
|
|
612
692
|
isStaleScan,
|
|
693
|
+
isStaleLessons,
|
|
694
|
+
planAgentsWarnings,
|
|
613
695
|
phaseCoherenceWarnings,
|
|
614
696
|
verifyGapsWithoutSummaryWarning,
|
|
615
697
|
specSectionWarnings,
|
package/bin/oxe-cc.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* OXE — CLI em pt-BR: instala workflows no projeto, bootstrap `.oxe/`, doctor, uninstall, update.
|
|
4
4
|
* Uso: npx oxe-cc, doctor, status, init-oxe, uninstall, update (ver --help).
|
|
@@ -1543,6 +1543,13 @@ ${green}Opções da instalação:${reset}
|
|
|
1543
1543
|
-h, --help
|
|
1544
1544
|
-v, --version
|
|
1545
1545
|
|
|
1546
|
+
${green}doctor${reset} (valida estrutura OXE, config e saúde do projeto)
|
|
1547
|
+
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
1548
|
+
|
|
1549
|
+
${green}init-oxe${reset} (bootstrap só de .oxe/ no projeto — STATE.md, codebase/, templates)
|
|
1550
|
+
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
1551
|
+
--force, -f sobrescreve arquivos existentes
|
|
1552
|
+
|
|
1546
1553
|
${green}status${reset} (coerência .oxe/ + um próximo passo sugerido; não exige pacote de workflows completo)
|
|
1547
1554
|
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
1548
1555
|
--json imprime um único objeto JSON (próximo passo + diagnósticos) em stdout; adequado a CI
|
|
@@ -1625,6 +1632,11 @@ function runInstall(opts) {
|
|
|
1625
1632
|
if (fs.existsSync(personasSrc)) {
|
|
1626
1633
|
copyDir(personasSrc, path.join(nested, 'personas'), copyOpts, false);
|
|
1627
1634
|
}
|
|
1635
|
+
// Schemas: copiar para .oxe/schemas/ (ex.: plan-agents.schema.json para validação local)
|
|
1636
|
+
const schemasSrc = path.join(PKG_ROOT, 'oxe', 'schemas');
|
|
1637
|
+
if (fs.existsSync(schemasSrc)) {
|
|
1638
|
+
copyDir(schemasSrc, path.join(nested, 'schemas'), copyOpts, false);
|
|
1639
|
+
}
|
|
1628
1640
|
}
|
|
1629
1641
|
|
|
1630
1642
|
const cursorBase = installCursorBase(opts);
|
package/commands/oxe/loop.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: oxe:loop
|
|
3
|
-
description: OXE — Execução iterativa de onda com retries automáticos e diagnóstico inline
|
|
4
|
-
argument-hint: "onda <N> [max:<tentativas>]"
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Bash
|
|
8
|
-
- Glob
|
|
9
|
-
- Grep
|
|
10
|
-
- Write
|
|
11
|
-
- Edit
|
|
12
|
-
- Task
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
**Workflow canônico:** `oxe/workflows/loop.md`
|
|
16
|
-
|
|
17
|
-
Execute integralmente esse ficheiro na raiz do repositório. `$ARGUMENTS` = onda alvo e máximo de tentativas. Pré-requisito: `.oxe/PLAN.md`.
|
|
1
|
+
---
|
|
2
|
+
name: oxe:loop
|
|
3
|
+
description: OXE — Execução iterativa de onda com retries automáticos e diagnóstico inline
|
|
4
|
+
argument-hint: "onda <N> [max:<tentativas>]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Edit
|
|
12
|
+
- Task
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
**Workflow canônico:** `oxe/workflows/loop.md`
|
|
16
|
+
|
|
17
|
+
Execute integralmente esse ficheiro na raiz do repositório. `$ARGUMENTS` = onda alvo e máximo de tentativas. Pré-requisito: `.oxe/PLAN.md`.
|
package/commands/oxe/oxe.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: oxe
|
|
3
|
-
description: OXE — Entrada universal: próximo passo, roteamento de linguagem natural ou help dos 8 comandos essenciais
|
|
4
|
-
argument-hint: "[contexto | 'help' | vazio]"
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Bash
|
|
8
|
-
- Glob
|
|
9
|
-
- Grep
|
|
10
|
-
- Write
|
|
11
|
-
- Task
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
**Workflow canônico:** `oxe/workflows/oxe.md`
|
|
15
|
-
|
|
16
|
-
Execute integralmente esse ficheiro. `$ARGUMENTS`: vazio → próximo passo; texto → roteamento inteligente; "help" → 8 comandos essenciais.
|
|
1
|
+
---
|
|
2
|
+
name: oxe
|
|
3
|
+
description: OXE — Entrada universal: próximo passo, roteamento de linguagem natural ou help dos 8 comandos essenciais
|
|
4
|
+
argument-hint: "[contexto | 'help' | vazio]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canônico:** `oxe/workflows/oxe.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro. `$ARGUMENTS`: vazio → próximo passo; texto → roteamento inteligente; "help" → 8 comandos essenciais.
|
package/commands/oxe/project.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: oxe:project
|
|
3
|
-
description: OXE — Gestão de projeto: milestone (M-NN), workstream (trilhas paralelas), checkpoint (snapshot)
|
|
4
|
-
argument-hint: "milestone new|complete|status|audit | workstream new|switch|list|close <nome> | checkpoint [slug]"
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Bash
|
|
8
|
-
- Glob
|
|
9
|
-
- Grep
|
|
10
|
-
- Write
|
|
11
|
-
- Task
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
**Workflow canônico:** `oxe/workflows/project.md`
|
|
15
|
-
|
|
16
|
-
Execute integralmente esse ficheiro. `$ARGUMENTS` = subcomando. Sem argumento: mostra status atual (milestone ativo, workstreams, último checkpoint).
|
|
1
|
+
---
|
|
2
|
+
name: oxe:project
|
|
3
|
+
description: OXE — Gestão de projeto: milestone (M-NN), workstream (trilhas paralelas), checkpoint (snapshot)
|
|
4
|
+
argument-hint: "milestone new|complete|status|audit | workstream new|switch|list|close <nome> | checkpoint [slug]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canônico:** `oxe/workflows/project.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro. `$ARGUMENTS` = subcomando. Sem argumento: mostra status atual (milestone ativo, workstreams, último checkpoint).
|
package/commands/oxe/retro.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: oxe:retro
|
|
3
|
-
description: OXE — Retrospectiva de ciclo: sintetiza lições prescritivas em .oxe/LESSONS.md (alimenta ciclos futuros automaticamente)
|
|
4
|
-
argument-hint: "[opcional: contexto sobre o ciclo]"
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Bash
|
|
8
|
-
- Glob
|
|
9
|
-
- Grep
|
|
10
|
-
- Write
|
|
11
|
-
- Task
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
**Workflow canônico:** `oxe/workflows/retro.md`
|
|
15
|
-
|
|
16
|
-
Execute integralmente esse ficheiro. Lê VERIFY.md, FORENSICS.md, SUMMARY.md para sintetizar 3–5 lições prescritivas. `$ARGUMENTS` = contexto extra opcional.
|
|
1
|
+
---
|
|
2
|
+
name: oxe:retro
|
|
3
|
+
description: OXE — Retrospectiva de ciclo: sintetiza lições prescritivas em .oxe/LESSONS.md (alimenta ciclos futuros automaticamente)
|
|
4
|
+
argument-hint: "[opcional: contexto sobre o ciclo]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canônico:** `oxe/workflows/retro.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro. Lê VERIFY.md, FORENSICS.md, SUMMARY.md para sintetizar 3–5 lições prescritivas. `$ARGUMENTS` = contexto extra opcional.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:review-pr
|
|
3
|
+
description: OXE — Revisão de diff/PR: analisa alterações, riscos, convenções e sugestões acionáveis
|
|
4
|
+
argument-hint: "<URL do PR ou branch:base..head>"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canônico:** `oxe/workflows/review-pr.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro. Recebe URL de PR do GitHub (`org/repo#N`) ou par de branches/SHAs. `$ARGUMENTS` = referência do diff.
|
package/commands/oxe/security.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: oxe:security
|
|
3
|
-
description: OXE — Auditoria de segurança OWASP (.oxe/SECURITY.md): P0 crítico / P1 alto / P2 médio
|
|
4
|
-
argument-hint: "[opcional: categoria OWASP, módulo ou arquivo]"
|
|
5
|
-
allowed-tools:
|
|
6
|
-
- Read
|
|
7
|
-
- Bash
|
|
8
|
-
- Glob
|
|
9
|
-
- Grep
|
|
10
|
-
- Write
|
|
11
|
-
- Task
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
**Workflow canônico:** `oxe/workflows/security.md`
|
|
15
|
-
|
|
16
|
-
Execute integralmente esse ficheiro na raiz do repositório. Lê `STACK.md` para determinar categorias OWASP pertinentes. `$ARGUMENTS` = foco opcional.
|
|
1
|
+
---
|
|
2
|
+
name: oxe:security
|
|
3
|
+
description: OXE — Auditoria de segurança OWASP (.oxe/SECURITY.md): P0 crítico / P1 alto / P2 médio
|
|
4
|
+
argument-hint: "[opcional: categoria OWASP, módulo ou arquivo]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canônico:** `oxe/workflows/security.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Lê `STACK.md` para determinar categorias OWASP pertinentes. `$ARGUMENTS` = foco opcional.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:session
|
|
3
|
+
description: "Gerir sessões OXE: new, list, switch, resume, status, close, migrate"
|
|
4
|
+
argument-hint: "[new <nome> | list | switch <id> | resume <id> | status | close | migrate <nome>]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/session.md`
|
|
15
|
+
|
|
16
|
+
Executa integralmente esse ficheiro na raiz do repositório em que estás a trabalhar. Usa `$ARGUMENTS` como subcomando e foco da operação da sessão ativa.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:update
|
|
3
|
+
description: OXE — Atualiza workflows e integrações para a versão mais recente do oxe-cc no npm
|
|
4
|
+
argument-hint: "[--force] [--check] [--if-newer]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canônico:** `oxe/workflows/update.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro. Verifica versão no npm, reinstala com --force se necessário e valida com doctor. `$ARGUMENTS` = flags opcionais.
|
package/lib/sdk/index.cjs
CHANGED
|
@@ -205,7 +205,25 @@ function parseState(stateMd) {
|
|
|
205
205
|
const msMatch = stateMd.match(/##\s*Milestone ativo\s*\n+[^`]*`([^`]+)`/im);
|
|
206
206
|
const activeMilestone = msMatch ? msMatch[1] : null;
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
// Último retro
|
|
209
|
+
const retroDate = health.parseLastRetroDate(stateMd);
|
|
210
|
+
const lastRetroDate = retroDate ? retroDate.toISOString().split('T')[0] : null;
|
|
211
|
+
|
|
212
|
+
// Blueprint de agentes (sessão)
|
|
213
|
+
const runIdMatch = stateMd.match(/^\s*[-*]?\s*\*?\*?run_id:\*?\*?\s*(.+)/im);
|
|
214
|
+
const runIdRaw = runIdMatch ? runIdMatch[1].trim().replace(/^[\(\-—]+|[\)\-—]+$/g, '').trim() : null;
|
|
215
|
+
const runId = runIdRaw && runIdRaw !== '—' && runIdRaw !== '-' ? runIdRaw : null;
|
|
216
|
+
|
|
217
|
+
const lifecycleMatch = stateMd.match(/^\s*[-*]?\s*\*?\*?lifecycle_status:\*?\*?\s*([^\s\n|`(]+)/im);
|
|
218
|
+
const lifecycleStatusRaw = lifecycleMatch ? lifecycleMatch[1].trim() : null;
|
|
219
|
+
const lifecycleStatus = lifecycleStatusRaw && lifecycleStatusRaw !== '—' && lifecycleStatusRaw !== '-' ? lifecycleStatusRaw : null;
|
|
220
|
+
|
|
221
|
+
// Loop (sessão)
|
|
222
|
+
const loopStatusMatch = stateMd.match(/^\s*[-*]?\s*\*?\*?loop_status:\*?\*?\s*([^\s\n|`(]+)/im);
|
|
223
|
+
const loopStatusRaw = loopStatusMatch ? loopStatusMatch[1].trim() : null;
|
|
224
|
+
const loopStatus = loopStatusRaw && loopStatusRaw !== '—' && loopStatusRaw !== '-' ? loopStatusRaw : null;
|
|
225
|
+
|
|
226
|
+
return { phase, lastScanDate, lastRetroDate, nextStep, decisions, activeWorkstreams, activeMilestone, runId, lifecycleStatus, loopStatus };
|
|
209
227
|
}
|
|
210
228
|
|
|
211
229
|
/**
|
|
@@ -456,7 +474,10 @@ module.exports = {
|
|
|
456
474
|
parseStatePhase: health.parseStatePhase,
|
|
457
475
|
parseLastScanDate: health.parseLastScanDate,
|
|
458
476
|
parseLastCompactDate: health.parseLastCompactDate,
|
|
477
|
+
parseLastRetroDate: health.parseLastRetroDate,
|
|
459
478
|
isStaleScan: health.isStaleScan,
|
|
479
|
+
isStaleLessons: health.isStaleLessons,
|
|
480
|
+
planAgentsWarnings: health.planAgentsWarnings,
|
|
460
481
|
phaseCoherenceWarnings: health.phaseCoherenceWarnings,
|
|
461
482
|
specSectionWarnings: health.specSectionWarnings,
|
|
462
483
|
planWaveWarningsFixed: health.planWaveWarningsFixed,
|
package/lib/sdk/index.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export interface OxeHealthReport {
|
|
|
56
56
|
stale: HealthStaleInfo;
|
|
57
57
|
compactDate: Date | null;
|
|
58
58
|
staleCompact: HealthStaleInfo;
|
|
59
|
+
retroDate: Date | null;
|
|
60
|
+
staleLessons: HealthStaleInfo;
|
|
59
61
|
phaseWarn: string[];
|
|
60
62
|
summaryGapWarn: string | null;
|
|
61
63
|
specWarn: string[];
|
|
@@ -124,10 +126,17 @@ export interface ParsedSpec {
|
|
|
124
126
|
export interface ParsedState {
|
|
125
127
|
phase: string | null;
|
|
126
128
|
lastScanDate: string | null;
|
|
129
|
+
lastRetroDate: string | null;
|
|
127
130
|
nextStep: string | null;
|
|
128
131
|
decisions: string[];
|
|
129
132
|
activeWorkstreams: string[];
|
|
130
133
|
activeMilestone: string | null;
|
|
134
|
+
/** run_id do blueprint ativo extraído da seção "Blueprint de agentes" em STATE.md. */
|
|
135
|
+
runId: string | null;
|
|
136
|
+
/** lifecycle_status do blueprint: pending_execute | executing | closed | invalidated. */
|
|
137
|
+
lifecycleStatus: string | null;
|
|
138
|
+
/** loop_status da sessão de loop: retrying | passed | escalated. */
|
|
139
|
+
loopStatus: string | null;
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
export interface DecisionFidelityResult {
|
|
@@ -173,6 +182,20 @@ export interface PluginValidationResult {
|
|
|
173
182
|
issues: Array<{ file: string; issue: string }>;
|
|
174
183
|
}
|
|
175
184
|
|
|
185
|
+
export interface ManifestAPI {
|
|
186
|
+
loadFileManifest: (home: string) => Record<string, unknown>;
|
|
187
|
+
writeFileManifest: (home: string, manifest: Record<string, unknown>) => void;
|
|
188
|
+
sha256File: (filePath: string) => string;
|
|
189
|
+
collectFilesRecursive: (dir: string) => string[];
|
|
190
|
+
MANIFEST_DIR: string;
|
|
191
|
+
PATCHES_DIR: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface AgentsAPI {
|
|
195
|
+
adjustWorkflowPathsForNestedLayout: (content: string, layout?: string) => string;
|
|
196
|
+
parseCursorCommandFrontmatter: (mdContent: string) => Record<string, unknown>;
|
|
197
|
+
}
|
|
198
|
+
|
|
176
199
|
export interface OxeSdk {
|
|
177
200
|
version: string;
|
|
178
201
|
name: string;
|
|
@@ -195,7 +218,10 @@ export interface OxeSdk {
|
|
|
195
218
|
parseStatePhase: (stateText: string) => string | null;
|
|
196
219
|
parseLastScanDate: (stateText: string) => Date | null;
|
|
197
220
|
parseLastCompactDate: (stateText: string) => Date | null;
|
|
221
|
+
parseLastRetroDate: (stateText: string) => Date | null;
|
|
198
222
|
isStaleScan: (scanDate: Date | null, maxAgeDays: number) => HealthStaleInfo;
|
|
223
|
+
isStaleLessons: (retroDate: Date | null, maxAgeDays: number) => HealthStaleInfo;
|
|
224
|
+
planAgentsWarnings: (target: string) => string[];
|
|
199
225
|
phaseCoherenceWarnings: (phase: string, paths: Record<string, string>) => string[];
|
|
200
226
|
specSectionWarnings: (specPath: string, requiredHeadings: string[]) => string[];
|
|
201
227
|
planWaveWarningsFixed: (planPath: string, maxPerWave: number) => string[];
|
|
@@ -230,8 +256,8 @@ export interface OxeSdk {
|
|
|
230
256
|
) => { options: Record<string, unknown>; warnings: string[] };
|
|
231
257
|
};
|
|
232
258
|
|
|
233
|
-
manifest:
|
|
234
|
-
agents:
|
|
259
|
+
manifest: ManifestAPI;
|
|
260
|
+
agents: AgentsAPI;
|
|
235
261
|
|
|
236
262
|
security: {
|
|
237
263
|
checkPathSafety: (filePath: string, projectRoot: string, options?: {
|
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
"properties": {
|
|
9
9
|
"oxePlanAgentsSchema": {
|
|
10
10
|
"type": "integer",
|
|
11
|
-
"enum": [
|
|
11
|
+
"enum": [2, 3],
|
|
12
|
+
"description": "Schema 3 = atual (com model_hint). Schema 2 = aceito (sem model_hint). Schema 1 = legado (não recomendado)."
|
|
12
13
|
},
|
|
13
14
|
"goal": { "type": "string", "minLength": 1 },
|
|
14
15
|
"specRef": { "type": "string" },
|
|
15
16
|
"runId": {
|
|
16
17
|
"type": "string",
|
|
17
18
|
"minLength": 8,
|
|
18
|
-
"description": "Obrigatório quando oxePlanAgentsSchema
|
|
19
|
+
"description": "Obrigatório quando oxePlanAgentsSchema >= 2"
|
|
19
20
|
},
|
|
20
21
|
"lifecycle": {
|
|
21
22
|
"type": "object",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"enum": ["quick", "out_of_scope", "new_plan", "manual"]
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
|
-
"description": "Obrigatório quando oxePlanAgentsSchema
|
|
37
|
+
"description": "Obrigatório quando oxePlanAgentsSchema >= 2"
|
|
37
38
|
},
|
|
38
39
|
"agents": {
|
|
39
40
|
"type": "array",
|
|
@@ -48,6 +49,11 @@
|
|
|
48
49
|
"pattern": "^[a-z0-9][a-z0-9-]*$"
|
|
49
50
|
},
|
|
50
51
|
"role": { "type": "string", "minLength": 1 },
|
|
52
|
+
"persona": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"minLength": 1,
|
|
55
|
+
"description": "ID de persona em oxe/personas/ (ex.: executor, architect). Opcional."
|
|
56
|
+
},
|
|
51
57
|
"scope": {
|
|
52
58
|
"type": "array",
|
|
53
59
|
"items": { "type": "string" },
|
|
@@ -72,6 +78,11 @@
|
|
|
72
78
|
"outputs": {
|
|
73
79
|
"type": "array",
|
|
74
80
|
"items": { "type": "string" }
|
|
81
|
+
},
|
|
82
|
+
"model_hint": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"enum": ["fast", "balanced", "powerful"],
|
|
85
|
+
"description": "Tier de modelo sugerido para este agente (schema v3). Opcional."
|
|
75
86
|
}
|
|
76
87
|
}
|
|
77
88
|
}
|
|
@@ -100,7 +111,7 @@
|
|
|
100
111
|
"allOf": [
|
|
101
112
|
{
|
|
102
113
|
"if": {
|
|
103
|
-
"properties": { "oxePlanAgentsSchema": { "
|
|
114
|
+
"properties": { "oxePlanAgentsSchema": { "enum": [2, 3] } },
|
|
104
115
|
"required": ["oxePlanAgentsSchema"]
|
|
105
116
|
},
|
|
106
117
|
"then": {
|
package/oxe/templates/CONFIG.md
CHANGED
|
@@ -8,18 +8,23 @@ Copie `oxe/templates/config.template.json` para **`.oxe/config.json`** no seu pr
|
|
|
8
8
|
|-------|------|-------------|
|
|
9
9
|
| `profile` | string | Profile de execução: `balanced` (padrão) \| `strict` \| `fast` \| `legacy`. Expande automaticamente outras keys — keys explícitas prevalecem. Ver tabela abaixo. |
|
|
10
10
|
| `discuss_before_plan` | boolean | Se `true`, o fluxo recomenda **`oxe:discuss`** entre spec e plan. |
|
|
11
|
-
| `verification_depth` | string | Profundidade da verificação: `standard` (padrão) \| `thorough` (
|
|
11
|
+
| `verification_depth` | string | Profundidade da verificação: `standard` (padrão) \| `thorough` (ativa Camada 5 — validate-gaps automático) \| `quick` (skip camadas 3–4 e UAT). |
|
|
12
|
+
| `security_in_verify` | boolean | Se `true`, executa auditoria OWASP automaticamente no **verify** como **Camada 6** (produz `.oxe/SECURITY.md`). Achados P0 bloqueiam `verify_complete`. Padrão: `false`. |
|
|
12
13
|
| `after_verify_suggest_pr` | boolean | Se `true`, o workflow **verify** inclui checklist de PR no fim. |
|
|
13
14
|
| `after_verify_draft_commit` | boolean | Se `true`, o **verify** propõe rascunho de mensagem de commit alinhado aos critérios de aceite. |
|
|
14
15
|
| `after_verify_suggest_uat` | boolean | Se `true`, o **verify** gera checklist UAT (Camada 4). Ativo automaticamente com `profile: strict`. |
|
|
15
16
|
| `default_verify_command` | string | Comando guarda-chuva opcional (ex.: `npm test`) sugerido em **plan**/**verify** quando o projeto não define outro. |
|
|
16
17
|
| `scan_max_age_days` | number | Se **> 0**, `oxe-cc doctor` / `status` avisam quando a **Data** do último scan em `STATE.md` é mais antiga que esse número de dias. Use **0** para desligar. |
|
|
17
18
|
| `compact_max_age_days` | number | Se **> 0**, `oxe-cc doctor` / `status` avisam quando a **Data** em **Último compact** em `STATE.md` é mais antiga que esse número de dias. Use **0** para desligar. |
|
|
19
|
+
| `lessons_max_age_days` | number | Se **> 0**, `oxe-cc doctor` / `status` avisam quando o campo `last_retro` em `STATE.md` é mais antigo que esse número de dias (ciclos sem retrospectiva). Use **0** para desligar (padrão). |
|
|
18
20
|
| `scale_adaptive` | boolean | Se `true` (padrão), o workflow **scan** sugere automaticamente um `profile` baseado no tamanho do projeto. |
|
|
19
21
|
| `scan_focus_globs` | string[] | Padrões (ex.: `src/api/**`) que o workflow **scan** deve priorizar; só orientação para o agente. |
|
|
20
22
|
| `scan_ignore_globs` | string[] | Padrões a tratar como baixa prioridade ou omitir no scan (ex.: `**/dist/**`). |
|
|
21
23
|
| `spec_required_sections` | string[] | Cabeçalhos que **devem** existir em `SPEC.md` (ex.: `"## Critérios de aceite"`). `doctor` / `status` emitem aviso se faltar. |
|
|
22
24
|
| `plan_max_tasks_per_wave` | number | Se **> 0**, `doctor` / `status` avisam se alguma **Onda** no `PLAN.md` tiver mais tarefas `T1…` que esse limite. **0** desliga. |
|
|
25
|
+
| `plugins` | array | Caminhos de plugins customizados em `.oxe/plugins/` (strings relativas). Padrão: `[]`. Ver [`PLUGINS.md`](PLUGINS.md). |
|
|
26
|
+
| `workstreams` | array | Lista de nomes de workstreams ativos (strings). Usado como referência pelo agente em **`/oxe-workstream`**. Padrão: `[]`. |
|
|
27
|
+
| `milestones` | array | Lista de milestones ativos (objetos `{ "id": "M-01", "name": "..." }`). Usado como referência pelo agente em **`/oxe-milestone`**. Padrão: `[]`. |
|
|
23
28
|
| `install` | object | Opcional. Preferências de **instalação** quando corre `npx oxe-cc` **sem** flags de CLI. Ver tabela abaixo. |
|
|
24
29
|
|
|
25
30
|
## Profiles de execução (`profile`)
|