@orkastery/cli 0.2.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 (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/adapters/README.md +22 -0
  4. package/adapters/claude-code/.claude-plugin/marketplace.json +15 -0
  5. package/adapters/claude-code/.claude-plugin/plugin.json +31 -0
  6. package/adapters/claude-code/README.md +102 -0
  7. package/adapters/claude-code/agents/ork-check.md +32 -0
  8. package/adapters/claude-code/agents/ork-go.md +32 -0
  9. package/adapters/claude-code/agents/ork-goal.md +33 -0
  10. package/adapters/claude-code/agents/ork-master.md +32 -0
  11. package/adapters/claude-code/agents/ork-plan.md +32 -0
  12. package/adapters/claude-code/agents/ork-ship.md +32 -0
  13. package/adapters/claude-code/commands/check.md +45 -0
  14. package/adapters/claude-code/commands/go.md +46 -0
  15. package/adapters/claude-code/commands/goal.md +54 -0
  16. package/adapters/claude-code/commands/master.md +42 -0
  17. package/adapters/claude-code/commands/ork.md +37 -0
  18. package/adapters/claude-code/commands/plan.md +47 -0
  19. package/adapters/claude-code/commands/ship.md +45 -0
  20. package/adapters/claude-code/hooks/hooks.json +17 -0
  21. package/adapters/claude-code/hooks/ork-guard.js +130 -0
  22. package/adapters/hermes/README.md +45 -0
  23. package/adapters/hermes/bin/ork-abrir-thread.sh +25 -0
  24. package/adapters/hermes/hermes.plugin.json +21 -0
  25. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +116 -0
  26. package/adapters/openclaw/README.md +63 -0
  27. package/adapters/openclaw/bin/ork-abrir-thread.sh +24 -0
  28. package/adapters/openclaw/openclaw.plugin.json +138 -0
  29. package/dist/adapters/claude-bg.js +308 -0
  30. package/dist/auditoria.js +848 -0
  31. package/dist/auditrun.js +976 -0
  32. package/dist/board.js +314 -0
  33. package/dist/canarios.js +271 -0
  34. package/dist/catalogo.js +124 -0
  35. package/dist/ciclos.js +156 -0
  36. package/dist/claims.js +226 -0
  37. package/dist/divida.js +374 -0
  38. package/dist/doctor.js +246 -0
  39. package/dist/evalrunner.js +458 -0
  40. package/dist/fix.js +450 -0
  41. package/dist/gates.js +92 -0
  42. package/dist/handoff.js +521 -0
  43. package/dist/hosts.js +331 -0
  44. package/dist/index.js +1910 -0
  45. package/dist/init.js +231 -0
  46. package/dist/leases.js +508 -0
  47. package/dist/ledger.js +138 -0
  48. package/dist/manifest.js +255 -0
  49. package/dist/master.js +453 -0
  50. package/dist/memoria.js +773 -0
  51. package/dist/modos.js +220 -0
  52. package/dist/orkmind.js +487 -0
  53. package/dist/orquestracao.js +559 -0
  54. package/dist/phase.js +572 -0
  55. package/dist/policies.js +176 -0
  56. package/dist/prompts.js +406 -0
  57. package/dist/ratelimit.js +179 -0
  58. package/dist/recall.js +252 -0
  59. package/dist/retry.js +917 -0
  60. package/dist/sandbox.js +94 -0
  61. package/dist/sessoes.js +104 -0
  62. package/dist/ship.js +551 -0
  63. package/dist/slug.js +100 -0
  64. package/dist/superficie.js +1347 -0
  65. package/dist/thread.js +333 -0
  66. package/dist/tokens.js +228 -0
  67. package/dist/types.js +20 -0
  68. package/dist/util.js +156 -0
  69. package/dist/verify.js +262 -0
  70. package/dist/worktree.js +576 -0
  71. package/dist/yaml.js +112 -0
  72. package/eval/README.md +85 -0
  73. package/eval/casos/check-quality.json +103 -0
  74. package/eval/casos/code-reviewer.json +102 -0
  75. package/eval/casos/decision-triage.json +103 -0
  76. package/eval/casos/go-implementation.json +103 -0
  77. package/eval/casos/goal-definition.json +103 -0
  78. package/eval/casos/master-metrics.json +103 -0
  79. package/eval/casos/narrative-guardian.json +163 -0
  80. package/eval/casos/orkastery-bootstrap.json +102 -0
  81. package/eval/casos/plan-specification.json +102 -0
  82. package/eval/casos/roadmap-keeper.json +103 -0
  83. package/eval/casos/scope-check-capability-map.json +83 -0
  84. package/eval/casos/security-auditor.json +102 -0
  85. package/eval/casos/ship-release.json +122 -0
  86. package/eval/casos/test-engineer.json +122 -0
  87. package/eval/casos/thread-state.json +82 -0
  88. package/eval/casos/thread-tracing.json +83 -0
  89. package/eval/casos/web-performance-auditor.json +102 -0
  90. package/eval/fixtures/b0-slug-e-modos/caso.json +56 -0
  91. package/eval/fixtures/b2-master-log/caso.json +91 -0
  92. package/eval/fixtures/fx-concurrency/caso.json +15 -0
  93. package/eval/fixtures/fx-hallucination/caso.json +12 -0
  94. package/eval/fixtures/fx-happy/caso.json +16 -0
  95. package/eval/fixtures/fx-schema-drift/caso.json +15 -0
  96. package/eval/fixtures/fx-stale-base/caso.json +12 -0
  97. package/eval/fixtures/fx-wiki-destroy/caso.json +16 -0
  98. package/eval/fixtures/superficie-de-rede/README.md +22 -0
  99. package/eval/fixtures/superficie-de-rede/api-express.js +30 -0
  100. package/eval/fixtures/superficie-de-rede/api_fastapi.py +17 -0
  101. package/eval/fixtures/superficie-de-rede/api_gin.go +18 -0
  102. package/package.json +56 -0
  103. package/references/README.md +25 -0
  104. package/references/code-review-axes.md +82 -0
  105. package/references/definition-of-done.md +74 -0
  106. package/references/performance-checklist.md +53 -0
  107. package/references/security-checklist.md +101 -0
  108. package/references/testing-patterns.md +51 -0
  109. package/skills/README.md +43 -0
  110. package/skills/core/orkastery-bootstrap/SKILL.md +89 -0
  111. package/skills/core/thread-state/SKILL.md +86 -0
  112. package/skills/governance/decision-triage/SKILL.md +65 -0
  113. package/skills/governance/narrative-guardian/SKILL.md +66 -0
  114. package/skills/governance/roadmap-keeper/SKILL.md +60 -0
  115. package/skills/governance/scope-check-capability-map/SKILL.md +61 -0
  116. package/skills/observability/thread-tracing/SKILL.md +63 -0
  117. package/skills/phases/check-quality/SKILL.md +87 -0
  118. package/skills/phases/go-implementation/SKILL.md +70 -0
  119. package/skills/phases/goal-definition/SKILL.md +69 -0
  120. package/skills/phases/master-metrics/SKILL.md +65 -0
  121. package/skills/phases/plan-specification/SKILL.md +67 -0
  122. package/skills/phases/ship-release/SKILL.md +68 -0
  123. package/skills/reviewers/code-reviewer/SKILL.md +61 -0
  124. package/skills/reviewers/security-auditor/SKILL.md +68 -0
  125. package/skills/reviewers/test-engineer/SKILL.md +66 -0
  126. package/skills/reviewers/web-performance-auditor/SKILL.md +63 -0
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ /**
3
+ * Onde mora o catalogo do produto (bloco B4).
4
+ *
5
+ * O `ork` roda de dentro de `core/dist`, de `core/dist-test` e, instalado, de qualquer lugar
6
+ * do PATH, mas o catalogo de skills, as checklists normativas e os adaptadores de host sao
7
+ * arquivos do produto, nao codigo compilado. Este modulo resolve essa raiz uma unica vez, em
8
+ * um lugar so, para nao existirem duas regras de "onde estao as skills" divergindo em
9
+ * silencio (que e exatamente o defeito que os proprios evals cacam nas skills).
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.BUCKETS = void 0;
46
+ exports.raizDoCatalogo = raizDoCatalogo;
47
+ exports.exigirCatalogo = exigirCatalogo;
48
+ exports.skillsDoCatalogo = skillsDoCatalogo;
49
+ exports.referenciasDoCatalogo = referenciasDoCatalogo;
50
+ const fs = __importStar(require("node:fs"));
51
+ const path = __importStar(require("node:path"));
52
+ /** O que precisa existir para um diretorio ser a raiz do catalogo. */
53
+ const MARCAS = ['skills', 'references', 'eval'];
54
+ function ehRaizDoCatalogo(dir) {
55
+ return MARCAS.every((m) => fs.existsSync(path.join(dir, m)));
56
+ }
57
+ function subirProcurando(inicial) {
58
+ let atual = path.resolve(inicial);
59
+ for (;;) {
60
+ if (ehRaizDoCatalogo(atual))
61
+ return atual;
62
+ const pai = path.dirname(atual);
63
+ if (pai === atual)
64
+ return null;
65
+ atual = pai;
66
+ }
67
+ }
68
+ /**
69
+ * A raiz do catalogo: o diretorio que tem `skills/`, `references/` e `eval/`.
70
+ *
71
+ * Procura a partir do diretorio informado (ou do cwd) e depois a partir do proprio codigo,
72
+ * que e o caminho que vale quando o `ork` roda instalado, fora do repositorio do produto.
73
+ */
74
+ function raizDoCatalogo(inicial) {
75
+ return subirProcurando(inicial ?? process.cwd()) ?? subirProcurando(__dirname);
76
+ }
77
+ /** A raiz do catalogo, com erro tipado quando o `ork` nao consegue achar o produto. */
78
+ function exigirCatalogo(inicial) {
79
+ const raiz = raizDoCatalogo(inicial);
80
+ if (!raiz) {
81
+ throw new Error('catalogo do Orkastery nao encontrado (esperado um diretorio com skills/, references/ e eval/)');
82
+ }
83
+ return raiz;
84
+ }
85
+ /** Os buckets do catalogo, na ordem em que o README os apresenta. */
86
+ exports.BUCKETS = [
87
+ 'core',
88
+ 'phases',
89
+ 'reviewers',
90
+ 'governance',
91
+ 'observability',
92
+ ];
93
+ /** Todas as skills do catalogo, varridas do disco (nunca de uma lista escrita a mao). */
94
+ function skillsDoCatalogo(raiz) {
95
+ const achadas = [];
96
+ for (const bucket of exports.BUCKETS) {
97
+ const dirBucket = path.join(raiz, 'skills', bucket);
98
+ if (!fs.existsSync(dirBucket))
99
+ continue;
100
+ for (const nome of fs.readdirSync(dirBucket).sort()) {
101
+ const caminho = path.join(dirBucket, nome, 'SKILL.md');
102
+ if (!fs.existsSync(caminho))
103
+ continue;
104
+ achadas.push({
105
+ nome,
106
+ bucket,
107
+ caminho,
108
+ relativo: path.join('skills', bucket, nome, 'SKILL.md'),
109
+ });
110
+ }
111
+ }
112
+ return achadas;
113
+ }
114
+ /** As 5 checklists normativas citaveis por item (`DoD 4`, `SEC 5`). */
115
+ function referenciasDoCatalogo(raiz) {
116
+ const dir = path.join(raiz, 'references');
117
+ if (!fs.existsSync(dir))
118
+ return [];
119
+ return fs
120
+ .readdirSync(dir)
121
+ .filter((a) => a.endsWith('.md'))
122
+ .sort()
123
+ .map((a) => path.join(dir, a));
124
+ }
package/dist/ciclos.js ADDED
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ /**
3
+ * Variantes de ciclo (`ork thread new --ciclo`), portadas do Devmaster (bloco B2).
4
+ *
5
+ * A variante NAO muda a verificacao nem os gates: ela muda como a thread NASCE.
6
+ * Ou o desenho dos blocos de loop (`goal-plan` funde GOAL e PLAN; `gap` publica a
7
+ * lacuna sem GO e sem SHIP), ou a arvore de onde ela parte (`merge-branch` parte de
8
+ * uma branch que ja existe; `greenfield` exige worktree isolada).
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ORDEM_DAS_VARIANTES = exports.VARIANTES = void 0;
12
+ exports.parseVariante = parseVariante;
13
+ exports.definicaoDaVariante = definicaoDaVariante;
14
+ exports.fundirGoalPlan = fundirGoalPlan;
15
+ exports.somenteAnalise = somenteAnalise;
16
+ exports.aplicarVariante = aplicarVariante;
17
+ exports.tabelaDeVariantes = tabelaDeVariantes;
18
+ const modos_1 = require("./modos");
19
+ /** As 5 variantes de ciclo, com o que cada uma muda na criacao da thread. */
20
+ exports.VARIANTES = {
21
+ greenfield: {
22
+ variante: 'greenfield',
23
+ descricao: 'Comeco do zero: worktree isolada obrigatoria, partindo da base do manifesto',
24
+ exigeBranch: false,
25
+ exigeWorktree: true,
26
+ mudaBlocos: false,
27
+ },
28
+ 'merge-branch': {
29
+ variante: 'merge-branch',
30
+ descricao: 'Parte de uma branch que ja existe (`--branch`), sem criar branch nova',
31
+ exigeBranch: true,
32
+ exigeWorktree: true,
33
+ mudaBlocos: false,
34
+ },
35
+ 'goal-plan': {
36
+ variante: 'goal-plan',
37
+ descricao: 'Funde GOAL e PLAN num bloco so: uma pausa a menos quando o modo os separava',
38
+ exigeBranch: false,
39
+ exigeWorktree: false,
40
+ mudaBlocos: true,
41
+ },
42
+ gap: {
43
+ variante: 'gap',
44
+ descricao: 'Analise de lacuna: sem GO e sem SHIP, a lacuna e publicada como lacuna',
45
+ exigeBranch: false,
46
+ exigeWorktree: false,
47
+ mudaBlocos: true,
48
+ },
49
+ 'feature-xl-faseada': {
50
+ variante: 'feature-xl-faseada',
51
+ descricao: 'Feature grande em fatias: o PLAN se compromete com N fatias verificaveis',
52
+ exigeBranch: false,
53
+ exigeWorktree: true,
54
+ mudaBlocos: false,
55
+ },
56
+ };
57
+ /** Ordem de apresentacao das variantes no CLI. */
58
+ exports.ORDEM_DAS_VARIANTES = [
59
+ 'greenfield',
60
+ 'merge-branch',
61
+ 'goal-plan',
62
+ 'gap',
63
+ 'feature-xl-faseada',
64
+ ];
65
+ /** Parseia `--ciclo`. Retorna null quando a variante nao existe. */
66
+ function parseVariante(bruto) {
67
+ if (!bruto)
68
+ return null;
69
+ const limpo = bruto.trim().toLowerCase();
70
+ return exports.ORDEM_DAS_VARIANTES.includes(limpo)
71
+ ? limpo
72
+ : null;
73
+ }
74
+ /** Definicao de uma variante, com erro claro quando ela nao existe. */
75
+ function definicaoDaVariante(variante) {
76
+ const def = exports.VARIANTES[variante];
77
+ if (!def)
78
+ throw new Error(`variante de ciclo desconhecida: ${variante}`);
79
+ return def;
80
+ }
81
+ function refazerBloco(fases, pausa, pausaSobre) {
82
+ return { fases, pausa, pausaSobre, slugFases: (0, modos_1.slugDasFases)(fases) };
83
+ }
84
+ /**
85
+ * Funde os blocos que conduzem GOAL e PLAN num bloco unico.
86
+ *
87
+ * Idempotente: em `#Default`, `#Maestro` e `#Auto` o GOAL e o PLAN ja vivem no mesmo
88
+ * bloco e nada muda. Em `#Look` e `#Ork` a fusao economiza exatamente uma pausa.
89
+ */
90
+ function fundirGoalPlan(blocos) {
91
+ const envolvidos = blocos.filter((b) => b.fases.includes('GOAL') || b.fases.includes('PLAN'));
92
+ if (envolvidos.length <= 1)
93
+ return blocos.map((b) => ({ ...b }));
94
+ const fases = envolvidos.flatMap((b) => b.fases);
95
+ const pausa = envolvidos.some((b) => b.pausa);
96
+ const pausaSobre = pausa ? 'premissas' : '';
97
+ const fundido = refazerBloco(fases, pausa, pausaSobre);
98
+ const saida = [];
99
+ let inserido = false;
100
+ for (const b of blocos) {
101
+ if (envolvidos.includes(b)) {
102
+ if (!inserido) {
103
+ saida.push(fundido);
104
+ inserido = true;
105
+ }
106
+ continue;
107
+ }
108
+ saida.push({ ...b });
109
+ }
110
+ return saida;
111
+ }
112
+ /** Tira GO e SHIP do ciclo: a thread de gap analisa e publica, nao implementa nem entrega. */
113
+ function somenteAnalise(blocos) {
114
+ const fora = ['GO', 'SHIP'];
115
+ const saida = [];
116
+ for (const b of blocos) {
117
+ const fases = b.fases.filter((f) => !fora.includes(f));
118
+ if (fases.length === 0)
119
+ continue;
120
+ // A pausa sobrevive so quando a fase que a motivava sobreviveu.
121
+ const ultima = b.fases[b.fases.length - 1];
122
+ const pausa = b.pausa && fases.includes(ultima);
123
+ saida.push(refazerBloco(fases, pausa, pausa ? b.pausaSobre : ''));
124
+ }
125
+ if (saida.length === 0)
126
+ throw new Error('a variante gap removeu todas as fases do ciclo');
127
+ return saida;
128
+ }
129
+ /** Aplica a variante ao desenho de blocos do modo. Variante nula devolve os blocos como estao. */
130
+ function aplicarVariante(blocos, variante) {
131
+ if (!variante)
132
+ return blocos.map((b) => ({ ...b }));
133
+ if (variante === 'goal-plan')
134
+ return fundirGoalPlan(blocos);
135
+ if (variante === 'gap')
136
+ return somenteAnalise(blocos);
137
+ return blocos.map((b) => ({ ...b }));
138
+ }
139
+ /** Tabela das variantes de ciclo, usada por `ork ciclos`. */
140
+ function tabelaDeVariantes() {
141
+ const linhas = ['Variantes de ciclo (`ork thread new --ciclo <variante>`)', ''];
142
+ for (const v of exports.ORDEM_DAS_VARIANTES) {
143
+ const def = exports.VARIANTES[v];
144
+ const exige = [];
145
+ if (def.exigeBranch)
146
+ exige.push('--branch <existente>');
147
+ if (def.exigeWorktree)
148
+ exige.push('worktree isolada');
149
+ linhas.push(` ${v.padEnd(20)} ${def.descricao}`);
150
+ linhas.push(` ${''.padEnd(20)} exige: ${exige.join(', ') || 'nada'} | ` +
151
+ `muda os blocos do modo: ${def.mudaBlocos ? 'sim' : 'nao'}`);
152
+ }
153
+ linhas.push('');
154
+ linhas.push('A variante muda como a thread NASCE. Verificacao e gates nao mudam.');
155
+ return linhas.join('\n');
156
+ }
package/dist/claims.js ADDED
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ /**
3
+ * Claims: o protocolo de alegacoes verificaveis (bloco B1).
4
+ *
5
+ * Uma fase nao "diz" que algo funciona: ela registra uma CLAIM com o comando que a
6
+ * comprova, e o `ork verify` reexecuta esse comando no HEAD real. Self-report nao vale
7
+ * como evidencia em nenhum modo de conducao.
8
+ *
9
+ * O caso EvoJ6 (alegacao negativa falsa que passou batido) e tratado aqui na origem:
10
+ * alegacao negativa ou absoluta ("nenhum", "zero", "sempre", "nunca") SEM comando de
11
+ * verificacao reprova no gate, porque nao existe como comprova-la depois.
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.caminhoClaims = caminhoClaims;
48
+ exports.lerClaims = lerClaims;
49
+ exports.proximoIdDeClaim = proximoIdDeClaim;
50
+ exports.ehAlegacaoNegativa = ehAlegacaoNegativa;
51
+ exports.montarClaim = montarClaim;
52
+ exports.gravarClaim = gravarClaim;
53
+ exports.adicionarClaim = adicionarClaim;
54
+ exports.exigirClaim = exigirClaim;
55
+ exports.anexarComando = anexarComando;
56
+ exports.retirarClaim = retirarClaim;
57
+ exports.carimbarEstado = carimbarEstado;
58
+ exports.tabelaDeClaims = tabelaDeClaims;
59
+ const path = __importStar(require("node:path"));
60
+ const ledger_1 = require("./ledger");
61
+ const thread_1 = require("./thread");
62
+ const util_1 = require("./util");
63
+ /** Caminho do `claims.jsonl` da thread (append-only, como o ledger). */
64
+ function caminhoClaims(raiz, threadId) {
65
+ return path.join((0, thread_1.dirThread)(raiz, threadId), 'claims.jsonl');
66
+ }
67
+ /** Le as claims da thread (armazem JSONL: a ultima gravacao de um id vence). */
68
+ function lerClaims(raiz, threadId) {
69
+ return (0, util_1.lerJsonl)(caminhoClaims(raiz, threadId));
70
+ }
71
+ /** Proximo id sequencial (`C1`, `C2`, ...) dentro da thread. */
72
+ function proximoIdDeClaim(claims) {
73
+ return (0, util_1.proximoIdSequencial)(claims.map((c) => c.id), 'C');
74
+ }
75
+ /** Palavras que tornam uma alegacao negativa ou absoluta, portanto nao auditavel a olho. */
76
+ const TERMOS_ABSOLUTOS = [
77
+ 'nenhum',
78
+ 'nenhuma',
79
+ 'nunca',
80
+ 'sempre',
81
+ 'zero',
82
+ 'todos',
83
+ 'todas',
84
+ 'nao ha',
85
+ 'nao existe',
86
+ 'nao resta',
87
+ 'sem nenhum',
88
+ '100%',
89
+ 'totalmente',
90
+ 'completamente',
91
+ ];
92
+ /** A alegacao e negativa/absoluta (exige comando de verificacao)? */
93
+ function ehAlegacaoNegativa(texto) {
94
+ const normalizado = texto
95
+ .normalize('NFD')
96
+ .replace(/[\u0300-\u036f]/g, '')
97
+ .toLowerCase();
98
+ return TERMOS_ABSOLUTOS.some((t) => normalizado.includes(t));
99
+ }
100
+ /**
101
+ * Monta a claim a partir dos dados brutos, SEM tocar em disco.
102
+ *
103
+ * E aqui que mora a regra de construcao de uma alegacao: quem e negativa/absoluta, e que
104
+ * uma alegacao sem comando ja nasce `nao-verificavel`. A funcao e pura de proposito: o
105
+ * auditor periodico do bloco B5 registra achados com esta MESMA regra, sem reimplementa-la
106
+ * e sem afrouxa-la (o auditor tambem nao tem direito a self-report).
107
+ */
108
+ function montarClaim(entrada) {
109
+ const verificar = (entrada.verificar ?? []).filter((c) => c.trim() !== '');
110
+ return {
111
+ id: entrada.id,
112
+ thread: entrada.dono,
113
+ fase: entrada.fase,
114
+ arquivo: entrada.arquivo,
115
+ alegacao: entrada.alegacao.trim(),
116
+ negativa: ehAlegacaoNegativa(entrada.alegacao),
117
+ verificar,
118
+ criadoEm: (0, util_1.agora)(),
119
+ estado: verificar.length > 0 ? 'pendente' : 'nao-verificavel',
120
+ };
121
+ }
122
+ /** Grava uma claim no `claims.jsonl` (append-only). */
123
+ function gravarClaim(raiz, claim) {
124
+ (0, util_1.anexarJsonl)(caminhoClaims(raiz, claim.thread), claim);
125
+ }
126
+ /** `ork claims add`: registra a alegacao e a lista no `thread.json` e no ledger. */
127
+ function adicionarClaim(raiz, threadId, opcoes) {
128
+ const thread = (0, thread_1.lerThread)(raiz, threadId);
129
+ const existentes = lerClaims(raiz, threadId);
130
+ const claim = montarClaim({
131
+ id: proximoIdDeClaim(existentes),
132
+ dono: threadId,
133
+ fase: opcoes.fase ?? thread.faseAtual,
134
+ arquivo: opcoes.arquivo,
135
+ alegacao: opcoes.alegacao,
136
+ verificar: opcoes.verificar,
137
+ });
138
+ const negativa = claim.negativa;
139
+ const verificar = claim.verificar;
140
+ gravarClaim(raiz, claim);
141
+ thread.claims = [...new Set([...(thread.claims ?? []), claim.id])];
142
+ (0, thread_1.gravarThread)(raiz, thread);
143
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.claimRegistrada, {
144
+ claim: claim.id,
145
+ fase: claim.fase,
146
+ arquivo: claim.arquivo,
147
+ alegacao: claim.alegacao,
148
+ negativa,
149
+ verificar,
150
+ estado: claim.estado,
151
+ });
152
+ return claim;
153
+ }
154
+ /** Acha a claim pelo id, com erro acionavel quando ela nao existe. */
155
+ function exigirClaim(raiz, threadId, claimId) {
156
+ const claim = lerClaims(raiz, threadId).find((c) => c.id === claimId);
157
+ if (!claim) {
158
+ throw new Error(`claim "${claimId}" nao existe na thread ${threadId}`);
159
+ }
160
+ return claim;
161
+ }
162
+ /**
163
+ * Anexa um comando de verificacao a uma claim ja registrada.
164
+ *
165
+ * E o caminho de correcao da alegacao negativa sem comando: em vez de apagar a alegacao
166
+ * do historico, o autor declara COMO ela se comprova, e o append mais novo passa a valer.
167
+ */
168
+ function anexarComando(raiz, threadId, claimId, comando) {
169
+ const claim = exigirClaim(raiz, threadId, claimId);
170
+ const atualizada = {
171
+ ...claim,
172
+ verificar: [...claim.verificar, comando],
173
+ estado: 'pendente',
174
+ };
175
+ gravarClaim(raiz, atualizada);
176
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.claimRegistrada, {
177
+ claim: claimId,
178
+ alteracao: 'comando de verificacao anexado',
179
+ verificar: atualizada.verificar,
180
+ estado: atualizada.estado,
181
+ });
182
+ return atualizada;
183
+ }
184
+ /**
185
+ * Retira uma claim, com motivo obrigatorio.
186
+ *
187
+ * O `claims.jsonl` e append-only: a alegacao errada continua no historico, com a retirada
188
+ * registrada em cima. `ork verify` para de exigir prova dela, e o ledger guarda o porque.
189
+ */
190
+ function retirarClaim(raiz, threadId, claimId, motivo) {
191
+ const claim = exigirClaim(raiz, threadId, claimId);
192
+ const atualizada = { ...claim, estado: 'retirada', motivoDaRetirada: motivo };
193
+ gravarClaim(raiz, atualizada);
194
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.claimRegistrada, {
195
+ claim: claimId,
196
+ alteracao: 'claim retirada',
197
+ alegacao: claim.alegacao,
198
+ motivoDaRetirada: motivo,
199
+ estado: 'retirada',
200
+ });
201
+ return atualizada;
202
+ }
203
+ /** Regrava a claim com o estado carimbado pelo `ork verify` (o append mais novo vence). */
204
+ function carimbarEstado(raiz, claim, estado) {
205
+ const atualizada = { ...claim, estado };
206
+ gravarClaim(raiz, atualizada);
207
+ return atualizada;
208
+ }
209
+ /** Tabela de `ork claims list`. */
210
+ function tabelaDeClaims(raiz, threadId) {
211
+ const claims = lerClaims(raiz, threadId);
212
+ if (claims.length === 0) {
213
+ return (`Nenhuma claim na thread ${threadId}.\n` +
214
+ `Registre uma com: ork claims add ${threadId} <arquivo> --claim "<alegacao>" --verificar "<comando>"`);
215
+ }
216
+ const linhas = claims.map((c) => [
217
+ c.id,
218
+ c.fase ?? '-',
219
+ c.estado,
220
+ c.negativa ? 'sim' : 'nao',
221
+ c.arquivo,
222
+ c.verificar.join(' && ') || '(sem comando)',
223
+ c.alegacao,
224
+ ]);
225
+ return (0, util_1.tabela)(['ID', 'FASE', 'ESTADO', 'NEGATIVA', 'ARQUIVO', 'VERIFICAR', 'ALEGACAO'], linhas);
226
+ }