@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.
Files changed (502) 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 +195 -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/autoridade.json +56 -0
  16. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  17. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  18. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  19. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  20. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  21. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  22. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  23. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  24. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  25. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  26. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  27. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  28. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  29. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  30. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  31. package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
  32. package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
  33. package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
  34. package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
  35. package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
  36. package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
  37. package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
  38. package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
  39. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  40. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  41. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  42. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  43. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  44. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  45. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  46. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  47. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  48. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  49. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  50. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +121 -0
  51. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  52. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  53. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  54. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  55. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  56. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  57. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  58. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  59. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  60. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  61. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  62. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  63. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  64. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  65. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  66. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  67. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  68. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  69. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  70. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  71. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  72. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  73. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  74. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  75. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  76. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  77. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  78. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  79. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  80. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  81. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  82. package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
  83. package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
  84. package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
  85. package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
  86. package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
  87. package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
  88. package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
  89. package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
  90. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  91. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  92. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  93. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  94. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  95. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  96. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  97. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  98. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  99. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  100. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  101. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  102. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  103. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  104. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  105. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  106. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  107. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  108. package/adapters/codex/skills/ork/SKILL.md +2 -0
  109. package/adapters/hermes/README.md +64 -1
  110. package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
  111. package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
  112. package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
  113. package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
  114. package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
  115. package/adapters/hermes/hermes.plugin.json +4 -0
  116. package/adapters/hermes/hitl-ingress/__init__.py +101 -8
  117. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +3 -3
  118. package/adapters/openclaw/README.md +83 -10
  119. package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
  120. package/adapters/openclaw/dist/hitl-ingress.js +106 -9
  121. package/adapters/openclaw/dist/index.js +86 -0
  122. package/adapters/openclaw/openclaw.plugin.json +34 -4
  123. package/adapters/openclaw/package.json +2 -2
  124. package/adapters/openclaw/src/hitl-ingress.ts +103 -9
  125. package/adapters/openclaw/src/index.ts +94 -0
  126. package/assets/adapters-en/claude-code/README.md +403 -0
  127. package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
  128. package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
  129. package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
  130. package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
  131. package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
  132. package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
  133. package/assets/adapters-en/claude-code/commands/check.md +46 -0
  134. package/assets/adapters-en/claude-code/commands/go.md +46 -0
  135. package/assets/adapters-en/claude-code/commands/goal.md +55 -0
  136. package/assets/adapters-en/claude-code/commands/master.md +54 -0
  137. package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
  138. package/assets/adapters-en/claude-code/commands/ork.md +126 -0
  139. package/assets/adapters-en/claude-code/commands/plan.md +47 -0
  140. package/assets/adapters-en/claude-code/commands/ship.md +45 -0
  141. package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
  142. package/assets/adapters-en/hermes/README.md +273 -0
  143. package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
  144. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  145. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  146. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  147. package/assets/docs-en/produto/README.md +14 -0
  148. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  149. package/assets/docs-en/roadmap/README.md +14 -0
  150. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  151. package/assets/references-en/README.md +25 -0
  152. package/assets/references-en/code-review-axes.md +82 -0
  153. package/assets/references-en/definition-of-done.md +74 -0
  154. package/assets/references-en/performance-checklist.md +53 -0
  155. package/assets/references-en/security-checklist.md +101 -0
  156. package/assets/references-en/testing-patterns.md +51 -0
  157. package/assets/security-scan/defaults/.golangci.yml +2 -0
  158. package/assets/security-scan/defaults/eslint.config.mjs +11 -0
  159. package/assets/security-scan/defaults/gitleaks.toml +3 -0
  160. package/assets/security-scan/defaults/ruff.toml +1 -0
  161. package/assets/security-scan/tools-agil.json +87 -0
  162. package/assets/security-scan/tools.json +625 -0
  163. package/assets/skills-en/core/onboarding/SKILL.md +58 -0
  164. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
  165. package/assets/skills-en/core/thread-state/SKILL.md +88 -0
  166. package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
  167. package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
  168. package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
  169. package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
  170. package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
  171. package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
  172. package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
  173. package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
  174. package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
  175. package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
  176. package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
  177. package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
  178. package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
  179. package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
  180. package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
  181. package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
  182. package/dist/adapters/claude-bg.js +193 -15
  183. package/dist/adapters/codex-controller-worker.js +12 -5
  184. package/dist/adapters/codex-events.js +16 -4
  185. package/dist/adapters/codex.js +13 -2
  186. package/dist/agents-md.js +24 -15
  187. package/dist/atualizar-branch.js +245 -0
  188. package/dist/auditoria.js +13 -11
  189. package/dist/auditrun.js +68 -48
  190. package/dist/autorizacao-duravel.js +327 -0
  191. package/dist/board.js +98 -43
  192. package/dist/branch-de-estado.js +39 -9
  193. package/dist/busca-semantica.js +7 -5
  194. package/dist/catalogo.js +35 -1
  195. package/dist/changelog-reconciliacao.js +290 -0
  196. package/dist/check-agil.js +500 -0
  197. package/dist/check-modo.js +41 -0
  198. package/dist/check-paralelo.js +183 -0
  199. package/dist/ci.js +255 -46
  200. package/dist/ciclos.js +8 -6
  201. package/dist/claim-lint.js +12 -8
  202. package/dist/claims-conferir.js +350 -0
  203. package/dist/claims.js +13 -10
  204. package/dist/company-brain-client.js +45 -3
  205. package/dist/company-brain-journal.js +2 -1
  206. package/dist/company-brain-migration.js +47 -6
  207. package/dist/conducao-batida.js +759 -0
  208. package/dist/conducao-sentinela.js +405 -0
  209. package/dist/conducao-texto.js +12 -18
  210. package/dist/conducao.js +206 -59
  211. package/dist/conhecimento-consulta.js +270 -0
  212. package/dist/conhecimento.js +514 -0
  213. package/dist/conta-esgotada.js +127 -0
  214. package/dist/dado-privado.js +816 -0
  215. package/dist/decisao-autonoma.js +5 -4
  216. package/dist/demo.js +14 -12
  217. package/dist/dependencias-da-worktree.js +25 -0
  218. package/dist/divida.js +38 -36
  219. package/dist/docs.js +103 -82
  220. package/dist/doctor-forja.js +345 -0
  221. package/dist/doctor-pulse-cron.js +294 -27
  222. package/dist/doctor-rede.js +18 -17
  223. package/dist/doctor.js +278 -116
  224. package/dist/dsn-da-memoria.js +417 -0
  225. package/dist/entrega-por-mod.js +503 -0
  226. package/dist/entrega-pr.js +158 -57
  227. package/dist/escopo-escrita.js +10 -1
  228. package/dist/esgotamentos.js +13 -11
  229. package/dist/estado-thread.js +42 -17
  230. package/dist/evalrunner.js +35 -32
  231. package/dist/experiencia-instalacao.js +45 -25
  232. package/dist/fabrica-batida.js +323 -0
  233. package/dist/fabrica-estado.js +49 -16
  234. package/dist/fabrica-publicar.js +3 -1
  235. package/dist/fila-pesada.js +444 -0
  236. package/dist/fix.js +24 -21
  237. package/dist/forja/adaptador.js +6 -0
  238. package/dist/forja/ambiente-de-ci.js +27 -0
  239. package/dist/forja/api.js +256 -0
  240. package/dist/forja/cache.js +89 -0
  241. package/dist/forja/cli.js +60 -0
  242. package/dist/forja/contrato.js +9 -0
  243. package/dist/forja/endereco.js +43 -0
  244. package/dist/forja/estado.js +22 -0
  245. package/dist/forja/executor.js +73 -0
  246. package/dist/forja/github/ci.js +95 -0
  247. package/dist/forja/github/dono-da-rede.js +18 -0
  248. package/dist/forja/github/metadados.js +15 -0
  249. package/dist/forja/github/pedidos.js +200 -0
  250. package/dist/forja/gitlab/ci.js +141 -0
  251. package/dist/forja/gitlab/consultas.js +59 -0
  252. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  253. package/dist/forja/gitlab/metadados.js +15 -0
  254. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  255. package/dist/forja/gitlab/pedidos.js +141 -0
  256. package/dist/forja/produtor.js +32 -0
  257. package/dist/forja/registro.js +31 -0
  258. package/dist/forja/resolver.js +121 -0
  259. package/dist/forja/texto.js +13 -0
  260. package/dist/forja/versao.js +71 -0
  261. package/dist/forja.js +124 -81
  262. package/dist/gates.js +3 -28
  263. package/dist/handoff.js +33 -19
  264. package/dist/hitl-contract.js +46 -43
  265. package/dist/hitl-curto.js +37 -25
  266. package/dist/hitl-gates.js +13 -11
  267. package/dist/hitl-local-receipt.js +53 -0
  268. package/dist/hitl-local.js +11 -2
  269. package/dist/hitl-lock.js +5 -11
  270. package/dist/hitl-public-receipt.js +11 -0
  271. package/dist/hitl-resumo.js +72 -3
  272. package/dist/hitl-sessions.js +62 -9
  273. package/dist/hitl-tempo-parado.js +4 -4
  274. package/dist/hitl-texto-livre.js +7 -4
  275. package/dist/hitl.js +63 -64
  276. package/dist/horario.js +30 -7
  277. package/dist/hosts.js +155 -134
  278. package/dist/impedimento.js +108 -14
  279. package/dist/index.js +1421 -1019
  280. package/dist/indice-vetorial.js +14 -12
  281. package/dist/indice.js +7 -1
  282. package/dist/init.js +54 -49
  283. package/dist/instabilidade.js +144 -0
  284. package/dist/integracoes-locais.js +4 -0
  285. package/dist/intelligence-graph-cli.js +213 -88
  286. package/dist/intelligence-graph-contexto.js +56 -17
  287. package/dist/intelligence-graph-contract.js +2 -1
  288. package/dist/intelligence-graph-extract-md.js +56 -4
  289. package/dist/intelligence-graph-extract-ts.js +71 -3
  290. package/dist/intelligence-graph-query.js +96 -34
  291. package/dist/leases.js +19 -18
  292. package/dist/ledger-stats.js +17 -16
  293. package/dist/ledger.js +46 -2
  294. package/dist/licoes.js +12 -11
  295. package/dist/liveness.js +6 -3
  296. package/dist/locale-accounts.js +220 -0
  297. package/dist/locale-adapter.js +291 -0
  298. package/dist/locale-ajuda.js +833 -0
  299. package/dist/locale-audit.js +199 -0
  300. package/dist/locale-claims.js +213 -0
  301. package/dist/locale-conducao.js +138 -0
  302. package/dist/locale-conhecimento.js +181 -0
  303. package/dist/locale-decisao.js +205 -0
  304. package/dist/locale-docs.js +230 -0
  305. package/dist/locale-estado.js +101 -0
  306. package/dist/locale-forja.js +290 -0
  307. package/dist/locale-gerados.js +165 -0
  308. package/dist/locale-grafo.js +129 -0
  309. package/dist/locale-master.js +182 -0
  310. package/dist/locale-network.js +524 -0
  311. package/dist/locale-onboarding.js +92 -0
  312. package/dist/locale-operacao-restante.js +931 -0
  313. package/dist/locale-phase.js +151 -0
  314. package/dist/locale-projetos.js +100 -0
  315. package/dist/locale-prompts.js +194 -0
  316. package/dist/locale-pulse.js +349 -0
  317. package/dist/locale-reservas.js +87 -0
  318. package/dist/locale-retry.js +524 -0
  319. package/dist/locale-roadmap.js +102 -0
  320. package/dist/locale-security-scan.js +69 -0
  321. package/dist/locale-setup.js +192 -0
  322. package/dist/locale-ship.js +597 -0
  323. package/dist/locale-thread.js +421 -0
  324. package/dist/locale-verify.js +201 -0
  325. package/dist/locale-worktree.js +246 -0
  326. package/dist/locale.js +1258 -0
  327. package/dist/maestro-runtime.js +22 -3
  328. package/dist/manifest.js +415 -13
  329. package/dist/maquina-ociosa.js +211 -0
  330. package/dist/maquina.js +31 -7
  331. package/dist/master-digest.js +6 -1
  332. package/dist/master-nota-local.js +200 -0
  333. package/dist/master-nota.js +14 -8
  334. package/dist/master.js +139 -65
  335. package/dist/mcp-artifacts.js +11 -2
  336. package/dist/mcp-conhecimento.js +52 -0
  337. package/dist/mcp-experiencia.js +26 -5
  338. package/dist/mcp-git.js +23 -6
  339. package/dist/mcp-grafo.js +7 -4
  340. package/dist/mcp-install.js +73 -8
  341. package/dist/mcp-noctum.js +101 -0
  342. package/dist/mcp-server.js +90 -16
  343. package/dist/mcp-ship-transporte.js +977 -0
  344. package/dist/mcp-ship.js +71 -25
  345. package/dist/mcp-transportes.js +17 -0
  346. package/dist/mcp-verify.js +6 -1
  347. package/dist/memoria.js +63 -58
  348. package/dist/modos-migracao.js +8 -6
  349. package/dist/modos.js +20 -24
  350. package/dist/network-roadmap.js +90 -51
  351. package/dist/noctum-aceite.js +789 -0
  352. package/dist/noctum-arco.js +1418 -0
  353. package/dist/noctum-capacidade.js +141 -0
  354. package/dist/noctum-changelog.js +399 -0
  355. package/dist/noctum-cli.js +482 -0
  356. package/dist/noctum-coordenacao.js +1225 -0
  357. package/dist/noctum-entrega.js +1169 -0
  358. package/dist/noctum-envelope.js +1046 -0
  359. package/dist/noctum-execucao.js +376 -0
  360. package/dist/noctum-fechamento.js +405 -0
  361. package/dist/noctum-fila.js +314 -0
  362. package/dist/noctum-guarda.js +256 -0
  363. package/dist/noctum-integracao.js +507 -0
  364. package/dist/noctum-maquinas.js +383 -0
  365. package/dist/noctum-medicao.js +450 -0
  366. package/dist/noctum-modo.js +362 -0
  367. package/dist/noctum-pergunta-canal.js +96 -0
  368. package/dist/noctum-pergunta.js +115 -0
  369. package/dist/noctum-provas.js +838 -0
  370. package/dist/noctum-reconciliacao.js +591 -0
  371. package/dist/noctum-registro.js +215 -0
  372. package/dist/noctum-relatorio.js +827 -0
  373. package/dist/noctum-resposta.js +207 -0
  374. package/dist/noctum-sessoes-em-voo.js +93 -0
  375. package/dist/noctum-supervisao.js +649 -0
  376. package/dist/noctum-terminal.js +459 -0
  377. package/dist/noctum-transporte.js +655 -0
  378. package/dist/noctum-vigia.js +639 -0
  379. package/dist/ocupacao.js +32 -3
  380. package/dist/onboarding.js +56 -26
  381. package/dist/orkmind.js +48 -25
  382. package/dist/orquestracao.js +44 -47
  383. package/dist/parado-no-condutor.js +174 -127
  384. package/dist/phase.js +144 -63
  385. package/dist/policies.js +37 -4
  386. package/dist/portfolio.js +4 -2
  387. package/dist/postura-local.js +235 -0
  388. package/dist/preflight.js +11 -10
  389. package/dist/procedencia.js +220 -0
  390. package/dist/projeto-alvo.js +186 -24
  391. package/dist/prompts.js +140 -42
  392. package/dist/prova-minima.js +5 -6
  393. package/dist/pulse-cadencia.js +5 -4
  394. package/dist/pulse-consentimento.js +53 -1
  395. package/dist/pulse-delivery.js +151 -24
  396. package/dist/pulse-resposta.js +368 -4
  397. package/dist/pulse.js +188 -22
  398. package/dist/ratelimit.js +16 -6
  399. package/dist/recall.js +14 -13
  400. package/dist/redacao-saida.js +63 -0
  401. package/dist/rede-adesao.js +13 -8
  402. package/dist/rede-forja.js +108 -24
  403. package/dist/rede-status.js +66 -47
  404. package/dist/rede.js +86 -46
  405. package/dist/retomada-checkpoint.js +101 -0
  406. package/dist/retry.js +451 -212
  407. package/dist/roadmap-reservas.js +45 -28
  408. package/dist/roadmap-status.js +129 -33
  409. package/dist/runtime-ambiente.js +5 -0
  410. package/dist/runtime-context.js +284 -32
  411. package/dist/runtime-escada.js +423 -0
  412. package/dist/runtime-profiles.js +103 -46
  413. package/dist/runtimes.js +2 -1
  414. package/dist/saida-segura.js +3 -2
  415. package/dist/security-scan/agil.js +355 -0
  416. package/dist/security-scan/cli.js +76 -0
  417. package/dist/security-scan/compare.js +149 -0
  418. package/dist/security-scan/config.js +93 -0
  419. package/dist/security-scan/detect.js +97 -0
  420. package/dist/security-scan/executor.js +188 -0
  421. package/dist/security-scan/guard.js +180 -0
  422. package/dist/security-scan/imagem-de-lint.js +96 -0
  423. package/dist/security-scan/normalize/actionlint.js +12 -0
  424. package/dist/security-scan/normalize/eslint.js +12 -0
  425. package/dist/security-scan/normalize/gitleaks.js +13 -0
  426. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  427. package/dist/security-scan/normalize/govulncheck.js +36 -0
  428. package/dist/security-scan/normalize/index.js +25 -0
  429. package/dist/security-scan/normalize/npm-audit.js +30 -0
  430. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  431. package/dist/security-scan/normalize/oxlint.js +51 -0
  432. package/dist/security-scan/normalize/pip-audit.js +16 -0
  433. package/dist/security-scan/normalize/ruff.js +12 -0
  434. package/dist/security-scan/normalize/semgrep.js +20 -0
  435. package/dist/security-scan/normalize/trivy.js +33 -0
  436. package/dist/security-scan/normalize/util.js +204 -0
  437. package/dist/security-scan/normalize/zizmor.js +19 -0
  438. package/dist/security-scan/report.js +156 -0
  439. package/dist/security-scan/run.js +448 -0
  440. package/dist/security-scan/tools.js +62 -0
  441. package/dist/security-scan/trabalhador.js +74 -0
  442. package/dist/security-scan/types.js +15 -0
  443. package/dist/session-events.js +26 -5
  444. package/dist/session-watcher-claude.js +81 -20
  445. package/dist/session-watcher.js +340 -42
  446. package/dist/sessoes-contas.js +10 -1
  447. package/dist/sessoes-inventario.js +1 -1
  448. package/dist/sessoes.js +25 -23
  449. package/dist/setup.js +59 -58
  450. package/dist/ship-publicar.js +971 -0
  451. package/dist/ship.js +243 -97
  452. package/dist/steal.js +77 -0
  453. package/dist/superficie.js +14 -11
  454. package/dist/thread-close.js +12 -11
  455. package/dist/thread.js +274 -100
  456. package/dist/tokens.js +15 -11
  457. package/dist/trabalho-thread.js +297 -0
  458. package/dist/transporte-do-canal.js +189 -0
  459. package/dist/types.js +12 -1
  460. package/dist/util.js +13 -3
  461. package/dist/varredura-acoes.js +507 -0
  462. package/dist/verify.js +608 -76
  463. package/dist/vida-da-thread.js +254 -0
  464. package/dist/worktree-local.js +167 -0
  465. package/dist/worktree.js +99 -83
  466. package/dist/yaml.js +27 -8
  467. package/eval/casos/check-quality.json +77 -0
  468. package/eval/casos/security-auditor.json +148 -0
  469. package/eval/casos/security-remediation.json +161 -0
  470. package/eval/fixtures/security-scan/README.md +8 -0
  471. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  472. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  473. package/eval/fixtures/security-scan/go/README.md +4 -0
  474. package/eval/fixtures/security-scan/go/config.go +4 -0
  475. package/eval/fixtures/security-scan/go/go.mod +5 -0
  476. package/eval/fixtures/security-scan/go/go.sum +2 -0
  477. package/eval/fixtures/security-scan/go/main.go +31 -0
  478. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  479. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  480. package/eval/fixtures/security-scan/js/README.md +4 -0
  481. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  482. package/eval/fixtures/security-scan/js/package.json +10 -0
  483. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  484. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  485. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  486. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  487. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  488. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  489. package/eval/fixtures/security-scan/python/README.md +4 -0
  490. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  491. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  492. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  493. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  494. package/package.json +9 -4
  495. package/references/security-checklist.md +3 -3
  496. package/schemas/code-artifact-graph.v1.schema.json +2 -1
  497. package/skills/README.md +1 -0
  498. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  499. package/skills/phases/check-quality/SKILL.md +16 -0
  500. package/skills/phases/go-implementation/SKILL.md +6 -0
  501. package/skills/phases/security-remediation/SKILL.md +70 -0
  502. package/skills/reviewers/security-auditor/SKILL.md +25 -0
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.donoDaRedeGithub = donoDaRedeGithub;
4
+ function donoDaRedeGithub(e) {
5
+ if (!e.dono.trim())
6
+ return { ok: false, erro: { codigo: 'forja.nao-achei', detalhe: 'dono vazio' } };
7
+ const eu = e.api({ metodo: 'GET', caminho: 'user' });
8
+ if (!eu.ok)
9
+ return eu;
10
+ const c = eu.valor.corpo;
11
+ const p = c && typeof c === 'object' && !Array.isArray(c) ? c : null;
12
+ if (!p || typeof p.login !== 'string' || !Number.isSafeInteger(p.id) || p.id <= 0) {
13
+ return { ok: false, erro: { codigo: 'forja.resposta-invalida', detalhe: 'user' } };
14
+ }
15
+ if (p.login !== e.dono)
16
+ return { ok: false, erro: { codigo: 'forja.nao-achei', detalhe: `${e.dono}: nao e o login ${p.login}` } };
17
+ return { ok: true, valor: { tipo: 'usuario', caminho: p.login, namespaceId: p.id, nivel: null } };
18
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.metadadosGithub = metadadosGithub;
4
+ const zod_1 = require("zod");
5
+ const META = zod_1.z.object({ verifiable_password_authentication: zod_1.z.boolean(), installed_version: zod_1.z.string().optional() });
6
+ /** `GET /meta`: o GitHub Enterprise Server diz a versao (`installed_version`); o github.com, nenhuma. */
7
+ function metadadosGithub(e) {
8
+ const r = e.api({ metodo: 'GET', caminho: 'meta' });
9
+ if (!r.ok)
10
+ return r;
11
+ const lido = META.safeParse(r.valor.corpo);
12
+ if (!lido.success)
13
+ return { ok: false, erro: { codigo: 'forja.resposta-invalida', detalhe: 'meta: verifiable_password_authentication' } };
14
+ return { ok: true, valor: { versao: lido.data.installed_version ?? null, edicao: null } };
15
+ }
@@ -0,0 +1,200 @@
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.pedidoMescladoGithub = pedidoMescladoGithub;
37
+ exports.branchPadraoGithub = branchPadraoGithub;
38
+ exports.pontaDaBranchGithub = pontaDaBranchGithub;
39
+ exports.compararGithub = compararGithub;
40
+ exports.pedidosDaBranchGithub = pedidosDaBranchGithub;
41
+ exports.abrirPedidoGithub = abrirPedidoGithub;
42
+ exports.pedidosAbertosGithub = pedidosAbertosGithub;
43
+ const fs = __importStar(require("node:fs"));
44
+ const os = __importStar(require("node:os"));
45
+ const path = __importStar(require("node:path"));
46
+ const texto_1 = require("../texto");
47
+ const SHA = /^[0-9a-f]{40}$/, BRANCH = /^[A-Za-z0-9._/-]{1,200}$/;
48
+ function lerJson(r) {
49
+ if (!r.ok)
50
+ return null;
51
+ try {
52
+ return JSON.parse(r.stdout);
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ }
58
+ function pedidoMescladoGithub(e) {
59
+ const pr = lerJson(e.executor(`repos/${e.repo}/pulls/${e.numero}`));
60
+ if (!pr)
61
+ return null;
62
+ return {
63
+ numero: e.numero, mesclado: pr.merged === true,
64
+ mergeSha: typeof pr.merge_commit_sha === 'string' && SHA.test(pr.merge_commit_sha) ? pr.merge_commit_sha : null,
65
+ headSha: typeof pr.head?.sha === 'string' && SHA.test(pr.head.sha) ? pr.head.sha : null,
66
+ base: typeof pr.base?.ref === 'string' && BRANCH.test(pr.base.ref) ? pr.base.ref : null,
67
+ branch: typeof pr.head?.ref === 'string' ? pr.head.ref : null,
68
+ titulo: typeof pr.title === 'string' ? pr.title : null, corpo: typeof pr.body === 'string' ? pr.body : null,
69
+ url: typeof pr.html_url === 'string' ? pr.html_url : null,
70
+ };
71
+ }
72
+ function branchPadraoGithub(e) {
73
+ const r = lerJson(e.executor(`repos/${e.repo}`));
74
+ return r ? (r.default_branch ?? '') : null;
75
+ }
76
+ function pontaDaBranchGithub(e) {
77
+ const r = lerJson(e.executor(`repos/${e.repo}/branches/${encodeURIComponent(e.branch)}`));
78
+ return typeof r?.commit?.sha === 'string' && SHA.test(r.commit.sha) ? r.commit.sha : null;
79
+ }
80
+ function compararGithub(e) {
81
+ const r = lerJson(e.executor(`repos/${e.repo}/compare/${e.de}...${e.ate}`));
82
+ return r ? String(r.status) : null;
83
+ }
84
+ /** Os campos do `gh pr list` de uma branch: os do `prDaForja`, com o estado de merge do PR aberto. */
85
+ const CAMPOS_DA_BRANCH = 'number,state,headRefName,headRefOid,baseRefName,isDraft,isCrossRepository,url,createdAt,mergedAt,mergeable';
86
+ /** Os PRs de uma branch, da base do projeto, do mais novo para o mais velho. */
87
+ function pedidosDaBranchGithub(e) {
88
+ const r = e.executor(['pr', 'list', `--repo=${e.host}/${e.repositorio}`, `--head=${e.branch}`, '--state=all', '--limit=10',
89
+ `--json=${CAMPOS_DA_BRANCH}`], e.prazoMs);
90
+ if (r.status !== 0)
91
+ return { prs: [], erro: (0, texto_1.deFora)(r.stderr || r.stdout || `codigo ${r.status ?? '-'}`) };
92
+ try {
93
+ const lista = JSON.parse(r.stdout);
94
+ if (!Array.isArray(lista))
95
+ throw new Error('a resposta nao e uma lista');
96
+ // Carga tardia: o parado-no-condutor chega a este módulo pelo entrega-pr; importar no topo fecharia um ciclo de carga.
97
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
98
+ const { prDaForja } = require('../../parado-no-condutor');
99
+ const prs = lista.map((p) => prDaForja(p, e.base)).filter((p) => !!p && p.branch === e.branch);
100
+ return { prs: prs.sort((a, b) => b.numero - a.numero), erro: null };
101
+ }
102
+ catch (err) {
103
+ return { prs: [], erro: (0, texto_1.deFora)(err.message) };
104
+ }
105
+ }
106
+ /** Abre o PR da branch na base. */
107
+ function abrirPedidoGithub(e) {
108
+ // O corpo vai por arquivo 600 num diretorio proprio: texto que parece flag (`--repo=outro/repo`) ou de 64 KiB nao toca o argv.
109
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ork-pr-'));
110
+ try {
111
+ const arquivo = path.join(dir, 'corpo.md');
112
+ fs.writeFileSync(arquivo, e.corpo, { mode: 0o600 });
113
+ return e.executor(['pr', 'create', `--repo=${e.host}/${e.repositorio}`, `--base=${e.base}`, `--head=${e.branch}`, `--title=${e.titulo}`,
114
+ '--body-file', arquivo], e.prazoMs);
115
+ }
116
+ finally {
117
+ fs.rmSync(dir, { recursive: true, force: true });
118
+ }
119
+ }
120
+ /** Os campos dos recentes e os dos abertos, com o rollup e o estado de merge (RM-059, F7). */
121
+ const CAMPOS_DOS_RECENTES = 'number,state,headRefName,headRefOid,baseRefName,isDraft,isCrossRepository,url,createdAt,mergedAt';
122
+ const CAMPOS_DOS_ABERTOS = `${CAMPOS_DOS_RECENTES},statusCheckRollup,mergeable`;
123
+ /** O texto de fora numa linha, sem segredo e com teto (`deFora`); vazio vira "sem detalhe". */
124
+ const detalheDeFora = (v, teto) => (v.replace(/\p{Cc}/gu, ' ').trim() ? (0, texto_1.deFora)(v, teto) : 'sem detalhe');
125
+ /**
126
+ * Os PRs da base para o pulse, pelo `gh pr list`: os abertos com o rollup (ate o teto; lista cheia e `parcial`), os
127
+ * recentes de qualquer estado, e cada candidata que nao apareceu, conferida pelo `--head` enquanto houver tempo
128
+ * (acima do teto ou sem tempo, ela fica em `semConferir`, que e "PR nao lido", nunca "sem PR"). O `gh` usa a
129
+ * autenticacao dele; nenhum token passa por aqui.
130
+ */
131
+ function pedidosAbertosGithub(e) {
132
+ // Carga tardia: o parado-no-condutor chega a este modulo pelo registro; importar no topo fecharia um ciclo de carga.
133
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
134
+ const { prDaForja } = require('../../parado-no-condutor');
135
+ const l = e.limites, repo = `--repo=${e.forja.host}/${e.forja.repo}`;
136
+ const falha = (detalhe, codigo = 'forja.indisponivel') => ({ ok: false, erro: { codigo, detalhe } });
137
+ const pedir = (args) => {
138
+ if (e.resta() <= 0)
139
+ return `gh pr list: orçamento de ${Math.round(e.orcamentoMs / 1000)} s da leitura esgotado`;
140
+ const r = e.executor(['pr', 'list', repo, `--base=${e.base}`, ...args], Math.min(l.prazoMs, e.resta()));
141
+ if (r.status !== 0) {
142
+ const detalhe = detalheDeFora(r.stderr || r.stdout || '', 160);
143
+ return `gh pr list falhou (${r.status === null ? 'sem código de saída' : `código ${r.status}`}): ${detalhe}`;
144
+ }
145
+ try {
146
+ const lista = JSON.parse(r.stdout);
147
+ if (!Array.isArray(lista))
148
+ throw new Error('a resposta não é uma lista');
149
+ return lista;
150
+ }
151
+ catch (err) {
152
+ return `resposta do gh pr list fora do formato: ${detalheDeFora(err.message, 120)}`;
153
+ }
154
+ };
155
+ try {
156
+ const porNumero = new Map();
157
+ const juntar = (lista, comChecks) => {
158
+ for (const bruto of lista) {
159
+ const pr = prDaForja(bruto, e.base);
160
+ if (!pr || porNumero.has(pr.numero))
161
+ continue;
162
+ // A leitura sem rollup nunca diz que o aberto nao tem checks.
163
+ if (!comChecks && pr.estado === 'aberto')
164
+ pr.checks = [{ nome: 'checks não lidos', situacao: 'pendente', concluidoEm: null }];
165
+ porNumero.set(pr.numero, pr);
166
+ }
167
+ };
168
+ const abertos = pedir(['--state=open', `--limit=${l.abertos}`, `--json=${CAMPOS_DOS_ABERTOS}`]);
169
+ if (typeof abertos === 'string')
170
+ return falha(abertos);
171
+ juntar(abertos, true);
172
+ const recentes = pedir(['--state=all', `--limit=${l.recentes}`, `--json=${CAMPOS_DOS_RECENTES}`]);
173
+ if (typeof recentes === 'string')
174
+ return falha(recentes);
175
+ juntar(recentes, false);
176
+ // Antes de dizer "sem PR", a candidata e conferida sozinha (o mesclado velho fica fora dos recentes).
177
+ const achadas = new Set([...porNumero.values()].map((p) => p.branch));
178
+ const faltam = [...new Set(e.candidatas)].filter((b) => BRANCH.test(b) && !achadas.has(b));
179
+ const semConferir = [];
180
+ for (const [i, branch] of faltam.entries()) {
181
+ if (i >= l.candidatas || e.resta() < l.minimoDaConferenciaMs) {
182
+ semConferir.push(branch);
183
+ continue;
184
+ }
185
+ const daBranch = pedir(['--state=all', `--head=${branch}`, '--limit=5', `--json=${CAMPOS_DOS_RECENTES}`]);
186
+ try {
187
+ if (typeof daBranch === 'string')
188
+ throw new Error(daBranch);
189
+ juntar(daBranch, false);
190
+ }
191
+ catch {
192
+ semConferir.push(branch);
193
+ }
194
+ }
195
+ return { ok: true, valor: { prs: [...porNumero.values()], parcial: abertos.length >= l.abertos, semConferir } };
196
+ }
197
+ catch (err) {
198
+ return falha(`resposta do gh pr list fora do formato: ${detalheDeFora(err.message, 120)}`, 'forja.resposta-invalida');
199
+ }
200
+ }
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_PIPELINES = void 0;
4
+ exports.estadoDeCiGitlab = estadoDeCiGitlab;
5
+ /**
6
+ * A CI de um commit no GitLab. O check exigido e lido dos commit statuses do commit, filtrados pelo nome e com as
7
+ * reexecucoes (`all=true`). So um job real de pipeline do projeto e `pipeline-job` (produtor `gitlab-ci`): o status
8
+ * traz o `pipeline_id`, e um job com o mesmo id e o mesmo nome esta na lista de jobs dessa pipeline (status e job sao
9
+ * a mesma linha no GitLab). O `pipeline_id` sozinho nao prova nada: um `POST /statuses` com nome novo entra na
10
+ * pipeline real (pelo `pipeline_id` ou pelo `ref` do MR) e um com `ref` de branch cria uma pipeline `external`; nos
11
+ * dois casos o status e um job `external`, que a lista de jobs nao traz. Ele fica `commit-status`, com o usuario que o
12
+ * criou como produtor.
13
+ *
14
+ * Resultado mesclado e merge train (EE) testam um commit temporario, nao o head. Sem job do check no head, numa
15
+ * instancia que pode te-los (edicao EE ou desconhecida, com a opcao ligada no projeto), a leitura procura a pipeline do
16
+ * pedido cujo commit tem o head como pai (o `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` que o job recebe); o vinculo e lido
17
+ * do proprio commit, pela API. Pipeline candidata sem esse pai marca `mescladoSemVinculo`.
18
+ *
19
+ * Qualquer erro de leitura, pagina a mais ou item fora do esquema sai como erro, nunca como lista curta.
20
+ */
21
+ const zod_1 = require("zod");
22
+ const api_1 = require("../api");
23
+ const estado_1 = require("../estado");
24
+ const pedidos_1 = require("./pedidos");
25
+ const INSTANTES = { created_at: zod_1.z.string().nullish(), started_at: zod_1.z.string().nullish(), finished_at: zod_1.z.string().nullish() };
26
+ const STATUS = zod_1.z.object({ id: zod_1.z.number().int(), name: zod_1.z.string(), status: zod_1.z.string(), target_url: zod_1.z.string().nullish(),
27
+ pipeline_id: zod_1.z.number().int().nullish(), author: zod_1.z.object({ username: zod_1.z.string() }).passthrough().nullish(), ...INSTANTES }).passthrough();
28
+ const JOB = zod_1.z.object({ id: zod_1.z.number().int(), name: zod_1.z.string(), status: zod_1.z.string(), web_url: zod_1.z.string().nullish(),
29
+ pipeline: zod_1.z.object({ id: zod_1.z.number().int(), project_id: zod_1.z.number().int().nullish() }).passthrough(), ...INSTANTES }).passthrough();
30
+ const PROJETO = zod_1.z.object({ id: zod_1.z.number().int(), merge_pipelines_enabled: zod_1.z.boolean().nullish(), merge_trains_enabled: zod_1.z.boolean().nullish() })
31
+ .passthrough();
32
+ const PEDIDO = zod_1.z.object({ iid: zod_1.z.number().int(), sha: zod_1.z.string().nullish() }).passthrough();
33
+ /** O sha completo: o que entra no caminho da API, de fora ou da resposta, tem esta forma. */
34
+ const SHA = /^[0-9a-f]{40}$/;
35
+ const PIPELINE = zod_1.z.object({ id: zod_1.z.number().int(), project_id: zod_1.z.number().int().nullish(), sha: zod_1.z.string().regex(SHA), ref: zod_1.z.string() }).passthrough();
36
+ const COMMIT = zod_1.z.object({ id: zod_1.z.string(), parent_ids: zod_1.z.array(zod_1.z.string()) }).passthrough();
37
+ /** As pipelines distintas que a leitura confere por commit (e por pedido, no resultado mesclado). */
38
+ exports.MAX_PIPELINES = 10;
39
+ const falha = (codigo, detalhe) => ({ ok: false, erro: { codigo, detalhe } });
40
+ /** Uma lista paginada, cada item no esquema; item fora dele e `forja.resposta-invalida`. */
41
+ function lista(api, caminho, esquema) {
42
+ const lido = (0, api_1.paginarPelaApi)(api, { caminho });
43
+ if (!lido.ok)
44
+ return lido;
45
+ const itens = zod_1.z.array(esquema).safeParse(lido.valor.itens);
46
+ return itens.success ? { ok: true, valor: itens.data } : falha('forja.resposta-invalida', caminho.split('?')[0]);
47
+ }
48
+ /** Um objeto, no esquema. */
49
+ function um(api, caminho, esquema) {
50
+ const r = api({ metodo: 'GET', caminho });
51
+ if (!r.ok)
52
+ return r;
53
+ const lido = esquema.safeParse(r.valor.corpo);
54
+ return lido.success ? { ok: true, valor: lido.data } : falha('forja.resposta-invalida', caminho);
55
+ }
56
+ /** A data que escolhe o mais novo de um produtor: `null` enquanto pendente; sem data nenhuma, `''` (a mais velha). */
57
+ function concluidoEm(fonte, s) {
58
+ if ((0, estado_1.estadoDoCheck)(fonte, s.status, null) === 'pendente')
59
+ return null;
60
+ return s.finished_at ?? s.started_at ?? s.created_at ?? '';
61
+ }
62
+ const doJob = (j) => ({ nome: j.name, fonte: 'pipeline-job', produtor: 'gitlab-ci', status: j.status, conclusao: null,
63
+ url: j.web_url ?? null, concluidoEm: concluidoEm('pipeline-job', j), ordem: j.id });
64
+ const jobsDaPipeline = (api, projeto, pipeline) => lista(api, `${projeto}/pipelines/${pipeline}/jobs?include_retried=true`, JOB);
65
+ function estadoDeCiGitlab(e) {
66
+ if (!SHA.test(e.sha))
67
+ return falha('forja.pedido-recusado', 'o sha do commit não tem 40 caracteres hexadecimais minúsculos');
68
+ const projeto = (0, pedidos_1.projetoNaApi)(e.repo);
69
+ const lidos = lista(e.api, `${projeto}/repository/commits/${e.sha}/statuses?name=${encodeURIComponent(e.context)}&all=true`, STATUS);
70
+ if (!lidos.ok)
71
+ return lidos;
72
+ const doNome = lidos.valor.filter((s) => s.name === e.context);
73
+ const pipelines = [...new Set(doNome.flatMap((s) => (typeof s.pipeline_id === 'number' ? [s.pipeline_id] : [])))].sort((a, b) => a - b);
74
+ if (pipelines.length > exports.MAX_PIPELINES)
75
+ return falha('forja.incompleto', `${e.context}: ${pipelines.length} pipelines > ${exports.MAX_PIPELINES}`);
76
+ // O job real de cada status: mesma pipeline, mesmo id e mesmo nome. A lista e a do projeto pedido; pipeline de outro
77
+ // projeto nao esta nela (404, que sai como erro).
78
+ const reais = new Map();
79
+ for (const pipeline of pipelines) {
80
+ const jobs = jobsDaPipeline(e.api, projeto, pipeline);
81
+ if (!jobs.ok)
82
+ return jobs;
83
+ for (const j of jobs.valor)
84
+ if (j.name === e.context && j.pipeline.id === pipeline)
85
+ reais.set(`${pipeline}:${j.id}`, j);
86
+ }
87
+ const checks = doNome.map((s) => {
88
+ const job = typeof s.pipeline_id === 'number' ? reais.get(`${s.pipeline_id}:${s.id}`) : undefined;
89
+ if (job)
90
+ return doJob(job);
91
+ return { nome: s.name, fonte: 'commit-status', produtor: s.author?.username ?? null, status: s.status, conclusao: null,
92
+ url: s.target_url ?? null, concluidoEm: concluidoEm('commit-status', s), ordem: s.id };
93
+ });
94
+ if (checks.some((c) => c.fonte === 'pipeline-job'))
95
+ return { ok: true, valor: { checks, mescladoSemVinculo: false } };
96
+ const mesclado = doResultadoMesclado(e, projeto);
97
+ if (!mesclado.ok)
98
+ return mesclado;
99
+ return { ok: true, valor: { checks: [...checks, ...mesclado.valor.checks], mescladoSemVinculo: mesclado.valor.mescladoSemVinculo } };
100
+ }
101
+ /** Os jobs do check na pipeline de resultado mesclado do pedido ligada ao head pelo pai do commit dela. */
102
+ function doResultadoMesclado(e, projeto) {
103
+ const nada = { ok: true, valor: { checks: [], mescladoSemVinculo: false } };
104
+ if (e.edicao === 'ce')
105
+ return nada;
106
+ const opcoes = um(e.api, projeto, PROJETO);
107
+ if (!opcoes.ok)
108
+ return opcoes;
109
+ if (opcoes.valor.merge_pipelines_enabled !== true && opcoes.valor.merge_trains_enabled !== true)
110
+ return nada;
111
+ const id = opcoes.valor.id;
112
+ const pedidos = lista(e.api, `${projeto}/repository/commits/${e.sha}/merge_requests`, PEDIDO);
113
+ if (!pedidos.ok)
114
+ return pedidos;
115
+ let semVinculo = false;
116
+ for (const pedido of pedidos.valor.filter((p) => p.sha === e.sha)) {
117
+ const doPedido = lista(e.api, `${projeto}/merge_requests/${pedido.iid}/pipelines`, PIPELINE);
118
+ if (!doPedido.ok)
119
+ return doPedido;
120
+ const ref = new RegExp(`^refs/merge-requests/${pedido.iid}/(?:merge|train)$`);
121
+ // So a pipeline do proprio projeto: a de um fork roda o codigo e a CI de outro projeto.
122
+ const candidatas = doPedido.valor.filter((p) => p.project_id === id && p.sha !== e.sha && ref.test(p.ref))
123
+ .sort((a, b) => b.id - a.id).slice(0, exports.MAX_PIPELINES);
124
+ for (const p of candidatas) {
125
+ const commit = um(e.api, `${projeto}/repository/commits/${p.sha}`, COMMIT);
126
+ if (!commit.ok)
127
+ return commit;
128
+ if (!commit.valor.parent_ids.includes(e.sha)) {
129
+ semVinculo = true;
130
+ continue;
131
+ }
132
+ const jobs = jobsDaPipeline(e.api, projeto, p.id);
133
+ if (!jobs.ok)
134
+ return jobs;
135
+ const doCheck = jobs.valor.filter((j) => j.name === e.context && j.pipeline.id === p.id && j.pipeline.project_id === id);
136
+ if (doCheck.length)
137
+ return { ok: true, valor: { checks: doCheck.map(doJob), mescladoSemVinculo: false } };
138
+ }
139
+ }
140
+ return { ok: true, valor: { checks: [], mescladoSemVinculo: semVinculo } };
141
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * As consultas GraphQL do adaptador GitLab, num lugar so: o codigo e o roteiro que grava as respostas reais
4
+ * (`scripts/forja-contrato.cjs`, que as le do `dist`) usam o mesmo texto. So consulta, sem mutation; o que vem do
5
+ * pedido vai em variaveis, nunca interpolado.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.CONSULTA_ARVORES_GITLAB = exports.CONSULTA_RAIZ_GITLAB = exports.CONSULTA_DOS_ABERTOS_SEGUINTES = exports.CONSULTA_DOS_PEDIDOS = void 0;
9
+ exports.consultaDeBlobsDoGitlab = consultaDeBlobsDoGitlab;
10
+ /** Os campos de um MR que o pulse le, nas tres listas. */
11
+ const CAMPOS_DO_PEDIDO = 'iid sourceBranch targetBranch diffHeadSha draft state webUrl createdAt mergedAt sourceProjectId targetProjectId';
12
+ /** Os do MR aberto: os de todos, o conflito, a pipeline do head e o job do check da CI (`$check`) dela, com o estagio. */
13
+ const CAMPOS_DO_ABERTO = `${CAMPOS_DO_PEDIDO} conflicts headPipeline { sha status finishedAt ` +
14
+ 'job(name: $check) { status startedAt finishedAt stage { name } } }';
15
+ /**
16
+ * Os MRs da base numa consulta so: os abertos (100 por pagina), os recentes de qualquer estado (100) e os das
17
+ * branches candidatas (ate 50). Medido no CE 17.0 e 19.4: complexidade 140 de 250. Lista vazia de candidatas nao devolve
18
+ * MR nenhum (`null` devolveria todos, por isso a variavel e obrigatoria).
19
+ */
20
+ exports.CONSULTA_DOS_PEDIDOS = `query($path: ID!, $base: String!, $candidatas: [String!]!, $check: String!) {
21
+ queryComplexity { score limit }
22
+ project(fullPath: $path) {
23
+ id
24
+ abertos: mergeRequests(state: opened, targetBranches: [$base], sort: CREATED_DESC, first: 100) {
25
+ pageInfo { hasNextPage endCursor } nodes { ${CAMPOS_DO_ABERTO} } }
26
+ recentes: mergeRequests(state: all, targetBranches: [$base], sort: CREATED_DESC, first: 100) { nodes { ${CAMPOS_DO_PEDIDO} } }
27
+ daBranch: mergeRequests(state: all, targetBranches: [$base], sourceBranches: $candidatas, sort: CREATED_DESC, first: 50) {
28
+ pageInfo { hasNextPage } nodes { ${CAMPOS_DO_PEDIDO} } }
29
+ }
30
+ }`;
31
+ /** A pagina seguinte dos abertos, pelo cursor da anterior. */
32
+ exports.CONSULTA_DOS_ABERTOS_SEGUINTES = `query($path: ID!, $base: String!, $depois: String!, $check: String!) {
33
+ queryComplexity { score limit }
34
+ project(fullPath: $path) {
35
+ id
36
+ abertos: mergeRequests(state: opened, targetBranches: [$base], sort: CREATED_DESC, first: 100, after: $depois) {
37
+ pageInfo { hasNextPage endCursor } nodes { ${CAMPOS_DO_ABERTO} } }
38
+ }
39
+ }`;
40
+ exports.CONSULTA_RAIZ_GITLAB = 'query($path: ID!) { project(fullPath: $path) { repository { rootRef } } }';
41
+ exports.CONSULTA_ARVORES_GITLAB = `query($path: ID!, $base: String!, $dirRoadmap: String!, $refReservas: String!, $dirReservas: String!,
42
+ $refFabrica: String!, $dirFabrica: String!) {
43
+ project(fullPath: $path) { repository {
44
+ baseTopo: tree(ref: $base) { lastCommit { sha committedDate } }
45
+ baseDir: tree(ref: $base, path: $dirRoadmap) { blobs(first: 100) { pageInfo { hasNextPage } nodes { name path } } }
46
+ reservasTopo: tree(ref: $refReservas) { lastCommit { sha committedDate } }
47
+ reservasDir: tree(ref: $refReservas, path: $dirReservas) { blobs(first: 100) { pageInfo { hasNextPage } nodes { name path } } }
48
+ fabricaTopo: tree(ref: $refFabrica) { lastCommit { sha committedDate } }
49
+ fabricaDir: tree(ref: $refFabrica, path: $dirFabrica) { blobs(first: 100) { pageInfo { hasNextPage } nodes { name path } } }
50
+ } }
51
+ }`;
52
+ /** Os blobs de cada ponta que existe; so as partes pedidas entram na consulta (texto fixo, sem interpolar o pedido). */
53
+ function consultaDeBlobsDoGitlab(partes) {
54
+ const sufixo = { base: 'Base', reservas: 'Reservas', fabrica: 'Fabrica' };
55
+ const declaracoes = ['$path: ID!', ...partes.flatMap((p) => [`$ref${sufixo[p]}: String!`, `$paths${sufixo[p]}: [String!]!`])];
56
+ const campos = partes.map((p) => `${p}: blobs(ref: $ref${sufixo[p]}, paths: $paths${sufixo[p]}, first: 100) ` +
57
+ '{ pageInfo { hasNextPage } nodes { path rawTextBlob } }');
58
+ return `query(${declaracoes.join(', ')}) { project(fullPath: $path) { repository { ${campos.join(' ')} } } }`;
59
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.donoDaRedeGitlab = donoDaRedeGitlab;
4
+ const obj = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
5
+ const id = (v) => Number.isSafeInteger(v) && v > 0;
6
+ const invalida = (detalhe) => ({ ok: false, erro: { codigo: 'forja.resposta-invalida', detalhe } });
7
+ const naoAchei = (detalhe) => ({ ok: false, erro: { codigo: 'forja.nao-achei', detalhe } });
8
+ function donoDaRedeGitlab(e) {
9
+ if (!e.dono.trim())
10
+ return naoAchei('dono vazio');
11
+ const ns = e.api({ metodo: 'GET', caminho: `namespaces/${encodeURIComponent(e.dono)}` });
12
+ if (!ns.ok)
13
+ return ns;
14
+ const n = ns.valor.corpo;
15
+ if (!obj(n) || !id(n.id) || (n.kind !== 'user' && n.kind !== 'group') || typeof n.full_path !== 'string')
16
+ return invalida(`namespaces/${e.dono}`);
17
+ // O GitLab acha o namespace sem diferenciar maiusculas; outro caminho na resposta e outra coisa.
18
+ if (n.full_path.toLowerCase() !== e.dono.toLowerCase())
19
+ return invalida(`namespaces/${e.dono}: ${n.full_path}`);
20
+ const eu = e.api({ metodo: 'GET', caminho: 'user' });
21
+ if (!eu.ok)
22
+ return eu;
23
+ const pessoa = eu.valor.corpo;
24
+ if (!obj(pessoa) || !id(pessoa.id))
25
+ return invalida('user');
26
+ if (n.kind === 'user') {
27
+ // Um token de admin le o namespace de qualquer usuario com 200; so o da propria pessoa serve de casa.
28
+ const propria = (typeof pessoa.username === 'string' && pessoa.username.toLowerCase() === n.full_path.toLowerCase()) || pessoa.namespace_id === n.id;
29
+ if (!propria)
30
+ return naoAchei(`namespaces/${e.dono}: nao e da pessoa logada`);
31
+ return { ok: true, valor: { tipo: 'usuario', caminho: n.full_path, namespaceId: n.id, nivel: null } };
32
+ }
33
+ const membro = e.api({ metodo: 'GET', caminho: `groups/${n.id}/members/all/${pessoa.id}` });
34
+ // Fora do grupo, nem herdado: 404, nivel 0.
35
+ if (!membro.ok && membro.erro.codigo === 'forja.nao-achei')
36
+ return { ok: true, valor: { tipo: 'grupo', caminho: n.full_path, namespaceId: n.id, nivel: 0 } };
37
+ if (!membro.ok)
38
+ return membro;
39
+ const m = membro.valor.corpo;
40
+ if (!obj(m) || !Number.isSafeInteger(m.access_level))
41
+ return invalida(`groups/${n.id}/members/all`);
42
+ return { ok: true, valor: { tipo: 'grupo', caminho: n.full_path, namespaceId: n.id, nivel: m.access_level } };
43
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.metadadosGitlab = metadadosGitlab;
4
+ const zod_1 = require("zod");
5
+ const METADATA = zod_1.z.object({ version: zod_1.z.string().regex(/^\d+\.\d+/), enterprise: zod_1.z.boolean() });
6
+ /** `GET /metadata`: a versao e a edicao da instancia. Responde tambem abaixo do piso (16.11 gravada), e a recusa e de quem le. */
7
+ function metadadosGitlab(e) {
8
+ const r = e.api({ metodo: 'GET', caminho: 'metadata' });
9
+ if (!r.ok)
10
+ return r;
11
+ const lido = METADATA.safeParse(r.valor.corpo);
12
+ if (!lido.success)
13
+ return { ok: false, erro: { codigo: 'forja.resposta-invalida', detalhe: 'metadata: version, enterprise' } };
14
+ return { ok: true, valor: { versao: lido.data.version, edicao: lido.data.enterprise ? 'ee' : 'ce' } };
15
+ }
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pedidosAbertosGitlab = pedidosAbertosGitlab;
4
+ /**
5
+ * Os MRs da base para o pulse, numa consulta GraphQL (todos os tiers; o REST pediria uma chamada por MR): os abertos
6
+ * com a pipeline do head e o job do check da CI (`ci.context`), os recentes de qualquer estado e os das branches
7
+ * candidatas. Os abertos paginam de 100 em 100 ate o teto; com a cota abaixo de 10 % a paginacao para, e o que faltou
8
+ * e `parcial`, nunca "sem MR". MR de fork (`sourceProjectId` de outro projeto) e de outra base ficam de fora, como o
9
+ * `isCrossRepository` do GitHub. O estado de cada job e da pipeline sai da regra unica (`estadoDoCheck`); como no
10
+ * GitHub, o pulse conta o pulado de proposito (`manual`, `skipped`) como verde. O status externo (`POST /statuses`)
11
+ * entra na pipeline com o estagio `external`: nunca e o check da CI, e a pipeline sem o job nao fica verde no pulse.
12
+ */
13
+ const api_1 = require("../api");
14
+ const estado_1 = require("../estado");
15
+ const texto_1 = require("../texto");
16
+ const consultas_1 = require("./consultas");
17
+ const pedidos_1 = require("./pedidos");
18
+ const obj = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
19
+ const SHA = /^[0-9a-f]{40}$/, BRANCH = /^[A-Za-z0-9._/-]{1,200}$/, IID = /^[1-9]\d{0,9}$/;
20
+ class ForaDoFormato extends Error {
21
+ }
22
+ /** Instante ISO de fora; ano antes de 2000 nao vale. */
23
+ function instante(v) {
24
+ if (typeof v !== 'string')
25
+ return null;
26
+ const ms = Date.parse(v);
27
+ return Number.isFinite(ms) && new Date(ms).getUTCFullYear() >= 2000 ? new Date(ms).toISOString() : null;
28
+ }
29
+ function situacao(status) {
30
+ if (typeof status !== 'string')
31
+ return 'pendente';
32
+ const estado = (0, estado_1.estadoDoCheck)('pipeline-job', status, null);
33
+ return estado === 'bloqueado' ? 'verde' : estado;
34
+ }
35
+ /** Os checks do MR aberto: a pipeline do head e o job do check da CI dela, com o nome do manifesto. */
36
+ function checksDoAberto(no, head, check) {
37
+ const p = no.headPipeline;
38
+ if (p === null || p === undefined)
39
+ return [];
40
+ if (!obj(p))
41
+ throw new ForaDoFormato('headPipeline');
42
+ // A pipeline de outro head (o MR ganhou commit e a nova ainda nao nasceu) nao diz nada do head de agora.
43
+ if (p.sha !== head)
44
+ return [{ nome: 'pipeline', situacao: 'pendente', concluidoEm: null }];
45
+ const daPipeline = situacao(p.status);
46
+ const checks = [{ nome: 'pipeline', situacao: daPipeline, concluidoEm: daPipeline === 'pendente' ? null : instante(p.finishedAt) }];
47
+ // Sem o job, o verde da pipeline pode ser so de status externos (qualquer nome fecha a pipeline): o check da CI
48
+ // fica pendente, nunca some.
49
+ if (p.job === null || p.job === undefined)
50
+ return [...checks, { nome: check, situacao: 'pendente', concluidoEm: null }];
51
+ if (!obj(p.job))
52
+ throw new ForaDoFormato('job');
53
+ const externo = !obj(p.job.stage) || p.job.stage.name === 'external';
54
+ const doJob = externo ? 'pendente' : situacao(p.job.status);
55
+ checks.push({ nome: check, situacao: doJob,
56
+ concluidoEm: doJob === 'pendente' ? null : instante(p.job.finishedAt) ?? instante(p.job.startedAt) });
57
+ return checks;
58
+ }
59
+ /** Um MR da resposta, ou `null` quando nao e desta base nem deste projeto (fork). Formato errado lanca. */
60
+ function pedidoDoGitlab(bruto, base, projeto, comChecks, check) {
61
+ if (!obj(bruto))
62
+ throw new ForaDoFormato('MR');
63
+ const estado = pedidos_1.ESTADOS_DO_MR[String(bruto.state)];
64
+ if (typeof bruto.iid !== 'string' || !IID.test(bruto.iid) || !estado || typeof bruto.draft !== 'boolean' ||
65
+ typeof bruto.sourceProjectId !== 'number')
66
+ throw new ForaDoFormato('MR');
67
+ if (bruto.sourceProjectId !== projeto || bruto.targetBranch !== base || typeof bruto.sourceBranch !== 'string' ||
68
+ !BRANCH.test(bruto.sourceBranch))
69
+ return null;
70
+ const head = bruto.diffHeadSha, aberto = estado === 'aberto';
71
+ if (typeof head !== 'string' || !SHA.test(head)) {
72
+ if (aberto)
73
+ throw new ForaDoFormato('diffHeadSha');
74
+ return null;
75
+ }
76
+ const url = typeof bruto.webUrl === 'string' && /^https:\/\/[^\s]+$/.test(bruto.webUrl) ? bruto.webUrl.slice(0, 300) : null;
77
+ // A leitura sem a pipeline (recentes, candidatas) nunca diz que o aberto nao tem checks.
78
+ const checks = !aberto ? [] : comChecks ? checksDoAberto(bruto, head, check) : [{ nome: 'checks não lidos', situacao: 'pendente', concluidoEm: null }];
79
+ return { numero: Number(bruto.iid), branch: bruto.sourceBranch, head, estado, rascunho: bruto.draft, url,
80
+ criadoEm: instante(bruto.createdAt), mescladoEm: instante(bruto.mergedAt), checks,
81
+ ...(aberto && comChecks && typeof bruto.conflicts === 'boolean' ? { conflito: bruto.conflicts } : {}) };
82
+ }
83
+ function pagina(conexao, comCursor) {
84
+ const info = conexao.pageInfo;
85
+ if (!obj(info) || typeof info.hasNextPage !== 'boolean')
86
+ throw new ForaDoFormato('pageInfo');
87
+ if (info.hasNextPage && comCursor && typeof info.endCursor !== 'string')
88
+ throw new ForaDoFormato('endCursor');
89
+ return { temMais: info.hasNextPage, cursor: typeof info.endCursor === 'string' ? info.endCursor : null };
90
+ }
91
+ function pedidosAbertosGitlab(e) {
92
+ const falha = (codigo, detalhe) => ({ ok: false, erro: { codigo, detalhe } });
93
+ const pedir = (query, variables) => {
94
+ if (e.resta() <= 0)
95
+ return falha('forja.indisponivel', `graphql: orçamento de ${Math.round(e.orcamentoMs / 1000)} s da leitura esgotado`);
96
+ const r = e.api({ metodo: 'POST', caminho: 'graphql', corpo: { query, variables }, prazoMs: Math.min(e.limites.prazoMs, e.resta()) });
97
+ if (!r.ok)
98
+ return r;
99
+ const corpo = r.valor.corpo;
100
+ if (obj(corpo) && Array.isArray(corpo.errors) && corpo.errors.length) {
101
+ const mensagens = corpo.errors.map((x) => (obj(x) && typeof x.message === 'string' ? x.message : '?')).join('; ');
102
+ return falha('forja.resposta-invalida', (0, texto_1.deFora)(`graphql: ${mensagens}`));
103
+ }
104
+ const dados = obj(corpo) ? corpo.data : undefined;
105
+ if (!obj(dados) || !('project' in dados))
106
+ return falha('forja.resposta-invalida', 'graphql: sem data.project');
107
+ // Projeto que nao existe e projeto privado sem acesso respondem igual: `project: null`.
108
+ if (dados.project === null)
109
+ return falha('forja.nao-achei', `graphql: projeto ${e.forja.repo}`);
110
+ if (!obj(dados.project))
111
+ return falha('forja.resposta-invalida', 'graphql: project');
112
+ return { ok: true, valor: { projeto: dados.project, baixo: (0, api_1.limiteBaixo)(r.valor.limite) } };
113
+ };
114
+ const candidatas = [...new Set(e.candidatas)].filter((b) => BRANCH.test(b));
115
+ const primeira = pedir(consultas_1.CONSULTA_DOS_PEDIDOS, { path: e.forja.repo, base: e.base, candidatas: candidatas.slice(0, e.limites.candidatas),
116
+ check: e.contexto });
117
+ if (!primeira.ok)
118
+ return primeira;
119
+ try {
120
+ const projeto = primeira.valor.projeto;
121
+ const id = /^gid:\/\/gitlab\/Project\/(\d+)$/.exec(String(projeto.id))?.[1];
122
+ if (!id)
123
+ throw new ForaDoFormato('project.id');
124
+ const porNumero = new Map();
125
+ const juntar = (conexao, comChecks, onde) => {
126
+ if (!obj(conexao) || !Array.isArray(conexao.nodes))
127
+ throw new ForaDoFormato(onde);
128
+ for (const bruto of conexao.nodes) {
129
+ const pr = pedidoDoGitlab(bruto, e.base, Number(id), comChecks, e.contexto);
130
+ if (pr && !porNumero.has(pr.numero))
131
+ porNumero.set(pr.numero, pr);
132
+ }
133
+ return conexao;
134
+ };
135
+ let abertos = juntar(projeto.abertos, true, 'abertos');
136
+ let lidos = abertos.nodes.length, baixo = primeira.valor.baixo, seguinte = pagina(abertos, true);
137
+ while (seguinte.temMais && lidos < e.limites.abertos && !baixo) {
138
+ const r = pedir(consultas_1.CONSULTA_DOS_ABERTOS_SEGUINTES, { path: e.forja.repo, base: e.base, depois: seguinte.cursor, check: e.contexto });
139
+ if (!r.ok)
140
+ return r;
141
+ abertos = juntar(r.valor.projeto.abertos, true, 'abertos');
142
+ lidos += abertos.nodes.length;
143
+ baixo = r.valor.baixo;
144
+ seguinte = pagina(abertos, true);
145
+ }
146
+ juntar(projeto.recentes, false, 'recentes');
147
+ const daBranch = juntar(projeto.daBranch, false, 'daBranch');
148
+ const cortada = pagina(daBranch, false).temMais;
149
+ const achadas = new Set([...porNumero.values()].map((p) => p.branch));
150
+ const semConferir = candidatas.filter((b, i) => !achadas.has(b) && (i >= e.limites.candidatas || cortada));
151
+ return { ok: true, valor: { prs: [...porNumero.values()], parcial: seguinte.temMais, semConferir } };
152
+ }
153
+ catch (err) {
154
+ if (err instanceof ForaDoFormato)
155
+ return falha('forja.resposta-invalida', `graphql: ${err.message} fora do formato`);
156
+ throw err;
157
+ }
158
+ }