oxe-cc 0.9.2 → 1.0.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/.cursor/commands/oxe-retro.md +2 -2
- package/.cursor/commands/oxe-spec.md +2 -2
- package/.github/prompts/oxe-retro.prompt.md +2 -2
- package/.github/prompts/oxe-spec.prompt.md +2 -2
- package/README.md +1 -1
- package/bin/banner.txt +1 -1
- package/bin/lib/oxe-context-engine.cjs +1 -0
- package/bin/lib/oxe-dashboard.cjs +9 -7
- package/bin/lib/oxe-operational.cjs +569 -4
- package/bin/oxe-cc.js +141 -57
- package/commands/oxe/retro.md +2 -2
- package/commands/oxe/spec.md +2 -2
- package/lib/runtime/compiler/graph-compiler.d.ts +83 -0
- package/lib/runtime/compiler/graph-compiler.js +135 -0
- package/lib/runtime/compiler/index.d.ts +1 -0
- package/lib/runtime/compiler/index.js +17 -0
- package/lib/runtime/context/context-pack-builder.d.ts +36 -0
- package/lib/runtime/context/context-pack-builder.js +136 -0
- package/lib/runtime/context/index.d.ts +1 -0
- package/lib/runtime/context/index.js +17 -0
- package/lib/runtime/delivery/branch-manager.d.ts +19 -0
- package/lib/runtime/delivery/branch-manager.js +78 -0
- package/lib/runtime/delivery/ci-checks.d.ts +34 -0
- package/lib/runtime/delivery/ci-checks.js +209 -0
- package/lib/runtime/delivery/index.d.ts +3 -0
- package/lib/runtime/delivery/index.js +19 -0
- package/lib/runtime/delivery/pr-manager.d.ts +30 -0
- package/lib/runtime/delivery/pr-manager.js +82 -0
- package/lib/runtime/events/bus.d.ts +9 -0
- package/lib/runtime/events/bus.js +63 -0
- package/lib/runtime/events/catalog.d.ts +3 -0
- package/lib/runtime/events/catalog.js +30 -0
- package/lib/runtime/events/envelope.d.ts +13 -0
- package/lib/runtime/events/envelope.js +2 -0
- package/lib/runtime/events/index.d.ts +3 -0
- package/lib/runtime/events/index.js +19 -0
- package/lib/runtime/evidence/evidence-store.d.ts +22 -0
- package/lib/runtime/evidence/evidence-store.js +106 -0
- package/lib/runtime/evidence/index.d.ts +1 -0
- package/lib/runtime/evidence/index.js +17 -0
- package/lib/runtime/gate/gate-manager.d.ts +39 -0
- package/lib/runtime/gate/gate-manager.js +104 -0
- package/lib/runtime/gate/index.d.ts +1 -0
- package/lib/runtime/gate/index.js +17 -0
- package/lib/runtime/index.d.ts +16 -0
- package/lib/runtime/index.js +40 -0
- package/lib/runtime/models/attempt.d.ts +12 -0
- package/lib/runtime/models/attempt.js +2 -0
- package/lib/runtime/models/evidence.d.ts +9 -0
- package/lib/runtime/models/evidence.js +2 -0
- package/lib/runtime/models/gate-decision.d.ts +10 -0
- package/lib/runtime/models/gate-decision.js +2 -0
- package/lib/runtime/models/index.d.ts +8 -0
- package/lib/runtime/models/index.js +24 -0
- package/lib/runtime/models/run.d.ts +13 -0
- package/lib/runtime/models/run.js +2 -0
- package/lib/runtime/models/session.d.ts +10 -0
- package/lib/runtime/models/session.js +2 -0
- package/lib/runtime/models/verification-result.d.ts +9 -0
- package/lib/runtime/models/verification-result.js +2 -0
- package/lib/runtime/models/work-item.d.ts +15 -0
- package/lib/runtime/models/work-item.js +2 -0
- package/lib/runtime/models/workspace.d.ts +25 -0
- package/lib/runtime/models/workspace.js +2 -0
- package/lib/runtime/plugins/index.d.ts +2 -0
- package/lib/runtime/plugins/index.js +18 -0
- package/lib/runtime/plugins/plugin-abi.d.ts +76 -0
- package/lib/runtime/plugins/plugin-abi.js +2 -0
- package/lib/runtime/plugins/plugin-registry.d.ts +21 -0
- package/lib/runtime/plugins/plugin-registry.js +114 -0
- package/lib/runtime/policy/index.d.ts +1 -0
- package/lib/runtime/policy/index.js +17 -0
- package/lib/runtime/policy/policy-engine.d.ts +40 -0
- package/lib/runtime/policy/policy-engine.js +80 -0
- package/lib/runtime/projection/index.d.ts +1 -0
- package/lib/runtime/projection/index.js +17 -0
- package/lib/runtime/projection/projection-engine.d.ts +11 -0
- package/lib/runtime/projection/projection-engine.js +218 -0
- package/lib/runtime/reducers/debug-reducer.d.ts +10 -0
- package/lib/runtime/reducers/debug-reducer.js +30 -0
- package/lib/runtime/reducers/index.d.ts +2 -0
- package/lib/runtime/reducers/index.js +18 -0
- package/lib/runtime/reducers/run-state-reducer.d.ts +20 -0
- package/lib/runtime/reducers/run-state-reducer.js +110 -0
- package/lib/runtime/scheduler/index.d.ts +1 -0
- package/lib/runtime/scheduler/index.js +17 -0
- package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +34 -0
- package/lib/runtime/scheduler/multi-agent-coordinator.js +166 -0
- package/lib/runtime/scheduler/scheduler.d.ts +39 -0
- package/lib/runtime/scheduler/scheduler.js +196 -0
- package/lib/runtime/verification/index.d.ts +1 -0
- package/lib/runtime/verification/index.js +17 -0
- package/lib/runtime/verification/verification-compiler.d.ts +56 -0
- package/lib/runtime/verification/verification-compiler.js +147 -0
- package/lib/runtime/workspace/index.d.ts +5 -0
- package/lib/runtime/workspace/index.js +24 -0
- package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +22 -0
- package/lib/runtime/workspace/strategies/ephemeral-container.js +109 -0
- package/lib/runtime/workspace/strategies/git-worktree.d.ts +12 -0
- package/lib/runtime/workspace/strategies/git-worktree.js +79 -0
- package/lib/runtime/workspace/strategies/inplace.d.ts +10 -0
- package/lib/runtime/workspace/strategies/inplace.js +37 -0
- package/lib/runtime/workspace/workspace-manager.d.ts +13 -0
- package/lib/runtime/workspace/workspace-manager.js +2 -0
- package/lib/sdk/index.cjs +24 -7
- package/lib/sdk/index.d.ts +17 -7
- package/oxe/templates/LESSONS-METRICS.template.json +13 -0
- package/oxe/workflows/references/robustness-elevation.md +295 -0
- package/oxe/workflows/references/workflow-runtime-contracts.json +32 -4
- package/oxe/workflows/retro.md +21 -0
- package/oxe/workflows/spec.md +50 -26
- package/oxe/workflows/verify.md +36 -0
- package/package.json +9 -3
- package/packages/runtime/package.json +17 -0
- package/packages/runtime/src/compiler/graph-compiler.ts +245 -0
- package/packages/runtime/src/compiler/index.ts +1 -0
- package/packages/runtime/src/context/context-pack-builder.ts +193 -0
- package/packages/runtime/src/context/index.ts +1 -0
- package/packages/runtime/src/delivery/branch-manager.ts +84 -0
- package/packages/runtime/src/delivery/ci-checks.ts +252 -0
- package/packages/runtime/src/delivery/index.ts +3 -0
- package/packages/runtime/src/delivery/pr-manager.ts +112 -0
- package/packages/runtime/src/events/bus.ts +92 -0
- package/packages/runtime/src/events/catalog.ts +29 -0
- package/packages/runtime/src/events/envelope.ts +14 -0
- package/packages/runtime/src/events/index.ts +3 -0
- package/packages/runtime/src/evidence/evidence-store.ts +130 -0
- package/packages/runtime/src/evidence/index.ts +1 -0
- package/packages/runtime/src/gate/gate-manager.ts +137 -0
- package/packages/runtime/src/gate/index.ts +1 -0
- package/packages/runtime/src/index.ts +32 -0
- package/packages/runtime/src/models/attempt.ts +19 -0
- package/packages/runtime/src/models/evidence.ts +21 -0
- package/packages/runtime/src/models/gate-decision.ts +21 -0
- package/packages/runtime/src/models/index.ts +8 -0
- package/packages/runtime/src/models/run.ts +24 -0
- package/packages/runtime/src/models/session.ts +11 -0
- package/packages/runtime/src/models/verification-result.ts +10 -0
- package/packages/runtime/src/models/work-item.ts +25 -0
- package/packages/runtime/src/models/workspace.ts +28 -0
- package/packages/runtime/src/plugins/index.ts +2 -0
- package/packages/runtime/src/plugins/plugin-abi.ts +95 -0
- package/packages/runtime/src/plugins/plugin-registry.ts +119 -0
- package/packages/runtime/src/policy/index.ts +1 -0
- package/packages/runtime/src/policy/policy-engine.ts +113 -0
- package/packages/runtime/src/projection/index.ts +1 -0
- package/packages/runtime/src/projection/projection-engine.ts +249 -0
- package/packages/runtime/src/reducers/debug-reducer.ts +36 -0
- package/packages/runtime/src/reducers/index.ts +2 -0
- package/packages/runtime/src/reducers/run-state-reducer.ts +127 -0
- package/packages/runtime/src/scheduler/index.ts +1 -0
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +231 -0
- package/packages/runtime/src/scheduler/scheduler.ts +281 -0
- package/packages/runtime/src/verification/index.ts +1 -0
- package/packages/runtime/src/verification/verification-compiler.ts +225 -0
- package/packages/runtime/src/workspace/index.ts +5 -0
- package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +121 -0
- package/packages/runtime/src/workspace/strategies/git-worktree.ts +77 -0
- package/packages/runtime/src/workspace/strategies/inplace.ts +35 -0
- package/packages/runtime/src/workspace/workspace-manager.ts +15 -0
- package/packages/runtime/tsconfig.json +17 -0
- package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
- package/vscode-extension/package.json +1 -1
package/oxe/workflows/spec.md
CHANGED
|
@@ -13,10 +13,10 @@ Para trabalho **muito pequeno** que não justifica spec completa: redirecionar p
|
|
|
13
13
|
Se **`.oxe/config.json`** tiver `discuss_before_plan: true`: mencionar no final da Fase 5 que o próximo passo é **`oxe:discuss`** antes do plano.
|
|
14
14
|
</objective>
|
|
15
15
|
|
|
16
|
-
<context>
|
|
17
|
-
**Contrato de raciocínio:** aplicar `oxe/workflows/references/reasoning-discovery.md`. Antes de perguntar, explorar o que o repo e os artefatos já respondem; separar fatos, inferências e lacunas.
|
|
18
|
-
|
|
19
|
-
**Pré-requisito preferível:** scan executado. Se não existir, mencionar na spec que o mapa está pendente.
|
|
16
|
+
<context>
|
|
17
|
+
**Contrato de raciocínio:** aplicar `oxe/workflows/references/reasoning-discovery.md`. Antes de perguntar, explorar o que o repo e os artefatos já respondem; separar fatos, inferências e lacunas.
|
|
18
|
+
|
|
19
|
+
**Pré-requisito preferível:** scan executado. Se não existir, mencionar na spec que o mapa está pendente.
|
|
20
20
|
|
|
21
21
|
**Contrato de robustez:** seguir `oxe/workflows/references/flow-robustness-contract.md`. Antes de escrever, resolver artefatos obrigatórios, validar pré-condições e só então produzir a spec. O output desta fase deve deixar evidência estruturada suficiente para o `plan` decidir se o plano é realmente o melhor disponível.
|
|
22
22
|
|
|
@@ -34,8 +34,8 @@ Ler no início:
|
|
|
34
34
|
- `.oxe/codebase/OVERVIEW.md` e `STACK.md` se existirem — não contradizer o repo
|
|
35
35
|
- **OBS do escopo ativo** — se houver entradas `pendente` com impacto `spec` ou `all`, incorporá-las na Fase 3 (Requisitos) e marcá-las `incorporada → spec (data)` após uso
|
|
36
36
|
- **`.oxe/global/LESSONS.md`** — se existir, ler entradas com `Aplicar em: spec` e status `ativo`. **Priorizar entradas com `Frequência >= 2` ou `Impacto: alto`** — aplicar como restrições explícitas. Entradas com `Frequência: 1` e `Impacto: baixo` são contexto secundário. Usar durante a Fase 1 (perguntas) e Fase 3 (requisitos). Exemplo: se uma lição diz "perguntar explicitamente sobre integração com X", adicionar essa pergunta no Bloco B da Fase 1.
|
|
37
|
-
- `.oxe/CAPABILITIES.md` e `.oxe/INVESTIGATIONS.md` — usar para sugerir capacidades e pesquisas já existentes antes de abrir novas lacunas
|
|
38
|
-
- Se o problema tocar Azure, ler `.oxe/cloud/azure/profile.json`, `auth-status.json` e `INVENTORY.md` antes de fechar requisitos; se o inventário estiver ausente ou stale, exigir discovery via `oxe-cc azure sync` antes de consolidar a spec
|
|
37
|
+
- `.oxe/CAPABILITIES.md` e `.oxe/INVESTIGATIONS.md` — usar para sugerir capacidades e pesquisas já existentes antes de abrir novas lacunas
|
|
38
|
+
- Se o problema tocar Azure, ler `.oxe/cloud/azure/profile.json`, `auth-status.json` e `INVENTORY.md` antes de fechar requisitos; se o inventário estiver ausente ou stale, exigir discovery via `oxe-cc azure sync` antes de consolidar a spec
|
|
39
39
|
|
|
40
40
|
**Brownfield (COBOL, JCL, copybooks, VB6, SP):** quando o objetivo for documentar ou planear migração, ver **`oxe/workflows/references/legacy-brownfield.md`** — épicos por trilha, critérios A* verificáveis por Grep/leitura/checklist.
|
|
41
41
|
|
|
@@ -88,9 +88,9 @@ Usar templates: **`oxe/templates/SPEC.template.md`** e **`oxe/templates/ROADMAP.
|
|
|
88
88
|
|
|
89
89
|
**Objetivo:** investigar domínios incertos antes de escrever requisitos.
|
|
90
90
|
|
|
91
|
-
**Proposta ao usuário:** com base na Fase 1, listar 2-4 áreas de investigação sugeridas e perguntar quais investigar. Exemplos:
|
|
92
|
-
- "Há 3 áreas com incerteza técnica: autenticação JWT, integração com Stripe, e deploy em edge. Quer investigar alguma antes de avançar para requisitos?"
|
|
93
|
-
- "A trilha depende de Azure e o inventário está incompleto. Quer sincronizar recursos reais antes de congelar os requisitos?"
|
|
91
|
+
**Proposta ao usuário:** com base na Fase 1, listar 2-4 áreas de investigação sugeridas e perguntar quais investigar. Exemplos:
|
|
92
|
+
- "Há 3 áreas com incerteza técnica: autenticação JWT, integração com Stripe, e deploy em edge. Quer investigar alguma antes de avançar para requisitos?"
|
|
93
|
+
- "A trilha depende de Azure e o inventário está incompleto. Quer sincronizar recursos reais antes de congelar os requisitos?"
|
|
94
94
|
|
|
95
95
|
**Se aprovado:**
|
|
96
96
|
- Criar notas de pesquisa datadas em `research/YYYY-MM-DD-<slug>.md` no escopo ativo (usar fluxo de `research.md`)
|
|
@@ -127,6 +127,27 @@ Usar templates: **`oxe/templates/SPEC.template.md`** e **`oxe/templates/ROADMAP.
|
|
|
127
127
|
**Apresentar ao usuário para validação** antes de avançar para Fase 4. Se ajustar: atualizar tabela e repetir até aprovação.
|
|
128
128
|
</fase_3_requisitos>
|
|
129
129
|
|
|
130
|
+
<fase_35_elevacao_robustez>
|
|
131
|
+
## Fase 3.5 — Elevação de Robustez (automática)
|
|
132
|
+
|
|
133
|
+
**Objetivo:** propor proativamente critérios de hardening baseados no stack detectado, antes de criar o roteiro. Garante que segurança e robustez entrem na spec — e portanto no plan, nos testes e no verify — em vez de ficarem como auditoria pós-hoc.
|
|
134
|
+
|
|
135
|
+
**Referência:** `oxe/workflows/references/robustness-elevation.md`
|
|
136
|
+
|
|
137
|
+
**Execução:**
|
|
138
|
+
|
|
139
|
+
1. **Detectar domínios** presentes: AUTH, API, DB, FRONTEND, FILE — conforme tabela de detecção do arquivo de referência.
|
|
140
|
+
2. **Para cada domínio detectado**, percorrer o checklist correspondente e filtrar critérios já cobertos por A* existentes.
|
|
141
|
+
3. **Propor** os critérios restantes como R-RB-NN com prioridade sugerida (v1 / v2 / fora).
|
|
142
|
+
4. **Apresentar ao usuário** em bloco único — domínios detectados, critérios propostos com justificativa breve para v1 críticos.
|
|
143
|
+
5. **Aguardar decisão** — usuário confirma, ajusta versão ou descarta cada critério.
|
|
144
|
+
6. **Incorporar aprovados** na tabela da Fase 3; registrar descartados com justificativa na seção "Suposições e riscos" da SPEC.
|
|
145
|
+
|
|
146
|
+
**Regra:** nunca forçar inclusão. Se o usuário descartar um v1, registrar o motivo explicitamente.
|
|
147
|
+
|
|
148
|
+
**Pulável apenas se:** stack não se encaixa em nenhum domínio detectável (ex.: script CLI puro sem auth, sem HTTP, sem DB).
|
|
149
|
+
</fase_35_elevacao_robustez>
|
|
150
|
+
|
|
130
151
|
<fase_4_roteiro>
|
|
131
152
|
## Fase 4 — Roteiro
|
|
132
153
|
|
|
@@ -178,6 +199,7 @@ Percorrer esta lista de verificação:
|
|
|
178
199
|
| 4 | **Conflito com stack:** algum requisito v1 pressupõe tecnologia ou capacidade que `STACK.md` indica ausente? (ex.: requer WebSocket mas stack usa REST puro) | Marcar como suposição explícita ou remover |
|
|
179
200
|
| 5 | **Critérios vagos:** algum A* usa linguagem não-mensurável ("deve ser rápido", "interface amigável") sem métrica? | Refinar: "resposta < 200ms p95", "WCAG 2.1 AA" |
|
|
180
201
|
| 6 | **Dependências implícitas:** algum requisito v1 pressupõe que outro requisito (v2 ou fora) já esteja implementado? | Tornar dependência explícita ou reordenar versioning |
|
|
202
|
+
| 7 | **Elevação de robustez:** todos os domínios detectados (AUTH, API, DB, FRONTEND, FILE) tiveram R-RB-NN propostos ou explicitamente descartados com justificativa? | Se Fase 3.5 foi pulada sem justificativa, executar agora ou registrar como risco em "Suposições e riscos" |
|
|
181
203
|
|
|
182
204
|
**Resultado obrigatório antes de avançar:**
|
|
183
205
|
- **0 problemas** → avançar para Fase 5 normalmente.
|
|
@@ -222,23 +244,24 @@ O resultado desta reflexão é **invisível ao usuário** — é trabalho intern
|
|
|
222
244
|
- Atualizar `STATE.md`: `phase: spec_ready`, próximo passo conforme escolha
|
|
223
245
|
</fase_5_aprovacao>
|
|
224
246
|
|
|
225
|
-
<process>
|
|
226
|
-
1. Ler `.oxe/STATE.md`, `OVERVIEW.md`, `STACK.md` e `OBSERVATIONS.md` do escopo ativo (verificar pendentes).
|
|
227
|
-
2. Fazer uma exploração inicial do repo e dos artefatos antes da primeira rodada de perguntas. Consolidar internamente: fatos confirmados, inferências e lacunas.
|
|
228
|
-
3. Aplicar `adaptive-discovery.md`: classificar a demanda, verificar se há capabilities úteis e se investigações anteriores reduzem incerteza.
|
|
229
|
-
4. **Fase 1 — Perguntas:** enviar bloco coeso de 3-5 perguntas; máx 3 rodadas; confirmar entendimento.
|
|
230
|
-
5. **Fase 2 — Pesquisa:** propor áreas de investigação; aguardar aprovação; executar se aprovado.
|
|
231
|
-
6. **Fase 3 — Requisitos:** extrair tabela R-ID com v1/v2/fora e critérios A*; incorporar OBS pendentes; apresentar para validação.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
-
|
|
236
|
-
-
|
|
237
|
-
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
247
|
+
<process>
|
|
248
|
+
1. Ler `.oxe/STATE.md`, `OVERVIEW.md`, `STACK.md` e `OBSERVATIONS.md` do escopo ativo (verificar pendentes).
|
|
249
|
+
2. Fazer uma exploração inicial do repo e dos artefatos antes da primeira rodada de perguntas. Consolidar internamente: fatos confirmados, inferências e lacunas.
|
|
250
|
+
3. Aplicar `adaptive-discovery.md`: classificar a demanda, verificar se há capabilities úteis e se investigações anteriores reduzem incerteza.
|
|
251
|
+
4. **Fase 1 — Perguntas:** enviar bloco coeso de 3-5 perguntas; máx 3 rodadas; confirmar entendimento.
|
|
252
|
+
5. **Fase 2 — Pesquisa:** propor áreas de investigação; aguardar aprovação; executar se aprovado.
|
|
253
|
+
6. **Fase 3 — Requisitos:** extrair tabela R-ID com v1/v2/fora e critérios A*; incorporar OBS pendentes; apresentar para validação.
|
|
254
|
+
6.5. **Fase 3.5 — Elevação de Robustez:** detectar domínios (AUTH/API/DB/FRONTEND/FILE); propor R-RB-NN não cobertos; aguardar decisão; incorporar aprovados na tabela antes de avançar.
|
|
255
|
+
7. **Fase 4 — Roteiro:** agrupar requisitos v1 em fases (incluindo R-RB aprovados); escrever `ROADMAP.md` no escopo ativo.
|
|
256
|
+
8. Escrever **`SPEC.md`** usando `oxe/templates/SPEC.template.md` no escopo ativo:
|
|
257
|
+
- Frontmatter YAML (`oxe_doc: spec`, `status`, `updated`, `inputs`)
|
|
258
|
+
- Objetivo, Escopo (dentro/fora), Critérios de aceite (tabela A*), Suposições e riscos, Referências
|
|
259
|
+
- Preencher explicitamente `Tipo de demanda` e `Incertezas estruturadas`
|
|
260
|
+
- Preservar chaves existentes se SPEC.md já existir; atualizar `updated:`
|
|
261
|
+
8b. **Auto-reflexão:** executar integralmente o bloco `<auto_reflexao>` antes de avançar. Corrigir a spec conforme necessário. Não apresentar a lista de verificação ao usuário — apenas a spec corrigida.
|
|
262
|
+
9. **Fase 5 — Aprovação:** apresentar resumo, aguardar aprovação do roteiro, redirecionar.
|
|
263
|
+
10. Atualizar **`.oxe/STATE.md`** global: `phase: spec_ready`, próximo passo e referência curta à sessão ativa quando existir.
|
|
264
|
+
11. Marcar OBS incorporadas em `OBSERVATIONS.md` do escopo ativo se houver pendentes de impacto `spec`.
|
|
242
265
|
</process>
|
|
243
266
|
|
|
244
267
|
<success_criteria>
|
|
@@ -248,4 +271,5 @@ O resultado desta reflexão é **invisível ao usuário** — é trabalho intern
|
|
|
248
271
|
- [ ] Usuário foi consultado no gate da Fase 5 e escolheu o próximo passo.
|
|
249
272
|
- [ ] OBS pendentes com impacto `spec` foram incorporadas e marcadas `incorporada`.
|
|
250
273
|
- [ ] Máximo 3 rodadas de perguntas utilizadas — não mais.
|
|
274
|
+
- [ ] Fase 3.5 executada: domínios detectados tiveram R-RB-NN propostos, aprovados ou descartados com justificativa.
|
|
251
275
|
</success_criteria>
|
package/oxe/workflows/verify.md
CHANGED
|
@@ -31,6 +31,7 @@ Se o usuário indicar uma tarefa (ex.: `T2`), focar só nela nas camadas 1–2;
|
|
|
31
31
|
- **UI:** se existirem `UI-SPEC.md` / `UI-REVIEW.md` no escopo resolvido, incorporar na evidência quando os critérios **A*** ou tarefas **Tn** tocarem interface.
|
|
32
32
|
- **Camada 5 — Validate-gaps (automático quando `verification_depth: "thorough"`):** após as 4 camadas, se `verification_depth: "thorough"` em `.oxe/config.json`, executar automaticamente a lógica de `oxe/workflows/validate-gaps.md` e produzir `.oxe/VALIDATION-GAPS.md` como parte deste verify. Não requer comando separado.
|
|
33
33
|
- **Camada 6 — Security (automático quando `security_in_verify: true`):** se `security_in_verify: true` em `.oxe/config.json`, executar automaticamente a lógica de `oxe/workflows/security.md` e produzir `.oxe/SECURITY.md` como parte deste verify. Não requer comando separado.
|
|
34
|
+
- **Camada QC — Quality Contract (automático quando SPEC.md contiver critérios R-RB):** se a SPEC.md do escopo resolvido contiver requisitos com ID `R-RB-NN` (gerados pela Fase 3.5 — Elevação de Robustez), executar a Camada QC conforme `<camada_qc_quality_contract>`. Não requer comando separado.
|
|
34
35
|
- **Rotina compact/checkpoint (opcional):** se esta entrega alterou **estrutura**, **stack** ou **pastas** de forma relevante, `/oxe-scan` em modo refresh alinha `.oxe/codebase/` ao repo. Após **verify** com sucesso, `/oxe-project checkpoint` com slug curto pode marcar estado estável.
|
|
35
36
|
</context>
|
|
36
37
|
|
|
@@ -103,6 +104,39 @@ Registrar em `VERIFY.md`: `Resultado de calibração | Confiança declarada | Re
|
|
|
103
104
|
4. Usar esses artefatos como apoio para a seção de gaps e para a calibração do plano.
|
|
104
105
|
</runtime_e_checkpoints>
|
|
105
106
|
|
|
107
|
+
<camada_qc_quality_contract>
|
|
108
|
+
**Camada QC — Contrato de Qualidade** (ativa quando SPEC.md contiver requisitos R-RB da Fase 3.5)
|
|
109
|
+
|
|
110
|
+
**Objetivo:** verificar que os critérios de qualidade comprometidos na spec (R-RB aprovados como v1) foram efetivamente implementados — com o mesmo rigor de evidência aplicado aos critérios A*.
|
|
111
|
+
|
|
112
|
+
**Execução:**
|
|
113
|
+
|
|
114
|
+
1. Ler SPEC.md procurando requisitos com ID `R-RB-NN` e versão `v1` na tabela de requisitos.
|
|
115
|
+
2. Localizar o **Accepted Risk Registry** da SPEC (seção "Suposições e riscos" ou "Riscos Aceitos") — anotar itens R-RB declinados.
|
|
116
|
+
3. Para cada R-RB aprovado como v1, verificar implementação com evidência (Grep, Read, teste):
|
|
117
|
+
|
|
118
|
+
| ID R-RB | Critério (resumo) | Tier | Evidência | Implementado? |
|
|
119
|
+
|---------|-------------------|------|-----------|---------------|
|
|
120
|
+
| RB-SEC-A1 | Bcrypt salt≥10 | Piso | `grep bcrypt src/` → linha X | ✓ / ✗ |
|
|
121
|
+
|
|
122
|
+
4. Calcular **Quality Score realizado:**
|
|
123
|
+
```
|
|
124
|
+
QS_realizado = (Piso_implementados / Piso_aprovados × 60) + (Base_implementados / Base_aprovados × 40)
|
|
125
|
+
```
|
|
126
|
+
5. Comparar com Quality Score comprometido na spec (se registrado).
|
|
127
|
+
6. Registrar na seção **Contrato de Qualidade** do VERIFY.md:
|
|
128
|
+
- Tabela de critérios R-RB (acima)
|
|
129
|
+
- Quality Score comprometido vs realizado
|
|
130
|
+
- Gap: itens aprovados como v1 mas não implementados
|
|
131
|
+
|
|
132
|
+
**Severidade dos gaps:**
|
|
133
|
+
- R-RB **Piso** não implementado → gap P0 → bloqueia `verify_complete` (mesma regra do security P0)
|
|
134
|
+
- R-RB **Base** não implementado → gap P1 → registrar, não bloqueia
|
|
135
|
+
- R-RB **Excelência** não implementado → informativo (estava em v2, não esperado)
|
|
136
|
+
|
|
137
|
+
**Pulável apenas se:** SPEC.md não contiver nenhum R-RB-NN com versão v1.
|
|
138
|
+
</camada_qc_quality_contract>
|
|
139
|
+
|
|
106
140
|
<process>
|
|
107
141
|
1. **Camada 1 — Auditoria de pré-execução:** checar integridade do PLAN.md e DISCUSS.md conforme `<camada_1_pre_exec_audit>`. Documentar resultado.
|
|
108
142
|
2. Resolver o context pack `verify` primeiro:
|
|
@@ -142,6 +176,7 @@ O `calibration_error` de cada dimensão = `|score declarado - resultado observad
|
|
|
142
176
|
8b. **Retrospectiva (pós-verify):** se `verify_complete`, sugerir **`/oxe-retro`** para capturar aprendizados do ciclo em `.oxe/LESSONS.md`. Especialmente importante quando: houve replanejamento (`--replan`), houve falhas em execute que precisaram de debug, critérios A* foram ajustados durante o ciclo, ou o ciclo durou mais de 2 ondas. Retro antes do próximo spec garante que lições orientem o próximo ciclo.
|
|
143
177
|
8c. **Camada 5 — Validate-gaps automático:** se `verification_depth: "thorough"` em `.oxe/config.json`, executar a lógica de `oxe/workflows/validate-gaps.md` e adicionar seção **Gaps de Cobertura** ao VERIFY.md (mesmo conteúdo de VALIDATION-GAPS.md). Também escrever `.oxe/VALIDATION-GAPS.md` separado.
|
|
144
178
|
8d. **Camada 6 — Security automático:** se `security_in_verify: true` em `.oxe/config.json`, executar a lógica de `oxe/workflows/security.md` e adicionar seção **Auditoria de Segurança** ao VERIFY.md. Também escrever `.oxe/SECURITY.md` separado. Achados P0 bloqueiam o `verify_complete` — registrar `verify_failed` até P0s serem resolvidos.
|
|
179
|
+
8e. **Camada QC — Quality Contract automático:** se SPEC.md contiver requisitos `R-RB-NN` com versão `v1`, executar o bloco `<camada_qc_quality_contract>` e adicionar seção **Contrato de Qualidade** ao VERIFY.md. R-RB Piso não implementados bloqueiam `verify_complete` — registrar `verify_failed` até serem resolvidos ou explicitamente aceitos como risco P0.
|
|
145
180
|
9. **Só se todas as verificações relevantes passarem:** se `after_verify_draft_commit` não for `false`: acrescentar em **VERIFY.md** a seção **Rascunho de commit** — mensagem convencional (ex.: `feat:` / `fix:`) + bullets alinhados aos critérios **A*** e decisões **D-NN**; **não** incluir segredos.
|
|
146
181
|
10. **Só se passou:** se `after_verify_suggest_pr` não for `false`: acrescentar **Checklist PR** — branch base, título sugerido, screenshots se UI, links a SPEC/PLAN/DISCUSS, testes executados.
|
|
147
182
|
11. No chat, responder nesta ordem:
|
|
@@ -161,4 +196,5 @@ O `calibration_error` de cada dimensão = `|score declarado - resultado observad
|
|
|
161
196
|
- [ ] Se existiu DISCUSS.md: tabela de Fidelidade de decisões preenchida sem divergências não documentadas.
|
|
162
197
|
- [ ] Se `verification_depth: "thorough"` em config: `.oxe/VALIDATION-GAPS.md` produzido como parte deste verify.
|
|
163
198
|
- [ ] Se `security_in_verify: true` em config: `.oxe/SECURITY.md` produzido; achados P0 resolvidos ou `verify_failed` registrado.
|
|
199
|
+
- [ ] Se SPEC.md contiver R-RB v1: seção **Contrato de Qualidade** presente em VERIFY.md com Quality Score realizado; R-RB Piso não implementados tratados como gaps P0.
|
|
164
200
|
</success_criteria>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxe-cc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "OXE — spec-driven workflows in .oxe/; integrates with Cursor, GitHub Copilot, Claude, OpenCode, Gemini, Codex, Windsurf, Antigravity (npx)",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"author": "",
|
|
@@ -49,14 +49,20 @@
|
|
|
49
49
|
".github",
|
|
50
50
|
"commands",
|
|
51
51
|
"vscode-extension",
|
|
52
|
+
"packages/runtime/src",
|
|
53
|
+
"packages/runtime/package.json",
|
|
54
|
+
"packages/runtime/tsconfig.json",
|
|
52
55
|
"AGENTS.md",
|
|
53
56
|
"README.md",
|
|
54
57
|
"CHANGELOG.md"
|
|
55
58
|
],
|
|
56
59
|
"scripts": {
|
|
60
|
+
"build:runtime": "cd packages/runtime && npm run build",
|
|
57
61
|
"sync:runtime-metadata": "node scripts/sync-runtime-metadata.cjs",
|
|
58
62
|
"sync:cursor": "node scripts/sync-cursor-from-prompts.cjs",
|
|
59
|
-
"test": "node --test tests/install.test.cjs tests/oxe-project-health.test.cjs tests/oxe-dashboard.test.cjs tests/oxe-operational.test.cjs tests/oxe-azure.test.cjs tests/oxe-sdk.test.cjs tests/oxe-manifest.test.cjs tests/oxe-agent-install.test.cjs tests/oxe-install-resolve-full.test.cjs tests/oxe-health-extended.test.cjs tests/oxe-workflows-edge.test.cjs tests/oxe-sdk-edge.test.cjs tests/oxe-cli-edge.test.cjs tests/oxe-npm-version.test.cjs tests/oxe-scripts.test.cjs tests/oxe-retro-health.test.cjs tests/oxe-security-permissions.test.cjs tests/oxe-runtime-semantics.test.cjs",
|
|
63
|
+
"test:root": "node --test tests/install.test.cjs tests/oxe-project-health.test.cjs tests/oxe-dashboard.test.cjs tests/oxe-operational.test.cjs tests/oxe-azure.test.cjs tests/oxe-sdk.test.cjs tests/oxe-manifest.test.cjs tests/oxe-agent-install.test.cjs tests/oxe-install-resolve-full.test.cjs tests/oxe-health-extended.test.cjs tests/oxe-workflows-edge.test.cjs tests/oxe-sdk-edge.test.cjs tests/oxe-cli-edge.test.cjs tests/oxe-npm-version.test.cjs tests/oxe-scripts.test.cjs tests/oxe-retro-health.test.cjs tests/oxe-security-permissions.test.cjs tests/oxe-runtime-semantics.test.cjs",
|
|
64
|
+
"test:runtime": "cd packages/runtime && npm test",
|
|
65
|
+
"test": "npm run build:runtime && npm run test:root && npm run test:runtime",
|
|
60
66
|
"test:coverage": "c8 --check-coverage --lines 82 --functions 85 --branches 58 --statements 82 npm test",
|
|
61
67
|
"scan:assets": "node scripts/oxe-assets-scan.cjs",
|
|
62
68
|
"build:vscode-ext": "cd vscode-extension && npx @vscode/vsce package --no-yarn --allow-missing-repository",
|
|
@@ -83,4 +89,4 @@
|
|
|
83
89
|
"dependencies": {
|
|
84
90
|
"semver": "^7.7.4"
|
|
85
91
|
}
|
|
86
|
-
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oxe/runtime",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "OXE agentic execution engine — Runtime Foundation (R1)",
|
|
6
|
+
"main": "../../lib/runtime/index.js",
|
|
7
|
+
"types": "../../lib/runtime/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "tsc --project tsconfig.test.json && node --test dist-tests/tests/*.test.js",
|
|
11
|
+
"clean": "node -e \"const fs=require('fs');['../../lib/runtime','dist-tests'].forEach(d=>{try{fs.rmSync(d,{recursive:true})}catch{}});\""
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/node": "^25.6.0",
|
|
15
|
+
"typescript": "^5.4.5"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import type { WorkspaceStrategy } from '../models/workspace';
|
|
3
|
+
|
|
4
|
+
// Mirror of SDK ParsedTask / ParsedSpec / ParsedPlan interfaces
|
|
5
|
+
// (avoids a hard dependency on the CJS SDK from TypeScript source)
|
|
6
|
+
export interface ParsedTask {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
wave: number | null;
|
|
10
|
+
dependsOn: string[];
|
|
11
|
+
files: string[];
|
|
12
|
+
verifyCommand: string | null;
|
|
13
|
+
aceite: string[];
|
|
14
|
+
done: boolean;
|
|
15
|
+
meta?: Record<string, unknown> | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ParsedSpecCriterion {
|
|
19
|
+
id: string;
|
|
20
|
+
criterion: string;
|
|
21
|
+
howToVerify: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ParsedSpec {
|
|
25
|
+
objective: string | null;
|
|
26
|
+
criteria: ParsedSpecCriterion[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ParsedPlan {
|
|
30
|
+
tasks: ParsedTask[];
|
|
31
|
+
waves: Record<number, string[]>;
|
|
32
|
+
totalTasks: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface Action {
|
|
36
|
+
type: 'read_code' | 'generate_patch' | 'run_tests' | 'run_lint' | 'collect_evidence' | 'custom';
|
|
37
|
+
command?: string;
|
|
38
|
+
targets?: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface VerifyContract {
|
|
42
|
+
must_pass: string[];
|
|
43
|
+
acceptance_refs: string[];
|
|
44
|
+
command: string | null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface NodePolicy {
|
|
48
|
+
requires_human_approval: boolean;
|
|
49
|
+
max_retries: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface GraphNode {
|
|
53
|
+
id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
wave: number;
|
|
56
|
+
depends_on: string[];
|
|
57
|
+
workspace_strategy: WorkspaceStrategy;
|
|
58
|
+
mutation_scope: string[];
|
|
59
|
+
actions: Action[];
|
|
60
|
+
verify: VerifyContract;
|
|
61
|
+
policy: NodePolicy;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface GraphEdge {
|
|
65
|
+
from: string;
|
|
66
|
+
to: string;
|
|
67
|
+
type: 'dependency' | 'wave_sequence';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface Wave {
|
|
71
|
+
wave_number: number;
|
|
72
|
+
node_ids: string[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface ExecutionGraphMetadata {
|
|
76
|
+
compiled_at: string;
|
|
77
|
+
plan_hash: string;
|
|
78
|
+
spec_hash: string;
|
|
79
|
+
node_count: number;
|
|
80
|
+
wave_count: number;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface ExecutionGraph {
|
|
84
|
+
nodes: Map<string, GraphNode>;
|
|
85
|
+
edges: GraphEdge[];
|
|
86
|
+
waves: Wave[];
|
|
87
|
+
metadata: ExecutionGraphMetadata;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface CompilerOptions {
|
|
91
|
+
default_workspace_strategy?: WorkspaceStrategy;
|
|
92
|
+
default_max_retries?: number;
|
|
93
|
+
require_approval_for_all?: boolean;
|
|
94
|
+
skip_done_tasks?: boolean;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function compile(
|
|
98
|
+
plan: ParsedPlan,
|
|
99
|
+
spec: ParsedSpec,
|
|
100
|
+
options: CompilerOptions = {}
|
|
101
|
+
): ExecutionGraph {
|
|
102
|
+
const {
|
|
103
|
+
default_workspace_strategy = 'git_worktree',
|
|
104
|
+
default_max_retries = 2,
|
|
105
|
+
require_approval_for_all = false,
|
|
106
|
+
skip_done_tasks = false,
|
|
107
|
+
} = options;
|
|
108
|
+
|
|
109
|
+
const nodes = new Map<string, GraphNode>();
|
|
110
|
+
const edges: GraphEdge[] = [];
|
|
111
|
+
const waveMap = new Map<number, string[]>();
|
|
112
|
+
|
|
113
|
+
for (const task of plan.tasks) {
|
|
114
|
+
if (skip_done_tasks && task.done) continue;
|
|
115
|
+
|
|
116
|
+
const waveNumber = task.wave ?? 1;
|
|
117
|
+
const node: GraphNode = {
|
|
118
|
+
id: task.id,
|
|
119
|
+
title: task.title,
|
|
120
|
+
wave: waveNumber,
|
|
121
|
+
depends_on: task.dependsOn,
|
|
122
|
+
workspace_strategy: default_workspace_strategy,
|
|
123
|
+
mutation_scope: task.files,
|
|
124
|
+
actions: buildActions(task),
|
|
125
|
+
verify: {
|
|
126
|
+
must_pass: task.verifyCommand ? ['tests'] : [],
|
|
127
|
+
acceptance_refs: task.aceite,
|
|
128
|
+
command: task.verifyCommand,
|
|
129
|
+
},
|
|
130
|
+
policy: {
|
|
131
|
+
requires_human_approval: require_approval_for_all,
|
|
132
|
+
max_retries: default_max_retries,
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
nodes.set(task.id, node);
|
|
137
|
+
|
|
138
|
+
for (const dep of task.dependsOn) {
|
|
139
|
+
edges.push({ from: dep, to: task.id, type: 'dependency' });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!waveMap.has(waveNumber)) waveMap.set(waveNumber, []);
|
|
143
|
+
waveMap.get(waveNumber)!.push(task.id);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const waves: Wave[] = Array.from(waveMap.entries())
|
|
147
|
+
.sort(([a], [b]) => a - b)
|
|
148
|
+
.map(([wave_number, node_ids]) => ({ wave_number, node_ids }));
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
nodes,
|
|
152
|
+
edges,
|
|
153
|
+
waves,
|
|
154
|
+
metadata: {
|
|
155
|
+
compiled_at: new Date().toISOString(),
|
|
156
|
+
plan_hash: hashObject(plan),
|
|
157
|
+
spec_hash: hashObject(spec),
|
|
158
|
+
node_count: nodes.size,
|
|
159
|
+
wave_count: waves.length,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function validateGraph(graph: ExecutionGraph): string[] {
|
|
165
|
+
const errors: string[] = [];
|
|
166
|
+
const nodeIds = new Set(graph.nodes.keys());
|
|
167
|
+
|
|
168
|
+
for (const [id, node] of graph.nodes) {
|
|
169
|
+
for (const dep of node.depends_on) {
|
|
170
|
+
if (!nodeIds.has(dep)) {
|
|
171
|
+
errors.push(`Node ${id} depends on unknown node ${dep}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Detect cycles using DFS
|
|
177
|
+
const visited = new Set<string>();
|
|
178
|
+
const inStack = new Set<string>();
|
|
179
|
+
|
|
180
|
+
function hasCycle(nodeId: string): boolean {
|
|
181
|
+
if (inStack.has(nodeId)) return true;
|
|
182
|
+
if (visited.has(nodeId)) return false;
|
|
183
|
+
visited.add(nodeId);
|
|
184
|
+
inStack.add(nodeId);
|
|
185
|
+
const node = graph.nodes.get(nodeId);
|
|
186
|
+
if (node) {
|
|
187
|
+
for (const dep of node.depends_on) {
|
|
188
|
+
if (hasCycle(dep)) return true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
inStack.delete(nodeId);
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (const id of nodeIds) {
|
|
196
|
+
if (hasCycle(id)) {
|
|
197
|
+
errors.push(`Cycle detected involving node ${id}`);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return errors;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function toSerializable(graph: ExecutionGraph): Record<string, unknown> {
|
|
206
|
+
return {
|
|
207
|
+
nodes: Object.fromEntries(graph.nodes),
|
|
208
|
+
edges: graph.edges,
|
|
209
|
+
waves: graph.waves,
|
|
210
|
+
metadata: graph.metadata,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function fromSerializable(raw: Record<string, unknown>): ExecutionGraph {
|
|
215
|
+
const nodes = new Map<string, GraphNode>(
|
|
216
|
+
Object.entries(raw.nodes as Record<string, GraphNode>)
|
|
217
|
+
);
|
|
218
|
+
return {
|
|
219
|
+
nodes,
|
|
220
|
+
edges: raw.edges as GraphEdge[],
|
|
221
|
+
waves: raw.waves as Wave[],
|
|
222
|
+
metadata: raw.metadata as ExecutionGraphMetadata,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function buildActions(task: ParsedTask): Action[] {
|
|
227
|
+
const actions: Action[] = [];
|
|
228
|
+
if (task.files.length > 0) {
|
|
229
|
+
actions.push({ type: 'read_code', targets: task.files });
|
|
230
|
+
}
|
|
231
|
+
actions.push({ type: 'generate_patch' });
|
|
232
|
+
if (task.verifyCommand) {
|
|
233
|
+
actions.push({ type: 'run_tests', command: task.verifyCommand });
|
|
234
|
+
}
|
|
235
|
+
actions.push({ type: 'collect_evidence' });
|
|
236
|
+
return actions;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function hashObject(obj: unknown): string {
|
|
240
|
+
return crypto
|
|
241
|
+
.createHash('sha256')
|
|
242
|
+
.update(JSON.stringify(obj))
|
|
243
|
+
.digest('hex')
|
|
244
|
+
.slice(0, 12);
|
|
245
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './graph-compiler';
|