@orkastery/cli 0.5.6 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/adapters/README.md +18 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
  3. package/adapters/claude-code/README.md +37 -5
  4. package/adapters/claude-code/agents/ork-check.md +1 -0
  5. package/adapters/claude-code/agents/ork-go.md +1 -0
  6. package/adapters/claude-code/agents/ork-goal.md +1 -0
  7. package/adapters/claude-code/agents/ork-master.md +1 -0
  8. package/adapters/claude-code/agents/ork-plan.md +1 -0
  9. package/adapters/claude-code/agents/ork-ship.md +1 -0
  10. package/adapters/claude-code/hooks/hooks.json +2 -1
  11. package/adapters/claude-code/hooks/ork-guard.js +15 -1
  12. package/adapters/claude-code/hooks/ork-resposta.js +91 -0
  13. package/adapters/claude-code/hooks/ork-sensor.js +18 -2
  14. package/adapters/claude-code/hooks/quota-signal.js +14 -0
  15. package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
  16. package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
  17. package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
  18. package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
  19. package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
  20. package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
  21. package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
  22. package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
  23. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
  24. package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
  25. package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
  27. package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
  28. package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
  29. package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
  30. package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
  31. package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
  32. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
  33. package/adapters/codex/skills/ork/SKILL.md +2 -0
  34. package/adapters/hermes/README.md +64 -1
  35. package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
  36. package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
  37. package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
  38. package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
  39. package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
  40. package/adapters/hermes/hermes.plugin.json +4 -0
  41. package/adapters/hermes/hitl-ingress/__init__.py +101 -8
  42. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
  43. package/adapters/openclaw/README.md +81 -9
  44. package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
  45. package/adapters/openclaw/dist/hitl-ingress.js +106 -9
  46. package/adapters/openclaw/dist/index.js +86 -0
  47. package/adapters/openclaw/openclaw.plugin.json +34 -4
  48. package/adapters/openclaw/package.json +2 -2
  49. package/adapters/openclaw/src/hitl-ingress.ts +103 -9
  50. package/adapters/openclaw/src/index.ts +94 -0
  51. package/assets/adapters-en/claude-code/README.md +403 -0
  52. package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
  53. package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
  54. package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
  55. package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
  56. package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
  57. package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
  58. package/assets/adapters-en/claude-code/commands/check.md +46 -0
  59. package/assets/adapters-en/claude-code/commands/go.md +46 -0
  60. package/assets/adapters-en/claude-code/commands/goal.md +55 -0
  61. package/assets/adapters-en/claude-code/commands/master.md +54 -0
  62. package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
  63. package/assets/adapters-en/claude-code/commands/ork.md +126 -0
  64. package/assets/adapters-en/claude-code/commands/plan.md +47 -0
  65. package/assets/adapters-en/claude-code/commands/ship.md +45 -0
  66. package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
  67. package/assets/adapters-en/hermes/README.md +273 -0
  68. package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
  69. package/assets/references-en/README.md +25 -0
  70. package/assets/references-en/code-review-axes.md +82 -0
  71. package/assets/references-en/definition-of-done.md +74 -0
  72. package/assets/references-en/performance-checklist.md +53 -0
  73. package/assets/references-en/security-checklist.md +101 -0
  74. package/assets/references-en/testing-patterns.md +51 -0
  75. package/assets/security-scan/defaults/.golangci.yml +2 -0
  76. package/assets/security-scan/defaults/eslint.config.mjs +11 -0
  77. package/assets/security-scan/defaults/gitleaks.toml +3 -0
  78. package/assets/security-scan/defaults/ruff.toml +1 -0
  79. package/assets/security-scan/tools-agil.json +87 -0
  80. package/assets/security-scan/tools.json +625 -0
  81. package/assets/skills-en/core/onboarding/SKILL.md +58 -0
  82. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
  83. package/assets/skills-en/core/thread-state/SKILL.md +88 -0
  84. package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
  85. package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
  86. package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
  87. package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
  88. package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
  89. package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
  90. package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
  91. package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
  92. package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
  93. package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
  94. package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
  95. package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
  96. package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
  97. package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
  98. package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
  99. package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
  100. package/dist/adapters/claude-bg.js +123 -9
  101. package/dist/adapters/codex-controller-worker.js +12 -5
  102. package/dist/adapters/codex-events.js +16 -4
  103. package/dist/adapters/codex.js +3 -1
  104. package/dist/adapters/grok-events.js +227 -0
  105. package/dist/adapters/grok-mcp-servidor.js +612 -0
  106. package/dist/adapters/grok-mcp.js +178 -0
  107. package/dist/adapters/grok.js +686 -0
  108. package/dist/agendador-cpu.js +92 -0
  109. package/dist/atualizar-branch.js +245 -0
  110. package/dist/auditoria.js +13 -11
  111. package/dist/auditrun.js +51 -46
  112. package/dist/autorizacao-duravel.js +327 -0
  113. package/dist/board.js +94 -40
  114. package/dist/branch-de-estado.js +23 -10
  115. package/dist/busca-semantica.js +7 -5
  116. package/dist/catalogo.js +2 -1
  117. package/dist/changelog-reconciliacao.js +290 -0
  118. package/dist/check-agil.js +528 -0
  119. package/dist/check-modo.js +41 -0
  120. package/dist/check-paralelo.js +238 -0
  121. package/dist/ci.js +248 -45
  122. package/dist/ciclos.js +8 -6
  123. package/dist/claim-lint.js +12 -8
  124. package/dist/claims-conferir.js +47 -39
  125. package/dist/claims.js +10 -9
  126. package/dist/company-brain-client.js +10 -3
  127. package/dist/company-brain-migration.js +11 -5
  128. package/dist/conducao-batida.js +759 -0
  129. package/dist/conducao-sentinela.js +25 -8
  130. package/dist/conducao.js +89 -29
  131. package/dist/conhecimento-consulta.js +270 -0
  132. package/dist/conhecimento.js +111 -87
  133. package/dist/conta-esgotada.js +127 -0
  134. package/dist/dado-privado.js +816 -0
  135. package/dist/decisao-autonoma.js +5 -4
  136. package/dist/demo.js +14 -12
  137. package/dist/dependencias-da-worktree.js +25 -0
  138. package/dist/divida.js +38 -36
  139. package/dist/docs.js +89 -89
  140. package/dist/doctor-forja.js +343 -0
  141. package/dist/doctor-pulse-cron.js +113 -1
  142. package/dist/doctor.js +164 -6
  143. package/dist/dsn-da-memoria.js +417 -0
  144. package/dist/entrega-por-mod.js +503 -0
  145. package/dist/entrega-pr.js +154 -54
  146. package/dist/esgotamentos.js +13 -11
  147. package/dist/estado-thread.js +21 -18
  148. package/dist/evalrunner.js +35 -32
  149. package/dist/fabrica-batida.js +34 -21
  150. package/dist/fabrica-estado.js +33 -21
  151. package/dist/fix.js +21 -19
  152. package/dist/forja/adaptador.js +6 -0
  153. package/dist/forja/ambiente-de-ci.js +27 -0
  154. package/dist/forja/api.js +256 -0
  155. package/dist/forja/cache.js +89 -0
  156. package/dist/forja/cli.js +60 -0
  157. package/dist/forja/contrato.js +9 -0
  158. package/dist/forja/endereco.js +43 -0
  159. package/dist/forja/estado.js +22 -0
  160. package/dist/forja/executor.js +73 -0
  161. package/dist/forja/github/ci.js +95 -0
  162. package/dist/forja/github/dono-da-rede.js +18 -0
  163. package/dist/forja/github/metadados.js +15 -0
  164. package/dist/forja/github/pedidos.js +200 -0
  165. package/dist/forja/gitlab/ci.js +141 -0
  166. package/dist/forja/gitlab/consultas.js +59 -0
  167. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  168. package/dist/forja/gitlab/metadados.js +15 -0
  169. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  170. package/dist/forja/gitlab/pedidos.js +141 -0
  171. package/dist/forja/produtor.js +32 -0
  172. package/dist/forja/registro.js +31 -0
  173. package/dist/forja/resolver.js +121 -0
  174. package/dist/forja/texto.js +13 -0
  175. package/dist/forja/versao.js +71 -0
  176. package/dist/forja.js +123 -80
  177. package/dist/handoff.js +23 -13
  178. package/dist/hitl-contract.js +46 -43
  179. package/dist/hitl-curto.js +37 -25
  180. package/dist/hitl-gates.js +13 -11
  181. package/dist/hitl-local-receipt.js +51 -0
  182. package/dist/hitl-local.js +11 -2
  183. package/dist/hitl-lock.js +5 -11
  184. package/dist/hitl-public-receipt.js +11 -0
  185. package/dist/hitl-resumo.js +44 -1
  186. package/dist/hitl-sessions.js +62 -9
  187. package/dist/hitl-texto-livre.js +7 -4
  188. package/dist/hitl.js +34 -31
  189. package/dist/horario.js +20 -1
  190. package/dist/hosts.js +104 -134
  191. package/dist/index.js +864 -554
  192. package/dist/indice-vetorial.js +14 -12
  193. package/dist/init.js +11 -2
  194. package/dist/integracoes-locais.js +4 -0
  195. package/dist/intelligence-graph-cli.js +123 -69
  196. package/dist/intelligence-graph-query.js +37 -22
  197. package/dist/leases.js +19 -18
  198. package/dist/ledger-stats.js +17 -16
  199. package/dist/ledger.js +31 -1
  200. package/dist/licoes.js +12 -11
  201. package/dist/locale-accounts.js +228 -0
  202. package/dist/locale-adapter.js +291 -0
  203. package/dist/locale-ajuda.js +86 -10
  204. package/dist/locale-audit.js +199 -0
  205. package/dist/locale-claims.js +213 -0
  206. package/dist/locale-conducao.js +138 -0
  207. package/dist/locale-conhecimento.js +181 -0
  208. package/dist/locale-decisao.js +205 -0
  209. package/dist/locale-docs.js +230 -0
  210. package/dist/locale-estado.js +101 -0
  211. package/dist/locale-forja.js +288 -0
  212. package/dist/locale-gerados.js +5 -0
  213. package/dist/locale-grafo.js +129 -0
  214. package/dist/locale-master.js +83 -0
  215. package/dist/locale-network.js +524 -0
  216. package/dist/locale-operacao-restante.js +931 -0
  217. package/dist/locale-projetos.js +100 -0
  218. package/dist/locale-prompts.js +194 -0
  219. package/dist/locale-pulse.js +140 -2
  220. package/dist/locale-reservas.js +87 -0
  221. package/dist/locale-retry.js +183 -6
  222. package/dist/locale-security-scan.js +69 -0
  223. package/dist/locale-setup.js +192 -0
  224. package/dist/locale-ship.js +177 -66
  225. package/dist/locale-thread.js +149 -5
  226. package/dist/locale-verify.js +80 -4
  227. package/dist/locale-worktree.js +246 -0
  228. package/dist/locale.js +553 -9
  229. package/dist/maestro-runtime.js +22 -3
  230. package/dist/manifest.js +293 -12
  231. package/dist/maquina-ociosa.js +211 -0
  232. package/dist/maquina.js +10 -5
  233. package/dist/master-nota-local.js +200 -0
  234. package/dist/master-nota.js +10 -2
  235. package/dist/master.js +118 -41
  236. package/dist/mcp-conhecimento.js +52 -0
  237. package/dist/mcp-experiencia.js +26 -5
  238. package/dist/mcp-install.js +90 -15
  239. package/dist/mcp-noctum.js +101 -0
  240. package/dist/mcp-server.js +116 -22
  241. package/dist/mcp-ship-transporte.js +977 -0
  242. package/dist/mcp-ship.js +68 -24
  243. package/dist/mcp-transportes.js +17 -0
  244. package/dist/memoria.js +63 -58
  245. package/dist/merge-da-entrega.js +85 -0
  246. package/dist/modos-migracao.js +8 -6
  247. package/dist/modos.js +17 -18
  248. package/dist/network-roadmap.js +94 -54
  249. package/dist/noctum-aceite.js +929 -0
  250. package/dist/noctum-arco.js +540 -33
  251. package/dist/noctum-capacidade.js +3 -3
  252. package/dist/noctum-changelog.js +399 -0
  253. package/dist/noctum-cli.js +539 -0
  254. package/dist/noctum-coordenacao.js +1225 -0
  255. package/dist/noctum-entrega.js +1217 -0
  256. package/dist/noctum-envelope.js +253 -17
  257. package/dist/noctum-execucao.js +100 -24
  258. package/dist/noctum-fechamento.js +416 -0
  259. package/dist/noctum-fila.js +49 -10
  260. package/dist/noctum-guarda.js +333 -0
  261. package/dist/noctum-integracao.js +507 -0
  262. package/dist/noctum-maquinas.js +387 -0
  263. package/dist/noctum-medicao.js +450 -0
  264. package/dist/noctum-modo.js +390 -0
  265. package/dist/noctum-pergunta-canal.js +96 -0
  266. package/dist/noctum-pergunta.js +115 -0
  267. package/dist/noctum-provas.js +838 -0
  268. package/dist/noctum-reconciliacao.js +594 -0
  269. package/dist/noctum-rede.js +102 -0
  270. package/dist/noctum-registro.js +215 -0
  271. package/dist/noctum-relatorio.js +861 -0
  272. package/dist/noctum-resposta.js +207 -0
  273. package/dist/noctum-retomada-rede.js +71 -0
  274. package/dist/noctum-sessoes-em-voo.js +93 -0
  275. package/dist/noctum-supervisao.js +649 -0
  276. package/dist/noctum-terminal.js +459 -0
  277. package/dist/noctum-transporte.js +655 -0
  278. package/dist/noctum-vigia.js +679 -0
  279. package/dist/ocupacao.js +3 -1
  280. package/dist/onboarding.js +16 -5
  281. package/dist/orkmind.js +39 -23
  282. package/dist/orquestracao.js +31 -35
  283. package/dist/parado-no-condutor.js +160 -139
  284. package/dist/phase.js +96 -42
  285. package/dist/policies.js +33 -0
  286. package/dist/postura-local.js +11 -6
  287. package/dist/preflight.js +2 -1
  288. package/dist/procedencia.js +9 -14
  289. package/dist/projeto-alvo.js +59 -20
  290. package/dist/prompts.js +136 -42
  291. package/dist/prova-minima.js +5 -6
  292. package/dist/pulse-cadencia.js +5 -4
  293. package/dist/pulse-consentimento.js +53 -1
  294. package/dist/pulse-delivery.js +143 -27
  295. package/dist/pulse-resposta.js +368 -4
  296. package/dist/pulse.js +136 -3
  297. package/dist/ratelimit.js +13 -4
  298. package/dist/recall.js +14 -13
  299. package/dist/rede-adesao.js +13 -8
  300. package/dist/rede-forja.js +108 -24
  301. package/dist/rede-status.js +63 -45
  302. package/dist/rede.js +86 -46
  303. package/dist/retomada-checkpoint.js +101 -0
  304. package/dist/retry.js +326 -78
  305. package/dist/roadmap-reservas.js +32 -32
  306. package/dist/runtime-ambiente.js +5 -0
  307. package/dist/runtime-context.js +279 -85
  308. package/dist/runtime-escada.js +429 -0
  309. package/dist/runtime-profiles.js +130 -63
  310. package/dist/runtimes.js +42 -5
  311. package/dist/saida-segura.js +3 -2
  312. package/dist/security-scan/agil.js +366 -0
  313. package/dist/security-scan/cli.js +76 -0
  314. package/dist/security-scan/compare.js +149 -0
  315. package/dist/security-scan/config.js +93 -0
  316. package/dist/security-scan/detect.js +97 -0
  317. package/dist/security-scan/executor.js +196 -0
  318. package/dist/security-scan/guard.js +180 -0
  319. package/dist/security-scan/imagem-de-lint.js +96 -0
  320. package/dist/security-scan/normalize/actionlint.js +12 -0
  321. package/dist/security-scan/normalize/eslint.js +12 -0
  322. package/dist/security-scan/normalize/gitleaks.js +13 -0
  323. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  324. package/dist/security-scan/normalize/govulncheck.js +36 -0
  325. package/dist/security-scan/normalize/index.js +25 -0
  326. package/dist/security-scan/normalize/npm-audit.js +30 -0
  327. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  328. package/dist/security-scan/normalize/oxlint.js +51 -0
  329. package/dist/security-scan/normalize/pip-audit.js +16 -0
  330. package/dist/security-scan/normalize/ruff.js +12 -0
  331. package/dist/security-scan/normalize/semgrep.js +20 -0
  332. package/dist/security-scan/normalize/trivy.js +33 -0
  333. package/dist/security-scan/normalize/util.js +204 -0
  334. package/dist/security-scan/normalize/zizmor.js +19 -0
  335. package/dist/security-scan/report.js +156 -0
  336. package/dist/security-scan/run.js +448 -0
  337. package/dist/security-scan/tools.js +62 -0
  338. package/dist/security-scan/trabalhador.js +74 -0
  339. package/dist/security-scan/types.js +15 -0
  340. package/dist/session-events.js +19 -2
  341. package/dist/session-watcher-claude.js +74 -19
  342. package/dist/session-watcher-grok.js +425 -0
  343. package/dist/session-watcher.js +174 -13
  344. package/dist/sessoes-contas.js +42 -5
  345. package/dist/sessoes-inventario.js +1 -1
  346. package/dist/sessoes.js +25 -23
  347. package/dist/setup.js +67 -66
  348. package/dist/ship-publicar.js +263 -92
  349. package/dist/ship.js +160 -17
  350. package/dist/superficie.js +14 -11
  351. package/dist/thread-close.js +9 -9
  352. package/dist/thread.js +121 -18
  353. package/dist/tokens.js +15 -11
  354. package/dist/trabalho-thread.js +297 -0
  355. package/dist/transporte-do-canal.js +189 -0
  356. package/dist/types.js +12 -1
  357. package/dist/util.js +5 -2
  358. package/dist/varredura-acoes.js +500 -0
  359. package/dist/verify.js +491 -32
  360. package/dist/worktree-local.js +12 -10
  361. package/dist/worktree.js +81 -85
  362. package/eval/casos/check-quality.json +77 -0
  363. package/eval/casos/security-auditor.json +148 -0
  364. package/eval/casos/security-remediation.json +161 -0
  365. package/eval/fixtures/security-scan/README.md +8 -0
  366. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  367. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  368. package/eval/fixtures/security-scan/go/README.md +4 -0
  369. package/eval/fixtures/security-scan/go/config.go +4 -0
  370. package/eval/fixtures/security-scan/go/go.mod +5 -0
  371. package/eval/fixtures/security-scan/go/go.sum +2 -0
  372. package/eval/fixtures/security-scan/go/main.go +31 -0
  373. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  374. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  375. package/eval/fixtures/security-scan/js/README.md +4 -0
  376. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  377. package/eval/fixtures/security-scan/js/package.json +10 -0
  378. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  379. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  380. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  381. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  382. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  383. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  384. package/eval/fixtures/security-scan/python/README.md +4 -0
  385. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  386. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  387. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  388. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  389. package/package.json +10 -5
  390. package/references/security-checklist.md +3 -3
  391. package/skills/README.md +1 -0
  392. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  393. package/skills/phases/check-quality/SKILL.md +16 -0
  394. package/skills/phases/go-implementation/SKILL.md +6 -0
  395. package/skills/phases/security-remediation/SKILL.md +70 -0
  396. package/skills/reviewers/security-auditor/SKILL.md +25 -0
