@orkastery/cli 0.3.0 → 0.4.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/README.md +1 -1
- package/adapters/claude-code/commands/check.md +4 -3
- package/adapters/claude-code/commands/goal.md +3 -2
- package/adapters/claude-code/commands/master.md +3 -2
- package/adapters/claude-code/commands/ork.md +1 -1
- package/adapters/claude-code/hooks/ork-guard.js +1 -1
- package/adapters/hermes/README.md +6 -8
- package/adapters/hermes/hermes.plugin.json +0 -2
- package/adapters/openclaw/README.md +3 -3
- package/adapters/openclaw/dist/index.js +4 -4
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/adapters/openclaw/src/index.ts +6 -4
- package/dist/auditoria.js +1 -1
- package/dist/board.js +1 -1
- package/dist/ci.js +8 -1
- package/dist/doctor.js +1 -1
- package/dist/fix.js +1 -1
- package/dist/gates.js +5 -3
- package/dist/index.js +5 -1
- package/dist/ledger.js +2 -0
- package/dist/licoes.js +10 -4
- package/dist/ocupacao.js +1 -1
- package/dist/phase.js +16 -1
- package/dist/policies.js +72 -0
- package/dist/retry.js +5 -5
- package/dist/session-watcher.js +22 -5
- package/dist/ship.js +18 -4
- package/dist/yaml.js +3 -1
- package/eval/casos/master-metrics.json +1 -1
- package/eval/casos/orkastery-bootstrap.json +2 -2
- package/eval/casos/ship-release.json +1 -1
- package/package.json +5 -5
- package/references/definition-of-done.md +2 -2
- package/skills/README.md +3 -3
- package/skills/core/orkastery-bootstrap/SKILL.md +1 -1
- package/skills/governance/decision-triage/SKILL.md +4 -4
- package/skills/governance/narrative-guardian/SKILL.md +1 -1
- package/skills/governance/roadmap-keeper/SKILL.md +1 -1
- package/skills/observability/thread-tracing/SKILL.md +1 -1
- package/skills/phases/check-quality/SKILL.md +2 -2
- package/skills/phases/goal-definition/SKILL.md +1 -1
- package/skills/phases/master-metrics/SKILL.md +9 -7
- package/skills/phases/plan-specification/SKILL.md +1 -1
- package/skills/phases/ship-release/SKILL.md +1 -1
- package/adapters/hermes/bin/ork-objective-message.sh +0 -17
- package/adapters/hermes/bin/ork-objective-status.sh +0 -12
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @orkastery/cli, the `ork` core
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**A software factory of AI agents that proves its work: parallel threads, verified results, and short decisions only when they matter.**
|
|
4
4
|
|
|
5
5
|
`ork` conducts coding agents (Claude Code, Codex) through six-phase threads, verifies every
|
|
6
6
|
claim by re-running the command that proves it, and only delivers with the push proven on the
|
|
@@ -27,11 +27,12 @@ ork worktree audit <thread>
|
|
|
27
27
|
ork phase list <thread>
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
4. Consolida UM veredito (PASSOU, PRECISA DE MUDANCA, BLOQUEADO) e, se o modo pausa,
|
|
31
|
-
builder
|
|
30
|
+
4. Consolida UM veredito (PASSOU, PRECISA DE MUDANCA, BLOQUEADO) e, se o modo pausa, abre o pedido
|
|
31
|
+
e espera. O builder responde pelo canal autenticado (dialogo nativo do host, ou
|
|
32
|
+
`/ork gate <thread> <pedido> <resposta>` no Telegram); o agente nunca responde por ele:
|
|
32
33
|
|
|
33
34
|
```bash
|
|
34
|
-
ork gate
|
|
35
|
+
ork gate request <thread>
|
|
35
36
|
```
|
|
36
37
|
|
|
37
38
|
## Regras do adaptador
|
|
@@ -37,10 +37,11 @@ ork claims add <thread> <arquivo> --claim "<alegacao>" --verificar "<comando>" -
|
|
|
37
37
|
ork verify <thread> --so-claims
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
5. Se o modo pausa neste bloco, apresenta a evidencia ao builder e para.
|
|
40
|
+
5. Se o modo pausa neste bloco, apresenta a evidencia ao builder e para. O pedido sai do nucleo, e a
|
|
41
|
+
liberacao so e registrada quando o builder responde pelo canal autenticado:
|
|
41
42
|
|
|
42
43
|
```bash
|
|
43
|
-
ork gate
|
|
44
|
+
ork gate request <thread>
|
|
44
45
|
```
|
|
45
46
|
|
|
46
47
|
## Regras do adaptador
|
|
@@ -25,10 +25,11 @@ ork master classes
|
|
|
25
25
|
ork master <thread> --score <0-5> --justificativa "<texto>" --classe <classe> --por "<quem>"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
4. Nos modos sem pausa de MASTER,
|
|
28
|
+
4. Nos modos sem pausa de MASTER, a entrega e aceita a menos que o builder diga o contrario. Mostra
|
|
29
|
+
as entregas com o indice derivado do ledger, inclusive as ja pontuadas:
|
|
29
30
|
|
|
30
31
|
```bash
|
|
31
|
-
ork master --
|
|
32
|
+
ork master --todas
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
## Regras do adaptador
|
|
@@ -52,7 +52,7 @@ const BLOQUEIOS = [
|
|
|
52
52
|
nome: 'reset-destrutivo',
|
|
53
53
|
regex: /\bgit\s+(?:reset\s+--hard|clean\s+-[a-zA-Z]*[fd]|checkout\s+--\s+\.)/,
|
|
54
54
|
motivo: 'descarte em massa apaga trabalho nao commitado sem deixar rastro',
|
|
55
|
-
caminho: 'descarte por arquivo,
|
|
55
|
+
caminho: 'descarte por arquivo; se o descarte amplo for mesmo necessario, peca a decisao ao dono: ork gate request <thread>',
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
nome: 'remocao-recursiva-ampla',
|
|
@@ -44,16 +44,14 @@ ork adapter install hermes --dry-run # lista o que seria escrito
|
|
|
44
44
|
| `hermes.plugin.json` | Declara a skill, o binario do `ork` e as tags de conducao |
|
|
45
45
|
| `bin/ork-abrir-thread.sh` | Abre a thread com o modo lido do pedido, em um comando |
|
|
46
46
|
| `bin/ork-brain.sh` | Consulta o Company Brain pelo contrato e identidade autenticada do OrkMind |
|
|
47
|
-
| `bin/ork-objective-status.sh` | Lê o ticket canônico compartilhado com o Kanban |
|
|
48
|
-
| `bin/ork-objective-message.sh` | Grava a mensagem do canal no histórico do ticket |
|
|
49
47
|
|
|
50
|
-
##
|
|
48
|
+
## Tickets `obj-*` aposentados
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
`ork_objective_status` e `ork_objective_message` sairam com o `ork objective` na I-43: o nucleo
|
|
51
|
+
recusa qualquer subcomando com `objective.aposentado` e saida != 0. O estado de uma entrega vem de
|
|
52
|
+
`ork thread status <thread>`; os ciclos ligados a um produto, projeto ou iniciativa, de
|
|
53
|
+
`ork portfolio inspect <id> --json`. Mensagem de conversa continua sem aprovar gate: a decisao do
|
|
54
|
+
dono passa pelo `/ork gate <thread> <pedido> <resposta>` correlacionado.
|
|
57
55
|
|
|
58
56
|
## O encolhimento, que e o ponto
|
|
59
57
|
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
"ork_maestro": "./bin/ork-maestro.sh",
|
|
13
13
|
"ork-abrir-thread": "./bin/ork-abrir-thread.sh",
|
|
14
14
|
"ork_brain": "./bin/ork-brain.sh",
|
|
15
|
-
"ork_objective_status": "./bin/ork-objective-status.sh",
|
|
16
|
-
"ork_objective_message": "./bin/ork-objective-message.sh",
|
|
17
15
|
"ork_gate_answer": "./bin/ork-hitl-answer.py",
|
|
18
16
|
"ork_session_answer": "./bin/ork-hitl-answer.py"
|
|
19
17
|
},
|
|
@@ -57,14 +57,14 @@ fallback: usa `ORK_BIN` do ambiente ou o `ork` do PATH.
|
|
|
57
57
|
| `ork_claims_add` | Registra alegacao verificavel com o comando que a comprova |
|
|
58
58
|
| `ork_verify` / `ork_verify_baseline` | Reexecuta no HEAD real; grava a baseline antes do GO |
|
|
59
59
|
| `ork_worktree_ensure` / `ork_worktree_audit` | Worktree isolada, conferida no proprio git |
|
|
60
|
-
| `ork_objective_status` |
|
|
61
|
-
| `ork_objective_message` | Preserva no ticket uma mensagem do canal autenticado |
|
|
60
|
+
| `ork_objective_status` / `ork_objective_message` | Aposentadas com o `ork objective` na I-43: devolvem a recusa tipada `objective.aposentado` |
|
|
62
61
|
| `ork_portfolio_list` | Lista produtos, projetos e iniciativas canônicos |
|
|
63
62
|
| `ork_gate_answer` | Resposta humana correlacionada a um gate |
|
|
64
63
|
| `ork_session_answer` | Resposta humana correlacionada a uma sessão |
|
|
65
64
|
| `ork_ship` | Merge serializado por lease e push provado contra o remoto |
|
|
66
65
|
| `ork_master` | POSTMORTEM tipado e o score HUMANO de 0 a 5 |
|
|
67
|
-
| `ork_board`
|
|
66
|
+
| `ork_board` | Escalonador: quem avanca agora e quem espera |
|
|
67
|
+
| `ork_master_batch` | Todas as entregas, com o indice do ledger (`ork master --todas`; a fila de score saiu na I-43) |
|
|
68
68
|
|
|
69
69
|
## A #TAG de conducao
|
|
70
70
|
|
|
@@ -256,13 +256,13 @@ const FERRAMENTAS = [
|
|
|
256
256
|
},
|
|
257
257
|
{
|
|
258
258
|
name: 'ork_objective_status',
|
|
259
|
-
description: '
|
|
259
|
+
description: 'Aposentado na I-43 junto com ork objective: devolve a recusa tipada objective.aposentado, com saida != 0. Estado de uma entrega: ork_thread_status. Ciclos ligados a um produto, projeto ou iniciativa: ork portfolio inspect <id> --json.',
|
|
260
260
|
parameters: schema({ objective: { type: 'string', description: 'ID obj-* do ticket' } }),
|
|
261
261
|
argv: (p) => ['objective', 'status', texto(p, 'objective'), '--json'],
|
|
262
262
|
},
|
|
263
263
|
{
|
|
264
264
|
name: 'ork_objective_message',
|
|
265
|
-
description: '
|
|
265
|
+
description: 'Aposentado na I-43 junto com ork objective: devolve a recusa tipada objective.aposentado, com saida != 0, e nao grava nada. Resposta do dono a uma pausa vai por ork_gate_answer ou ork_session_answer.',
|
|
266
266
|
parameters: schema({
|
|
267
267
|
objective: { type: 'string', description: 'ID obj-* do ticket' },
|
|
268
268
|
author: { type: 'string', description: 'Identidade fornecida pelo gateway autenticado' },
|
|
@@ -403,9 +403,9 @@ const FERRAMENTAS = [
|
|
|
403
403
|
},
|
|
404
404
|
{
|
|
405
405
|
name: 'ork_master_batch',
|
|
406
|
-
description: '
|
|
406
|
+
description: 'Todas as entregas em JSON, com o indice derivado do ledger, as ja pontuadas e as aceitas por omissao. Roda ork master --todas; o nome e da antiga fila de score (ork master --batch), aposentada na I-43.',
|
|
407
407
|
parameters: schema({}),
|
|
408
|
-
argv: () => ['master', '--
|
|
408
|
+
argv: () => ['master', '--todas', '--json'],
|
|
409
409
|
},
|
|
410
410
|
];
|
|
411
411
|
const plugin = defineToolPlugin({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "orkastery",
|
|
3
3
|
"name": "Orkastery",
|
|
4
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.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.4.1",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"properties": {},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkastery/openclaw-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
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
5
|
"type": "module",
|
|
6
6
|
"private": true,
|
|
@@ -267,13 +267,15 @@ const FERRAMENTAS: FerramentaOrk[] = [
|
|
|
267
267
|
},
|
|
268
268
|
{
|
|
269
269
|
name: 'ork_objective_status',
|
|
270
|
-
description:
|
|
270
|
+
description:
|
|
271
|
+
'Aposentado na I-43 junto com ork objective: devolve a recusa tipada objective.aposentado, com saida != 0. Estado de uma entrega: ork_thread_status. Ciclos ligados a um produto, projeto ou iniciativa: ork portfolio inspect <id> --json.',
|
|
271
272
|
parameters: schema({ objective: { type: 'string', description: 'ID obj-* do ticket' } }),
|
|
272
273
|
argv: (p) => ['objective', 'status', texto(p, 'objective'), '--json'],
|
|
273
274
|
},
|
|
274
275
|
{
|
|
275
276
|
name: 'ork_objective_message',
|
|
276
|
-
description:
|
|
277
|
+
description:
|
|
278
|
+
'Aposentado na I-43 junto com ork objective: devolve a recusa tipada objective.aposentado, com saida != 0, e nao grava nada. Resposta do dono a uma pausa vai por ork_gate_answer ou ork_session_answer.',
|
|
277
279
|
parameters: schema({
|
|
278
280
|
objective: { type: 'string', description: 'ID obj-* do ticket' },
|
|
279
281
|
author: { type: 'string', description: 'Identidade fornecida pelo gateway autenticado' },
|
|
@@ -422,9 +424,9 @@ const FERRAMENTAS: FerramentaOrk[] = [
|
|
|
422
424
|
{
|
|
423
425
|
name: 'ork_master_batch',
|
|
424
426
|
description:
|
|
425
|
-
'
|
|
427
|
+
'Todas as entregas em JSON, com o indice derivado do ledger, as ja pontuadas e as aceitas por omissao. Roda ork master --todas; o nome e da antiga fila de score (ork master --batch), aposentada na I-43.',
|
|
426
428
|
parameters: schema({}),
|
|
427
|
-
argv: () => ['master', '--
|
|
429
|
+
argv: () => ['master', '--todas', '--json'],
|
|
428
430
|
},
|
|
429
431
|
];
|
|
430
432
|
|
package/dist/auditoria.js
CHANGED
|
@@ -425,7 +425,7 @@ exports.PACKS = {
|
|
|
425
425
|
},
|
|
426
426
|
{
|
|
427
427
|
id: 'PR2',
|
|
428
|
-
regra: 'Thread entregue sem score humano registrado
|
|
428
|
+
regra: 'Thread entregue sem score humano registrado.',
|
|
429
429
|
evidencia: 'thread entregue sem master_done.por humano correspondente ao score',
|
|
430
430
|
},
|
|
431
431
|
{
|
package/dist/board.js
CHANGED
|
@@ -212,7 +212,7 @@ function planejar(carregado, opcoes = {}) {
|
|
|
212
212
|
situacao: 'pausada',
|
|
213
213
|
motivo: 'human.pending',
|
|
214
214
|
detalhe: oc.detalhe,
|
|
215
|
-
correcao: `ork gate
|
|
215
|
+
correcao: `ork gate request ${t.id}`,
|
|
216
216
|
leases: meus,
|
|
217
217
|
});
|
|
218
218
|
continue;
|
package/dist/ci.js
CHANGED
|
@@ -209,8 +209,15 @@ function executarBundleCi(carregado, file = '.ork-ci/bundle.json') {
|
|
|
209
209
|
const bundle = JSON.parse(fs.readFileSync(absolute, 'utf8'));
|
|
210
210
|
if (bundle.schema !== 'ork.ci-bundle/v1' || !/^ork-[a-z0-9-]+$/.test(bundle.thread) || !Array.isArray(bundle.claims) || !Array.isArray(bundle.commands))
|
|
211
211
|
throw new Error('bundle de CI inválido');
|
|
212
|
+
// O CI roda o mesmo preparo do `ork verify` local (I-54), uma vez e antes das claims: a claim
|
|
213
|
+
// que passa na maquina de quem entrega passa aqui pelo mesmo caminho. Como no verify, o
|
|
214
|
+
// preparo nao e condicao de claim; ele so deixa a compilacao pronta e sai no resultado.
|
|
215
|
+
const comandoDoPreparo = carregado.manifesto.verify.preparo;
|
|
216
|
+
const preparo = comandoDoPreparo
|
|
217
|
+
? (0, verify_2.executar)('preparo', comandoDoPreparo, carregado.raiz, (0, verify_2.prazoDoComando)(carregado.manifesto, 'preparo'))
|
|
218
|
+
: null;
|
|
212
219
|
const claims = bundle.claims.map((claim) => (0, verify_2.verificarClaim)(claim, carregado.raiz));
|
|
213
220
|
const commands = bundle.commands.map((item) => (0, verify_2.executar)(item.name, item.command, carregado.raiz));
|
|
214
221
|
const ok = claims.every((item) => item.verificado || item.motivo === 'claims.unverifiable') && commands.every((item) => item.ok);
|
|
215
|
-
return { schema: 'ork.ci-run/v1', ok, thread: bundle.thread, commit: (0, verify_2.commitReal)(carregado.raiz), claims, commands };
|
|
222
|
+
return { schema: 'ork.ci-run/v1', ok, thread: bundle.thread, commit: (0, verify_2.commitReal)(carregado.raiz), preparo, claims, commands };
|
|
216
223
|
}
|
package/dist/doctor.js
CHANGED
|
@@ -329,7 +329,7 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
329
329
|
: `${esperando.length} aguardando janela, ${escalados.length} escalado(s) para humano` +
|
|
330
330
|
(esperando.length > 0 ? `; proxima janela em ${(0, horario_1.formatarDataHoraRotulada)(esperando[0].liberaEm)}` : ''),
|
|
331
331
|
correcao: escalados.length > 0
|
|
332
|
-
? `pedido escalado alem do limite de retry.max_tentativas: ork retry list e ork gate
|
|
332
|
+
? `pedido escalado alem do limite de retry.max_tentativas: ork retry list e ork gate request <thread>`
|
|
333
333
|
: esperando.length > 0
|
|
334
334
|
? 'ork retry resume retoma o que ja liberou'
|
|
335
335
|
: undefined,
|
package/dist/fix.js
CHANGED
|
@@ -381,7 +381,7 @@ function reverificarSobConducao(carregado, threadId, opcoes) {
|
|
|
381
381
|
modo: thread.modo,
|
|
382
382
|
detalhe: razao,
|
|
383
383
|
evidencia: `rodada ${rodada} de GO-FIX/CHECK-REVERIFY na thread ${threadId}`,
|
|
384
|
-
correcao: `ork gate
|
|
384
|
+
correcao: `ork gate request ${threadId}`,
|
|
385
385
|
rodada,
|
|
386
386
|
limite,
|
|
387
387
|
pausaQualquerModo: true,
|
package/dist/gates.js
CHANGED
|
@@ -86,10 +86,12 @@ function descreverMotivo(motivo, detalhe) {
|
|
|
86
86
|
return `motivo tipado: ${motivo} (${exports.DESCRICAO_DO_MOTIVO[motivo]})\n detalhe: ${detalhe}`;
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
|
-
* `ork gate approve
|
|
89
|
+
* `ork gate approve`, APOSENTADO: aprovacao sem pedido e recusada. A pausa se libera pela
|
|
90
|
+
* resposta ao `ork gate request`, que chega pelo ingresso humano autenticado.
|
|
90
91
|
*
|
|
91
|
-
*
|
|
92
|
-
* evento no ledger com quem autorizou e quando, em vez de
|
|
92
|
+
* Antes da aposentadoria, era o que tornava verificavel a "autorizacao antecipada de push"
|
|
93
|
+
* do `#Classic`: ela virava um evento no ledger com quem autorizou e quando, em vez de
|
|
94
|
+
* memoria de conversa.
|
|
93
95
|
*/
|
|
94
96
|
function aprovarGateHumano(_raiz, _threadId, _sobre, _por, _observacao) {
|
|
95
97
|
throw new Error('aprovação cega aposentada: use ork gate request e responda ao pedido pelo ingresso humano autenticado');
|
package/dist/index.js
CHANGED
|
@@ -1022,6 +1022,8 @@ function comandoPhase(args) {
|
|
|
1022
1022
|
console.log(` modelo/esforco : ${r.model}/${r.effort}`);
|
|
1023
1023
|
// O prompt inteiro nao cabe na tela: o argumento longo aparece mascarado.
|
|
1024
1024
|
console.log(` comando : ${r.comando.map((c) => (c.length > 80 ? '"<prompt>"' : c)).join(' ')}`);
|
|
1025
|
+
for (const l of (0, policies_1.linhasDeAviso)(r.violacoes ?? []))
|
|
1026
|
+
console.log(l);
|
|
1025
1027
|
return 0;
|
|
1026
1028
|
}
|
|
1027
1029
|
if (r.bloqueado) {
|
|
@@ -1040,6 +1042,8 @@ function comandoPhase(args) {
|
|
|
1040
1042
|
return 1;
|
|
1041
1043
|
}
|
|
1042
1044
|
console.log(`Fase ${fase} despachada como background agent.`);
|
|
1045
|
+
for (const l of (0, policies_1.linhasDeAviso)(r.violacoes ?? []))
|
|
1046
|
+
console.log(l);
|
|
1043
1047
|
console.log(` sessionId : ${r.sessionId}`);
|
|
1044
1048
|
console.log(` slug da sessao : ${r.slug} (${(0, phase_1.descreverSlug)(r.slug)})`);
|
|
1045
1049
|
console.log(` prompt : ${r.promptPath}`);
|
|
@@ -1512,7 +1516,7 @@ function comandoGate(args) {
|
|
|
1512
1516
|
const sobre = args.posicionais[3];
|
|
1513
1517
|
const por = texto(args.opcoes.por) ?? texto(args.opcoes.quem);
|
|
1514
1518
|
if (!id || !sobre || !por) {
|
|
1515
|
-
console.error('
|
|
1519
|
+
console.error('gate approve aposentado: aprovação sem pedido é recusada. Use ork gate request <thread-id> e responda pelo ingresso humano autenticado.');
|
|
1516
1520
|
return 2;
|
|
1517
1521
|
}
|
|
1518
1522
|
(0, thread_1.lerThread)(carregado.raiz, id);
|
package/dist/ledger.js
CHANGED
|
@@ -147,6 +147,8 @@ exports.TIPOS_DE_EVENTO = {
|
|
|
147
147
|
lintDeClaim: 'claim_lint',
|
|
148
148
|
// I-55 (RM-008): a mesma falha em 3+ threads fechadas virou proposta de policy (so proposta).
|
|
149
149
|
politicaProposta: 'policy_proposta',
|
|
150
|
+
// RM-008 (fatia 3): policy em warn que disparou num gate. Registra e segue; nunca bloqueia.
|
|
151
|
+
politicaAviso: 'policy_warn',
|
|
150
152
|
// I-36 (RM-036): conducao multicanal. O segundo pedido recusado, o despacho repetido que nao abriu
|
|
151
153
|
// sessao nova, a liberacao com prova (fim da sessao ou dono morto), o handoff e a renovacao do prazo.
|
|
152
154
|
conducaoRecusada: 'conducao_recusada',
|
package/dist/licoes.js
CHANGED
|
@@ -57,6 +57,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
57
57
|
const path = __importStar(require("node:path"));
|
|
58
58
|
const estado_thread_1 = require("./estado-thread");
|
|
59
59
|
const ledger_1 = require("./ledger");
|
|
60
|
+
const policies_1 = require("./policies");
|
|
60
61
|
/** O que evita cada bloqueio, na forma de comando. Sem dica, a licao so conta a recorrencia. */
|
|
61
62
|
const DICA_DO_MOTIVO = {
|
|
62
63
|
'claims.failed': 'rode o comando da claim antes de registra-la; claim sem prova local volta como GO-FIX',
|
|
@@ -175,10 +176,15 @@ function propostasDePolicy(raiz, agoraIso = new Date().toISOString()) {
|
|
|
175
176
|
const limite = Date.parse(agoraIso) - exports.JANELA_DA_PROPOSTA_DIAS * 86_400_000;
|
|
176
177
|
const recentes = lerLicoes(raiz).filter((l) => Date.parse(l.fechadaEm) >= limite);
|
|
177
178
|
const { motivos, classes } = recorrencias(recentes);
|
|
178
|
-
return [...motivos, ...classes].filter((r) => r.threads.length >= exports.PISO_DA_PROPOSTA).map((r) =>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
return [...motivos, ...classes].filter((r) => r.threads.length >= exports.PISO_DA_PROPOSTA).map((r) => {
|
|
180
|
+
const policy = r.nome.replace(/[^a-z0-9]+/gi, '_');
|
|
181
|
+
const dica = r.dica ?? 'revisar a causa comum antes da proxima thread';
|
|
182
|
+
// RM-008 (fatia 3): com avaliador no nucleo, a proposta ja diz como vira policy de verdade.
|
|
183
|
+
const sugestao = policy in policies_1.POLICIES_CONHECIDAS
|
|
184
|
+
? `policy \`${policy}\` executavel: declare \`${policy}: warn\` em policies: do orkastery.yaml; o que evita: ${dica}`
|
|
185
|
+
: `policy \`${policy}\` em warn: ${dica}`;
|
|
186
|
+
return { chave: r.chave, tipo: r.tipo, nome: r.nome, threads: [...r.threads], janelaDias: exports.JANELA_DA_PROPOSTA_DIAS, sugestao };
|
|
187
|
+
});
|
|
182
188
|
}
|
|
183
189
|
/**
|
|
184
190
|
* Grava no ledger do projeto a proposta que ainda nao foi registrada nesta janela. Idempotente:
|
package/dist/ocupacao.js
CHANGED
|
@@ -45,7 +45,7 @@ exports.EVENTOS_QUE_DESTRAVAM = [
|
|
|
45
45
|
ledger_1.TIPOS_DE_EVENTO.shipConcluido,
|
|
46
46
|
ledger_1.TIPOS_DE_EVENTO.masterConcluido,
|
|
47
47
|
];
|
|
48
|
-
/** O evento e uma autorizacao humana ja registrada (`ork gate
|
|
48
|
+
/** O evento e uma autorizacao humana ja registrada (resposta ao `ork gate request`)? */
|
|
49
49
|
function ehAprovacaoHumana(e) {
|
|
50
50
|
return e.tipo === ledger_1.TIPOS_DE_EVENTO.pausaHumana && e.estado === 'aprovado';
|
|
51
51
|
}
|
package/dist/phase.js
CHANGED
|
@@ -560,8 +560,23 @@ function rodarFaseSobLock(carregado, threadId, opcoes) {
|
|
|
560
560
|
// Gate tipado do bloco B1: as policies do manifesto valem ANTES do despacho, em
|
|
561
561
|
// qualquer modo. Prompt reprovado nem chega a ser gravado em disco: gravar um prompt
|
|
562
562
|
// com credencial e criar um segundo vazamento no proprio repositorio.
|
|
563
|
-
|
|
563
|
+
// RM-008 (fatia 3): as licoes que viraram policy recebem os fatos da thread, calculados aqui.
|
|
564
|
+
const blocoDespachado = (0, thread_1.blocoDaThread)(thread, fase);
|
|
565
|
+
const violacoes = (0, policies_1.avaliarPolicies)(manifesto, {
|
|
566
|
+
gate: 'phase.dispatch', prompt, threadId: thread.id, modo: thread.modo, fase,
|
|
567
|
+
bloco: thread.blocos.indexOf(blocoDespachado) + 1,
|
|
568
|
+
blocoComGo: blocoDespachado.fases.includes('GO'),
|
|
569
|
+
temBaseline: (0, ledger_1.lerLedger)(dir).some((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.baselineGravada),
|
|
570
|
+
fallbackDoBloco: (0, setup_1.fallbackDoBloco)(setup, thread.modo, fase),
|
|
571
|
+
});
|
|
564
572
|
const bloqueiam = (0, policies_1.bloqueantes)(violacoes);
|
|
573
|
+
// Warn registra e segue: o aviso vai ao ledger (fora do ensaio) e o despacho continua.
|
|
574
|
+
if (!opcoes.dryRun) {
|
|
575
|
+
for (const v of (0, policies_1.avisos)(violacoes)) {
|
|
576
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.politicaAviso, { gate: 'phase.dispatch', fase, slug,
|
|
577
|
+
policy: v.policy, detalhe: v.detalhe, correcao: v.correcao, modo: thread.modo });
|
|
578
|
+
}
|
|
579
|
+
}
|
|
565
580
|
if (bloqueiam.length > 0) {
|
|
566
581
|
const detalhe = bloqueiam.map((v) => `${v.policy}: ${v.detalhe}`).join('; ');
|
|
567
582
|
// Bloco B3: violacao de CUSTO sai tipada como tal. E o que permite a politica de
|
package/dist/policies.js
CHANGED
|
@@ -15,8 +15,10 @@ exports.POLICIES_CONHECIDAS = void 0;
|
|
|
15
15
|
exports.procurarSegredos = procurarSegredos;
|
|
16
16
|
exports.policiesDesconhecidas = policiesDesconhecidas;
|
|
17
17
|
exports.avaliarPolicies = avaliarPolicies;
|
|
18
|
+
exports.avisos = avisos;
|
|
18
19
|
exports.bloqueantes = bloqueantes;
|
|
19
20
|
exports.motivoDominante = motivoDominante;
|
|
21
|
+
exports.linhasDeAviso = linhasDeAviso;
|
|
20
22
|
exports.textoDeViolacoes = textoDeViolacoes;
|
|
21
23
|
/**
|
|
22
24
|
* Variaveis que REDIRECIONAM o despacho do `claude` para um provider pago.
|
|
@@ -73,6 +75,24 @@ exports.POLICIES_CONHECIDAS = {
|
|
|
73
75
|
quando: ['ship'],
|
|
74
76
|
descricao: 'proibe entregar sem branch de thread (push direto na base)',
|
|
75
77
|
},
|
|
78
|
+
// RM-008 (fatia 3): licoes do loop de aprendizado que o `ork` sabe conferir sem ambiguidade.
|
|
79
|
+
// O nome e o mesmo que o `ork licoes` propoe, para a proposta ser declarada como veio.
|
|
80
|
+
verify_regression: {
|
|
81
|
+
quando: ['phase.dispatch'],
|
|
82
|
+
descricao: 'avisa quando o bloco que contem GO sai sem baseline gravada',
|
|
83
|
+
},
|
|
84
|
+
verify_failed: {
|
|
85
|
+
quando: ['phase.dispatch'],
|
|
86
|
+
descricao: 'avisa quando o bloco que contem GO sai sem baseline gravada (mesma conferencia de verify_regression)',
|
|
87
|
+
},
|
|
88
|
+
runtime_unavailable: {
|
|
89
|
+
quando: ['phase.dispatch'],
|
|
90
|
+
descricao: 'avisa quando o bloco despachado nao declara runtime de fallback',
|
|
91
|
+
},
|
|
92
|
+
tree_blocked: {
|
|
93
|
+
quando: ['ship'],
|
|
94
|
+
descricao: 'avisa quando a branch da thread esta atras da base',
|
|
95
|
+
},
|
|
76
96
|
};
|
|
77
97
|
function severidade(bruta) {
|
|
78
98
|
if (bruta === 'block' || bruta === 'warn' || bruta === 'off')
|
|
@@ -87,6 +107,8 @@ function policiesDesconhecidas(manifesto) {
|
|
|
87
107
|
function avaliarPolicies(manifesto, ctx) {
|
|
88
108
|
const declaradas = manifesto.policies ?? {};
|
|
89
109
|
const violacoes = [];
|
|
110
|
+
// verify_regression e verify_failed conferem a mesma coisa: um aviso so, com o nome da primeira declarada.
|
|
111
|
+
let baselineJaAvaliada = false;
|
|
90
112
|
for (const [nome, bruta] of Object.entries(declaradas)) {
|
|
91
113
|
const conhecida = exports.POLICIES_CONHECIDAS[nome];
|
|
92
114
|
if (!conhecida || !conhecida.quando.includes(ctx.gate))
|
|
@@ -148,9 +170,52 @@ function avaliarPolicies(manifesto, ctx) {
|
|
|
148
170
|
}
|
|
149
171
|
continue;
|
|
150
172
|
}
|
|
173
|
+
if (nome === 'verify_regression' || nome === 'verify_failed') {
|
|
174
|
+
if (baselineJaAvaliada)
|
|
175
|
+
continue;
|
|
176
|
+
baselineJaAvaliada = true;
|
|
177
|
+
if (ctx.blocoComGo === true && ctx.temBaseline === false) {
|
|
178
|
+
violacoes.push({
|
|
179
|
+
policy: nome,
|
|
180
|
+
severidade: sev,
|
|
181
|
+
motivo: 'policy.violation',
|
|
182
|
+
detalhe: 'o bloco que contem GO vai sair sem baseline: uma falha que ja existia passaria por regressao desta thread',
|
|
183
|
+
correcao: `ork verify ${ctx.threadId ?? '<thread>'} --baseline`,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (nome === 'runtime_unavailable') {
|
|
189
|
+
if (Array.isArray(ctx.fallbackDoBloco) && ctx.fallbackDoBloco.length === 0) {
|
|
190
|
+
violacoes.push({
|
|
191
|
+
policy: nome,
|
|
192
|
+
severidade: sev,
|
|
193
|
+
motivo: 'policy.violation',
|
|
194
|
+
detalhe: 'o bloco nao declara runtime de fallback: se o runtime cair, a fase para ate alguem trocar a mao',
|
|
195
|
+
correcao: `ork setup ${ctx.modo ?? '<modo>'} --bloco ${ctx.bloco ?? 'N'} --fallback <runtime:modelo>`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (nome === 'tree_blocked') {
|
|
201
|
+
if (ctx.branchAtrasDaBase === true) {
|
|
202
|
+
violacoes.push({
|
|
203
|
+
policy: nome,
|
|
204
|
+
severidade: sev,
|
|
205
|
+
motivo: 'policy.violation',
|
|
206
|
+
detalhe: `a branch "${ctx.de ?? 'da thread'}" esta atras de "${ctx.para ?? ctx.baseBranch ?? 'base'}": a entrega mistura a mudanca com o que a base ja andou`,
|
|
207
|
+
correcao: `ork worktree sync ${ctx.threadId ?? '<thread>'}`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
151
212
|
}
|
|
152
213
|
return violacoes;
|
|
153
214
|
}
|
|
215
|
+
/** So as violacoes com severidade `warn` (as que registram e seguem). */
|
|
216
|
+
function avisos(violacoes) {
|
|
217
|
+
return violacoes.filter((v) => v.severidade === 'warn');
|
|
218
|
+
}
|
|
154
219
|
/** So as violacoes com severidade `block` (as que reprovam em qualquer modo). */
|
|
155
220
|
function bloqueantes(violacoes) {
|
|
156
221
|
return violacoes.filter((v) => v.severidade === 'block');
|
|
@@ -168,6 +233,13 @@ function motivoDominante(violacoes) {
|
|
|
168
233
|
? 'cost.violation'
|
|
169
234
|
: 'policy.violation';
|
|
170
235
|
}
|
|
236
|
+
/** RM-008 (fatia 3): as linhas de aviso (policies em warn) para a saida do CLI. Nada quando nao ha aviso. */
|
|
237
|
+
function linhasDeAviso(violacoes, recuo = ' ') {
|
|
238
|
+
return avisos(violacoes).flatMap((v) => [
|
|
239
|
+
`${recuo}aviso da policy ${v.policy}: ${v.detalhe}`,
|
|
240
|
+
`${recuo} correcao: ${v.correcao}`,
|
|
241
|
+
]);
|
|
242
|
+
}
|
|
171
243
|
/** Texto das violacoes para a saida do CLI. */
|
|
172
244
|
function textoDeViolacoes(violacoes) {
|
|
173
245
|
return violacoes
|
package/dist/retry.js
CHANGED
|
@@ -73,7 +73,7 @@ const claude_bg_1 = require("./adapters/claude-bg");
|
|
|
73
73
|
* violacao de custo e gastar de novo, e a politica `subscription-only` esta no manifesto.
|
|
74
74
|
* 2. **O modo afrouxa a PAUSA, nunca a VERIFICACAO.** A politica e identica em
|
|
75
75
|
* `#Classic` e em `#Auto`. O que muda e a AUTORIZACAO: num bloco de loop que pausa,
|
|
76
|
-
* a acao espera `ork gate
|
|
76
|
+
* a acao espera a resposta humana ao `ork gate request`; num bloco sem pausa (`#Maestro`, `#Auto`) o
|
|
77
77
|
* `ork` executa sozinho e grava a decisao autonoma no ledger.
|
|
78
78
|
* 3. **O limite de escalacao pausa QUALQUER modo.** Estouradas as tentativas do
|
|
79
79
|
* manifesto pelo MESMO motivo na MESMA fase, a acao vira `escalar-humano`,
|
|
@@ -278,7 +278,7 @@ exports.POLITICA_DE_RETRY = {
|
|
|
278
278
|
acao: 'escalar-humano',
|
|
279
279
|
automatica: false,
|
|
280
280
|
porque: 'nao e reprovacao de verdade, e espera de autorizacao: automatizar a espera seria a maquina se autorizando',
|
|
281
|
-
correcao: 'ork gate
|
|
281
|
+
correcao: 'ork gate request <thread>',
|
|
282
282
|
},
|
|
283
283
|
};
|
|
284
284
|
/** A politica de um motivo tipado. */
|
|
@@ -756,7 +756,7 @@ function retomarPedido(carregado, pedidoOriginal, opcoes = {}) {
|
|
|
756
756
|
motivo: 'human.pending',
|
|
757
757
|
modo: thread.modo,
|
|
758
758
|
detalhe: escolha.razao,
|
|
759
|
-
correcao: `ork gate
|
|
759
|
+
correcao: `ork gate request ${thread.id}`,
|
|
760
760
|
fase: pedido.fase,
|
|
761
761
|
slug: pedido.slug,
|
|
762
762
|
pedido: pedido.id,
|
|
@@ -1137,7 +1137,7 @@ function executarRetry(carregado, threadId, opcoes = {}) {
|
|
|
1137
1137
|
motivo: plano.acao === 'sem-retry' ? plano.motivo : 'human.pending',
|
|
1138
1138
|
modo: thread.modo,
|
|
1139
1139
|
detalhe: plano.razao,
|
|
1140
|
-
correcao: plano.politica?.correcao ?? `ork gate
|
|
1140
|
+
correcao: plano.politica?.correcao ?? `ork gate request ${threadId}`,
|
|
1141
1141
|
fase: plano.fase,
|
|
1142
1142
|
origem: 'retry.run',
|
|
1143
1143
|
pausaQualquerModo: true,
|
|
@@ -1259,7 +1259,7 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
|
|
|
1259
1259
|
const escalar = (razao, diagnostico) => {
|
|
1260
1260
|
if (!opcoes.dryRun) {
|
|
1261
1261
|
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'human.pending', modo: thread.modo, detalhe: diagnostico,
|
|
1262
|
-
diagnostico, correcao: `ork gate
|
|
1262
|
+
diagnostico, correcao: `ork gate request ${thread.id}`, fase, origem: 'retry.rotacao', pausaQualquerModo: true });
|
|
1263
1263
|
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.retryEscalado, { fase, motivo, origem: 'retry.rotacao', acao: plano.acao,
|
|
1264
1264
|
tentativas: plano.tentativas, limite: plano.limite, modo: thread.modo, razao });
|
|
1265
1265
|
}
|
package/dist/session-watcher.js
CHANGED
|
@@ -118,6 +118,27 @@ function lerJson(file) {
|
|
|
118
118
|
throw new Error('metadado de sensor excessivo');
|
|
119
119
|
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Sob o mutex de recovery: `true` quando o lock ficou livre (dono morto, lock sem dono vencido, ou
|
|
123
|
+
* dono vivo que soltou o lock no meio da leitura) e `false` quando o dono segue vivo.
|
|
124
|
+
*/
|
|
125
|
+
function lockLiberado(lock, owner) {
|
|
126
|
+
try {
|
|
127
|
+
const atual = lerJson(owner);
|
|
128
|
+
if (atual ? (0, codex_runner_1.estadoProcesso)(atual.identidade) !== 'ausente' : Date.now() - fs.statSync(lock).mtimeMs < 60000)
|
|
129
|
+
return false;
|
|
130
|
+
if (atual)
|
|
131
|
+
fs.unlinkSync(owner);
|
|
132
|
+
fs.rmdirSync(lock);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
// O dono vivo pode soltar o lock entre o EEXIST e esta leitura: sumir aqui quer dizer lock livre, não falha.
|
|
137
|
+
if (e.code === 'ENOENT')
|
|
138
|
+
return true;
|
|
139
|
+
throw e;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
121
142
|
/** Recovery serializado: quem perde o mutex não remove lock recém-adquirido. */
|
|
122
143
|
function comLockWatcher(dir, action) {
|
|
123
144
|
const lock = path.join(dir, 'watch.lock'), recover = path.join(dir, 'recover.lock');
|
|
@@ -137,12 +158,8 @@ function comLockWatcher(dir, action) {
|
|
|
137
158
|
return null;
|
|
138
159
|
}
|
|
139
160
|
try {
|
|
140
|
-
|
|
141
|
-
if (atual ? (0, codex_runner_1.estadoProcesso)(atual.identidade) !== 'ausente' : Date.now() - fs.statSync(lock).mtimeMs < 60000)
|
|
161
|
+
if (!lockLiberado(lock, owner))
|
|
142
162
|
return null;
|
|
143
|
-
if (atual)
|
|
144
|
-
fs.unlinkSync(owner);
|
|
145
|
-
fs.rmdirSync(lock);
|
|
146
163
|
try {
|
|
147
164
|
criar();
|
|
148
165
|
}
|
package/dist/ship.js
CHANGED
|
@@ -131,8 +131,7 @@ function autorizacaoDePush(raiz, thread, opcoes) {
|
|
|
131
131
|
tipo: 'pendente',
|
|
132
132
|
por: '',
|
|
133
133
|
razao: `o modo ${tag} pausa no push e ainda nao ha autorizacao humana registrada. ` +
|
|
134
|
-
`Autorize
|
|
135
|
-
`ou rode: ork ship ${thread.id} --para <branch> --autorizar-push <quem>`,
|
|
134
|
+
`Autorize na entrega: ork ship ${thread.id} --para <branch> --autorizar-push <quem>`,
|
|
136
135
|
};
|
|
137
136
|
}
|
|
138
137
|
/** Diretorio temporario onde a arvore de merge e montada quando preciso. */
|
|
@@ -365,16 +364,30 @@ function ship(carregado, threadId, opcoes) {
|
|
|
365
364
|
const autorizacao = autorizacaoDePush(raiz, thread, opcoes);
|
|
366
365
|
r.autorizacao = autorizacao;
|
|
367
366
|
if (!autorizacao.autorizado) {
|
|
368
|
-
return bloquear('human.pending', autorizacao.razao, `ork
|
|
367
|
+
return bloquear('human.pending', autorizacao.razao, `ork ship ${threadId} --para <branch> --autorizar-push <quem>`);
|
|
369
368
|
}
|
|
370
|
-
// 2. Policies do manifesto que valem no gate `ship`.
|
|
369
|
+
// 2. Policies do manifesto que valem no gate `ship`. RM-008 (fatia 3): a branch da thread
|
|
370
|
+
// atras da base e fato do git, calculado aqui (a ponta da base nao esta contida na branch).
|
|
371
|
+
const pontaDe = shaDaRef(raiz, `refs/heads/${de}`);
|
|
372
|
+
const pontaPara = shaDaRef(raiz, `refs/heads/${para}`);
|
|
373
|
+
const branchAtrasDaBase = pontaDe && pontaPara && de !== para
|
|
374
|
+
? !(0, util_1.exec)('git', ['merge-base', '--is-ancestor', pontaPara, pontaDe], raiz).ok
|
|
375
|
+
: undefined;
|
|
371
376
|
const violacoes = (0, policies_1.avaliarPolicies)(manifesto, {
|
|
372
377
|
gate: 'ship',
|
|
373
378
|
de,
|
|
374
379
|
para,
|
|
375
380
|
baseBranch: manifesto.worktree.base_branch,
|
|
381
|
+
threadId,
|
|
382
|
+
branchAtrasDaBase,
|
|
376
383
|
});
|
|
377
384
|
r.violacoes = violacoes;
|
|
385
|
+
if (!r.dryRun) {
|
|
386
|
+
for (const v of (0, policies_1.avisos)(violacoes)) {
|
|
387
|
+
(0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.politicaAviso, { gate: 'ship', de, para,
|
|
388
|
+
policy: v.policy, detalhe: v.detalhe, correcao: v.correcao, modo: thread.modo });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
378
391
|
const bloqueiam = (0, policies_1.bloqueantes)(violacoes);
|
|
379
392
|
if (bloqueiam.length > 0) {
|
|
380
393
|
return bloquear('policy.violation', bloqueiam.map((v) => `${v.policy}: ${v.detalhe}`).join('; '), bloqueiam.map((v) => v.correcao).join('; '));
|
|
@@ -641,6 +654,7 @@ function textoDoShip(r) {
|
|
|
641
654
|
if (r.ci) {
|
|
642
655
|
linhas.push(` ci ${r.ci.required ? `${r.ci.state.toUpperCase()} ${r.ci.context} em ${r.ci.sha.slice(0, 8)}` : 'não exigido'}`);
|
|
643
656
|
}
|
|
657
|
+
linhas.push(...(0, policies_1.linhasDeAviso)(r.violacoes ?? []));
|
|
644
658
|
if (r.leaseOcupadoPor) {
|
|
645
659
|
comHorario = true;
|
|
646
660
|
linhas.push(` lease ${leases_1.LEASE_MAIN_TREE} OCUPADO pela thread ${r.leaseOcupadoPor.thread} (desde ${(0, horario_1.formatarDataHora)(r.leaseOcupadoPor.adquiridoEm)})`);
|
package/dist/yaml.js
CHANGED
|
@@ -38,7 +38,9 @@ function escalar(bruto) {
|
|
|
38
38
|
return true;
|
|
39
39
|
if (t === 'false' || t === 'no')
|
|
40
40
|
return false;
|
|
41
|
-
|
|
41
|
+
// Inteiro so vira numero quando volta igual ao texto. Zero a esquerda (um SHA curto como
|
|
42
|
+
// `0123456`) e digitos alem da precisao segura ficam texto, porque o numero perderia informacao.
|
|
43
|
+
if (/^-?(0|[1-9]\d*)$/.test(t) && Number.isSafeInteger(Number(t)))
|
|
42
44
|
return Number(t);
|
|
43
45
|
if (/^-?\d*\.\d+$/.test(t))
|
|
44
46
|
return Number(t);
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"tipo": "racionalizacao",
|
|
46
46
|
"gravidade": "maior",
|
|
47
47
|
"cenario": "Uma thread foi entregue sem score e o builder quer abrir a proxima antes de avaliar.",
|
|
48
|
-
"esperado": "Recusado: entrega sem MASTER log nao aconteceu; nos modos sem pausa
|
|
48
|
+
"esperado": "Recusado: entrega sem MASTER log nao aconteceu; nos modos sem pausa a entrega e aceita por omissao com o indice do ledger, e a nota humana sobrescreve.",
|
|
49
49
|
"racionalizacao": "Depois eu dou o score da thread anterior.",
|
|
50
50
|
"assercoes": [
|
|
51
51
|
{
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
"tipo": "contem",
|
|
58
|
-
"valor": "
|
|
58
|
+
"valor": "aceita por omissao com o indice do ledger",
|
|
59
59
|
"porque": "o caminho que substitui a pausa nos modos autonomos, sem tirar o humano"
|
|
60
60
|
}
|
|
61
61
|
]
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkastery/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "A software factory of AI agents that proves its work: parallel threads, verified results, and short decisions only when they matter.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"homepage": "https://github.com/
|
|
6
|
+
"homepage": "https://github.com/orkastery/orkastery#readme",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
9
|
+
"url": "git+https://github.com/orkastery/orkastery.git",
|
|
10
10
|
"directory": "core"
|
|
11
11
|
},
|
|
12
12
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/
|
|
13
|
+
"url": "https://github.com/orkastery/orkastery/issues"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"orkastery",
|
|
@@ -39,7 +39,7 @@ flowchart LR
|
|
|
39
39
|
| 8 | Os cinco eixos de review (correcao, seguranca, performance, manutenibilidade, estilo) trazem achados ou um "nenhum" explicito, cada um categorizado bloqueador, aviso ou sugestao. | A tabela dos cinco eixos do relatorio de CHECK, conforme [code-review-axes.md](code-review-axes.md). |
|
|
40
40
|
| 9 | A auditoria de seguranca reporta zero bloqueadores, e a auditoria de performance web ou rodou ou declara por que o alvo nao tem superficie web. | As secoes de auditoria do relatorio, conforme [security-checklist.md](security-checklist.md) e [performance-checklist.md](performance-checklist.md). |
|
|
41
41
|
| 10 | Correcoes classificadas com honestidade: tipo A e uma linha ou equivalente, registrada, com as verificacoes afetadas reexecutadas; tipo B devolveu a tarefa ao GO, e esta rodada de CHECK e a reexecucao completa. | `ork fix open <thread>` deriva uma correcao por motivo tipado, com a spec exata e o comando que a julga; `ork fix reverify <thread>` da o veredito POR correcao e RECUSA reexecucao parcial quando ha tipo B. Os eventos `go_fix_opened` e `check_reverify` do ledger contra as contagens do relatorio. Estas contagens medem a qualidade do PLAN e do GO, nao a do reviewer. |
|
|
42
|
-
| 11 | O relatorio esta no diretorio da thread com exatamente um veredito (PASSOU, PRECISA DE MUDANCA, BLOQUEADO), todo aviso aceito tem seu registro, e o gate foi resolvido pelo caminho certo. | `ork gate
|
|
42
|
+
| 11 | O relatorio esta no diretorio da thread com exatamente um veredito (PASSOU, PRECISA DE MUDANCA, BLOQUEADO), todo aviso aceito tem seu registro, e o gate foi resolvido pelo caminho certo. | A resposta humana ao `ork gate request <thread>`, pelo canal autenticado, para decisao humana, ou o evento de decisao autonoma do modo, que so um veredito PASSOU pode tomar. Falha de verify, falha anti-alucinacao, qualquer CHECK com correcao tipo B, desvio de envelope, veredito diferente de PASSOU e emergencia sobem sempre para o humano, em qualquer modo. |
|
|
43
43
|
|
|
44
44
|
## Todo merge, antes de o SHIP fechar
|
|
45
45
|
|
|
@@ -48,7 +48,7 @@ flowchart LR
|
|
|
48
48
|
| 12 | Guarda de contrato: nada no diff final muda contrato publico versionado (schema de telemetria, contrato de interface, layout de estado, tipos de evento) sem decisao de classe 2 ratificada. | `git diff <base>...HEAD` sobre esses arquivos e o id do gate que ratificou, no ledger. Sem ratificacao nao ha merge. |
|
|
49
49
|
| 13 | O merge passou pela fila serializada, atualizado contra a base mais recente, revalidado por inteiro sempre que a atualizacao trouxe mudanca, com a guarda de `DoD 12` reexecutada contra o diff final. | `ork ship <thread> --para <base>` toma o lease `main-tree`; a atualizacao pode trazer mudanca que toca contrato, entao um veredito calculado antes dela descreve um diff que nao existe mais. |
|
|
50
50
|
| 14 | O push foi provado por comando, nao relatado. | O `ork ship` compara o sha local com `git ls-remote` no remoto e grava `pushVerificado` no ledger. Push relatado sem sha do remoto conta como push nao acontecido. |
|
|
51
|
-
| 15 | Passo irreversivel so acontece com autorizacao do modo: push, merge e delecao exigem a pausa que a #TAG previu ou uma autorizacao antecipada registrada. | `ork
|
|
51
|
+
| 15 | Passo irreversivel so acontece com autorizacao do modo: push, merge e delecao exigem a pausa que a #TAG previu ou uma autorizacao antecipada registrada. | `ork ship <thread> --para <base> --autorizar-push <quem>`, ou a resposta humana a pausa do modo, visivel em `ork phase list <thread>`. |
|
|
52
52
|
|
|
53
53
|
## Todo fechamento, antes de a thread morrer
|
|
54
54
|
|
package/skills/README.md
CHANGED
|
@@ -15,14 +15,14 @@ faz, o nucleo vence, e a divergencia e defeito da skill.
|
|
|
15
15
|
| phases | [goal-definition](phases/goal-definition/SKILL.md) | `ork phase run <t> GOAL`, `ork claims add` |
|
|
16
16
|
| phases | [plan-specification](phases/plan-specification/SKILL.md) | `ork phase run <t> PLAN`, `ork lease acquire` |
|
|
17
17
|
| phases | [go-implementation](phases/go-implementation/SKILL.md) | `ork worktree ensure`, `ork verify --baseline` |
|
|
18
|
-
| phases | [check-quality](phases/check-quality/SKILL.md) | `ork verify`, `ork gate
|
|
18
|
+
| phases | [check-quality](phases/check-quality/SKILL.md) | `ork verify`, `ork gate request` |
|
|
19
19
|
| phases | [ship-release](phases/ship-release/SKILL.md) | `ork ship` |
|
|
20
|
-
| phases | [master-metrics](phases/master-metrics/SKILL.md) | `ork master`, `ork master --
|
|
20
|
+
| phases | [master-metrics](phases/master-metrics/SKILL.md) | `ork master`, `ork master --aceitar-omissao` |
|
|
21
21
|
| reviewers | [code-reviewer](reviewers/code-reviewer/SKILL.md) | `references/code-review-axes.md` |
|
|
22
22
|
| reviewers | [security-auditor](reviewers/security-auditor/SKILL.md) | `references/security-checklist.md` |
|
|
23
23
|
| reviewers | [test-engineer](reviewers/test-engineer/SKILL.md) | `references/testing-patterns.md` |
|
|
24
24
|
| reviewers | [web-performance-auditor](reviewers/web-performance-auditor/SKILL.md) | `references/performance-checklist.md` |
|
|
25
|
-
| governance | [decision-triage](governance/decision-triage/SKILL.md) | `ork gate
|
|
25
|
+
| governance | [decision-triage](governance/decision-triage/SKILL.md) | `ork gate request` |
|
|
26
26
|
| governance | [narrative-guardian](governance/narrative-guardian/SKILL.md) | `ork verify`, `ork phase list` |
|
|
27
27
|
| governance | [roadmap-keeper](governance/roadmap-keeper/SKILL.md) | `ork board`, `ork thread new` |
|
|
28
28
|
| governance | [scope-check-capability-map](governance/scope-check-capability-map/SKILL.md) | `ork doctor`, `ork board plan` |
|
|
@@ -110,7 +110,7 @@ No pedido de despacho, descreva o objetivo e o escopo de todas as fases do bloco
|
|
|
110
110
|
|
|
111
111
|
Quando `ork_observe` mostrar `turno.estado=encerrado`, reconcilie o ultimo resultado oficial e os artefatos do bloco. Isso indica um turno encerrado, nao `phase_result`, fase concluida ou entrega. Os campos nativos `state` e `status` podem divergir; preserve a divergencia em vez de interpretar `working` isoladamente. Atividade posterior invalida a evidencia de turno encerrado. Sem resultado suficiente, registre o ponto pendente e use somente a continuacao suportada pelo nucleo, sem duplicar despacho nem fabricar conclusao. Nao use sleeps longos ou polling repetido para transformar silencio em prova de vida, morte ou progresso.
|
|
112
112
|
|
|
113
|
-
Despacho nao e conclusao. Testes, CHECK, SHIP e MASTER sao provas diferentes. Entregue mudancas, validacao, publicacao efetiva e pendencias, com links uteis ao dono. SHIP usa `ork ship`;
|
|
113
|
+
Despacho nao e conclusao. Testes, CHECK, SHIP e MASTER sao provas diferentes. Entregue mudancas, validacao, publicacao efetiva e pendencias, com links uteis ao dono. SHIP usa `ork ship`; entrega sem nota humana e aceita por omissao com o indice do ledger (`ork master`), e a nota humana sobrescreve. Entrega sem MASTER log nao aconteceu; publicacao e ratificacao continuam distintas.
|
|
114
114
|
## Racionalizacoes comuns
|
|
115
115
|
Despacho, silêncio ou modo Auto nunca substituem resultado, `verify` e recibos.
|
|
116
116
|
## Bandeiras vermelhas
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: decision-triage
|
|
3
|
-
description: "A disciplina de delegacao: classifica cada decisao em classe 1 (humano decide), 2 (contrato publico, exige ratificacao) ou 3 (delegada, registrada), e sobe tradeoff real com opcoes e uma recomendacao. Roteia para ork gate
|
|
3
|
+
description: "A disciplina de delegacao: classifica cada decisao em classe 1 (humano decide), 2 (contrato publico, exige ratificacao) ou 3 (delegada, registrada), e sobe tradeoff real com opcoes e uma recomendacao. Roteia para ork gate request."
|
|
4
4
|
bucket: governance
|
|
5
|
-
roteia: "ork gate
|
|
5
|
+
roteia: "ork gate request <thread>"
|
|
6
6
|
license: MIT
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -25,8 +25,8 @@ atras de "detalhe tecnico": ela classifica, registra o que e delegado e sobe o q
|
|
|
25
25
|
## Como rotear
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
ork gate
|
|
29
|
-
ork phase list <thread>
|
|
28
|
+
ork gate request <thread> # abre o pedido; o humano responde pelo canal autenticado
|
|
29
|
+
ork phase list <thread> # a auditoria de delegacao le daqui
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## Conduta
|
|
@@ -25,7 +25,7 @@ nao existe nao vira promessa em README.
|
|
|
25
25
|
```bash
|
|
26
26
|
ork verify <thread> # o que a maquina realmente prova hoje
|
|
27
27
|
ork phase list <thread> # a origem de cada evidencia citada
|
|
28
|
-
ork master --
|
|
28
|
+
ork master --todas # o que ja foi fechado e pode ser citado como entregue
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
## As regras do canon
|
|
@@ -20,7 +20,7 @@ silencio. **Demanda que vira thread sem estar registrada e trabalho sem dono e s
|
|
|
20
20
|
ork board # o estado de todas as threads
|
|
21
21
|
ork board plan # quem avanca agora, quem espera e por que
|
|
22
22
|
ork thread new "<nome>" --mode <modo>
|
|
23
|
-
ork master
|
|
23
|
+
ork master # as entregas, com o indice derivado do ledger
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Conduta
|
|
@@ -22,7 +22,7 @@ ork thread status <thread> # o estado gravado cruzado com o runtime real
|
|
|
22
22
|
ork sessions --all # as sessoes vivas do runtime
|
|
23
23
|
ork claims list <thread> # as alegacoes e o estado de cada uma
|
|
24
24
|
ork board # todas as threads, uma visao
|
|
25
|
-
ork master
|
|
25
|
+
ork master # as entregas, com o indice derivado do ledger
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## O que o rastro precisa responder
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: check-quality
|
|
3
3
|
description: "Fase CHECK (F4): verificacao contra a baseline, os cinco eixos de review, auditoria de seguranca e de performance, auditoria de delegacao e um veredito unico. Roteia para ork verify e para as quatro skills de reviewer."
|
|
4
4
|
bucket: phases
|
|
5
|
-
roteia: "ork verify <thread> | ork gate
|
|
5
|
+
roteia: "ork verify <thread> | ork gate request <thread>"
|
|
6
6
|
license: MIT
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ corrige o que encontra: correcao e trabalho de GO.
|
|
|
20
20
|
ork verify <thread> # reexecuta claims e verify contra a baseline
|
|
21
21
|
ork phase list <thread> # o ledger, para a auditoria de delegacao
|
|
22
22
|
ork worktree audit <thread> # a worktree confere no proprio git
|
|
23
|
-
ork gate
|
|
23
|
+
ork gate request <thread> # o pedido da pausa; o humano responde pelo canal autenticado
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Quando o veredito e PRECISA DE MUDANCA, o sub-loop GO-FIX / CHECK-REVERIFY do bloco B3 e
|
|
@@ -21,7 +21,7 @@ ork thread new "<nome>" --mode <modo>
|
|
|
21
21
|
ork phase run <thread> GOAL --prompt "<pedido do builder>"
|
|
22
22
|
ork claims add <thread> <arquivo> --claim "<alegacao>" --verificar "<comando>" --fase GOAL
|
|
23
23
|
ork verify <thread> --so-claims
|
|
24
|
-
ork gate
|
|
24
|
+
ork gate request <thread>
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## O que o GOAL entrega
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: master-metrics
|
|
3
|
-
description: "Fase MASTER (F6): POSTMORTEM tipado, MASTER log no contrato congelado ork.master-log/v1 e o score humano de 0 a 5 com justificativa. Roteia para ork master e ork master --
|
|
3
|
+
description: "Fase MASTER (F6): POSTMORTEM tipado, MASTER log no contrato congelado ork.master-log/v1 e o score humano de 0 a 5 com justificativa. Roteia para ork master e ork master --aceitar-omissao."
|
|
4
4
|
bucket: phases
|
|
5
|
-
roteia: "ork master <thread> --score N --justificativa \"...\" | ork master --
|
|
5
|
+
roteia: "ork master <thread> --score N --justificativa \"...\" | ork master --aceitar-omissao"
|
|
6
6
|
license: MIT
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -19,8 +19,9 @@ cumpre. **Uma entrega sem MASTER log nao aconteceu.**
|
|
|
19
19
|
```bash
|
|
20
20
|
ork master classes # as classes de falha do catalogo fixo
|
|
21
21
|
ork master <thread> --score 4 --justificativa "<texto>" --classe base-avancou --por <quem>
|
|
22
|
-
ork master
|
|
23
|
-
ork master --
|
|
22
|
+
ork master # as entregas, com o indice derivado do ledger
|
|
23
|
+
ork master --todas # inclusive as ja pontuadas
|
|
24
|
+
ork master --aceitar-omissao # aceita as entregues, com indice e insumos no ledger
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
## O que o MASTER entrega
|
|
@@ -31,7 +32,8 @@ ork master --batch --todas
|
|
|
31
32
|
2. **MASTER log no contrato `ork.master-log/v1`**, congelado: mudar o contrato sem mudar a versao
|
|
32
33
|
e reprovado, porque contrato de telemetria e contrato publico.
|
|
33
34
|
3. **Score humano inteiro de 0 a 5, com justificativa nao vazia.** O score e do humano, sempre. Nos
|
|
34
|
-
modos sem pausa de MASTER
|
|
35
|
+
modos sem pausa de MASTER a entrega e aceita por omissao, com o indice derivado do ledger, que
|
|
36
|
+
nenhum agente digita; a nota humana, quando vier, sobrescreve.
|
|
35
37
|
4. **Evidencia apontando o ledger e o POSTMORTEM**, com contagem de eventos, sessoes e claims. Log
|
|
36
38
|
sem evidencia e recusado.
|
|
37
39
|
|
|
@@ -50,14 +52,14 @@ grava metade e pior que recusa inteira.
|
|
|
50
52
|
| "Dou 4,5, ficou entre os dois" | O score e inteiro de 0 a 5. Escala com meio ponto vira negociacao, e o que se mede aqui e conducao, nao simpatia. |
|
|
51
53
|
| "A classe de falha dessa foi 'quase deu certo'" | O catalogo e fixo. Classe inventada e recusada, porque classe livre destroi a comparabilidade entre threads. |
|
|
52
54
|
| "Preencho o MASTER log depois, a entrega ja foi" | Uma entrega sem MASTER log nao aconteceu. Fase de aprendizado adiada e fase de aprendizado que nao existe. |
|
|
53
|
-
| "O modo e `#Auto`, entao o score pode ser automatico" | O score e humano em todos os modos. `#Auto` muda quando ele e dado
|
|
55
|
+
| "O modo e `#Auto`, entao o score pode ser automatico" | O score e humano em todos os modos. `#Auto` muda quando ele e dado (a entrega e aceita por omissao e a nota humana sobrescreve), nunca quem da. |
|
|
54
56
|
|
|
55
57
|
## Bandeiras vermelhas
|
|
56
58
|
|
|
57
59
|
- Thread entregue sem `master-log.json`.
|
|
58
60
|
- Score gravado sem nome de quem avaliou.
|
|
59
61
|
- Classe de falha fora do catalogo fixo, ou nenhuma classe numa thread que teve retrabalho.
|
|
60
|
-
-
|
|
62
|
+
- Nota de score digitada por agente em nome do humano.
|
|
61
63
|
|
|
62
64
|
## Verificacao antes de sair da fase
|
|
63
65
|
|
|
@@ -19,7 +19,7 @@ tradeoff do humano: ela despacha a fase pelo `ork` e transforma o plano em taref
|
|
|
19
19
|
```bash
|
|
20
20
|
ork phase run <thread> PLAN --prompt "<pedido do builder>"
|
|
21
21
|
ork lease acquire "path:<glob>" --thread <thread> --motivo "PLAN reservou a regiao"
|
|
22
|
-
ork gate
|
|
22
|
+
ork gate request <thread>
|
|
23
23
|
ork handoff export <thread> --proxima-fase GO
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -18,8 +18,8 @@ o push comparando o sha local com o que o remoto reporta**.
|
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
ork worktree sync <thread> # rebasa quando a base avancou
|
|
21
|
-
ork gate approve <thread> push --por <quem> # autorizacao humana registrada
|
|
22
21
|
ork ship <thread> --para main --dry-run # ensaio: mostra tudo, nao toca em nada
|
|
22
|
+
# autorizacao humana registrada: vai no proprio ship, com o nome de quem autorizou
|
|
23
23
|
ork ship <thread> --para main --autorizar-push <quem>
|
|
24
24
|
ork phase list <thread> # a prova: mergeSha, shaRemoto, pushVerificado
|
|
25
25
|
```
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
# Acrescenta uma mensagem do canal ao mesmo histórico durável visto no Kanban.
|
|
3
|
-
set -eu
|
|
4
|
-
# I-36 (D6): o adaptador declara o canal de conducao do Hermes; descreve a porta, nao da autoridade.
|
|
5
|
-
export ORK_CANAL="${ORK_CANAL:-hermes}"
|
|
6
|
-
|
|
7
|
-
if [ "$#" -lt 3 ]; then
|
|
8
|
-
echo "uso: ork-objective-message.sh <objective-id> <autor-do-canal> <texto>" >&2
|
|
9
|
-
exit 2
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
OBJECTIVE="$1"
|
|
13
|
-
AUTHOR="$2"
|
|
14
|
-
shift 2
|
|
15
|
-
|
|
16
|
-
exec "${ORK_BIN:-ork}" objective message "$OBJECTIVE" \
|
|
17
|
-
--text "$*" --por "$AUTHOR" --role human
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
# Lê o ticket canônico para que o Hermes continue a conversa iniciada no Kanban.
|
|
3
|
-
set -eu
|
|
4
|
-
# I-36 (D6): o adaptador declara o canal de conducao do Hermes; descreve a porta, nao da autoridade.
|
|
5
|
-
export ORK_CANAL="${ORK_CANAL:-hermes}"
|
|
6
|
-
|
|
7
|
-
if [ "$#" -ne 1 ]; then
|
|
8
|
-
echo "uso: ork-objective-status.sh <objective-id>" >&2
|
|
9
|
-
exit 2
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
exec "${ORK_BIN:-ork}" objective status "$1" --json
|