@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.
- package/adapters/README.md +18 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
- package/adapters/claude-code/README.md +37 -5
- package/adapters/claude-code/agents/ork-check.md +1 -0
- package/adapters/claude-code/agents/ork-go.md +1 -0
- package/adapters/claude-code/agents/ork-goal.md +1 -0
- package/adapters/claude-code/agents/ork-master.md +1 -0
- package/adapters/claude-code/agents/ork-plan.md +1 -0
- package/adapters/claude-code/agents/ork-ship.md +1 -0
- package/adapters/claude-code/hooks/hooks.json +2 -1
- package/adapters/claude-code/hooks/ork-guard.js +15 -1
- package/adapters/claude-code/hooks/ork-resposta.js +91 -0
- package/adapters/claude-code/hooks/ork-sensor.js +18 -2
- package/adapters/claude-code/hooks/quota-signal.js +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
- package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
- package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
- package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
- package/adapters/codex/skills/ork/SKILL.md +2 -0
- package/adapters/hermes/README.md +64 -1
- package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
- package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
- package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
- package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
- package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
- package/adapters/hermes/hermes.plugin.json +4 -0
- package/adapters/hermes/hitl-ingress/__init__.py +101 -8
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
- package/adapters/openclaw/README.md +81 -9
- package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
- package/adapters/openclaw/dist/hitl-ingress.js +106 -9
- package/adapters/openclaw/dist/index.js +86 -0
- package/adapters/openclaw/openclaw.plugin.json +34 -4
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +103 -9
- package/adapters/openclaw/src/index.ts +94 -0
- package/assets/adapters-en/claude-code/README.md +403 -0
- package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
- package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
- package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
- package/assets/adapters-en/claude-code/commands/check.md +46 -0
- package/assets/adapters-en/claude-code/commands/go.md +46 -0
- package/assets/adapters-en/claude-code/commands/goal.md +55 -0
- package/assets/adapters-en/claude-code/commands/master.md +54 -0
- package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
- package/assets/adapters-en/claude-code/commands/ork.md +126 -0
- package/assets/adapters-en/claude-code/commands/plan.md +47 -0
- package/assets/adapters-en/claude-code/commands/ship.md +45 -0
- package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
- package/assets/adapters-en/hermes/README.md +273 -0
- package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
- package/assets/references-en/README.md +25 -0
- package/assets/references-en/code-review-axes.md +82 -0
- package/assets/references-en/definition-of-done.md +74 -0
- package/assets/references-en/performance-checklist.md +53 -0
- package/assets/references-en/security-checklist.md +101 -0
- package/assets/references-en/testing-patterns.md +51 -0
- package/assets/security-scan/defaults/.golangci.yml +2 -0
- package/assets/security-scan/defaults/eslint.config.mjs +11 -0
- package/assets/security-scan/defaults/gitleaks.toml +3 -0
- package/assets/security-scan/defaults/ruff.toml +1 -0
- package/assets/security-scan/tools-agil.json +87 -0
- package/assets/security-scan/tools.json +625 -0
- package/assets/skills-en/core/onboarding/SKILL.md +58 -0
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
- package/assets/skills-en/core/thread-state/SKILL.md +88 -0
- package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
- package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
- package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
- package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
- package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
- package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
- package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
- package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
- package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
- package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
- package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
- package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
- package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
- package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
- package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
- package/dist/adapters/claude-bg.js +123 -9
- package/dist/adapters/codex-controller-worker.js +12 -5
- package/dist/adapters/codex-events.js +16 -4
- package/dist/adapters/codex.js +3 -1
- package/dist/adapters/grok-events.js +227 -0
- package/dist/adapters/grok-mcp-servidor.js +612 -0
- package/dist/adapters/grok-mcp.js +178 -0
- package/dist/adapters/grok.js +686 -0
- package/dist/agendador-cpu.js +92 -0
- package/dist/atualizar-branch.js +245 -0
- package/dist/auditoria.js +13 -11
- package/dist/auditrun.js +51 -46
- package/dist/autorizacao-duravel.js +327 -0
- package/dist/board.js +94 -40
- package/dist/branch-de-estado.js +23 -10
- package/dist/busca-semantica.js +7 -5
- package/dist/catalogo.js +2 -1
- package/dist/changelog-reconciliacao.js +290 -0
- package/dist/check-agil.js +528 -0
- package/dist/check-modo.js +41 -0
- package/dist/check-paralelo.js +238 -0
- package/dist/ci.js +248 -45
- package/dist/ciclos.js +8 -6
- package/dist/claim-lint.js +12 -8
- package/dist/claims-conferir.js +47 -39
- package/dist/claims.js +10 -9
- package/dist/company-brain-client.js +10 -3
- package/dist/company-brain-migration.js +11 -5
- package/dist/conducao-batida.js +759 -0
- package/dist/conducao-sentinela.js +25 -8
- package/dist/conducao.js +89 -29
- package/dist/conhecimento-consulta.js +270 -0
- package/dist/conhecimento.js +111 -87
- package/dist/conta-esgotada.js +127 -0
- package/dist/dado-privado.js +816 -0
- package/dist/decisao-autonoma.js +5 -4
- package/dist/demo.js +14 -12
- package/dist/dependencias-da-worktree.js +25 -0
- package/dist/divida.js +38 -36
- package/dist/docs.js +89 -89
- package/dist/doctor-forja.js +343 -0
- package/dist/doctor-pulse-cron.js +113 -1
- package/dist/doctor.js +164 -6
- package/dist/dsn-da-memoria.js +417 -0
- package/dist/entrega-por-mod.js +503 -0
- package/dist/entrega-pr.js +154 -54
- package/dist/esgotamentos.js +13 -11
- package/dist/estado-thread.js +21 -18
- package/dist/evalrunner.js +35 -32
- package/dist/fabrica-batida.js +34 -21
- package/dist/fabrica-estado.js +33 -21
- package/dist/fix.js +21 -19
- package/dist/forja/adaptador.js +6 -0
- package/dist/forja/ambiente-de-ci.js +27 -0
- package/dist/forja/api.js +256 -0
- package/dist/forja/cache.js +89 -0
- package/dist/forja/cli.js +60 -0
- package/dist/forja/contrato.js +9 -0
- package/dist/forja/endereco.js +43 -0
- package/dist/forja/estado.js +22 -0
- package/dist/forja/executor.js +73 -0
- package/dist/forja/github/ci.js +95 -0
- package/dist/forja/github/dono-da-rede.js +18 -0
- package/dist/forja/github/metadados.js +15 -0
- package/dist/forja/github/pedidos.js +200 -0
- package/dist/forja/gitlab/ci.js +141 -0
- package/dist/forja/gitlab/consultas.js +59 -0
- package/dist/forja/gitlab/dono-da-rede.js +43 -0
- package/dist/forja/gitlab/metadados.js +15 -0
- package/dist/forja/gitlab/pedidos-abertos.js +158 -0
- package/dist/forja/gitlab/pedidos.js +141 -0
- package/dist/forja/produtor.js +32 -0
- package/dist/forja/registro.js +31 -0
- package/dist/forja/resolver.js +121 -0
- package/dist/forja/texto.js +13 -0
- package/dist/forja/versao.js +71 -0
- package/dist/forja.js +123 -80
- package/dist/handoff.js +23 -13
- package/dist/hitl-contract.js +46 -43
- package/dist/hitl-curto.js +37 -25
- package/dist/hitl-gates.js +13 -11
- package/dist/hitl-local-receipt.js +51 -0
- package/dist/hitl-local.js +11 -2
- package/dist/hitl-lock.js +5 -11
- package/dist/hitl-public-receipt.js +11 -0
- package/dist/hitl-resumo.js +44 -1
- package/dist/hitl-sessions.js +62 -9
- package/dist/hitl-texto-livre.js +7 -4
- package/dist/hitl.js +34 -31
- package/dist/horario.js +20 -1
- package/dist/hosts.js +104 -134
- package/dist/index.js +864 -554
- package/dist/indice-vetorial.js +14 -12
- package/dist/init.js +11 -2
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +123 -69
- package/dist/intelligence-graph-query.js +37 -22
- package/dist/leases.js +19 -18
- package/dist/ledger-stats.js +17 -16
- package/dist/ledger.js +31 -1
- package/dist/licoes.js +12 -11
- package/dist/locale-accounts.js +228 -0
- package/dist/locale-adapter.js +291 -0
- package/dist/locale-ajuda.js +86 -10
- package/dist/locale-audit.js +199 -0
- package/dist/locale-claims.js +213 -0
- package/dist/locale-conducao.js +138 -0
- package/dist/locale-conhecimento.js +181 -0
- package/dist/locale-decisao.js +205 -0
- package/dist/locale-docs.js +230 -0
- package/dist/locale-estado.js +101 -0
- package/dist/locale-forja.js +288 -0
- package/dist/locale-gerados.js +5 -0
- package/dist/locale-grafo.js +129 -0
- package/dist/locale-master.js +83 -0
- package/dist/locale-network.js +524 -0
- package/dist/locale-operacao-restante.js +931 -0
- package/dist/locale-projetos.js +100 -0
- package/dist/locale-prompts.js +194 -0
- package/dist/locale-pulse.js +140 -2
- package/dist/locale-reservas.js +87 -0
- package/dist/locale-retry.js +183 -6
- package/dist/locale-security-scan.js +69 -0
- package/dist/locale-setup.js +192 -0
- package/dist/locale-ship.js +177 -66
- package/dist/locale-thread.js +149 -5
- package/dist/locale-verify.js +80 -4
- package/dist/locale-worktree.js +246 -0
- package/dist/locale.js +553 -9
- package/dist/maestro-runtime.js +22 -3
- package/dist/manifest.js +293 -12
- package/dist/maquina-ociosa.js +211 -0
- package/dist/maquina.js +10 -5
- package/dist/master-nota-local.js +200 -0
- package/dist/master-nota.js +10 -2
- package/dist/master.js +118 -41
- package/dist/mcp-conhecimento.js +52 -0
- package/dist/mcp-experiencia.js +26 -5
- package/dist/mcp-install.js +90 -15
- package/dist/mcp-noctum.js +101 -0
- package/dist/mcp-server.js +116 -22
- package/dist/mcp-ship-transporte.js +977 -0
- package/dist/mcp-ship.js +68 -24
- package/dist/mcp-transportes.js +17 -0
- package/dist/memoria.js +63 -58
- package/dist/merge-da-entrega.js +85 -0
- package/dist/modos-migracao.js +8 -6
- package/dist/modos.js +17 -18
- package/dist/network-roadmap.js +94 -54
- package/dist/noctum-aceite.js +929 -0
- package/dist/noctum-arco.js +540 -33
- package/dist/noctum-capacidade.js +3 -3
- package/dist/noctum-changelog.js +399 -0
- package/dist/noctum-cli.js +539 -0
- package/dist/noctum-coordenacao.js +1225 -0
- package/dist/noctum-entrega.js +1217 -0
- package/dist/noctum-envelope.js +253 -17
- package/dist/noctum-execucao.js +100 -24
- package/dist/noctum-fechamento.js +416 -0
- package/dist/noctum-fila.js +49 -10
- package/dist/noctum-guarda.js +333 -0
- package/dist/noctum-integracao.js +507 -0
- package/dist/noctum-maquinas.js +387 -0
- package/dist/noctum-medicao.js +450 -0
- package/dist/noctum-modo.js +390 -0
- package/dist/noctum-pergunta-canal.js +96 -0
- package/dist/noctum-pergunta.js +115 -0
- package/dist/noctum-provas.js +838 -0
- package/dist/noctum-reconciliacao.js +594 -0
- package/dist/noctum-rede.js +102 -0
- package/dist/noctum-registro.js +215 -0
- package/dist/noctum-relatorio.js +861 -0
- package/dist/noctum-resposta.js +207 -0
- package/dist/noctum-retomada-rede.js +71 -0
- package/dist/noctum-sessoes-em-voo.js +93 -0
- package/dist/noctum-supervisao.js +649 -0
- package/dist/noctum-terminal.js +459 -0
- package/dist/noctum-transporte.js +655 -0
- package/dist/noctum-vigia.js +679 -0
- package/dist/ocupacao.js +3 -1
- package/dist/onboarding.js +16 -5
- package/dist/orkmind.js +39 -23
- package/dist/orquestracao.js +31 -35
- package/dist/parado-no-condutor.js +160 -139
- package/dist/phase.js +96 -42
- package/dist/policies.js +33 -0
- package/dist/postura-local.js +11 -6
- package/dist/preflight.js +2 -1
- package/dist/procedencia.js +9 -14
- package/dist/projeto-alvo.js +59 -20
- package/dist/prompts.js +136 -42
- package/dist/prova-minima.js +5 -6
- package/dist/pulse-cadencia.js +5 -4
- package/dist/pulse-consentimento.js +53 -1
- package/dist/pulse-delivery.js +143 -27
- package/dist/pulse-resposta.js +368 -4
- package/dist/pulse.js +136 -3
- package/dist/ratelimit.js +13 -4
- package/dist/recall.js +14 -13
- package/dist/rede-adesao.js +13 -8
- package/dist/rede-forja.js +108 -24
- package/dist/rede-status.js +63 -45
- package/dist/rede.js +86 -46
- package/dist/retomada-checkpoint.js +101 -0
- package/dist/retry.js +326 -78
- package/dist/roadmap-reservas.js +32 -32
- package/dist/runtime-ambiente.js +5 -0
- package/dist/runtime-context.js +279 -85
- package/dist/runtime-escada.js +429 -0
- package/dist/runtime-profiles.js +130 -63
- package/dist/runtimes.js +42 -5
- package/dist/saida-segura.js +3 -2
- package/dist/security-scan/agil.js +366 -0
- package/dist/security-scan/cli.js +76 -0
- package/dist/security-scan/compare.js +149 -0
- package/dist/security-scan/config.js +93 -0
- package/dist/security-scan/detect.js +97 -0
- package/dist/security-scan/executor.js +196 -0
- package/dist/security-scan/guard.js +180 -0
- package/dist/security-scan/imagem-de-lint.js +96 -0
- package/dist/security-scan/normalize/actionlint.js +12 -0
- package/dist/security-scan/normalize/eslint.js +12 -0
- package/dist/security-scan/normalize/gitleaks.js +13 -0
- package/dist/security-scan/normalize/golangci-lint.js +13 -0
- package/dist/security-scan/normalize/govulncheck.js +36 -0
- package/dist/security-scan/normalize/index.js +25 -0
- package/dist/security-scan/normalize/npm-audit.js +30 -0
- package/dist/security-scan/normalize/osv-scanner.js +32 -0
- package/dist/security-scan/normalize/oxlint.js +51 -0
- package/dist/security-scan/normalize/pip-audit.js +16 -0
- package/dist/security-scan/normalize/ruff.js +12 -0
- package/dist/security-scan/normalize/semgrep.js +20 -0
- package/dist/security-scan/normalize/trivy.js +33 -0
- package/dist/security-scan/normalize/util.js +204 -0
- package/dist/security-scan/normalize/zizmor.js +19 -0
- package/dist/security-scan/report.js +156 -0
- package/dist/security-scan/run.js +448 -0
- package/dist/security-scan/tools.js +62 -0
- package/dist/security-scan/trabalhador.js +74 -0
- package/dist/security-scan/types.js +15 -0
- package/dist/session-events.js +19 -2
- package/dist/session-watcher-claude.js +74 -19
- package/dist/session-watcher-grok.js +425 -0
- package/dist/session-watcher.js +174 -13
- package/dist/sessoes-contas.js +42 -5
- package/dist/sessoes-inventario.js +1 -1
- package/dist/sessoes.js +25 -23
- package/dist/setup.js +67 -66
- package/dist/ship-publicar.js +263 -92
- package/dist/ship.js +160 -17
- package/dist/superficie.js +14 -11
- package/dist/thread-close.js +9 -9
- package/dist/thread.js +121 -18
- package/dist/tokens.js +15 -11
- package/dist/trabalho-thread.js +297 -0
- package/dist/transporte-do-canal.js +189 -0
- package/dist/types.js +12 -1
- package/dist/util.js +5 -2
- package/dist/varredura-acoes.js +500 -0
- package/dist/verify.js +491 -32
- package/dist/worktree-local.js +12 -10
- package/dist/worktree.js +81 -85
- package/eval/casos/check-quality.json +77 -0
- package/eval/casos/security-auditor.json +148 -0
- package/eval/casos/security-remediation.json +161 -0
- package/eval/fixtures/security-scan/README.md +8 -0
- package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/go/Dockerfile +4 -0
- package/eval/fixtures/security-scan/go/README.md +4 -0
- package/eval/fixtures/security-scan/go/config.go +4 -0
- package/eval/fixtures/security-scan/go/go.mod +5 -0
- package/eval/fixtures/security-scan/go/go.sum +2 -0
- package/eval/fixtures/security-scan/go/main.go +31 -0
- package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/js/Dockerfile +3 -0
- package/eval/fixtures/security-scan/js/README.md +4 -0
- package/eval/fixtures/security-scan/js/package-lock.json +844 -0
- package/eval/fixtures/security-scan/js/package.json +10 -0
- package/eval/fixtures/security-scan/js/src/config.js +4 -0
- package/eval/fixtures/security-scan/js/src/server.js +17 -0
- package/eval/fixtures/security-scan/js/src/util.ts +4 -0
- package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
- package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/python/Dockerfile +3 -0
- package/eval/fixtures/security-scan/python/README.md +4 -0
- package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
- package/eval/fixtures/security-scan/python/app/config.py +2 -0
- package/eval/fixtures/security-scan/python/app/main.py +19 -0
- package/eval/fixtures/security-scan/python/requirements.txt +1 -0
- package/package.json +10 -5
- package/references/security-checklist.md +3 -3
- package/skills/README.md +1 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/check-quality/SKILL.md +16 -0
- package/skills/phases/go-implementation/SKILL.md +6 -0
- package/skills/phases/security-remediation/SKILL.md +70 -0
- package/skills/reviewers/security-auditor/SKILL.md +25 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// O painel do Mensageiro de Sessoes (RM-059, fatia F9), em funcoes puras: o estado vira linhas da tela, uma por
|
|
2
|
+
// elemento, e as linhas viram a arvore do painel com os elementos que a superficie resolveu (so `Box`, `Text` e
|
|
3
|
+
// `Button`, os mesmos no terminal e no desktop). Todo estado tem rotulo e glifo, nunca so cor (regra da Partitura).
|
|
4
|
+
// O texto da resposta do dono nunca aparece aqui: so a thread, o pedido e o estado da entrega. So importa tipos e
|
|
5
|
+
// modulos puros do Mensageiro.
|
|
6
|
+
import type { MensageiroDono, MensageiroEntrega, MensageiroEstadoDaEntrega, MensageiroEstadoDaRecebida, MensageiroFase, MensageiroMostrado,
|
|
7
|
+
MensageiroRecebida } from '../types'
|
|
8
|
+
import { umaLinha } from './caixa'
|
|
9
|
+
import { codigoDoMotivo, motivoLegivel } from './recepcao'
|
|
10
|
+
|
|
11
|
+
export type LinhaDoMensageiro = {
|
|
12
|
+
tipo: 'titulo' | 'secao' | 'texto' | 'dim' | 'falha' | 'feito'
|
|
13
|
+
chave: string
|
|
14
|
+
texto: string
|
|
15
|
+
/** O que vai ao registro do mostrado da ponte quando a linha esta na janela de rolagem do painel a vista. */
|
|
16
|
+
mostrado?: MensageiroMostrado
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const ROTULO_DO_ESTADO: Record<MensageiroEstadoDaEntrega, string> = {
|
|
20
|
+
'na-fila': 'na fila do núcleo',
|
|
21
|
+
'a-caminho': 'a caminho: na fila da sessão, esperando a conferência',
|
|
22
|
+
'reservada': 'recebida pela sessão, confirmando',
|
|
23
|
+
'sem-recibo': 'recebida pela sessão, sem recibo em 5 min: confira pelo claude attach',
|
|
24
|
+
'nao-chegou': 'não entrou na fila da sessão; nova tentativa em breve',
|
|
25
|
+
'desistiu': 'não chegou: responda pelo claude attach',
|
|
26
|
+
'entregue': 'entregue, com o recibo da sessão',
|
|
27
|
+
'saiu-da-caixa': 'saiu da caixa sem recibo: responda pelo claude attach',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const GLIFO: Record<MensageiroEstadoDaEntrega, string> = {
|
|
31
|
+
'na-fila': '·', 'a-caminho': '●', 'reservada': '●', 'sem-recibo': '?', 'nao-chegou': '×', 'desistiu': '×', 'entregue': '✓', 'saiu-da-caixa': '?',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const TIPO: Record<MensageiroEstadoDaEntrega, LinhaDoMensageiro['tipo']> = {
|
|
35
|
+
'na-fila': 'texto', 'a-caminho': 'texto', 'reservada': 'texto', 'sem-recibo': 'falha', 'nao-chegou': 'falha', 'desistiu': 'falha', 'entregue': 'feito', 'saiu-da-caixa': 'falha',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Quanto tempo faz, como o dono le. */
|
|
39
|
+
export function idade(ms: number): string {
|
|
40
|
+
if (!(ms >= 60000)) return 'agora'
|
|
41
|
+
const min = Math.floor(ms / 60000)
|
|
42
|
+
return min < 60 ? `há ${min} min` : `há ${Math.floor(min / 60)} h`
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const curto = (id: string) => id.slice(0, 8)
|
|
46
|
+
|
|
47
|
+
function linhasDaEntrega(e: MensageiroEntrega, agora: number): LinhaDoMensageiro[] {
|
|
48
|
+
const k = (s: string) => `${e.envioId}:${s}`
|
|
49
|
+
const envios = e.tentativas > 1 ? ` · ${e.tentativas} envios` : ''
|
|
50
|
+
const texto = `${GLIFO[e.estado]} ${e.thread} · pedido ${curto(e.pedidoId)} · ${ROTULO_DO_ESTADO[e.estado]}${envios} · ${idade(agora - e.em)}`
|
|
51
|
+
const linhas: LinhaDoMensageiro[] = [{ tipo: TIPO[e.estado], chave: k('estado'), texto: umaLinha(texto, 300),
|
|
52
|
+
mostrado: { chave: `hitl:${e.pedidoId}`, thread: e.thread, texto: `${e.thread}: resposta do dono ${ROTULO_DO_ESTADO[e.estado]}` } }]
|
|
53
|
+
if (e.motivo) linhas.push({ tipo: 'dim', chave: k('motivo'), texto: ` ${umaLinha(e.motivo, 200)}` })
|
|
54
|
+
return linhas
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** As linhas do painel na sessao do dono. */
|
|
58
|
+
export function linhasDoDono(dono: MensageiroDono, agora: number): LinhaDoMensageiro[] {
|
|
59
|
+
const linhas: LinhaDoMensageiro[] = [
|
|
60
|
+
{ tipo: 'titulo', chave: 'titulo', texto: 'Mensageiro de Sessões' },
|
|
61
|
+
{ tipo: 'dim', chave: 'o-que-faz', texto: 'Leva a resposta que você deu pelo diálogo à sessão de fase que parou esperando por ela.' },
|
|
62
|
+
]
|
|
63
|
+
if (dono.erro) linhas.push({ tipo: 'falha', chave: 'erro', texto: `× ${umaLinha(dono.erro, 200)}` })
|
|
64
|
+
linhas.push({ tipo: 'secao', chave: 'secao-entregas', texto: 'Respostas desta sessão' })
|
|
65
|
+
if (!dono.entregas.length) linhas.push({ tipo: 'dim', chave: 'sem-entregas', texto: ' nenhuma resposta a caminho agora' })
|
|
66
|
+
for (const e of [...dono.entregas].reverse()) linhas.push(...linhasDaEntrega(e, agora))
|
|
67
|
+
if (dono.incertas.length) {
|
|
68
|
+
// O retrato so diz que a entrega esta incerta (sem o runtime): ela pode seguir noutra sessao do dono ou noutro canal
|
|
69
|
+
// (um envio nativo pendente), ou ter se perdido com uma sessao que fechou. O painel nao sabe qual, e diz isso.
|
|
70
|
+
linhas.push({ tipo: 'secao', chave: 'secao-incertas', texto: 'Fora desta sessão' })
|
|
71
|
+
for (const i of dono.incertas) {
|
|
72
|
+
linhas.push({ tipo: 'texto', chave: `incerta:${i.pedidoId}`,
|
|
73
|
+
texto: `· ${i.thread} · pedido ${curto(i.pedidoId)} · entrega incerta fora desta sessão: noutra sessão do dono, noutro canal ou perdida` })
|
|
74
|
+
}
|
|
75
|
+
linhas.push({ tipo: 'dim', chave: 'incertas-limite', texto: ' sem retorno, responda pelo claude attach' })
|
|
76
|
+
}
|
|
77
|
+
linhas.push({ tipo: 'dim', chave: 'limite', texto: 'A resposta chega como mensagem de outra sessão: informa a sessão de fase, não autoriza ação que só você aprova. Para isso, claude attach.' })
|
|
78
|
+
if (dono.lidoEm === null) linhas.push({ tipo: 'dim', chave: 'lido', texto: 'a caixa de saída ainda não foi lida' })
|
|
79
|
+
else linhas.push({ tipo: 'dim', chave: 'lido', texto: `caixa de saída lida ${idade(agora - dono.lidoEm)}` })
|
|
80
|
+
return linhas
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const ROTULO_DA_RECEBIDA: Record<MensageiroEstadoDaRecebida, string> = {
|
|
84
|
+
'consumida': 'consumida antes do modelo',
|
|
85
|
+
'confirmando': 'entrou na conversa; gravando o recibo no núcleo',
|
|
86
|
+
'entregue': 'entrou na conversa, com o recibo no núcleo',
|
|
87
|
+
'sem-recibo': 'entrou na conversa, mas o recibo não foi gravado',
|
|
88
|
+
'nao-entrou': 'conferida, mas não entrou na conversa',
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const GLIFO_DA_RECEBIDA: Record<MensageiroEstadoDaRecebida, string> = {
|
|
92
|
+
'consumida': '○', 'confirmando': '●', 'entregue': '✓', 'sem-recibo': '?', 'nao-entrou': '×',
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const TIPO_DA_RECEBIDA: Record<MensageiroEstadoDaRecebida, LinhaDoMensageiro['tipo']> = {
|
|
96
|
+
'consumida': 'texto', 'confirmando': 'texto', 'entregue': 'feito', 'sem-recibo': 'falha', 'nao-entrou': 'falha',
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function linhasDaRecebida(r: MensageiroRecebida, i: number, agora: number): LinhaDoMensageiro[] {
|
|
100
|
+
const k = (s: string) => `recebida:${i}:${s}`
|
|
101
|
+
const quem = r.estado === 'consumida'
|
|
102
|
+
? `mensagem de outra sessão (${umaLinha(r.origem, 80)})${r.pedidoId ? ` com a marca do pedido ${curto(r.pedidoId)}` : ''}`
|
|
103
|
+
: `resposta do dono ao pedido ${r.pedidoId ? curto(r.pedidoId) : '?'}`
|
|
104
|
+
const linhas: LinhaDoMensageiro[] = [{ tipo: TIPO_DA_RECEBIDA[r.estado], chave: k('estado'),
|
|
105
|
+
texto: umaLinha(`${GLIFO_DA_RECEBIDA[r.estado]} ${quem} · ${ROTULO_DA_RECEBIDA[r.estado]} · ${idade(agora - r.em)}`, 300) }]
|
|
106
|
+
if (r.motivo) {
|
|
107
|
+
const motivo = r.estado === 'consumida' ? `${motivoLegivel(r.motivo)} · ${codigoDoMotivo(r.motivo)}` : r.motivo
|
|
108
|
+
linhas.push({ tipo: 'dim', chave: k('motivo'), texto: ` ${umaLinha(motivo, 200)}` })
|
|
109
|
+
}
|
|
110
|
+
return linhas
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* As linhas do painel na sessao de fase: o que chegou de outras sessoes, o mais novo primeiro. Sem botao: o estado so
|
|
115
|
+
* muda quando algo chega, e o painel se redesenha sozinho. O texto de nenhuma mensagem aparece aqui.
|
|
116
|
+
*/
|
|
117
|
+
export function linhasDaFase(fase: MensageiroFase, agora: number): LinhaDoMensageiro[] {
|
|
118
|
+
const linhas: LinhaDoMensageiro[] = [
|
|
119
|
+
{ tipo: 'secao', chave: 'titulo', texto: 'Mensageiro de Sessões' },
|
|
120
|
+
{ tipo: 'dim', chave: 'o-que-faz', texto: `Nesta sessão de fase${fase.thread ? ` da ${fase.thread}` : ''}, só entra na conversa a resposta do dono que o núcleo conferiu; o resto que chega de outra sessão é consumido.` },
|
|
121
|
+
]
|
|
122
|
+
if (fase.erro) linhas.push({ tipo: 'falha', chave: 'erro', texto: `× ${umaLinha(fase.erro, 200)}` })
|
|
123
|
+
linhas.push({ tipo: 'secao', chave: 'secao-recebidas', texto: 'O que chegou de outras sessões' })
|
|
124
|
+
if (!fase.recebidas.length) linhas.push({ tipo: 'dim', chave: 'sem-recebidas', texto: ' nada chegou de outra sessão' })
|
|
125
|
+
const recebidas = fase.recebidas.map((r, i) => ({ r, i })).reverse()
|
|
126
|
+
for (const { r, i } of recebidas) linhas.push(...linhasDaRecebida(r, i, agora))
|
|
127
|
+
linhas.push({ tipo: 'dim', chave: 'limite', texto: 'A resposta do dono informa esta sessão; ação que só o dono aprova continua pedindo o dono.' })
|
|
128
|
+
return linhas
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* O que esta inteiro dentro da janela de rolagem do painel: so isso conta como mostrado ao dono (M5). Toda linha do
|
|
133
|
+
* painel trunca numa linha da tela, e a do titulo divide a linha com o botao.
|
|
134
|
+
*/
|
|
135
|
+
export function mostradosVisiveis(linhas: readonly LinhaDoMensageiro[], janela: { offset: number; bodyRows: number } | undefined): MensageiroMostrado[] {
|
|
136
|
+
if (!janela || !(janela.bodyRows > 0)) return []
|
|
137
|
+
const fim = janela.offset + janela.bodyRows
|
|
138
|
+
return linhas.flatMap((l, i) => (l.mostrado && i >= janela.offset && i < fim ? [l.mostrado] : []))
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export type Gestos = { atualizar?: () => void }
|
|
142
|
+
|
|
143
|
+
/** A arvore do painel com os elementos que a superficie resolveu. */
|
|
144
|
+
export function desenharPainel(el: { Box: any; Text: any; Button: any }, linhas: readonly LinhaDoMensageiro[], gestos: Gestos) {
|
|
145
|
+
const { Box, Text, Button } = el
|
|
146
|
+
return (
|
|
147
|
+
<Box flexDirection="column">
|
|
148
|
+
{linhas.map(l => {
|
|
149
|
+
if (l.tipo === 'titulo') {
|
|
150
|
+
return (
|
|
151
|
+
<Box key="titulo" flexDirection="row">
|
|
152
|
+
<Text key="titulo-texto" bold wrap="truncate">{l.texto}</Text>
|
|
153
|
+
<Button key="atualizar" label="Atualizar" onPress={() => gestos.atualizar?.()} />
|
|
154
|
+
</Box>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
if (l.tipo === 'secao') return <Text key={l.chave} bold wrap="truncate">{l.texto}</Text>
|
|
158
|
+
if (l.tipo === 'falha') return <Text key={l.chave} color="error" wrap="truncate">{l.texto}</Text>
|
|
159
|
+
if (l.tipo === 'feito') return <Text key={l.chave} color="success" wrap="truncate">{l.texto}</Text>
|
|
160
|
+
if (l.tipo === 'dim') return <Text key={l.chave} dimColor wrap="truncate">{l.texto}</Text>
|
|
161
|
+
return <Text key={l.chave} wrap="truncate">{l.texto}</Text>
|
|
162
|
+
})}
|
|
163
|
+
</Box>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// O lado da sessao de fase do Mensageiro de Sessoes (RM-059, fatia F9, T9.3), em funcoes puras. Na sessao de fase,
|
|
2
|
+
// a mensagem que chega de outra sessao so entra na conversa do modelo depois que o nucleo confirma, pela
|
|
3
|
+
// `ork_session_inbox` do servidor preso ao despacho, que ela e a resposta do dono reservada para esta sessao, com o
|
|
4
|
+
// mesmo texto. O nome do plugin remetente (`origin.plugin`) e so o que o remetente declara: entra no registro, nunca
|
|
5
|
+
// na decisao. Nada daqui guarda o texto da mensagem no estado (D12 da thread ork-rm059mensag). So importa tipos e o
|
|
6
|
+
// modulo puro da caixa.
|
|
7
|
+
import type { MensageiroEstadoDaRecebida, MensageiroFase, MensageiroRecebida } from '../types'
|
|
8
|
+
import { CONTRATO_DA_ENTREGA, umaLinha } from './caixa'
|
|
9
|
+
|
|
10
|
+
/** A ferramenta da conferencia no receptor, so no servidor preso ao despacho (T9.1). */
|
|
11
|
+
export const FERRAMENTA_DA_CONFERENCIA = 'ork_session_inbox'
|
|
12
|
+
/** A maior mensagem que vai a conferencia, o mesmo teto do nucleo (`LIMITE_DA_MENSAGEM` de `entrega-por-mod.ts`). */
|
|
13
|
+
export const LIMITE_DA_MENSAGEM = 8192
|
|
14
|
+
export const MAXIMO_DE_RECEBIDAS = 30
|
|
15
|
+
/** O recibo que nao foi gravado volta nestas esperas; depois delas, a linha fica sem recibo. */
|
|
16
|
+
export const ESPERAS_DA_CONFIRMACAO_MS = [5000, 30000, 120000]
|
|
17
|
+
/**
|
|
18
|
+
* D21: o prazo que a conferencia leva ao nucleo (`ate`), bem antes do teto de 20 s da chamada no mod. O nucleo nao
|
|
19
|
+
* reserva depois dele: a conferencia atrasada nao deixa reserva sem ninguem para confirma-la.
|
|
20
|
+
*/
|
|
21
|
+
export const PRAZO_DA_CONFERENCIA_MS = 15000
|
|
22
|
+
export const FASE_VAZIA: MensageiroFase = { thread: null, recebidas: [], erro: null }
|
|
23
|
+
|
|
24
|
+
const UUID = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/
|
|
25
|
+
const objeto = (v: unknown): v is Record<string, any> => !!v && typeof v === 'object' && !Array.isArray(v)
|
|
26
|
+
const uuid = (v: unknown): v is string => typeof v === 'string' && UUID.test(v)
|
|
27
|
+
const curto = (id: string) => id.slice(0, 8)
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* As origens que nao trazem texto de outra sessao (G4, D22 da thread ork-rm059mensag): o Remote Control do dono
|
|
31
|
+
* (`bridge`), a notificacao de tarefa, o agendamento e o canal. A lista e fechada: tipo novo ou desconhecido conta
|
|
32
|
+
* como outra sessao ate entrar aqui.
|
|
33
|
+
*/
|
|
34
|
+
const EXTERNAS = ['bridge', 'task-notification', 'scheduled-trigger', 'slack-ping']
|
|
35
|
+
/** Entre a conversa principal e os agentes desta sessao: so com o `agentId` do agente de destino. */
|
|
36
|
+
const ENTRE_AGENTES = ['peer', 'coordinator']
|
|
37
|
+
|
|
38
|
+
export type ClasseDaOrigem = 'outra-sessao' | 'da-propria-sessao' | 'externa'
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Classifica uma entrega que chegou: externa (a lista fechada acima), da propria sessao (para um agente desta sessao,
|
|
42
|
+
* ou de teammate que o harness verificou) ou de outra sessao, que so entra confirmada pelo nucleo. Conta como outra
|
|
43
|
+
* sessao o mailbox que o harness nao verificou (`isVerified` diferente de `true`, D17: o despacho roda os teammates no
|
|
44
|
+
* mesmo processo, e ali a entrada sem verificacao e uma que nenhum membro mandou), `peer` e `coordinator` sem agente
|
|
45
|
+
* desta sessao como destino, inclusive a mensagem de um agente desta sessao para a conversa principal, que chega sem
|
|
46
|
+
* `agentId` e nao se distingue da de outra sessao (D22), e todo tipo desconhecido ou origem malformada.
|
|
47
|
+
*/
|
|
48
|
+
export function classificarOrigem(origem: unknown, agentId: unknown): ClasseDaOrigem {
|
|
49
|
+
const o = objeto(origem) ? origem : {}
|
|
50
|
+
if ('teammate' in o || 'isVerified' in o) return o.isVerified === true ? 'da-propria-sessao' : 'outra-sessao'
|
|
51
|
+
const kind = typeof o.kind === 'string' ? o.kind : ''
|
|
52
|
+
if (EXTERNAS.includes(kind)) return 'externa'
|
|
53
|
+
if (ENTRE_AGENTES.includes(kind) && typeof agentId === 'string' && agentId !== '') return 'da-propria-sessao'
|
|
54
|
+
return 'outra-sessao'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A origem para o registro e o painel, numa linha curta: o tipo e o plugin que o remetente diz ser. */
|
|
58
|
+
export function nomeDaOrigem(origem: unknown): string {
|
|
59
|
+
const o = objeto(origem) ? origem : {}
|
|
60
|
+
const kind = typeof o.kind === 'string' && /^[a-z-]{1,40}$/.test(o.kind) ? o.kind : 'desconhecida'
|
|
61
|
+
const plugin = typeof o.plugin === 'string' && /^[a-zA-Z0-9._-]{1,64}$/.test(o.plugin) ? `, plugin declarado ${o.plugin}` : ''
|
|
62
|
+
return `${kind}${'teammate' in o || 'isVerified' in o ? ' do mailbox' : ''}${plugin}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** O cabecalho que o nucleo compoe (`cabecalhoDaEntrega` de `entrega-por-mod.ts`), conferido pelo teste do nucleo. */
|
|
66
|
+
export function cabecalhoDaEntrega(pedidoId: string, envioId: string): string {
|
|
67
|
+
return `[${CONTRATO_DA_ENTREGA} pedido=${pedidoId} entrega=${envioId}] Resposta do dono à pergunta deste turno, conferida pelo núcleo do Orkastery:`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** O rotulo visual da entrega confirmada (`rotuloDaEntrega` do nucleo). */
|
|
71
|
+
export function rotuloDaEntrega(pedidoId: string): string {
|
|
72
|
+
return `Resposta do dono ao pedido ${curto(pedidoId)}, conferida pelo núcleo`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** A mensagem traz a marca da entrega do nucleo: so essa vai a conferencia (D13); quem decide e o nucleo. */
|
|
76
|
+
export function temMarca(texto: unknown): boolean {
|
|
77
|
+
return typeof texto === 'string' && texto.length <= LIMITE_DA_MENSAGEM && texto.includes(`[${CONTRATO_DA_ENTREGA} pedido=`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Os ids que a marca diz ter, sem conferir nada: so para o registro de quem chegou. */
|
|
81
|
+
export function idsDaMarca(texto: unknown): { pedidoId: string | null; envioId: string | null } {
|
|
82
|
+
const m = typeof texto === 'string' ? /\[ork\.session-delivery\/v1 pedido=([0-9a-f-]{36}) entrega=([0-9a-f-]{36})\]/.exec(texto) : null
|
|
83
|
+
return { pedidoId: m && uuid(m[1]) ? m[1] : null, envioId: m && uuid(m[2]) ? m[2] : null }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** O argumento do `conferir`, com o prazo (`ate`) contado do relogio da sessao. */
|
|
87
|
+
export function argsDaConferencia(thread: string, texto: string, agora: number): Record<string, unknown> {
|
|
88
|
+
return { threadId: thread, operacao: 'conferir', texto, ate: new Date(agora + PRAZO_DA_CONFERENCIA_MS).toISOString() }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function argsDaConfirmacao(thread: string, envioId: string, texto: string): Record<string, unknown> {
|
|
92
|
+
return { threadId: thread, operacao: 'confirmar', envioId, texto }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type Conferencia = { confirmada: true; pedidoId: string; envioId: string } | { confirmada: false; motivo: string }
|
|
96
|
+
|
|
97
|
+
/** A resposta do `conferir`: so `confirmada: true` com os dois ids passa; o resto e recusa, com o motivo do nucleo. */
|
|
98
|
+
export function lerConferencia(dados: unknown): Conferencia {
|
|
99
|
+
if (objeto(dados) && dados.confirmada === true && uuid(dados.pedidoId) && uuid(dados.envioId)) {
|
|
100
|
+
return { confirmada: true, pedidoId: dados.pedidoId, envioId: dados.envioId }
|
|
101
|
+
}
|
|
102
|
+
const motivo = objeto(dados) && dados.confirmada === false && typeof dados.motivo === 'string' && /^entrega\.[a-z-]{1,40}$/.test(dados.motivo)
|
|
103
|
+
? dados.motivo : 'entrega.fora-do-contrato'
|
|
104
|
+
return { confirmada: false, motivo }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** A resposta do `confirmar`: entregue com o recibo; a recusa do nucleo e definitiva; o resto volta a tentar. */
|
|
108
|
+
export function lerConfirmacao(dados: unknown): { ok: boolean; definitiva: boolean; motivo: string | null } {
|
|
109
|
+
if (objeto(dados) && dados.ok === true && dados.estado === 'entregue') return { ok: true, definitiva: true, motivo: null }
|
|
110
|
+
const recusada = objeto(dados) && dados.estado === 'recusada'
|
|
111
|
+
const motivo = objeto(dados) && typeof dados.motivo === 'string' ? dados.motivo
|
|
112
|
+
: objeto(dados) && typeof dados.estado === 'string' ? `o núcleo respondeu ${dados.estado}` : 'a confirmação respondeu fora do contrato'
|
|
113
|
+
return { ok: false, definitiva: recusada, motivo: umaLinha(motivo, 120) }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** O que cada motivo quer dizer, para o painel e para o registro. Os do nucleo sao os de `MotivoDoReceptor`. */
|
|
117
|
+
export const MOTIVO_LEGIVEL: Record<string, string> = {
|
|
118
|
+
'entrega.sem-marca': 'sem a marca da entrega do núcleo',
|
|
119
|
+
'entrega.grande': 'maior que qualquer entrega do núcleo',
|
|
120
|
+
'entrega.formato': 'fora do formato da entrega',
|
|
121
|
+
'entrega.despacho': 'o despacho desta sessão não confere no núcleo',
|
|
122
|
+
'entrega.desconhecida': 'o núcleo não tem essa entrega',
|
|
123
|
+
'entrega.outra-sessao': 'a entrega é de outra sessão',
|
|
124
|
+
'entrega.texto-diferente': 'o texto não é o da resposta do dono',
|
|
125
|
+
'entrega.respondida': 'o pedido já foi respondido',
|
|
126
|
+
'entrega.reservada': 'cópia de uma entrega que já entrou',
|
|
127
|
+
'entrega.turno-mudou': 'a sessão já saiu do turno do pedido',
|
|
128
|
+
'entrega.sem-reserva': 'a entrega não foi reservada por esta sessão',
|
|
129
|
+
'entrega.prazo': 'a conferência chegou ao núcleo depois do prazo',
|
|
130
|
+
'entrega.fora-do-contrato': 'a conferência respondeu fora do contrato',
|
|
131
|
+
'entrega.conferencia-falhou': 'a conferência no núcleo falhou',
|
|
132
|
+
'entrega.sem-ponte': 'a ponte do Orkastery não carregou nesta sessão',
|
|
133
|
+
'entrega.sem-papel': 'a ponte não disse o papel desta sessão',
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** O codigo de um motivo (`entrega.x`, ou `entrega.x: detalhe`). */
|
|
137
|
+
export function codigoDoMotivo(motivo: string): string {
|
|
138
|
+
const i = motivo.indexOf(': ')
|
|
139
|
+
return i < 0 ? motivo : motivo.slice(0, i)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** O motivo como o dono le, com o detalhe entre parenteses quando ha. */
|
|
143
|
+
export function motivoLegivel(motivo: string): string {
|
|
144
|
+
const codigo = codigoDoMotivo(motivo)
|
|
145
|
+
const base = MOTIVO_LEGIVEL[codigo]
|
|
146
|
+
if (!base) return umaLinha(motivo, 120)
|
|
147
|
+
return codigo === motivo ? base : `${base} (${umaLinha(motivo.slice(codigo.length + 2), 120)})`
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** O motivo que vai ao `{ consumed }`: o Claude Code o registra com o nome do plugin. */
|
|
151
|
+
export function motivoDoConsumo(motivo: string): string {
|
|
152
|
+
const codigo = codigoDoMotivo(motivo)
|
|
153
|
+
return `mensagem de outra sessão sem entrega confirmada pelo núcleo do Orkastery (${MOTIVO_LEGIVEL[codigo] ?? 'motivo desconhecido'}; ${umaLinha(codigo, 60)})`
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** A linha do transcript (dim, fora do modelo) para o que nao entrou na conversa como devia. */
|
|
157
|
+
export function registroDaRecebida(r: MensageiroRecebida): string | null {
|
|
158
|
+
const pedido = r.pedidoId ? curto(r.pedidoId) : null
|
|
159
|
+
if (r.estado === 'consumida') return `Mensageiro de Sessões: mensagem de outra sessão (${r.origem}) consumida antes do modelo: ${motivoLegivel(r.motivo ?? '')}.`
|
|
160
|
+
if (r.estado === 'nao-entrou') return `Mensageiro de Sessões: a resposta do dono ao pedido ${pedido}, conferida pelo núcleo, não entrou na conversa: ${r.motivo ?? 'consumida abaixo do Mensageiro'}.`
|
|
161
|
+
if (r.estado === 'sem-recibo') return `Mensageiro de Sessões: a resposta do dono ao pedido ${pedido} entrou na conversa, mas o recibo não foi gravado no núcleo (${r.motivo ?? 'sem motivo'}); a entrega segue incerta para o dono.`
|
|
162
|
+
return null
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** O remetente do envelope fixo com que o receptor entrega a resposta conferida ao modelo (D23). */
|
|
166
|
+
export const REMETENTE_DO_MENSAGEIRO = 'ork-mensageiro'
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* O texto que a sessao de fase le (D23): a mensagem que o nucleo conferiu, no envelope fixo do Mensageiro. O envelope
|
|
170
|
+
* que chegou sai inteiro, com os rotulos que o remetente escolhe (o nome da sessao, o plugin, o endereco), e o
|
|
171
|
+
* enquadramento de mensagem de outra sessao fica. O `from-plugin` vai no proprio envelope: sem ele, o motor
|
|
172
|
+
* acrescentaria o plugin que o remetente declara na apresentacao. Do remetente, nada passa deste gancho; o anexo de
|
|
173
|
+
* arquivo do `SendFile`, que o motor poe no envelope depois dos ganchos, e limite dito no guia.
|
|
174
|
+
*/
|
|
175
|
+
export function textoParaOModelo(mensagem: string): string {
|
|
176
|
+
return `<cross-session-message from="${REMETENTE_DO_MENSAGEIRO}" from-plugin="${REMETENTE_DO_MENSAGEIRO}">\n${mensagem}\n</cross-session-message>`
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export type DecisaoNaFalha = { acao: 'passa' } | { acao: 'conferida'; texto: string } | { acao: 'consome' }
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* O que o `.catch` do receptor faz quando o gancho falha antes de chamar `next` (D18): a entrega que nao e de outra
|
|
183
|
+
* sessao passa como chegou, como na sessao que nao e de fase; a de outra sessao que o nucleo ja confirmou e reservou
|
|
184
|
+
* (em voo) segue no envelope do Mensageiro, como no caminho normal; o resto e consumido. Papel desconhecido conta como
|
|
185
|
+
* fase.
|
|
186
|
+
*/
|
|
187
|
+
export function decisaoNaFalha(f: { origem: unknown; agentId: unknown; texto: unknown; papel: string | null;
|
|
188
|
+
emVoo: ReadonlyMap<string, string> }): DecisaoNaFalha {
|
|
189
|
+
if (classificarOrigem(f.origem, f.agentId) !== 'outra-sessao') return { acao: 'passa' }
|
|
190
|
+
if (f.papel !== null && f.papel !== 'fase') return { acao: 'passa' }
|
|
191
|
+
const conferida = typeof f.texto === 'string' ? f.emVoo.get(f.texto) : undefined
|
|
192
|
+
return conferida !== undefined ? { acao: 'conferida', texto: conferida } : { acao: 'consome' }
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Um valor de atributo do envelope do motor: uma linha so, sem aspas nem sinal de tag (o mesmo do nucleo). */
|
|
196
|
+
const VALOR_DE_LINHA = '[^"<>\\n\\r\\v\\f\\u0085\\u2028\\u2029]{1,200}'
|
|
197
|
+
/** O envelope do Claude Code na forma que o motor escreve, o mesmo que o nucleo aceita (`entrega-por-mod.ts`). */
|
|
198
|
+
const ENVELOPE_DO_MOTOR = new RegExp('^<cross-session-message' +
|
|
199
|
+
'(?: from="[^"<>\\s]{1,300}")?' +
|
|
200
|
+
'(?: from-session="[A-Za-z0-9_-]{1,80}")?' +
|
|
201
|
+
'(?: hop-chain="[0-9a-f]{24}(?:,[0-9a-f]{24}){0,31}")?' +
|
|
202
|
+
`(?: from-name="${VALOR_DE_LINHA}")?` +
|
|
203
|
+
'(?: from-mode="[A-Za-z-]{1,40}")?' +
|
|
204
|
+
`(?: from-plugin="${VALOR_DE_LINHA}")?` +
|
|
205
|
+
'>\\n([\\s\\S]*)\\n</cross-session-message>$')
|
|
206
|
+
|
|
207
|
+
/** A mensagem sem o envelope do motor, como a linha da conversa a mostra; o texto como veio quando nao ha envelope. */
|
|
208
|
+
export function mensagemSemEnvelope(texto: string): string | null {
|
|
209
|
+
const t = texto.replace(/\r\n?/g, '\n')
|
|
210
|
+
if (!t.startsWith('<')) return t
|
|
211
|
+
const m = ENVELOPE_DO_MOTOR.exec(t)
|
|
212
|
+
return m ? m[1] : null
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* A impressao do texto de uma mensagem (FNV-1a de 32 bits do texto normalizado, com o tamanho): so diz se a linha da
|
|
217
|
+
* conversa e a mensagem que o nucleo confirmou, sem guardar o texto (D12). Nao e prova: o que prova e a conferencia.
|
|
218
|
+
*/
|
|
219
|
+
export function impressaoDoTexto(texto: string): string {
|
|
220
|
+
const t = texto.replace(/\r\n?/g, '\n').replace(/\s+$/, '')
|
|
221
|
+
let h = 0x811c9dc5
|
|
222
|
+
for (let i = 0; i < t.length; i++) {
|
|
223
|
+
h ^= t.charCodeAt(i)
|
|
224
|
+
h = Math.imul(h, 0x01000193) >>> 0
|
|
225
|
+
}
|
|
226
|
+
return `${t.length.toString(16)}-${h.toString(16).padStart(8, '0')}`
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Guarda o que chegou, o mais novo por ultimo e com teto, sem o texto da mensagem. */
|
|
230
|
+
export function comRecebida(fase: MensageiroFase, r: MensageiroRecebida): MensageiroFase {
|
|
231
|
+
return { ...fase, recebidas: [...fase.recebidas, r].slice(-MAXIMO_DE_RECEBIDAS) }
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Muda a recebida de uma entrega confirmada (pelo `envioId`); sem ela, a fase fica como estava. */
|
|
235
|
+
export function mudarRecebida(fase: MensageiroFase, envioId: string, estado: MensageiroEstadoDaRecebida, motivo: string | null, em: number): MensageiroFase {
|
|
236
|
+
if (!fase.recebidas.some(r => r.envioId === envioId && r.estado !== 'consumida')) return fase
|
|
237
|
+
return { ...fase, recebidas: fase.recebidas.map(r => (r.envioId === envioId && r.estado !== 'consumida' ? { ...r, estado, motivo, em } : r)) }
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** As entregas que o nucleo confirmou nesta sessao, com a impressao do texto: so a linha de uma delas ganha o rotulo. */
|
|
241
|
+
export function confirmadasDaFase(fase: MensageiroFase | null | undefined): Map<string, string> {
|
|
242
|
+
return new Map((fase?.recebidas ?? []).flatMap(r =>
|
|
243
|
+
(r.envioId && r.impressao && r.estado !== 'consumida' && r.estado !== 'nao-entrou' ? [[r.envioId, r.impressao] as [string, string]] : [])))
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* O texto da linha da mensagem com o rotulo no lugar do cabecalho, so para a entrega que o nucleo confirmou nesta
|
|
248
|
+
* sessao e com o mesmo texto (a impressao); `null` deixa a linha como o Claude Code a desenha. So visual: o que fica
|
|
249
|
+
* guardado e o que o modelo le nao mudam.
|
|
250
|
+
*/
|
|
251
|
+
export function textoComRotulo(texto: unknown, confirmadas: ReadonlyMap<string, string>): string | null {
|
|
252
|
+
const { pedidoId, envioId } = idsDaMarca(texto)
|
|
253
|
+
if (typeof texto !== 'string' || !pedidoId || !envioId || confirmadas.get(envioId) !== impressaoDoTexto(texto)) return null
|
|
254
|
+
const cabecalho = `${cabecalhoDaEntrega(pedidoId, envioId)}\n`
|
|
255
|
+
return texto.startsWith(cabecalho) ? `${rotuloDaEntrega(pedidoId)}\n${texto.slice(cabecalho.length)}` : null
|
|
256
|
+
}
|