@@ -33,11 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.CONTRATO_FORJA_SEM_LEITURA = exports.ghPadrao = exports.FORJA_SEM_LEITURA = exports.LIMITE_DE_RECENTES = exports.LIMITE_DE_PRS = exports.VALIDADE_DO_RETRATO_MIN = exports.LIMIAR_PARADO_NO_CONDUTOR_MIN = exports.CONTRATO_PRS = void 0;
36
+ exports.CONTRATO_FORJA_SEM_LEITURA = exports.ghPadrao = exports.FORJA_SEM_LEITURA = exports.LIMITES_DOS_PEDIDOS = exports.LIMITE_DE_RECENTES = exports.LIMITE_DE_PRS = exports.VALIDADE_DO_RETRATO_MIN = exports.LIMIAR_PARADO_NO_CONDUTOR_MIN = exports.CONTRATO_PRS = void 0;
37
37
  exports.nomeDeCheck = nomeDeCheck;
38
38
  exports.prDaForja = prDaForja;
39
39
  exports.githubDoRemoto = githubDoRemoto;
40
40
  exports.repositorioDoRemoto = repositorioDoRemoto;
41
+ exports.forjaDoRemotoDoPulse = forjaDoRemotoDoPulse;
41
42
  exports.lerPrsDaForja = lerPrsDaForja;
