@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,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fatosDeCapacidade = fatosDeCapacidade;
|
|
4
|
+
exports.admitir = admitir;
|
|
5
|
+
exports.escolherConta = escolherConta;
|
|
6
|
+
const conducao_1 = require("./conducao");
|
|
7
|
+
const ledger_1 = require("./ledger");
|
|
8
|
+
const ocupacao_1 = require("./ocupacao");
|
|
9
|
+
const sessoes_contas_1 = require("./sessoes-contas");
|
|
10
|
+
const thread_1 = require("./thread");
|
|
11
|
+
/** O runtime mostra a sessão trabalhando agora: o claude-bg diz `running` ou `busy` (o watcher chama de `working`). */
|
|
12
|
+
const TRABALHANDO = ['running', 'busy', 'working'];
|
|
13
|
+
const estadoDe = (s) => String(s.state ?? s.status ?? '').trim().toLowerCase();
|
|
14
|
+
/**
|
|
15
|
+
* O runtime prova que a sessão do lease acabou? Presente com estado terminal ou fantasma, sim. Ausente, só no
|
|
16
|
+
* claude-bg (o `claude agents` lista as sessões que o daemon da conta mantém), com todas as fontes lidas e a conta
|
|
17
|
+
* dela entre as consultadas. O codex lista só rollouts recentes: ausência lá não prova nada.
|
|
18
|
+
*/
|
|
19
|
+
function encerradaPeloRuntime(dono, leitura, porSessao, semLacuna) {
|
|
20
|
+
const vista = porSessao.get(dono.sessionId);
|
|
21
|
+
if (vista)
|
|
22
|
+
return (0, sessoes_contas_1.encerradaNaLista)(vista);
|
|
23
|
+
if (!semLacuna || dono.runtime !== 'claude-bg')
|
|
24
|
+
return false;
|
|
25
|
+
return leitura.contas.some(c => c.runtime === 'claude-bg' && (c.perfil?.id ?? null) === dono.perfil);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A ocupação desta máquina agora, relida a cada chamada. `consultar` é dependência dos testes; sem ela, as sessões de
|
|
29
|
+
* todas as contas pelo `consultarContas`, a mesma leitura do escalonador.
|
|
30
|
+
*/
|
|
31
|
+
function fatosDeCapacidade(carregado, opcoes = {}) {
|
|
32
|
+
const quando = opcoes.quando ?? new Date().toISOString();
|
|
33
|
+
const { raiz, manifesto } = carregado;
|
|
34
|
+
const staleMin = manifesto.concurrency.stale_after_min;
|
|
35
|
+
const leitura = (opcoes.consultar ?? (() => (0, sessoes_contas_1.consultarContas)(raiz, { staleMin })))();
|
|
36
|
+
const lacunas = leitura.fontes.filter(f => !f.ok).map(f => `${f.origem}: ${f.detalhe}`);
|
|
37
|
+
const porSessao = new Map(leitura.sessoes.map(s => [s.sessionId, s]));
|
|
38
|
+
const ocupantes = [];
|
|
39
|
+
const encerradasPeloRuntime = [];
|
|
40
|
+
const contadas = new Set();
|
|
41
|
+
// A sessão que a regra da vaga solta (turno encerrado, espera do dono, parada) não volta pela lista do runtime,
|
|
42
|
+
// a não ser que o runtime a mostre trabalhando agora (A8 do CHECK): a regra da vaga lê só o ledger.
|
|
43
|
+
const soltas = new Set();
|
|
44
|
+
for (const id of (0, thread_1.listarIds)(raiz)) {
|
|
45
|
+
let atual = null;
|
|
46
|
+
try {
|
|
47
|
+
atual = (0, conducao_1.conducaoDaThread)(raiz, id);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!atual)
|
|
53
|
+
continue;
|
|
54
|
+
if (atual.dono.tipo === 'processo' && (atual.operacao === 'phase.run' || atual.operacao === 'retry.run')) {
|
|
55
|
+
ocupantes.push({ sessionId: null, thread: id, runtime: null, conta: null, revisao: atual.fase === 'CHECK', origem: 'despacho' });
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (atual.dono.tipo !== 'sessao')
|
|
59
|
+
continue;
|
|
60
|
+
const dono = atual.dono;
|
|
61
|
+
const vista = porSessao.get(dono.sessionId);
|
|
62
|
+
try {
|
|
63
|
+
if ((0, ocupacao_1.sessaoLivreDaVaga)((0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id)), atual.desde, quando, staleMin, dono.sessionId) &&
|
|
64
|
+
!(vista?.viva && TRABALHANDO.includes(estadoDe(vista)))) {
|
|
65
|
+
soltas.add(dono.sessionId);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch { /* ledger ilegível: a condução viva continua contando, como no portão do phase run */ }
|
|
70
|
+
if (encerradaPeloRuntime(dono, leitura, porSessao, lacunas.length === 0)) {
|
|
71
|
+
encerradasPeloRuntime.push(dono.sessionId);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
contadas.add(dono.sessionId);
|
|
75
|
+
// A5 do CHECK: o despacho sem `--perfil` grava o lease sem conta; a conta é a que o runtime atribui à sessão.
|
|
76
|
+
ocupantes.push({ sessionId: dono.sessionId, thread: id, runtime: dono.runtime, conta: dono.perfil ?? vista?.perfil ?? null,
|
|
77
|
+
revisao: atual.fase === 'CHECK', origem: 'conducao' });
|
|
78
|
+
}
|
|
79
|
+
for (const s of leitura.sessoes) {
|
|
80
|
+
if (!s.viva || !TRABALHANDO.includes(estadoDe(s)) || contadas.has(s.sessionId) || soltas.has(s.sessionId) ||
|
|
81
|
+
encerradasPeloRuntime.includes(s.sessionId))
|
|
82
|
+
continue;
|
|
83
|
+
contadas.add(s.sessionId);
|
|
84
|
+
ocupantes.push({ sessionId: s.sessionId, thread: null, runtime: s.runtime, conta: s.perfil, revisao: false, origem: 'runtime' });
|
|
85
|
+
}
|
|
86
|
+
return { quando, ocupantes, lacunas, encerradasPeloRuntime };
|
|
87
|
+
}
|
|
88
|
+
const limiteDe = (lista, chave, nome) => lista.find(x => x[chave] === nome)?.sessoes ?? null;
|
|
89
|
+
/**
|
|
90
|
+
* Cabe mais esta sessão? Todos os limites ao mesmo tempo, na ordem: leitura completa, conta e runtime autorizados,
|
|
91
|
+
* o projeto (o portão do `phase run`, que o chamador consulta para a thread), a máquina, a margem de revisão (a
|
|
92
|
+
* execução não usa os slots reservados ao CHECK), a conta e o runtime.
|
|
93
|
+
*/
|
|
94
|
+
function admitir(pedido, limites, fatos, vagaDoProjeto) {
|
|
95
|
+
if (fatos.lacunas.length) {
|
|
96
|
+
return { ok: false, motivo: 'capacidade.fonte-indisponivel', detalhe: `sessões sem leitura: ${fatos.lacunas.join('; ')}` };
|
|
97
|
+
}
|
|
98
|
+
const limiteDoRuntime = limiteDe(limites.porRuntime, 'runtime', pedido.runtime);
|
|
99
|
+
if (limiteDoRuntime === null) {
|
|
100
|
+
return { ok: false, motivo: 'capacidade.runtime-nao-autorizado', detalhe: `o runtime ${pedido.runtime} não está no envelope` };
|
|
101
|
+
}
|
|
102
|
+
const limiteDaConta = limiteDe(limites.porConta, 'conta', pedido.conta);
|
|
103
|
+
if (limiteDaConta === null) {
|
|
104
|
+
return { ok: false, motivo: 'capacidade.conta-nao-autorizada', detalhe: `a conta ${pedido.conta} não está no envelope` };
|
|
105
|
+
}
|
|
106
|
+
if (vagaDoProjeto)
|
|
107
|
+
return { ok: false, motivo: 'capacidade.projeto', detalhe: vagaDoProjeto.detalhe };
|
|
108
|
+
const total = fatos.ocupantes.length;
|
|
109
|
+
if (total >= limites.maquina) {
|
|
110
|
+
return { ok: false, motivo: 'capacidade.maquina', detalhe: `${total} sessão(ões) nesta máquina e o limite do envelope é ${limites.maquina}` };
|
|
111
|
+
}
|
|
112
|
+
const execucao = fatos.ocupantes.filter(o => !o.revisao).length;
|
|
113
|
+
if (!pedido.revisao && execucao >= limites.maquina - limites.revisao) {
|
|
114
|
+
return { ok: false, motivo: 'capacidade.revisao', detalhe: `${execucao} sessão(ões) de execução e ${limites.revisao} slot(s) ` +
|
|
115
|
+
`reservado(s) à revisão de ${limites.maquina}: só o CHECK usa o que sobra` };
|
|
116
|
+
}
|
|
117
|
+
const naConta = fatos.ocupantes.filter(o => o.conta === pedido.conta).length;
|
|
118
|
+
if (naConta >= limiteDaConta) {
|
|
119
|
+
return { ok: false, motivo: 'capacidade.conta', detalhe: `${naConta} sessão(ões) na conta ${pedido.conta} e o limite é ${limiteDaConta}` };
|
|
120
|
+
}
|
|
121
|
+
const noRuntime = fatos.ocupantes.filter(o => o.runtime === pedido.runtime).length;
|
|
122
|
+
if (noRuntime >= limiteDoRuntime) {
|
|
123
|
+
return { ok: false, motivo: 'capacidade.runtime', detalhe: `${noRuntime} sessão(ões) no ${pedido.runtime} e o limite é ${limiteDoRuntime}` };
|
|
124
|
+
}
|
|
125
|
+
return { ok: true };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A conta do despacho: entre as do envelope que são perfis do runtime (`perfisDoRuntime`, do store de contas), a com
|
|
129
|
+
* mais folga no limite dela; empate pela ordem do envelope. `null` quando nenhuma tem vaga.
|
|
130
|
+
*/
|
|
131
|
+
function escolherConta(limites, fatos, perfisDoRuntime) {
|
|
132
|
+
let melhor = null;
|
|
133
|
+
for (const { conta, sessoes } of limites.porConta) {
|
|
134
|
+
if (!perfisDoRuntime.includes(conta))
|
|
135
|
+
continue;
|
|
136
|
+
const folga = sessoes - fatos.ocupantes.filter(o => o.conta === conta).length;
|
|
137
|
+
if (folga > 0 && (!melhor || folga > melhor.folga))
|
|
138
|
+
melhor = { conta, folga };
|
|
139
|
+
}
|
|
140
|
+
return melhor?.conta ?? null;
|
|
141
|
+
}
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RM-058, fatia N5 (D4 e D5 da ork-rm058n5): o CHANGELOG e os conflitos só aditivos da atualização do candidato.
|
|
4
|
+
*
|
|
5
|
+
* Nas noites de 11 a 13/10 a `main` andou várias vezes, e cada PR precisou de merge da base com conflito só aditivo no
|
|
6
|
+
* `CHANGELOG.md` (às vezes no código). Depois de uma versão, o merge ainda pôs a linha da thread dentro de `## [versão]`,
|
|
7
|
+
* logo abaixo de um "Não publicado" vazio, sem conflito textual nenhum. Aqui mora a regra que o núcleo aplica sozinho:
|
|
8
|
+
*
|
|
9
|
+
* - um conflito diff3 é só aditivo quando a seção do ancestral comum está vazia, ou é prefixo (ou sufixo) dos dois lados
|
|
10
|
+
* sem mudança; ele vira a união, com o lado da base de destino primeiro e o da thread depois. Qualquer outro conflito, ou
|
|
11
|
+
* marcador fora do formato, é recusa: o núcleo não escolhe por ninguém;
|
|
12
|
+
* - a entrada da thread é o bloco novo em "Não publicado" do lado da thread desde o ancestral comum; depois do merge, a que
|
|
13
|
+
* caiu numa seção de versão que, na base, não a tem volta para "Não publicado", na subseção de origem;
|
|
14
|
+
* - a regra do `core/scripts/checar-changelog.cjs` (que não vai no pacote) está portada aqui para a prova da entrega.
|
|
15
|
+
*
|
|
16
|
+
* Puro: texto entra, texto sai. Quem lê o git e grava o merge é `noctum-entrega.ts`; quem recomputa um merge para saber se
|
|
17
|
+
* ele foi mecânico é `noctum-provas.ts`. As duas usam estas mesmas funções, então a recomputação reproduz a atualização.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.ARQUIVO_DO_CHANGELOG = exports.SECAO_NAO_PUBLICADO = void 0;
|
|
21
|
+
exports.blocosNaoPublicados = blocosNaoPublicados;
|
|
22
|
+
exports.entradasDaThread = entradasDaThread;
|
|
23
|
+
exports.resolverConflitosAditivos = resolverConflitosAditivos;
|
|
24
|
+
exports.posicionarEntradas = posicionarEntradas;
|
|
25
|
+
exports.linhasRemovidas = linhasRemovidas;
|
|
26
|
+
exports.linhasDaBasePerdidas = linhasDaBasePerdidas;
|
|
27
|
+
exports.ehTeste = ehTeste;
|
|
28
|
+
exports.pedeLinha = pedeLinha;
|
|
29
|
+
exports.linhasDaSecao = linhasDaSecao;
|
|
30
|
+
exports.versoes = versoes;
|
|
31
|
+
exports.conferirChangelog = conferirChangelog;
|
|
32
|
+
exports.SECAO_NAO_PUBLICADO = '## Não publicado';
|
|
33
|
+
exports.ARQUIVO_DO_CHANGELOG = 'CHANGELOG.md';
|
|
34
|
+
/**
|
|
35
|
+
* As linhas como estão, sem converter CRLF (B3 da rodada 1 do CHECK): a resolução não pode mudar a quebra de linha de quem
|
|
36
|
+
* não conflitou. A linha em branco é a que só tem espaço (`branca`), com ou sem o `\r`.
|
|
37
|
+
*/
|
|
38
|
+
const linhasDe = (texto) => texto.split('\n');
|
|
39
|
+
const branca = (l) => l !== undefined && l.trim() === '';
|
|
40
|
+
const chaveDoBloco = (b) => b.linhas.join('\n');
|
|
41
|
+
const titulo = (linha) => /^## /.test(linha);
|
|
42
|
+
const subtitulo = (linha) => /^### /.test(linha);
|
|
43
|
+
const continuacao = (linha) => /^\s+\S/.test(linha);
|
|
44
|
+
/** As seções de nível 2, com o índice da linha do título e o fim exclusivo (o título seguinte, ou o fim do texto). */
|
|
45
|
+
function secoes(linhas) {
|
|
46
|
+
const s = [];
|
|
47
|
+
linhas.forEach((l, i) => {
|
|
48
|
+
if (!titulo(l))
|
|
49
|
+
return;
|
|
50
|
+
if (s.length)
|
|
51
|
+
s[s.length - 1].fim = i;
|
|
52
|
+
s.push({ titulo: l.trim(), inicio: i, fim: linhas.length });
|
|
53
|
+
});
|
|
54
|
+
return s;
|
|
55
|
+
}
|
|
56
|
+
/** Os blocos de uma seção, com a posição de cada um. */
|
|
57
|
+
function blocosComPosicao(linhas, secao) {
|
|
58
|
+
const blocos = [];
|
|
59
|
+
let subsecao = null;
|
|
60
|
+
for (let i = secao.inicio + 1; i < secao.fim; i++) {
|
|
61
|
+
const l = linhas[i];
|
|
62
|
+
if (subtitulo(l)) {
|
|
63
|
+
subsecao = l.trim();
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (!/^- /.test(l))
|
|
67
|
+
continue;
|
|
68
|
+
let j = i + 1;
|
|
69
|
+
while (j < secao.fim && continuacao(linhas[j]))
|
|
70
|
+
j++;
|
|
71
|
+
blocos.push({ linhas: linhas.slice(i, j), subsecao, inicio: i });
|
|
72
|
+
i = j - 1;
|
|
73
|
+
}
|
|
74
|
+
return blocos;
|
|
75
|
+
}
|
|
76
|
+
const secaoNaoPublicada = (linhas) => secoes(linhas).find(s => s.titulo === exports.SECAO_NAO_PUBLICADO) ?? null;
|
|
77
|
+
/** Os blocos da seção "Não publicado", ou `null` quando ela não existe. */
|
|
78
|
+
function blocosNaoPublicados(texto) {
|
|
79
|
+
const linhas = linhasDe(texto);
|
|
80
|
+
const s = secaoNaoPublicada(linhas);
|
|
81
|
+
return s ? blocosComPosicao(linhas, s).map(({ linhas: l, subsecao }) => ({ linhas: l, subsecao })) : null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* D5: as entradas que a thread acrescentou em "Não publicado": os blocos de `depois` que `antes` não tinha na mesma seção,
|
|
85
|
+
* contados como multiconjunto (um bloco repetido que já existia não conta como novo), na ordem em que aparecem.
|
|
86
|
+
*/
|
|
87
|
+
function entradasDaThread(antes, depois) {
|
|
88
|
+
const naBase = new Map();
|
|
89
|
+
for (const b of blocosNaoPublicados(antes) ?? [])
|
|
90
|
+
naBase.set(chaveDoBloco(b), (naBase.get(chaveDoBloco(b)) ?? 0) + 1);
|
|
91
|
+
const novas = [];
|
|
92
|
+
for (const b of blocosNaoPublicados(depois) ?? []) {
|
|
93
|
+
const n = naBase.get(chaveDoBloco(b)) ?? 0;
|
|
94
|
+
if (n > 0)
|
|
95
|
+
naBase.set(chaveDoBloco(b), n - 1);
|
|
96
|
+
else
|
|
97
|
+
novas.push(b);
|
|
98
|
+
}
|
|
99
|
+
return novas;
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// D4: conflitos diff3 só aditivos.
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
const INICIO = /^<{7}(?: |\r?$)/;
|
|
105
|
+
const ANCESTRAL = /^\|{7}(?: |\r?$)/;
|
|
106
|
+
const MEIO = /^={7}\r?$/;
|
|
107
|
+
const FIM = /^>{7}(?: |\r?$)/;
|
|
108
|
+
const marcador = (l) => INICIO.test(l) || ANCESTRAL.test(l) || MEIO.test(l) || FIM.test(l);
|
|
109
|
+
const comeca = (a, p) => p.every((l, i) => a[i] === l);
|
|
110
|
+
const termina = (a, s) => s.every((l, i) => a[a.length - s.length + i] === l);
|
|
111
|
+
/**
|
|
112
|
+
* Um conflito: `primeiro` é o lado do HEAD do merge (a thread), `segundo` o lado que entra (a base de destino) e
|
|
113
|
+
* `ancestral` a seção do ancestral comum. Só aditivo: a união, com a base primeiro; senão, `null`.
|
|
114
|
+
*/
|
|
115
|
+
function unir(primeiro, ancestral, segundo) {
|
|
116
|
+
if (ancestral.length === 0)
|
|
117
|
+
return [...segundo, ...primeiro];
|
|
118
|
+
const n = ancestral.length;
|
|
119
|
+
if (primeiro.length >= n && segundo.length >= n && comeca(primeiro, ancestral) && comeca(segundo, ancestral)) {
|
|
120
|
+
return [...ancestral, ...segundo.slice(n), ...primeiro.slice(n)];
|
|
121
|
+
}
|
|
122
|
+
if (primeiro.length >= n && segundo.length >= n && termina(primeiro, ancestral) && termina(segundo, ancestral)) {
|
|
123
|
+
return [...segundo.slice(0, segundo.length - n), ...primeiro.slice(0, primeiro.length - n), ...ancestral];
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* D4: resolve os conflitos diff3 de um arquivo (os marcadores `<<<<<<<`, `|||||||`, `=======` e `>>>>>>>` do
|
|
129
|
+
* `merge.conflictStyle=diff3`). Só aditivo vira a união; o conflito que muda linha do ancestral, o conflito sem a seção do
|
|
130
|
+
* ancestral (outro estilo de merge) e o marcador fora do formato voltam como recusa, com o motivo.
|
|
131
|
+
*/
|
|
132
|
+
function resolverConflitosAditivos(texto) {
|
|
133
|
+
const saida = [];
|
|
134
|
+
let estado = 'fora';
|
|
135
|
+
let primeiro = [], ancestral = [], segundo = [];
|
|
136
|
+
let conflitos = 0;
|
|
137
|
+
const recusa = (motivo, n) => ({ ok: false, recusa: `${motivo} (linha ${n + 1})` });
|
|
138
|
+
const linhas = linhasDe(texto);
|
|
139
|
+
for (let i = 0; i < linhas.length; i++) {
|
|
140
|
+
const l = linhas[i];
|
|
141
|
+
if (estado === 'fora') {
|
|
142
|
+
if (INICIO.test(l)) {
|
|
143
|
+
estado = 'primeiro';
|
|
144
|
+
primeiro = [];
|
|
145
|
+
ancestral = [];
|
|
146
|
+
segundo = [];
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (marcador(l))
|
|
150
|
+
return recusa('marcador de conflito fora do formato', i);
|
|
151
|
+
saida.push(l);
|
|
152
|
+
}
|
|
153
|
+
else if (estado === 'primeiro') {
|
|
154
|
+
if (ANCESTRAL.test(l)) {
|
|
155
|
+
estado = 'ancestral';
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (marcador(l))
|
|
159
|
+
return recusa('conflito sem a seção do ancestral comum (o merge precisa de merge.conflictStyle=diff3)', i);
|
|
160
|
+
primeiro.push(l);
|
|
161
|
+
}
|
|
162
|
+
else if (estado === 'ancestral') {
|
|
163
|
+
if (MEIO.test(l)) {
|
|
164
|
+
estado = 'segundo';
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (marcador(l))
|
|
168
|
+
return recusa('marcador de conflito fora do formato', i);
|
|
169
|
+
ancestral.push(l);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
if (FIM.test(l)) {
|
|
173
|
+
const unido = unir(primeiro, ancestral, segundo);
|
|
174
|
+
if (!unido)
|
|
175
|
+
return recusa('conflito que muda linha do ancestral comum: não é só aditivo', i);
|
|
176
|
+
saida.push(...unido);
|
|
177
|
+
conflitos += 1;
|
|
178
|
+
estado = 'fora';
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (marcador(l))
|
|
182
|
+
return recusa('marcador de conflito fora do formato', i);
|
|
183
|
+
segundo.push(l);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (estado !== 'fora')
|
|
187
|
+
return recusa('conflito sem o marcador de fim', linhas.length - 1);
|
|
188
|
+
return { ok: true, texto: saida.join('\n'), conflitos };
|
|
189
|
+
}
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// D5: a entrada da thread em "Não publicado".
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
/** O índice da primeira linha de cada ocorrência do bloco como item inteiro (nem pedaço de outro item, nem prefixo). */
|
|
194
|
+
function ocorrencias(linhas, bloco) {
|
|
195
|
+
const achadas = [];
|
|
196
|
+
for (let i = 0; i + bloco.linhas.length <= linhas.length; i++) {
|
|
197
|
+
if (!bloco.linhas.every((l, k) => linhas[i + k] === l))
|
|
198
|
+
continue;
|
|
199
|
+
const depois = linhas[i + bloco.linhas.length];
|
|
200
|
+
if (depois !== undefined && continuacao(depois))
|
|
201
|
+
continue;
|
|
202
|
+
achadas.push(i);
|
|
203
|
+
}
|
|
204
|
+
return achadas;
|
|
205
|
+
}
|
|
206
|
+
/** A seção que contém a linha `i`, ou `null` quando ela vem antes da primeira seção. */
|
|
207
|
+
const secaoDaLinha = (s, i) => s.find(x => i > x.inicio && i < x.fim) ?? null;
|
|
208
|
+
/** A versão é seção de versão? `## [0.5.0] - 2026-09-30` e o formato antigo `## 0.4.3`, sem colchetes. */
|
|
209
|
+
const ehVersao = (t) => /^## \[?\d+\.\d+\.\d+/.test(t);
|
|
210
|
+
/**
|
|
211
|
+
* D5: põe em "Não publicado" as entradas da thread que caíram numa seção de versão que, em `daBase` (o CHANGELOG da base de
|
|
212
|
+
* destino), não tem o mesmo bloco. A entrada volta para a subseção de origem (criada no alto da seção quando falta), e
|
|
213
|
+
* "Não publicado" é criada antes da primeira versão quando falta. O subtítulo que fica vazio na versão e que a base não tem
|
|
214
|
+
* sai junto. Entrada que já está em "Não publicado" não muda; a que sumiu conta em `perdidas`.
|
|
215
|
+
*/
|
|
216
|
+
function posicionarEntradas(texto, entradas, daBase) {
|
|
217
|
+
const linhas = linhasDe(texto);
|
|
218
|
+
const base = linhasDe(daBase);
|
|
219
|
+
const naBase = new Map();
|
|
220
|
+
for (const s of secoes(base)) {
|
|
221
|
+
naBase.set(s.titulo, new Set(blocosComPosicao(base, s).map(chaveDoBloco)));
|
|
222
|
+
}
|
|
223
|
+
const subtitulosDaBase = new Map();
|
|
224
|
+
for (const s of secoes(base)) {
|
|
225
|
+
subtitulosDaBase.set(s.titulo, new Set(base.slice(s.inicio + 1, s.fim).filter(subtitulo).map(l => l.trim())));
|
|
226
|
+
}
|
|
227
|
+
let movidas = 0, perdidas = 0;
|
|
228
|
+
for (const e of entradas) {
|
|
229
|
+
const s = secoes(linhas);
|
|
230
|
+
const achadas = ocorrencias(linhas, e);
|
|
231
|
+
if (!achadas.length) {
|
|
232
|
+
perdidas += 1;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (achadas.some(i => secaoDaLinha(s, i)?.titulo === exports.SECAO_NAO_PUBLICADO))
|
|
236
|
+
continue;
|
|
237
|
+
const fora = achadas.find(i => {
|
|
238
|
+
const sec = secaoDaLinha(s, i);
|
|
239
|
+
return !!sec && ehVersao(sec.titulo) && !naBase.get(sec.titulo)?.has(chaveDoBloco(e));
|
|
240
|
+
});
|
|
241
|
+
if (fora === undefined)
|
|
242
|
+
continue;
|
|
243
|
+
const sec = secaoDaLinha(s, fora);
|
|
244
|
+
// Tira o bloco e a linha em branco que sobraria dobrada.
|
|
245
|
+
linhas.splice(fora, e.linhas.length);
|
|
246
|
+
if (branca(linhas[fora]) && (fora === 0 || branca(linhas[fora - 1])))
|
|
247
|
+
linhas.splice(fora, 1);
|
|
248
|
+
// O subtítulo que ficou sem nada na versão, e que a base não tem nela, era da thread: sai também.
|
|
249
|
+
const subAcima = (() => { for (let k = fora - 1; k > sec.inicio; k--) {
|
|
250
|
+
if (subtitulo(linhas[k]))
|
|
251
|
+
return k;
|
|
252
|
+
if (/^- /.test(linhas[k]) || continuacao(linhas[k]))
|
|
253
|
+
return -1;
|
|
254
|
+
} return -1; })();
|
|
255
|
+
if (subAcima > 0) {
|
|
256
|
+
let k = subAcima + 1;
|
|
257
|
+
while (k < linhas.length && branca(linhas[k]))
|
|
258
|
+
k++;
|
|
259
|
+
const vazio = k >= linhas.length || titulo(linhas[k]) || subtitulo(linhas[k]);
|
|
260
|
+
if (vazio && !subtitulosDaBase.get(sec.titulo)?.has(linhas[subAcima].trim())) {
|
|
261
|
+
linhas.splice(subAcima, branca(linhas[subAcima + 1]) ? 2 : 1);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
inserirEmNaoPublicado(linhas, e);
|
|
265
|
+
movidas += 1;
|
|
266
|
+
}
|
|
267
|
+
return { texto: linhas.join('\n'), movidas, perdidas };
|
|
268
|
+
}
|
|
269
|
+
/** Insere o bloco no alto da subseção de origem dele em "Não publicado", criando a seção e a subseção quando faltam. */
|
|
270
|
+
function inserirEmNaoPublicado(linhas, e) {
|
|
271
|
+
let s = secaoNaoPublicada(linhas);
|
|
272
|
+
if (!s) {
|
|
273
|
+
const primeiraVersao = secoes(linhas).find(x => ehVersao(x.titulo));
|
|
274
|
+
const onde = primeiraVersao ? primeiraVersao.inicio : linhas.length;
|
|
275
|
+
const antes = onde > 0 && !branca(linhas[onde - 1]) ? [''] : [];
|
|
276
|
+
linhas.splice(onde, 0, ...antes, exports.SECAO_NAO_PUBLICADO, '');
|
|
277
|
+
s = secaoNaoPublicada(linhas);
|
|
278
|
+
}
|
|
279
|
+
// Depois do título da seção (e da linha em branco dele, que é criada quando falta).
|
|
280
|
+
if (!branca(linhas[s.inicio + 1]))
|
|
281
|
+
linhas.splice(s.inicio + 1, 0, '');
|
|
282
|
+
s = secaoNaoPublicada(linhas);
|
|
283
|
+
let alvo = s.inicio + 2;
|
|
284
|
+
if (e.subsecao !== null) {
|
|
285
|
+
const h = linhas.slice(s.inicio + 1, s.fim).findIndex(l => l.trim() === e.subsecao);
|
|
286
|
+
if (h < 0) {
|
|
287
|
+
linhas.splice(s.inicio + 2, 0, e.subsecao, '');
|
|
288
|
+
alvo = s.inicio + 4;
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
const k = s.inicio + 1 + h;
|
|
292
|
+
if (!branca(linhas[k + 1]))
|
|
293
|
+
linhas.splice(k + 1, 0, '');
|
|
294
|
+
alvo = k + 2;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
linhas.splice(alvo, 0, ...e.linhas, '');
|
|
298
|
+
}
|
|
299
|
+
/** As linhas de texto de `antes` que `depois` não tem mais (multiconjunto, sem as linhas em branco). */
|
|
300
|
+
function linhasRemovidas(antes, depois) {
|
|
301
|
+
const restantes = new Map();
|
|
302
|
+
for (const l of linhasDe(depois))
|
|
303
|
+
if (l.trim())
|
|
304
|
+
restantes.set(l, (restantes.get(l) ?? 0) + 1);
|
|
305
|
+
const removidas = [];
|
|
306
|
+
for (const l of linhasDe(antes)) {
|
|
307
|
+
if (!l.trim())
|
|
308
|
+
continue;
|
|
309
|
+
const n = restantes.get(l) ?? 0;
|
|
310
|
+
if (n > 0)
|
|
311
|
+
restantes.set(l, n - 1);
|
|
312
|
+
else
|
|
313
|
+
removidas.push(l);
|
|
314
|
+
}
|
|
315
|
+
return removidas;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* As linhas de texto da base que o resultado não tem mais (multiconjunto, sem as linhas em branco), fora as que a própria
|
|
319
|
+
* thread tirou desde o ancestral comum (`daThread`, A3 da rodada 1): a correção de uma linha antiga não é perda.
|
|
320
|
+
*/
|
|
321
|
+
function linhasDaBasePerdidas(daBase, resultado, daThread = []) {
|
|
322
|
+
const permitidas = new Map();
|
|
323
|
+
for (const l of daThread)
|
|
324
|
+
permitidas.set(l, (permitidas.get(l) ?? 0) + 1);
|
|
325
|
+
return linhasRemovidas(daBase, resultado).filter(l => {
|
|
326
|
+
const n = permitidas.get(l) ?? 0;
|
|
327
|
+
if (n > 0) {
|
|
328
|
+
permitidas.set(l, n - 1);
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
return true;
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
// ---------------------------------------------------------------------------
|
|
335
|
+
// A regra do checador do CHANGELOG (core/scripts/checar-changelog.cjs), portada.
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
const PASTAS_DE_PRODUTO = ['core/', 'adapters/', 'marketplaces/'];
|
|
338
|
+
const DE_CI = [/^\.github\//, /^\.ork-ci\//, /^core\/scripts\/test-ci\.js$/, /^core\/scripts\/checar-[a-z0-9-]+\.cjs$/];
|
|
339
|
+
/** Arquivo de teste: pasta `test`, `tests` ou `__tests__` no caminho, ou nome `*.test.*`/`*.spec.*`. */
|
|
340
|
+
function ehTeste(arquivo) {
|
|
341
|
+
const partes = arquivo.split('/');
|
|
342
|
+
return partes.slice(0, -1).some(p => p === 'test' || p === 'tests' || p === '__tests__')
|
|
343
|
+
|| /\.(test|spec)\.[A-Za-z0-9]+$/.test(partes[partes.length - 1]);
|
|
344
|
+
}
|
|
345
|
+
/** Arquivo que pede linha no CHANGELOG: dentro das pastas do produto, fora de teste e de CI. */
|
|
346
|
+
function pedeLinha(arquivo) {
|
|
347
|
+
return PASTAS_DE_PRODUTO.some(p => arquivo.startsWith(p)) && !ehTeste(arquivo) && !DE_CI.some(re => re.test(arquivo));
|
|
348
|
+
}
|
|
349
|
+
/** As linhas de texto da seção "Não publicado" (sem título e sem linha em branco); `null` sem a seção. */
|
|
350
|
+
function linhasDaSecao(texto) {
|
|
351
|
+
const linhas = linhasDe(texto);
|
|
352
|
+
const inicio = linhas.findIndex(l => l.trim() === exports.SECAO_NAO_PUBLICADO);
|
|
353
|
+
if (inicio < 0)
|
|
354
|
+
return null;
|
|
355
|
+
const corpo = [];
|
|
356
|
+
for (const linha of linhas.slice(inicio + 1)) {
|
|
357
|
+
if (/^## /.test(linha))
|
|
358
|
+
break;
|
|
359
|
+
if (linha.trim() && !/^#/.test(linha.trim()))
|
|
360
|
+
corpo.push(linha.trimEnd());
|
|
361
|
+
}
|
|
362
|
+
return corpo;
|
|
363
|
+
}
|
|
364
|
+
/** As versões do CHANGELOG, nos dois formatos que ele já teve. */
|
|
365
|
+
function versoes(texto) {
|
|
366
|
+
return new Set([...texto.replace(/\r\n/g, '\n').matchAll(/^## \[?(\d+\.\d+\.\d+[0-9A-Za-z.+-]*)\]?(?=\s|$)/gm)].map(m => m[1]));
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* A regra do job `documentacao`: o diff que muda `core/`, `adapters/` ou `marketplaces/` (fora de teste e de CI) acrescenta
|
|
370
|
+
* ao menos uma linha em "Não publicado" ou abre uma versão nova. `antes` é o CHANGELOG no ancestral comum com a base;
|
|
371
|
+
* `depois`, o da fonte; `arquivos`, os caminhos que a fonte muda desde esse ancestral.
|
|
372
|
+
*/
|
|
373
|
+
function conferirChangelog(antes, depois, arquivos) {
|
|
374
|
+
const pedem = arquivos.filter(pedeLinha);
|
|
375
|
+
if (!pedem.length)
|
|
376
|
+
return { ok: true, detalhe: 'nada pede linha: a mudança não toca core/, adapters/ nem marketplaces/ fora de teste e CI', linhas: [] };
|
|
377
|
+
const nova = [...versoes(depois)].filter(v => !versoes(antes).has(v));
|
|
378
|
+
if (nova.length)
|
|
379
|
+
return { ok: true, detalhe: `versão nova no CHANGELOG: ${nova.join(', ')}`, linhas: [] };
|
|
380
|
+
const secao = linhasDaSecao(depois);
|
|
381
|
+
if (secao === null)
|
|
382
|
+
return { ok: false, motivo: 'changelog.secao-ausente', detalhe: `o CHANGELOG não tem a seção "${exports.SECAO_NAO_PUBLICADO}"` };
|
|
383
|
+
const naBase = new Map();
|
|
384
|
+
for (const l of linhasDaSecao(antes) ?? [])
|
|
385
|
+
naBase.set(l, (naBase.get(l) ?? 0) + 1);
|
|
386
|
+
const novas = [];
|
|
387
|
+
for (const l of secao) {
|
|
388
|
+
const n = naBase.get(l) ?? 0;
|
|
389
|
+
if (n > 0)
|
|
390
|
+
naBase.set(l, n - 1);
|
|
391
|
+
else
|
|
392
|
+
novas.push(l);
|
|
393
|
+
}
|
|
394
|
+
if (novas.length)
|
|
395
|
+
return { ok: true, detalhe: `${novas.length} linha(s) nova(s) em "${exports.SECAO_NAO_PUBLICADO}"`, linhas: novas };
|
|
396
|
+
return { ok: false, motivo: 'changelog.linha-ausente',
|
|
397
|
+
detalhe: `a mudança toca ${pedem.length} arquivo(s) do produto (${pedem.slice(0, 3).join(', ')}${pedem.length > 3 ? ', ...' : ''}) ` +
|
|
398
|
+
`e não acrescenta linha em "${exports.SECAO_NAO_PUBLICADO}"` };
|
|
399
|
+
}
|