@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,444 @@
|
|
|
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.ErroDaFilaPesada = exports.ENV_DONO_DA_FILA = exports.CONTRATO_FILA_PESADA = void 0;
|
|
37
|
+
exports.kernelDisponivel = kernelDisponivel;
|
|
38
|
+
exports.tentarTravaExclusiva = tentarTravaExclusiva;
|
|
39
|
+
exports.dirDaFilaPesada = dirDaFilaPesada;
|
|
40
|
+
exports.ocupantesDaFilaPesada = ocupantesDaFilaPesada;
|
|
41
|
+
exports.comRecursoPesado = comRecursoPesado;
|
|
42
|
+
/**
|
|
43
|
+
* RM-058, fatia N2 (D9 da ork-rm058n2): a fila de recursos pesados.
|
|
44
|
+
*
|
|
45
|
+
* Verify rodando junto com build de outra worktree deu regressão falsa nesta máquina: com a CPU dividida, teste
|
|
46
|
+
* com relógio estoura o prazo e a suíte reprova sem que nada tenha quebrado. A fila deixa no máximo `slots`
|
|
47
|
+
* operações pesadas ao mesmo tempo por raiz de estado (todas as worktrees do projeto nesta máquina) e nunca duas
|
|
48
|
+
* no mesmo artefato (o diretório onde a operação compila e testa).
|
|
49
|
+
*
|
|
50
|
+
* Tudo é trava do kernel (`flock` exclusivo, como a condução e o lock do HITL): quem segura é o processo, e a
|
|
51
|
+
* trava solta sozinha quando ele morre, inclusive por SIGKILL. Nenhum prazo, PID ou arquivo apagado libera vaga;
|
|
52
|
+
* um processo perdido em segundo plano não prende a fila. A ordem de chegada é uma senha, também com trava do
|
|
53
|
+
* kernel: quem chegou antes e segue vivo passa antes, e a senha de quem morreu não segura ninguém.
|
|
54
|
+
*
|
|
55
|
+
* Limites ditos: a fila é da raiz de estado, e outro projeto da mesma máquina tem a sua; o descritor não passa
|
|
56
|
+
* aos filhos, então o processo que morre por SIGKILL solta a vaga mesmo que um comando dele ainda rode até o
|
|
57
|
+
* próprio prazo (o `timeout` do verify o encerra); e só o Linux com `/usr/bin/flock` tem a fila.
|
|
58
|
+
*
|
|
59
|
+
* O dono da vez passa aos comandos que roda a marca da posse (`ORK_FILA_PESADA_DONO`): um verify aninhado num
|
|
60
|
+
* comando dele (a claim que roda `ork verify` de outra thread do mesmo projeto) entra como reentrada, em vez de
|
|
61
|
+
* esperar a vaga do próprio pai até o prazo. A marca só vale com o dono vivo, ancestral do processo e segurando a
|
|
62
|
+
* vaga que diz, com o identificador da posse que gravou nela: marca copiada para fora dessa árvore de processos, ou
|
|
63
|
+
* guardada de uma vez anterior do mesmo dono, não pula a fila.
|
|
64
|
+
*/
|
|
65
|
+
const fs = __importStar(require("node:fs"));
|
|
66
|
+
const path = __importStar(require("node:path"));
|
|
67
|
+
const node_crypto_1 = require("node:crypto");
|
|
68
|
+
const node_child_process_1 = require("node:child_process");
|
|
69
|
+
const estado_thread_1 = require("./estado-thread");
|
|
70
|
+
const horario_1 = require("./horario");
|
|
71
|
+
exports.CONTRATO_FILA_PESADA = 'ork.fila-pesada/v1';
|
|
72
|
+
/** A marca da posse que o dono da vez passa aos processos filhos. */
|
|
73
|
+
exports.ENV_DONO_DA_FILA = 'ORK_FILA_PESADA_DONO';
|
|
74
|
+
const FLOCK = '/usr/bin/flock';
|
|
75
|
+
const DIR = 'fila-pesada';
|
|
76
|
+
/** Entre uma tentativa e outra. A vez costuma durar minutos; meio segundo não pesa em ninguém. */
|
|
77
|
+
const PAUSA_MS = 500;
|
|
78
|
+
/** A recusa é resposta, não falha: o CLI a imprime como a da condução, e sai com 3. */
|
|
79
|
+
class ErroDaFilaPesada extends Error {
|
|
80
|
+
recusa;
|
|
81
|
+
constructor(recusa) {
|
|
82
|
+
super(`fila-pesada.ocupada: ${recusa.texto}`);
|
|
83
|
+
this.name = 'ErroDaFilaPesada';
|
|
84
|
+
this.recusa = recusa;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.ErroDaFilaPesada = ErroDaFilaPesada;
|
|
88
|
+
function kernelDisponivel() {
|
|
89
|
+
return process.platform === 'linux' && fs.existsSync(FLOCK);
|
|
90
|
+
}
|
|
91
|
+
/** O `flock` exclusivo sem espera sobre um descritor já aberto. O helper tranca a descrição de arquivo, que fica do processo. */
|
|
92
|
+
function trancar(fd) {
|
|
93
|
+
const r = (0, node_child_process_1.spawnSync)(FLOCK, ['--exclusive', '--nonblock', '3'], { stdio: ['ignore', 'ignore', 'ignore', fd], timeout: 5000 });
|
|
94
|
+
return r.status === 0 && !r.error;
|
|
95
|
+
}
|
|
96
|
+
function abrirTrava(arquivo, criar) {
|
|
97
|
+
const fd = fs.openSync(arquivo, fs.constants.O_RDWR | fs.constants.O_NOFOLLOW | (criar ? fs.constants.O_CREAT : 0), 0o600);
|
|
98
|
+
const st = fs.fstatSync(fd);
|
|
99
|
+
if (!st.isFile() || st.uid !== process.getuid?.()) {
|
|
100
|
+
fs.closeSync(fd);
|
|
101
|
+
throw new Error(`fila-pesada: ${path.basename(arquivo)} não é arquivo de trava do núcleo`);
|
|
102
|
+
}
|
|
103
|
+
return fd;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A trava exclusiva do kernel num arquivo da raiz de estado: o descritor, ou `null` quando outro processo vivo a
|
|
107
|
+
* segura. A trava dura enquanto o descritor estiver aberto neste processo, e nunca mais que o processo.
|
|
108
|
+
*/
|
|
109
|
+
function tentarTravaExclusiva(arquivo) {
|
|
110
|
+
const fd = abrirTrava(arquivo, true);
|
|
111
|
+
if (trancar(fd))
|
|
112
|
+
return fd;
|
|
113
|
+
fs.closeSync(fd);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
/** O diretório da fila na raiz de estado, criado privado. */
|
|
117
|
+
function dirDaFilaPesada(raiz) {
|
|
118
|
+
const principal = (0, estado_thread_1.raizDoEstado)(raiz);
|
|
119
|
+
(0, estado_thread_1.exigirEstadoSemLink)(principal, ['.orkastery', DIR]);
|
|
120
|
+
const dir = path.join(principal, '.orkastery', DIR);
|
|
121
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
122
|
+
return dir;
|
|
123
|
+
}
|
|
124
|
+
/** O artefato pelo caminho real: a mesma worktree por dois caminhos é o mesmo artefato. */
|
|
125
|
+
function chaveDoArtefato(artefato) {
|
|
126
|
+
let real;
|
|
127
|
+
try {
|
|
128
|
+
real = fs.realpathSync(artefato);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
real = path.resolve(artefato);
|
|
132
|
+
}
|
|
133
|
+
return (0, node_crypto_1.createHash)('sha256').update(real).digest('hex').slice(0, 16);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* A senha de chegada: criada com outro nome, trancada e só então renomeada, para ninguém vê-la destrancada e
|
|
137
|
+
* tomá-la por senha de processo morto. O nome começa pelo instante, com zeros: a ordem dos nomes é a de chegada.
|
|
138
|
+
*/
|
|
139
|
+
function tirarSenha(dir) {
|
|
140
|
+
const marca = `${String(Date.now()).padStart(15, '0')}-${String(process.pid).padStart(10, '0')}-${(0, node_crypto_1.randomUUID)().slice(0, 8)}`;
|
|
141
|
+
const provisorio = path.join(dir, `.senha-${marca}.tmp`);
|
|
142
|
+
const fd = abrirTrava(provisorio, true);
|
|
143
|
+
if (!trancar(fd)) {
|
|
144
|
+
fs.closeSync(fd);
|
|
145
|
+
fs.rmSync(provisorio, { force: true });
|
|
146
|
+
throw new Error('fila-pesada: a senha nova não trancou');
|
|
147
|
+
}
|
|
148
|
+
const nome = `senha-${marca}.lock`;
|
|
149
|
+
fs.renameSync(provisorio, path.join(dir, nome));
|
|
150
|
+
return { nome, fd };
|
|
151
|
+
}
|
|
152
|
+
/** Apaga a senha com a trava na mão e só depois a solta: ninguém a vê destrancada no diretório. */
|
|
153
|
+
function devolverSenha(dir, senha) {
|
|
154
|
+
if (!senha)
|
|
155
|
+
return;
|
|
156
|
+
try {
|
|
157
|
+
fs.unlinkSync(path.join(dir, senha.nome));
|
|
158
|
+
}
|
|
159
|
+
catch { /* já saiu */ }
|
|
160
|
+
try {
|
|
161
|
+
fs.closeSync(senha.fd);
|
|
162
|
+
}
|
|
163
|
+
catch { /* já fechado */ }
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* É a vez desta senha? Só quando nenhuma senha anterior segue viva. A de processo morto está destrancada: quem a
|
|
167
|
+
* acha a tranca, apaga e solta, para ela não segurar a fila de ninguém. A provisória de quem morreu entre criar e
|
|
168
|
+
* renomear também sai, pelo mesmo teste da trava.
|
|
169
|
+
*/
|
|
170
|
+
function minhaVez(dir, senha) {
|
|
171
|
+
const nomes = fs.readdirSync(dir);
|
|
172
|
+
for (const nome of nomes.filter(n => /^\.senha-.+\.tmp$/.test(n))) {
|
|
173
|
+
// Entre criar e trancar, a provisória viva fica um instante destrancada: só a velha é de quem morreu.
|
|
174
|
+
const st = fs.statSync(path.join(dir, nome), { throwIfNoEntry: false });
|
|
175
|
+
if (!st || Date.now() - st.mtimeMs < 30_000)
|
|
176
|
+
continue;
|
|
177
|
+
let fd;
|
|
178
|
+
try {
|
|
179
|
+
fd = abrirTrava(path.join(dir, nome), false);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (trancar(fd)) {
|
|
185
|
+
try {
|
|
186
|
+
fs.unlinkSync(path.join(dir, nome));
|
|
187
|
+
}
|
|
188
|
+
catch { /* outro já limpou */ }
|
|
189
|
+
}
|
|
190
|
+
fs.closeSync(fd);
|
|
191
|
+
}
|
|
192
|
+
const anteriores = nomes.filter(n => /^senha-.+\.lock$/.test(n) && n < senha.nome).sort();
|
|
193
|
+
for (const nome of anteriores) {
|
|
194
|
+
let fd;
|
|
195
|
+
try {
|
|
196
|
+
fd = abrirTrava(path.join(dir, nome), false);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (!trancar(fd)) {
|
|
202
|
+
fs.closeSync(fd);
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
fs.unlinkSync(path.join(dir, nome));
|
|
207
|
+
}
|
|
208
|
+
catch { /* outro já limpou */ }
|
|
209
|
+
fs.closeSync(fd);
|
|
210
|
+
}
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
function gravarDono(fd, dono, posse) {
|
|
214
|
+
const bytes = Buffer.from(JSON.stringify({ contrato: exports.CONTRATO_FILA_PESADA, ...dono, posse }) + '\n', 'utf8');
|
|
215
|
+
fs.ftruncateSync(fd, 0);
|
|
216
|
+
fs.writeSync(fd, bytes, 0, bytes.length, 0);
|
|
217
|
+
}
|
|
218
|
+
/** O artefato primeiro, depois a primeira vaga livre; sem vaga, solta o artefato. Nunca espera segurando nada. */
|
|
219
|
+
function tentarVaga(dir, pedido) {
|
|
220
|
+
const fdArtefato = tentarTravaExclusiva(path.join(dir, `artefato-${chaveDoArtefato(pedido.artefato)}.lock`));
|
|
221
|
+
if (fdArtefato === null)
|
|
222
|
+
return null;
|
|
223
|
+
for (let slot = 0; slot < pedido.slots; slot++) {
|
|
224
|
+
const fdVaga = tentarTravaExclusiva(path.join(dir, `vaga-${slot}.lock`));
|
|
225
|
+
if (fdVaga === null)
|
|
226
|
+
continue;
|
|
227
|
+
const dono = { slot, operacao: pedido.operacao, thread: pedido.thread, artefato: path.resolve(pedido.artefato),
|
|
228
|
+
pid: process.pid, desde: new Date().toISOString() };
|
|
229
|
+
const id = (0, node_crypto_1.randomUUID)();
|
|
230
|
+
gravarDono(fdVaga, dono, id);
|
|
231
|
+
gravarDono(fdArtefato, dono, id);
|
|
232
|
+
return { fdArtefato, fdVaga, slot, id };
|
|
233
|
+
}
|
|
234
|
+
fs.closeSync(fdArtefato);
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
function soltar(posse) {
|
|
238
|
+
for (const fd of [posse.fdVaga, posse.fdArtefato]) {
|
|
239
|
+
try {
|
|
240
|
+
fs.ftruncateSync(fd, 0);
|
|
241
|
+
}
|
|
242
|
+
catch { /* o descritor fecha de qualquer jeito */ }
|
|
243
|
+
try {
|
|
244
|
+
fs.closeSync(fd);
|
|
245
|
+
}
|
|
246
|
+
catch { /* já fechado */ }
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Quem ocupa as vagas agora. Somente leitura do que os donos gravaram; a vaga que tranca na hora está livre e é
|
|
251
|
+
* solta em seguida. Vaga trancada sem dono legível ainda conta, como ocupada por desconhecido.
|
|
252
|
+
*/
|
|
253
|
+
function ocupantesDaFilaPesada(raiz) {
|
|
254
|
+
if (!kernelDisponivel())
|
|
255
|
+
return [];
|
|
256
|
+
const dir = dirDaFilaPesada(raiz);
|
|
257
|
+
const ocupantes = [];
|
|
258
|
+
for (const nome of fs.readdirSync(dir).filter(n => /^vaga-\d+\.lock$/.test(n)).sort()) {
|
|
259
|
+
let fd;
|
|
260
|
+
try {
|
|
261
|
+
fd = abrirTrava(path.join(dir, nome), false);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
if (trancar(fd))
|
|
268
|
+
continue;
|
|
269
|
+
const slot = Number(/^vaga-(\d+)\.lock$/.exec(nome)[1]);
|
|
270
|
+
let dono = {};
|
|
271
|
+
try {
|
|
272
|
+
dono = JSON.parse(fs.readFileSync(path.join(dir, nome), 'utf8'));
|
|
273
|
+
}
|
|
274
|
+
catch { /* dono ainda gravando */ }
|
|
275
|
+
ocupantes.push({ slot, operacao: typeof dono.operacao === 'string' ? dono.operacao : 'desconhecida',
|
|
276
|
+
thread: typeof dono.thread === 'string' ? dono.thread : null, artefato: typeof dono.artefato === 'string' ? dono.artefato : '',
|
|
277
|
+
pid: typeof dono.pid === 'number' ? dono.pid : 0, desde: typeof dono.desde === 'string' ? dono.desde : '' });
|
|
278
|
+
}
|
|
279
|
+
finally {
|
|
280
|
+
fs.closeSync(fd);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return ocupantes;
|
|
284
|
+
}
|
|
285
|
+
function recusaDaFila(pedido, esperouMs, ocupantes) {
|
|
286
|
+
const espera = esperouMs < 60000 ? `${Math.round(esperouMs / 1000)} s` : `${Math.round(esperouMs / 60000)} min`;
|
|
287
|
+
const linhas = [
|
|
288
|
+
`Operação pesada não executada: ${pedido.operacao}${pedido.thread ? ` da thread ${pedido.thread}` : ''} esperou ${espera} ` +
|
|
289
|
+
`e a fila de recursos pesados não liberou a vez (até ${pedido.slots} ao mesmo tempo, concurrency.max_parallel_heavy). ` +
|
|
290
|
+
'Verify e build juntos nesta máquina dão regressão falsa.',
|
|
291
|
+
...(ocupantes.length ? ocupantes.map(o => ` Quem ocupa: ${o.operacao}${o.thread ? ` da thread ${o.thread}` : ''}, ` +
|
|
292
|
+
`desde ${(0, horario_1.formatarDesde)(o.desde)}, processo ${o.pid}.`) : [' Quem ocupa: a vez é de outro pedido que chegou antes e ainda espera.']),
|
|
293
|
+
'O que você pode fazer:',
|
|
294
|
+
' 1. Esperar a vez: o dono da vaga segue rodando e, quando ele termina ou morre, a vaga volta sozinha.',
|
|
295
|
+
...(pedido.comandoDeEsperar ? [` ${pedido.comandoDeEsperar}`] : []),
|
|
296
|
+
' 2. Desligar a fila só nesta máquina, se ela aguenta: concurrency.max_parallel_heavy no orkastery.yaml (0 desliga).',
|
|
297
|
+
];
|
|
298
|
+
return { contrato: 'ork.fila-pesada-recusa/v1', motivo: 'fila-pesada.ocupada', operacao: pedido.operacao, thread: pedido.thread,
|
|
299
|
+
slots: pedido.slots, esperouMs, ocupantes, texto: linhas.join('\n') };
|
|
300
|
+
}
|
|
301
|
+
const pausa = new Int32Array(new SharedArrayBuffer(4));
|
|
302
|
+
function dormir(ms) {
|
|
303
|
+
if (ms > 0)
|
|
304
|
+
Atomics.wait(pausa, 0, 0, Math.ceil(ms));
|
|
305
|
+
}
|
|
306
|
+
/** A vez que este processo segura, por raiz de estado: a reentrada não pede vaga de novo. */
|
|
307
|
+
const emCurso = new Map();
|
|
308
|
+
/** O campo 22 do `/proc/<pid>/stat` (instante de início em ticks): com o pid, identifica o processo sem reuso. */
|
|
309
|
+
function inicioDoProcesso(pid) {
|
|
310
|
+
try {
|
|
311
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
312
|
+
return stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19] ?? null;
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function paiDe(pid) {
|
|
319
|
+
try {
|
|
320
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
321
|
+
const pai = Number(stat.slice(stat.lastIndexOf(')') + 2).split(' ')[1]);
|
|
322
|
+
return Number.isSafeInteger(pai) && pai > 0 ? pai : null;
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/** O processo é ancestral deste? Sobe pela cadeia de pais, no máximo 64 degraus. */
|
|
329
|
+
function ancestral(pid) {
|
|
330
|
+
let atual = process.ppid;
|
|
331
|
+
for (let i = 0; i < 64 && atual !== null && atual > 1; i++) {
|
|
332
|
+
if (atual === pid)
|
|
333
|
+
return true;
|
|
334
|
+
atual = paiDe(atual);
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* A vaga que um processo ancestral segura nesta raiz, pela marca que ele passou; `null` quando a marca não vale: outra
|
|
340
|
+
* raiz, dono morto ou trocado (pid com outro início), dono que não é ancestral, ou vaga que ele não segura mais, inclusive
|
|
341
|
+
* a de uma vez anterior dele (o identificador da posse gravado na vaga é outro).
|
|
342
|
+
*/
|
|
343
|
+
function vagaDoAncestral(chave, dir) {
|
|
344
|
+
const bruto = process.env[exports.ENV_DONO_DA_FILA];
|
|
345
|
+
if (!bruto)
|
|
346
|
+
return null;
|
|
347
|
+
let marca;
|
|
348
|
+
try {
|
|
349
|
+
marca = JSON.parse(bruto);
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
const { pid, slot } = marca;
|
|
355
|
+
if (marca.raiz !== chave || typeof pid !== 'number' || !Number.isSafeInteger(pid) || pid <= 1 || pid === process.pid ||
|
|
356
|
+
typeof slot !== 'number' || !Number.isSafeInteger(slot) || slot < 0 || typeof marca.posse !== 'string')
|
|
357
|
+
return null;
|
|
358
|
+
if (inicioDoProcesso(pid) !== marca.inicio || !ancestral(pid))
|
|
359
|
+
return null;
|
|
360
|
+
const arquivo = path.join(dir, `vaga-${slot}.lock`);
|
|
361
|
+
try {
|
|
362
|
+
const gravado = JSON.parse(fs.readFileSync(arquivo, 'utf8'));
|
|
363
|
+
if (gravado.pid !== pid || gravado.posse !== marca.posse)
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
let fd;
|
|
370
|
+
try {
|
|
371
|
+
fd = abrirTrava(arquivo, false);
|
|
372
|
+
}
|
|
373
|
+
catch {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
return trancar(fd) ? null : slot;
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
fs.closeSync(fd);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Roda `executar` com a vez da fila de recursos pesados desta raiz de estado: a senha de chegada, a trava do
|
|
385
|
+
* artefato e uma das `slots` vagas, todas do kernel. Espera em primeiro plano até `esperarMs` e, sem a vez, lança
|
|
386
|
+
* `ErroDaFilaPesada` sem rodar nada. Dentro de quem já segura a vez neste processo, roda direto.
|
|
387
|
+
*/
|
|
388
|
+
function comRecursoPesado(raiz, pedido, executar) {
|
|
389
|
+
if (!(pedido.slots > 0))
|
|
390
|
+
return executar({ situacao: 'desligada', slot: null, esperouMs: 0 });
|
|
391
|
+
const chave = path.resolve((0, estado_thread_1.raizDoEstado)(raiz));
|
|
392
|
+
const atual = emCurso.get(chave);
|
|
393
|
+
if (atual)
|
|
394
|
+
return executar({ situacao: 'reentrada', slot: atual.slot, esperouMs: 0 });
|
|
395
|
+
if (!kernelDisponivel())
|
|
396
|
+
return executar({ situacao: 'sem-kernel', slot: null, esperouMs: 0 });
|
|
397
|
+
const dir = dirDaFilaPesada(raiz);
|
|
398
|
+
const doAncestral = vagaDoAncestral(chave, dir);
|
|
399
|
+
if (doAncestral !== null)
|
|
400
|
+
return executar({ situacao: 'reentrada', slot: doAncestral, esperouMs: 0 });
|
|
401
|
+
const inicio = Date.now();
|
|
402
|
+
const prazo = inicio + Math.max(0, pedido.esperarMs);
|
|
403
|
+
let senha = tirarSenha(dir);
|
|
404
|
+
let avisou = false;
|
|
405
|
+
try {
|
|
406
|
+
for (;;) {
|
|
407
|
+
const posse = minhaVez(dir, senha) ? tentarVaga(dir, pedido) : null;
|
|
408
|
+
if (posse) {
|
|
409
|
+
// Com a vaga na mão, a senha sai: quem vem depois disputa a próxima vaga livre.
|
|
410
|
+
devolverSenha(dir, senha);
|
|
411
|
+
senha = null;
|
|
412
|
+
emCurso.set(chave, { slot: posse.slot });
|
|
413
|
+
// Os comandos que rodam dentro da vez herdam a marca da posse: o verify aninhado neles é reentrada.
|
|
414
|
+
const marcaAnterior = process.env[exports.ENV_DONO_DA_FILA];
|
|
415
|
+
process.env[exports.ENV_DONO_DA_FILA] = JSON.stringify({ raiz: chave, pid: process.pid, inicio: inicioDoProcesso(process.pid), slot: posse.slot,
|
|
416
|
+
posse: posse.id });
|
|
417
|
+
try {
|
|
418
|
+
return executar({ situacao: 'adquirida', slot: posse.slot, esperouMs: Date.now() - inicio });
|
|
419
|
+
}
|
|
420
|
+
finally {
|
|
421
|
+
if (marcaAnterior === undefined)
|
|
422
|
+
delete process.env[exports.ENV_DONO_DA_FILA];
|
|
423
|
+
else
|
|
424
|
+
process.env[exports.ENV_DONO_DA_FILA] = marcaAnterior;
|
|
425
|
+
emCurso.delete(chave);
|
|
426
|
+
soltar(posse);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (Date.now() >= prazo)
|
|
430
|
+
throw new ErroDaFilaPesada(recusaDaFila(pedido, Date.now() - inicio, ocupantesDaFilaPesada(raiz)));
|
|
431
|
+
if (!avisou) {
|
|
432
|
+
avisou = true;
|
|
433
|
+
try {
|
|
434
|
+
pedido.aoEsperar?.(ocupantesDaFilaPesada(raiz));
|
|
435
|
+
}
|
|
436
|
+
catch { /* o aviso nunca derruba a espera */ }
|
|
437
|
+
}
|
|
438
|
+
dormir(Math.min(PAUSA_MS, prazo - Date.now()));
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
finally {
|
|
442
|
+
devolverSenha(dir, senha);
|
|
443
|
+
}
|
|
444
|
+
}
|
package/dist/fix.js
CHANGED
|
@@ -75,6 +75,7 @@ const thread_1 = require("./thread");
|
|
|
75
75
|
const util_1 = require("./util");
|
|
76
76
|
const verify_1 = require("./verify");
|
|
77
77
|
const conducao_1 = require("./conducao");
|
|
78
|
+
const locale_1 = require("./locale");
|
|
78
79
|
/** Armazem append-only das correcoes da thread. */
|
|
79
80
|
function caminhoDosFixes(raiz, threadId) {
|
|
80
81
|
return path.join((0, thread_1.dirThread)(raiz, threadId), 'fixes.jsonl');
|
|
@@ -213,7 +214,8 @@ function abrirRodada(carregado, threadId, opcoes = {}) {
|
|
|
213
214
|
function abrirRodadaSobConducao(carregado, threadId, opcoes) {
|
|
214
215
|
const { raiz } = carregado;
|
|
215
216
|
const thread = (0, thread_1.lerThread)(raiz, threadId);
|
|
216
|
-
|
|
217
|
+
// RM-058 N2 (A1 da rodada 2 do CHECK): a espera da fila pesada que o `--esperar` do CLI pediu.
|
|
218
|
+
const resultado = (0, verify_1.verificar)(carregado, threadId, { soClaims: opcoes.soClaims, conducao: { filaPesada: opcoes.conducao?.filaPesada } });
|
|
217
219
|
const rodada = ultimaRodada(raiz, threadId) + 1;
|
|
218
220
|
if (resultado.ok && resultado.motivos.length === 0) {
|
|
219
221
|
return {
|
|
@@ -319,7 +321,7 @@ function reverificarSobConducao(carregado, threadId, opcoes) {
|
|
|
319
321
|
: `${execucoes.length} comando(s) reexecutado(s) com sucesso no HEAD real`,
|
|
320
322
|
};
|
|
321
323
|
});
|
|
322
|
-
const verify = cobertura === 'completa' ? (0, verify_1.verificar)(carregado, threadId) : null;
|
|
324
|
+
const verify = cobertura === 'completa' ? (0, verify_1.verificar)(carregado, threadId, { conducao: { filaPesada: opcoes.conducao?.filaPesada } }) : null;
|
|
323
325
|
for (const v of vereditos) {
|
|
324
326
|
// Correcao sem comando proprio herda o veredito do verify completo, e so quando ele
|
|
325
327
|
// roda: sem ele, ela continua aberta em vez de virar aprovada por conveniencia.
|
|
@@ -417,25 +419,25 @@ function rodadasGastas(raiz, threadId) {
|
|
|
417
419
|
}
|
|
418
420
|
/** Texto de `ork fix open`. */
|
|
419
421
|
function textoDaRodada(r) {
|
|
422
|
+
const m = (0, locale_1.msg)().operacao.restante.fix;
|
|
420
423
|
if (r.correcoes.length === 0) {
|
|
421
|
-
return (
|
|
422
|
-
' (nenhum motivo tipado bloqueante em `ork verify`)');
|
|
424
|
+
return m.semCorrecoes(r.thread);
|
|
423
425
|
}
|
|
424
426
|
const linhas = [];
|
|
425
|
-
linhas.push(
|
|
426
|
-
linhas.push(
|
|
427
|
-
linhas.push(
|
|
428
|
-
linhas.push(
|
|
427
|
+
linhas.push(m.aberto(r.thread, r.rodada));
|
|
428
|
+
linhas.push(m.veredito(m.vereditos[r.veredito] ?? r.veredito));
|
|
429
|
+
linhas.push(m.motivos(r.motivos.join(', ')));
|
|
430
|
+
linhas.push(m.reexecucao(r.temTipoB));
|
|
429
431
|
linhas.push('');
|
|
430
|
-
linhas.push((0, util_1.tabela)([
|
|
432
|
+
linhas.push((0, util_1.tabela)([...m.colunas], r.correcoes.map((c) => [
|
|
431
433
|
c.id,
|
|
432
434
|
c.tipo,
|
|
433
435
|
c.origem,
|
|
434
436
|
c.alvo,
|
|
435
|
-
c.verificar.join(' && ') ||
|
|
437
|
+
c.verificar.join(' && ') || m.verifyCompleto,
|
|
436
438
|
])));
|
|
437
439
|
linhas.push('');
|
|
438
|
-
linhas.push(
|
|
440
|
+
linhas.push(m.spec);
|
|
439
441
|
linhas.push('');
|
|
440
442
|
for (const l of r.spec.split('\n'))
|
|
441
443
|
linhas.push(` ${l}`);
|
|
@@ -443,29 +445,30 @@ function textoDaRodada(r) {
|
|
|
443
445
|
}
|
|
444
446
|
/** Texto de `ork fix reverify`. */
|
|
445
447
|
function textoDoReverify(r) {
|
|
448
|
+
const m = (0, locale_1.msg)().operacao.restante.fix;
|
|
446
449
|
const linhas = [];
|
|
447
|
-
linhas.push(
|
|
448
|
-
linhas.push(
|
|
449
|
-
linhas.push(
|
|
450
|
+
linhas.push(m.reverify(r.thread, r.rodada));
|
|
451
|
+
linhas.push(m.cobertura(m.coberturas[r.cobertura] ?? r.cobertura));
|
|
452
|
+
linhas.push(m.rodadas(r.rodadas, r.limite));
|
|
450
453
|
linhas.push('');
|
|
451
|
-
linhas.push(
|
|
454
|
+
linhas.push(m.porCorrecao);
|
|
452
455
|
for (const v of r.vereditos) {
|
|
453
|
-
linhas.push(
|
|
454
|
-
linhas.push(
|
|
456
|
+
linhas.push(m.correcao(v.correcao.id, v.correcao.tipo, v.aprovada, v.correcao.alvo));
|
|
457
|
+
linhas.push(m.origem(v.correcao.origem));
|
|
455
458
|
linhas.push(` ${v.detalhe}`);
|
|
456
459
|
for (const e of v.execucoes) {
|
|
457
|
-
linhas.push(
|
|
460
|
+
linhas.push(m.execucao(e.ok, e.comando));
|
|
458
461
|
}
|
|
459
462
|
}
|
|
460
463
|
if (r.verify) {
|
|
461
464
|
linhas.push('');
|
|
462
|
-
linhas.push(
|
|
465
|
+
linhas.push(m.verify((0, util_1.shaCurto)(r.verify.commit), r.verify.ok, r.verify.motivos.join(', ')));
|
|
463
466
|
}
|
|
464
467
|
linhas.push('');
|
|
465
|
-
linhas.push(
|
|
468
|
+
linhas.push(m.final(m.vereditos[r.veredito] ?? r.veredito));
|
|
466
469
|
linhas.push(` ${r.razao}`);
|
|
467
470
|
if (r.escalado) {
|
|
468
|
-
linhas.push(
|
|
471
|
+
linhas.push(m.escalado);
|
|
469
472
|
}
|
|
470
473
|
return linhas.join('\n');
|
|
471
474
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CAPACIDADES = void 0;
|
|
4
|
+
/** Todas as capacidades, na ordem em que o `doctor` as mostra. */
|
|
5
|
+
exports.CAPACIDADES = ['checksNoCommit', 'estadoDeCi', 'pedidoMesclado', 'branchPadrao', 'pontaDaBranch',
|
|
6
|
+
'comparar', 'pedidosDaBranch', 'abrirPedido', 'metadados', 'pedidosAbertos', 'donoDaRede'];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ambienteDeCi = ambienteDeCi;
|
|
4
|
+
const CAMINHO = /^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)+$/;
|
|
5
|
+
/** A pagina web, sem credencial na URL (`user:senha@`): a URL vai ao JSON do `ork ci run`. */
|
|
6
|
+
const URL_WEB = /^https?:\/\/(?![^/]*@)\S+$/;
|
|
7
|
+
const NUMERO = /^\d+$/;
|
|
8
|
+
function valor(v, forma) {
|
|
9
|
+
const t = v?.trim();
|
|
10
|
+
if (!t || /\p{Cc}/u.test(t))
|
|
11
|
+
return null;
|
|
12
|
+
return !forma || forma.test(t) ? t : null;
|
|
13
|
+
}
|
|
14
|
+
function ambienteDeCi(env = process.env) {
|
|
15
|
+
if (env.GITLAB_CI === 'true') {
|
|
16
|
+
return { tipo: 'gitlab', produtor: 'gitlab-ci', repository: valor(env.CI_PROJECT_PATH, CAMINHO),
|
|
17
|
+
branch: valor(env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME) ?? valor(env.CI_COMMIT_BRANCH), url: valor(env.CI_JOB_URL, URL_WEB) };
|
|
18
|
+
}
|
|
19
|
+
if (env.GITHUB_ACTIONS === 'true') {
|
|
20
|
+
const repository = valor(env.GITHUB_REPOSITORY, CAMINHO);
|
|
21
|
+
const servidor = valor(env.GITHUB_SERVER_URL, URL_WEB), run = valor(env.GITHUB_RUN_ID, NUMERO);
|
|
22
|
+
return { tipo: 'github', produtor: 'github-actions', repository,
|
|
23
|
+
branch: valor(env.GITHUB_HEAD_REF) ?? (env.GITHUB_REF_TYPE === 'branch' ? valor(env.GITHUB_REF_NAME) : null),
|
|
24
|
+
url: servidor && repository && run ? `${servidor}/${repository}/actions/runs/${run}` : null };
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|