izanagi-ai 3.17.0 → 3.17.1

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/.manifest CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "izanagi-ai",
3
- "version": "3.17.0",
3
+ "version": "3.17.1",
4
4
  "description": "Izanagi AI - Modular Skill-Oriented AI Prompt & Agent Framework for Autonomous Software Engineering",
5
5
  "author": "Pedro Henrique Sanches Leal",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai#readme",
8
- "generatedAt": "2026-09-02T13:41:16.345Z",
8
+ "generatedAt": "2026-09-02T13:43:32.890Z",
9
9
  "agents": [
10
10
  {
11
11
  "id": "adversarial-critic",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@
4
4
 
5
5
  ---
6
6
 
7
+ ## [3.17.1]: 2026-09-02
8
+
9
+ ### Fixed
10
+ - **`docs/` ficava fora do pacote npm.** O README publicado apontava para `docs/HANDOFF.md`, `docs/RUNTIME-PENDING.md` e `docs/POLYGLOT.md`, e quem instalava do registry encontrava links quebrados: a lista `files` do `package.json` nunca incluiu o diretório. Encontrado inspecionando o tarball publicado da 3.17.0.
11
+
12
+ ---
13
+
7
14
  ## [3.17.0]: 2026-09-02
8
15
 
9
16
  Decisão de produto que estava pendente desde a Fase 4, tomada: **o Izanagi é local-first**. Não fica de pé, não escuta porta, não guarda credencial em repouso. Quem agenda é o cron ou o Task Scheduler do sistema, e esta versão entrega o que faltava para eles conseguirem consumi-lo.
@@ -0,0 +1,210 @@
1
+ # Handoff: rearquitetura do runtime (v3.13.0 → v3.17.0)
2
+
3
+ > Escrito em 2026-09-02. Documento de passagem: o que mudou, onde cada coisa vive, o que foi decidido e por quê, o que sobrou. Feito para quem abrir o repositório sem ter acompanhado a sessão.
4
+ >
5
+ > Regra deste arquivo, herdada do `RUNTIME-PENDING.md`: **só entra o que é verificável no código**. Onde há número, ele foi medido. Onde não há, está dito que não há.
6
+
7
+ ---
8
+
9
+ ## 1. O que era e o que ficou
10
+
11
+ A v3.13.0 entregou as peças da rearquitetura (Commander, Task Contracts, roteamento por papel, verificação por evidência) e deixou registrado, com honestidade, que várias delas **existiam e não tinham caller**. Este handoff cobre o fechamento disso.
12
+
13
+ | | v3.13.0 | v3.17.0 |
14
+ |---|---|---|
15
+ | Crítica adversarial | Produzia texto que ninguém lia | Reprova o nó criticado, com correção mínima e reverificação |
16
+ | Protocolo A2A | Testado, sem caller | `ConversationLog` do run, por referência de artefato |
17
+ | Juiz semântico | Injetável, nunca injetado | Ligado por default (papel `worker`), `--no-judge` desliga |
18
+ | Replanejamento | Mesmo grafo com um nó reaberto | Plano B: troca agente → sobe papel → quebra a tarefa |
19
+ | Memória | Só no roteamento de skills | Informa modo e escolha de agente no planejamento |
20
+ | Skills | Uma chain para o run inteiro | Ranking por tarefa (teto 3) |
21
+ | Degradação de orçamento | Registrada, não aplicada | Cada degrau muda a execução |
22
+ | Artefato | Metadado em disco, conteúdo em RAM | Content store com `contentRef` e truncamento declarado |
23
+ | Paralelismo | `Promise.all` sem limite | Pool com teto configurável |
24
+ | Policy Engine | Fora do caminho de `run` | Nó `kind: 'tool'` com permissão, trust tier e sandbox |
25
+ | Execução de código | Inexistente (bloqueada por isolamento) | Processo isolado com Permission Model |
26
+ | Grafo | Plano | Sub-orquestração com teto de profundidade e orçamento dividido |
27
+ | Sucesso repetido | Virava estatística | Vira skill procedural por recorrência |
28
+ | Headless (sem API key) | Terminava `FAIL` sempre | `PASS` com verificação real |
29
+ | Uso agendado | Impossível | `--json` + exit code + webhook |
30
+
31
+ ### Fluxo hoje
32
+
33
+ ```
34
+ usuário ──> Commander (classifica · consulta memória · escolhe modo)
35
+ │
36
+ ├─ contratos por tarefa, com skills do próprio objetivo
37
+ ▼
38
+ Task Graph ──> pool com teto de concorrência
39
+ │
40
+ ├─ nó de agente ──> modelo do papel (commander/specialist/worker)
41
+ └─ nó de tool ──> ToolRegistry ─> PolicyEngine ─> sandbox
42
+ │
43
+ ├─ pediu decomposição? ──> subgrafo (orçamento do pai DIVIDIDO)
44
+ ▼
45
+ Verificação (determinística · evidência · juiz semântico)
46
+ │
47
+ ┌───────┴────────┐
48
+ VERIFIED FAILED ──> healing ──> Commander.replan (Plano B)
49
+ │
50
+ ├─ crítica bloqueante? ──> reprova o criticado + correção mínima
51
+ ▼
52
+ trajetória registrada ──> 3ª recorrência verificada ──> skill procedural
53
+
54
+ em volta: orçamento com degradação real · ConversationLog A2A · trace · cache
55
+ ```
56
+
57
+ ---
58
+
59
+ ## 2. Onde cada coisa vive
60
+
61
+ Arquivos criados nesta rodada, com a responsabilidade de cada um:
62
+
63
+ | Arquivo | Responsabilidade |
64
+ |---|---|
65
+ | `runtime/protocol/conversation.ts` | Log A2A do run. Mensagem carrega referência de artefato e resumo de 240 chars, nunca conteúdo |
66
+ | `runtime/verification/judge.ts` | Juiz semântico apoiado em modelo. Saída ilegível vira `inconclusive`, nunca reprovação |
67
+ | `runtime/orchestration/subgraph.ts` | Decomposição em execução: parsing, construção do subgrafo, agregação |
68
+ | `runtime/tools/code-sandbox.ts` | Processo isolado com Permission Model do Node |
69
+ | `runtime/evolution/trajectories.ts` | Assinatura de caminho, barra de recorrência, corpo da skill procedural |
70
+ | `runtime/benchmarks/arena.ts` | Métricas de execução real: verificação, recuperação, retries, custo |
71
+ | `runtime/benchmarks/memory-benchmark.ts` | Medição de busca e compressão, com limiar declarado |
72
+ | `runtime/notify/webhook.ts` | Notificação de fim de run, payload de metadado, exit code |
73
+
74
+ Arquivos que mudaram de comportamento e valem uma leitura antes de mexer:
75
+
76
+ - `runtime/orchestrator.ts` — ganhou `interpretCritique`, `executeTool`, `runSubgraph`, `recordTrajectory`. É o arquivo mais denso do runtime.
77
+ - `runtime/orchestration/commander.ts` — `replan`, memória no planejamento, skills por tarefa, marcação de decomponível.
78
+ - `runtime/orchestration/context-resolver.ts` — correção dirigida, contrato de saída de crítica, protocolo de decomposição.
79
+ - `runtime/memory/store.ts` — stats por domínio, trajetórias, e a correção do recall da busca.
80
+ - `runtime/tools/registry.ts` — `code.execute` e `execute()` assíncrono.
81
+
82
+ ---
83
+
84
+ ## 3. Bugs reais encontrados
85
+
86
+ Nenhum destes foi procurado: todos apareceram escrevendo o teste da feature ao lado. Estão aqui porque cada um vale mais que a feature que o revelou.
87
+
88
+ | Bug | Por que importava |
89
+ |---|---|
90
+ | **Busca de memória com recall truncado** | `search()` operava sobre o conteúdo já cortado em 4000 chars. Tudo que o projeto aprendia depois das primeiras páginas era invisível. Busca lenta se percebe; busca cega, não. Depois do conserto: 296KB alcançáveis contra 16KB, mesma latência |
91
+ | **Caminho relativo escapava da sandbox** | `ensureInside` resolvia contra o **cwd do processo**, não contra a zona declarada. `fs.write` com `"saida.txt"` gravava no diretório de onde o izanagi foi invocado |
92
+ | **Sandbox concedia `os.tmpdir()` inteiro** | O diretório de trabalho vive lá dentro, então qualquer temp de terceiro ficava legível pelo script |
93
+ | **`toText` devolvia `undefined`** | `JSON.stringify(undefined)` não é string. Validar retorno vazio de tool estourava em vez de reprovar o artefato |
94
+ | **Timeout da sandbox resolvia cedo** | A Promise resolvia antes do processo morrer: handle aberto, EPERM na limpeza no Windows, resíduo acumulando |
95
+ | **Verificação reprovada abortava na 1ª tentativa** | `classifyFailure` não reconhecia "verificação", então critério não comprovado caía no ramo genérico em vez do caminho de cura de validação |
96
+ | **`minSize: 60` reprovava crítica que aprova** | `{"status":"approved","issues":[]}` tem 33 chars |
97
+ | **Recomendação de crítica nunca aparecia** | Testava `ctx.artifacts.has('critique')` — `critique` é o *kind*, a chave do mapa é o id do nó (`critic`) |
98
+ | **Tabela de economia do dashboard** | Referenciava `costUsd`/`degradations`; os campos reais são `estimatedCostUsd`/`degradationsApplied`. Metade sairia vazia |
99
+
100
+ ---
101
+
102
+ ## 4. Decisões que valem conhecer antes de mexer
103
+
104
+ Cada uma foi tomada com um motivo, e mudá-las sem esse motivo em mente vai quebrar algo que hoje funciona.
105
+
106
+ **Ausência não é aprovação.** Juiz que não respondeu devolve `inconclusive`, não reprovação nem aprovação. Métrica sem execução aparece como ausente, nunca como `0%`. Artefato sem validade avaliada é `valid: false`, não `true` por conveniência de tipo. Recall truncado era exatamente a violação disso.
107
+
108
+ **Toda autonomia tem teto do runtime, não do agente.** Crítica reabre um nó UMA vez. Sub-tarefa não decompõe. Profundidade de orquestração é do `Orchestrator`. Recursão decidida por quem está dentro dela não termina.
109
+
110
+ **Decompor não libera orçamento.** O subgrafo divide o teto do pai, com piso de 512 por sub-tarefa. Sem isso, pedir decomposição vira a saída mais barata para qualquer agente.
111
+
112
+ **Confiança vem da origem, não da declaração.** Trust tier sai do diretório de onde o agente foi lido (`agents/generated/` → generated, `.agents/` → community, resto → builtin). Um agente não declara o próprio tier. Agente desconhecido é `community`, o mais restritivo.
113
+
114
+ **Isolamento é do runtime, não de varredura de string.** A sandbox usa o Permission Model do Node. Varrer `import` no código seria evasível e daria falsa segurança.
115
+
116
+ **Metadado sai, conteúdo fica.** O webhook leva status, tokens, custo e nomes de artefato. Nunca o que os agentes produziram — endpoint de notificação costuma ser canal de equipe ou serviço não auditado.
117
+
118
+ **A barra para virar conhecimento é recorrência.** Trajetória só vira skill na 3ª execução verificada. Sintetizar a cada sucesso produziria skills genéricas competindo com as boas no ranking.
119
+
120
+ **Medir antes de trocar.** FTS5 e compressão neural têm limiar declarado no código. `izanagi benchmark memory` aplica o limiar ao número medido e diz o que ele sustenta.
121
+
122
+ ---
123
+
124
+ ## 5. Números medidos
125
+
126
+ Reproduzíveis neste repositório, hoje:
127
+
128
+ ```
129
+ izanagi benchmark memory
130
+ busca textual: p95 2.0ms sobre 296KB → abaixo do teto de 25ms
131
+ compressão: 48000 → 3993 chars (8.3%) → abaixo do alvo de 35%
132
+
133
+ izanagi benchmark run architecture --execute
134
+ Arena: verificação 100% · retries 0 · tokens 3360 · 42ms
135
+
136
+ izanagi run "..." --mode autonomous (headless, sem API key)
137
+ antes: FAIL, 3 tentativas, abort
138
+ agora: PASS, 4/4 VERIFIED, 10 mensagens A2A
139
+
140
+ izanagi run "..." --json
141
+ JSON único no stdout · stderr vazio · exit 0
142
+ ```
143
+
144
+ Testes: **572, com 571 passando**. O vermelho é `polyglot: bin Rust presente com --version barato`, que escreve um binário falso com shebang bash e tenta executá-lo — não roda no Windows. É anterior a esta rodada e independente dela.
145
+
146
+ ---
147
+
148
+ ## 6. O que NÃO foi feito, e por quê
149
+
150
+ Nada aqui está aberto por falta de tempo. Está aberto por escolha, e a escolha tem motivo.
151
+
152
+ **Rede não é isolada na sandbox.** O Permission Model do Node não cobre rede: medi, `fetch` funciona com `--permission` ligado. Existe um teste que registra esse limite e **quebra se o comportamento mudar** — limite testado é um limite; limite só documentado é esperança. Mitigação: `code.execute` exige permissão `shell`, que a política nega a `generated` e `community`. Isolar de verdade exige container ou firewall de processo.
153
+
154
+ **Templates do Planner não geram nós de tool.** O caminho existe, é seguro e testado. Colocar tool nos templates exige saber qual tool cada workflow precisa, e isso depende do projeto de quem usa.
155
+
156
+ **Decomposição por LLM no planejamento não tem caller.** `Commander.plan({ decompose })` aceita, mas nem CLI nem SDK injetam. O planejamento em produção é template + heurística, e é determinístico por isso: planejar não gasta token. (Decomposição em **execução** é outra coisa e existe.)
157
+
158
+ **Token Benchmark mede plano, não execução.** Separado de propósito. Consumo real sai de `izanagi budget <run-id>` ou de `benchmark run --execute`. Os dois números nunca dividem o mesmo campo.
159
+
160
+ **A medição de compressão não avalia qualidade.** Mede razão de tamanho, não se o que sobrou era o que importava. Isso exigiria gabarito anotado, e é por isso que a reavaliação de compressão neural fica condicionada a essa medida existir.
161
+
162
+ **Sem daemon, porta ou credencial em repouso.** Decisão de produto tomada nesta rodada: local-first. Receber comando de fora exigiria autenticação, isolamento entre execuções e credenciais paradas — e as decisões de segurança já tomadas precisariam ser revisitadas, não estendidas.
163
+
164
+ ---
165
+
166
+ ## 7. Por onde continuar
167
+
168
+ Em ordem de valor por esforço, com o critério de pronto de cada um.
169
+
170
+ **1. Rodar a Arena contra um provider real.** Tudo que existe hoje foi exercitado headless ou com producer de teste. `izanagi benchmark run --execute` com uma API key configurada produziria os primeiros números de verificação e recuperação sobre execução de verdade. *Pronto quando:* existir um relatório salvo em `.izanagi/state/benchmarks/` com `execution.verificationRate` vindo de chamadas reais, e um segundo relatório para comparar.
171
+
172
+ **2. Exercitar o critique loop com modelo real.** O parsing é tolerante e testado, mas nenhum modelo de verdade produziu uma crítica ainda. É onde o formato costuma quebrar. *Pronto quando:* um run `--mode autonomous` com provider real registrar uma correção dirigida no `izanagi explain --conversation`.
173
+
174
+ **3. Primeiro nó de tool num template.** Hoje o caminho seguro existe e ninguém passa por ele em produção. O candidato natural é um nó de verificação que roda teste de verdade (`code.execute` chamando o runner do projeto) em vez de um critério `file-exists`. *Pronto quando:* um template gerar nó de tool e a verificação de um run depender do resultado dele.
175
+
176
+ **4. Cache de resultado de tool.** É função pura da entrada, como a validação. Vale depois do item 3, quando houver tool sendo chamada.
177
+
178
+ **5. Estatística por domínio com volume real.** `agentStats(agent, domain)` já existe mas só decide com amostra mínima. Precisa de runs acumulados para significar algo.
179
+
180
+ **Não faça sem um caso concreto:** aumentar `maxOrchestrationDepth` além de 2, afrouxar a barra de recorrência da síntese de skills, ou permitir que sub-tarefa decomponha. Os três parecem melhorias e são as três formas conhecidas de transformar isto numa colmeia.
181
+
182
+ ---
183
+
184
+ ## 8. Verificação rápida
185
+
186
+ Para quem pegar o repositório e quiser confirmar que está tudo de pé:
187
+
188
+ ```bash
189
+ npm ci
190
+ npm run build
191
+ node --test "dist/runtime/tests/*.test.js" # 572 testes, 1 vermelho conhecido (polyglot/Windows)
192
+
193
+ izanagi benchmark memory # medição de busca e compressão
194
+ izanagi run "auditar a segurança da API" --mode orchestrated --json
195
+ echo $? # 0 concluiu · 1 falhou · 2 aguarda aprovação
196
+ izanagi explain <run-id> --conversation # quem falou com quem
197
+ izanagi budget <run-id> # para onde foi o orçamento
198
+ ```
199
+
200
+ ---
201
+
202
+ ## 9. Documentos irmãos
203
+
204
+ | Arquivo | O que responde |
205
+ |---|---|
206
+ | [`RUNTIME-PENDING.md`](RUNTIME-PENDING.md) | O que ainda falta (nada aberto) e o que é escolha com motivo registrado |
207
+ | [`../ROADMAP.md`](../ROADMAP.md) | Fases 8 a 12, com o entregue e as limitações de cada uma |
208
+ | [`../CHANGELOG.md`](../CHANGELOG.md) | Mudança por versão, com Compatibility e breaking changes |
209
+ | [`../SYSTEM.md`](../SYSTEM.md) | Engines internas, quality gates, arquitetura de memória |
210
+ | [`../ARCHITECTURE.md`](../ARCHITECTURE.md) | Topologia e decisões estruturais |
@@ -0,0 +1,556 @@
1
+ # Arquitetura Poliglota do Izanagi AI — Referência Canônica
2
+
3
+ > Escopo: topologia, contratos de integração e procedimentos de build/verificação dos núcleos poliglotas (`crates/`, `go-services/`, `python-engine/`, `packages/`) e sua relação com o framework npm legado.
4
+ > Fontes: código real deste repositório + ADRs em `.agents/memoria/decisoes.md`. Nenhuma feature futura é descrita como existente; lacunas conhecidas estão marcadas como **Gap**.
5
+ > Última auditoria com execução local: 2026-08-23.
6
+
7
+ ---
8
+
9
+ ## Índice
10
+
11
+ 1. [Visão geral e topologia](#1-visão-geral-e-topologia)
12
+ 2. [Componentes por linguagem](#2-componentes-por-linguagem)
13
+ 3. [Contratos de integração](#3-contratos-de-integração)
14
+ 4. [Pipeline de execução da izanagi-next](#4-pipeline-de-execução-da-izanagi-next)
15
+ 5. [Quality gates e anti-generacidade](#5-quality-gates-e-anti-generacidade)
16
+ 6. [Skills v2 e Agents YAML](#6-skills-v2-e-agents-yaml)
17
+ 7. [Build e verificação local](#7-build-e-verificação-local)
18
+ 8. [CI e Release](#8-ci-e-release)
19
+ 9. [Decisões arquiteturais (ADRs)](#9-decisões-arquiteturais-adrs)
20
+
21
+ ---
22
+
23
+ ## 1. Visão geral e topologia
24
+
25
+ O Izanagi AI vive em duas camadas que coexistem por estratégia **Strangler Fig** (ADR-001):
26
+
27
+ - **Legado npm** (`src/`, `core/`, `agents/`, `skills/`, CLI `izanagi` publicado como `izanagi-ai`): fonte canônica dos agentes e skills, intocado e publicável.
28
+ - **Topologia poliglota** (crescimento novo): um SDK TypeScript (`packages/sdk`) que ponteia quatro núcleos nativos — quality gate **Rust**, orquestrador de swarm **Go**, cliente MCP **Rust** e analisador semântico **Python** — consumidos pela CLI de nova geração (`packages/cli`, binário `izanagi-next`).
29
+
30
+ Não há npm workspaces na raiz nesta fase (decisão ADR-001: zero risco ao pacote publicado). O SDK importa-se por caminho relativo dentro de `packages/`; ambos os pacotes são `"private": true`.
31
+
32
+ ### Topologia
33
+
34
+ ```text
35
+ ┌──────────────────────────────────────────────────────┐
36
+ │ TypeScript (Node >= 22) │
37
+ │ packages/cli — @izanagi/cli-next │
38
+ │ binário: izanagi-next │
39
+ └───────────────────────────┬──────────────────────────┘
40
+ │ import relativo
41
+ ┌───────────────────────────▼──────────────────────────┐
42
+ │ packages/sdk — @izanagi/sdk │
43
+ │ RustCoreClient · OrchestratorClient · McpClient · │
44
+ │ SemanticAnalyzer · loadSkillCatalog │
45
+ └──┬──────────────┬──────────────┬──────────────┬──────┘
46
+ subprocess │ │ UDS │ subprocess │ subprocess
47
+ NDJSON stdin/out │ JSON-RPC │ JSON-RPC │ NDJSON stdio │ CLI + JSON
48
+ │ │ + push event │ │
49
+ ┌─────────────▼───┐ ┌──────▼─────────┐ ┌▼────────────┐ ┌▼─────────────────┐
50
+ │ RUST │ │ GO │ │ RUST │ │ PYTHON │
51
+ │ crates/ │ │ go-services/ │ │ crates/ │ │ python-engine/ │
52
+ │ izanagi_core │ │ swarm_ │ │ izanagi_mcp │ │ ast_analyzer │
53
+ │ bin: izanagi- │ │ orchestrator │ │ bin: │ │ │
54
+ │ core │ │ │ │ izanagi-mcp │ │ │
55
+ │ quality gate │ │ pipeline │ │ cliente MCP │ │ AST treesitter │
56
+ │ (7 heurísticas) │ │ architect → │ │ JSON-RPC │ │ + fallback │
57
+ │ │ │ engineer → qa │ │ stdio │ │ estrutural │
58
+ │ │ │ → security │ │ │ │ │
59
+ └─────────────────┘ └────────────────┘ └─────────────┘ └──────────────────┘
60
+
61
+ Catálogo de skills/agents (arquivos, não serviços):
62
+ .skills/<name>/SKILL.md formato v2 (106 módulos) ← packages/skill-migrator
63
+ .agents/agents/<slug>.yaml derivação v2 (22 YAMLs) ← packages/agent-migrator
64
+ agents/*.json fonte canônica legado (22 agentes)
65
+ ```
66
+
67
+ Fluxo típico de uma tarefa: a `izanagi-next` roteia skills pelo front-matter, compõe o payload, submete ao orquestrador Go pelo socket Unix e valida os artefatos produzidos com o gate Rust. O núcleo Python analisa código semanticamente (símbolos, complexidade, imports); o núcleo MCP descobre/invoça tools de servidores MCP externos.
68
+
69
+ ---
70
+
71
+ ## 2. Componentes por linguagem
72
+
73
+ | Caminho | Linguagem | Papel | Entrypoints | Testes |
74
+ |---|---|---|---|---|
75
+ | `crates/izanagi_core` | Rust | Quality Engine: validação estrutural estática de TS/Python/Go contra 7 heurísticas anti-slop + scanner anti-racionalização | lib `izanagi_core::analyze`; binário `izanagi-core` (NDJSON stdin/stdout + modo `scan-rationalizations`); bindings WASM sob feature `wasm` | `cargo test --workspace` (**111 testes** na verificação de 2026-08-23: 66 lib core + 4 bin core + 16 integração `rationalizations` + 2 doc-tests core + 7 lib mcp + 15 mock_server + 1 doc-test mcp) |
76
+ | `crates/izanagi_mcp` | Rust | Cliente MCP: JSON-RPC 2.0 sobre stdio delimitado por newlines; ciclo spawn → handshake → request → teardown | binário `izanagi-mcp` (modos discovery e `call --tool=`) | inclusos no `cargo test --workspace` |
77
+ | `go-services/swarm_orchestrator` | Go 1.26 | Orquestrador de swarm: pipeline concorrente multi-estágio por canais, exposto via JSON-RPC 2.0 sobre Unix Domain Socket com push de eventos; wiring com Uber Fx | `main.go` → `app.Run()` | `go build ./... && go vet ./... && go test ./...` |
78
+ | `python-engine/ast_analyzer` | Python ≥3.10 | Analisador semântico multilíngue (py/ts/tsx/go): símbolos, complexidade ciclomática, imports, chunks para embedding | `python -m ast_analyzer analyze <path>`; console script `ast-analyzer` | `pytest tests/ -q` no `python-engine/` (70 passed na verificação) |
79
+ | `packages/sdk` | TypeScript | `@izanagi/sdk`: clientes tipados strict para os quatro núcleos + catálogo de skills. Zero dependências runtime | `composePipeline()` em `src/index.ts` | `npm test` (= tsc + `node --test dist/tests/*.test.js`; **42 testes** na verificação de 2026-08-23, incluindo o novo cliente `RustCoreClient.scanRationalizations`) |
80
+ | `packages/cli` | TypeScript | `@izanagi/cli-next`: CLI sobre o SDK — pipeline de 4 fases com auto-heal e gates duplos (código + anti-racionalização), listagem/inspeção de agents/skills, checagem de gates | `src/index.ts` → `dist/cli/src/index.js` (`bin: izanagi-next`) | `npm test` (= tsc + node --test; **13 testes** na verificação de 2026-08-23, suíte própria desde a v3.10.0) + smoke manual (`help`, `agent list`, `skill list/show`, `gates check`) |
81
+ | `packages/skill-migrator` | Node (ESM, `.mjs`) | Conversor determinístico idempotente skills v1 → v2 (+ campo `references:` no front-matter v2) | `cli.mjs` (`--src --dest --dry-run --clean --check --json`) | dry-run e `--check` anti-drift (exit 1 em drift) + sha256 da árvore (documentado no README do pacote) |
82
+ | `packages/agent-migrator` | Node (ESM, `.mjs`) | Gerador determinístico idempotente dos YAMLs v2 a partir de `agents/*.json` | `cli.mjs` (`--src --dest --check --json`) | modo `--check` (round-trip interno byte-a-byte) |
83
+ | raiz (`package.json`, `src/`, `core/`, …) | TypeScript | Framework npm legado `izanagi-ai` (v3.10.0), fonte canônica de agentes/skills | `bin/izanagi.js`; scripts `npm run build/test/verify/doctor` | `npm test` na raiz |
84
+
85
+ ---
86
+
87
+ ## 3. Contratos de integração
88
+
89
+ Todo IPC entre as partes é texto JSON delimitado por newline — não há protobuf nem gRPC nesta fase (ver ADR-002 e **Gap** na seção 9).
90
+
91
+ ### 3.1 Orquestrador Go — JSON-RPC 2.0 sobre UDS
92
+
93
+ Fonte da verdade: `internal/server/rpc.go`, `internal/server/server.go`, `internal/domain/domain.go` (confirmados por leitura e por sondagem E2E contra o servidor real).
94
+
95
+ #### Métodos
96
+
97
+ | Método | Params | Result / Erro |
98
+ |---|---|---|
99
+ | `orchestrator.submit` | `{taskId, task, agentChain?}` — `agentChain` opcional; default = cadeia canônica | Result `{accepted:true, taskId}`; erros mapeados de sentinels do domínio |
100
+ | `orchestrator.status` | `{taskId}` | Result `TaskStatus {taskId, state, stage, error?, events[]}`; `-32001` se desconhecida |
101
+ | `orchestrator.cancel` | `{taskId}` | Result `{cancelled, taskId}`; já-terminal ⇒ `cancelled:false` (sem erro); desconhecida ⇒ `-32001` |
102
+
103
+ Regras do fio (validadas em server.go):
104
+
105
+ - Todo request deve carregar `"jsonrpc":"2.0"` exato; caso contrário `-32600`.
106
+ - Batch requests (frames `[...]`) são rejeitados com `-32600`.
107
+ - Notifications (sem `id` ou `id:null`) executam efeitos colaterais mas **nunca** recebem resposta.
108
+ - O servidor faz **push** da notificação `event` para todo cliente conectado; params = `domain.Event`:
109
+
110
+ ```json
111
+ { "jsonrpc": "2.0", "method": "event",
112
+ "params": { "taskId": "probe1", "type": "stage.completed",
113
+ "data": {"role":"qa","artifactPath":"…/03-qa.md"}, "at":"2026-08-23T04:17:49Z" } }
114
+ ```
115
+
116
+ Tipos de evento emitidos (`domain.go`): `task.submitted`, `stage.started`, `stage.completed`, `stage.failed`, `task.completed`, `task.failed`, `task.canceled`, `task.dropped`.
117
+
118
+ #### Error codes
119
+
120
+ | Código | Constante (`rpc.go`) | Significado |
121
+ |---|---|---|
122
+ | `-32700` | `codeParseError` | Frame ilegível (JSON inválido) |
123
+ | `-32600` | `codeInvalidRequest` | Request object inválido / batch / `jsonrpc` errado |
124
+ | `-32601` | `codeMethodNotFound` | Método inexistente |
125
+ | `-32602` | `codeInvalidParams` | Params malformados, taskId fora do padrão, prompt vazio |
126
+ | `-32001` | `codeUnknownTask` | TaskId desconhecido |
127
+ | `-32002` | `codeTaskConflict` | TaskId já ativo (não-terminal) |
128
+ | `-32003` | `codeQueueFull` | Fila de ingresso saturada |
129
+ | `-32004` | `codeShuttingDown` | Orquestrador em drain/shutdown |
130
+ | `-32005` | `codeSocketInUse` | **Reservado**: declarado em `rpc.go` mas nunca usado num frame de erro — a colisão de socket falha o boot em `Server.Start()` (erro de processo, não RPC) |
131
+
132
+ Padrão de taskId (compartilhado por Go e TS): `^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$` (`domain.go::ValidateTaskID`; espelhado em `packages/sdk/src/contracts.ts::TASK_ID_PATTERN`). Estados de task: `queued | running | done | failed`.
133
+
134
+ #### Socket paths — mismatch documentado
135
+
136
+ Há **dois defaults diferentes** e **duas envs diferentes** (uma por lado). Confirmado em código:
137
+
138
+ | Lado | Default | Variável de ambiente |
139
+ |---|---|---|
140
+ | Servidor Go (`internal/app/app.go`) | `/tmp/izanagi-orch.sock` | `IZANAGI_ORCHESTRATOR_SOCK` |
141
+ | SDK/CLI TS (`packages/sdk/src/environment.ts`) | `/tmp/izanagi-swarm.sock` | `IZANAGI_ORCHESTRATOR_SOCKET` |
142
+
143
+ Consequência prática: com defaults, cliente TS e servidor Go **não se encontram**. Para casá-los, aponte ambos para o mesmo path:
144
+
145
+ ```bash
146
+ # terminal do servidor
147
+ IZANAGI_ORCHESTRATOR_SOCK=/tmp/izanagi.sock ./swarm_orchestrator
148
+ # terminal do cliente TS
149
+ IZANAGI_ORCHESTRATOR_SOCKET=/tmp/izanagi.sock node dist/cli/src/index.js run --agent=… --task="…"
150
+ ```
151
+
152
+ (ou `socketPath` explícito no `OrchestratorClientOptions`). Este assimetria é conhecida e registrada em `.agents/memoria/contexto.md`; não há ainda unificação de default no código (**Gap**).
153
+
154
+ #### Pipeline interno (Go)
155
+
156
+ - Cadeia canônica (`domain.DefaultChain()`): `architect → senior-engineer → qa → security`. Cada papel tem seu próprio pool de workers sobre canal buffered (`Options.WorkersPerStage`, default 2, máx 32; `QueueDepth`, default 64, máx 10 000).
157
+ - Executor default (`FileArtifactExecutor`): renderiza markdown determinístico por estágio e grava atomicamente (temp+rename) em `<IZANAGI_ARTIFACTS_DIR>/<taskId>/NN-<role>.md` (default root: `.agents/artifacts`). Sem chamada externa/LLM — maquinaria real de pipeline cuja saída alimenta o contexto do próximo estágio.
158
+ - Shutdown graceful (SIGINT/SIGTERM): drena tasks aceitas; tarefas não-terminais são persistidas em `<artifacts>/pending-tasks.json`; segundo sinal força saída.
159
+
160
+ Env vars do servidor Go: `IZANAGI_ORCHESTRATOR_SOCK`, `IZANAGI_ARTIFACTS_DIR`, `IZANAGI_STAGE_WORKERS`, `IZANAGI_QUEUE_DEPTH`.
161
+
162
+ ### 3.2 Quality gate Rust — NDJSON stdin/stdout
163
+
164
+ Fonte da verdade: `crates/izanagi_core/src/protocol.rs`. Uma linha = um request; uma linha = um response; EOF encerra. Linhas vazias são ignoradas sem resposta. Payloads malformados geram erro estruturado inline (nunca derrubam a sessão); única falha fatal é transporte (pipe quebrado).
165
+
166
+ ```text
167
+ → {"op":"validate","language":"typescript","code":"function f() {}"}
168
+ ← {"ok":true,"score":85,"findings":[{"rule":"EMPTY_FUNCTION","severity":"error","line":1,"message":"…"}]}
169
+
170
+ → {"op":"rules"}
171
+ ← {"ok":true,"rules":["STUB_BODY","EMPTY_FUNCTION","GENERIC_CATCH","GENERIC_NAME","REDUNDANT_COMMENT","AI_WATERMARK","LONG_FUNCTION"]}
172
+
173
+ → {"op":"version"}
174
+ ← {"ok":true,"version":"0.1.0"}
175
+
176
+ → {"op":"scan-rationalizations","text":"// TODO: implement later"}
177
+ ← {"ok":true,"clean":false,"findings":[{"pattern_id":"ENG-STUB-MARKER","category":"engineering",
178
+ "severity":"blocker","excerpt":"// TODO: implement later","line":1}]}
179
+
180
+ → <qualquer coisa malformada>
181
+ ← {"ok":false,"error":"invalid request: …"}
182
+ ```
183
+
184
+ - `language` aceita somente `typescript | python | go` (fora disso: `{"ok":false,"error":"unknown language …"}`).
185
+ - `version` = versão do crate (`PROTOCOL_VERSION` derivado de `CARGO_PKG_VERSION`; `0.1.0` no workspace atual).
186
+ - `scan-rationalizations` aceita só a chave obrigatória `text` e devolve relatório próprio: `clean` booleano + findings com `pattern_id`/`category`/`severity` (`blocker|major|minor`)/`excerpt`/`line`. As duas listas de findings (`validate` vs. `scan-rationalizations`) são mutuamente exclusivas por operação.
187
+ - O mesmo scanner existe como **modo CLI** do binário: `izanagi-core scan-rationalizations --file=<path>` ou `--stdin` (relatório JSON numa linha no stdout; **exit 0** limpo · **exit 1** com findings · **exit 2** fonte ilegível/uso).
188
+ - Score 100 = sem findings; severidades possíveis nos findings: `error` (crítico, recusa gate) e demais níveis informativos.
189
+ - O SDK (`RustCoreClient`) usa **um processo curto por request** — enquadramento FIFO à prova de dessincronização. Resolução do binário: opção explícita > `$IZANAGI_CORE_BIN` > busca em `<repoRoot>/target/{debug,release}` e `<repoRoot>/crates/target/{debug,release}`.
190
+ - Descoberta de repo-root (`resolveRepoRoot`): sobe diretórios até achar pasta com `package.json` **e** `crates/`; `$IZANAGI_REPO_ROOT` atalha a busca.
191
+
192
+ #### Bindings WASM (feature `wasm`, ADR-003)
193
+
194
+ - Sob `#[cfg(feature = "wasm")]` em `src/wasm.rs`: exports `validateSource(source, language)`, `supportedLanguages()`, `ruleIds()`, `engineVersion()`, `scanRationalizations(text)` e `rationalizationPatternIds()` (o scanner anti-racionalização também cruza a fronteira WASM). Erros lançam envelope tipado (`{code:"UNKNOWN_LANGUAGE", message, supportedLanguages[]}`), nunca string parseável.
195
+ - Compilação nativa type-checka tudo: `cargo check -p izanagi_core --features wasm` (executado e verde na auditoria). Chamadas diretas em host abortam por design — a fronteira de interop só existe sob `wasm32`.
196
+ - Artefato `.wasm` real: apenas no job CI `wasm-build` (requer `rustup`/target `wasm32-unknown-unknown` + `wasm-bindgen-cli` na mesma versão do `Cargo.lock`, hoje 0.2.127). Local dev desta máquina **não tem rustup/wasm-pack** — não é possível gerar `.wasm` localmente (**Gap**, por design do ADR-003).
197
+
198
+ ### 3.3 MCP — harness Rust + sessão nativa TS
199
+
200
+ Duas superfícies complementares (`crates/izanagi_mcp` + `packages/sdk/src/mcp-client.ts`):
201
+
202
+ 1. **Discovery via binário** `izanagi-mcp [--timeout-ms=N] <server-cmd...>`: faz handshake e imprime um passo NDJSON por linha:
203
+
204
+ ```text
205
+ {"step":"initialize","result":{…}}
206
+ {"step":"tools/list","tools":[…]}
207
+ ```
208
+
209
+ Invocação pontual: `izanagi-mcp call --tool=<name> [--args=<json>] [--timeout-ms=N] <server-cmd...>` imprime adicionalmente `{"step":"tools/call","result":{…}}`. Erros vão para stderr como `izanagi-mcp: <message>` com exit 1 (inclui códigos reservados, ex.: `tools/call failed: method not found (-32601)`). O harness derruba o filho ao fim — não serve para sessões longas.
210
+
211
+ 2. **Sessão nativa TS** (`McpClient.connect()`): fala o mesmo framing de `codec.rs` diretamente com o servidor:
212
+ `initialize` com `protocolVersion "2025-06-18"` (constante em `client.rs`), notificação `notifications/initialized`,
213
+ requests correlacionados por id numérico, timeout por request e a taxonomia de erros reservados
214
+ `-32700/-32600/-32601/-32602/-32603` (`error.rs`). `callTool` retorna `{isError:true}` para falhas in-band;
215
+ falhas de transporte estouram erros tipados.
216
+
217
+ O servidor MCP alvo é configurado por comando (ex.: `IZANAGI_MCP_SERVER_CMD="node meu-server.cjs"`); sem comando, `pipeline.mcp` é `null` e o CLI segue sem o caminho MCP.
218
+
219
+ ### 3.4 Analisador Python — subprocess CLI
220
+
221
+ Contrato (`ast_analyzer/cli.py`, espelhado em `packages/sdk/src/semantic.ts`):
222
+
223
+ ```bash
224
+ <python> -m ast_analyzer analyze <path> [--glob PATTERN]
225
+ ```
226
+
227
+ - Exit 0 → relatório JSON no stdout (`FileReport` ou `DirReport`, snake_case: símbolos, complexidade, imports, chunks).
228
+ - Exit 1 → payload JSON no stderr: `{"ok":false,"error":{"type","message","path"}}`.
229
+ - Backends: tree-sitter quando importável (grammars py/ts/tsx/go), fallback estrutural (regex + indentação/chaves) com mesmo contrato de métricas; o modo ativo aparece em `capabilities.tree_sitter`.
230
+ - Interprete (ordem do SDK): opção explícita > `$IZANAGI_PYTHON` > `python-engine/.venv/bin/python` > `python3` no PATH. O filho roda com `cwd` fixado em `python-engine/` (módulo precisa ser importável).
231
+ - `pyproject.toml` declara `dependencies=[]` — tree-sitter é extra opcional; o CI instala via `requirements-dev.txt` pinado (`pytest==9.1.1`, `tree-sitter==0.25.2`, grammars `0.25.0/0.25.0/0.23.2`).
232
+
233
+ ### 3.5 Tabela consolidada de variáveis de ambiente
234
+
235
+ | Variável | Quem lê | Default | Função |
236
+ |---|---|---|---|
237
+ | `IZANAGI_CORE_BIN` | SDK/CLI | busca em `target/{debug,release}` | path do binário `izanagi-core` |
238
+ | `IZANAGI_MCP_BIN` | SDK/CLI | busca em `target/{debug,release}` | path do binário `izanagi-mcp` |
239
+ | `IZANAGI_ORCHESTRATOR_SOCKET` | SDK/CLI (TS) | `/tmp/izanagi-swarm.sock` | socket UDS do orquestrador (lado cliente) |
240
+ | `IZANAGI_ORCHESTRATOR_SOCK` | Servidor Go | `/tmp/izanagi-orch.sock` | socket UDS do orquestrador (lado servidor) — **nome diferente do TS, de propósito documentado** |
241
+ | `IZANAGI_PYTHON` | SDK | `python-engine/.venv/bin/python` → `python3` | interprete do analisador |
242
+ | `IZANAGI_MCP_SERVER_CMD` | SDK/CLI | ausente (MCP desligado) | comando do servidor MCP, separado por espaços |
243
+ | `IZANAGI_REPO_ROOT` | SDK | auto-detecção (`package.json` + `crates/`) | raiz do workspace poliglota |
244
+ | `IZANAGI_ARTIFACTS_DIR` | Servidor Go | `.agents/artifacts` | raiz de artefatos de estágio + `pending-tasks.json` |
245
+ | `IZANAGI_STAGE_WORKERS` | Servidor Go | `2` (máx 32) | goroutines por estágio |
246
+ | `IZANAGI_QUEUE_DEPTH` | Servidor Go | `64` (máx 10 000) | capacidade dos canais por estágio/ingresso |
247
+
248
+ ---
249
+
250
+ ## 4. Pipeline de execução da izanagi-next
251
+
252
+ Comando: `node dist/cli/src/index.js run --agent=<name> --task="<texto>" [--skills=a,b] [--files=f1,f2] [--max-heal-attempts=2] [--standalone] [--timeout-ms=120000] [--json]`
253
+
254
+ Exit codes do binário: `0` sucesso · `1` falha operacional (gate recusou, task falhou) · `2` erro de uso · `3` erro de ambiente (binário ausente, socket inacessível).
255
+
256
+ ```mermaid
257
+ sequenceDiagram
258
+ autonumber
259
+ participant C as izanagi-next run
260
+ participant K as Catálogo skills (.skills/ → skills/)
261
+ participant O as Orquestrador Go (UDS)
262
+ participant G as izanagi-core (gate Rust)
263
+
264
+ C->>K: Fase 1 · Routing — lê SOMENTE front-matter<br/>(--skills=a,b sobrepõe scorer heurístico)
265
+ K-->>C: até 5 skills candidatas
266
+ C->>C: Fase 2 · Loading — injeta corpos SKILL.md no payload<br/>(corpo truncado em 4.000 chars por skill)
267
+ C->>O: Fase 3 · Submission — orchestrator.submit(taskId, task)
268
+ alt socket disponível
269
+ O-->>C: accepted=true
270
+ loop polling exponencial (150ms→2s) até done|failed
271
+ C->>O: orchestrator.status(taskId)
272
+ end
273
+ else socket ausente ou --standalone
274
+ C->>C: grava .izanagi/tasks/<taskId>/prompt.md<br/>(via MCP fs_write se houver servidor; senão fs direto)
275
+ end
276
+ loop Fase 4 · Quality gates (código + anti-racionalização) + auto-heal (até max-heal-attempts)
277
+ C->>G: validate por cada arquivo de --files
278
+ C->>G: scan-rationalizations pelos mesmos conteúdos
279
+ alt findings severity=error · racionalização severity=blocker
280
+ G-->>C: REFUSED
281
+ C->>O: re-submit com relatório de violações anexado (taskId base-rN)
282
+ else sem violações
283
+ G-->>C: PASSED
284
+ C->>C: receipt .izanagi/tasks/<taskId>/result.json (exit 0)
285
+ end
286
+ end
287
+ C->>C: persistência do fracasso: violations.md (exit 1)
288
+ ```
289
+
290
+ Detalhes confirmados em `packages/cli/src/commands/run.ts`:
291
+
292
+ - **Fase 1**: scoring heurístico tokeniza a task (+3 nome da skill, +2 categoria, +1 prefixo na descrição) e mantém top-5 com score > 0; skill pedida e inexistente = erro loud.
293
+ - **Fase 3**: `taskId` base = `t<epoch36>-<agent sanitizado[12]>`; re-submissões de heal usam sufixo `-r<N>`. Queda de socket no meio do submit também cai para standalone.
294
+ - **Fase 4**: sem `--files`, a fase de gate é pulada (exit 0 após submissão). Dois gates rodam sobre os mesmos conteúdos, em ordem: o quality gate estrutural primeiro (findings `severity=error` recusam); só quando ele aceita todos os arquivos é que o gate anti-racionalização via `RustCoreClient.scanRationalizations` julga a prontidão da entrega (findings `severity=blocker` recusam; `major`/`minor` ficam advisory, sem reprovar). Recusa final grava `violations.md` com ambos os relatórios e sai 1 — cada tentativa de auto-heal re-submete com o relatório anexado ao payload. Binário Rust ausente ⇒ a fase inteira degrada para advisory: warnings loud no stderr, receipt registra `qualityGate`/`rationalizations` com `status:"skipped"` e a delivery prossegue com exit 0.
295
+ - Outros comandos: `agent list` (lê `agents/*.json`: nome, role, chains), `skill list [--category] [--search] [--json]` (catálogo v2 com fallback legado), `skill show <name>` (front-matter resumido + arquivos declarados em `references:` — disclosure progressivo: o corpo completo só entra no payload quando pedido) e `skill show <name> --ref=<file>` (imprime uma referência; o caminho é confinado ao `references/` da skill — absoluto, contendo `..` ou escapando do diretório = erro loud, anti-traversal), `gates check <file>` (gate em um arquivo; exit 1 se houver finding severity=error).
296
+
297
+ ---
298
+
299
+ ## 5. Quality gates e anti-generacidade
300
+
301
+ ### O que o core Rust valida
302
+
303
+ Sete heurísticas estruturais (`RULE_IDS`, ordem canônica), sobre código mascarado (comentários/strings blanked preservando linhas):
304
+
305
+ | Regra | Detecta |
306
+ |---|---|
307
+ | `STUB_BODY` | Corpos-stub (`pass`, `TODO`, corpo omitido) |
308
+ | `EMPTY_FUNCTION` | Funções com corpo vazio |
309
+ | `GENERIC_CATCH` | `catch`/`recover()` genéricos que engolem erro |
310
+ | `GENERIC_NAME` | Nomes genéricos sem intenção |
311
+ | `REDUNDANT_COMMENT` | Comentários que repetem o código |
312
+ | `AI_WATERMARK` | Marcas de geração por IA (ex.: “Generated by GPT”) |
313
+ | `LONG_FUNCTION` | Funções excessivamente longas |
314
+
315
+ Arquitetura interna (`lib.rs`): `mask` (blanks comments/strings) → `functions` (extents) → `rules` (7 heurísticas com atribuição exata de linha) → `engine` (scoring) → `protocol` (fio). A mesma engine alimenta as três superfícies (lib Rust, protocolo NDJSON, WASM) — as formas serializadas são pinadas por testes, então as superfícies não podem divergir.
316
+
317
+ ### Anti-generacidade nas skills v2
318
+
319
+ As seções obrigatórias `Common Rationalizations` e `Red Flags` (presentes em 106/106 arquivos `.skills/*/SKILL.md`, verificado por grep) materializam as leis do framework (`RULES.md`) como bibliotecas anti-racionalização por categoria (`engineering/testing/security/design/docs/devops/data/ai` — ver `packages/skill-migrator/rationalizations.mjs`). Elas pré-respondem as desculpas clássicas de atalho (“depois do launch”, “é neutro”, “ajusto no final”) com a Verdade técnica correspondente, e listam sinais-vermelhos que invalidam a entrega. A cadeia completa funciona assim: o gate Rust recusa **código** com cheiro de stub/slop; as skills v2 recusam **raciocínio** que leve a stub/slop — ambos os mecanismos determinísticos e verificáveis.
320
+
321
+ A cadeia completa funciona assim: o gate Rust recusa **código** com cheiro de stub/slop; as skills v2 recusam **raciocínio** que leve a stub/slop. Ambos os mecanismos são determinísticos e verificáveis (regras compiladas vs. seções obrigatórias validadas pelo migrador).
322
+
323
+ ---
324
+
325
+ ## 6. Skills v2 e Agents YAML
326
+
327
+ ### Skills v2 — `.skills/<name>/SKILL.md`
328
+
329
+ Gerado exclusivamente por `packages/skill-migrator` (ADR-004). Formato (exemplo real de `.skills/anti-ai-slop/SKILL.md`):
330
+
331
+ ```markdown
332
+ ---
333
+ name: "anti-ai-slop"
334
+ description: "<descrição original + gatilhos derivados>"
335
+ version: 2.0.0
336
+ category: design
337
+ tools:
338
+ mcp:
339
+ - mcp:fs_read
340
+ - mcp:fs_write
341
+ references: ← disclosure progressivo (v3.10.0)
342
+ - "references.md"
343
+ ---
344
+ ## Triggering Criteria
345
+ ## Step-by-Step Workflow
346
+ ## Verification Steps
347
+ ## Common Rationalizations
348
+ ## Red Flags
349
+ ## Legacy Reference (v1) ← corpo original preservado
350
+ ```
351
+
352
+ Garantias (implementadas em `migrate.mjs`, README do pacote):
353
+
354
+ - **Determinismo/idempotência**: funções puras, ordem de leitura ordenada, zero timestamps no output — rodadas repetidas produzem bytes idênticos (verificável por sha256 da árvore).
355
+ - **Fidelidade**: nada inventado; corpo original íntegro em Legacy Reference; estratégias de extração do workflow registradas em comentário HTML dentro da seção.
356
+ - **Falha loud**: skill sem corpo aproveitável ou divergência nome/diretório interrompe com exit 1 — nunca stub silencioso.
357
+ - Estado atual: 106/106 módulos migrados; todas as seis seções obrigatórias presentes em todos os arquivos (grep verificado em 2026-08-23).
358
+ - **Progressive disclosure (v3.10.0)**: o migrador copia `.skills/<name>/references/` e declara no front-matter `references:` a lista ordenada/deduplicada dos arquivos efetivamente disponíveis — é essa declaração que o `izanagi-next skill show --ref` consome (com fallback para scan do diretório).
359
+
360
+ Uso:
361
+
362
+ ```bash
363
+ node packages/skill-migrator/cli.mjs # migra (src=skills dest=.skills)
364
+ node packages/skill-migrator/cli.mjs --dry-run # valida sem escrever (exit codes 0/1/2)
365
+ node packages/skill-migrator/cli.mjs --check # anti-drift: re-migra em temp dir limpo e compara;
366
+ # drift/ausência/sobras = exit 1, uso inválido = exit 2
367
+ ```
368
+
369
+ O modo `--check` (desde a v3.10.0) fecha o antigo gap anti-drift do catálogo v2: compara o destino com uma re-migração limpa byte-a-byte, no mesmo espírito do `--check` do agent-migrador.
370
+
371
+ ### Agents YAML — `.agents/agents/<slug>.yaml`
372
+
373
+ Gerado exclusivamente por `packages/agent-migrator` (ADR-005). `agents/*.json` permanece a **fonte canônica** (Strangler Fig segue válido); o YAML é representação derivada — interface de leitura estruturada para CLIs. **Proibido editar YAML à mão**: toda mudança nasce no JSON e propaga por regeneração.
374
+
375
+ ```yaml
376
+ source: "agents/architect-agent.json" # primeira chave sempre
377
+ name: "Software Architect"
378
+ version: "2.8.0"
379
+ role: "System Design de alta escala, Clean Architecture, DDD..."
380
+ chains:
381
+ design_system:
382
+ - "memoria-projeto"
383
+ - "requirement-analyzer"
384
+ handoffs:
385
+ - to: "senior-engineer"
386
+ reason: "implementacao"
387
+ evaluation:
388
+ metrics:
389
+ - "correctness"
390
+ minScore: 0.7
391
+ ```
392
+
393
+ Garantias: espelhamento campo-a-campo do JSON (ausente = omitido; nada inventado; chaves desconhecidas anexadas em ordem alfabética), ordem canônica de grupos, metadado `source`, zero timestamps → **idempotência byte-a-byte**, round-trip interno obrigatório (leitor relê e compara profundamente), colisão de slug = erro loud antes de escrever, órfãos reportados e nunca apagados silenciosamente.
394
+
395
+ Anti-drift:
396
+
397
+ ```bash
398
+ node packages/agent-migrator/cli.mjs # regenera .agents/agents/
399
+ node packages/agent-migrator/cli.mjs --check # compara byte-a-byte sem escrever;
400
+ # detecta DRIFT (edição manual),
401
+ # AUSENTE e órfãos (exit 0/1/2)
402
+ ```
403
+
404
+ Estado atual: 22 YAMLs ↔ 22 JSONs em sincronia (`--check` executado em 2026-08-23: `EM SINCRONIA`, tree hash `6c88bf01…`).
405
+
406
+ Nota de higiene de repo (ADR-005): o antigo `.gitignore` com `.agents/` inteiro virou negativa fina (`.agents/memoria/`, `.agents/auditoria/`), pois gitignore não reinclui filhos de diretório totalmente excluído — YAMLs derivados são versionáveis; memória local nunca.
407
+
408
+ ---
409
+
410
+ ## 7. Build e verificação local
411
+
412
+ Comandos copiáveis por linguagem. Os marcados ✅ foram executados com sucesso na máquina de referência em 2026-08-23; os marcados 🔧 requerem toolchain ausente no ambiente local (honestidade acima de otimismo).
413
+
414
+ ### Rust (workspace na raiz)
415
+
416
+ ```bash
417
+ cargo build --workspace # binários em target/debug/{izanagi-core,izanagi-mcp}
418
+ cargo test --workspace # ✅ 111 testes verdes
419
+ cargo clippy --workspace --all-targets # ⚠️ não-bloqueante: 4 warnings pre-existentes
420
+ cargo check -p izanagi_core --features wasm # ✅ type-check dos bindings (ADR-003)
421
+ cargo fmt --check # ❌ falha hoje (44 pontos de diff) — NÃO bloqueante no CI
422
+ ```
423
+
424
+ Smoke do protocolo NDJSON (✅ executado):
425
+
426
+ ```bash
427
+ echo '{"op":"validate","language":"python","code":"def save():\n pass\n"}' \
428
+ | target/debug/izanagi-core
429
+ # {"ok":true,"score":85,"findings":[{"rule":"STUB_BODY","severity":"error","line":1,"message":"…"}]}
430
+ ```
431
+
432
+ ### Go
433
+
434
+ ```bash
435
+ cd go-services/swarm_orchestrator
436
+ go build ./... # ✅
437
+ go vet ./... # ✅
438
+ go test ./... # ✅ (suíte do módulo)
439
+
440
+ # subir servidor apontando para um socket explícito (✅ executado em /tmp):
441
+ go build -o /tmp/swarm_orchestrator .
442
+ IZANAGI_ORCHESTRATOR_SOCK=/tmp/izanagi.sock IZANAGI_ARTIFACTS_DIR=/tmp/artifacts /tmp/swarm_orchestrator
443
+ ```
444
+
445
+ ### Python
446
+
447
+ ```bash
448
+ cd python-engine
449
+ python -m venv .venv
450
+ .venv/bin/python -m pip install -r requirements-dev.txt # pins exatos (pytest 9.1.1, tree-sitter 0.25.2…)
451
+ .venv/bin/python -m pip install -e .
452
+ .venv/bin/python -m pytest tests/ -q # ✅ 70 passed
453
+ .venv/bin/python -m ast_analyzer analyze <arquivo> # ✅ relatório JSON no stdout
454
+ ```
455
+
456
+ ### Packages TypeScript (SDK e CLI)
457
+
458
+ ```bash
459
+ cd packages/sdk && npm install && npm test # ✅ 42/42 (tsc + node --test dist/tests/*.test.js)
460
+ cd ../cli && npm install && npm test && npm run build
461
+ # ✅ cli: 13/13 na suíte própria (dist/cli/tests) + dist/cli/src/index.js gerado
462
+
463
+ # smoke (✅ executado):
464
+ node dist/cli/src/index.js help
465
+ node dist/cli/src/index.js agent list
466
+ node dist/cli/src/index.js skill list --search=wasm
467
+ node dist/cli/src/index.js skill show tdd # front-matter + referências declaradas
468
+ node dist/cli/src/index.js skill show tdd --ref=references.md # conteúdo da referência (path confinado)
469
+ node dist/cli/src/index.js gates check <arquivo> # exit 1 se houver violation severity=error
470
+
471
+ # pipeline completo (requer binários Rust construídos; orquestrador Go opcional):
472
+ cargo build -p izanagi_core
473
+ export IZANAGI_ORCHESTRATOR_SOCKET=/tmp/izanagi.sock # casar com o IZANAGI_ORCHESTRATOR_SOCK do Go!
474
+ node dist/cli/src/index.js run --agent=senior-engineer --task="…" --files=a.ts
475
+ ```
476
+
477
+ ### Migradores (Node ≥18, zero deps)
478
+
479
+ ```bash
480
+ node packages/agent-migrator/cli.mjs --check # ✅ EM SINCRONIA (22/22)
481
+ node packages/skill-migrator/cli.mjs --dry-run # ✅ 106/106 ok
482
+ node packages/skill-migrator/cli.mjs --check # ✅ SEM DRIFT (106/106)
483
+ ```
484
+
485
+ ### Requer toolchain indisponível localmente (🔧)
486
+
487
+ - **Build `.wasm` real**: `rustup target add wasm32-unknown-unknown` + `wasm-bindgen-cli 0.2.127` (versão TEM que bater com `Cargo.lock`). Fluxo completo documentado em `crates/izanagi_core/README.md` e exercido apenas no job CI `wasm-build`.
488
+ - **gRPC**: condicionado à disponibilidade de `protoc` (ADR-002) — ausente neste ambiente; nada de gRPC existe no código hoje.
489
+
490
+ ### Verificação global sugerida (ordem)
491
+
492
+ ```bash
493
+ npm test # raiz legado (build + suíte node:test) ✅ 288/288 em 2026-08-23*
494
+ (cd go-services/swarm_orchestrator && go build ./... && go vet ./... && go test ./...)
495
+ cargo test --workspace
496
+ (cd python-engine && .venv/bin/python -m pytest tests/ -q)
497
+ (cd packages/sdk && npm test)
498
+ (cd packages/cli && npm test && npm run build)
499
+ node packages/agent-migrator/cli.mjs --check
500
+ node packages/skill-migrator/cli.mjs --check
501
+ ```
502
+
503
+ \* Os números de testes mudam conforme o código evolui (raiz: 262 no AGENTS.md → 266 na memória → 284 na auditoria anterior → 288 hoje; Rust workspace: 81 → **111**; SDK: 41 → **42**; CLI-next: 0 → **13**); o valor canônico é sempre o resultado corrente de cada suíte.
504
+
505
+ ---
506
+
507
+ ## 8. CI e Release
508
+
509
+ ### `.github/workflows/polyglot.yml` — Polyglot CI
510
+
511
+ Gatilhos: push e PR em `main`. Seis jobs **100% paralelos** (nenhum `needs`): qualquer job vermelho falha o run (fail-fast global). Permissões `contents: read` (least privilege, nenhum secret acessado). Concurrency group cancela runs obsoletos de PR. Todas as actions de terceiros fixadas por SHA de commit completo (imutável) — nunca tags mutáveis (`@v4`/`@main`).
512
+
513
+ | # | Job | Conteúdo |
514
+ |---|---|---|
515
+ | 1 | `legacy-npm` | Node 24 · `npm ci` · `npm run build` · `npm test` (framework legado da raiz) |
516
+ | 2 | `rust` | stable + clippy · `cargo clippy --workspace --all-targets` (não-bloqueante) · `cargo test --workspace` · `cargo check -p izanagi_core --features wasm` |
517
+ | 3 | `wasm-build` | target `wasm32-unknown-unknown` · download do `wasm-bindgen-cli 0.2.127` (asset musl x86_64, sha256 conferido) · `cargo build -p izanagi_core --features wasm --target wasm32-unknown-unknown` · `wasm-bindgen … --out-dir target/wasm-bindgen` — prova E2E do ADR-003 |
518
+ | 4 | `go` | setup-go lê a versão do `go.mod` (`go-version-file`) · `go build/vet/test ./...` |
519
+ | 5 | `python` | Python 3.14 · venv explícito · `pip install -r requirements-dev.txt` (pins) + `-e .` · `pytest tests/ -q` |
520
+ | 6 | `ts-packages` | matriz paralela com fail-fast: `sdk` → `npm test`; `cli` → `npm run build` (ambos com lockfile commitado ⇒ `npm ci`) |
521
+
522
+ Notas registradas no próprio workflow (fatos medidos, não opinião):
523
+
524
+ - `cargo check --features wasm` **na raiz** de workspace virtual é silenciosamente ignorado pelo cargo — a forma correta exige `-p izanagi_core` (por isso o job usa `-p`).
525
+ - `cargo fmt --check` não roda: o código atual falha com 44 pontos de diff; reativar após passar o `cargo fmt`.
526
+ - Clippy roda sem `-D warnings`: existem 4 warnings pre-existentes; endurecer após limpeza.
527
+ - Cache Rust (`Swatinem/rust-cache`) na raiz; o input `workspaces: true` foi rejeitado deliberadamente (seria resolvido como path `<repo>/true`).
528
+
529
+ ### Release
530
+
531
+ Dois circuitos independentes:
532
+
533
+ 1. **npm legado (intocado)**: fluxo vigente do `package.json` da raiz — `npm run bump:{patch,minor,major}` → commit (`chore: bump to vX.Y.Z`) → `npm publish` (`prepublishOnly` roda o build) → `git push`. A whitelist `files` do pacote publicado **não inclui** `crates/`, `go-services/`, `python-engine/`, `packages/` — decisão deliberada (zero inchaço até consumo real; ver gaps em `.agents/memoria/contexto.md`). Desde a v3.10.0 o job `publish` roda `npm publish --access public --provenance`: provenance OIDC do npm com permissão `id-token: write` escopada exclusivamente ao job (least privilege — o bloco de job sobrescreve o top-level read-only) e direção **fail-closed** (sem OIDC/provenance o release falha; nunca publica silenciosamente sem attestation). Provado em produção: `izanagi-ai@3.10.0` está no registry com attestation SLSA v1. Os adapters multi-CLI gerados por `izanagi export --cli …` também ganharam rodapé de proveniência **determinístico** (``Gerado pelo Izanagi AI: `izanagi export --cli <cli>``) — o caminho absoluto da máquina geradora saiu do output (`src/exporters.ts`), restaurando a idempotência byte-a-byte cross-machine.
534
+ 2. **Pacotes poliglotas (`@izanagi/sdk`, `@izanagi/cli-next`)**: ambos `"private": true` — não publicados. O CLI consome o SDK por caminho relativo. Integração SDK→CLI legado no npm é gap aberto registrado em memória.
535
+
536
+ ---
537
+
538
+ ## 9. Decisões arquiteturais (ADRs)
539
+
540
+ Resumo operativo abaixo. Texto integral e racional em `.agents/memoria/decisoes.md` — atenção: esse arquivo é memória local e está no `.gitignore` (`.agents/memoria/`), então existe apenas nesta máquina de desenvolvimento, não no repositório versionado.
541
+
542
+ | ADR | Decisão | Status / Gap |
543
+ |---|---|---|
544
+ | **ADR-001** Strangler Fig | Legado npm intocado e publicável; topologia nova cresce em `crates/`, `go-services/`, `python-engine/`, `packages/`; sem npm workspaces na raiz nesta fase | Vigente. Trade-off assumido: duplicação temporária de tooling vs. risco zero de regressão para usuários npm |
545
+ | **ADR-002** IPC = UDS + JSON-RPC 2.0 | Prompt master pedia gRPC; `protoc` ausente no ambiente. Mantido JSON-RPC 2.0 sobre UDS (já implementado e testado em Go); migração futura seria só de transporte (payloads preservados) | Vigente. **Gap**: gRPC condicionado ao provisionamento de `protoc` em CI; nada de gRPC existe no código hoje |
546
+ | **ADR-003** WASM feature-gated | Bindings wasm-bindgen sob feature `wasm` em `izanagi_core`; verificação local via `cargo check -p izanagi_core --features wasm`; build `.wasm` real (target `wasm32-unknown-unknown`) apenas em CI com rustup | Vigente. Local dev sem rustup/wasm-pack não gera `.wasm` (por design); job CI `wasm-build` cobre o fluxo |
547
+ | **ADR-004** Skills v2 via migrador determinístico | Conversor idempotente deriva SKILL.md v2 do conteúdo REAL original + biblioteca de Rationalizations/Red Flags por categoria; proibido inventar conteúdo; falha loud | Vigente. 106/106 migrados; `--check` anti-drift desde a v3.10.0 |
548
+ | **ADR-005** Agents v2 em YAML derivado | `.agents/agents/<slug>.yaml` gerado exclusivamente pelo `agent-migrator` a partir de `agents/*.json` (fonte canônica); idempotência byte-a-byte, round-trip interno, `--check` anti-drift; proibido editar YAML à mão; `.gitignore` afinado (memória local fora, YAMLs versionados) | Vigente. 22/22 em sincronia |
549
+
550
+ ### Lacunas conhecidas (consolidadas)
551
+
552
+ - **Socket default divergente** Go (`/tmp/izanagi-orch.sock`) vs. TS (`/tmp/izanagi-swarm.sock`), com nomes de env distintos — alinhar via env (seção 3.1); unificação de default não existe no código.
553
+ - **`-32005` reservado sem uso em fio**: colisão de socket falha o boot do processo, não vira resposta RPC.
554
+ - **Publicação npm dos pacotes novos**: pendente por decisão (fora do `files` do legado; pacotes `private`).
555
+ - **`cargo fmt`/clippy `-D warnings`** preparados para endurecer no CI após limpeza do código Rust.
556
+ - Drift documental pontual fora deste arquivo: `AGENTS.md` ainda menciona `agents/generated/c-systems-engineer.json`, que não existe mais na árvore (registrado em memória; correção pertence à frente responsável pelo AGENTS.md).
@@ -0,0 +1,72 @@
1
+ # Runtime: trabalho pendente
2
+
3
+ > Estado em **v3.17.0** (2026-09-02). Handoff vivo da rearquitetura do runtime. Nesta versão ele deixa de ter itens abertos: o que resta são escolhas com motivo registrado, não dívida.
4
+ >
5
+ > Passagem completa da rearquitetura (o que mudou, decisões, números medidos, por onde continuar): [`HANDOFF.md`](HANDOFF.md).
6
+ >
7
+ > Regra deste arquivo: só entra o que é gap **verificado no código**. Nada aqui é aspiracional sem lastro. Ao fechar um item, remover daqui **e** atualizar `ROADMAP.md` na mesma mudança.
8
+
9
+ ---
10
+
11
+ ## Estado
12
+
13
+ **Nenhum item aberto.** Os dezenove da lista original foram fechados (tabela no fim), e a última decisão pendente foi tomada.
14
+
15
+ ### A decisão que estava aberta: local-first
16
+
17
+ O Izanagi **não fica de pé**. Modo daemon, porta escutando e credencial em repouso estão fora de escopo por decisão, não por falta de implementação.
18
+
19
+ Quem agenda é o **cron ou o Task Scheduler do sistema**. O que faltava era o Izanagi ser consumível por eles, e isso foi entregue na v3.17.0:
20
+
21
+ ```bash
22
+ izanagi run "..." --json --notify-webhook=https://exemplo/hook
23
+ ```
24
+
25
+ - `--json`: um único objeto no stdout, saída humana silenciada, `console.error` preservado (erro real precisa chegar ao stderr do agendador).
26
+ - **código de saída com significado**: `0` concluiu, `1` falhou, `2` aguarda decisão humana. Aguardar aprovação não é falha e não deve alertar como falha.
27
+ - `--notify-webhook`: POST de fim de run, com uma retentativa. 4xx não é repetido (configuração errada não melhora repetindo), 5xx é.
28
+
29
+ O que isso NÃO dá: receber comando de fora. Para isso seria preciso autenticação, isolamento entre execuções e credenciais em repouso — e essas decisões de segurança precisariam ser revisitadas, não estendidas.
30
+
31
+ **A regra do payload:** o webhook leva metadado (status, score, tokens, custo, verificação por tarefa, nomes de artefato), **nunca conteúdo de artefato**. Um endpoint de notificação costuma ser um canal de equipe ou um serviço que ninguém auditou; mandar para lá o que os agentes produziram é exfiltração com aparência de conveniência. Quem quer o conteúdo usa `izanagi explain <run-id> --artifacts`, na máquina onde o run aconteceu.
32
+
33
+ ---
34
+
35
+ ## Limitações conhecidas que NÃO são gaps
36
+
37
+ Coisas que alguém pode confundir com dívida ao ler o código. São escolhas, e o motivo está registrado.
38
+
39
+ - **Rede não é isolada na sandbox de código.** O Permission Model do Node não cobre rede: um script executado por `code.execute` pode fazer requisição de saída. Existe um teste que MEDE isso e quebra se o comportamento mudar. A mitigação é a permissão `shell` no contrato, que a `PolicyEngine` nega a trust tier `generated` e `community`. Isolar rede de verdade exige container ou firewall de processo — outra ordem de dependência.
40
+ - **Templates do Planner não geram nós de tool.** O caminho `kind: 'tool'` existe, é seguro e testado; quem monta grafo com tool é o SDK ou uma decomposição externa. Colocar tool nos templates exige saber QUAL tool cada workflow precisa, e isso depende do projeto.
41
+ - **Decomposição por LLM no planejamento não tem caller.** `Commander.plan({ decompose })` aceita decomposição externa, mas nem CLI nem SDK injetam uma. O planejamento em produção é template + heurística, e é determinístico por isso: planejar não gasta token. (Decomposição em EXECUÇÃO é outra coisa e existe — ver `orchestration/subgraph.ts`.)
42
+ - **Token Benchmark mede plano, não execução.** Continua separado de propósito. Consumo real sai de `izanagi budget <run-id>` ou de `izanagi benchmark run --execute`.
43
+ - **Cache de validação economiza CPU, não token.** Nenhuma chamada de modelo é evitada, e por isso não aparece na telemetria de economia.
44
+ - **Estatística por domínio depende de volume.** `agentStats(agent, domain)` só decide com amostra mínima no domínio; abaixo disso vale o agregado global.
45
+ - **A medição de compressão não avalia qualidade.** Mede razão de tamanho, não se o que sobrou é o que importava. Avaliar isso exigiria gabarito anotado, e é por isso que a reavaliação de compressão neural fica condicionada a essa medida existir.
46
+ - **Sub-orquestração só é oferecida a papel `commander` em modo `autonomous`.** Não é limitação técnica: é onde o planejamento tem mais chance de subestimar escopo e onde o orçamento comporta a divisão.
47
+
48
+ ---
49
+
50
+ ## Fechados
51
+
52
+ | Item original | Fechado em | Como |
53
+ |---|---|---|
54
+ | 🔴 1. Degradação registrada mas nunca aplicada | `8a5d04c` | Cada degrau muda a execução: contexto pela metade, saída a 60%, `demoteRole`, concorrência dividida, opcionais cortadas, pausa por aprovação. Limiar por degrau e pressão pela maior razão **por fase**. |
55
+ | 🔴 2. Artefato sem content store | `8a5d04c` | Conteúdo em `.izanagi/state/artifacts/<runId>/`, com `contentRef`, teto de 512KB e truncamento declarado. |
56
+ | 🔴 3. Paralelismo sem teto de concorrência | `8a5d04c` | Pool com ordem preservada e falha isolada, default 3, reduzido pela degradação. |
57
+ | 🟡 4. Protocolo A2A e crítica sem caller | `c108699` | `interpretCritique`: crítica bloqueante reprova o nó criticado com correção mínima. `ConversationLog` por referência de artefato. `critique` virou ArtifactKind com formato obrigatório. |
58
+ | 🟡 5. Juiz semântico não injetado | `e977b7a` | `verification/judge.ts` no papel `worker`. Saída ilegível vira `inconclusive`, nunca reprovação. `--no-judge` desliga. |
59
+ | 🟡 6. Replan não passa pelo Commander | `e803837` | `Commander.replan`: troca agente → sobe papel → quebra em duas. Só o delta da falha; `changes` vazio quando não há alternativa. |
60
+ | 🟡 7. Memória não informa o planejamento | `96714ff` | Padrão de falha sobe o modo um degrau; agente com histórico ruim sai da disputa; consulta no Decision Journal. |
61
+ | 🟡 8. Skills resolvidas por run | `96714ff` | `resolveSkills` por tarefa (teto de 3), com memoização de manifesto. |
62
+ | 🔵 9. Cache além de resposta de modelo | `35ade52` | `validateArtifact` por `(kind, hash)`, teto 512, FIFO. Economiza CPU, não token. |
63
+ | 🔵 10. Producer headless não satisfazia schema | `35ade52` | `simulatedArtifact` derivado do schema real, com teste sobre TODO kind registrado. |
64
+ | 🔵 11. Estatística de agente global | `35ade52` | `AgentStats.byDomain`; ausência no domínio é ausência de sinal, não sinal ruim. |
65
+ | 🔵 12. Policy Engine fora do caminho de run | `641e198` | Nó `kind: 'tool'` por `ToolRegistry` + `PolicyEngine`, `TaskContract.permissions`, trust tier pela ORIGEM do arquivo. Corrigidos: `toText` devolvendo `undefined` e caminho relativo escapando da sandbox pelo cwd. |
66
+ | 🔵 13. Dashboard sem os campos novos | `6e0b0da` | Modo, verificação por tarefa, economia e conversa A2A no Run Explorer. Corrigidos os campos inexistentes na tabela de economia. |
67
+ | 🔵 14. Arena sem métricas de execução | `6e0b0da` | `benchmark run --execute`: verificação, recuperação, retries, healing, tokens e custo reais. Métrica ausente aparece como ausente. |
68
+ | 🔵 15. Sub-orquestradores hierárquicos | `5ae9b57` | `orchestration/subgraph.ts`: decomposição em execução com orçamento do pai DIVIDIDO, profundidade com teto do runtime, largura máxima 5, sub-tarefa não decompõe, pedido malformado recusado inteiro. |
69
+ | 🔵 16. `execute_code` | `1387bb0` | `tools/code-sandbox.ts`: processo isolado com Permission Model. FS restrito ao diretório de trabalho, subprocessos/workers/addons bloqueados, ambiente montado do zero, timeout com kill. Rede continua não isolada, e isso está testado como limite. |
70
+ | 🔵 17. Síntese de skills por trajetória | `4490dbf` | `evolution/trajectories.ts`: barra de recorrência (3 execuções verificadas), assinatura por caminho e não por objetivo, skill que declara o próprio limite. |
71
+ | ⏸ 19. Local-first ou serviço hospedado | `v3.17.0` | Decisão tomada: local-first. `--json`, código de saída com significado (0/1/2) e `--notify-webhook` fecham o caminho pelo agendador do SO, sem processo de longa duração. Payload leva metadado, nunca conteúdo. |
72
+ | 🔵 18. FTS5 e compressão neural | `4490dbf` | `izanagi benchmark memory` mede e aplica limiar declarado: busca p95 2.0ms sobre 296KB (FTS5 não se paga), compressão a 8.3% do original (neural não se justifica pelo tamanho). Bug encontrado pela medição: a busca tinha recall truncado em 4000 chars por arquivo. |
package/package.json CHANGED
@@ -1,99 +1,100 @@
1
- {
2
- "name": "izanagi-ai",
3
- "version": "3.17.0",
4
- "description": "Izanagi AI - Modular Skill-Oriented AI Prompt & Agent Framework for Autonomous Software Engineering",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "type": "module",
9
- "bin": {
10
- "izanagi": "bin/izanagi.js",
11
- "izanagi-ai": "bin/izanagi.js"
12
- },
13
- "files": [
14
- "dist",
15
- "bin",
16
- "agents",
17
- "architecture",
18
- "coding",
19
- "backend",
20
- "core",
21
- "database",
22
- "devops",
23
- "frontend",
24
- "memory",
25
- "optimization",
26
- "security",
27
- "skills",
28
- "teaching",
29
- "testing",
30
- ".opencode",
31
- ".claude",
32
- ".codex",
33
- ".cursor",
34
- ".github",
35
- ".kimi",
36
- "references",
37
- "benchmarks",
38
- "SYSTEM.md",
39
- "RULES.md",
40
- "AGENTS.md",
41
- "CLAUDE.md",
42
- "kimi.md",
43
- "CHANGELOG.md",
44
- "ROADMAP.md",
45
- ".manifest"
46
- ],
47
- "scripts": {
48
- "build": "tsc && node dist/scripts/generate-manifest.js",
49
- "postinstall": "node bin/postinstall.js",
50
- "build:clean": "node dist/scripts/build-clean.js",
51
- "verify": "node dist/scripts/verify-build.js && node --test \"dist/runtime/tests/*.test.js\"",
52
- "test": "npm run build && node --test \"dist/runtime/tests/*.test.js\"",
53
- "test:only": "node --test \"dist/runtime/tests/*.test.js\"",
54
- "release": "node dist/scripts/release.js",
55
- "release:patch": "node dist/scripts/release.js patch",
56
- "release:minor": "node dist/scripts/release.js minor",
57
- "release:major": "node dist/scripts/release.js major",
58
- "bump": "node dist/scripts/bump.js",
59
- "bump:patch": "node dist/scripts/bump.js patch",
60
- "bump:minor": "node dist/scripts/bump.js minor",
61
- "bump:major": "node dist/scripts/bump.js major",
62
- "prepublishOnly": "npm run build",
63
- "start": "node bin/izanagi.js",
64
- "doctor": "node bin/izanagi.js doctor",
65
- "list": "node bin/izanagi.js list"
66
- },
67
- "keywords": [
68
- "izanagi",
69
- "izanagi-ai",
70
- "ai",
71
- "agents",
72
- "prompt-engineering",
73
- "skills",
74
- "cli",
75
- "llm",
76
- "code-generation",
77
- "autonomous-agents"
78
- ],
79
- "author": "Pedro Henrique Sanches Leal",
80
- "license": "MIT",
81
- "engines": {
82
- "node": ">=18.0.0"
83
- },
84
- "devDependencies": {
85
- "@types/node": "^20.19.43",
86
- "typescript": "^5.9.3"
87
- },
88
- "repository": {
89
- "type": "git",
90
- "url": "git+https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai.git"
91
- },
92
- "dependencies": {
93
- "undici-types": "^6.21.0"
94
- },
95
- "bugs": {
96
- "url": "https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai/issues"
97
- },
98
- "homepage": "https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai#readme"
99
- }
1
+ {
2
+ "name": "izanagi-ai",
3
+ "version": "3.17.1",
4
+ "description": "Izanagi AI - Modular Skill-Oriented AI Prompt & Agent Framework for Autonomous Software Engineering",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "type": "module",
9
+ "bin": {
10
+ "izanagi": "bin/izanagi.js",
11
+ "izanagi-ai": "bin/izanagi.js"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "bin",
16
+ "agents",
17
+ "architecture",
18
+ "coding",
19
+ "backend",
20
+ "core",
21
+ "database",
22
+ "devops",
23
+ "frontend",
24
+ "memory",
25
+ "optimization",
26
+ "security",
27
+ "skills",
28
+ "teaching",
29
+ "testing",
30
+ ".opencode",
31
+ ".claude",
32
+ ".codex",
33
+ ".cursor",
34
+ ".github",
35
+ ".kimi",
36
+ "references",
37
+ "benchmarks",
38
+ "SYSTEM.md",
39
+ "RULES.md",
40
+ "AGENTS.md",
41
+ "CLAUDE.md",
42
+ "kimi.md",
43
+ "CHANGELOG.md",
44
+ "ROADMAP.md",
45
+ "docs",
46
+ ".manifest"
47
+ ],
48
+ "scripts": {
49
+ "build": "tsc && node dist/scripts/generate-manifest.js",
50
+ "postinstall": "node bin/postinstall.js",
51
+ "build:clean": "node dist/scripts/build-clean.js",
52
+ "verify": "node dist/scripts/verify-build.js && node --test \"dist/runtime/tests/*.test.js\"",
53
+ "test": "npm run build && node --test \"dist/runtime/tests/*.test.js\"",
54
+ "test:only": "node --test \"dist/runtime/tests/*.test.js\"",
55
+ "release": "node dist/scripts/release.js",
56
+ "release:patch": "node dist/scripts/release.js patch",
57
+ "release:minor": "node dist/scripts/release.js minor",
58
+ "release:major": "node dist/scripts/release.js major",
59
+ "bump": "node dist/scripts/bump.js",
60
+ "bump:patch": "node dist/scripts/bump.js patch",
61
+ "bump:minor": "node dist/scripts/bump.js minor",
62
+ "bump:major": "node dist/scripts/bump.js major",
63
+ "prepublishOnly": "npm run build",
64
+ "start": "node bin/izanagi.js",
65
+ "doctor": "node bin/izanagi.js doctor",
66
+ "list": "node bin/izanagi.js list"
67
+ },
68
+ "keywords": [
69
+ "izanagi",
70
+ "izanagi-ai",
71
+ "ai",
72
+ "agents",
73
+ "prompt-engineering",
74
+ "skills",
75
+ "cli",
76
+ "llm",
77
+ "code-generation",
78
+ "autonomous-agents"
79
+ ],
80
+ "author": "Pedro Henrique Sanches Leal",
81
+ "license": "MIT",
82
+ "engines": {
83
+ "node": ">=18.0.0"
84
+ },
85
+ "devDependencies": {
86
+ "@types/node": "^20.19.43",
87
+ "typescript": "^5.9.3"
88
+ },
89
+ "repository": {
90
+ "type": "git",
91
+ "url": "git+https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai.git"
92
+ },
93
+ "dependencies": {
94
+ "undici-types": "^6.21.0"
95
+ },
96
+ "bugs": {
97
+ "url": "https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai/issues"
98
+ },
99
+ "homepage": "https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai#readme"
100
+ }