@orkastery/cli 0.2.0 → 0.3.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 (242) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +86 -65
  3. package/adapters/README.md +30 -15
  4. package/adapters/claude-code/.claude-plugin/plugin.json +11 -5
  5. package/adapters/claude-code/README.md +110 -8
  6. package/adapters/claude-code/commands/onboarding.md +21 -0
  7. package/adapters/claude-code/commands/ork.md +99 -27
  8. package/adapters/claude-code/hooks/hooks.json +6 -1
  9. package/adapters/claude-code/hooks/ork-sensor.js +66 -0
  10. package/adapters/codex/skills/ork/SKILL.md +57 -0
  11. package/adapters/hermes/README.md +163 -0
  12. package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
  13. package/adapters/hermes/bin/ork-brain.sh +4 -0
  14. package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
  15. package/adapters/hermes/bin/ork-maestro.sh +6 -0
  16. package/adapters/hermes/bin/ork-master-enviar.py +84 -0
  17. package/adapters/hermes/bin/ork-objective-message.sh +17 -0
  18. package/adapters/hermes/bin/ork-objective-status.sh +12 -0
  19. package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
  20. package/adapters/hermes/hermes.plugin.json +26 -4
  21. package/adapters/hermes/hitl-ingress/__init__.py +356 -0
  22. package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
  23. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
  24. package/adapters/openclaw/README.md +135 -26
  25. package/adapters/openclaw/bin/ork-brain.sh +4 -0
  26. package/adapters/openclaw/construir.sh +19 -0
  27. package/adapters/openclaw/dist/hitl-ingress.js +199 -0
  28. package/adapters/openclaw/dist/index.js +437 -0
  29. package/adapters/openclaw/openclaw.plugin.json +39 -134
  30. package/adapters/openclaw/package.json +26 -0
  31. package/adapters/openclaw/src/hitl-ingress.ts +180 -0
  32. package/adapters/openclaw/src/index.ts +458 -0
  33. package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
  34. package/adapters/openclaw/tsconfig.json +15 -0
  35. package/assets/docs/markdownlint-cli2.jsonc +22 -0
  36. package/assets/docs/padroes/documentacao-de-produto.md +133 -0
  37. package/assets/docs/padroes/roadmap-de-produto.md +98 -0
  38. package/assets/docs/produto/README.md +14 -0
  39. package/assets/docs/produto/_modelo-feature.md +59 -0
  40. package/assets/docs/roadmap/README.md +14 -0
  41. package/assets/docs/roadmap/_modelo-item.md +73 -0
  42. package/assets/orkmind-native-schema.json +32 -0
  43. package/assets/orkmind_bridge.py +357 -0
  44. package/assets/orkmind_fixture.py +67 -0
  45. package/assets/orkmind_prospective.py +138 -0
  46. package/assets/reference-tariffs-i07.json +23 -0
  47. package/dist/adapters/claude-bg.js +488 -39
  48. package/dist/adapters/codex-controller-sensor.js +449 -0
  49. package/dist/adapters/codex-controller-worker.js +361 -0
  50. package/dist/adapters/codex-controller.js +252 -0
  51. package/dist/adapters/codex-events.js +205 -0
  52. package/dist/adapters/codex-question.js +26 -0
  53. package/dist/adapters/codex-runner.js +133 -0
  54. package/dist/adapters/codex.js +394 -0
  55. package/dist/agents-md.js +84 -0
  56. package/dist/auditoria.js +11 -8
  57. package/dist/auditrun.js +5 -4
  58. package/dist/board.js +173 -22
  59. package/dist/branch-de-estado.js +136 -0
  60. package/dist/canarios-hitl.js +177 -0
  61. package/dist/canarios-i43.js +543 -0
  62. package/dist/canarios-pulse.js +147 -0
  63. package/dist/canarios-sensores.js +129 -0
  64. package/dist/canarios.js +111 -2
  65. package/dist/catalogo.js +9 -0
  66. package/dist/ci.js +216 -0
  67. package/dist/ciclos.js +2 -1
  68. package/dist/claim-lint.js +64 -0
  69. package/dist/claims.js +60 -0
  70. package/dist/company-brain-capture.js +195 -0
  71. package/dist/company-brain-cli.js +123 -0
  72. package/dist/company-brain-client.js +61 -0
  73. package/dist/company-brain-contract.js +166 -0
  74. package/dist/company-brain-journal.js +192 -0
  75. package/dist/company-brain-mcp.js +33 -0
  76. package/dist/company-brain-migration.js +60 -0
  77. package/dist/company-brain-source.js +177 -0
  78. package/dist/company-brain-worker.js +18 -0
  79. package/dist/conducao-texto.js +61 -0
  80. package/dist/conducao.js +876 -0
  81. package/dist/contrato-publico.js +39 -0
  82. package/dist/creation-operation-store.js +251 -0
  83. package/dist/creation-operation.js +148 -0
  84. package/dist/decisao-autonoma.js +183 -0
  85. package/dist/delegation.js +79 -0
  86. package/dist/demo.js +120 -0
  87. package/dist/docs.js +828 -0
  88. package/dist/doctor.js +183 -24
  89. package/dist/entrega-pr.js +117 -0
  90. package/dist/escopo-escrita.js +71 -0
  91. package/dist/estado-thread.js +222 -0
  92. package/dist/evalrunner.js +12 -0
  93. package/dist/fabrica-estado.js +329 -0
  94. package/dist/fabrica-publicar.js +76 -0
  95. package/dist/fix.js +21 -0
  96. package/dist/gates.js +55 -9
  97. package/dist/handoff.js +39 -23
  98. package/dist/hitl-canais.js +333 -0
  99. package/dist/hitl-classificacao.js +131 -0
  100. package/dist/hitl-contract.js +465 -0
  101. package/dist/hitl-estado.js +136 -0
  102. package/dist/hitl-gates.js +554 -0
  103. package/dist/hitl-ingress-receipt.js +382 -0
  104. package/dist/hitl-local-atestado.js +57 -0
  105. package/dist/hitl-local-receipt.js +328 -0
  106. package/dist/hitl-local.js +143 -0
  107. package/dist/hitl-lock.js +139 -0
  108. package/dist/hitl-lote.js +223 -0
  109. package/dist/hitl-native-offer.js +97 -0
  110. package/dist/hitl-native.js +65 -0
  111. package/dist/hitl-presentation.js +209 -0
  112. package/dist/hitl-public-receipt.js +176 -0
  113. package/dist/hitl-resumo.js +209 -0
  114. package/dist/hitl-sessions.js +475 -0
  115. package/dist/hitl.js +711 -0
  116. package/dist/horario.js +269 -0
  117. package/dist/hosts.js +198 -22
  118. package/dist/index.js +1736 -93
  119. package/dist/indice.js +99 -0
  120. package/dist/init.js +28 -3
  121. package/dist/integracoes-locais.js +17 -0
  122. package/dist/leases.js +65 -21
  123. package/dist/ledger-stats.js +272 -0
  124. package/dist/ledger.js +107 -2
  125. package/dist/licoes.js +215 -0
  126. package/dist/liveness.js +218 -0
  127. package/dist/maestro-actions.js +51 -0
  128. package/dist/maestro-authority.js +152 -0
  129. package/dist/maestro-cli.js +97 -0
  130. package/dist/maestro-contract.js +55 -0
  131. package/dist/maestro-discovery.js +132 -0
  132. package/dist/maestro-runtime.js +268 -0
  133. package/dist/maestro-snapshot.js +86 -0
  134. package/dist/maestro-sources.js +224 -0
  135. package/dist/manifest.js +165 -6
  136. package/dist/maquina.js +102 -0
  137. package/dist/master-audit.js +101 -0
  138. package/dist/master-batch.js +43 -0
  139. package/dist/master-digest.js +149 -0
  140. package/dist/master-migracao.js +155 -0
  141. package/dist/master.js +361 -77
  142. package/dist/mcp-artifacts.js +234 -0
  143. package/dist/mcp-git.js +433 -0
  144. package/dist/mcp-install.js +310 -0
  145. package/dist/mcp-maestro.js +25 -0
  146. package/dist/mcp-server.js +469 -0
  147. package/dist/mcp-ship.js +436 -0
  148. package/dist/mcp-verify.js +173 -0
  149. package/dist/memoria-humana.js +207 -0
  150. package/dist/memoria.js +314 -78
  151. package/dist/memory-migration.js +279 -0
  152. package/dist/memory-prospective.js +148 -0
  153. package/dist/modos-migracao.js +191 -0
  154. package/dist/modos.js +151 -15
  155. package/dist/monitor-lock.js +110 -0
  156. package/dist/objective.js +449 -0
  157. package/dist/ocupacao.js +267 -0
  158. package/dist/onboarding.js +303 -0
  159. package/dist/orkmind.js +389 -90
  160. package/dist/orquestracao.js +96 -69
  161. package/dist/phase.js +596 -150
  162. package/dist/playbook-capabilities.js +150 -0
  163. package/dist/playbook-contracts.js +188 -0
  164. package/dist/portfolio-context.js +61 -0
  165. package/dist/portfolio.js +180 -0
  166. package/dist/preflight.js +207 -0
  167. package/dist/process-audit.js +112 -0
  168. package/dist/project-state.js +93 -0
  169. package/dist/prompts.js +25 -5
  170. package/dist/prova-minima.js +112 -0
  171. package/dist/pulse-cadencia.js +163 -0
  172. package/dist/pulse-consentimento.js +260 -0
  173. package/dist/pulse-delivery.js +323 -0
  174. package/dist/pulse-resposta.js +542 -0
  175. package/dist/pulse.js +262 -0
  176. package/dist/ratelimit.js +35 -2
  177. package/dist/recall.js +80 -3
  178. package/dist/redacao-saida.js +45 -0
  179. package/dist/redacao-url.js +66 -0
  180. package/dist/retry.js +637 -115
  181. package/dist/roadmap-reservas.js +243 -0
  182. package/dist/runtime-ambiente.js +38 -0
  183. package/dist/runtime-context.js +215 -0
  184. package/dist/runtime-profiles.js +869 -0
  185. package/dist/runtimes.js +103 -0
  186. package/dist/sandbox.js +9 -0
  187. package/dist/session-events.js +203 -0
  188. package/dist/session-watcher-claude.js +637 -0
  189. package/dist/session-watcher.js +683 -0
  190. package/dist/sessoes-adopt.js +154 -0
  191. package/dist/sessoes-inventario.js +159 -0
  192. package/dist/sessoes.js +16 -35
  193. package/dist/setup.js +691 -0
  194. package/dist/ship.js +150 -15
  195. package/dist/slug.js +1 -1
  196. package/dist/thread-close.js +115 -0
  197. package/dist/thread.js +142 -28
  198. package/dist/tokens.js +1 -1
  199. package/dist/util.js +4 -2
  200. package/dist/verify-sandbox.js +265 -0
  201. package/dist/verify.js +270 -25
  202. package/dist/versao.js +60 -0
  203. package/dist/worktree.js +31 -2
  204. package/dist/write-activation.js +291 -0
  205. package/dist/yaml.js +2 -0
  206. package/eval/casos/onboarding.json +102 -0
  207. package/eval/casos/orkastery-bootstrap.json +35 -1
  208. package/eval/casos/scope-check-capability-map.json +45 -7
  209. package/eval/casos/ship-release.json +2 -2
  210. package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
  211. package/eval/fixtures/b2-master-log/caso.json +1 -1
  212. package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
  213. package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
  214. package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
  215. package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
  216. package/eval/fixtures/fx-codex-dry/caso.json +18 -0
  217. package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
  218. package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
  219. package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
  220. package/eval/fixtures/fx-happy/caso.json +6 -4
  221. package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
  222. package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
  223. package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
  224. package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
  225. package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
  226. package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
  227. package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
  228. package/eval/fixtures/fx-omnicanal/caso.json +17 -0
  229. package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
  230. package/monitor/company-brain.cjs +17 -0
  231. package/monitor/pulse-scope.cjs +45 -0
  232. package/monitor/pulse.cron +18 -0
  233. package/monitor/varredura-pulse.sh +27 -0
  234. package/package.json +25 -4
  235. package/schemas/claims.schema.json +25 -0
  236. package/schemas/company-brain.schema.json +1158 -0
  237. package/schemas/creation-operation.schema.json +365 -0
  238. package/schemas/maestro-snapshot.schema.json +2716 -0
  239. package/skills/core/onboarding/SKILL.md +50 -0
  240. package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
  241. package/skills/core/thread-state/SKILL.md +3 -1
  242. package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