42
43
  exports.gravarRetratoDePrs = gravarRetratoDePrs;
43
44
  exports.avisarForjaSemLeitura = avisarForjaSemLeitura;
@@ -78,11 +79,18 @@ exports.entregasDoProjeto = entregasDoProjeto;
78
79
  */
79
80
  const fs = __importStar(require("node:fs"));
80
81
  const path = __importStar(require("node:path"));
81
- const node_child_process_1 = require("node:child_process");
82
+ const api_1 = require("./forja/api");
83
+ const cli_1 = require("./forja/cli");
84
+ const endereco_1 = require("./forja/endereco");
85
+ const executor_1 = require("./forja/executor");
86
+ const resolver_1 = require("./forja/resolver");
87
+ const registro_1 = require("./forja/registro");
88
+ const estado_1 = require("./forja/estado");
82
89
  const branch_de_estado_1 = require("./branch-de-estado");
83
90
  const conducao_1 = require("./conducao");
84
91
  const estado_thread_1 = require("./estado-thread");
85
92
  const forja_1 = require("./forja");
93
+ const locale_1 = require("./locale");
86
94
  const hitl_1 = require("./hitl");
87
95
  const hitl_contract_1 = require("./hitl-contract");
88
96
  const hitl_classificacao_1 = require("./hitl-classificacao");
