@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,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MOTIVO_DO_ERRO_NO_DESPACHO = exports.ERROS_SEGUIDOS_QUE_BLOQUEIAM = exports.BACKOFF_MAXIMO_MS = exports.CADENCIA_MS = exports.CONTRATO_FILA = void 0;
|
|
4
|
+
exports.montarFila = montarFila;
|
|
5
|
+
exports.fatosDaFila = fatosDaFila;
|
|
6
|
+
/**
|
|
7
|
+
* RM-058, fatia N2 (D2 a D6 da ork-rm058n2): a fila do arco.
|
|
8
|
+
*
|
|
9
|
+
* O que entra: os trabalhos do envelope `v2` vigente, cada um uma thread (a que já existe, ou a que o arco abre com o
|
|
10
|
+
* pedido do dono), com o item reservado por esta máquina e trabalho possível. A ordem: só com as dependências entregues,
|
|
11
|
+
* depois a prioridade do dono, a prova mais adiantada (a fase a despachar mais adiante primeiro; abrir thread por último),
|
|
12
|
+
* a posição no envelope e o id. O passo de cada thread aberta é o da Sentinela (`passoDaThread`, pela prova mais adiantada
|
|
13
|
+
* que a sessão do bloco deixou): o bloco inteiro numa sessão só, cujo `phase_result` sai com a fase do despacho, não ganha
|
|
14
|
+
* um PLAN repetido (aprendizado 3 de 12/10).
|
|
15
|
+
*
|
|
16
|
+
* Quando a fila acaba: vazia (todo trabalho entregue, encerrado ou preso a uma dependência que fechou sem entrega)
|
|
17
|
+
* encerra cedo; só bloqueada, ou com fonte que não foi lida, espera com backoff até o fim da janela; com sessão em curso,
|
|
18
|
+
* espera a cadência de 5 min. Lacuna nunca vira fila vazia. O trabalho cujo despacho falhou no núcleo, antes de lançar,
|
|
19
|
+
* três vezes seguidas fica bloqueado (`erro-repetido`), e o que pode ter uma sessão aberta (reserva pendente no log do arco,
|
|
20
|
+
* ou thread nunca despachada cuja falha disse o id da sessão) vai para a retomada da N4: o passo não insiste no mesmo erro a
|
|
21
|
+
* noite toda nem abre outra sessão por cima de uma que pode estar aberta. A falha que não abriu nada (a conta sem cota, sem
|
|
22
|
+
* id) deixa o trabalho na fila, e o despacho seguinte sai por outra conta. Fechar o arco e o relatório são da N6.
|
|
23
|
+
*
|
|
24
|
+
* `fatosDaFila` relê o disco a cada chamada; `montarFila` é pura sobre os fatos e o instante. Nada aqui despacha nem grava.
|
|
25
|
+
*
|
|
26
|
+
* RM-058, fatia N4 (D8 e D21 da ork-rm058n4): a fila respeita, quando vem, o que a supervisão do arco decidiu. O trabalho
|
|
27
|
+
* isolado não sai sozinho neste arco; o trabalho bloqueado para a N4 sem reserva pendente (a falha com id antes do primeiro
|
|
28
|
+
* despacho, o passo de retomar, o fim de turno sem resultado e o que ficou sem passo depois da sessão morta) volta à fila
|
|
29
|
+
* na fase da retomada que o vigia autorizou. A reserva pendente nunca é sobreposta. Sem a supervisão, nada muda.
|
|
30
|
+
*/
|
|
31
|
+
const roadmap_reservas_1 = require("./roadmap-reservas");
|
|
32
|
+
const branch_de_estado_1 = require("./branch-de-estado");
|
|
33
|
+
const parado_no_condutor_1 = require("./parado-no-condutor");
|
|
34
|
+
const conducao_sentinela_1 = require("./conducao-sentinela");
|
|
35
|
+
const ledger_1 = require("./ledger");
|
|
36
|
+
const maquina_1 = require("./maquina");
|
|
37
|
+
const noctum_arco_1 = require("./noctum-arco");
|
|
38
|
+
const noctum_envelope_1 = require("./noctum-envelope");
|
|
39
|
+
const thread_1 = require("./thread");
|
|
40
|
+
const types_1 = require("./types");
|
|
41
|
+
exports.CONTRATO_FILA = 'ork.noctum-fila/v1';
|
|
42
|
+
/** A cadência do vigia (D3 do dono): a espera da fila em curso e o menor passo do backoff. */
|
|
43
|
+
exports.CADENCIA_MS = 5 * 60 * 1000;
|
|
44
|
+
/** O maior passo do backoff da fila bloqueada. */
|
|
45
|
+
exports.BACKOFF_MAXIMO_MS = 60 * 60 * 1000;
|
|
46
|
+
/** Quantas falhas seguidas do núcleo no despacho de um trabalho o bloqueiam (A4 do CHECK da ork-rm058n2). */
|
|
47
|
+
exports.ERROS_SEGUIDOS_QUE_BLOQUEIAM = 3;
|
|
48
|
+
/** O motivo que o passo grava no log do arco quando o despacho de um candidato falha antes de lançar a sessão. */
|
|
49
|
+
exports.MOTIVO_DO_ERRO_NO_DESPACHO = 'noctum.despacho.erro';
|
|
50
|
+
/** Bloqueio que vem de fonte não lida, e não de um fato: vira lacuna, nunca trabalho a menos. */
|
|
51
|
+
const DE_LACUNA = ['reserva-sem-leitura', 'thread-ilegivel', 'thread-ambigua'];
|
|
52
|
+
const adiante = (t) => t.estado === 'abrir' ? -1 : t.fase ? types_1.FASES.indexOf(t.fase) : -1;
|
|
53
|
+
/** D3: prioridade do dono, prova mais adiantada, posição no envelope e id. */
|
|
54
|
+
function antes(a, b) {
|
|
55
|
+
return a.prioridade - b.prioridade || adiante(b) - adiante(a) || a.posicao - b.posicao || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
56
|
+
}
|
|
57
|
+
const FASES_DA_ENTREGA = ['SHIP', 'MASTER'];
|
|
58
|
+
/** As falhas seguidas do núcleo antes de lançar, nos despachos mais recentes do trabalho, contadas do último para trás. */
|
|
59
|
+
function errosSeguidos(trabalho, despachos) {
|
|
60
|
+
let n = 0;
|
|
61
|
+
for (const d of despachos.filter(x => x.trabalho === trabalho).sort((a, b) => b.seq - a.seq)) {
|
|
62
|
+
if (d.desfecho !== 'recusado' || d.motivo !== exports.MOTIVO_DO_ERRO_NO_DESPACHO)
|
|
63
|
+
break;
|
|
64
|
+
n += 1;
|
|
65
|
+
}
|
|
66
|
+
return n;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* O estado de um trabalho do envelope pelos fatos; `entregues` são os ids já entregues (para as dependências) e
|
|
70
|
+
* `semSaida` os que nunca mais entregam neste arco (fecharam sem entrega, ou dependem de quem fechou).
|
|
71
|
+
*/
|
|
72
|
+
function classificar(t, posicao, f, fatos, entregues, semSaida, estado) {
|
|
73
|
+
const decisoes = estado.decisoes;
|
|
74
|
+
const base = { id: t.id, item: t.item, prioridade: t.prioridade, posicao, thread: null, fase: null,
|
|
75
|
+
motivo: null, entregueEm: null };
|
|
76
|
+
const bloqueado = (motivo, detalhe) => ({ ...base, estado: 'bloqueado', motivo, detalhe });
|
|
77
|
+
// N3: a entrega em outra máquina do arco vale aqui, até sem thread nesta raiz.
|
|
78
|
+
const naRede = fatos.coordenacao?.entregues.get(t.id);
|
|
79
|
+
if (naRede)
|
|
80
|
+
return { ...base, thread: f?.threads[0]?.id ?? null, estado: 'entregue', entregueEm: naRede, detalhe: 'entregue em outra máquina do arco' };
|
|
81
|
+
if (fatos.coordenacao?.encerrados?.has(t.id)) {
|
|
82
|
+
return { ...base, thread: f?.threads[0]?.id ?? null, estado: 'encerrado-sem-entrega', detalhe: 'encerrado sem entrega em outra máquina do arco' };
|
|
83
|
+
}
|
|
84
|
+
if (!f)
|
|
85
|
+
return bloqueado('thread-ilegivel', 'o trabalho não foi lido');
|
|
86
|
+
if (f.ilegivel)
|
|
87
|
+
return bloqueado('thread-ilegivel', `a thread ${f.ilegivel} não pôde ser lida`);
|
|
88
|
+
if (f.threads.length > 1) {
|
|
89
|
+
return bloqueado('thread-ambigua', `${f.threads.map(x => x.id).join(', ')} casam com o item e o pedido; o arco não escolhe por ninguém`);
|
|
90
|
+
}
|
|
91
|
+
const th = f.threads[0] ?? null;
|
|
92
|
+
base.thread = th?.id ?? null;
|
|
93
|
+
if (t.thread !== undefined && !th)
|
|
94
|
+
return bloqueado('thread-ausente', `a thread ${t.thread} não existe neste projeto`);
|
|
95
|
+
if (th && th.roadmap !== t.item)
|
|
96
|
+
return bloqueado('item-divergente', `a thread ${th.id} é do item ${th.roadmap ?? 'nenhum'}, não do ${t.item}`);
|
|
97
|
+
if (th && f.entregueEm)
|
|
98
|
+
return { ...base, estado: 'entregue', entregueEm: f.entregueEm, detalhe: `ship_done da thread ${th.id}` };
|
|
99
|
+
if (th && th.status === 'fechada')
|
|
100
|
+
return { ...base, estado: 'encerrado-sem-entrega', detalhe: `a thread ${th.id} fechou sem ship_done` };
|
|
101
|
+
// RM-058 N4 (D16): o trabalho isolado pela supervisão não sai sozinho neste arco, nem com uma sessão de fora rodando nele.
|
|
102
|
+
const isolado = fatos.supervisao?.isolados.get(t.id);
|
|
103
|
+
if (isolado !== undefined)
|
|
104
|
+
return bloqueado('isolado', isolado);
|
|
105
|
+
if (th && f.passo?.conduzida)
|
|
106
|
+
return { ...base, estado: 'em-curso', detalhe: `a thread ${th.id} está sendo conduzida agora` };
|
|
107
|
+
const mortas = t.dependeDe.filter(d => semSaida.has(d));
|
|
108
|
+
if (mortas.length) {
|
|
109
|
+
return bloqueado('dependencia-encerrada', `depende de ${mortas.join(', ')}, que não entrega mais neste arco (fechou sem entrega)`);
|
|
110
|
+
}
|
|
111
|
+
const faltam = t.dependeDe.filter(d => !entregues.has(d));
|
|
112
|
+
if (faltam.length)
|
|
113
|
+
return bloqueado('dependencia', `depende de ${faltam.join(', ')}, ainda não entregue(s)`);
|
|
114
|
+
if (fatos.coordenacao && !fatos.coordenacao.trabalhos.has(t.id)) {
|
|
115
|
+
return bloqueado('sem-ordem', 'o trabalho não tem ordem aceita desta máquina no ramo de coordenação do arco');
|
|
116
|
+
}
|
|
117
|
+
if (fatos.reservas.leitura === 'sem-copia')
|
|
118
|
+
return bloqueado('reserva-sem-leitura', 'esta máquina não tem cópia da branch de reservas');
|
|
119
|
+
const reserva = fatos.reservas.porItem.get(t.item);
|
|
120
|
+
if (!reserva)
|
|
121
|
+
return bloqueado('reserva-ausente', `o item ${t.item} não está reservado; tomar reserva é da N3`);
|
|
122
|
+
if (reserva.maquina !== fatos.maquina)
|
|
123
|
+
return bloqueado('reserva-de-outra-maquina', `o item ${t.item} está com a máquina ${reserva.maquina}`);
|
|
124
|
+
if (th && decisoes.some(d => d.thread === th.id || d.dependentes.includes(th.id))) {
|
|
125
|
+
return bloqueado('decisao-no-lote', `a thread ${th.id} espera uma decisão do dono no lote do arco`);
|
|
126
|
+
}
|
|
127
|
+
// B1 da rodada 2 e A1 da rodada 3: a reserva pendente é um lançamento incerto; despachar de novo abriria outra sessão.
|
|
128
|
+
if (estado.despachos.some(d => d.trabalho === t.id && d.desfecho === 'pendente')) {
|
|
129
|
+
return bloqueado('retomada', 'um despacho deste trabalho ficou pendente, e o runtime pode ter aberto a sessão; a retomada é da N4');
|
|
130
|
+
}
|
|
131
|
+
const erros = errosSeguidos(t.id, estado.despachos);
|
|
132
|
+
if (erros >= exports.ERROS_SEGUIDOS_QUE_BLOQUEIAM) {
|
|
133
|
+
return bloqueado('erro-repetido', `os ${erros} últimos despachos falharam no núcleo antes de lançar; quem decide é a N4 ou o dono`);
|
|
134
|
+
}
|
|
135
|
+
// RM-058 N4 (D8): o bloqueio que a N2 deixou para a N4 vira a retomada que o vigia autorizou, na fase dela.
|
|
136
|
+
const retomada = fatos.supervisao?.retomadas.get(t.id);
|
|
137
|
+
const paraAN4 = (motivo, detalhe) => retomada
|
|
138
|
+
? { ...base, estado: 'despachavel', fase: retomada.fase,
|
|
139
|
+
detalhe: `retomada autorizada pela supervisão (tentativa ${retomada.tentativa}, ${retomada.motivo}) no lugar de: ${detalhe}` }
|
|
140
|
+
: bloqueado(motivo, detalhe);
|
|
141
|
+
if (!th) {
|
|
142
|
+
// A4 do CHECK: abrir a thread num projeto que não deixa criar #Auto falharia toda noite; o arco nem tenta.
|
|
143
|
+
if (!fatos.modosPermitidos.includes('auto'))
|
|
144
|
+
return bloqueado('modo', 'o projeto não deixa criar thread #Auto (conduction.allowed_modes)');
|
|
145
|
+
return { ...base, estado: 'abrir', fase: 'GOAL', detalhe: `abre a thread do item ${t.item} com o pedido do dono` };
|
|
146
|
+
}
|
|
147
|
+
if (th.modo !== 'auto')
|
|
148
|
+
return bloqueado('modo', `a thread ${th.id} está em ${th.modo}; o arco só conduz #Auto`);
|
|
149
|
+
if (f.doDono)
|
|
150
|
+
return bloqueado('dono', `a thread ${th.id} espera o dono (${f.doDono})`);
|
|
151
|
+
if (!f.pedidoGuardado)
|
|
152
|
+
return bloqueado('pedido-ausente', `a thread ${th.id} não guardou o pedido na criação; o arco não inventa um`);
|
|
153
|
+
if (!f.despachada) {
|
|
154
|
+
// B1 da rodada 2: a falha disse o id da sessão, que pode estar aberta; despachar de novo abriria outra.
|
|
155
|
+
if (f.despachoFalho)
|
|
156
|
+
return paraAN4('retomada', `o despacho da thread ${th.id} falhou depois de o runtime dizer o id da sessão; a retomada é da N4`);
|
|
157
|
+
return { ...base, estado: 'despachavel', fase: th.faseAtual, detalhe: `a thread ${th.id} nunca foi despachada` };
|
|
158
|
+
}
|
|
159
|
+
const passo = f.passo;
|
|
160
|
+
if (passo?.acao === 'despachar' && passo.fase) {
|
|
161
|
+
if (FASES_DA_ENTREGA.includes(passo.fase))
|
|
162
|
+
return { ...base, estado: 'aguardando-entrega', detalhe: `${passo.porque}; a entrega é da N5` };
|
|
163
|
+
return { ...base, estado: 'despachavel', fase: passo.fase, detalhe: passo.porque };
|
|
164
|
+
}
|
|
165
|
+
if (passo?.acao === 'retomar')
|
|
166
|
+
return paraAN4('retomada', `${passo.porque}; a retomada é da N4`);
|
|
167
|
+
if (f.espera?.tipo === 'stop-sem-resultado')
|
|
168
|
+
return paraAN4('fim-de-turno-sem-resultado', 'o turno acabou sem o resultado da fase; quem decide é a N4');
|
|
169
|
+
if (f.espera?.tipo === 'concluida')
|
|
170
|
+
return { ...base, estado: 'aguardando-entrega', detalhe: `${passo?.porque ?? 'fase concluída'}; a entrega é da N5` };
|
|
171
|
+
return paraAN4('sem-passo', passo?.porque ?? 'nenhum passo do condutor para a thread');
|
|
172
|
+
}
|
|
173
|
+
/** O último progresso do arco: a autorização, um despacho ou uma entrega. O backoff conta a partir dele. */
|
|
174
|
+
function ultimoProgresso(estado, trabalhos) {
|
|
175
|
+
const instantes = [estado.autorizadoPor?.recebidoEm, ...estado.despachos.flatMap(d => [d.reservadoEm, d.concluidoEm]),
|
|
176
|
+
...trabalhos.map(t => t.entregueEm)].map(x => typeof x === 'string' ? Date.parse(x) : NaN).filter(Number.isFinite);
|
|
177
|
+
return instantes.length ? Math.max(...instantes) : Date.parse(estado.conteudo?.janela.inicio ?? '');
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A fila e a decisão no instante dos fatos. Fora da janela, ou sem envelope `v2` autorizado, nada é candidato; o
|
|
181
|
+
* resto segue a D6 da ork-rm058n2.
|
|
182
|
+
*/
|
|
183
|
+
function montarFila(fatos) {
|
|
184
|
+
const { arco, quando, estado } = fatos;
|
|
185
|
+
const agora = Date.parse(quando);
|
|
186
|
+
const vazia = (situacao, decisao, lacunas = []) => ({ contrato: exports.CONTRATO_FILA, arco, envelopeSha256: estado?.envelopeSha256 ?? null, quando, situacao, trabalhos: [], candidatos: [],
|
|
187
|
+
lacunas, decisao });
|
|
188
|
+
const daqui = (ms, limite) => new Date(Math.min(agora + ms, limite ? Date.parse(limite) : Number.POSITIVE_INFINITY)).toISOString();
|
|
189
|
+
if (!estado || !estado.conteudo || estado.situacao === 'proposto') {
|
|
190
|
+
return vazia('fonte-indisponivel', { acao: 'aguardar', motivo: 'sem-autorizacao', ate: daqui(exports.CADENCIA_MS) }, ['o arco não tem envelope autorizado']);
|
|
191
|
+
}
|
|
192
|
+
const conteudo = estado.conteudo;
|
|
193
|
+
// RM-058 N6: o arco encerrado (hora, custo ou fila vazia) também acabou: nada é candidato.
|
|
194
|
+
if (estado.situacao === 'revogado' || estado.situacao === 'expirado' || estado.situacao === 'encerrado') {
|
|
195
|
+
return vazia('vazia', { acao: 'encerrar', motivo: 'arco-encerrado' });
|
|
196
|
+
}
|
|
197
|
+
if (estado.situacao === 'agendado')
|
|
198
|
+
return vazia('bloqueada', { acao: 'aguardar', motivo: 'agendado', ate: conteudo.janela.inicio });
|
|
199
|
+
if (!(0, noctum_envelope_1.envelopeComTrabalhos)(conteudo)) {
|
|
200
|
+
return vazia('fonte-indisponivel', { acao: 'aguardar', motivo: 'fonte-indisponivel', ate: daqui(exports.CADENCIA_MS, conteudo.janela.fim) }, ['o envelope vigente é v1, sem lista de trabalhos']);
|
|
201
|
+
}
|
|
202
|
+
// Primeiro quem já foi entregue, para as dependências (aqui ou, no arco entre máquinas, em outra); depois cada trabalho.
|
|
203
|
+
const entregues = new Set(conteudo.trabalhos.filter(t => {
|
|
204
|
+
const f = fatos.porTrabalho.get(t.id);
|
|
205
|
+
return fatos.coordenacao?.entregues.has(t.id) || (!!f && f.threads.length === 1 && !!f.entregueEm && f.threads[0].roadmap === t.item);
|
|
206
|
+
}).map(t => t.id));
|
|
207
|
+
// S7 do CHECK: quem fechou sem entrega nunca mais entrega neste arco, nem quem depende dele, de qualquer distância. No arco
|
|
208
|
+
// entre máquinas (B1 e S1 da rodada 3 da ork-rm058n3), a rede decide antes da thread local: o entregue lá nunca fica sem
|
|
209
|
+
// saída por uma thread antiga fechada aqui, e o encerrado lá fica sem saída aqui também.
|
|
210
|
+
const semSaida = new Set(conteudo.trabalhos.filter(t => {
|
|
211
|
+
if (fatos.coordenacao?.entregues.has(t.id))
|
|
212
|
+
return false;
|
|
213
|
+
if (fatos.coordenacao?.encerrados?.has(t.id))
|
|
214
|
+
return true;
|
|
215
|
+
const f = fatos.porTrabalho.get(t.id);
|
|
216
|
+
return !!f && f.threads.length === 1 && !f.entregueEm && f.threads[0].status === 'fechada' && f.threads[0].roadmap === t.item;
|
|
217
|
+
}).map(t => t.id));
|
|
218
|
+
for (let mudou = true; mudou;) {
|
|
219
|
+
mudou = false;
|
|
220
|
+
for (const t of conteudo.trabalhos) {
|
|
221
|
+
if (!semSaida.has(t.id) && !entregues.has(t.id) && t.dependeDe.some(d => semSaida.has(d))) {
|
|
222
|
+
semSaida.add(t.id);
|
|
223
|
+
mudou = true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const trabalhos = conteudo.trabalhos.map((t, i) => classificar(t, i, fatos.porTrabalho.get(t.id), fatos, entregues, semSaida, estado));
|
|
228
|
+
const candidatos = trabalhos.filter(t => t.estado === 'despachavel' || t.estado === 'abrir').sort(antes);
|
|
229
|
+
// Thread ilegível só é lacuna quando pode ser a de um trabalho (S7 do CHECK): a classificação já a pôs no trabalho.
|
|
230
|
+
const lacunas = trabalhos.filter(t => t.motivo && DE_LACUNA.includes(t.motivo)).map(t => `trabalho ${t.id}: ${t.detalhe}`);
|
|
231
|
+
const terminal = (t) => t.estado === 'entregue' || t.estado === 'encerrado-sem-entrega' ||
|
|
232
|
+
t.motivo === 'dependencia-encerrada';
|
|
233
|
+
const situacao = candidatos.length ? 'com-trabalho' : trabalhos.some(t => t.estado === 'em-curso') ? 'em-curso'
|
|
234
|
+
: lacunas.length ? 'fonte-indisponivel' : trabalhos.every(terminal) ? 'vazia' : 'bloqueada';
|
|
235
|
+
const fim = conteudo.janela.fim;
|
|
236
|
+
const backoff = Math.min(exports.BACKOFF_MAXIMO_MS, Math.max(exports.CADENCIA_MS, Math.floor((agora - ultimoProgresso(estado, trabalhos)) / 2)));
|
|
237
|
+
const decisao = situacao === 'com-trabalho' ? { acao: 'despachar' }
|
|
238
|
+
: situacao === 'vazia' ? { acao: 'encerrar', motivo: 'fila-vazia' }
|
|
239
|
+
: situacao === 'em-curso' ? { acao: 'aguardar', motivo: 'em-curso', ate: daqui(exports.CADENCIA_MS, fim) }
|
|
240
|
+
: { acao: 'aguardar', motivo: situacao, ate: daqui(backoff, fim) };
|
|
241
|
+
return { contrato: exports.CONTRATO_FILA, arco, envelopeSha256: estado.envelopeSha256, quando, situacao, trabalhos, candidatos, lacunas, decisao };
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Os fatos da fila, relidos do disco: o arco, as threads de cada trabalho, o passo do condutor delas, as reservas da
|
|
245
|
+
* última cópia local (sem rede) e o lote. `lerReservas` é dependência dos testes.
|
|
246
|
+
*/
|
|
247
|
+
function fatosDaFila(carregado, arco, opcoes = {}) {
|
|
248
|
+
const quando = opcoes.quando ?? new Date().toISOString();
|
|
249
|
+
const { raiz } = carregado;
|
|
250
|
+
const estado = (0, noctum_arco_1.lerArco)(raiz, arco, quando);
|
|
251
|
+
const maquina = (0, maquina_1.nomeDaMaquina)(opcoes.maquina);
|
|
252
|
+
const lidas = (opcoes.lerReservas ?? (() => (0, branch_de_estado_1.pontaLocal)(raiz, roadmap_reservas_1.REMOTO_PADRAO, roadmap_reservas_1.BRANCH_DE_RESERVAS) === null
|
|
253
|
+
? { leitura: 'sem-copia', reservas: [] }
|
|
254
|
+
: { leitura: 'copia-local', reservas: (0, roadmap_reservas_1.reservasLocais)(raiz) }))();
|
|
255
|
+
const fatos = { arco, quando, maquina, estado, porTrabalho: new Map(), threadsIlegiveis: [],
|
|
256
|
+
modosPermitidos: carregado.manifesto.conduction.allowed_modes, ...(opcoes.coordenacao ? { coordenacao: opcoes.coordenacao } : {}),
|
|
257
|
+
...(opcoes.supervisao ? { supervisao: opcoes.supervisao } : {}),
|
|
258
|
+
reservas: { leitura: lidas.leitura, porItem: new Map(lidas.reservas.map(r => [r.item, { maquina: r.maquina, thread: r.thread }])) } };
|
|
259
|
+
if (!estado?.conteudo || !(0, noctum_envelope_1.envelopeComTrabalhos)(estado.conteudo))
|
|
260
|
+
return fatos;
|
|
261
|
+
const threads = [];
|
|
262
|
+
for (const id of (0, thread_1.listarIds)(raiz)) {
|
|
263
|
+
try {
|
|
264
|
+
threads.push((0, thread_1.lerThread)(raiz, id));
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
fatos.threadsIlegiveis.push(id);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const passos = new Map((0, conducao_sentinela_1.passosDoCondutor)(carregado, { quando }).map(p => [p.thread, p]));
|
|
271
|
+
for (const t of estado.conteudo.trabalhos) {
|
|
272
|
+
let casam;
|
|
273
|
+
let ilegivel = null;
|
|
274
|
+
if (t.thread !== undefined) {
|
|
275
|
+
casam = threads.filter(x => x.id === t.thread);
|
|
276
|
+
if (!casam.length && fatos.threadsIlegiveis.includes(t.thread))
|
|
277
|
+
ilegivel = t.thread;
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const alvo = (0, noctum_envelope_1.shaDoPedido)(t.pedido);
|
|
281
|
+
casam = threads.filter(x => x.roadmap === t.item && x.pedido?.sha256 === alvo);
|
|
282
|
+
// Sem casar e com thread ilegível, ela pode ser a do trabalho: abrir outra duplicaria a thread.
|
|
283
|
+
if (!casam.length && fatos.threadsIlegiveis.length)
|
|
284
|
+
ilegivel = fatos.threadsIlegiveis[0];
|
|
285
|
+
}
|
|
286
|
+
const th = casam.length === 1 ? casam[0] : null;
|
|
287
|
+
let eventos = [];
|
|
288
|
+
try {
|
|
289
|
+
eventos = th ? (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, th.id)) : [];
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
ilegivel = th.id;
|
|
293
|
+
}
|
|
294
|
+
let pedidoGuardado = false;
|
|
295
|
+
try {
|
|
296
|
+
pedidoGuardado = !!th && (0, thread_1.pedidoDaThread)(raiz, th) !== null;
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
pedidoGuardado = false;
|
|
300
|
+
}
|
|
301
|
+
fatos.porTrabalho.set(t.id, {
|
|
302
|
+
threads: casam, ilegivel,
|
|
303
|
+
entregueEm: eventos.find(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.shipConcluido)?.ts ?? null,
|
|
304
|
+
despachada: eventos.some(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.faseDespachada),
|
|
305
|
+
despachoFalho: !eventos.some(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.faseDespachada) &&
|
|
306
|
+
eventos.some(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.despachoFalhou && typeof e.sessionId === 'string'),
|
|
307
|
+
pedidoGuardado,
|
|
308
|
+
passo: th ? passos.get(th.id) ?? null : null,
|
|
309
|
+
espera: th && th.status !== 'fechada' ? (0, parado_no_condutor_1.esperaDoCondutor)(th, eventos, quando) : null,
|
|
310
|
+
doDono: th && th.status !== 'fechada' ? (0, parado_no_condutor_1.pendenciaDoDono)(th, eventos, quando) : null,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
return fatos;
|
|
314
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
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.pedidoDoArco = exports.linhaDoArco = exports.MOTIVO_DO_ARCO_ILEGIVEL = exports.MOTIVO_DA_GUARDA = void 0;
|
|
37
|
+
exports.lerArcosDaRaiz = lerArcosDaRaiz;
|
|
38
|
+
exports.arcoDosEventos = arcoDosEventos;
|
|
39
|
+
exports.arcoDoUltimoDespacho = arcoDoUltimoDespacho;
|
|
40
|
+
exports.vinculosDaThread = vinculosDaThread;
|
|
41
|
+
exports.guardaOsCaminhosManuais = guardaOsCaminhosManuais;
|
|
42
|
+
exports.guardaDaThread = guardaDaThread;
|
|
43
|
+
exports.arcoDoPasso = arcoDoPasso;
|
|
44
|
+
/**
|
|
45
|
+
* RM-058, integração das fatias N1 a N6 (T1.1 da ork-rm058integra, D3 e D5): quem é thread de um arco #Noctum.
|
|
46
|
+
*
|
|
47
|
+
* O arco entrega as threads dele pelo passo da entrega da N5: a revisão independente, o verify no SHA, o envelope conferido
|
|
48
|
+
* antes de cada efeito e o MASTER por omissão. Os caminhos de fora do arco não sabiam disso: a sessão do bloco chegava ao
|
|
49
|
+
* SHIP e mesclava pelo `ork ship`, sem a revisão, e nada impedia o `ork ship registrar-pr` de gravar a entrega dela.
|
|
50
|
+
*
|
|
51
|
+
* A regra (D3) mora aqui, e os chamadores só leem as funções. É thread de um arco a que está:
|
|
52
|
+
*
|
|
53
|
+
* - na lista do envelope vigente ou na da proposta que espera o dono no prazo: a thread fixada no trabalho, ou a que casa
|
|
54
|
+
* com o item e o sha256 do pedido do trabalho (a regra da fila e da supervisão);
|
|
55
|
+
* - no log de despachos do arco (a thread reservada e a que o despacho abriu);
|
|
56
|
+
* - ou cujo último `phase_dispatch` tem a correlação `noctum:<arco>`.
|
|
57
|
+
*
|
|
58
|
+
* Nos caminhos manuais (`ork ship`, o `ork_ship` do MCP, `ork ship publicar`, `ork ship registrar-pr` e
|
|
59
|
+
* `ork conducao atualizar`), guardam o arco agendado, o vigente e o proposto com a proposta no prazo. O proposto sem
|
|
60
|
+
* proposta no prazo (o nunca autorizado fica `proposto` para sempre), o expirado, o revogado e o encerrado não guardam. O
|
|
61
|
+
* arco que não se lê recusa só a thread cujo último despacho tem a correlação dele (`noctum.guarda.arco-ilegivel`); as
|
|
62
|
+
* outras seguem. Sem nenhum arco nesta raiz, nada é lido além da pasta dos arcos: quem não usa o #Noctum não paga nada.
|
|
63
|
+
*
|
|
64
|
+
* Nos caminhos automáticos (T1.2, D4), a batida, a varredura, a Sentinela e a máquina ociosa leem o campo `arco` do passo
|
|
65
|
+
* do condutor (`arcoDoPasso`): a guarda segura toda ação; a retenção, a do arco terminal que despachou a thread por último,
|
|
66
|
+
* segura o despacho, a retomada e o merge até um despacho fora do arco ou um arco novo, autorizado depois, que a liste.
|
|
67
|
+
*/
|
|
68
|
+
const fs = __importStar(require("node:fs"));
|
|
69
|
+
const path = __importStar(require("node:path"));
|
|
70
|
+
const estado_thread_1 = require("./estado-thread");
|
|
71
|
+
const ledger_1 = require("./ledger");
|
|
72
|
+
const locale_1 = require("./locale");
|
|
73
|
+
const noctum_arco_1 = require("./noctum-arco");
|
|
74
|
+
const noctum_sessoes_em_voo_1 = require("./noctum-sessoes-em-voo");
|
|
75
|
+
const noctum_envelope_1 = require("./noctum-envelope");
|
|
76
|
+
const thread_1 = require("./thread");
|
|
77
|
+
exports.MOTIVO_DA_GUARDA = 'noctum.guarda.thread-do-arco';
|
|
78
|
+
exports.MOTIVO_DO_ARCO_ILEGIVEL = 'noctum.guarda.arco-ilegivel';
|
|
79
|
+
/** A recusa com os três textos do catálogo, cada um remontável no locale de quem imprime. */
|
|
80
|
+
function recusa(motivo, thread, arco, situacao, origem, detalhe, correcao) {
|
|
81
|
+
return { motivo, thread, arco, situacao, origem, detalhe: (0, locale_1.textoDoCatalogo)(detalhe), correcao: (0, locale_1.textoDoCatalogo)(correcao),
|
|
82
|
+
texto: (0, locale_1.textoDoCatalogo)((m) => `${detalhe(m)}; ${correcao(m)}`) };
|
|
83
|
+
}
|
|
84
|
+
/** Os nomes das pastas de arco desta raiz de estado (o `listarArcos` do modo, sem puxar o passo, a entrega e o relatório). */
|
|
85
|
+
function nomesDosArcos(raiz) {
|
|
86
|
+
try {
|
|
87
|
+
return fs.readdirSync(path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery', 'noctum', 'arcos')).filter(n => noctum_envelope_1.ID_DO_ARCO.test(n)).sort();
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/** Lê cada arco desta raiz uma vez. O arco que não se lê fica com o motivo, e os outros seguem. */
|
|
94
|
+
function lerArcosDaRaiz(raiz, quando = new Date().toISOString()) {
|
|
95
|
+
const arcos = { quando, lidos: new Map(), ilegiveis: new Map() };
|
|
96
|
+
for (const arco of nomesDosArcos(raiz)) {
|
|
97
|
+
try {
|
|
98
|
+
const lido = (0, noctum_arco_1.lerArcoComProposta)(raiz, arco, quando);
|
|
99
|
+
if (lido)
|
|
100
|
+
arcos.lidos.set(arco, lido);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
arcos.ilegiveis.set(arco, e instanceof noctum_envelope_1.RecusaDoArco ? e.motivo : (e instanceof Error ? e.message : String(e)).split('\n')[0].slice(0, 160));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return arcos;
|
|
107
|
+
}
|
|
108
|
+
/** O arco da correlação `noctum:<arco>` do último `phase_dispatch` entre os eventos dados; `null` sem ele. */
|
|
109
|
+
function arcoDosEventos(eventos) {
|
|
110
|
+
for (let i = eventos.length - 1; i >= 0; i--) {
|
|
111
|
+
if (eventos[i].tipo !== ledger_1.TIPOS_DE_EVENTO.faseDespachada)
|
|
112
|
+
continue;
|
|
113
|
+
const c = eventos[i].correlacao;
|
|
114
|
+
const arco = typeof c === 'string' && c.startsWith('noctum:') ? c.slice('noctum:'.length) : '';
|
|
115
|
+
return noctum_envelope_1.ID_DO_ARCO.test(arco) ? arco : null;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/** O arco da correlação `noctum:<arco>` do último `phase_dispatch` da thread; `null` sem despacho ou com outra correlação. */
|
|
120
|
+
function arcoDoUltimoDespacho(raiz, thread) {
|
|
121
|
+
try {
|
|
122
|
+
return arcoDosEventos((0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread)));
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/** A thread está na lista? A fixada no trabalho, ou a que casa com o item e o sha256 do pedido dele. */
|
|
129
|
+
function naLista(conteudo, thread, dados) {
|
|
130
|
+
return !!conteudo?.trabalhos?.some(w => w.thread !== undefined ? w.thread === thread
|
|
131
|
+
: w.pedido !== undefined && dados().roadmap === w.item && dados().pedido === (0, noctum_envelope_1.shaDoPedido)(w.pedido));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Os vínculos da thread com os arcos lidos, um por arco, na ordem das origens: a lista do envelope vigente, a da proposta
|
|
135
|
+
* no prazo, o log de despachos e a correlação do último despacho (`ultimo`, quando o chamador já a leu).
|
|
136
|
+
*/
|
|
137
|
+
function vinculosDaThread(raiz, arcos, thread, ultimo) {
|
|
138
|
+
if (!arcos.lidos.size)
|
|
139
|
+
return [];
|
|
140
|
+
const doUltimo = ultimo === undefined ? arcoDoUltimoDespacho(raiz, thread) : ultimo;
|
|
141
|
+
let lidos = null;
|
|
142
|
+
const dados = () => {
|
|
143
|
+
if (!lidos) {
|
|
144
|
+
try {
|
|
145
|
+
const t = (0, thread_1.lerThread)(raiz, thread);
|
|
146
|
+
lidos = { roadmap: t.roadmap ?? null, pedido: t.pedido?.sha256 ?? null };
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
lidos = { roadmap: null, pedido: null };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return lidos;
|
|
153
|
+
};
|
|
154
|
+
const vinculos = [];
|
|
155
|
+
for (const [arco, { estado, proposta }] of arcos.lidos) {
|
|
156
|
+
const origem = naLista(estado.conteudo, thread, dados) ? 'envelope'
|
|
157
|
+
: naLista(proposta, thread, dados) ? 'proposta'
|
|
158
|
+
: estado.despachos.some(d => d.thread === thread || d.threadDespachada === thread) ? 'despacho'
|
|
159
|
+
: doUltimo === arco ? 'correlacao' : null;
|
|
160
|
+
if (origem)
|
|
161
|
+
vinculos.push({ arco, situacao: estado.situacao, origem });
|
|
162
|
+
}
|
|
163
|
+
return vinculos;
|
|
164
|
+
}
|
|
165
|
+
/** D3: guardam os caminhos manuais o arco agendado, o vigente e o proposto pela proposta no prazo (a única que dá vínculo). */
|
|
166
|
+
function guardaOsCaminhosManuais(v) {
|
|
167
|
+
return v.situacao === 'agendado' || v.situacao === 'vigente' || (v.situacao === 'proposto' && v.origem === 'proposta');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* A guarda dos caminhos manuais: a recusa tipada quando a thread é trabalho de um arco que a guarda agora, ou `null`. O
|
|
171
|
+
* `doArco` é o arco que entrega pelo próprio passo (o da entrega da N5 publica com ele): a guarda dele não o recusa, e a de
|
|
172
|
+
* outro arco recusa. `arcos` reaproveita a leitura de quem confere várias threads de uma vez (o `registrar-pr --todas`).
|
|
173
|
+
*/
|
|
174
|
+
function guardaDaThread(raiz, thread, quando = new Date().toISOString(), opcoes = {}) {
|
|
175
|
+
const arcos = opcoes.arcos ?? lerArcosDaRaiz(raiz, quando);
|
|
176
|
+
if (!arcos.lidos.size && !arcos.ilegiveis.size)
|
|
177
|
+
return null;
|
|
178
|
+
const ultimo = arcoDoUltimoDespacho(raiz, thread);
|
|
179
|
+
const ilegivel = ultimo !== null && ultimo !== opcoes.doArco ? arcos.ilegiveis.get(ultimo) : undefined;
|
|
180
|
+
if (ultimo !== null && ilegivel !== undefined) {
|
|
181
|
+
return recusa(exports.MOTIVO_DO_ARCO_ILEGIVEL, thread, ultimo, null, 'correlacao', (m) => m.ship.guarda.arcoIlegivel(thread, ultimo, ilegivel), (m) => m.ship.guarda.arcoIlegivelCorrecao(ultimo));
|
|
182
|
+
}
|
|
183
|
+
const vinculos = vinculosDaThread(raiz, arcos, thread, ultimo);
|
|
184
|
+
const v = vinculos.find(x => x.arco !== opcoes.doArco && guardaOsCaminhosManuais(x));
|
|
185
|
+
if (!v) {
|
|
186
|
+
// A2 do CHECK: no arco que terminou (revogado, expirado ou encerrado), a sessão que ele despachou e que ainda conduz a
|
|
187
|
+
// thread não entrega fora dele; sem sessão dele em voo, a thread se entrega à mão, como antes.
|
|
188
|
+
for (const t of vinculos.filter(x => x.arco !== opcoes.doArco && TERMINAIS.includes(x.situacao))) {
|
|
189
|
+
const lido = arcos.lidos.get(t.arco);
|
|
190
|
+
const sessao = lido ? sessaoDoArcoEmVoo(raiz, thread, lido.estado) : null;
|
|
191
|
+
if (!sessao)
|
|
192
|
+
continue;
|
|
193
|
+
if ('seq' in sessao) {
|
|
194
|
+
return recusa(exports.MOTIVO_DA_GUARDA, thread, t.arco, t.situacao, t.origem, (m) => m.ship.guarda.reservaDoArco(thread, t.arco, m.ship.guarda.situacoes[t.situacao] ?? t.situacao, sessao.seq), (m) => m.ship.guarda.reservaDoArcoCorrecao(t.arco));
|
|
195
|
+
}
|
|
196
|
+
return recusa(exports.MOTIVO_DA_GUARDA, thread, t.arco, t.situacao, t.origem, (m) => m.ship.guarda.sessaoDoArco(thread, t.arco, m.ship.guarda.situacoes[t.situacao] ?? t.situacao, sessao.sessionId), (m) => m.ship.guarda.sessaoDoArcoCorrecao(t.arco));
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
return recusa(exports.MOTIVO_DA_GUARDA, thread, v.arco, v.situacao, v.origem, (m) => m.ship.guarda.doArco(thread, v.arco, m.ship.guarda.situacoes[v.situacao] ?? v.situacao, m.ship.guarda.origens[v.origem] ?? v.origem), (m) => m.ship.guarda.doArcoCorrecao(v.arco));
|
|
201
|
+
}
|
|
202
|
+
/** As situações do arco que já terminou: nada novo sai dele, e a retenção vale (D4). */
|
|
203
|
+
const TERMINAIS = ['expirado', 'revogado', 'encerrado'];
|
|
204
|
+
/**
|
|
205
|
+
* A2 do CHECK: a sessão que o arco despachou nesta thread e que ainda não acabou, ou `null`. É a conta do fechamento
|
|
206
|
+
* (`sessoesEmVooDoArco`): a sessão concluída sem resultado, morte nem superação no ledger, e a da reserva pendente, que o
|
|
207
|
+
* runtime abriu antes de o condutor morrer (N4 do CHECK 2), com o id que ele disse ou, sem id, a reserva (M3 do CHECK 3).
|
|
208
|
+
* O ledger que não se lê não prova o fim: a guarda falha fechada. Só os despachos desta thread entram, e a reserva pendente
|
|
209
|
+
* ainda sem thread gravada (M2 do CHECK 3): a guarda não lê os ledgers do arco inteiro a cada consulta.
|
|
210
|
+
*/
|
|
211
|
+
function sessaoDoArcoEmVoo(raiz, thread, estado) {
|
|
212
|
+
const despachos = estado.despachos.filter(d => (d.threadDespachada ?? d.thread) === thread || (d.desfecho === 'pendente' && !(d.threadDespachada ?? d.thread)));
|
|
213
|
+
const s = (0, noctum_sessoes_em_voo_1.sessoesEmVooDoArco)(raiz, { ...estado, despachos }).find(x => x.thread === thread);
|
|
214
|
+
return !s ? null : s.sessionId ? { sessionId: s.sessionId } : { seq: s.seq };
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* O arco que segura ou retém a thread nos caminhos automáticos, ou `null`. `eventos` é o ledger da thread que o chamador
|
|
218
|
+
* já leu (o passo do condutor lê todos), e `arcos` é a leitura única desta raiz.
|
|
219
|
+
*/
|
|
220
|
+
function arcoDoPasso(raiz, arcos, thread, eventos) {
|
|
221
|
+
if (!arcos.lidos.size && !arcos.ilegiveis.size)
|
|
222
|
+
return null;
|
|
223
|
+
const ultimo = arcoDosEventos(eventos);
|
|
224
|
+
const ilegivel = ultimo === null ? undefined : arcos.ilegiveis.get(ultimo);
|
|
225
|
+
if (ultimo !== null && ilegivel !== undefined) {
|
|
226
|
+
return { arco: ultimo, situacao: null, efeito: 'guarda', motivo: exports.MOTIVO_DO_ARCO_ILEGIVEL,
|
|
227
|
+
detalhe: (0, locale_1.textoDoCatalogo)((m) => m.ship.guarda.arcoIlegivel(thread, ultimo, ilegivel)) };
|
|
228
|
+
}
|
|
229
|
+
const vinculos = vinculosDaThread(raiz, arcos, thread, ultimo);
|
|
230
|
+
const g = vinculos.find(guardaOsCaminhosManuais);
|
|
231
|
+
if (g) {
|
|
232
|
+
return { arco: g.arco, situacao: g.situacao, efeito: 'guarda', motivo: exports.MOTIVO_DA_GUARDA,
|
|
233
|
+
detalhe: (0, locale_1.textoDoCatalogo)((m) => m.ship.guarda.doArco(thread, g.arco, m.ship.guarda.situacoes[g.situacao] ?? g.situacao, m.ship.guarda.origens[g.origem] ?? g.origem)) };
|
|
234
|
+
}
|
|
235
|
+
const doUltimo = ultimo === null ? undefined : arcos.lidos.get(ultimo);
|
|
236
|
+
if (ultimo === null || !doUltimo || !TERMINAIS.includes(doUltimo.estado.situacao))
|
|
237
|
+
return null;
|
|
238
|
+
// Um arco novo, autorizado depois deste, que lista a thread (na lista dele ou no log de despachos) acaba a retenção.
|
|
239
|
+
const desde = Date.parse(doUltimo.estado.autorizadoPor?.recebidoEm ?? '');
|
|
240
|
+
const novo = vinculos.some(v => v.arco !== ultimo && (v.origem === 'envelope' || v.origem === 'despacho') &&
|
|
241
|
+
Date.parse(arcos.lidos.get(v.arco)?.estado.autorizadoPor?.recebidoEm ?? '') > desde);
|
|
242
|
+
if (novo)
|
|
243
|
+
return null;
|
|
244
|
+
const situacao = doUltimo.estado.situacao;
|
|
245
|
+
return { arco: ultimo, situacao, efeito: 'retencao', motivo: exports.MOTIVO_DA_GUARDA,
|
|
246
|
+
detalhe: (0, locale_1.textoDoCatalogo)((m) => m.ship.guarda.retencao(thread, ultimo, m.ship.guarda.situacoes[situacao] ?? situacao)) };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* D5: a linha que o passo do arco anexa ao pedido de toda sessão que ele despacha. Fixa e determinística: o mesmo arco dá
|
|
250
|
+
* o mesmo texto em toda chamada, e o `rodarFase` segue idempotente para a mesma fase e o mesmo prompt.
|
|
251
|
+
*/
|
|
252
|
+
const linhaDoArco = (arco) => `Esta thread é trabalho do arco \`${arco}\` do #Noctum: o SHIP e o MASTER dela são do arco; não faça push, não abra PR e não mescle.`;
|
|
253
|
+
exports.linhaDoArco = linhaDoArco;
|
|
254
|
+
/** O pedido da sessão do arco: o do dono e, no fim, a linha do arco. */
|
|
255
|
+
const pedidoDoArco = (pedido, arco) => `${pedido.trimEnd()}\n\n${(0, exports.linhaDoArco)(arco)}`;
|
|
256
|
+
exports.pedidoDoArco = pedidoDoArco;
|