@@ -0,0 +1,437 @@
1
+ /**
2
+ * Plugin Orkastery para OpenClaw, no formato de extensao 2026.7.1.
3
+ *
4
+ * Zero regra de negocio no host: cada tool monta um VETOR argv e chama o CLI
5
+ * `ork`. O parse da #TAG, a validacao de modo, gates e verificacao vivem no
6
+ * nucleo, com teste. Tool nova que precisa de logica e sinal de que a logica
7
+ * pertence ao `ork`.
8
+ */
9
+ import { registerHitlIngress } from './hitl-ingress.js';
10
+ import { execFile } from 'node:child_process';
11
+ import { defineToolPlugin } from 'openclaw/plugin-sdk/tool-plugin';
12
+ /**
13
+ * Renderizado pelo `ork adapter install openclaw` para o caminho absoluto do
14
+ * `ork` desta maquina. Se a copia nao passou pelo instalador, o placeholder
15
+ * sobrevive e o fallback abaixo usa ORK_BIN do ambiente ou o `ork` do PATH.
16
+ */
17
+ const ORK_RENDERIZADO = '{{ork_bin}}';
18
+ /**
19
+ * Abre-chaves duplo montado por concatenacao: o arquivo instalado nao pode
20
+ * conter o par literal fora do placeholder, porque a prova do pitfall 1 e o
21
+ * grep pelo par devolvendo 0 no dist renderizado.
22
+ */
23
+ const MARCA_DE_PLACEHOLDER = '{' + '{';
24
+ function resolverOrkBin() {
25
+ if (!ORK_RENDERIZADO.startsWith(MARCA_DE_PLACEHOLDER))
26
+ return ORK_RENDERIZADO;
27
+ const doAmbiente = process.env.ORK_BIN;
28
+ if (doAmbiente && doAmbiente.trim() !== '')
29
+ return doAmbiente;
30
+ return 'ork';
31
+ }
32
+ /** Limite generoso para saidas de board/ledger sem estourar o buffer padrao. */
33
+ const MAX_BUFFER = 16 * 1024 * 1024;
34
+ /**
35
+ * Roda o `ork` com argv em vetor (nunca string de shell: um pedido com espaco,
36
+ * aspas ou quebra de linha chega inteiro em --prompt). Devolve stdout+stderr
37
+ * como texto; exit diferente de zero vira texto prefixado, nunca excecao, para
38
+ * o agente ler o erro tipado do nucleo em vez de um stack trace do host.
39
+ */
40
+ async function rodarOrk(args, signal, entrada) {
41
+ const bin = resolverOrkBin();
42
+ const parentEnv = { ...process.env };
43
+ const hasPrivateHitlAuthority = Object.keys(parentEnv).some((name) => /^ORK_HITL_(?:INGRESS_KEY|NATIVE_KEY)/.test(name));
44
+ // O núcleo prepara recibos legados do ORK_HITL_ROOT confiável e deriva a raiz
45
+ // pública antes de sanitizar. Nenhum argumento do modelo chega ao helper.
46
+ let verifiers;
47
+ try {
48
+ verifiers = await new Promise((resolve, reject) => {
49
+ execFile(bin, ['receipt-verifiers', '--json'], { env: parentEnv, signal, timeout: 5000, maxBuffer: 4096 }, (error, stdout) => {
50
+ if (error)
51
+ return reject(error);
52
+ try {
53
+ const value = JSON.parse(stdout);
54
+ if (value !== null && value.schema !== 'ork.hitl-verifiers/v1')
55
+ throw Error('invalid');
56
+ if (hasPrivateHitlAuthority && (!value || !value.verifiers || !Object.keys(value.verifiers).length))
57
+ throw Error('missing');
58
+ resolve(value === null ? undefined : JSON.stringify(value));
59
+ }
60
+ catch (error) {
61
+ reject(error);
62
+ }
63
+ });
64
+ });
65
+ }
66
+ catch {
67
+ // Sem autoridade HITL não há segredo a transformar: comandos comuns seguem
68
+ // com o ambiente sanitizado. Com autoridade presente, falhamos fechado para
69
+ // nunca entregar ao executor uma sessão incapaz de verificar seus recibos.
70
+ if (hasPrivateHitlAuthority)
71
+ return '[ork recusou] hitl.receipt.verifiers-unavailable';
72
+ }
73
+ // Tools do modelo não herdam a autoridade da callback humana no mesmo host.
74
+ const env = Object.fromEntries(Object.entries(parentEnv).filter(([name]) => !name.startsWith('ORK_HITL_') && name !== 'ORK_RECEIPT_VERIFIERS'));
75
+ if (verifiers)
76
+ env.ORK_RECEIPT_VERIFIERS = verifiers;
77
+ // I-36 (D6): o adaptador declara o proprio canal de conducao. Descreve a porta, nao concede autoridade.
78
+ env.ORK_CANAL = 'openclaw';
79
+ return new Promise((resolve) => {
80
+ const filho = execFile(bin, args, { maxBuffer: MAX_BUFFER, signal, env }, (erro, stdout, stderr) => {
81
+ const partes = [stdout, stderr].map((t) => (t ?? '').trim()).filter((t) => t !== '');
82
+ const saida = partes.join('\n');
83
+ if (!erro) {
84
+ resolve(saida === '' ? 'ok (sem saida)' : saida);
85
+ return;
86
+ }
87
+ const codigo = typeof erro.code === 'string'
88
+ ? erro.code
89
+ : (erro.code ?? 'desconhecido');
90
+ if (codigo === 'ENOENT') {
91
+ resolve(`ork nao encontrado em "${bin}". Instale o adapter com ` +
92
+ '`ork adapter install openclaw` (que renderiza o caminho) ou exporte ORK_BIN.');
93
+ return;
94
+ }
95
+ resolve(`[ork saiu com ${String(codigo)}]\n${saida}`);
96
+ });
97
+ if (entrada !== undefined)
98
+ filho.stdin?.end(entrada);
99
+ });
100
+ }
101
+ /** Schema de objeto JSON com todas as propriedades obrigatorias. */
102
+ function schema(propriedades) {
103
+ return {
104
+ type: 'object',
105
+ properties: propriedades,
106
+ required: Object.keys(propriedades),
107
+ additionalProperties: false,
108
+ };
109
+ }
110
+ function texto(params, chave) {
111
+ const valor = params[chave];
112
+ if (typeof valor === 'string')
113
+ return valor;
114
+ return String(valor ?? '');
115
+ }
116
+ /** O gateway fornece o update original; o agente não pode sintetizar evidência humana. */
117
+ function argvDaResposta(p, alvo) {
118
+ const update = p.updateTelegram;
119
+ const callback = update?.callback_query;
120
+ const mensagem = callback?.message ?? update?.message;
121
+ const remetente = callback?.from ?? mensagem?.from;
122
+ const usuario = String(remetente?.id ?? '');
123
+ const chat = String(mensagem?.chat?.id ?? '');
124
+ const permitidos = (nome) => (process.env[nome] ?? '').split(',').map(v => v.trim()).filter(Boolean);
125
+ if (!usuario || !chat || remetente?.is_bot !== false || mensagem?.forward_origin ||
126
+ !permitidos('ORK_HITL_TELEGRAM_USERS').includes(usuario) ||
127
+ !permitidos('ORK_HITL_TELEGRAM_CHATS').includes(chat)) {
128
+ throw new Error('origem humana não autorizada pelo gateway');
129
+ }
130
+ const thread = texto(p, 'thread'), pedido = texto(p, 'pedido');
131
+ if (![thread, pedido].every(v => /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/.test(v))) {
132
+ throw new Error('thread ou pedido inválido');
133
+ }
134
+ let resposta, referencia;
135
+ if (callback) {
136
+ const prefixo = `ork:${thread}:${pedido}:`;
137
+ if (typeof callback.data !== 'string' || !callback.data.startsWith(prefixo)) {
138
+ throw new Error('callback não corresponde ao pedido');
139
+ }
140
+ resposta = callback.data.slice(prefixo.length);
141
+ if (!/^[1-9][0-9]?$/.test(String(resposta)))
142
+ throw new Error('opção inválida');
143
+ referencia = callback.id;
144
+ }
145
+ else {
146
+ const origem = mensagem?.reply_to_message?.text;
147
+ if (typeof origem !== 'string' || !origem.split('\n').includes(`ork-hitl ${thread} ${pedido}`)) {
148
+ throw new Error('responda à mensagem do pedido HITL');
149
+ }
150
+ resposta = mensagem.text;
151
+ referencia = mensagem.message_id;
152
+ }
153
+ if (typeof resposta !== 'string' || !resposta.trim() || resposta.length > 4096 ||
154
+ resposta.includes('\0') || !referencia)
155
+ throw new Error('resposta ou mensagem inválida');
156
+ return [alvo, 'answer', thread, pedido, '--resposta-stdin', '--por', `telegram:${usuario}`,
157
+ '--mensagem', `telegram:${chat}:${referencia}`, '--origem', 'telegram'];
158
+ }
159
+ const FERRAMENTAS = [
160
+ {
161
+ name: 'ork_maestro',
162
+ description: 'Ao receber a frase exata orkastery maestro, consulte o panorama somente leitura. Não cria thread. Apresente fontes, lacunas e HITL com recomendação e opções claras; horários para o dono vêm dos campos *Local (fuso do dono), nunca do ISO. Ação posterior exige operação autorizada e readback.',
163
+ parameters: { type: 'object', additionalProperties: false, properties: {
164
+ thread: { type: 'string' }, section: { type: 'string', enum: ['portfolio', 'demands', 'threads', 'sessions', 'blockers', 'leases', 'retries', 'hitl', 'ship', 'master', 'nextActions'] },
165
+ offset: { type: 'integer', minimum: 0, maximum: 100000 },
166
+ } },
167
+ argv: p => {
168
+ if (Object.keys(p).some(k => !['thread', 'section', 'offset'].includes(k)) ||
169
+ (p.thread !== undefined && (typeof p.thread !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/.test(p.thread))) ||
170
+ (p.section === undefined) !== (p.offset === undefined) ||
171
+ (p.offset !== undefined && (!Number.isSafeInteger(p.offset) || Number(p.offset) < 0 || Number(p.offset) > 100000)))
172
+ throw Error('maestro.arguments.invalid');
173
+ return ['maestro', '--json', ...(p.thread === undefined ? [] : ['--thread', String(p.thread)]),
174
+ ...(p.section === undefined ? [] : ['--section', String(p.section), '--offset', String(p.offset)])];
175
+ },
176
+ },
177
+ {
178
+ name: 'ork_onboarding',
179
+ description: 'Consulta a pauta do núcleo e registra respostas públicas. Credenciais somente como nomes de variáveis; valores ficam em ~/.hermes/.env. Sync publica opcionalmente e relata degradação.',
180
+ parameters: {
181
+ type: 'object', additionalProperties: false, required: ['acao'],
182
+ properties: {
183
+ acao: { type: 'string', enum: ['show', 'set', 'reset', 'sync'] },
184
+ etapa: { type: 'string', description: 'Etapa devolvida pela pauta do CLI; omita para reset total.' },
185
+ conteudo: { type: 'string', description: 'JSON público serializado; nunca valores secretos.' },
186
+ por: { type: 'string', description: 'Autoria da resposta; omitido usa owner.' },
187
+ },
188
+ },
189
+ argv: (p) => ['onboarding', texto(p, 'acao'),
190
+ ...(p.etapa === undefined ? [] : [texto(p, 'etapa')]),
191
+ ...(p.conteudo === undefined ? [] : ['--conteudo', texto(p, 'conteudo')]),
192
+ ...(p.por === undefined ? [] : ['--por', texto(p, 'por')]), '--json'],
193
+ },
194
+ {
195
+ name: 'ork_doctor',
196
+ description: 'O que vale nesta maquina agora: runtime, assinatura, provider de custo. Sai diferente de zero quando o despacho nao vale.',
197
+ parameters: schema({}),
198
+ argv: () => ['doctor'],
199
+ },
200
+ {
201
+ name: 'ork_modo_do_pedido',
202
+ description: 'Le a #TAG de conducao do pedido do builder (#Classic, #Maestro, #Auto, #Fast) e devolve o modo. #TAG aposentada (#Look, #Ork) recebe recusa tipada modo.aposentado, com saida != 0, em vez de virar o default em silencio. Sem tag, devolve o conduction.default_mode do manifesto. Use SEMPRE este tool em vez de reconhecer a tag no host.',
203
+ parameters: schema({
204
+ pedido: { type: 'string', description: 'O texto inteiro do pedido do builder' },
205
+ }),
206
+ argv: (p) => ['modos', '--do-pedido', texto(p, 'pedido'), '--json'],
207
+ },
208
+ {
209
+ name: 'ork_thread_new',
210
+ description: 'Cria a thread, o slug de 3 partes e o ledger. O modo vem de ork_modo_do_pedido; o nucleo valida contra conduction.allowed_modes e recusa o que o projeto nao permite.',
211
+ parameters: schema({
212
+ nome: { type: 'string', description: 'Nome curto da demanda' },
213
+ modo: {
214
+ type: 'string',
215
+ description: 'classic|maestro|auto|fast, vindo de ork_modo_do_pedido',
216
+ },
217
+ }),
218
+ argv: (p) => [
219
+ 'thread',
220
+ 'new',
221
+ texto(p, 'nome'),
222
+ '--mode',
223
+ texto(p, 'modo'),
224
+ '--worktree',
225
+ 'auto',
226
+ ],
227
+ },
228
+ {
229
+ name: 'ork_thread_status',
230
+ description: 'Estado da thread lido do disco e cruzado com o runtime real.',
231
+ parameters: schema({ thread: { type: 'string' } }),
232
+ argv: (p) => ['thread', 'status', texto(p, 'thread')],
233
+ },
234
+ {
235
+ name: 'ork_phase_run',
236
+ description: 'Despacha uma fase (GOAL PLAN GO CHECK SHIP MASTER) pelo runtime adapter, gravando o prompt exato com sha256 no ledger.',
237
+ parameters: schema({
238
+ thread: { type: 'string' },
239
+ fase: { type: 'string', enum: ['GOAL', 'PLAN', 'GO', 'CHECK', 'SHIP', 'MASTER'] },
240
+ prompt: { type: 'string', description: 'O pedido do builder para esta fase' },
241
+ }),
242
+ argv: (p) => [
243
+ 'phase',
244
+ 'run',
245
+ texto(p, 'thread'),
246
+ texto(p, 'fase'),
247
+ '--prompt',
248
+ texto(p, 'prompt'),
249
+ ],
250
+ },
251
+ {
252
+ name: 'ork_phase_list',
253
+ description: 'O ledger da thread, evento a evento, com quem decidiu e a evidencia.',
254
+ parameters: schema({ thread: { type: 'string' } }),
255
+ argv: (p) => ['phase', 'list', texto(p, 'thread')],
256
+ },
257
+ {
258
+ name: 'ork_objective_status',
259
+ description: 'Retoma no canal o mesmo ticket canônico e histórico vistos no Kanban.',
260
+ parameters: schema({ objective: { type: 'string', description: 'ID obj-* do ticket' } }),
261
+ argv: (p) => ['objective', 'status', texto(p, 'objective'), '--json'],
262
+ },
263
+ {
264
+ name: 'ork_objective_message',
265
+ description: 'Preserva no ticket uma mensagem recebida pelo canal autenticado. Não aprova gates.',
266
+ parameters: schema({
267
+ objective: { type: 'string', description: 'ID obj-* do ticket' },
268
+ author: { type: 'string', description: 'Identidade fornecida pelo gateway autenticado' },
269
+ message: { type: 'string', description: 'Texto integral recebido do dono' },
270
+ }),
271
+ argv: (p) => [
272
+ 'objective', 'message', texto(p, 'objective'),
273
+ '--text', texto(p, 'message'), '--por', texto(p, 'author'), '--role', 'human',
274
+ ],
275
+ },
276
+ {
277
+ name: 'ork_portfolio_list',
278
+ description: 'Lista produtos, projetos e iniciativas do catálogo canônico usado pelo Kanban.',
279
+ parameters: schema({}),
280
+ argv: () => ['portfolio', 'list', '--json'],
281
+ },
282
+ {
283
+ name: 'ork_brain_status',
284
+ description: 'Confere contrato, disponibilidade e tenant do Company Brain sem aceitar identidade ou DSN nos argumentos.',
285
+ parameters: schema({ thread: { type: 'string' } }),
286
+ argv: (p) => ['brain', 'status', '--thread', texto(p, 'thread')],
287
+ },
288
+ {
289
+ name: 'ork_brain_query',
290
+ description: 'Consulta a ontologia do Company Brain pela identidade autenticada no transporte.',
291
+ parameters: schema({
292
+ thread: { type: 'string' },
293
+ kinds: { type: 'string', description: 'prod,proj,init,assertion' },
294
+ }),
295
+ argv: (p) => ['brain', 'query', '--thread', texto(p, 'thread'), '--kinds', texto(p, 'kinds'), '--limit', '50'],
296
+ },
297
+ {
298
+ name: 'ork_brain_get',
299
+ description: 'Lê uma entidade exata do Company Brain; ausência e retenção permanecem explícitas.',
300
+ parameters: schema({ thread: { type: 'string' }, id: { type: 'string' } }),
301
+ argv: (p) => ['brain', 'get', texto(p, 'id'), '--thread', texto(p, 'thread')],
302
+ },
303
+ {
304
+ name: 'ork_claims_add',
305
+ description: 'Registra uma alegacao verificavel com o comando que a comprova. Toda citacao de arquivo ou teste vira claim.',
306
+ parameters: schema({
307
+ thread: { type: 'string' },
308
+ arquivo: { type: 'string' },
309
+ alegacao: { type: 'string' },
310
+ comando: { type: 'string' },
311
+ }),
312
+ argv: (p) => [
313
+ 'claims',
314
+ 'add',
315
+ texto(p, 'thread'),
316
+ texto(p, 'arquivo'),
317
+ '--claim',
318
+ texto(p, 'alegacao'),
319
+ '--verificar',
320
+ texto(p, 'comando'),
321
+ ],
322
+ },
323
+ {
324
+ name: 'ork_verify',
325
+ description: 'Reexecuta claims e comandos do manifesto no HEAD real e compara com a baseline. Passagem relatada nao e passagem.',
326
+ parameters: schema({ thread: { type: 'string' } }),
327
+ argv: (p) => ['verify', texto(p, 'thread')],
328
+ },
329
+ {
330
+ name: 'ork_verify_baseline',
331
+ description: 'Grava a baseline: o estado do mundo ANTES do GO, que separa regressao de divida pre-existente.',
332
+ parameters: schema({ thread: { type: 'string' } }),
333
+ argv: (p) => ['verify', texto(p, 'thread'), '--baseline'],
334
+ },
335
+ {
336
+ name: 'ork_worktree_ensure',
337
+ description: 'Garante a worktree isolada da thread, com a base resolvida pelo nucleo.',
338
+ parameters: schema({ thread: { type: 'string' } }),
339
+ argv: (p) => ['worktree', 'ensure', texto(p, 'thread')],
340
+ },
341
+ {
342
+ name: 'ork_worktree_audit',
343
+ description: 'Confere a worktree no proprio git. Sai diferente de zero quando ela divergiu ou a base avancou.',
344
+ parameters: schema({ thread: { type: 'string' } }),
345
+ argv: (p) => ['worktree', 'audit', texto(p, 'thread')],
346
+ },
347
+ ...['gate', 'sessions'].map((alvo) => ({
348
+ name: alvo === 'gate' ? 'ork_gate_answer' : 'ork_session_answer',
349
+ description: 'Transporta uma resposta humana do Telegram ao pedido HITL correlacionado. Use o update original do gateway autenticado; nunca crie update em nome do builder. O núcleo verifica modo, prazo e idempotência.',
350
+ parameters: schema({
351
+ thread: { type: 'string' },
352
+ pedido: { type: 'string' },
353
+ updateTelegram: { type: 'object', description: 'Update original recebido pelo gateway Telegram autenticado' },
354
+ }),
355
+ argv: p => argvDaResposta(p, alvo),
356
+ entrada: p => {
357
+ const update = p.updateTelegram;
358
+ return update.callback_query ? update.callback_query.data.split(':').at(-1) : update.message.text;
359
+ },
360
+ })),
361
+ {
362
+ name: 'ork_ship',
363
+ description: 'Merge serializado por lease e push PROVADO comparando o sha local com o que o remoto reporta.',
364
+ parameters: schema({
365
+ thread: { type: 'string' },
366
+ base: { type: 'string' },
367
+ quem: { type: 'string' },
368
+ }),
369
+ argv: (p) => [
370
+ 'ship',
371
+ texto(p, 'thread'),
372
+ '--para',
373
+ texto(p, 'base'),
374
+ '--autorizar-push',
375
+ texto(p, 'quem'),
376
+ ],
377
+ },
378
+ {
379
+ name: 'ork_master',
380
+ description: 'Fecha a thread: POSTMORTEM tipado, MASTER log no contrato congelado e o score HUMANO de 0 a 5 com justificativa. Nunca invente a nota.',
381
+ parameters: schema({
382
+ thread: { type: 'string' },
383
+ score: { type: 'string', description: 'inteiro de 0 a 5, dado pelo humano' },
384
+ justificativa: { type: 'string' },
385
+ quem: { type: 'string' },
386
+ }),
387
+ argv: (p) => [
388
+ 'master',
389
+ texto(p, 'thread'),
390
+ '--score',
391
+ texto(p, 'score'),
392
+ '--justificativa',
393
+ texto(p, 'justificativa'),
394
+ '--por',
395
+ texto(p, 'quem'),
396
+ ],
397
+ },
398
+ {
399
+ name: 'ork_board',
400
+ description: 'Todas as threads em uma visao, e o escalonador dizendo quem avanca agora e quem espera.',
401
+ parameters: schema({}),
402
+ argv: () => ['board', 'plan'],
403
+ },
404
+ {
405
+ name: 'ork_master_batch',
406
+ description: 'A fila de score dos modos sem pausa de MASTER. Fila que ninguem passa e score que nao existe.',
407
+ parameters: schema({}),
408
+ argv: () => ['master', '--batch'],
409
+ },
410
+ ];
411
+ const plugin = defineToolPlugin({
412
+ id: 'orkastery',
413
+ name: 'Orkastery',
414
+ description: 'Conducao de looping threads em 6 fases pelo nucleo `ork`, exposta ao OpenClaw como tools `ork_*`. Zero regra de negocio no host: cada tool e uma chamada de CLI.',
415
+ tools: (tool) => FERRAMENTAS.map((f) => tool({
416
+ name: f.name,
417
+ description: f.description,
418
+ parameters: f.parameters,
419
+ execute: (params, _config, contexto) => {
420
+ try {
421
+ return rodarOrk(f.argv(params), contexto.signal, f.entrada?.(params));
422
+ }
423
+ catch {
424
+ return '[ork recusou] resposta humana não confirmada; confira origem e correlação do pedido';
425
+ }
426
+ },
427
+ })),
428
+ });
429
+ // Preserve SDK metadata and its tool registration; add only a native ingress hook.
430
+ const entry = plugin;
431
+ const registerTools = entry.register;
432
+ entry.register = (api) => {
433
+ const result = registerTools?.(api);
434
+ registerHitlIngress(api, resolverOrkBin());
435
+ return result;
436
+ };
437
+ export default plugin;
@@ -1,138 +1,43 @@
1
1
  {
2
- "name": "orkastery",
3
- "displayName": "Orkastery",
4
- "version": "{{versao}}",
2
+ "id": "orkastery",
3
+ "name": "Orkastery",
5
4
  "description": "Conducao de looping threads em 6 fases pelo nucleo `ork`, exposta ao OpenClaw como tools `ork_*`. Zero regra de negocio no host: cada tool e uma chamada de CLI.",
6
- "license": "MIT",
7
- "runtime": { "type": "cli", "command": "{{ork_bin}}" },
8
- "conduction": {
9
- "tags": ["#Look", "#Ork", "#Classic", "#Maestro", "#Auto"],
10
- "parse": "ork_modo_do_pedido",
11
- "nota": "O host transporta a tag. A validacao contra conduction.allowed_modes e do nucleo, no ork thread new."
5
+ "version": "0.3.0",
6
+ "configSchema": {
7
+ "type": "object",
8
+ "properties": {},
9
+ "additionalProperties": false
12
10
  },
13
- "tools": [
14
- {
15
- "name": "ork_doctor",
16
- "description": "O que vale nesta maquina agora: runtime, assinatura, provider de custo. Sai diferente de zero quando o despacho nao vale.",
17
- "command": ["{{ork_bin}}", "doctor"],
18
- "parameters": {}
19
- },
20
- {
21
- "name": "ork_modo_do_pedido",
22
- "description": "Le a #TAG de conducao do pedido do builder (#Look, #Ork, #Classic, #Maestro, #Auto) e devolve o modo. Sem tag, devolve o conduction.default_mode do manifesto. Use SEMPRE este tool em vez de reconhecer a tag no host.",
23
- "command": ["{{ork_bin}}", "modos", "--do-pedido", "{pedido}", "--json"],
24
- "parameters": {
25
- "pedido": { "type": "string", "required": true, "description": "O texto inteiro do pedido do builder" }
26
- }
27
- },
28
- {
29
- "name": "ork_thread_new",
30
- "description": "Cria a thread, o slug de 3 partes e o ledger. O modo vem de ork_modo_do_pedido; o nucleo valida contra conduction.allowed_modes e recusa o que o projeto nao permite.",
31
- "command": ["{{ork_bin}}", "thread", "new", "{nome}", "--mode", "{modo}", "--worktree", "auto"],
32
- "parameters": {
33
- "nome": { "type": "string", "required": true, "description": "Nome curto da demanda" },
34
- "modo": { "type": "string", "required": true, "description": "look|default|ork|maestro|auto, vindo de ork_modo_do_pedido" }
35
- }
36
- },
37
- {
38
- "name": "ork_thread_status",
39
- "description": "Estado da thread lido do disco e cruzado com o runtime real.",
40
- "command": ["{{ork_bin}}", "thread", "status", "{thread}"],
41
- "parameters": { "thread": { "type": "string", "required": true } }
42
- },
43
- {
44
- "name": "ork_phase_run",
45
- "description": "Despacha uma fase (GOAL PLAN GO CHECK SHIP MASTER) pelo runtime adapter, gravando o prompt exato com sha256 no ledger.",
46
- "command": ["{{ork_bin}}", "phase", "run", "{thread}", "{fase}", "--prompt", "{prompt}"],
47
- "parameters": {
48
- "thread": { "type": "string", "required": true },
49
- "fase": { "type": "string", "required": true, "enum": ["GOAL", "PLAN", "GO", "CHECK", "SHIP", "MASTER"] },
50
- "prompt": { "type": "string", "required": true, "description": "O pedido do builder para esta fase" }
51
- }
52
- },
53
- {
54
- "name": "ork_phase_list",
55
- "description": "O ledger da thread, evento a evento, com quem decidiu e a evidencia.",
56
- "command": ["{{ork_bin}}", "phase", "list", "{thread}"],
57
- "parameters": { "thread": { "type": "string", "required": true } }
58
- },
59
- {
60
- "name": "ork_claims_add",
61
- "description": "Registra uma alegacao verificavel com o comando que a comprova. Toda citacao de arquivo ou teste vira claim.",
62
- "command": ["{{ork_bin}}", "claims", "add", "{thread}", "{arquivo}", "--claim", "{alegacao}", "--verificar", "{comando}"],
63
- "parameters": {
64
- "thread": { "type": "string", "required": true },
65
- "arquivo": { "type": "string", "required": true },
66
- "alegacao": { "type": "string", "required": true },
67
- "comando": { "type": "string", "required": true }
68
- }
69
- },
70
- {
71
- "name": "ork_verify",
72
- "description": "Reexecuta claims e comandos do manifesto no HEAD real e compara com a baseline. Passagem relatada nao e passagem.",
73
- "command": ["{{ork_bin}}", "verify", "{thread}"],
74
- "parameters": { "thread": { "type": "string", "required": true } }
75
- },
76
- {
77
- "name": "ork_verify_baseline",
78
- "description": "Grava a baseline: o estado do mundo ANTES do GO, que separa regressao de divida pre-existente.",
79
- "command": ["{{ork_bin}}", "verify", "{thread}", "--baseline"],
80
- "parameters": { "thread": { "type": "string", "required": true } }
81
- },
82
- {
83
- "name": "ork_worktree_ensure",
84
- "description": "Garante a worktree isolada da thread, com a base resolvida pelo nucleo.",
85
- "command": ["{{ork_bin}}", "worktree", "ensure", "{thread}"],
86
- "parameters": { "thread": { "type": "string", "required": true } }
87
- },
88
- {
89
- "name": "ork_worktree_audit",
90
- "description": "Confere a worktree no proprio git. Sai diferente de zero quando ela divergiu ou a base avancou.",
91
- "command": ["{{ork_bin}}", "worktree", "audit", "{thread}"],
92
- "parameters": { "thread": { "type": "string", "required": true } }
93
- },
94
- {
95
- "name": "ork_gate_approve",
96
- "description": "Registra no ledger a autorizacao humana de um gate (objetivo, premissas, evidencias, push, score).",
97
- "command": ["{{ork_bin}}", "gate", "approve", "{thread}", "{sobre}", "--por", "{quem}"],
98
- "parameters": {
99
- "thread": { "type": "string", "required": true },
100
- "sobre": { "type": "string", "required": true },
101
- "quem": { "type": "string", "required": true }
102
- }
103
- },
104
- {
105
- "name": "ork_ship",
106
- "description": "Merge serializado por lease e push PROVADO comparando o sha local com o que o remoto reporta.",
107
- "command": ["{{ork_bin}}", "ship", "{thread}", "--para", "{base}", "--autorizar-push", "{quem}"],
108
- "parameters": {
109
- "thread": { "type": "string", "required": true },
110
- "base": { "type": "string", "required": true },
111
- "quem": { "type": "string", "required": true }
112
- }
113
- },
114
- {
115
- "name": "ork_master",
116
- "description": "Fecha a thread: POSTMORTEM tipado, MASTER log no contrato congelado e o score HUMANO de 0 a 5 com justificativa. Nunca invente a nota.",
117
- "command": ["{{ork_bin}}", "master", "{thread}", "--score", "{score}", "--justificativa", "{justificativa}", "--por", "{quem}"],
118
- "parameters": {
119
- "thread": { "type": "string", "required": true },
120
- "score": { "type": "string", "required": true, "description": "inteiro de 0 a 5, dado pelo humano" },
121
- "justificativa": { "type": "string", "required": true },
122
- "quem": { "type": "string", "required": true }
123
- }
124
- },
125
- {
126
- "name": "ork_board",
127
- "description": "Todas as threads em uma visao, e o escalonador dizendo quem avanca agora e quem espera.",
128
- "command": ["{{ork_bin}}", "board", "plan"],
129
- "parameters": {}
130
- },
131
- {
132
- "name": "ork_master_batch",
133
- "description": "A fila de score dos modos sem pausa de MASTER. Fila que ninguem passa e score que nao existe.",
134
- "command": ["{{ork_bin}}", "master", "--batch"],
135
- "parameters": {}
136
- }
137
- ]
11
+ "activation": {
12
+ "onStartup": true
13
+ },
14
+ "contracts": {
15
+ "tools": [
16
+ "ork_maestro",
17
+ "ork_onboarding",
18
+ "ork_doctor",
19
+ "ork_modo_do_pedido",
20
+ "ork_thread_new",
21
+ "ork_thread_status",
22
+ "ork_phase_run",
23
+ "ork_phase_list",
24
+ "ork_objective_status",
25
+ "ork_objective_message",
26
+ "ork_portfolio_list",
27
+ "ork_brain_status",
28
+ "ork_brain_query",
29
+ "ork_brain_get",
30
+ "ork_claims_add",
31
+ "ork_verify",
32
+ "ork_verify_baseline",
33
+ "ork_worktree_ensure",
34
+ "ork_worktree_audit",
35
+ "ork_gate_answer",
36
+ "ork_session_answer",
37
+ "ork_ship",
38
+ "ork_master",
39
+ "ork_board",
40
+ "ork_master_batch"
41
+ ]
42
+ }
138
43
  }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@orkastery/openclaw-plugin",
3
+ "version": "0.3.0",
4
+ "description": "Plugin Orkastery para OpenClaw: 25 tools ork_* que traduzem intencao em chamada de CLI do nucleo `ork`. Zero regra de negocio no host.",
5
+ "type": "module",
6
+ "private": true,
7
+ "license": "MIT",
8
+ "files": [
9
+ "dist",
10
+ "openclaw.plugin.json",
11
+ "README.md"
12
+ ],
13
+ "peerDependencies": {
14
+ "openclaw": ">=2026.7.1"
15
+ },
16
+ "peerDependenciesMeta": {
17
+ "openclaw": {
18
+ "optional": true
19
+ }
20
+ },
21
+ "openclaw": {
22
+ "extensions": [
23
+ "./dist/index.js"
24
+ ]
25
+ }
26
+ }