@@ -94,6 +102,7 @@ const session_watcher_claude_1 = require("./session-watcher-claude");
94
102
  const thread_1 = require("./thread");
95
103
  const util_1 = require("./util");
96
104
  const worktree_1 = require("./worktree");
105
+ const merge_da_entrega_1 = require("./merge-da-entrega");
97
106
  exports.CONTRATO_PRS = 'ork.prs-abertos/v1';
98
107
  /** D4: duas batidas do pulse. Abaixo disto o condutor pode estar agindo. */
99
108
  exports.LIMIAR_PARADO_NO_CONDUTOR_MIN = 30;
@@ -103,36 +112,26 @@ exports.VALIDADE_DO_RETRATO_MIN = 60;
103
112
  exports.LIMITE_DE_PRS = 200;
104
113
  /** Quantos PRs recentes (de qualquer estado) a segunda leitura pede: so para achar o mesclado e o fechado. */
105
114
  exports.LIMITE_DE_RECENTES = 100;
115
+ const PRAZO_DO_GH_MS = 30000;
116
+ /** Os tetos e o prazo de cada chamada da leitura de pedidos, que o adaptador de cada forja respeita. */
117
+ exports.LIMITES_DOS_PEDIDOS = { abertos: exports.LIMITE_DE_PRS, recentes: exports.LIMITE_DE_RECENTES, candidatas: 10,
118
+ minimoDaConferenciaMs: 5000, prazoMs: PRAZO_DO_GH_MS };
106
119
  /** Retrato com data mais a frente do relogio do que isto nao vale (relogio adiantado ou arquivo mexido). */
107
120
  const FOLGA_DO_RELOGIO_MIN = 5;
108
121
  const ARQUIVO_DOS_PRS = 'prs.json';
109
- const PRAZO_DO_GH_MS = 30000;
110
122
  /** A leitura inteira da forja numa batida: cabe com folga nos 240 s que a varredura da ao subprocesso do pulse. */
111
123
  const ORCAMENTO_DA_LEITURA_MS = 60000;
112
- const CAMPOS_DOS_RECENTES = 'number,state,headRefName,headRefOid,baseRefName,isDraft,isCrossRepository,url,createdAt,mergedAt';
113
- /** RM-059 (F7, D11 da ork-rm059pista): o estado de merge do PR aberto, que a pista de entrega mostra como conflito. */
114
- const CAMPOS_DO_GH = `${CAMPOS_DOS_RECENTES},statusCheckRollup,mergeable`;
115
- /** Quantas branches candidatas a "sem PR" sao conferidas uma a uma por batida; o resto fica "PR nao lido". */
116
- const LIMITE_DE_CANDIDATAS = 10;
117
- /** A conferencia de uma candidata so comeca com este tempo de sobra no orcamento; com menos, a branch fica sem conferir. */
118
- const MINIMO_DA_CONFERENCIA_MS = 5000;
119
124
  /** As fases que o ciclo despacha antes da entrega: depois de um bloco que para nelas, o passo e despachar, nao publicar. */
120
125
  const FASES_ANTES_DA_ENTREGA = ['GOAL', 'PLAN', 'GO', 'CHECK'];
121
126
  /** Os modos em que a #TAG ja autoriza o push (`autorizacaoDePush`, `core/src/ship.ts`). */
122
127
  const MODOS_COM_PUSH_AUTORIZADO = ['auto', 'maestro'];
123
128
  /** RM-037 (fatia 5, A5): o que as linhas e o resumo dizem quando a forja nao tem leitura de PR. */
124
129
  exports.FORJA_SEM_LEITURA = 'forja sem leitura de PR';
125
- /** O ambiente do `gh`: sem cor, sem prompt e sem host ou repositorio herdados (o host vai no `--repo`). */
126
- function ambienteDoGh() {
127
- const env = { ...process.env, GH_PROMPT_DISABLED: '1', NO_COLOR: '1', CLICOLOR: '0', CLICOLOR_FORCE: '0' };
128
- delete env.GH_HOST;
129
- delete env.GH_REPO;
130
- delete env.GH_FORCE_TTY;
131
- return env;
132
- }
133
130
  const ghPadrao = (args, timeoutMs) => {
134
- const r = (0, node_child_process_1.spawnSync)('gh', [...args], { encoding: 'utf8', timeout: timeoutMs, maxBuffer: 16 * 1024 * 1024, env: ambienteDoGh() });
135
- return { status: r.status, stdout: r.stdout ?? '', stderr: r.error ? r.error.message : (r.stderr ?? '') };
131
+ const r = (0, executor_1.rodarCli)({ cmd: 'gh', args, prazoMs: timeoutMs, maxBuffer: 16 * 1024 * 1024, procurarBinario: false,
132
+ acrescentar: { GH_PROMPT_DISABLED: '1', NO_COLOR: '1', CLICOLOR: '0', CLICOLOR_FORCE: '0' },
133
+ apagar: ['GH_HOST', 'GH_REPO', 'GH_FORCE_TTY'] });
134
+ return { status: r.status, stdout: r.stdout, stderr: r.mensagemDoErro ?? r.stderr };
136
135
  };
137
136
  exports.ghPadrao = ghPadrao;
138
137
  /** Git local sem rede escondida: clone parcial nunca busca objeto durante uma leitura daqui. */
