@brunosps00/dev-workflow 2.1.0 → 2.3.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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +118 -0
- package/README.md +17 -6
- package/lib/constants.js +24 -20
- package/lib/init.js +34 -0
- package/lib/instruction-health.js +38 -0
- package/lib/post-update.js +2 -1
- package/lib/validate.js +3 -1
- package/package.json +1 -1
- package/scaffold/config/routing.json +61 -23
- package/scaffold/en/agent-instructions.md +31 -135
- package/scaffold/en/commands/dw-analyze-project.md +2 -0
- package/scaffold/en/commands/dw-autopilot.md +22 -243
- package/scaffold/en/commands/dw-bugfix.md +9 -35
- package/scaffold/en/commands/dw-claude-run.md +29 -45
- package/scaffold/en/commands/dw-codex-run.md +30 -45
- package/scaffold/en/commands/dw-context-budget.md +6 -14
- package/scaffold/en/commands/dw-copilot-run.md +29 -41
- package/scaffold/en/commands/dw-generate-pr.md +2 -2
- package/scaffold/en/commands/dw-goal.md +11 -5
- package/scaffold/en/commands/dw-harness-audit.md +2 -0
- package/scaffold/en/commands/dw-help.md +8 -4
- package/scaffold/en/commands/dw-pause.md +1 -0
- package/scaffold/en/commands/dw-plan.md +14 -7
- package/scaffold/en/commands/dw-qa.md +2 -0
- package/scaffold/en/commands/dw-report.md +169 -0
- package/scaffold/en/commands/dw-resume.md +5 -11
- package/scaffold/en/commands/dw-review.md +4 -3
- package/scaffold/en/commands/dw-run.md +19 -165
- package/scaffold/en/commands/dw-skill-health.md +7 -0
- package/scaffold/en/commands/dw-update.md +18 -4
- package/scaffold/en/commands/dw-worktree.md +100 -0
- package/scaffold/en/references/command-routing.md +53 -0
- package/scaffold/en/references/execution-contract.md +55 -0
- package/scaffold/en/templates/frontend-quality-template.md +43 -0
- package/scaffold/en/templates/task-template.md +20 -40
- package/scaffold/en/templates/tasks-template.md +9 -6
- package/scaffold/en/templates/techspec-template.md +4 -0
- package/scaffold/pt-br/agent-instructions.md +31 -135
- package/scaffold/pt-br/commands/dw-analyze-project.md +2 -0
- package/scaffold/pt-br/commands/dw-autopilot.md +22 -243
- package/scaffold/pt-br/commands/dw-bugfix.md +9 -35
- package/scaffold/pt-br/commands/dw-claude-run.md +29 -46
- package/scaffold/pt-br/commands/dw-codex-run.md +30 -45
- package/scaffold/pt-br/commands/dw-context-budget.md +6 -14
- package/scaffold/pt-br/commands/dw-copilot-run.md +29 -43
- package/scaffold/pt-br/commands/dw-generate-pr.md +2 -2
- package/scaffold/pt-br/commands/dw-goal.md +11 -5
- package/scaffold/pt-br/commands/dw-harness-audit.md +2 -0
- package/scaffold/pt-br/commands/dw-help.md +8 -4
- package/scaffold/pt-br/commands/dw-pause.md +1 -0
- package/scaffold/pt-br/commands/dw-plan.md +14 -7
- package/scaffold/pt-br/commands/dw-qa.md +2 -0
- package/scaffold/pt-br/commands/dw-report.md +169 -0
- package/scaffold/pt-br/commands/dw-resume.md +7 -11
- package/scaffold/pt-br/commands/dw-review.md +4 -3
- package/scaffold/pt-br/commands/dw-run.md +19 -165
- package/scaffold/pt-br/commands/dw-skill-health.md +7 -0
- package/scaffold/pt-br/commands/dw-update.md +18 -4
- package/scaffold/pt-br/commands/dw-worktree.md +100 -0
- package/scaffold/pt-br/references/command-routing.md +53 -0
- package/scaffold/pt-br/references/execution-contract.md +55 -0
- package/scaffold/pt-br/templates/frontend-quality-template.md +43 -0
- package/scaffold/pt-br/templates/task-template.md +20 -40
- package/scaffold/pt-br/templates/tasks-template.md +9 -6
- package/scaffold/pt-br/templates/techspec-template.md +4 -0
- package/scaffold/scripts/hooks/git-guardrails.mjs +1 -0
- package/scaffold/scripts/lib/workflow-contract.mjs +101 -0
- package/scaffold/scripts/lib/worktree-gc.mjs +460 -0
- package/scaffold/skill-registry.json +23 -23
- package/scaffold/skills/dw-cli-run/SKILL.md +33 -208
- package/scaffold/skills/dw-cli-run/references/dispatch-tuning.md +14 -72
- package/scaffold/skills/dw-codebase-intel/SKILL.md +5 -39
- package/scaffold/skills/dw-codebase-intel/agents/intel-updater.md +1 -1
- package/scaffold/skills/dw-codebase-intel/references/agents-detail.md +7 -0
- package/scaffold/skills/dw-codebase-intel/references/files-in-dw-intel-detail.md +16 -0
- package/scaffold/skills/dw-codebase-intel/references/how-dw-intel-reads-this-detail.md +12 -0
- package/scaffold/skills/dw-codebase-intel/references/how-to-compose-the-typical-flow-detail.md +11 -0
- package/scaffold/skills/dw-council/SKILL.md +2 -17
- package/scaffold/skills/dw-council/references/integration-with-other-dw-commands-detail.md +7 -0
- package/scaffold/skills/dw-council/references/phase-2-tensions-and-rebuttals-detail.md +15 -0
- package/scaffold/skills/dw-domain-modeling/SKILL.md +1 -1
- package/scaffold/skills/dw-execute-phase/SKILL.md +12 -32
- package/scaffold/skills/dw-execute-phase/agents/executor.md +15 -252
- package/scaffold/skills/dw-execute-phase/agents/plan-checker.md +4 -207
- package/scaffold/skills/dw-execute-phase/references/atomic-commits.md +8 -18
- package/scaffold/skills/dw-execute-phase/references/de-sloppify-pass-optional-cleanup-task-detail.md +12 -0
- package/scaffold/skills/dw-execute-phase/references/deviation-rules-during-execution-detail.md +8 -0
- package/scaffold/skills/dw-execute-phase/references/how-the-two-agents-compose-detail.md +7 -0
- package/scaffold/skills/dw-execute-phase/references/plan-verification.md +9 -155
- package/scaffold/skills/dw-execute-phase/references/wave-coordination.md +6 -97
- package/scaffold/skills/dw-git-discipline/SKILL.md +2 -2
- package/scaffold/skills/dw-grilling/SKILL.md +1 -1
- package/scaffold/skills/dw-incident-response/SKILL.md +1 -64
- package/scaffold/skills/dw-incident-response/references/the-five-phases-detail.md +66 -0
- package/scaffold/skills/dw-llm-eval/SKILL.md +5 -53
- package/scaffold/skills/dw-llm-eval/references/agent-tool-use-evaluation-detail.md +23 -0
- package/scaffold/skills/dw-llm-eval/references/anti-patterns-will-block-in-dw-review-code-only-detail.md +9 -0
- package/scaffold/skills/dw-llm-eval/references/consistency-run-to-run-stability-detail.md +10 -0
- package/scaffold/skills/dw-llm-eval/references/integration-with-dev-workflow-commands-detail.md +6 -0
- package/scaffold/skills/dw-llm-eval/references/the-oracle-ladder-detail.md +15 -0
- package/scaffold/skills/dw-memory/SKILL.md +4 -50
- package/scaffold/skills/dw-memory/references/context-budget.md +8 -56
- package/scaffold/skills/dw-memory/references/promotion-decision-test-detail.md +30 -0
- package/scaffold/skills/dw-minimalism/SKILL.md +4 -5
- package/scaffold/skills/dw-review-rigor/SKILL.md +1 -54
- package/scaffold/skills/dw-review-rigor/references/the-five-rules-detail.md +56 -0
- package/scaffold/skills/dw-simplification/SKILL.md +2 -55
- package/scaffold/skills/dw-simplification/references/pattern-recognition-detail.md +11 -0
- package/scaffold/skills/dw-simplification/references/the-five-rules-detail.md +48 -0
- package/scaffold/skills/dw-source-grounding/SKILL.md +1 -56
- package/scaffold/skills/dw-source-grounding/references/the-protocol-detect-fetch-implement-cite-detail.md +58 -0
- package/scaffold/skills/dw-testing-discipline/SKILL.md +25 -177
- package/scaffold/skills/dw-testing-discipline/references/agent-guardrails.md +9 -167
- package/scaffold/skills/dw-testing-discipline/references/core-rules.md +3 -3
- package/scaffold/skills/dw-testing-discipline/references/mutation-testing.md +19 -0
- package/scaffold/skills/dw-testing-discipline/references/patterns.md +3 -12
- package/scaffold/skills/dw-ui-discipline/SKILL.md +2 -59
- package/scaffold/skills/dw-ui-discipline/references/frontend-engineering.md +46 -0
- package/scaffold/skills/dw-ui-discipline/references/the-four-grounding-questions-detail.md +61 -0
- package/scaffold/skills/dw-verify/SKILL.md +26 -148
- package/scaffold/skills/dw-verify/references/verification-discovery-and-attribution.md +2 -2
- package/scaffold/skills/humanizer/SKILL.md +2 -1
- package/scaffold/skills/security-review/SKILL.md +3 -183
- package/scaffold/skills/security-review/references/do-not-flag-detail.md +49 -0
- package/scaffold/skills/security-review/references/quick-patterns-reference-detail.md +56 -0
- package/scaffold/skills/security-review/references/review-process-detail.md +84 -0
- package/scaffold/skills/vercel-react-best-practices/SKILL.md +1 -90
- package/scaffold/skills/vercel-react-best-practices/references/quick-reference-detail.md +92 -0
|
@@ -1,72 +1,52 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: task
|
|
3
|
-
schema_version: "1.
|
|
3
|
+
schema_version: "1.1"
|
|
4
4
|
status: pending
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Tarefa X.0: [Título da Tarefa Principal]
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Leia as seções relevantes do PRD/TechSpec e as restrições da task; use os links abaixo.
|
|
10
10
|
|
|
11
11
|
## Visão Geral
|
|
12
12
|
|
|
13
13
|
[Breve descrição da tarefa]
|
|
14
14
|
|
|
15
|
-
**Requisitos Funcionais cobertos**: RF-X.Y, RF-X.Z
|
|
15
|
+
**Requisitos Funcionais cobertos**: RF-X.Y, RF-X.Z
|
|
16
16
|
Depends on: none
|
|
17
17
|
|
|
18
18
|
<requirements>
|
|
19
19
|
[Lista de requisitos obrigatórios]
|
|
20
20
|
</requirements>
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Escolha de execução
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
- [ ] X.1 [Descrição da subtarefa]
|
|
26
|
-
- [ ] X.2 [Descrição da subtarefa]
|
|
24
|
+
Espelhe a entrada aprovada desta task em `execution-plan.json` (veja `.dw/references/execution-contract.md`).
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
| Complexidade + justificativa | Ferramenta | Modelo / esforço | Agentes | Fallbacks aprovados |
|
|
27
|
+
|---|---|---|---|---|
|
|
28
|
+
| standard — [motivo] | local | inherit / inherit | nenhum | nenhum |
|
|
31
29
|
|
|
32
|
-
##
|
|
30
|
+
## Implementação
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
- [ ] [Comportamento a entregar]
|
|
33
|
+
- [ ] [Verificações relevantes e critérios de aceitação]
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|--------|-------|
|
|
38
|
-
| `[método1]` | Happy path, edge case, erro |
|
|
39
|
-
| `[método2]` | Happy path, not found |
|
|
35
|
+
## Verificação e critérios de sucesso
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
| Comportamento / risco | Suíte existente ou novo teste | Comando / evidência observável |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| [Resultado exigido] | [Menor camada eficaz; teste novo só se necessário] | [Comando do projeto ou inspeção] |
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
Use a estratégia de testes do projeto. Defina mocks só em fronteiras justificadas; não imponha percentuais de cobertura nem teste novo para toda edição. Inclua falhas relevantes quando aplicável.
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
## Arquivos e decisões relevantes
|
|
47
44
|
|
|
48
|
-
|
|
45
|
+
[Caminhos de código e seções relevantes do TechSpec/ADR; não duplique documentos inteiros.]
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
- [Requisitos de qualidade]
|
|
52
|
-
- **Testes unitários passando**
|
|
53
|
-
- **Cobertura mínima 80%** em services/use-cases
|
|
47
|
+
## Commit ao concluir
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
- [Arquivos relevantes desta tarefa]
|
|
57
|
-
- [Arquivo].spec.ts - Testes unitários
|
|
58
|
-
|
|
59
|
-
## Commit ao Final
|
|
60
|
-
|
|
61
|
-
Ao completar esta task, fazer commit:
|
|
62
|
-
```bash
|
|
63
|
-
git add .
|
|
64
|
-
git commit -m "feat([modulo]): [descrição]
|
|
65
|
-
|
|
66
|
-
- [item 1]
|
|
67
|
-
- [item 2]
|
|
68
|
-
- Add unit tests"
|
|
69
|
-
```
|
|
49
|
+
Use o protocolo de commit atômico com escopo do `/dw-run`. Faça stage apenas dos arquivos desta task, preserve IDs de requisitos, registre o SHA resultante em tasks.md/run-log e inclua os registros finais antes da entrega. Não implica push nem merge.
|
|
70
50
|
|
|
71
51
|
## Related ADRs
|
|
72
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: tasks-index
|
|
3
|
-
schema_version: "1.
|
|
3
|
+
schema_version: "1.1"
|
|
4
4
|
status: draft
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -34,10 +34,13 @@ feat/prd-[nome-funcionalidade]
|
|
|
34
34
|
- [ ] 2.0 Título da Tarefa Principal Depends on: 1.0
|
|
35
35
|
- [ ] 3.0 Título da Tarefa Principal Depends on: 1.0, 2.0
|
|
36
36
|
|
|
37
|
+
## Plano de execução
|
|
38
|
+
|
|
39
|
+
Proponha desenvolvimento local ou cruzado por task na quebra. Resuma complexidade/justificativa, ferramenta, modelo/esforço, agentes, dependências e verificação. Salve escolhas validadas e fallbacks aprovados em `execution-plan.json`; use `.dw/references/execution-contract.md`. Registre aprovação da mesma matriz antes de executar.
|
|
40
|
+
|
|
37
41
|
## Workflow
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
4. Próxima task ou `/dw-generate-pr [branch-alvo]` quando todas concluídas
|
|
43
|
+
1. `/dw-run` consome escolhas aprovadas em ordem de dependências.
|
|
44
|
+
2. Cada task implementa, verifica e commita mudanças no escopo; o parent revisa handoffs externos e encaminha correções.
|
|
45
|
+
3. Continue implementação aprovada até review final e QA aplicável. Pedido somente de planejamento termina no plano.
|
|
46
|
+
4. Prepare entrega validada; integre/envie/publique só dentro da autorização existente.
|
|
@@ -78,6 +78,10 @@ type NomeServico interface {
|
|
|
78
78
|
|
|
79
79
|
## Sequenciamento de Desenvolvimento
|
|
80
80
|
|
|
81
|
+
### Qualidade do Frontend (quando aplicável)
|
|
82
|
+
|
|
83
|
+
[Leia a baseline de qualidade existente do módulo. Use linhas relevantes de `.dw/templates/frontend-quality-template.md` para contratos de API, tipos, limites de imports ou ferramentas de qualidade alterados. Registre fontes autoritativas, checks exatos, política atual, adoção proposta e evidência comportamental. Separe diagnósticos consultivos de gates obrigatórios; não transforme uma funcionalidade de UI em migração de ferramentas do repositório inteiro.]
|
|
84
|
+
|
|
81
85
|
### Ordem de Construção
|
|
82
86
|
|
|
83
87
|
[Defina sequência de implementação:
|
|
@@ -23,6 +23,7 @@ export const DANGEROUS = [
|
|
|
23
23
|
{ re: /\bgit\s+reset\b[^\n|&;]*--hard\b/, why: 'hard reset discards uncommitted work and rewrites the branch' },
|
|
24
24
|
{ re: /\bgit\s+clean\b[^\n|&;]*-[a-z]*f/, why: 'git clean -f permanently deletes untracked files' },
|
|
25
25
|
{ re: /\bgit\s+branch\b[^\n|&;]*\s-D\b/, why: 'force-deletes a branch that may be unmerged' },
|
|
26
|
+
{ re: /\bgit\s+worktree\s+remove\b[^\n|&;]*(--force\b|\s-f\b)/, why: 'force-removes a worktree that may hold uncommitted work — commit first or use /dw-worktree clean (never --force)' },
|
|
26
27
|
{ re: /\bgit\s+checkout\b[^\n|&;]*\s(--\s+\.|\.\s*$)/, why: 'discards all local changes in the working tree' },
|
|
27
28
|
{ re: /\bgit\s+restore\b[^\n|&;]*\s(--\s+)?\.(?=\s*(?:$|[|&;]))/, why: 'discards all local changes in the working tree' },
|
|
28
29
|
];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const tools = new Set(['local', 'codex', 'claude', 'copilot']);
|
|
6
|
+
const tiers = new Set(['light', 'standard', 'heavy']);
|
|
7
|
+
|
|
8
|
+
// A small executable contract for the agent-authored execution-plan.json.
|
|
9
|
+
// This validates assignments, not account access or authorization on its own.
|
|
10
|
+
export function validatePlan(plan) {
|
|
11
|
+
const issues = [];
|
|
12
|
+
if (!plan || !['1.0', '1.1'].includes(plan.schema_version)) return ['Unsupported execution plan schema'];
|
|
13
|
+
if (!Array.isArray(plan.tasks) || !plan.tasks.length) return ['tasks must be a nonempty array'];
|
|
14
|
+
if (typeof plan.approved !== 'boolean') issues.push('approved must be a boolean');
|
|
15
|
+
const ids = new Set();
|
|
16
|
+
for (const task of plan.tasks) {
|
|
17
|
+
if (!task || typeof task.id !== 'string' || !task.id.trim()) {
|
|
18
|
+
issues.push('Every task needs a nonempty string id');
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (ids.has(task.id)) issues.push(`Duplicate task ${task.id}`);
|
|
22
|
+
ids.add(task.id);
|
|
23
|
+
if (!Array.isArray(task.depends_on) || task.depends_on.some(id => typeof id !== 'string')) issues.push(`${task.id}: depends_on must be a string array`);
|
|
24
|
+
if (plan.schema_version === '1.1' && !task.execution) issues.push(`${task.id}: missing execution assignment`);
|
|
25
|
+
if (task.execution) {
|
|
26
|
+
const e = task.execution;
|
|
27
|
+
if (typeof e !== 'object' || Array.isArray(e)) { issues.push(`${task.id}: execution must be an object`); continue; }
|
|
28
|
+
if (!tiers.has(e.complexity)) issues.push(`${task.id}: invalid complexity`);
|
|
29
|
+
if (typeof e.rationale !== 'string' || !e.rationale.trim()) issues.push(`${task.id}: missing rationale`);
|
|
30
|
+
if (!Array.isArray(e.agents) || e.agents.some(a => typeof a !== 'string')) issues.push(`${task.id}: agents must be a string array`);
|
|
31
|
+
for (const assignment of [e, ...(Array.isArray(e.fallbacks) ? e.fallbacks : [])]) {
|
|
32
|
+
if (!assignment || typeof assignment !== 'object' || Array.isArray(assignment)) { issues.push(`${task.id}: invalid fallback assignment`); continue; }
|
|
33
|
+
if (!tools.has(assignment.tool)) issues.push(`${task.id}: invalid tool`);
|
|
34
|
+
if (typeof assignment.model !== 'string' || !assignment.model.trim()) issues.push(`${task.id}: missing model`);
|
|
35
|
+
if (typeof assignment.effort !== 'string' || !assignment.effort.trim()) issues.push(`${task.id}: missing effort`);
|
|
36
|
+
if (assignment.tool !== 'local' && [assignment.model, assignment.effort].includes('inherit')) issues.push(`${task.id}: external assignments must resolve model and effort`);
|
|
37
|
+
}
|
|
38
|
+
if (e.fallbacks !== undefined && !Array.isArray(e.fallbacks)) issues.push(`${task.id}: fallbacks must be an array`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const tasks = new Map(plan.tasks.filter(t => t?.id).map(t => [t.id, t]));
|
|
42
|
+
const visiting = new Set(), visited = new Set();
|
|
43
|
+
function visit(id) {
|
|
44
|
+
if (visiting.has(id)) { issues.push(`Dependency cycle at ${id}`); return; }
|
|
45
|
+
if (visited.has(id)) return;
|
|
46
|
+
visiting.add(id);
|
|
47
|
+
for (const dep of tasks.get(id)?.depends_on || []) {
|
|
48
|
+
if (!ids.has(dep)) issues.push(`${id}: unknown dependency ${dep}`);
|
|
49
|
+
else visit(dep);
|
|
50
|
+
}
|
|
51
|
+
visiting.delete(id); visited.add(id);
|
|
52
|
+
}
|
|
53
|
+
if (!issues.length) for (const id of ids) visit(id);
|
|
54
|
+
return issues;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function resolveAssignment(plan, taskId, availableTools) {
|
|
58
|
+
const issues = validatePlan(plan);
|
|
59
|
+
if (issues.length) throw new Error(issues.join('; '));
|
|
60
|
+
if (plan.approved !== true) throw new Error('Execution plan is not approved');
|
|
61
|
+
const task = plan.tasks.find(t => t.id === taskId);
|
|
62
|
+
if (!task) throw new Error(`Unknown task ${taskId}`);
|
|
63
|
+
// Legacy plans never imply permission to start another CLI.
|
|
64
|
+
const assignment = task.execution || { tool: 'local', model: 'inherit', effort: 'inherit', agents: [] };
|
|
65
|
+
const candidates = [assignment, ...(assignment.fallbacks || [])];
|
|
66
|
+
const chosen = candidates.find(c => availableTools.includes(c.tool));
|
|
67
|
+
if (!chosen) throw new Error(`No approved executor available for ${taskId}`);
|
|
68
|
+
return { ...chosen, agents: assignment.agents || [], fallback: chosen !== assignment };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function readyTasks(plan, completedIds) {
|
|
72
|
+
const issues = validatePlan(plan);
|
|
73
|
+
if (issues.length) throw new Error(issues.join('; '));
|
|
74
|
+
const done = new Set(completedIds);
|
|
75
|
+
return plan.tasks.filter(t => !done.has(t.id) && t.depends_on.every(id => done.has(id))).map(t => t.id);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Callers fingerprint actual inputs (including relevant untracked files) and
|
|
79
|
+
// environment. Unknown values fail closed. Time/message boundaries are irrelevant.
|
|
80
|
+
export function reusableEvidence(evidence, current) {
|
|
81
|
+
if (!evidence || evidence.exit_code !== 0 || !current) return false;
|
|
82
|
+
for (const key of ['command', 'input_fingerprint', 'environment_fingerprint']) {
|
|
83
|
+
if (typeof current[key] !== 'string' || !current[key] || evidence[key] !== current[key]) return false;
|
|
84
|
+
}
|
|
85
|
+
return Array.isArray(current.scope) && current.scope.length > 0 && Array.isArray(evidence.scope)
|
|
86
|
+
&& current.scope.every(item => evidence.scope.includes(item));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
90
|
+
try {
|
|
91
|
+
const [mode, file, taskId, available = 'local'] = process.argv.slice(2);
|
|
92
|
+
if (!['validate', 'resolve', 'ready'].includes(mode) || !file) throw new Error('Usage: workflow-contract.mjs validate|resolve|ready <plan.json> [task-id|completed-csv] [available-tools-csv]');
|
|
93
|
+
const plan = JSON.parse(readFileSync(file, 'utf8'));
|
|
94
|
+
if (mode === 'validate') {
|
|
95
|
+
const issues = validatePlan(plan);
|
|
96
|
+
console.log(JSON.stringify({ status: issues.length ? 'BLOCKED' : 'PASS', issues }));
|
|
97
|
+
if (issues.length) process.exitCode = 1;
|
|
98
|
+
} else if (mode === 'resolve') console.log(JSON.stringify(resolveAssignment(plan, taskId, available.split(','))));
|
|
99
|
+
else console.log(JSON.stringify(readyTasks(plan, taskId ? taskId.split(',') : [])));
|
|
100
|
+
} catch (error) { console.error(error.message); process.exitCode = 1; }
|
|
101
|
+
}
|