@orkastery/cli 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/README.md +18 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
- package/adapters/claude-code/README.md +195 -5
- package/adapters/claude-code/agents/ork-check.md +1 -0
- package/adapters/claude-code/agents/ork-go.md +1 -0
- package/adapters/claude-code/agents/ork-goal.md +1 -0
- package/adapters/claude-code/agents/ork-master.md +1 -0
- package/adapters/claude-code/agents/ork-plan.md +1 -0
- package/adapters/claude-code/agents/ork-ship.md +1 -0
- package/adapters/claude-code/hooks/hooks.json +2 -1
- package/adapters/claude-code/hooks/ork-guard.js +15 -1
- package/adapters/claude-code/hooks/ork-resposta.js +91 -0
- package/adapters/claude-code/hooks/ork-sensor.js +18 -2
- package/adapters/claude-code/hooks/quota-signal.js +14 -0
- package/adapters/claude-code/mods/autoridade.json +56 -0
- package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
- package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
- package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
- package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
- package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
- package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
- package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
- package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
- package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
- package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
- package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
- package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
- package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +121 -0
- package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
- package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
- package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
- package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
- package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
- package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
- package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
- package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
- package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
- package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
- package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
- package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
- package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
- package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
- package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
- package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
- package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
- package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
- package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
- package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
- package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
- package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
- package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
- package/adapters/codex/skills/ork/SKILL.md +2 -0
- package/adapters/hermes/README.md +64 -1
- package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
- package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
- package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
- package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
- package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
- package/adapters/hermes/hermes.plugin.json +4 -0
- package/adapters/hermes/hitl-ingress/__init__.py +101 -8
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +3 -3
- package/adapters/openclaw/README.md +83 -10
- package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
- package/adapters/openclaw/dist/hitl-ingress.js +106 -9
- package/adapters/openclaw/dist/index.js +86 -0
- package/adapters/openclaw/openclaw.plugin.json +34 -4
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +103 -9
- package/adapters/openclaw/src/index.ts +94 -0
- package/assets/adapters-en/claude-code/README.md +403 -0
- package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
- package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
- package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
- package/assets/adapters-en/claude-code/commands/check.md +46 -0
- package/assets/adapters-en/claude-code/commands/go.md +46 -0
- package/assets/adapters-en/claude-code/commands/goal.md +55 -0
- package/assets/adapters-en/claude-code/commands/master.md +54 -0
- package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
- package/assets/adapters-en/claude-code/commands/ork.md +126 -0
- package/assets/adapters-en/claude-code/commands/plan.md +47 -0
- package/assets/adapters-en/claude-code/commands/ship.md +45 -0
- package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
- package/assets/adapters-en/hermes/README.md +273 -0
- package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
- package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
- package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
- package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
- package/assets/docs-en/produto/README.md +14 -0
- package/assets/docs-en/produto/_modelo-feature.md +62 -0
- package/assets/docs-en/roadmap/README.md +14 -0
- package/assets/docs-en/roadmap/_modelo-item.md +75 -0
- package/assets/references-en/README.md +25 -0
- package/assets/references-en/code-review-axes.md +82 -0
- package/assets/references-en/definition-of-done.md +74 -0
- package/assets/references-en/performance-checklist.md +53 -0
- package/assets/references-en/security-checklist.md +101 -0
- package/assets/references-en/testing-patterns.md +51 -0
- package/assets/security-scan/defaults/.golangci.yml +2 -0
- package/assets/security-scan/defaults/eslint.config.mjs +11 -0
- package/assets/security-scan/defaults/gitleaks.toml +3 -0
- package/assets/security-scan/defaults/ruff.toml +1 -0
- package/assets/security-scan/tools-agil.json +87 -0
- package/assets/security-scan/tools.json +625 -0
- package/assets/skills-en/core/onboarding/SKILL.md +58 -0
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
- package/assets/skills-en/core/thread-state/SKILL.md +88 -0
- package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
- package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
- package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
- package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
- package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
- package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
- package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
- package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
- package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
- package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
- package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
- package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
- package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
- package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
- package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
- package/dist/adapters/claude-bg.js +193 -15
- package/dist/adapters/codex-controller-worker.js +12 -5
- package/dist/adapters/codex-events.js +16 -4
- package/dist/adapters/codex.js +13 -2
- package/dist/agents-md.js +24 -15
- package/dist/atualizar-branch.js +245 -0
- package/dist/auditoria.js +13 -11
- package/dist/auditrun.js +68 -48
- package/dist/autorizacao-duravel.js +327 -0
- package/dist/board.js +98 -43
- package/dist/branch-de-estado.js +39 -9
- package/dist/busca-semantica.js +7 -5
- package/dist/catalogo.js +35 -1
- package/dist/changelog-reconciliacao.js +290 -0
- package/dist/check-agil.js +500 -0
- package/dist/check-modo.js +41 -0
- package/dist/check-paralelo.js +183 -0
- package/dist/ci.js +255 -46
- package/dist/ciclos.js +8 -6
- package/dist/claim-lint.js +12 -8
- package/dist/claims-conferir.js +350 -0
- package/dist/claims.js +13 -10
- package/dist/company-brain-client.js +45 -3
- package/dist/company-brain-journal.js +2 -1
- package/dist/company-brain-migration.js +47 -6
- package/dist/conducao-batida.js +759 -0
- package/dist/conducao-sentinela.js +405 -0
- package/dist/conducao-texto.js +12 -18
- package/dist/conducao.js +206 -59
- package/dist/conhecimento-consulta.js +270 -0
- package/dist/conhecimento.js +514 -0
- package/dist/conta-esgotada.js +127 -0
- package/dist/dado-privado.js +816 -0
- package/dist/decisao-autonoma.js +5 -4
- package/dist/demo.js +14 -12
- package/dist/dependencias-da-worktree.js +25 -0
- package/dist/divida.js +38 -36
- package/dist/docs.js +103 -82
- package/dist/doctor-forja.js +345 -0
- package/dist/doctor-pulse-cron.js +294 -27
- package/dist/doctor-rede.js +18 -17
- package/dist/doctor.js +278 -116
- package/dist/dsn-da-memoria.js +417 -0
- package/dist/entrega-por-mod.js +503 -0
- package/dist/entrega-pr.js +158 -57
- package/dist/escopo-escrita.js +10 -1
- package/dist/esgotamentos.js +13 -11
- package/dist/estado-thread.js +42 -17
- package/dist/evalrunner.js +35 -32
- package/dist/experiencia-instalacao.js +45 -25
- package/dist/fabrica-batida.js +323 -0
- package/dist/fabrica-estado.js +49 -16
- package/dist/fabrica-publicar.js +3 -1
- package/dist/fila-pesada.js +444 -0
- package/dist/fix.js +24 -21
- package/dist/forja/adaptador.js +6 -0
- package/dist/forja/ambiente-de-ci.js +27 -0
- package/dist/forja/api.js +256 -0
- package/dist/forja/cache.js +89 -0
- package/dist/forja/cli.js +60 -0
- package/dist/forja/contrato.js +9 -0
- package/dist/forja/endereco.js +43 -0
- package/dist/forja/estado.js +22 -0
- package/dist/forja/executor.js +73 -0
- package/dist/forja/github/ci.js +95 -0
- package/dist/forja/github/dono-da-rede.js +18 -0
- package/dist/forja/github/metadados.js +15 -0
- package/dist/forja/github/pedidos.js +200 -0
- package/dist/forja/gitlab/ci.js +141 -0
- package/dist/forja/gitlab/consultas.js +59 -0
- package/dist/forja/gitlab/dono-da-rede.js +43 -0
- package/dist/forja/gitlab/metadados.js +15 -0
- package/dist/forja/gitlab/pedidos-abertos.js +158 -0
- package/dist/forja/gitlab/pedidos.js +141 -0
- package/dist/forja/produtor.js +32 -0
- package/dist/forja/registro.js +31 -0
- package/dist/forja/resolver.js +121 -0
- package/dist/forja/texto.js +13 -0
- package/dist/forja/versao.js +71 -0
- package/dist/forja.js +124 -81
- package/dist/gates.js +3 -28
- package/dist/handoff.js +33 -19
- package/dist/hitl-contract.js +46 -43
- package/dist/hitl-curto.js +37 -25
- package/dist/hitl-gates.js +13 -11
- package/dist/hitl-local-receipt.js +53 -0
- package/dist/hitl-local.js +11 -2
- package/dist/hitl-lock.js +5 -11
- package/dist/hitl-public-receipt.js +11 -0
- package/dist/hitl-resumo.js +72 -3
- package/dist/hitl-sessions.js +62 -9
- package/dist/hitl-tempo-parado.js +4 -4
- package/dist/hitl-texto-livre.js +7 -4
- package/dist/hitl.js +63 -64
- package/dist/horario.js +30 -7
- package/dist/hosts.js +155 -134
- package/dist/impedimento.js +108 -14
- package/dist/index.js +1421 -1019
- package/dist/indice-vetorial.js +14 -12
- package/dist/indice.js +7 -1
- package/dist/init.js +54 -49
- package/dist/instabilidade.js +144 -0
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +213 -88
- package/dist/intelligence-graph-contexto.js +56 -17
- package/dist/intelligence-graph-contract.js +2 -1
- package/dist/intelligence-graph-extract-md.js +56 -4
- package/dist/intelligence-graph-extract-ts.js +71 -3
- package/dist/intelligence-graph-query.js +96 -34
- package/dist/leases.js +19 -18
- package/dist/ledger-stats.js +17 -16
- package/dist/ledger.js +46 -2
- package/dist/licoes.js +12 -11
- package/dist/liveness.js +6 -3
- package/dist/locale-accounts.js +220 -0
- package/dist/locale-adapter.js +291 -0
- package/dist/locale-ajuda.js +833 -0
- package/dist/locale-audit.js +199 -0
- package/dist/locale-claims.js +213 -0
- package/dist/locale-conducao.js +138 -0
- package/dist/locale-conhecimento.js +181 -0
- package/dist/locale-decisao.js +205 -0
- package/dist/locale-docs.js +230 -0
- package/dist/locale-estado.js +101 -0
- package/dist/locale-forja.js +290 -0
- package/dist/locale-gerados.js +165 -0
- package/dist/locale-grafo.js +129 -0
- package/dist/locale-master.js +182 -0
- package/dist/locale-network.js +524 -0
- package/dist/locale-onboarding.js +92 -0
- package/dist/locale-operacao-restante.js +931 -0
- package/dist/locale-phase.js +151 -0
- package/dist/locale-projetos.js +100 -0
- package/dist/locale-prompts.js +194 -0
- package/dist/locale-pulse.js +349 -0
- package/dist/locale-reservas.js +87 -0
- package/dist/locale-retry.js +524 -0
- package/dist/locale-roadmap.js +102 -0
- package/dist/locale-security-scan.js +69 -0
- package/dist/locale-setup.js +192 -0
- package/dist/locale-ship.js +597 -0
- package/dist/locale-thread.js +421 -0
- package/dist/locale-verify.js +201 -0
- package/dist/locale-worktree.js +246 -0
- package/dist/locale.js +1258 -0
- package/dist/maestro-runtime.js +22 -3
- package/dist/manifest.js +415 -13
- package/dist/maquina-ociosa.js +211 -0
- package/dist/maquina.js +31 -7
- package/dist/master-digest.js +6 -1
- package/dist/master-nota-local.js +200 -0
- package/dist/master-nota.js +14 -8
- package/dist/master.js +139 -65
- package/dist/mcp-artifacts.js +11 -2
- package/dist/mcp-conhecimento.js +52 -0
- package/dist/mcp-experiencia.js +26 -5
- package/dist/mcp-git.js +23 -6
- package/dist/mcp-grafo.js +7 -4
- package/dist/mcp-install.js +73 -8
- package/dist/mcp-noctum.js +101 -0
- package/dist/mcp-server.js +90 -16
- package/dist/mcp-ship-transporte.js +977 -0
- package/dist/mcp-ship.js +71 -25
- package/dist/mcp-transportes.js +17 -0
- package/dist/mcp-verify.js +6 -1
- package/dist/memoria.js +63 -58
- package/dist/modos-migracao.js +8 -6
- package/dist/modos.js +20 -24
- package/dist/network-roadmap.js +90 -51
- package/dist/noctum-aceite.js +789 -0
- package/dist/noctum-arco.js +1418 -0
- package/dist/noctum-capacidade.js +141 -0
- package/dist/noctum-changelog.js +399 -0
- package/dist/noctum-cli.js +482 -0
- package/dist/noctum-coordenacao.js +1225 -0
- package/dist/noctum-entrega.js +1169 -0
- package/dist/noctum-envelope.js +1046 -0
- package/dist/noctum-execucao.js +376 -0
- package/dist/noctum-fechamento.js +405 -0
- package/dist/noctum-fila.js +314 -0
- package/dist/noctum-guarda.js +256 -0
- package/dist/noctum-integracao.js +507 -0
- package/dist/noctum-maquinas.js +383 -0
- package/dist/noctum-medicao.js +450 -0
- package/dist/noctum-modo.js +362 -0
- package/dist/noctum-pergunta-canal.js +96 -0
- package/dist/noctum-pergunta.js +115 -0
- package/dist/noctum-provas.js +838 -0
- package/dist/noctum-reconciliacao.js +591 -0
- package/dist/noctum-registro.js +215 -0
- package/dist/noctum-relatorio.js +827 -0
- package/dist/noctum-resposta.js +207 -0
- package/dist/noctum-sessoes-em-voo.js +93 -0
- package/dist/noctum-supervisao.js +649 -0
- package/dist/noctum-terminal.js +459 -0
- package/dist/noctum-transporte.js +655 -0
- package/dist/noctum-vigia.js +639 -0
- package/dist/ocupacao.js +32 -3
- package/dist/onboarding.js +56 -26
- package/dist/orkmind.js +48 -25
- package/dist/orquestracao.js +44 -47
- package/dist/parado-no-condutor.js +174 -127
- package/dist/phase.js +144 -63
- package/dist/policies.js +37 -4
- package/dist/portfolio.js +4 -2
- package/dist/postura-local.js +235 -0
- package/dist/preflight.js +11 -10
- package/dist/procedencia.js +220 -0
- package/dist/projeto-alvo.js +186 -24
- package/dist/prompts.js +140 -42
- package/dist/prova-minima.js +5 -6
- package/dist/pulse-cadencia.js +5 -4
- package/dist/pulse-consentimento.js +53 -1
- package/dist/pulse-delivery.js +151 -24
- package/dist/pulse-resposta.js +368 -4
- package/dist/pulse.js +188 -22
- package/dist/ratelimit.js +16 -6
- package/dist/recall.js +14 -13
- package/dist/redacao-saida.js +63 -0
- package/dist/rede-adesao.js +13 -8
- package/dist/rede-forja.js +108 -24
- package/dist/rede-status.js +66 -47
- package/dist/rede.js +86 -46
- package/dist/retomada-checkpoint.js +101 -0
- package/dist/retry.js +451 -212
- package/dist/roadmap-reservas.js +45 -28
- package/dist/roadmap-status.js +129 -33
- package/dist/runtime-ambiente.js +5 -0
- package/dist/runtime-context.js +284 -32
- package/dist/runtime-escada.js +423 -0
- package/dist/runtime-profiles.js +103 -46
- package/dist/runtimes.js +2 -1
- package/dist/saida-segura.js +3 -2
- package/dist/security-scan/agil.js +355 -0
- package/dist/security-scan/cli.js +76 -0
- package/dist/security-scan/compare.js +149 -0
- package/dist/security-scan/config.js +93 -0
- package/dist/security-scan/detect.js +97 -0
- package/dist/security-scan/executor.js +188 -0
- package/dist/security-scan/guard.js +180 -0
- package/dist/security-scan/imagem-de-lint.js +96 -0
- package/dist/security-scan/normalize/actionlint.js +12 -0
- package/dist/security-scan/normalize/eslint.js +12 -0
- package/dist/security-scan/normalize/gitleaks.js +13 -0
- package/dist/security-scan/normalize/golangci-lint.js +13 -0
- package/dist/security-scan/normalize/govulncheck.js +36 -0
- package/dist/security-scan/normalize/index.js +25 -0
- package/dist/security-scan/normalize/npm-audit.js +30 -0
- package/dist/security-scan/normalize/osv-scanner.js +32 -0
- package/dist/security-scan/normalize/oxlint.js +51 -0
- package/dist/security-scan/normalize/pip-audit.js +16 -0
- package/dist/security-scan/normalize/ruff.js +12 -0
- package/dist/security-scan/normalize/semgrep.js +20 -0
- package/dist/security-scan/normalize/trivy.js +33 -0
- package/dist/security-scan/normalize/util.js +204 -0
- package/dist/security-scan/normalize/zizmor.js +19 -0
- package/dist/security-scan/report.js +156 -0
- package/dist/security-scan/run.js +448 -0
- package/dist/security-scan/tools.js +62 -0
- package/dist/security-scan/trabalhador.js +74 -0
- package/dist/security-scan/types.js +15 -0
- package/dist/session-events.js +26 -5
- package/dist/session-watcher-claude.js +81 -20
- package/dist/session-watcher.js +340 -42
- package/dist/sessoes-contas.js +10 -1
- package/dist/sessoes-inventario.js +1 -1
- package/dist/sessoes.js +25 -23
- package/dist/setup.js +59 -58
- package/dist/ship-publicar.js +971 -0
- package/dist/ship.js +243 -97
- package/dist/steal.js +77 -0
- package/dist/superficie.js +14 -11
- package/dist/thread-close.js +12 -11
- package/dist/thread.js +274 -100
- package/dist/tokens.js +15 -11
- package/dist/trabalho-thread.js +297 -0
- package/dist/transporte-do-canal.js +189 -0
- package/dist/types.js +12 -1
- package/dist/util.js +13 -3
- package/dist/varredura-acoes.js +507 -0
- package/dist/verify.js +608 -76
- package/dist/vida-da-thread.js +254 -0
- package/dist/worktree-local.js +167 -0
- package/dist/worktree.js +99 -83
- package/dist/yaml.js +27 -8
- package/eval/casos/check-quality.json +77 -0
- package/eval/casos/security-auditor.json +148 -0
- package/eval/casos/security-remediation.json +161 -0
- package/eval/fixtures/security-scan/README.md +8 -0
- package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/go/Dockerfile +4 -0
- package/eval/fixtures/security-scan/go/README.md +4 -0
- package/eval/fixtures/security-scan/go/config.go +4 -0
- package/eval/fixtures/security-scan/go/go.mod +5 -0
- package/eval/fixtures/security-scan/go/go.sum +2 -0
- package/eval/fixtures/security-scan/go/main.go +31 -0
- package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/js/Dockerfile +3 -0
- package/eval/fixtures/security-scan/js/README.md +4 -0
- package/eval/fixtures/security-scan/js/package-lock.json +844 -0
- package/eval/fixtures/security-scan/js/package.json +10 -0
- package/eval/fixtures/security-scan/js/src/config.js +4 -0
- package/eval/fixtures/security-scan/js/src/server.js +17 -0
- package/eval/fixtures/security-scan/js/src/util.ts +4 -0
- package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
- package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/python/Dockerfile +3 -0
- package/eval/fixtures/security-scan/python/README.md +4 -0
- package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
- package/eval/fixtures/security-scan/python/app/config.py +2 -0
- package/eval/fixtures/security-scan/python/app/main.py +19 -0
- package/eval/fixtures/security-scan/python/requirements.txt +1 -0
- package/package.json +9 -4
- package/references/security-checklist.md +3 -3
- package/schemas/code-artifact-graph.v1.schema.json +2 -1
- package/skills/README.md +1 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/check-quality/SKILL.md +16 -0
- package/skills/phases/go-implementation/SKILL.md +6 -0
- package/skills/phases/security-remediation/SKILL.md +70 -0
- package/skills/reviewers/security-auditor/SKILL.md +25 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.compararLacunas = exports.detalheDoConhecimento = exports.LIMITES_DO_CONHECIMENTO = exports.REFERENCIA_DE_DECISAO = exports.NOME_DE_COLECAO = exports.ID_DE_DOCUMENTO = exports.CONTRATO_CONHECIMENTO = void 0;
|
|
37
|
+
exports.lacunaDoConhecimento = lacunaDoConhecimento;
|
|
38
|
+
exports.lerConhecimento = lerConhecimento;
|
|
39
|
+
/**
|
|
40
|
+
* RM-026 K7 (fatia 1): conhecimento escrito, no contrato `ork.conhecimento/v1`.
|
|
41
|
+
*
|
|
42
|
+
* Cada documento é um Markdown versionado na pasta que o `orkastery.yaml` declara (`conhecimento.dir`), com
|
|
43
|
+
* frontmatter fechado: `id` (`doc-...`), `titulo`, `colecoes` e, opcional, `referencias` a ids do Brain e a
|
|
44
|
+
* decisões `thread#linha` do ledger. A coleção é o nome no frontmatter, sem arquivo próprio.
|
|
45
|
+
*
|
|
46
|
+
* Só leitura. Documento inválido ou referência que não confere vira lacuna tipada, nunca resposta (D4). A pasta
|
|
47
|
+
* vem com o repositório e segue a fronteira da RM-047 (D6): relativa, dentro da raiz pelo caminho real, sem
|
|
48
|
+
* seguir link e sem executar nada. O leitor confere a decisão no ledger canônico e o id do Brain só pela forma
|
|
49
|
+
* (D5); a conferência por `get` mora na consulta (`conhecimento-consulta.ts`, fatia 2), a porta pública da CLI e das
|
|
50
|
+
* tools MCP. O detalhe das lacunas sai pelo catálogo (família `conhecimento`). Contrato:
|
|
51
|
+
* docs/referencia/contratos/conhecimento-rm026.md.
|
|
52
|
+
*/
|
|
53
|
+
const fs = __importStar(require("node:fs"));
|
|
54
|
+
const path = __importStar(require("node:path"));
|
|
55
|
+
const node_buffer_1 = require("node:buffer");
|
|
56
|
+
const company_brain_journal_1 = require("./company-brain-journal");
|
|
57
|
+
const docs_1 = require("./docs");
|
|
58
|
+
const locale_1 = require("./locale");
|
|
59
|
+
const portfolio_1 = require("./portfolio");
|
|
60
|
+
const saida_segura_1 = require("./saida-segura");
|
|
61
|
+
const thread_1 = require("./thread");
|
|
62
|
+
const yaml_1 = require("./yaml");
|
|
63
|
+
exports.CONTRATO_CONHECIMENTO = 'ork.conhecimento/v1';
|
|
64
|
+
/** D3: a forma do id do documento (a regra dos ids do portfólio), da coleção e da citação de decisão. */
|
|
65
|
+
exports.ID_DE_DOCUMENTO = /^doc-[a-z0-9][a-z0-9-]{2,47}$/;
|
|
66
|
+
exports.NOME_DE_COLECAO = /^[a-z0-9][a-z0-9-]{0,47}$/;
|
|
67
|
+
exports.REFERENCIA_DE_DECISAO = /^([a-zA-Z0-9][a-zA-Z0-9._-]{0,79})#([1-9][0-9]{0,8})$/;
|
|
68
|
+
const LIMITE_DO_TITULO = 160;
|
|
69
|
+
const COLECOES_POR_DOCUMENTO = 16;
|
|
70
|
+
const REFERENCIAS_POR_LISTA = 64;
|
|
71
|
+
/** D2: as chaves do frontmatter; qualquer outra invalida o documento. */
|
|
72
|
+
const CHAVES_DO_DOCUMENTO = ['id', 'titulo', 'colecoes', 'referencias'];
|
|
73
|
+
const CHAVES_DAS_REFERENCIAS = ['brain', 'decisoes'];
|
|
74
|
+
/** D5: as linhas do ledger que são decisão, as do dossiê; `human_decision` é relato sem recibo e não conta. */
|
|
75
|
+
const TIPOS_DE_DECISAO = ['autonomous_decision', 'hitl_requested', 'human_gate'];
|
|
76
|
+
/** D6: pastas do repositório que nunca guardam conhecimento, sem distinguir caixa (o disco do macOS não distingue). */
|
|
77
|
+
const PASTAS_RESERVADAS = ['.git', '.orkastery'];
|
|
78
|
+
const reservada = (segmento) => PASTAS_RESERVADAS.includes(segmento.toLowerCase());
|
|
79
|
+
/** D10: o invisível é o do `saida-segura.ts`, a regra única do núcleo para texto alheio (ZWJ e seletores de emoji valem). */
|
|
80
|
+
const INVISIVEIS = new RegExp(saida_segura_1.INVISIVEL.source, 'gu');
|
|
81
|
+
exports.LIMITES_DO_CONHECIMENTO = Object.freeze({
|
|
82
|
+
entradas: 5000, profundidade: 8, bytesPorDocumento: 1024 * 1024, bytesDoFrontmatter: 16 * 1024,
|
|
83
|
+
bytesNoTotal: 32 * 1024 * 1024, bytesDoLedger: 16 * 1024 * 1024, bytesDosLedgers: 64 * 1024 * 1024,
|
|
84
|
+
getsDoBrain: 100, msDaConferencia: 60 * 1000,
|
|
85
|
+
});
|
|
86
|
+
const comparar = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
87
|
+
const ehMapa = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
|
|
88
|
+
/** Texto que veio do repositório, pronto para a resposta: numa linha, sem invisível e, com teto, cortado sem partir caractere. */
|
|
89
|
+
const limpo = (v, teto = Infinity) => Array.from((0, saida_segura_1.emUmaLinha)(v)).slice(0, teto).join('');
|
|
90
|
+
const relativo = (raizReal, abs) => path.relative(raizReal, abs).split(path.sep).join('/');
|
|
91
|
+
/**
|
|
92
|
+
* O detalhe de uma lacuna, pelo catálogo (D13 da fatia 2): nasce no locale ativo, o pt-BR do `--json` e do MCP, e a
|
|
93
|
+
* impressão do comando coberto o remonta no locale dela.
|
|
94
|
+
*/
|
|
95
|
+
const detalheDoConhecimento = (montar) => (0, locale_1.textoDoCatalogo)((m) => montar(m.conhecimento.lacunas));
|
|
96
|
+
exports.detalheDoConhecimento = detalheDoConhecimento;
|
|
97
|
+
const t = exports.detalheDoConhecimento;
|
|
98
|
+
/** `stat` que nunca lança: a pasta que some ou não abre vale como ausente. */
|
|
99
|
+
const statOuNulo = (p) => { try {
|
|
100
|
+
return fs.statSync(p, { throwIfNoEntry: false }) ?? null;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
} };
|
|
105
|
+
/** Uma lacuna, com a referência como escrita, numa linha e cortada (a mesma regra no leitor e na consulta). */
|
|
106
|
+
function lacunaDoConhecimento(codigo, detalhe, onde = {}) {
|
|
107
|
+
return { codigo, arquivo: onde.arquivo ?? null, documento: onde.documento ?? null,
|
|
108
|
+
referencia: typeof onde.referencia === 'string' ? limpo(onde.referencia, 200) : null, detalhe };
|
|
109
|
+
}
|
|
110
|
+
const lacuna = lacunaDoConhecimento;
|
|
111
|
+
/** A ordem estável das lacunas: por arquivo, código e referência. */
|
|
112
|
+
const compararLacunas = (a, b) => comparar(a.arquivo ?? '', b.arquivo ?? '') || comparar(a.codigo, b.codigo) || comparar(a.referencia ?? '', b.referencia ?? '');
|
|
113
|
+
exports.compararLacunas = compararLacunas;
|
|
114
|
+
/**
|
|
115
|
+
* D6: a pasta declarada, pelo caminho real. A forma recusa antes de tocar o disco (vazia, absoluta, `..`, `\`,
|
|
116
|
+
* invisível, a própria raiz, `.git` e `.orkastery`); o caminho real, com os links resolvidos, precisa ficar dentro
|
|
117
|
+
* da raiz.
|
|
118
|
+
*/
|
|
119
|
+
function pastaDoConhecimento(raiz, dir) {
|
|
120
|
+
const segmentos = dir.split('/').filter((s) => s !== '' && s !== '.');
|
|
121
|
+
if (path.isAbsolute(dir) || dir.includes('\\') || saida_segura_1.INVISIVEL.test(dir) || !segmentos.length || segmentos.includes('..') ||
|
|
122
|
+
reservada(segmentos[0])) {
|
|
123
|
+
return lacuna('conhecimento.dir-invalido', t((l) => l.dirForma));
|
|
124
|
+
}
|
|
125
|
+
let raizReal, real;
|
|
126
|
+
try {
|
|
127
|
+
raizReal = fs.realpathSync(raiz);
|
|
128
|
+
real = fs.realpathSync(path.join(raizReal, ...segmentos));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return lacuna('conhecimento.dir-ausente', t((l) => l.dirNaoAbre));
|
|
132
|
+
}
|
|
133
|
+
const rel = path.relative(raizReal, real);
|
|
134
|
+
if (rel === '..' || rel.startsWith('..' + path.sep) || path.isAbsolute(rel)) {
|
|
135
|
+
return lacuna('conhecimento.dir-fora-da-raiz', t((l) => l.dirForaDaRaiz));
|
|
136
|
+
}
|
|
137
|
+
if (rel === '' || reservada(rel.split(path.sep)[0]) || saida_segura_1.INVISIVEL.test(rel)) {
|
|
138
|
+
return lacuna('conhecimento.dir-invalido', t((l) => l.dirReal));
|
|
139
|
+
}
|
|
140
|
+
if (!statOuNulo(real)?.isDirectory())
|
|
141
|
+
return lacuna('conhecimento.dir-ausente', t((l) => l.dirNaoEPasta));
|
|
142
|
+
return { real, raizReal };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Varre a pasta sem seguir link (D6) e sem ler entrada oculta (D8). Devolve os candidatos a documento, ou o
|
|
146
|
+
* detalhe do teto estourado (D7), que falha fechado. Entrada que não abre vira lacuna, nunca exceção.
|
|
147
|
+
*/
|
|
148
|
+
function varrer(real, raizReal, limites, lacunas) {
|
|
149
|
+
const candidatos = [];
|
|
150
|
+
const pilha = [{ abs: real, profundidade: 0 }];
|
|
151
|
+
let entradas = 0;
|
|
152
|
+
while (pilha.length) {
|
|
153
|
+
const atual = pilha.pop();
|
|
154
|
+
// Uma pasta trocada por link depois de entrar na pilha não leva a varredura para fora: o caminho real é
|
|
155
|
+
// conferido logo antes da listagem. Num clone parado não há troca; a conferência fecha a janela larga.
|
|
156
|
+
let realDaPasta;
|
|
157
|
+
try {
|
|
158
|
+
realDaPasta = fs.realpathSync(atual.abs);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
realDaPasta = null;
|
|
162
|
+
}
|
|
163
|
+
if (realDaPasta !== atual.abs) {
|
|
164
|
+
lacunas.push(lacuna('documento.link', t((l) => l.link), { arquivo: relativo(raizReal, atual.abs) }));
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
let nomes;
|
|
168
|
+
try {
|
|
169
|
+
nomes = fs.readdirSync(atual.abs, { encoding: 'buffer' }).sort(Buffer.compare);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
lacunas.push(lacuna('documento.nao-regular', t((l) => l.pastaNaoAbriu), { arquivo: relativo(raizReal, atual.abs) }));
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
for (const bruto of nomes) {
|
|
176
|
+
if (bruto[0] === 0x2e)
|
|
177
|
+
continue;
|
|
178
|
+
if (++entradas > limites.entradas)
|
|
179
|
+
return { teto: t((l) => l.limiteEntradas(limites.entradas)) };
|
|
180
|
+
const nome = bruto.toString('utf8');
|
|
181
|
+
if (!Buffer.from(nome, 'utf8').equals(bruto) || saida_segura_1.INVISIVEL.test(nome)) {
|
|
182
|
+
lacunas.push(lacuna('documento.nome-invalido', t((l) => l.nomeInvalido), { arquivo: relativo(raizReal, path.join(atual.abs, nome.replace(INVISIVEIS, '?'))) }));
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const abs = path.join(atual.abs, nome), arquivo = relativo(raizReal, abs);
|
|
186
|
+
let st;
|
|
187
|
+
try {
|
|
188
|
+
st = fs.lstatSync(abs, { throwIfNoEntry: false });
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
lacunas.push(lacuna('documento.nao-regular', t((l) => l.entradaNaoAbriu), { arquivo }));
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (!st)
|
|
195
|
+
continue;
|
|
196
|
+
if (st.isSymbolicLink()) {
|
|
197
|
+
lacunas.push(lacuna('documento.link', t((l) => l.link), { arquivo }));
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (st.isDirectory()) {
|
|
201
|
+
if (atual.profundidade + 1 > limites.profundidade)
|
|
202
|
+
return { teto: t((l) => l.limiteNiveis(limites.profundidade)) };
|
|
203
|
+
pilha.push({ abs, profundidade: atual.profundidade + 1 });
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (!(0, docs_1.ehPaginaDeDocs)(nome))
|
|
207
|
+
continue;
|
|
208
|
+
if (!st.isFile()) {
|
|
209
|
+
lacunas.push(lacuna('documento.nao-regular', t((l) => l.naoRegular), { arquivo }));
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
candidatos.push({ abs, arquivo, st });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return candidatos;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Lê um arquivo comum sem seguir link (`O_NOFOLLOW`) e sem travar em FIFO (`O_NONBLOCK`), conferindo que é o
|
|
219
|
+
* mesmo do `lstat` e que cabe no teto. Devolve os bytes ou o motivo. Com `crescer` (o ledger, que só recebe linha
|
|
220
|
+
* no fim), vale o que existia no `fstat`, mesmo que o arquivo cresça durante a leitura; o documento que muda
|
|
221
|
+
* durante a leitura não vale.
|
|
222
|
+
*/
|
|
223
|
+
function lerArquivo(abs, st, teto, crescer = false) {
|
|
224
|
+
let fd;
|
|
225
|
+
try {
|
|
226
|
+
fd = fs.openSync(abs, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
return e.code === 'ELOOP' ? 'link' : 'nao-regular';
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
const f = fs.fstatSync(fd);
|
|
233
|
+
if (!f.isFile() || f.dev !== st.dev || f.ino !== st.ino)
|
|
234
|
+
return 'nao-regular';
|
|
235
|
+
if (f.size > teto)
|
|
236
|
+
return 'grande';
|
|
237
|
+
const bytes = Buffer.alloc(crescer ? f.size : f.size + 1);
|
|
238
|
+
let lidos = 0, n;
|
|
239
|
+
while (lidos < bytes.length && (n = fs.readSync(fd, bytes, lidos, bytes.length - lidos, null)) > 0)
|
|
240
|
+
lidos += n;
|
|
241
|
+
if (crescer)
|
|
242
|
+
return bytes.subarray(0, lidos);
|
|
243
|
+
return lidos === f.size ? bytes.subarray(0, lidos) : 'nao-regular';
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
fs.closeSync(fd);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Valor de lista do frontmatter: lista de textos ou um texto só. Inteiro vira texto, sem perda; nulo, booleano
|
|
251
|
+
* e decimal (o `yes` que o YAML lê como `true`, a vírgula sobrando que vira nulo) recusam em vez de virar texto.
|
|
252
|
+
*/
|
|
253
|
+
function lista(v) {
|
|
254
|
+
if (v === undefined || v === null)
|
|
255
|
+
return [];
|
|
256
|
+
const itens = [];
|
|
257
|
+
for (const b of Array.isArray(v) ? v : [v]) {
|
|
258
|
+
if (typeof b === 'string')
|
|
259
|
+
itens.push(b);
|
|
260
|
+
else if (typeof b === 'number' && Number.isSafeInteger(b))
|
|
261
|
+
itens.push(String(b));
|
|
262
|
+
else
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
return itens;
|
|
266
|
+
}
|
|
267
|
+
/** D2 e D3: o frontmatter vale inteiro ou devolve a lacuna do primeiro problema, com o id quando ele já vale. */
|
|
268
|
+
function validarFrontmatter(dados, arquivo) {
|
|
269
|
+
if (!ehMapa(dados))
|
|
270
|
+
return lacuna('documento.frontmatter-invalido', t((l) => l.frontmatterNaoEMapa), { arquivo });
|
|
271
|
+
const id = typeof dados.id === 'string' && exports.ID_DE_DOCUMENTO.test(dados.id) ? dados.id : null;
|
|
272
|
+
if (!id)
|
|
273
|
+
return lacuna('documento.id-invalido', t((l) => l.idInvalido), { arquivo });
|
|
274
|
+
const onde = { arquivo, documento: id };
|
|
275
|
+
const estranhas = Object.keys(dados).filter((k) => !CHAVES_DO_DOCUMENTO.includes(k));
|
|
276
|
+
if (estranhas.length) {
|
|
277
|
+
const chaves = estranhas.map((k) => JSON.stringify(limpo(k, 40))).join(', ');
|
|
278
|
+
return lacuna('documento.chave-desconhecida', t((l) => l.chaveDesconhecida(chaves, CHAVES_DO_DOCUMENTO.join(', '))), onde);
|
|
279
|
+
}
|
|
280
|
+
const titulo = typeof dados.titulo === 'string' ? dados.titulo.trim() : '';
|
|
281
|
+
if (!titulo || titulo.length > LIMITE_DO_TITULO || saida_segura_1.INVISIVEL.test(titulo)) {
|
|
282
|
+
return lacuna('documento.titulo-invalido', t((l) => l.tituloInvalido(LIMITE_DO_TITULO)), onde);
|
|
283
|
+
}
|
|
284
|
+
const colecoes = lista(dados.colecoes);
|
|
285
|
+
if (!colecoes || !colecoes.length || colecoes.length > COLECOES_POR_DOCUMENTO ||
|
|
286
|
+
colecoes.some((c) => !exports.NOME_DE_COLECAO.test(c)) || new Set(colecoes).size !== colecoes.length) {
|
|
287
|
+
return lacuna('documento.colecoes-invalidas', t((l) => l.colecoesInvalidas(COLECOES_POR_DOCUMENTO)), onde);
|
|
288
|
+
}
|
|
289
|
+
const refs = dados.referencias ?? null;
|
|
290
|
+
const brain = ehMapa(refs) ? lista(refs.brain) : [], decisoes = ehMapa(refs) ? lista(refs.decisoes) : [];
|
|
291
|
+
if ((refs !== null && !ehMapa(refs)) || (ehMapa(refs) && Object.keys(refs).some((k) => !CHAVES_DAS_REFERENCIAS.includes(k))) ||
|
|
292
|
+
!brain || brain.length > REFERENCIAS_POR_LISTA || !decisoes || decisoes.length > REFERENCIAS_POR_LISTA) {
|
|
293
|
+
return lacuna('documento.referencias-invalidas', t((l) => l.referenciasInvalidas(REFERENCIAS_POR_LISTA)), onde);
|
|
294
|
+
}
|
|
295
|
+
return { id, titulo, colecoes: [...colecoes].sort(comparar), brain: [...new Set(brain)], decisoes: [...new Set(decisoes)] };
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* As linhas citadas do ledger canônico de uma thread (D5). O ledger é lido como a captura do Brain o lê
|
|
299
|
+
* (`readCycle`): só linhas completas, em UTF-8 exato, para o sha256 da linha ser o `source_hash` dela no Brain.
|
|
300
|
+
* Cada ledger é lido uma vez, até a maior linha citada, e só as linhas citadas viram texto (fatia 2: a leitura não parte
|
|
301
|
+
* o ledger inteiro em linhas). `completas` é exato quando alguma linha citada passa do fim, o único caso em que ele é
|
|
302
|
+
* dito. O `orcamento` é o que resta do teto de bytes dos ledgers da leitura.
|
|
303
|
+
*/
|
|
304
|
+
function linhasCitadas(raiz, thread, citadas, limites, orcamento) {
|
|
305
|
+
let arquivo;
|
|
306
|
+
try {
|
|
307
|
+
arquivo = path.join((0, thread_1.dirThread)(raiz, thread), 'ledger.jsonl');
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return { motivo: t((l) => l.ledgerLinkOuId) };
|
|
311
|
+
}
|
|
312
|
+
let st;
|
|
313
|
+
try {
|
|
314
|
+
st = fs.lstatSync(arquivo, { throwIfNoEntry: false });
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
// A pasta da thread que é arquivo comum dá ENOTDIR: a thread não tem ledger, e nada lança.
|
|
318
|
+
if (e.code !== 'ENOTDIR')
|
|
319
|
+
return { motivo: t((l) => l.ledgerNaoAbriu(thread)) };
|
|
320
|
+
}
|
|
321
|
+
if (!st)
|
|
322
|
+
return { motivo: t((l) => l.semLedger(thread)) };
|
|
323
|
+
if (st.size > orcamento.restante)
|
|
324
|
+
return { motivo: t((l) => l.ledgersDemais(limites.bytesDosLedgers / 1024 / 1024)) };
|
|
325
|
+
const bytes = lerArquivo(arquivo, st, limites.bytesDoLedger, true);
|
|
326
|
+
if (!Buffer.isBuffer(bytes))
|
|
327
|
+
return { motivo: t((l) => l.ledgerNaoRegular(thread, limites.bytesDoLedger / 1024 / 1024)) };
|
|
328
|
+
orcamento.restante -= bytes.length;
|
|
329
|
+
const completo = bytes.subarray(0, bytes.lastIndexOf(10) + 1);
|
|
330
|
+
if (!(0, node_buffer_1.isUtf8)(completo))
|
|
331
|
+
return { motivo: t((l) => l.ledgerNaoUtf8(thread)) };
|
|
332
|
+
let maior = 0;
|
|
333
|
+
for (const n of citadas)
|
|
334
|
+
if (n > maior)
|
|
335
|
+
maior = n;
|
|
336
|
+
const linhas = new Map();
|
|
337
|
+
let inicio = 0, n = 0;
|
|
338
|
+
while (inicio < completo.length && n < maior) {
|
|
339
|
+
const fimDaLinha = completo.indexOf(10, inicio);
|
|
340
|
+
n++;
|
|
341
|
+
if (citadas.has(n))
|
|
342
|
+
linhas.set(n, completo.subarray(inicio, fimDaLinha).toString('utf8'));
|
|
343
|
+
inicio = fimDaLinha + 1;
|
|
344
|
+
}
|
|
345
|
+
return { linhas, completas: n };
|
|
346
|
+
}
|
|
347
|
+
/** D5: a referência `thread#linha` confere quando a linha completa existe, é da thread e é uma decisão. */
|
|
348
|
+
function conferirDecisao(ref, ledgers) {
|
|
349
|
+
const m = exports.REFERENCIA_DE_DECISAO.exec(ref);
|
|
350
|
+
if (!m)
|
|
351
|
+
return { codigo: 'referencia.invalida', detalhe: t((l) => l.decisaoForma) };
|
|
352
|
+
const thread = m[1], linha = Number(m[2]);
|
|
353
|
+
const ledger = ledgers.get(thread);
|
|
354
|
+
if ('motivo' in ledger)
|
|
355
|
+
return { codigo: 'referencia.decisao-ausente', detalhe: ledger.motivo };
|
|
356
|
+
const bruta = ledger.linhas.get(linha);
|
|
357
|
+
if (bruta === undefined) {
|
|
358
|
+
return { codigo: 'referencia.decisao-ausente', detalhe: t((l) => l.linhasCompletas(thread, ledger.completas)) };
|
|
359
|
+
}
|
|
360
|
+
let evento = null;
|
|
361
|
+
try {
|
|
362
|
+
const lido = JSON.parse(bruta);
|
|
363
|
+
if (lido && typeof lido === 'object' && !Array.isArray(lido))
|
|
364
|
+
evento = lido;
|
|
365
|
+
}
|
|
366
|
+
catch { /* linha que não é JSON não é decisão */ }
|
|
367
|
+
if (!evento)
|
|
368
|
+
return { codigo: 'referencia.nao-e-decisao', detalhe: t((l) => l.naoEJson(linha, thread)) };
|
|
369
|
+
if (evento.thread !== thread)
|
|
370
|
+
return { codigo: 'referencia.nao-e-decisao', detalhe: t((l) => l.outraThread(linha, thread)) };
|
|
371
|
+
const tipo = TIPOS_DE_DECISAO.find((x) => x === evento?.tipo);
|
|
372
|
+
if (!tipo) {
|
|
373
|
+
const visto = typeof evento.tipo === 'string' && /^[a-z_]{1,40}$/.test(evento.tipo) ? evento.tipo : null;
|
|
374
|
+
return { codigo: 'referencia.nao-e-decisao', detalhe: t((l) => l.naoEDecisao(linha, thread, visto, TIPOS_DE_DECISAO.join(', '))) };
|
|
375
|
+
}
|
|
376
|
+
return { ref, thread, linha, tipo, fonte: `threads/${thread}/ledger.jsonl#L${linha}`, sha256: (0, company_brain_journal_1.bytesHash)(bruta) };
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Lê o conhecimento declarado no manifesto: documentos válidos, coleções e lacunas, tudo em ordem estável.
|
|
380
|
+
* Nunca lança por causa do conteúdo do repositório; o que não vale vira lacuna tipada.
|
|
381
|
+
*/
|
|
382
|
+
function lerConhecimento(c, limites = exports.LIMITES_DO_CONHECIMENTO, opcoes = {}) {
|
|
383
|
+
const declarado = c.manifesto.conhecimento?.dir ?? null;
|
|
384
|
+
const dir = declarado === null ? null : limpo(declarado);
|
|
385
|
+
const so = (l) => ({ contrato: exports.CONTRATO_CONHECIMENTO, dir, documentos: [], colecoes: [], lacunas: [l] });
|
|
386
|
+
if (declarado === null)
|
|
387
|
+
return so(lacuna('conhecimento.nao-declarado', t((l) => l.naoDeclarado)));
|
|
388
|
+
const pasta = pastaDoConhecimento(c.raiz, declarado);
|
|
389
|
+
if ('codigo' in pasta)
|
|
390
|
+
return so(pasta);
|
|
391
|
+
const teto = (detalhe) => so(lacuna('conhecimento.limite', detalhe));
|
|
392
|
+
const lacunas = [];
|
|
393
|
+
const candidatos = varrer(pasta.real, pasta.raizReal, limites, lacunas);
|
|
394
|
+
if (!Array.isArray(candidatos))
|
|
395
|
+
return teto(candidatos.teto);
|
|
396
|
+
const decodificador = new TextDecoder('utf-8', { fatal: true });
|
|
397
|
+
const validos = [];
|
|
398
|
+
const declarados = new Map();
|
|
399
|
+
let total = 0;
|
|
400
|
+
for (const { abs, arquivo, st } of candidatos) {
|
|
401
|
+
const bytes = lerArquivo(abs, st, limites.bytesPorDocumento);
|
|
402
|
+
if (bytes === 'link') {
|
|
403
|
+
lacunas.push(lacuna('documento.link', t((l) => l.link), { arquivo }));
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
if (bytes === 'nao-regular') {
|
|
407
|
+
lacunas.push(lacuna('documento.nao-regular', t((l) => l.naoAbriuComoArquivo), { arquivo }));
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
if (bytes === 'grande') {
|
|
411
|
+
lacunas.push(lacuna('documento.grande-demais', t((l) => l.grandeDemais(limites.bytesPorDocumento / 1024)), { arquivo }));
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
total += bytes.length;
|
|
415
|
+
if (total > limites.bytesNoTotal)
|
|
416
|
+
return teto(t((l) => l.limiteTotal(limites.bytesNoTotal / 1024 / 1024)));
|
|
417
|
+
let texto;
|
|
418
|
+
try {
|
|
419
|
+
texto = decodificador.decode(bytes);
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
lacunas.push(lacuna('documento.codificacao', t((l) => l.codificacao), { arquivo }));
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
const { bruto, corpo } = (0, docs_1.separarFrontmatter)(texto);
|
|
426
|
+
if (bruto === null) {
|
|
427
|
+
lacunas.push(lacuna('documento.sem-frontmatter', t((l) => l.semFrontmatter), { arquivo }));
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
if (Buffer.byteLength(bruto, 'utf8') > limites.bytesDoFrontmatter) {
|
|
431
|
+
lacunas.push(lacuna('documento.frontmatter-invalido', t((l) => l.frontmatterGrande(limites.bytesDoFrontmatter / 1024)), { arquivo }));
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
let dados;
|
|
435
|
+
// A linha do `---` de abertura entra na leitura (e é pulada nela) para o erro dizer a linha do arquivo.
|
|
436
|
+
try {
|
|
437
|
+
dados = (0, yaml_1.lerYaml)('---\n' + bruto, { estrito: true });
|
|
438
|
+
}
|
|
439
|
+
catch (e) {
|
|
440
|
+
const erro = limpo(e.message, 200);
|
|
441
|
+
lacunas.push(lacuna('documento.frontmatter-invalido', t((l) => l.frontmatterYaml(erro)), { arquivo }));
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
// D4: o id na forma certa conta para a regra do repetido mesmo quando o resto do documento não vale.
|
|
445
|
+
const idDeclarado = ehMapa(dados) && typeof dados.id === 'string' && exports.ID_DE_DOCUMENTO.test(dados.id) ? dados.id : null;
|
|
446
|
+
if (idDeclarado)
|
|
447
|
+
declarados.set(idDeclarado, (declarados.get(idDeclarado) ?? 0) + 1);
|
|
448
|
+
const v = validarFrontmatter(dados, arquivo);
|
|
449
|
+
if ('codigo' in v) {
|
|
450
|
+
lacunas.push(v);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
validos.push({ ...v, arquivo, bytes: bytes.length, sha256: (0, company_brain_journal_1.bytesHash)(bytes), ...(v.id === opcoes.corpoDe ? { corpo } : {}) });
|
|
454
|
+
}
|
|
455
|
+
// D4: id repetido não escolhe arquivo; todos os documentos com ele saem da resposta, também quando a outra
|
|
456
|
+
// cópia não vale por outro motivo (ela já tem a lacuna dela).
|
|
457
|
+
const unicos = validos.filter((v) => {
|
|
458
|
+
const vezes = declarados.get(v.id);
|
|
459
|
+
if (vezes > 1) {
|
|
460
|
+
lacunas.push(lacuna('documento.id-repetido', t((l) => l.idRepetido(vezes)), { arquivo: v.arquivo, documento: v.id }));
|
|
461
|
+
}
|
|
462
|
+
return vezes === 1;
|
|
463
|
+
});
|
|
464
|
+
// D5: cada ledger citado é lido uma vez, com as linhas que os documentos válidos pedem, em ordem de thread e até o
|
|
465
|
+
// teto de bytes da leitura. Fatia 2: só os documentos cujas decisões a consulta mostra (`decisoesDe`).
|
|
466
|
+
const decisoesDe = opcoes.decisoesDe ?? 'todos';
|
|
467
|
+
const confere = (id) => decisoesDe === 'todos' || decisoesDe === id;
|
|
468
|
+
const citadas = new Map();
|
|
469
|
+
for (const v of unicos)
|
|
470
|
+
if (confere(v.id))
|
|
471
|
+
for (const ref of v.decisoes) {
|
|
472
|
+
const m = exports.REFERENCIA_DE_DECISAO.exec(ref);
|
|
473
|
+
if (m)
|
|
474
|
+
citadas.set(m[1], (citadas.get(m[1]) ?? new Set()).add(Number(m[2])));
|
|
475
|
+
}
|
|
476
|
+
const ledgers = new Map(), orcamento = { restante: limites.bytesDosLedgers };
|
|
477
|
+
for (const thread of [...citadas.keys()].sort(comparar)) {
|
|
478
|
+
ledgers.set(thread, linhasCitadas(c.raiz, thread, citadas.get(thread), limites, orcamento));
|
|
479
|
+
}
|
|
480
|
+
const documentos = [];
|
|
481
|
+
for (const v of unicos) {
|
|
482
|
+
const onde = { arquivo: v.arquivo, documento: v.id };
|
|
483
|
+
const brain = [], decisoes = [];
|
|
484
|
+
for (const referencia of v.brain) {
|
|
485
|
+
if (portfolio_1.ID_DE_ENTIDADE.test(referencia))
|
|
486
|
+
brain.push(referencia);
|
|
487
|
+
else
|
|
488
|
+
lacunas.push(lacuna('referencia.invalida', t((l) => l.brainForma), { ...onde, referencia }));
|
|
489
|
+
}
|
|
490
|
+
for (const referencia of confere(v.id) ? v.decisoes : []) {
|
|
491
|
+
const r = conferirDecisao(referencia, ledgers);
|
|
492
|
+
if ('codigo' in r)
|
|
493
|
+
lacunas.push(lacuna(r.codigo, r.detalhe, { ...onde, referencia }));
|
|
494
|
+
else
|
|
495
|
+
decisoes.push(r);
|
|
496
|
+
}
|
|
497
|
+
documentos.push({ id: v.id, titulo: v.titulo, colecoes: v.colecoes,
|
|
498
|
+
referencias: { brain: brain.sort(comparar), decisoes: decisoes.sort((a, b) => comparar(a.thread, b.thread) || a.linha - b.linha) },
|
|
499
|
+
arquivo: v.arquivo, bytes: v.bytes, sha256: v.sha256, ...(v.corpo !== undefined ? { corpo: v.corpo } : {}) });
|
|
500
|
+
}
|
|
501
|
+
const colecoes = new Map();
|
|
502
|
+
for (const d of documentos)
|
|
503
|
+
for (const nome of d.colecoes) {
|
|
504
|
+
const ids = colecoes.get(nome) ?? [];
|
|
505
|
+
ids.push(d.id);
|
|
506
|
+
colecoes.set(nome, ids);
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
contrato: exports.CONTRATO_CONHECIMENTO, dir,
|
|
510
|
+
documentos: documentos.sort((a, b) => comparar(a.id, b.id)),
|
|
511
|
+
colecoes: [...colecoes].map(([nome, ids]) => ({ nome, documentos: ids.sort(comparar) })).sort((a, b) => comparar(a.nome, b.nome)),
|
|
512
|
+
lacunas: lacunas.sort(exports.compararLacunas),
|
|
513
|
+
};
|
|
514
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reconciliarContaEsgotada = reconciliarContaEsgotada;
|
|
4
|
+
/** RM-064 T1/T2: uma cota esgotada pertence à conta, não só à sessão que a revelou. */
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const claude_bg_1 = require("./adapters/claude-bg");
|
|
7
|
+
const hitl_sessions_1 = require("./hitl-sessions");
|
|
8
|
+
const ledger_1 = require("./ledger");
|
|
9
|
+
const projeto_alvo_1 = require("./projeto-alvo");
|
|
10
|
+
const runtime_profiles_1 = require("./runtime-profiles");
|
|
11
|
+
const session_events_1 = require("./session-events");
|
|
12
|
+
const sessoes_inventario_1 = require("./sessoes-inventario");
|
|
13
|
+
const thread_1 = require("./thread");
|
|
14
|
+
const sha = (v) => (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(v)).digest('hex');
|
|
15
|
+
const padrao = {
|
|
16
|
+
inventario: (raiz) => (0, sessoes_inventario_1.inventariarSessoes)(raiz, { global: true, todas: true, prazoMs: 30_000 }),
|
|
17
|
+
projetos: (raiz) => [...new Set([raiz, ...(0, projeto_alvo_1.listarProjetos)().filter((p) => p.presente).map((p) => p.raiz)])],
|
|
18
|
+
parar: (sessionId, id, perfil, vinculo) => {
|
|
19
|
+
if (perfil.runtime === 'codex') {
|
|
20
|
+
if (!vinculo)
|
|
21
|
+
return { ok: false, detalhe: 'vínculo canônico do controller ausente' };
|
|
22
|
+
try {
|
|
23
|
+
const ctl = (0, hitl_sessions_1.controleNativo)('codex', vinculo.raiz, vinculo.thread, sessionId);
|
|
24
|
+
const consulta = ctl.consultar();
|
|
25
|
+
const candidatas = consulta.sessoes.filter((s) => s.sessionId === sessionId && s.runtime === 'codex');
|
|
26
|
+
if (!consulta.ok || candidatas.length !== 1)
|
|
27
|
+
return { ok: false, detalhe: 'controller codex não confirmou identidade única' };
|
|
28
|
+
return { ok: ctl.parar(candidatas[0]), detalhe: 'controller codex vinculado recebeu interrupção' };
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
return { ok: false, detalhe: e.message };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const r = (0, claude_bg_1.pararAchada)({ sessionId, ...(id ? { id } : {}) }, (0, claude_bg_1.ambienteDoPerfil)(perfil));
|
|
35
|
+
return { ok: r.ok, detalhe: r.texto || (r.ok ? 'runtime confirmou a parada' : 'runtime recusou a parada') };
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
function vinculosDaConta(projetos, sessionId, conta) {
|
|
39
|
+
const vinculos = [], falhas = [];
|
|
40
|
+
for (const raiz of projetos) {
|
|
41
|
+
let ids;
|
|
42
|
+
try {
|
|
43
|
+
ids = (0, thread_1.listarIds)(raiz);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
falhas.push(`projeto não lido: ${e.message}`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
for (const id of ids) {
|
|
50
|
+
try {
|
|
51
|
+
const thread = (0, thread_1.lerThread)(raiz, id);
|
|
52
|
+
const sessao = thread.sessoes.find((s) => s.sessionId === sessionId && s.origem !== 'adocao');
|
|
53
|
+
if (!sessao?.despachadaEm)
|
|
54
|
+
continue;
|
|
55
|
+
const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id));
|
|
56
|
+
const perfil = (0, runtime_profiles_1.perfilDoRegistro)(eventos, { sessionId, despachadaEm: sessao.despachadaEm });
|
|
57
|
+
if (!perfil || (0, runtime_profiles_1.chaveDaConta)(perfil) !== conta)
|
|
58
|
+
continue;
|
|
59
|
+
vinculos.push({ raiz, thread: id, fase: sessao.fase, despachoEm: sessao.despachadaEm });
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
falhas.push(`vínculo ${id} não confirmado: ${e.message}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { vinculos: vinculos.filter((v, i, a) => a.findIndex((x) => x.raiz === v.raiz && x.thread === v.thread) === i), falhas };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Para cada sessão viva da mesma conta: prova o vínculo pelo ledger, pede a parada uma vez e só
|
|
70
|
+
* então grava o terminal que libera a condução. Consulta incompleta nunca vira falso sucesso.
|
|
71
|
+
*/
|
|
72
|
+
function reconciliarContaEsgotada(entrada, deps = padrao) {
|
|
73
|
+
const agoraMs = entrada.agoraMs ?? Date.now();
|
|
74
|
+
const contaBruta = (0, runtime_profiles_1.chaveDaConta)(entrada.perfil), conta = sha(contaBruta);
|
|
75
|
+
const episodio = sha([conta, entrada.erroEm, entrada.esgotadoAte]);
|
|
76
|
+
const inv = deps.inventario(entrada.raiz);
|
|
77
|
+
const projetos = deps.projetos(entrada.raiz);
|
|
78
|
+
const falhas = inv.fontes.filter((f) => !f.ok).map((f) => f.detalhe);
|
|
79
|
+
const sessoes = [];
|
|
80
|
+
const candidatas = inv.sessoes.filter((s) => s.runtime === entrada.perfil.runtime && s.perfil === entrada.perfil.id && s.viva);
|
|
81
|
+
for (const sessao of candidatas) {
|
|
82
|
+
const achados = vinculosDaConta(projetos, sessao.sessionId, contaBruta);
|
|
83
|
+
falhas.push(...achados.falhas);
|
|
84
|
+
if (achados.vinculos.length === 0)
|
|
85
|
+
continue;
|
|
86
|
+
const pendentes = achados.vinculos.filter((v) => !(0, ledger_1.lerLedger)((0, thread_1.dirThread)(v.raiz, v.thread)).some((e) => e.tipo === 'phase_result' && e.quotaEpisodeId === episodio && e.sessionId === sessao.sessionId));
|
|
87
|
+
for (const v of achados.vinculos.filter((x) => !pendentes.includes(x))) {
|
|
88
|
+
sessoes.push({ ...v, sessionId: sessao.sessionId, parada: true, registrada: false, detalhe: 'episódio já reconciliado' });
|
|
89
|
+
}
|
|
90
|
+
if (pendentes.length === 0)
|
|
91
|
+
continue;
|
|
92
|
+
const paradaUnica = sessao.runtime === 'claude-bg'
|
|
93
|
+
? deps.parar(sessao.sessionId, sessao.id, entrada.perfil) : null;
|
|
94
|
+
for (const v of pendentes) {
|
|
95
|
+
const parada = paradaUnica ?? deps.parar(sessao.sessionId, sessao.id, entrada.perfil, v);
|
|
96
|
+
const dir = (0, thread_1.dirThread)(v.raiz, v.thread);
|
|
97
|
+
if (!parada.ok || !(0, ledger_1.threadPresente)(dir)) {
|
|
98
|
+
sessoes.push({ ...v, sessionId: sessao.sessionId, parada: parada.ok, registrada: false, detalhe: parada.detalhe });
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
let registrada = false;
|
|
102
|
+
(0, session_events_1.comLockDeSessao)(dir, () => {
|
|
103
|
+
const atuais = (0, ledger_1.lerLedger)(dir);
|
|
104
|
+
if (atuais.some((e) => e.tipo === 'phase_result' && e.quotaEpisodeId === episodio && e.sessionId === sessao.sessionId))
|
|
105
|
+
return;
|
|
106
|
+
const dados = { fase: v.fase, sessionId: sessao.sessionId, despachoEm: v.despachoEm, runtime: sessao.runtime,
|
|
107
|
+
motivo: 'runtime.quota-exhausted', quotaEpisodeId: episodio, conta, resetEm: entrada.falha.resetEm,
|
|
108
|
+
esgotadoAte: entrada.esgotadoAte, observadoEm: new Date(agoraMs).toISOString(), origem: 'account.quota-exhausted',
|
|
109
|
+
perfil: { id: entrada.perfil.id, runtime: entrada.perfil.runtime },
|
|
110
|
+
falhaDeConta: { motivo: entrada.falha.motivo, resetEm: entrada.falha.resetEm,
|
|
111
|
+
fonte: entrada.falha.fonte, trecho: entrada.falha.trecho },
|
|
112
|
+
evidencia: 'vínculo da sessão, conta do despacho e parada confirmados pelo núcleo' };
|
|
113
|
+
(0, ledger_1.registrarSeExiste)(dir, v.thread, 'runtime_account_exhausted', dados);
|
|
114
|
+
(0, ledger_1.registrarSeExiste)(dir, v.thread, ledger_1.TIPOS_DE_EVENTO.gateBloqueado, { ...dados, gate: 'phase.dispatch',
|
|
115
|
+
modo: (0, thread_1.lerThread)(v.raiz, v.thread).modo, detalhe: 'a conta do despacho esgotou; retomar no próximo destino capaz',
|
|
116
|
+
correcao: `ork retry run ${v.thread}` });
|
|
117
|
+
(0, ledger_1.registrarSeExiste)(dir, v.thread, 'phase_result', { ...dados, sensorResultId: `quota:${episodio}:${sessao.sessionId}`,
|
|
118
|
+
classificacao: 'gate_blocked', ok: false, estado: 'bloqueada', paradaConfirmada: true });
|
|
119
|
+
registrada = true;
|
|
120
|
+
});
|
|
121
|
+
sessoes.push({ ...v, sessionId: sessao.sessionId, parada: true, registrada,
|
|
122
|
+
detalhe: registrada ? 'sessão parada e condução liberada' : 'episódio já reconciliado' });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { conta, episodio, completo: inv.ok && falhas.length === 0 && sessoes.every((s) => s.parada && (s.registrada || s.detalhe.includes('já'))),
|
|
126
|
+
sessoes, falhas };
|
|
127
|
+
}
|