@@ -140,6 +139,10 @@ const git = (raiz, args) => (0, util_1.exec)('git', args, raiz, 60000, { ...proc
140
139
  const SHA = /^[0-9a-f]{40}$/;
141
140
  const BRANCH = /^[A-Za-z0-9._/-]{1,200}$/;
142
141
  const REPOSITORIO = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
142
+ /** O caminho do projeto no retrato: `dono/nome` no GitHub, o caminho completo com subgrupos no GitLab. */
143
+ const CAMINHO_DO_PROJETO = /^[A-Za-z0-9_.-]{1,100}(?:\/[A-Za-z0-9_.-]{1,100}){1,19}$/;
144
+ /** O caminho do projeto na forma, sem segmento `.` ou `..`. */
145
+ const caminhoDoProjeto = (v) => CAMINHO_DO_PROJETO.test(v) && v.split('/').every((p) => p !== '.' && p !== '..');
143
146
  /** O host do GitHub Enterprise guardado no retrato: rotulos alfanumericos separados por ponto, como na forja. */
144
147
  const HOST = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/;
145
148
  /** Texto curto vindo de fora: sem controle, num teto. */
@@ -185,11 +188,13 @@ function checkDaForja(c) {
185
188
  let situacao;
186
189
  if (o.__typename === 'StatusContext' || (o.status === undefined && typeof o.state === 'string')) {
187
190
  const s = String(o.state ?? '').toUpperCase();
188
- situacao = s === 'SUCCESS' ? 'verde' : s === 'FAILURE' || s === 'ERROR' ? 'vermelho' : 'pendente';
191
+ situacao = (0, estado_1.estadoDoCheck)('commit-status', s, null);
189
192
  }
190
193
  else {
191
194
  const status = String(o.status ?? '').toUpperCase(), conclusao = String(o.conclusion ?? '').toUpperCase();
192
- situacao = status !== 'COMPLETED' ? 'pendente' : ['SUCCESS', 'NEUTRAL', 'SKIPPED'].includes(conclusao) ? 'verde' : 'vermelho';
195
+ // O pulse mostra o job pulado de proposito como verde, como sempre: so o gate trata `bloqueado` como nao verde.
196
+ const estado = (0, estado_1.estadoDoCheck)('check-run', status, conclusao);
197
+ situacao = estado === 'bloqueado' ? 'verde' : estado;
193
198
  }
194
199
  const concluidoEm = situacao === 'pendente' ? null : instante(o.completedAt) ?? instante(o.startedAt);
195
200
  return { check: { nome, situacao, concluidoEm }, chave, inicio: instante(o.startedAt) ?? instante(o.completedAt) ?? '' };
@@ -252,52 +257,97 @@ function repositorioDoRemoto(raiz, remoto) {
252
257
  const github = githubDoRemoto(raiz, remoto);
253
258
  return github && github.host === 'github.com' ? github.repositorio : null;
254
259
  }
260
+ const githubResolvido = (f) => ({ tipo: 'github', host: f.host, porta: null,
261
+ caminhoBase: '', sshHost: null, sshPorta: null, ca: null, repo: f.repositorio,
262
+ origem: { tipo: 'remoto', host: 'remoto', porta: 'padrao', caminhoBase: 'padrao' } });
255
263
  /**
256
- * RM-037 (fatia 5, A5): de onde o pulse le os PRs do remoto. O github.com, como sempre; o host proprio em que o `gh`
257
- * esta autenticado, que e um GitHub Enterprise (`gh auth status --hostname <host>`); ou nenhum: GitLab, caminho local,
258
- * ou host em que o `gh` nao tem login. Ficar sem leitura nao e falha desta batida (o "PR nao lido"): e o estado da
259
- * forja, que o pulse diz uma vez.
264
+ * As sondas do pulse: o GitHub pelo `gh auth status --hostname` de sempre (o host proprio em que o `gh` tem login e
265
+ * um GitHub Enterprise) e o GitLab pela sonda padrao (o `glab` com login no host responde o `metadata`). O `auth
266
+ * status` que falha por outro motivo que nao a falta de login (prazo, rede, `gh` ausente) fica em `falha`.
260
267
  */
261
- function forjaDosPrs(raiz, remoto, executor, prazoMs) {
268
+ function sondasDoPulse(executor, prazoMs, rodar, logins, falha) {
269
+ return {
270
+ github: (alvo) => {
271
+ if (alvo.caminhoBase)
272
+ return 'nao-responde';
273
+ // Com porta propria, o login se confere no `host:porta` exato, pela sonda padrao: o `--hostname` nao leva porta.
274
+ if (alvo.porta !== null && alvo.porta !== 443)
275
+ return (0, resolver_1.sondasPadrao)(rodar, logins).github(alvo);
276
+ const auth = executor(['auth', 'status', '--hostname', alvo.host], prazoMs);
277
+ if (auth.status === 0)
278
+ return 'responde';
279
+ // So a resposta de login ausente (o `gh` 2.46 diz "You are not logged into any accounts on <host>") e o estado
280
+ // da forja; prazo estourado, `gh` ausente ou host fora do ar sao falha desta batida.
281
+ if (auth.status === 1 && /\bnot logged in/i.test(`${auth.stdout}\n${auth.stderr}`)) {
282
+ falha.ghSemLogin = true;
283
+ return 'sem-login';
284
+ }
285
+ falha.gh = `gh auth status --hostname ${alvo.host} falhou (${auth.status === null ? 'sem código de saída' : `código ${auth.status}`}): ` +
286
+ (curto((0, hitl_1.redigirSegredos)(auth.stderr || auth.stdout || ''), 120) ?? 'sem detalhe');
287
+ return 'nao-responde';
288
+ },
289
+ gitlab: (alvo) => {
290
+ const r = (0, resolver_1.sondasPadrao)(rodar, logins).gitlab(alvo);
291
+ if (r === 'sem-login')
292
+ falha.glabSemLogin = true;
293
+ return r;
294
+ },
295
+ };
296
+ }
297
+ /**
298
+ * De onde o pulse le os pedidos do remoto: a forja resolvida pelo bloco `forja:` do manifesto, pelo host conhecido ou
299
+ * pela sondagem so por CLI com login no host (nunca pelo nome do host). Ficar sem leitura (remoto sem forja, forja
300
+ * que nao se resolve, tipo sem a capacidade) nao e falha desta batida: e o estado da forja, que o pulse diz uma vez.
301
+ */
302
+ function forjaDosPrs(carregado, remoto, executor, prazoMs, rodar, logins, sondas) {
262
303
  // RM-047: remoto que nao e nome de remoto nao chega ao git; para o pulse, e forja sem leitura.
263
304
  if (!(0, branch_de_estado_1.remotoValido)(remoto)) {
264
305
  return { leitura: false, host: null, motivo: `o remoto ${(0, branch_de_estado_1.remotoRedigido)(remoto)} não é nome de remoto do git`, semLeitura: true };
265
306
  }
266
- const url = git(raiz, ['remote', 'get-url', '--', remoto]);
307
+ const url = git(carregado.raiz, ['remote', 'get-url', '--', remoto]);
267
308
  if (!url.ok)
268
309
  return { leitura: false, host: null, motivo: `o remoto ${remoto} não está configurado neste checkout`, semLeitura: true };
269
- const endereco = (0, forja_1.enderecoDoRemoto)(url.stdout.trim());
310
+ const endereco = (0, forja_1.enderecoDoRemoto)(url.stdout.trim()), lido = (0, endereco_1.lerEnderecoDoRemoto)(url.stdout.trim());
270
311
  // Caminho local, ou apelido de SSH sem dominio (`git@github-trabalho:dono/repo.git`): nao ha host para ler.
271
- if (!endereco) {
312
+ if (!endereco || !lido) {
272
313
  return { leitura: false, host: null, motivo: `o remoto ${remoto} não tem host de forja (caminho local ou apelido de SSH)`, semLeitura: true };
273
314
  }
274
- if ((0, forja_1.identidadeDaForja)(url.stdout.trim())?.tipo === 'gitlab') {
275
- return { leitura: false, host: endereco.host, motivo: `a forja de ${remoto} (${endereco.host}) é um GitLab, e o ork só lê PR do GitHub`,
276
- semLeitura: true };
315
+ const falha = {};
316
+ // Sem o cache de 24 h: o pulse percebe na batida seguinte a CLI que perdeu o login no host.
317
+ const r = (0, resolver_1.resolverForja)({ endereco: lido, manifesto: carregado.manifesto.forja, sondas: sondas ?? sondasDoPulse(executor, prazoMs, rodar, logins, falha) });
318
+ if (!r.ok) {
319
+ if (falha.gh)
320
+ return { leitura: false, host: endereco.host, semLeitura: false, motivo: falha.gh };
321
+ const erro = r.erro;
322
+ const motivo = erro.codigo === 'forja.desconhecida' && falha.ghSemLogin
323
+ ? (0, locale_1.textoDoCatalogo)((m) => falha.glabSemLogin ? m.pulse.forjaSemLoginNasDuas(endereco.host, remoto) : m.pulse.forjaSemLogin('gh', endereco.host, remoto))
324
+ : (0, locale_1.textoDoCatalogo)((m) => m.pulse.forjaNaoResolvida(remoto, m.forja.motivo(erro, null)));
325
+ return { leitura: false, host: endereco.host, semLeitura: true, motivo };
277
326
  }
278
- const github = githubDoRemoto(raiz, remoto);
279
- if (!github) {
327
+ const forja = r.valor;
328
+ if (forja.tipo === 'github' && !REPOSITORIO.test(forja.repo)) {
280
329
  return { leitura: false, host: endereco.host, motivo: `o remoto ${remoto} (${endereco.host}) não aponta um repositório dono/nome`,
281
330
  semLeitura: true };
282
331
  }
283
- if (github.host === 'github.com')
284
- return { leitura: true, ...github };
285
- const auth = executor(['auth', 'status', '--hostname', github.host], prazoMs);
286
- if (auth.status === 0)
287
- return { leitura: true, ...github };
288
- // So a resposta de login ausente (o `gh` 2.46 diz "You are not logged into any accounts on <host>") e o estado da
289
- // forja; prazo estourado, `gh` ausente ou host fora do ar sao falha desta batida.
290
- const semLogin = auth.status === 1 && /\bnot logged in/i.test(`${auth.stdout}\n${auth.stderr}`);
291
- return { leitura: false, host: github.host, semLeitura: semLogin, motivo: semLogin
292
- ? `o gh não está autenticado em ${github.host}, a forja de ${remoto}`
293
- : `gh auth status --hostname ${github.host} falhou (${auth.status === null ? 'sem código de saída' : `código ${auth.status}`}): ` +
294
- (curto((0, hitl_1.redigirSegredos)(auth.stderr || auth.stdout || ''), 120) ?? 'sem detalhe') };
332
+ if (!(0, registro_1.adaptadorDaForja)(forja.tipo).pedidosAbertos) {
333
+ return { leitura: false, host: endereco.host, semLeitura: true,
334
+ motivo: (0, locale_1.textoDoCatalogo)((m) => m.pulse.forjaSemPedidos(forja.tipo, forja.host, remoto)) };
335
+ }
336
+ return { leitura: true, forja, hostDoRemoto: endereco.host };
337
+ }
338
+ /**
339
+ * A forja do remoto como o pulse a resolve (o bloco `forja:`, o host conhecido, o cache ou a sondagem pela CLI com
340
+ * login), sem ler pedido nenhum: a pista a usa num host proprio, para seguir o caminho da forja certa. `erro` e a frase
341
+ * que a leitura dos pedidos diria.
342
+ */
343
+ function forjaDoRemotoDoPulse(carregado, remoto, opcoes = {}) {
344
+ const lido = forjaDosPrs(carregado, remoto, opcoes.executor ?? exports.ghPadrao, PRAZO_DO_GH_MS, opcoes.rodar ?? executor_1.rodarCli, new Map(), opcoes.sondas);
345
+ return lido.leitura ? { ok: true, forja: lido.forja } : { ok: false, erro: lido.motivo };
295
346
  }
296
347
  /**
297
- * Le os PRs da base do repositorio do remoto em duas chamadas: os abertos (ate `LIMITE_DE_PRS`; e so a
298
- * lista deles que pode dizer "sem PR") e os recentes de qualquer estado (para achar o mesclado e o fechado).
299
- * O `gh` usa a autenticacao dele; nenhum token passa por aqui. RM-037 (fatia 5, A5): no GitHub Enterprise, o host
300
- * vai no `--repo`; forja sem leitura de PR nao chama o `gh pr list`.
348
+ * Le os pedidos da base do projeto pela capacidade `pedidosAbertos` da forja resolvida: os abertos (so a lista deles
349
+ * pode dizer "sem PR"), os recentes de qualquer estado e as candidatas que nao apareceram. A CLI usa a autenticacao
350
+ * dela; nenhum token passa por aqui. Forja sem leitura de pedidos nao chama CLI nenhuma alem da sondagem.
301
351
  */
302
352
  function lerPrsDaForja(carregado, opcoes = {}) {
303
353
  const lidoEm = opcoes.quando ?? new Date().toISOString();
@@ -305,79 +355,52 @@ function lerPrsDaForja(carregado, opcoes = {}) {
305
355
  const base = carregado.manifesto.worktree.base_branch;
306
356
  const orcamento = opcoes.orcamentoMs ?? ORCAMENTO_DA_LEITURA_MS, fimDaLeitura = Date.now() + orcamento;
307
357
  const resta = () => fimDaLeitura - Date.now();
308
- const executor = opcoes.executor ?? exports.ghPadrao;
309
- const forja = opcoes.forja ? { leitura: true, ...opcoes.forja }
310
- : forjaDosPrs(carregado.raiz, remoto, executor, Math.min(PRAZO_DO_GH_MS, Math.max(1, resta())));
311
- if (!forja.leitura)
312
- return { ok: false, lidoEm, erro: forja.motivo, ...(forja.semLeitura ? { semLeitura: { remoto, host: forja.host } } : {}) };
313
- const { host, repositorio } = forja;
314
- const pedir = (args) => {
315
- if (resta() <= 0)
316
- return `gh pr list: orçamento de ${Math.round(orcamento / 1000)} s da leitura esgotado`;
317
- const r = executor(['pr', 'list', `--repo=${host}/${repositorio}`, `--base=${base}`, ...args], Math.min(PRAZO_DO_GH_MS, resta()));
318
- if (r.status !== 0) {
319
- const detalhe = curto((0, hitl_1.redigirSegredos)(r.stderr || r.stdout || ''), 160) ?? 'sem detalhe';
320
- return `gh pr list falhou (${r.status === null ? 'sem código de saída' : `código ${r.status}`}): ${detalhe}`;
321
- }
322
- try {
323
- const lista = JSON.parse(r.stdout);
324
- if (!Array.isArray(lista))
325
- throw new Error('a resposta não é uma lista');
326
- return lista;
327
- }
328
- catch (e) {
329
- return `resposta do gh pr list fora do formato: ${curto((0, hitl_1.redigirSegredos)(e.message), 120) ?? 'sem detalhe'}`;
330
- }
331
- };
332
- try {
333
- const porNumero = new Map();
334
- const juntar = (lista, comChecks) => {
335
- for (const bruto of lista) {
336
- const pr = prDaForja(bruto, base);
337
- if (!pr || porNumero.has(pr.numero))
338
- continue;
339
- // S-b do CHECK (rodada 3): a leitura sem rollup nunca diz que o aberto nao tem checks.
340
- if (!comChecks && pr.estado === 'aberto')
341
- pr.checks = [{ nome: 'checks não lidos', situacao: 'pendente', concluidoEm: null }];
342
- porNumero.set(pr.numero, pr);
343
- }
344
- };
345
- const abertos = pedir(['--state=open', `--limit=${exports.LIMITE_DE_PRS}`, `--json=${CAMPOS_DO_GH}`]);
346
- if (typeof abertos === 'string')
347
- return { ok: false, lidoEm, erro: abertos };
348
- juntar(abertos, true);
349
- const recentes = pedir(['--state=all', `--limit=${exports.LIMITE_DE_RECENTES}`, `--json=${CAMPOS_DOS_RECENTES}`]);
350
- if (typeof recentes === 'string')
351
- return { ok: false, lidoEm, erro: recentes };
352
- juntar(recentes, false);
353
- // R1 do CHECK (rodada 3): antes de dizer "sem PR", a branch candidata e conferida sozinha (o mesclado velho
354
- // fica fora dos recentes). Acima do teto da batida, a branch fica sem conferir, e isso e "PR nao lido".
355
- const achadas = new Set([...porNumero.values()].map((p) => p.branch));
356
- const faltam = [...new Set(opcoes.candidatas ?? [])].filter((b) => BRANCH.test(b) && !achadas.has(b));
357
- const semConferir = [];
358
- for (const [i, branch] of faltam.entries()) {
359
- // Acima do teto da batida, sem tempo para a conferencia inteira ou com ela falhando, a candidata fica sem conferir
360
- // ("PR nao lido") e o que ja foi lido vale (sugestao da seguranca na rodada 4 do CHECK).
361
- if (i >= LIMITE_DE_CANDIDATAS || resta() < MINIMO_DA_CONFERENCIA_MS) {
362
- semConferir.push(branch);
363
- continue;
364
- }
365
- const daBranch = pedir(['--state=all', `--head=${branch}`, '--limit=5', `--json=${CAMPOS_DOS_RECENTES}`]);
366
- try {
367
- if (typeof daBranch === 'string')
368
- throw new Error(daBranch);
369
- juntar(daBranch, false);
370
- }
371
- catch {
372
- semConferir.push(branch);
373
- }
358
+ const executor = opcoes.executor ?? exports.ghPadrao, rodar = opcoes.rodar ?? executor_1.rodarCli, logins = new Map();
359
+ const lido = opcoes.resolvida ? { leitura: true, forja: opcoes.resolvida, hostDoRemoto: null }
360
+ : opcoes.forja ? { leitura: true, forja: githubResolvido(opcoes.forja), hostDoRemoto: null }
361
+ : forjaDosPrs(carregado, remoto, executor, Math.min(PRAZO_DO_GH_MS, Math.max(1, resta())), rodar, logins, opcoes.sondas);
362
+ if (!lido.leitura)
363
+ return { ok: false, lidoEm, erro: lido.motivo, ...(lido.semLeitura ? { semLeitura: { remoto, host: lido.host } } : {}) };
364
+ const forja = lido.forja;
365
+ const lidos = (0, registro_1.exigirCapacidade)((0, registro_1.adaptadorDaForja)(forja.tipo), 'pedidosAbertos')({ forja, base, candidatas: opcoes.candidatas ?? [],
366
+ contexto: carregado.manifesto.ci.context || 'ork-verify',
367
+ api: (0, api_1.chamadorDaApi)(forja, { rodar, logins }), executor, resta, orcamentoMs: orcamento, limites: exports.LIMITES_DOS_PEDIDOS });
368
+ if (!lidos.ok) {
369
+ const erro = lidos.erro, cli = cli_1.CLI_DA_FORJA[forja.tipo].cmd;
370
+ // O GitHub guarda a frase de sempre do `gh pr list` (o pulse e os snapshots a fixam); as outras dizem o motivo tipado.
371
+ if (forja.tipo === 'github')
372
+ return { ok: false, lidoEm, erro: erro.detalhe };
373
+ // A CLI sem login no host e o estado da forja, dito uma vez, como o `gh` sem login no host proprio.
374
+ if (erro.codigo === 'forja.sem-login') {
375
+ return { ok: false, lidoEm, erro: (0, locale_1.textoDoCatalogo)((m) => m.pulse.forjaSemLogin(cli, forja.host, remoto)),
376
+ semLeitura: { remoto, host: lido.hostDoRemoto ?? forja.host } };
374
377
  }
375
- return { ok: true, retrato: { contrato: exports.CONTRATO_PRS, lidoEm, repositorio, ...(host !== 'github.com' ? { host } : {}), base,
376
- parcial: abertos.length >= exports.LIMITE_DE_PRS, ...(semConferir.length ? { semConferir } : {}), prs: [...porNumero.values()] } };
377
- }
378
- catch (e) {
379
- return { ok: false, lidoEm, erro: `resposta do gh pr list fora do formato: ${curto((0, hitl_1.redigirSegredos)(e.message), 120) ?? 'sem detalhe'}` };
378
+ return { ok: false, lidoEm, erro: (0, locale_1.textoDoCatalogo)((m) => m.forja.motivo(erro, forja.tipo)) };
380
379
  }
380
+ return { ok: true, retrato: { contrato: exports.CONTRATO_PRS, lidoEm, repositorio: forja.repo, ...(forja.host !== 'github.com' ? { host: forja.host } : {}),
381
+ base, parcial: lidos.valor.parcial, ...(lidos.valor.semConferir.length ? { semConferir: lidos.valor.semConferir } : {}), prs: lidos.valor.prs } };
382
+ }
383
+ /**
384
+ * O host e o caminho do projeto no remoto, sem rede nem CLI: o que o retrato tem de bater. A resolucao roda sem
385
+ * sondas; sem tipo declarado e fora dos hosts conhecidos, valem o host (o declarado, senao o do remoto) e o caminho do
386
+ * remoto sem o caminho base.
387
+ */
388
+ function forjaDoRemotoSemRede(carregado, remoto) {
389
+ if (!(0, branch_de_estado_1.remotoValido)(remoto))
390
+ return null;
391
+ const url = git(carregado.raiz, ['remote', 'get-url', '--', remoto]);
392
+ const endereco = url.ok ? (0, endereco_1.lerEnderecoDoRemoto)(url.stdout.trim()) : null;
393
+ if (!endereco)
394
+ return null;
395
+ const m = carregado.manifesto.forja;
396
+ const r = (0, resolver_1.resolverForja)({ endereco, manifesto: m, sondas: {} });
397
+ if (r.ok)
398
+ return { host: r.valor.host, repositorio: r.valor.repo };
399
+ if (r.erro.codigo !== 'forja.desconhecida')
400
+ return null;
401
+ const prefixo = m?.caminho_base ? `${m.caminho_base.slice(1)}/` : '';
402
+ return { host: m?.host ?? endereco.host,
403
+ repositorio: prefixo && endereco.caminho.startsWith(prefixo) ? endereco.caminho.slice(prefixo.length) : endereco.caminho };
381
404
  }
382
405
  const dirDoMonitor = (raiz) => path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery', 'monitor');
383
406
  /** Grava o retrato de uma leitura que deu certo: arquivo novo exclusivo, so do dono, renomeado por cima. */
@@ -460,7 +483,7 @@ function lerRetratoDePrs(raiz) {
460
483
  try {
461
484
  const r = JSON.parse(fs.readFileSync(path.join(dirDoMonitor(raiz), ARQUIVO_DOS_PRS), 'utf8'));
462
485
  const lidoEm = instante(r.lidoEm);
463
- if (r.contrato !== exports.CONTRATO_PRS || !lidoEm || typeof r.repositorio !== 'string' || !REPOSITORIO.test(r.repositorio) ||
486
+ if (r.contrato !== exports.CONTRATO_PRS || !lidoEm || typeof r.repositorio !== 'string' || !caminhoDoProjeto(r.repositorio) ||
464
487
  typeof r.base !== 'string' || typeof r.parcial !== 'boolean' || !Array.isArray(r.prs) ||
465
488
  (r.host !== undefined && !(typeof r.host === 'string' && HOST.test(r.host))) ||
466
489
  (r.semConferir !== undefined && !(Array.isArray(r.semConferir) && r.semConferir.every((b) => typeof b === 'string' && BRANCH.test(b)))))
@@ -761,20 +784,19 @@ function refsLocais(raiz, remoto) {
761
784
  }
762
785
  return mapa;
763
786
  }
764
- /** Os merges `ship(<thread>)` da base numa leitura so, do mais novo para o mais velho (fica o mais novo). */
765
- function mergesNaBase(raiz, baseRef) {
787
+ /** Os merges das entregas da base numa leitura so, do mais novo para o mais velho (fica o mais novo). */
788
+ function mergesNaBase(raiz, baseRef, base, threads) {
766
789
  const mapa = new Map();
767
790
  if (!baseRef)
768
791
  return mapa;
769
- // Regex basica do git: o `(` e literal. A ref vem qualificada do `for-each-ref`.
770
- const r = git(raiz, ['log', baseRef, '--first-parent', '--format=%H%x09%cI%x09%s', '--grep=^ship(']);
771
- if (!r.ok)
772
- return mapa;
773
- for (const linha of r.stdout.split('\n')) {
774
- const [sha, em, assunto] = linha.split('\t');
775
- const m = /^ship\(([A-Za-z0-9._-]+)\)/.exec(assunto ?? '');
776
- if (m && sha && SHA.test(sha) && !mapa.has(m[1]))
777
- mapa.set(m[1], { sha, em: instante(em) });
792
+ const reconhecidos = (0, merge_da_entrega_1.mergesDasEntregasNaBase)(raiz, baseRef, base, threads.map((t) => ({
793
+ thread: t.id,
794
+ branch: (0, merge_da_entrega_1.branchRegistradaDaEntrega)(raiz, t.id) ?? (0, worktree_1.branchDaWorktree)(t),
795
+ })));
796
+ for (const t of threads) {
797
+ const merge = reconhecidos.get(t.id)?.[0];
798
+ if (merge)
799
+ mapa.set(t.id, { sha: merge.mergeSha, em: merge.em });
778
800
  }
779
801
  return mapa;
780
802
  }
@@ -835,7 +857,6 @@ function entregasDoProjeto(carregado, opcoes) {
835
857
  const refs = refsLocais(raiz, remoto);
836
858
  // A copia do remoto vem primeiro: a base local desta maquina pode estar parada (o merge e pelo GitHub).
837
859
  const baseRef = [`refs/remotes/${remoto}/${baseBranch}`, `refs/heads/${baseBranch}`].find((r) => refs.has(r)) ?? null;
838
- const merges = mergesNaBase(raiz, baseRef);
839
860
  const sessoes = opcoes.sessoes ?? [];
840
861
  const threads = [];
841
862
  for (const id of (0, thread_1.listarIds)(raiz)) {
@@ -844,6 +865,7 @@ function entregasDoProjeto(carregado, opcoes) {
844
865
  }
845
866
  catch { /* thread ilegivel fica de fora */ }
846
867
  }
868
+ const merges = mergesNaBase(raiz, baseRef, baseBranch, threads);
847
869
  const fatos = threads.filter((t) => t.status !== 'fechada').map((t) => {
848
870
  let eventos = [];
849
871
  try {
@@ -880,7 +902,7 @@ function entregasDoProjeto(carregado, opcoes) {
880
902
  const semLeituraDaForja = !!prs && !prs.ok && !!prs.semLeitura;
881
903
  let retrato = null, semRetrato = prs && !prs.ok ? (semLeituraDaForja ? exports.FORJA_SEM_LEITURA : prs.erro) : 'sem leitura dos PRs';
882
904
  if (prs?.ok) {
883
- const r = prs.retrato, atual = githubDoRemoto(raiz, remoto);
905
+ const r = prs.retrato, atual = forjaDoRemotoSemRede(carregado, remoto);
884
906
  // O retrato vale do mesmo host: o do GitHub Enterprise (`host`) ou, sem ele, o github.com.
885
907
  if (r.base !== baseBranch || !atual || r.repositorio !== atual.repositorio || (r.host ?? 'github.com') !== atual.host) {
886
908
  semRetrato = 'retrato de PRs de outro repositório ou base';
@@ -985,11 +1007,10 @@ function entregasDoProjeto(carregado, opcoes) {
985
1007
  desde = f.merge.em ?? fimEm;
986
1008
  peloGit = true;
987
1009
  passo = `registrar a entrega do merge ${f.merge.sha.slice(0, 7)} (ork ship registrar-pr ${t.id})`;
988
- evidencia.push(`git log: merge ship(${t.id}) ${f.merge.sha.slice(0, 7)} na base, sem ship_done no ledger`);
1010
+ evidencia.push(`git log: merge da entrega de ${t.id} ${f.merge.sha.slice(0, 7)} na base, sem ship_done no ledger`);
989
1011
  }
990
1012
  else if (!aberto && daBranch.mesclado && !f.entregueNaPonta && (daBranch.mesclado.mescladoEm ?? fimEm)) {
991
- // N4 do CHECK (rodada 2): PR mesclado sem o assunto ship(<thread>); o `registrar-pr` nao o acha sozinho. Com o
992
- // merge ship(<thread>) ainda sem registro na base (squash), o `registrar-pr` acha.
1013
+ // N4 do CHECK (rodada 2): PR mesclado sem assunto ou branch reconhecivel; o `registrar-pr` nao o acha sozinho.
993
1014
  caso = 'sem-registro';
994
1015
  desde = daBranch.mesclado.mescladoEm ?? fimEm;
995
1016
  passo = f.merge && !f.mergeRegistrado ? `registrar a entrega do merge ${f.merge.sha.slice(0, 7)} (ork ship registrar-pr ${t.id})`