@orkastery/cli 0.2.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/LICENSE +1 -1
- package/README.md +86 -65
- package/adapters/README.md +30 -15
- package/adapters/claude-code/.claude-plugin/plugin.json +11 -5
- package/adapters/claude-code/README.md +110 -8
- 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/onboarding.md +21 -0
- package/adapters/claude-code/commands/ork.md +99 -27
- package/adapters/claude-code/hooks/hooks.json +6 -1
- package/adapters/claude-code/hooks/ork-guard.js +1 -1
- package/adapters/claude-code/hooks/ork-sensor.js +66 -0
- package/adapters/codex/skills/ork/SKILL.md +57 -0
- package/adapters/hermes/README.md +161 -0
- package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
- package/adapters/hermes/bin/ork-brain.sh +4 -0
- package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
- package/adapters/hermes/bin/ork-maestro.sh +6 -0
- package/adapters/hermes/bin/ork-master-enviar.py +84 -0
- package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
- package/adapters/hermes/hermes.plugin.json +24 -4
- package/adapters/hermes/hitl-ingress/__init__.py +356 -0
- package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
- package/adapters/openclaw/README.md +136 -27
- package/adapters/openclaw/bin/ork-brain.sh +4 -0
- package/adapters/openclaw/construir.sh +19 -0
- package/adapters/openclaw/dist/hitl-ingress.js +199 -0
- package/adapters/openclaw/dist/index.js +437 -0
- package/adapters/openclaw/openclaw.plugin.json +39 -134
- package/adapters/openclaw/package.json +26 -0
- package/adapters/openclaw/src/hitl-ingress.ts +180 -0
- package/adapters/openclaw/src/index.ts +460 -0
- package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
- package/adapters/openclaw/tsconfig.json +15 -0
- package/assets/docs/markdownlint-cli2.jsonc +22 -0
- package/assets/docs/padroes/documentacao-de-produto.md +133 -0
- package/assets/docs/padroes/roadmap-de-produto.md +98 -0
- package/assets/docs/produto/README.md +14 -0
- package/assets/docs/produto/_modelo-feature.md +59 -0
- package/assets/docs/roadmap/README.md +14 -0
- package/assets/docs/roadmap/_modelo-item.md +73 -0
- package/assets/orkmind-native-schema.json +32 -0
- package/assets/orkmind_bridge.py +357 -0
- package/assets/orkmind_fixture.py +67 -0
- package/assets/orkmind_prospective.py +138 -0
- package/assets/reference-tariffs-i07.json +23 -0
- package/dist/adapters/claude-bg.js +488 -39
- package/dist/adapters/codex-controller-sensor.js +449 -0
- package/dist/adapters/codex-controller-worker.js +361 -0
- package/dist/adapters/codex-controller.js +252 -0
- package/dist/adapters/codex-events.js +205 -0
- package/dist/adapters/codex-question.js +26 -0
- package/dist/adapters/codex-runner.js +133 -0
- package/dist/adapters/codex.js +394 -0
- package/dist/agents-md.js +84 -0
- package/dist/auditoria.js +12 -9
- package/dist/auditrun.js +5 -4
- package/dist/board.js +174 -23
- package/dist/branch-de-estado.js +136 -0
- package/dist/canarios-hitl.js +177 -0
- package/dist/canarios-i43.js +543 -0
- package/dist/canarios-pulse.js +147 -0
- package/dist/canarios-sensores.js +129 -0
- package/dist/canarios.js +111 -2
- package/dist/catalogo.js +9 -0
- package/dist/ci.js +223 -0
- package/dist/ciclos.js +2 -1
- package/dist/claim-lint.js +64 -0
- package/dist/claims.js +60 -0
- package/dist/company-brain-capture.js +195 -0
- package/dist/company-brain-cli.js +123 -0
- package/dist/company-brain-client.js +61 -0
- package/dist/company-brain-contract.js +166 -0
- package/dist/company-brain-journal.js +192 -0
- package/dist/company-brain-mcp.js +33 -0
- package/dist/company-brain-migration.js +60 -0
- package/dist/company-brain-source.js +177 -0
- package/dist/company-brain-worker.js +18 -0
- package/dist/conducao-texto.js +61 -0
- package/dist/conducao.js +876 -0
- package/dist/contrato-publico.js +39 -0
- package/dist/creation-operation-store.js +251 -0
- package/dist/creation-operation.js +148 -0
- package/dist/decisao-autonoma.js +183 -0
- package/dist/delegation.js +79 -0
- package/dist/demo.js +120 -0
- package/dist/docs.js +828 -0
- package/dist/doctor.js +184 -25
- package/dist/entrega-pr.js +117 -0
- package/dist/escopo-escrita.js +71 -0
- package/dist/estado-thread.js +222 -0
- package/dist/evalrunner.js +12 -0
- package/dist/fabrica-estado.js +329 -0
- package/dist/fabrica-publicar.js +76 -0
- package/dist/fix.js +22 -1
- package/dist/gates.js +59 -11
- package/dist/handoff.js +39 -23
- package/dist/hitl-canais.js +333 -0
- package/dist/hitl-classificacao.js +131 -0
- package/dist/hitl-contract.js +465 -0
- package/dist/hitl-estado.js +136 -0
- package/dist/hitl-gates.js +554 -0
- package/dist/hitl-ingress-receipt.js +382 -0
- package/dist/hitl-local-atestado.js +57 -0
- package/dist/hitl-local-receipt.js +328 -0
- package/dist/hitl-local.js +143 -0
- package/dist/hitl-lock.js +139 -0
- package/dist/hitl-lote.js +223 -0
- package/dist/hitl-native-offer.js +97 -0
- package/dist/hitl-native.js +65 -0
- package/dist/hitl-presentation.js +209 -0
- package/dist/hitl-public-receipt.js +176 -0
- package/dist/hitl-resumo.js +209 -0
- package/dist/hitl-sessions.js +475 -0
- package/dist/hitl.js +711 -0
- package/dist/horario.js +269 -0
- package/dist/hosts.js +198 -22
- package/dist/index.js +1741 -94
- package/dist/indice.js +99 -0
- package/dist/init.js +28 -3
- package/dist/integracoes-locais.js +17 -0
- package/dist/leases.js +65 -21
- package/dist/ledger-stats.js +272 -0
- package/dist/ledger.js +109 -2
- package/dist/licoes.js +221 -0
- package/dist/liveness.js +218 -0
- package/dist/maestro-actions.js +51 -0
- package/dist/maestro-authority.js +152 -0
- package/dist/maestro-cli.js +97 -0
- package/dist/maestro-contract.js +55 -0
- package/dist/maestro-discovery.js +132 -0
- package/dist/maestro-runtime.js +268 -0
- package/dist/maestro-snapshot.js +86 -0
- package/dist/maestro-sources.js +224 -0
- package/dist/manifest.js +165 -6
- package/dist/maquina.js +102 -0
- package/dist/master-audit.js +101 -0
- package/dist/master-batch.js +43 -0
- package/dist/master-digest.js +149 -0
- package/dist/master-migracao.js +155 -0
- package/dist/master.js +361 -77
- package/dist/mcp-artifacts.js +234 -0
- package/dist/mcp-git.js +433 -0
- package/dist/mcp-install.js +310 -0
- package/dist/mcp-maestro.js +25 -0
- package/dist/mcp-server.js +469 -0
- package/dist/mcp-ship.js +436 -0
- package/dist/mcp-verify.js +173 -0
- package/dist/memoria-humana.js +207 -0
- package/dist/memoria.js +314 -78
- package/dist/memory-migration.js +279 -0
- package/dist/memory-prospective.js +148 -0
- package/dist/modos-migracao.js +191 -0
- package/dist/modos.js +151 -15
- package/dist/monitor-lock.js +110 -0
- package/dist/objective.js +449 -0
- package/dist/ocupacao.js +267 -0
- package/dist/onboarding.js +303 -0
- package/dist/orkmind.js +389 -90
- package/dist/orquestracao.js +96 -69
- package/dist/phase.js +612 -151
- package/dist/playbook-capabilities.js +150 -0
- package/dist/playbook-contracts.js +188 -0
- package/dist/policies.js +72 -0
- package/dist/portfolio-context.js +61 -0
- package/dist/portfolio.js +180 -0
- package/dist/preflight.js +207 -0
- package/dist/process-audit.js +112 -0
- package/dist/project-state.js +93 -0
- package/dist/prompts.js +25 -5
- package/dist/prova-minima.js +112 -0
- package/dist/pulse-cadencia.js +163 -0
- package/dist/pulse-consentimento.js +260 -0
- package/dist/pulse-delivery.js +323 -0
- package/dist/pulse-resposta.js +542 -0
- package/dist/pulse.js +262 -0
- package/dist/ratelimit.js +35 -2
- package/dist/recall.js +80 -3
- package/dist/redacao-saida.js +45 -0
- package/dist/redacao-url.js +66 -0
- package/dist/retry.js +640 -118
- package/dist/roadmap-reservas.js +243 -0
- package/dist/runtime-ambiente.js +38 -0
- package/dist/runtime-context.js +215 -0
- package/dist/runtime-profiles.js +869 -0
- package/dist/runtimes.js +103 -0
- package/dist/sandbox.js +9 -0
- package/dist/session-events.js +203 -0
- package/dist/session-watcher-claude.js +637 -0
- package/dist/session-watcher.js +700 -0
- package/dist/sessoes-adopt.js +154 -0
- package/dist/sessoes-inventario.js +159 -0
- package/dist/sessoes.js +16 -35
- package/dist/setup.js +691 -0
- package/dist/ship.js +168 -19
- package/dist/slug.js +1 -1
- package/dist/thread-close.js +115 -0
- package/dist/thread.js +142 -28
- package/dist/tokens.js +1 -1
- package/dist/util.js +4 -2
- package/dist/verify-sandbox.js +265 -0
- package/dist/verify.js +270 -25
- package/dist/versao.js +60 -0
- package/dist/worktree.js +31 -2
- package/dist/write-activation.js +291 -0
- package/dist/yaml.js +5 -1
- package/eval/casos/master-metrics.json +1 -1
- package/eval/casos/onboarding.json +102 -0
- package/eval/casos/orkastery-bootstrap.json +37 -3
- package/eval/casos/scope-check-capability-map.json +45 -7
- package/eval/casos/ship-release.json +3 -3
- package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
- package/eval/fixtures/b2-master-log/caso.json +1 -1
- package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
- package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
- package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
- package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
- package/eval/fixtures/fx-codex-dry/caso.json +18 -0
- package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
- package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
- package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
- package/eval/fixtures/fx-happy/caso.json +6 -4
- package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
- package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
- package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
- package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
- package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
- package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
- package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
- package/eval/fixtures/fx-omnicanal/caso.json +17 -0
- package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
- package/monitor/company-brain.cjs +17 -0
- package/monitor/pulse-scope.cjs +45 -0
- package/monitor/pulse.cron +18 -0
- package/monitor/varredura-pulse.sh +27 -0
- package/package.json +28 -7
- package/references/definition-of-done.md +2 -2
- package/schemas/claims.schema.json +25 -0
- package/schemas/company-brain.schema.json +1158 -0
- package/schemas/creation-operation.schema.json +365 -0
- package/schemas/maestro-snapshot.schema.json +2716 -0
- package/skills/README.md +3 -3
- package/skills/core/onboarding/SKILL.md +50 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
- package/skills/core/thread-state/SKILL.md +3 -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/governance/scope-check-capability-map/SKILL.md +17 -7
- 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/dist/memoria.js
CHANGED
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* A camada de memoria do `ork` (bloco B6): o que o nucleo grava, com que tags, e o que
|
|
4
|
-
* ele injeta de volta no prompt de cada fase.
|
|
5
|
-
*
|
|
6
|
-
* Divisao de trabalho deste bloco:
|
|
7
|
-
* - `orkmind.ts` sabe FALAR com o OrkMind (transporte, degradacao, governanca);
|
|
8
|
-
* - `memoria.ts` (aqui) sabe O QUE o Orkastery grava e le de volta (decisao, handoff,
|
|
9
|
-
* rule, learning, roadmap), e como isso vira contexto de prompt;
|
|
10
|
-
* - `recall.ts` sabe RESOLVER o que ficou fora do prompt, no momento indicado.
|
|
11
|
-
*
|
|
12
|
-
* Nenhuma regra de negocio nova nasce aqui. Decisao, claim, baseline, achado e score
|
|
13
|
-
* continuam sendo do nucleo que ja existe: esta camada os PUBLICA e os RECUPERA.
|
|
14
|
-
*
|
|
15
|
-
* A propriedade que o B6 precisa provar e a da injecao deterministica: um prompt de fase
|
|
16
|
-
* carrega 100 por cento das decisoes fechadas da thread, venham elas do `thread.json`
|
|
17
|
-
* (regime `files`) ou da colecao `decision` (regime `orkmind`). Por isso a injecao NAO
|
|
18
|
-
* depende do OrkMind estar ligado: ela troca de fonte, nao de garantia.
|
|
19
|
-
*/
|
|
20
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
3
|
if (k2 === undefined) k2 = k;
|
|
22
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -51,13 +33,18 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
51
33
|
};
|
|
52
34
|
})();
|
|
53
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.sincronizarOnboarding = sincronizarOnboarding;
|
|
54
37
|
exports.abrirMemoria = abrirMemoria;
|
|
55
38
|
exports.tagsDoProjeto = tagsDoProjeto;
|
|
56
39
|
exports.situacaoDaThread = situacaoDaThread;
|
|
57
40
|
exports.situacaoDaFase = situacaoDaFase;
|
|
58
41
|
exports.skillDaColecao = skillDaColecao;
|
|
42
|
+
exports.agenteDaThread = agenteDaThread;
|
|
59
43
|
exports.tagsDaThread = tagsDaThread;
|
|
60
44
|
exports.gravarDecisoes = gravarDecisoes;
|
|
45
|
+
exports.identidadeDoHandoff = identidadeDoHandoff;
|
|
46
|
+
exports.origemCanonicaDoHandoff = origemCanonicaDoHandoff;
|
|
47
|
+
exports.prepararHandoffGovernado = prepararHandoffGovernado;
|
|
61
48
|
exports.gravarHandoff = gravarHandoff;
|
|
62
49
|
exports.gravarPolicies = gravarPolicies;
|
|
63
50
|
exports.gravarLearning = gravarLearning;
|
|
@@ -79,19 +66,132 @@ exports.publicarPropostas = publicarPropostas;
|
|
|
79
66
|
exports.textoDoEstado = textoDoEstado;
|
|
80
67
|
exports.textoDoSync = textoDoSync;
|
|
81
68
|
exports.parsePrioridade = parsePrioridade;
|
|
69
|
+
const write_activation_1 = require("./write-activation");
|
|
70
|
+
const escopo_escrita_1 = require("./escopo-escrita");
|
|
71
|
+
const project_state_1 = require("./project-state");
|
|
72
|
+
/**
|
|
73
|
+
* A camada de memoria do `ork` (bloco B6): o que o nucleo grava, com que tags, e o que
|
|
74
|
+
* ele injeta de volta no prompt de cada fase.
|
|
75
|
+
*
|
|
76
|
+
* Divisao de trabalho deste bloco:
|
|
77
|
+
* - `orkmind.ts` sabe FALAR com o OrkMind (transporte, degradacao, governanca);
|
|
78
|
+
* - `memoria.ts` (aqui) sabe O QUE o Orkastery grava e le de volta (decisao, handoff,
|
|
79
|
+
* rule, learning, roadmap), e como isso vira contexto de prompt;
|
|
80
|
+
* - `recall.ts` sabe RESOLVER o que ficou fora do prompt, no momento indicado.
|
|
81
|
+
*
|
|
82
|
+
* Nenhuma regra de negocio nova nasce aqui. Decisao, claim, baseline, achado e score
|
|
83
|
+
* continuam sendo do nucleo que ja existe: esta camada os PUBLICA e os RECUPERA.
|
|
84
|
+
*
|
|
85
|
+
* A propriedade que o B6 precisa provar e a da injecao deterministica: um prompt de fase
|
|
86
|
+
* carrega 100 por cento das decisoes fechadas da thread, venham elas do `thread.json`
|
|
87
|
+
* (regime `files`) ou da colecao `decision` (regime `orkmind`). Por isso a injecao NAO
|
|
88
|
+
* depende do OrkMind estar ligado: ela troca de fonte, nao de garantia.
|
|
89
|
+
*/
|
|
82
90
|
const fs = __importStar(require("node:fs"));
|
|
83
91
|
const path = __importStar(require("node:path"));
|
|
92
|
+
const manifest_1 = require("./manifest");
|
|
93
|
+
const onboarding_1 = require("./onboarding");
|
|
94
|
+
const node_crypto_1 = require("node:crypto");
|
|
95
|
+
const node_util_1 = require("node:util");
|
|
96
|
+
const memoria_humana_1 = require("./memoria-humana");
|
|
84
97
|
const master_1 = require("./master");
|
|
85
98
|
const modos_1 = require("./modos");
|
|
86
99
|
const orkmind_1 = require("./orkmind");
|
|
87
100
|
const ledger_1 = require("./ledger");
|
|
88
101
|
const thread_1 = require("./thread");
|
|
89
102
|
const util_1 = require("./util");
|
|
103
|
+
const licoes_1 = require("./licoes");
|
|
104
|
+
/** Publica somente a entrevista deste projeto; jamais percorre threads. */
|
|
105
|
+
function sincronizarOnboarding(carregado, opcoes = {}) {
|
|
106
|
+
carregado = (0, project_state_1.memoryState)(carregado).loaded;
|
|
107
|
+
const estado = (0, onboarding_1.lerOnboarding)(carregado.raiz);
|
|
108
|
+
const etapas = onboarding_1.ETAPAS_ONBOARDING.filter(e => estado.etapas[e] !== null);
|
|
109
|
+
const resultado = { regime: 'files', motivo: null, respondidas: etapas.length,
|
|
110
|
+
gravadas: 0, duplicadas: 0, falhas: 0, detalhe: '' };
|
|
111
|
+
const degradar = (motivo) => {
|
|
112
|
+
resultado.regime = 'files';
|
|
113
|
+
resultado.motivo = motivo;
|
|
114
|
+
resultado.detalhe = 'Entrevista preservada em arquivos; publicação semântica não concluída. Consulte ork memory status.';
|
|
115
|
+
(0, ledger_1.registrar)((0, manifest_1.dirEstado)(carregado.raiz), 'projeto', ledger_1.TIPOS_DE_EVENTO.memoriaDegradada, { origem: 'onboarding', motivo, respondidas: etapas.length, gravadas: resultado.gravadas, falhas: resultado.falhas });
|
|
116
|
+
return resultado;
|
|
117
|
+
};
|
|
118
|
+
// Os detalhes devolvidos por um driver podem conter credenciais. Só expor códigos locais.
|
|
119
|
+
try {
|
|
120
|
+
const memoria = abrirMemoria(carregado, opcoes);
|
|
121
|
+
if (!memoria.ativo)
|
|
122
|
+
return degradar(memoria.estado.motivo ?? 'orkmind.indisponivel');
|
|
123
|
+
const tenant = memoria.estado.tenant;
|
|
124
|
+
for (const etapa of etapas) {
|
|
125
|
+
const resposta = estado.etapas[etapa];
|
|
126
|
+
const identidade = `onboarding:${encodeURIComponent(tenant)}:${etapa}`;
|
|
127
|
+
const r = memoria.gravar({ collection: 'decision', priority: 'medium',
|
|
128
|
+
content: `Onboarding ${onboarding_1.CONTRATO_ONBOARDING} tenant=${JSON.stringify(tenant)} etapa=${etapa}\n${(0, onboarding_1.jsonCanonico)(resposta.conteudo)}`,
|
|
129
|
+
tags: { ...tagsDoProjeto(carregado.manifesto), skill: ['orkastery-onboarding'],
|
|
130
|
+
situation: ['onboarding', identidade] },
|
|
131
|
+
metadata: { identidade, etapa, tenant, por: resposta.por, respondidaEm: resposta.respondidaEm },
|
|
132
|
+
});
|
|
133
|
+
if (!r.ok)
|
|
134
|
+
resultado.falhas++;
|
|
135
|
+
else if (r.duplicada)
|
|
136
|
+
resultado.duplicadas++;
|
|
137
|
+
else
|
|
138
|
+
resultado.gravadas++;
|
|
139
|
+
}
|
|
140
|
+
if (resultado.falhas)
|
|
141
|
+
return degradar('orkmind.indisponivel');
|
|
142
|
+
resultado.regime = 'orkmind';
|
|
143
|
+
resultado.detalhe = `${resultado.gravadas} nova(s), ${resultado.duplicadas} já existente(s); ${etapas.length} etapa(s) publicada(s).`;
|
|
144
|
+
return resultado;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
resultado.falhas++;
|
|
148
|
+
return degradar('orkmind.indisponivel');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function resolverLeituraRestrita(manifesto, contexto) {
|
|
152
|
+
if (contexto === undefined)
|
|
153
|
+
return undefined;
|
|
154
|
+
if (!contexto || typeof contexto !== 'object' || Array.isArray(contexto) ||
|
|
155
|
+
Object.keys(contexto).some(k => !['thread', 'limite'].includes(k)))
|
|
156
|
+
throw Error('memory.query.invalid');
|
|
157
|
+
const q = (0, orkmind_1.validarConsultaDelimitada)({ collection: 'handoff',
|
|
158
|
+
escopo: (0, orkmind_1.criarEscopoDeLeitura)(manifesto, contexto.thread), tags: {},
|
|
159
|
+
limite: contexto.limite === undefined ? orkmind_1.LIMITE_CONSULTA_PADRAO : contexto.limite });
|
|
160
|
+
return Object.freeze({ ...q.escopo, limite: q.limite });
|
|
161
|
+
}
|
|
90
162
|
/** Abre a memoria do projeto, ja com o regime efetivo resolvido. */
|
|
91
163
|
function abrirMemoria(carregado, opcoes = {}) {
|
|
164
|
+
const context = (0, project_state_1.memoryState)(carregado);
|
|
165
|
+
carregado = context.loaded;
|
|
166
|
+
// Pedido invalido nao abre driver nem executa sua verificacao de saude.
|
|
167
|
+
const leituraRestrita = resolverLeituraRestrita(carregado.manifesto, opcoes.leituraRestrita);
|
|
92
168
|
const { estado, driver } = (0, orkmind_1.resolverRegime)(carregado.manifesto, opcoes.driver ?? null);
|
|
93
169
|
const ativo = estado.efetivo === 'orkmind' && driver !== null;
|
|
170
|
+
const consultarRestrito = (collection, tags) => {
|
|
171
|
+
if (!leituraRestrita)
|
|
172
|
+
throw Error('memory.query.invalid');
|
|
173
|
+
const q = (0, orkmind_1.validarConsultaDelimitada)({ collection, tags,
|
|
174
|
+
escopo: { tenant: leituraRestrita.tenant, thread: leituraRestrita.thread }, limite: leituraRestrita.limite });
|
|
175
|
+
if (!ativo || !driver)
|
|
176
|
+
return [];
|
|
177
|
+
if (typeof driver.consultar !== 'function')
|
|
178
|
+
throw Error('memory.query.unsupported');
|
|
179
|
+
return (0, orkmind_1.concluirConsultaDelimitada)(driver.consultar(q), q);
|
|
180
|
+
};
|
|
94
181
|
return {
|
|
182
|
+
configSource: context.source,
|
|
183
|
+
configDivergent: context.divergent,
|
|
184
|
+
get leituraRestrita() { return leituraRestrita; },
|
|
185
|
+
raiz: carregado.raiz,
|
|
186
|
+
submeterHandoff(pedido) {
|
|
187
|
+
if (!ativo || !driver?.submeterHandoff)
|
|
188
|
+
return { ok: false, id: null, duplicada: false,
|
|
189
|
+
collection: 'handoff', detalhe: 'memory.g3.unavailable' };
|
|
190
|
+
if (pedido.tenant !== estado.tenant)
|
|
191
|
+
return { ok: false, id: null, duplicada: false,
|
|
192
|
+
collection: 'handoff', detalhe: 'memory.tenant.mismatch' };
|
|
193
|
+
return driver.submeterHandoff(pedido);
|
|
194
|
+
},
|
|
95
195
|
estado,
|
|
96
196
|
ativo,
|
|
97
197
|
regime: estado.efetivo,
|
|
@@ -118,6 +218,14 @@ function abrirMemoria(carregado, opcoes = {}) {
|
|
|
118
218
|
return driver.adicionar(entrada);
|
|
119
219
|
},
|
|
120
220
|
buscar(consulta) {
|
|
221
|
+
if (leituraRestrita) {
|
|
222
|
+
if (consulta.limite !== undefined && (!Number.isInteger(consulta.limite) ||
|
|
223
|
+
consulta.limite < 1 || consulta.limite > orkmind_1.LIMITE_CONSULTA_MAXIMO))
|
|
224
|
+
throw Error('memory.query.invalid');
|
|
225
|
+
const entradas = consultarRestrito(consulta.collection, consulta.tags);
|
|
226
|
+
// Corte de apresentacao somente depois da janela completa e dos filtros locais.
|
|
227
|
+
return consulta.limite === undefined ? entradas : entradas.slice(0, consulta.limite);
|
|
228
|
+
}
|
|
121
229
|
if (!ativo || !driver)
|
|
122
230
|
return [];
|
|
123
231
|
const colecoes = consulta.collection ? [consulta.collection] : [...orkmind_1.COLECOES_DO_ORK];
|
|
@@ -125,6 +233,11 @@ function abrirMemoria(carregado, opcoes = {}) {
|
|
|
125
233
|
return (0, orkmind_1.filtrarPorTags)(tudo, consulta);
|
|
126
234
|
},
|
|
127
235
|
porId(colecao, id) {
|
|
236
|
+
if (leituraRestrita) {
|
|
237
|
+
if (typeof id !== 'string' || !id || id.length > 512 || /[\x00-\x1f\x7f]/.test(id))
|
|
238
|
+
throw Error('memory.query.invalid');
|
|
239
|
+
return consultarRestrito(colecao, {}).find(e => e.id === id) ?? null;
|
|
240
|
+
}
|
|
128
241
|
if (!ativo || !driver)
|
|
129
242
|
return null;
|
|
130
243
|
return driver.exportar(colecao).find((e) => e.id === id) ?? null;
|
|
@@ -141,7 +254,7 @@ function abrirMemoria(carregado, opcoes = {}) {
|
|
|
141
254
|
function tagsDoProjeto(manifesto) {
|
|
142
255
|
return {
|
|
143
256
|
project: [manifesto.memory.tenant || manifesto.project.name],
|
|
144
|
-
agent: ['ork'],
|
|
257
|
+
agent: ['desconhecido:desconhecido', 'ork'],
|
|
145
258
|
domain: ['orkastery'],
|
|
146
259
|
};
|
|
147
260
|
}
|
|
@@ -157,14 +270,27 @@ function situacaoDaFase(fase) {
|
|
|
157
270
|
function skillDaColecao(colecao) {
|
|
158
271
|
return `orkastery-${colecao}`;
|
|
159
272
|
}
|
|
273
|
+
/** Autoria observada; manifesto do executor nao prova autoria historica. */
|
|
274
|
+
function agenteDaThread(thread, slug) {
|
|
275
|
+
const sessao = slug ? thread.sessoes.find(s => s.slug === slug) : thread.sessoes.at(-1);
|
|
276
|
+
if (!sessao)
|
|
277
|
+
return 'desconhecido:desconhecido';
|
|
278
|
+
let modelo = 'desconhecido';
|
|
279
|
+
if (thread.worktree) {
|
|
280
|
+
const evento = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(thread.worktree, thread.id)).find(e => e.tipo === 'phase_dispatch' && e.sessionId === sessao.sessionId);
|
|
281
|
+
if (typeof evento?.model === 'string' && evento.model)
|
|
282
|
+
modelo = evento.model;
|
|
283
|
+
}
|
|
284
|
+
return `${sessao.runtime || 'desconhecido'}:${modelo}`;
|
|
285
|
+
}
|
|
160
286
|
/** As tags completas de uma entrada de thread. */
|
|
161
287
|
function tagsDaThread(manifesto, colecao, thread, fase) {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
situacao.push(situacaoDaFase(fase));
|
|
288
|
+
const aplicavel = fase ?? thread.faseAtual;
|
|
289
|
+
const situacao = [colecao, situacaoDaThread(thread.id), `modo:${thread.modo}`, situacaoDaFase(aplicavel)];
|
|
165
290
|
return {
|
|
166
291
|
...tagsDoProjeto(manifesto),
|
|
167
|
-
|
|
292
|
+
agent: [agenteDaThread(thread), 'ork'],
|
|
293
|
+
skill: [aplicavel, skillDaColecao(colecao)],
|
|
168
294
|
situation: situacao,
|
|
169
295
|
};
|
|
170
296
|
}
|
|
@@ -202,14 +328,15 @@ function gravarDecisoes(memoria, manifesto, thread) {
|
|
|
202
328
|
// metadata, entao a identidade da entrada precisa viajar por onde a busca por
|
|
203
329
|
// tag ja e exata. Sem ela, a mesma decisao voltaria duas vezes ao prompt (uma
|
|
204
330
|
// do thread.json, outra da memoria), porque nao haveria como deduplicar.
|
|
205
|
-
tags: {
|
|
331
|
+
tags: Object.fromEntries(Object.entries({
|
|
206
332
|
...tagsDaThread(manifesto, 'decision', thread),
|
|
207
333
|
situation: [
|
|
334
|
+
'decision',
|
|
208
335
|
situacaoDaThread(thread.id),
|
|
209
336
|
`modo:${thread.modo}`,
|
|
210
337
|
`decisao:${d.id}`,
|
|
211
338
|
],
|
|
212
|
-
},
|
|
339
|
+
}).map(([k, v]) => [k, [...new Set(v)].sort()])),
|
|
213
340
|
priority: 'high',
|
|
214
341
|
metadata: {
|
|
215
342
|
thread: thread.id,
|
|
@@ -223,43 +350,81 @@ function gravarDecisoes(memoria, manifesto, thread) {
|
|
|
223
350
|
}
|
|
224
351
|
return juntar(resultados, memoria.regime);
|
|
225
352
|
}
|
|
226
|
-
/**
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
353
|
+
/** Identidade independente da worktree: tenant, caminho canonico e bytes da origem. */
|
|
354
|
+
function identidadeDoHandoff(tenant, arquivo, sha256) {
|
|
355
|
+
const digest = (0, node_crypto_1.createHash)('sha256').update([tenant, arquivo, sha256].join('\0')).digest('hex');
|
|
356
|
+
return digest.match(/.{8}/g).join(':');
|
|
357
|
+
}
|
|
358
|
+
function origemCanonicaDoHandoff(arquivo) {
|
|
359
|
+
const normalizado = arquivo.split(path.sep).join('/');
|
|
360
|
+
const inicio = normalizado.lastIndexOf('.orkastery/');
|
|
361
|
+
return inicio >= 0 ? normalizado.slice(inicio) : normalizado;
|
|
362
|
+
}
|
|
363
|
+
/** Adaptacao do v1 para o G3. Ausencias sao declaradas; o original fica integral. */
|
|
364
|
+
function prepararHandoffGovernado(manifesto, thread, handoff, arquivo, textoOriginal, raiz) {
|
|
365
|
+
const tenant = manifesto.memory.tenant || manifesto.project.name;
|
|
366
|
+
if (thread.projeto.name !== manifesto.project.name || handoff.thread !== thread.id) {
|
|
367
|
+
throw new Error('memory.tenant.mismatch');
|
|
368
|
+
}
|
|
369
|
+
if (!(0, node_util_1.isDeepStrictEqual)(JSON.parse(textoOriginal), handoff))
|
|
370
|
+
throw new Error('memory.handoff.source-mismatch');
|
|
371
|
+
if (!handoff.de?.slug || !handoff.para?.slug || !Array.isArray(handoff.inline) ||
|
|
372
|
+
!Array.isArray(handoff.pointers) || !Array.isArray(handoff.summaries))
|
|
373
|
+
throw new Error('memory.handoff.invalid');
|
|
374
|
+
arquivo = origemCanonicaDoHandoff(arquivo);
|
|
375
|
+
const sha256 = (0, node_crypto_1.createHash)('sha256').update(textoOriginal).digest('hex');
|
|
376
|
+
const identidade = identidadeDoHandoff(tenant, arquivo, sha256);
|
|
377
|
+
const anteriores = thread.sessoes.filter(s => s.origem !== 'adocao' && s.fase === handoff.de.fase &&
|
|
378
|
+
Date.parse(s.despachadaEm) <= Date.parse(handoff.geradoEm));
|
|
379
|
+
const exata = anteriores.find(s => s.slug === handoff.de.slug);
|
|
380
|
+
// O v1 exportava thread.slug no campo de.slug. A data/fase identifica a sessao
|
|
381
|
+
// efetivamente em curso quando o arquivo foi produzido, sem atribuir o migrador.
|
|
382
|
+
const sessao = exata ?? (handoff.de.slug === thread.slug ? anteriores.at(-1) : undefined);
|
|
383
|
+
const evento = sessao ? (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread.id)).find(e => e.tipo === 'phase_dispatch' && e.sessionId === sessao.sessionId) : undefined;
|
|
384
|
+
const agente = `${sessao?.runtime || 'desconhecido'}:${typeof evento?.model === 'string' ? evento.model : 'desconhecido'}`;
|
|
385
|
+
const sessionId = sessao?.sessionId || `origem-declarada:${tenant}:${thread.id}:${handoff.de.slug}`;
|
|
386
|
+
const autoria = { sessionId, slug: sessao?.slug ?? handoff.de.slug, agente,
|
|
387
|
+
criterio: exata ? 'slug, fase e data do despacho' : sessao ? 'ultima sessao da fase anterior ao arquivo; slug v1 da thread' :
|
|
388
|
+
'somente slug declarado no arquivo; runtime e modelo desconhecidos',
|
|
389
|
+
evidencia: sessao ? `.orkastery/threads/${thread.id}/thread.json#json:sessoes` : `${arquivo}#json:de` };
|
|
390
|
+
const decisoes = handoff.inline.filter(i => /decis[aã]o/i.test(i.titulo) || i.proveniencia.location.includes('decisoes'));
|
|
391
|
+
const tags = { ...tagsDaThread(manifesto, 'handoff', thread, handoff.para.fase ?? undefined), agent: [agente, 'ork'] };
|
|
392
|
+
const progresso = `Handoff da thread ${thread.id} de ${handoff.de.slug} (${handoff.de.fase}) para ` +
|
|
393
|
+
`${handoff.para.slug} (${handoff.para.fase}), regime ${handoff.memory}.\n` +
|
|
394
|
+
`Triagem: ${handoff.inline.length} inline, ${handoff.pointers.length} ponteiros e ${handoff.summaries.length} resumos.\n` +
|
|
395
|
+
`Arquivo commitado: ${arquivo}\nResumos declarados na origem: ${JSON.stringify(handoff.summaries)}`;
|
|
396
|
+
return { tenant, identidade, sessionId, origem: handoff.de.slug, destino: handoff.para.slug, tags,
|
|
397
|
+
metadata: { tenant, thread: thread.id, arquivo, sha256, bytes: Buffer.byteLength(textoOriginal),
|
|
398
|
+
de: handoff.de, para: handoff.para, autoria },
|
|
399
|
+
payload: {
|
|
400
|
+
progresso,
|
|
401
|
+
decisoes: decisoes.length ? `Decisoes declaradas no pacote original, preservadas a seguir:\n${JSON.stringify(decisoes)}` :
|
|
402
|
+
'O pacote original nao declara decisoes inline identificaveis. Esta ausencia foi preservada, sem inferir uma decisao.',
|
|
403
|
+
referencias_criticas: `Caminhos e ancoras declarados pelo produtor; hashes integrais permanecem no pacote original:\n${JSON.stringify({
|
|
404
|
+
inline: handoff.inline.map(i => i.proveniencia.location),
|
|
405
|
+
pointers: handoff.pointers.map(p => ({ location: p.location, retrieve_when: p.retrieve_when }))
|
|
406
|
+
})}`,
|
|
407
|
+
proximos_passos: `Destino declarado: ${handoff.para.slug}, fase ${handoff.para.fase ?? 'nao declarada'}. ` +
|
|
408
|
+
`Momentos de recuperacao dos ponteiros: ${JSON.stringify(handoff.pointers.map(p => ({ id: p.id, retrieve_when: p.retrieve_when })))}. ` +
|
|
409
|
+
'O formato v1 nao declara outra lista de tarefas seguintes; nenhuma foi inferida nesta adaptacao.',
|
|
410
|
+
original: handoff, original_texto: textoOriginal, orkastery_identity: identidade,
|
|
411
|
+
} };
|
|
412
|
+
}
|
|
413
|
+
/** Publica exclusivamente por G3, com readback; arquivo ausente nunca vira pacote vazio. */
|
|
233
414
|
function gravarHandoff(memoria, manifesto, thread, handoff, caminhoRelativo) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
`modo:${thread.modo}`,
|
|
248
|
-
...(handoff.para.fase ? [situacaoDaFase(handoff.para.fase)] : []),
|
|
249
|
-
`slug:${handoff.para.slug}`,
|
|
250
|
-
],
|
|
251
|
-
},
|
|
252
|
-
priority: 'high',
|
|
253
|
-
metadata: {
|
|
254
|
-
thread: thread.id,
|
|
255
|
-
de: handoff.de,
|
|
256
|
-
para: handoff.para,
|
|
257
|
-
arquivo: caminhoRelativo,
|
|
258
|
-
inline: handoff.inline.length,
|
|
259
|
-
pointers: handoff.pointers.length,
|
|
260
|
-
summaries: handoff.summaries.length,
|
|
261
|
-
},
|
|
262
|
-
});
|
|
415
|
+
try {
|
|
416
|
+
const arquivo = path.resolve(memoria.raiz, caminhoRelativo);
|
|
417
|
+
const textoOriginal = fs.readFileSync(arquivo, 'utf8');
|
|
418
|
+
const pedido = prepararHandoffGovernado(manifesto, thread, handoff, caminhoRelativo, textoOriginal, memoria.raiz);
|
|
419
|
+
const resultado = memoria.submeterHandoff(pedido);
|
|
420
|
+
if (memoria.ativo && !resultado.ok)
|
|
421
|
+
throw new Error(resultado.detalhe);
|
|
422
|
+
return resultado;
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
// Falha de publicacao precisa reprovar export/sync, preservando o arquivo de origem.
|
|
426
|
+
throw new Error('memory.handoff.failed: fonte, G3 ou readback nao confirmado');
|
|
427
|
+
}
|
|
263
428
|
}
|
|
264
429
|
/**
|
|
265
430
|
* Grava as policies do manifesto na colecao `rule`.
|
|
@@ -279,8 +444,8 @@ function gravarPolicies(memoria, manifesto) {
|
|
|
279
444
|
'e regra mandatoria do ecossistema.',
|
|
280
445
|
tags: {
|
|
281
446
|
...tagsDoProjeto(manifesto),
|
|
282
|
-
skill: [skillDaColecao('rule')],
|
|
283
|
-
situation: [`policy:${nome}`, `postura:${postura}`],
|
|
447
|
+
skill: ['GOAL', 'PLAN', 'GO', 'CHECK', 'SHIP', 'MASTER', skillDaColecao('rule')],
|
|
448
|
+
situation: ['policy', `policy:${nome}`, `postura:${postura}`],
|
|
284
449
|
},
|
|
285
450
|
priority: 'high',
|
|
286
451
|
metadata: { policy: nome, postura, origem: 'orkastery.yaml' },
|
|
@@ -310,8 +475,9 @@ function gravarLearning(memoria, manifesto, thread, postmortem, master) {
|
|
|
310
475
|
`Postmortem: .orkastery/threads/${thread.id}/POSTMORTEM.json`,
|
|
311
476
|
tags: {
|
|
312
477
|
...tagsDoProjeto(manifesto),
|
|
313
|
-
skill: [skillDaColecao('learning')],
|
|
478
|
+
skill: ['GOAL', skillDaColecao('learning')],
|
|
314
479
|
situation: [
|
|
480
|
+
'learning',
|
|
315
481
|
situacaoDaThread(thread.id),
|
|
316
482
|
`score:${master.score}`,
|
|
317
483
|
...postmortem.classesDeFalha.map((c) => `classe:${c}`),
|
|
@@ -340,7 +506,7 @@ function gravarOrigemDaThread(memoria, manifesto, thread, origem) {
|
|
|
340
506
|
`Modo ${(0, modos_1.tagDoModo)(thread.modo)}, base ${thread.base.branch} @ ${thread.base.commit}.`,
|
|
341
507
|
tags: {
|
|
342
508
|
...tagsDaThread(manifesto, 'roadmap', thread),
|
|
343
|
-
situation: [situacaoDaThread(thread.id), `origem:${origem.tipo}`],
|
|
509
|
+
situation: ['roadmap', situacaoDaThread(thread.id), `origem:${origem.tipo}`],
|
|
344
510
|
},
|
|
345
511
|
priority: 'medium',
|
|
346
512
|
metadata: {
|
|
@@ -370,8 +536,9 @@ function gravarPropostaDeAuditoria(memoria, manifesto, achado) {
|
|
|
370
536
|
`Claim do auditor: ${achado.claim.alegacao} (verificar com: ${achado.claim.verificar.join(' && ') || 'sem comando'})`,
|
|
371
537
|
tags: {
|
|
372
538
|
...tagsDoProjeto(manifesto),
|
|
373
|
-
skill: [skillDaColecao('roadmap')],
|
|
539
|
+
skill: ['GOAL', skillDaColecao('roadmap')],
|
|
374
540
|
situation: [
|
|
541
|
+
'proposta_auditoria',
|
|
375
542
|
`achado:${achado.id}`,
|
|
376
543
|
`rodada:${achado.rodada}`,
|
|
377
544
|
`pack:${achado.pack}`,
|
|
@@ -453,6 +620,9 @@ function decisoesDaThreadNaMemoria(memoria, manifesto, thread) {
|
|
|
453
620
|
* de ter fechado, e repetir a propria licao no GOAL so gasta janela.
|
|
454
621
|
*/
|
|
455
622
|
function licoesDoProduto(memoria, manifesto, threadCorrente, limite = 5) {
|
|
623
|
+
if (memoria.ativo && memoria.leituraRestrita) {
|
|
624
|
+
throw Error('memory.query.broad-operation: licoes do produto exigem contexto de manutencao ou regime files');
|
|
625
|
+
}
|
|
456
626
|
const todas = memoria.buscar({
|
|
457
627
|
collection: 'learning',
|
|
458
628
|
tags: {
|
|
@@ -487,6 +657,7 @@ function primeiraLinha(texto) {
|
|
|
487
657
|
* - Todo item declara a proveniencia: `path#ancora` ou `orkmind://<colecao>/<id>`.
|
|
488
658
|
*/
|
|
489
659
|
function injecaoDaFase(carregado, memoria, thread, fase) {
|
|
660
|
+
carregado = (0, project_state_1.memoryState)(carregado).loaded;
|
|
490
661
|
const { manifesto } = carregado;
|
|
491
662
|
const itens = [];
|
|
492
663
|
const caminhoThread = `.orkastery/threads/${thread.id}/thread.json`;
|
|
@@ -545,6 +716,23 @@ function injecaoDaFase(carregado, memoria, thread, fase) {
|
|
|
545
716
|
});
|
|
546
717
|
}
|
|
547
718
|
}
|
|
719
|
+
// I-55 (RM-008): a licao dos POSTMORTEMs em disco volta no GOAL e no PLAN, em qualquer regime.
|
|
720
|
+
// E um item so, agregado: o que mais bloqueou, o que mais fechou thread e as notas baixas. No
|
|
721
|
+
// GOAL ela so entra quando o OrkMind nao trouxe licao, para o prompt nao repetir a mesma thread.
|
|
722
|
+
if (fase === 'PLAN' || (fase === 'GOAL' && licoes === 0)) {
|
|
723
|
+
const texto = (0, licoes_1.textoDasLicoes)((0, licoes_1.resumoDasLicoes)(carregado.raiz, thread.id));
|
|
724
|
+
if (texto) {
|
|
725
|
+
licoes += 1;
|
|
726
|
+
add({
|
|
727
|
+
colecao: 'learning',
|
|
728
|
+
titulo: 'Licoes das threads fechadas deste produto (POSTMORTEM e MASTER)',
|
|
729
|
+
conteudo: texto,
|
|
730
|
+
origem: 'postmortem',
|
|
731
|
+
location: '.orkastery/threads/*/POSTMORTEM.json',
|
|
732
|
+
mandatory: false,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
}
|
|
548
736
|
// 3. Regras `mandatory` do ecossistema: elas sempre voltam quando as tags casam, em
|
|
549
737
|
// qualquer fase. O `ork` nunca as cria; ele apenas as respeita.
|
|
550
738
|
let regras = 0;
|
|
@@ -628,22 +816,35 @@ function caminhoRelativoDoHandoff(raiz, threadId) {
|
|
|
628
816
|
* vezes nao duplica decisao nem licao. Em regime `files` ele nao falha: ele relata que
|
|
629
817
|
* nada foi para a memoria semantica, e por que.
|
|
630
818
|
*/
|
|
631
|
-
function sincronizarMemoria(carregado, memoria, threadId, origem) {
|
|
819
|
+
function sincronizarMemoria(carregado, memoria, threadId, origem, perfil = 'integral') {
|
|
820
|
+
carregado = (0, project_state_1.memoryState)(carregado).loaded;
|
|
632
821
|
const { raiz, manifesto } = carregado;
|
|
822
|
+
if (!['fabrica', 'integral'].includes(perfil) || (perfil === 'fabrica' && !threadId))
|
|
823
|
+
throw Error('memory.publication.profile-invalid');
|
|
633
824
|
const vazio = juntar([], memoria.regime);
|
|
634
825
|
let decisoes = vazio;
|
|
635
826
|
let handoff = null;
|
|
636
827
|
let learning = null;
|
|
637
828
|
let roadmap = null;
|
|
638
|
-
|
|
829
|
+
if (threadId) {
|
|
830
|
+
(0, escopo_escrita_1.validarDiretorioDeThread)(raiz, threadId);
|
|
831
|
+
const autorizada = (0, thread_1.lerThread)(raiz, threadId);
|
|
832
|
+
if (autorizada.projeto.name !== manifesto.project.name)
|
|
833
|
+
throw new Error('memory.tenant.mismatch');
|
|
834
|
+
}
|
|
835
|
+
const policies = perfil === 'integral' ? gravarPolicies(memoria, manifesto)
|
|
836
|
+
: { ...vazio, detalhe: 'fora do perfil fabrica: rules exigem sync integral; nenhuma tentativa feita' };
|
|
837
|
+
const humanos = threadId ? (0, memoria_humana_1.publicarGatesHumanos)(carregado, memoria, threadId)
|
|
838
|
+
: { inventario: [], resultados: [], elegiveis: 0, excluidos: 0, falhas: 0 };
|
|
639
839
|
if (threadId) {
|
|
640
840
|
const thread = (0, thread_1.lerThread)(raiz, threadId);
|
|
641
841
|
decisoes = gravarDecisoes(memoria, manifesto, thread);
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
842
|
+
if (perfil === 'integral')
|
|
843
|
+
roadmap = gravarOrigemDaThread(memoria, manifesto, thread, origem ?? {
|
|
844
|
+
tipo: 'pedido',
|
|
845
|
+
referencia: '',
|
|
846
|
+
detalhe: `Thread aberta no modo ${(0, modos_1.tagDoModo)(thread.modo)} para "${thread.nome}".`,
|
|
847
|
+
});
|
|
647
848
|
const caminhoDoHandoff = path.join((0, thread_1.dirThread)(raiz, threadId), 'handoff.json');
|
|
648
849
|
if (fs.existsSync(caminhoDoHandoff)) {
|
|
649
850
|
const pacote = (0, util_1.lerJson)(caminhoDoHandoff);
|
|
@@ -652,19 +853,22 @@ function sincronizarMemoria(carregado, memoria, threadId, origem) {
|
|
|
652
853
|
// A licao so existe depois do MASTER: sem score humano nao ha o que ensinar a
|
|
653
854
|
// proxima thread, e inventar licao de thread aberta e self-report.
|
|
654
855
|
const caminhoDoPostmortem = (0, master_1.caminhoPostmortem)(raiz, threadId);
|
|
655
|
-
const master = (0, master_1.lerMasterLog)(raiz, threadId);
|
|
856
|
+
const master = perfil === 'integral' ? (0, master_1.lerMasterLog)(raiz, threadId) : null;
|
|
656
857
|
if (master && fs.existsSync(caminhoDoPostmortem)) {
|
|
657
858
|
const postmortem = (0, util_1.lerJson)(caminhoDoPostmortem);
|
|
658
859
|
learning = gravarLearning(memoria, manifesto, thread, postmortem, master);
|
|
659
860
|
}
|
|
660
861
|
}
|
|
661
862
|
const unitarios = [handoff, learning, roadmap].filter((g) => g !== null);
|
|
662
|
-
const total = decisoes.gravadas.length + policies.gravadas.length + unitarios.length;
|
|
663
|
-
const falhas = decisoes.falhas + policies.falhas + unitarios.filter((g) => !g.ok).length;
|
|
863
|
+
const total = decisoes.gravadas.length + policies.gravadas.length + unitarios.length + humanos.resultados.length;
|
|
864
|
+
const falhas = decisoes.falhas + policies.falhas + unitarios.filter((g) => !g.ok).length + humanos.falhas;
|
|
664
865
|
return {
|
|
665
866
|
regime: memoria.regime,
|
|
666
867
|
estado: memoria.estado,
|
|
667
868
|
thread: threadId,
|
|
869
|
+
perfil,
|
|
870
|
+
colecoesForaDoPerfil: perfil === 'fabrica' ? ['rule', 'learning', 'roadmap'] : [],
|
|
871
|
+
humanos,
|
|
668
872
|
decisoes,
|
|
669
873
|
policies,
|
|
670
874
|
handoff,
|
|
@@ -682,8 +886,29 @@ function sincronizarMemoria(carregado, memoria, threadId, origem) {
|
|
|
682
886
|
* resultado dizendo que nada foi gravado, e o comando segue igual.
|
|
683
887
|
*/
|
|
684
888
|
function publicar(carregado, threadId, origem, memoriaAberta) {
|
|
889
|
+
carregado = (0, project_state_1.memoryState)(carregado).loaded;
|
|
890
|
+
if (threadId)
|
|
891
|
+
(0, escopo_escrita_1.validarDiretorioDeThread)(carregado.raiz, threadId);
|
|
892
|
+
let perfil = 'integral', motivo = null;
|
|
893
|
+
if (!memoriaAberta && carregado.manifesto.memory.mode === 'orkmind') {
|
|
894
|
+
try {
|
|
895
|
+
perfil = (0, write_activation_1.exigirAtivacao)(carregado, threadId ?? '', 'memory').perfil;
|
|
896
|
+
}
|
|
897
|
+
catch (e) {
|
|
898
|
+
motivo = e instanceof Error && /^(write\.activation|scope\.|memory\.tenant)/.test(e.message) ? e.message : 'write.activation.invalid';
|
|
899
|
+
}
|
|
900
|
+
}
|
|
685
901
|
const memoria = memoriaAberta ?? abrirMemoria(carregado);
|
|
686
|
-
|
|
902
|
+
if (motivo && memoria.ativo) {
|
|
903
|
+
const vazio = { ...juntar([], memoria.regime), detalhe: motivo };
|
|
904
|
+
return { regime: memoria.regime, estado: memoria.estado, thread: threadId, perfil,
|
|
905
|
+
publicacao: { estado: 'pendente', motivo }, humanos: { inventario: [], resultados: [], elegiveis: 0, excluidos: 0, falhas: 0 },
|
|
906
|
+
decisoes: vazio, policies: vazio, handoff: null, learning: null, roadmap: null, total: 0, falhas: 1 };
|
|
907
|
+
}
|
|
908
|
+
const r = sincronizarMemoria(carregado, memoria, threadId, origem, perfil);
|
|
909
|
+
// O driver files apenas relata tentativas recusadas; conserva a degradacao publicada.
|
|
910
|
+
if (motivo)
|
|
911
|
+
r.publicacao = { estado: 'pendente', motivo };
|
|
687
912
|
if (threadId && memoria.ativo) {
|
|
688
913
|
(0, ledger_1.registrar)((0, thread_1.dirThread)(carregado.raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.memoriaGravada, {
|
|
689
914
|
origem: origem?.tipo ?? 'sync',
|
|
@@ -691,6 +916,7 @@ function publicar(carregado, threadId, origem, memoriaAberta) {
|
|
|
691
916
|
tenant: memoria.estado.tenant,
|
|
692
917
|
decisoes: r.decisoes.gravadas.length,
|
|
693
918
|
policies: r.policies.gravadas.length,
|
|
919
|
+
humanGates: r.humanos.elegiveis,
|
|
694
920
|
handoff: r.handoff?.id ?? null,
|
|
695
921
|
learning: r.learning?.id ?? null,
|
|
696
922
|
roadmap: r.roadmap?.id ?? null,
|
|
@@ -706,7 +932,13 @@ function publicar(carregado, threadId, origem, memoriaAberta) {
|
|
|
706
932
|
* board em arquivo e chega ao roadmap do produto pela memoria, quando ela esta ligada.
|
|
707
933
|
*/
|
|
708
934
|
function publicarPropostas(carregado, achados, memoriaAberta) {
|
|
935
|
+
carregado = (0, project_state_1.memoryState)(carregado).loaded;
|
|
709
936
|
const memoria = memoriaAberta ?? abrirMemoria(carregado);
|
|
937
|
+
// Propostas globais nao herdam uma autorizacao de thread por conveniencia.
|
|
938
|
+
if (!memoriaAberta && carregado.manifesto.memory.mode === 'orkmind')
|
|
939
|
+
return juntar(achados.map(() => ({
|
|
940
|
+
ok: false, id: null, duplicada: false, collection: 'roadmap', detalhe: 'write.activation.operator-required'
|
|
941
|
+
})), memoria.regime);
|
|
710
942
|
const resultados = achados.map((a) => gravarPropostaDeAuditoria(memoria, carregado.manifesto, a));
|
|
711
943
|
return juntar(resultados, memoria.regime);
|
|
712
944
|
}
|
|
@@ -734,7 +966,7 @@ function textoDoEstado(estado) {
|
|
|
734
966
|
linhas.push(` ${estado.detalhe}`);
|
|
735
967
|
linhas.push('');
|
|
736
968
|
linhas.push(` colecoes gravadas: ${orkmind_1.COLECOES_DO_ORK.join(', ')}`);
|
|
737
|
-
linhas.push(' governanca: source=agent
|
|
969
|
+
linhas.push(' governanca: source=agent; decision/human exige human_gate comprovado; mandatory=false e regra nunca critical.');
|
|
738
970
|
}
|
|
739
971
|
return linhas.join('\n');
|
|
740
972
|
}
|
|
@@ -742,12 +974,16 @@ function textoDoEstado(estado) {
|
|
|
742
974
|
function textoDoSync(r) {
|
|
743
975
|
const linhas = [];
|
|
744
976
|
linhas.push(`Sincronizacao de memoria (regime ${r.regime})${r.thread ? ` da thread ${r.thread}` : ''}`);
|
|
977
|
+
linhas.push(`Perfil: ${r.perfil ?? 'integral'}; fora do perfil: ${(r.colecoesForaDoPerfil ?? []).join(', ') || '(nenhuma)'}`);
|
|
978
|
+
if (r.publicacao?.estado === 'pendente')
|
|
979
|
+
linhas.push(`Publicacao pendente: ${r.publicacao.motivo}`);
|
|
745
980
|
linhas.push('');
|
|
746
981
|
const linha = (nome, s) => {
|
|
747
982
|
linhas.push(` ${nome.padEnd(10)} ${s.gravadas.length} entrada(s): ${s.detalhe}`);
|
|
748
983
|
};
|
|
749
984
|
linha('decision', r.decisoes);
|
|
750
985
|
linha('rule', r.policies);
|
|
986
|
+
linhas.push(` human_gate ${r.humanos.elegiveis} elegiveis, ${r.humanos.excluidos} excluidos, ${r.humanos.falhas} falhas`);
|
|
751
987
|
const um = (nome, g) => {
|
|
752
988
|
linhas.push(` ${nome.padEnd(10)} ${g ? (g.ok ? `${g.duplicada ? 'ja existente' : 'gravado'} (${g.id})` : `nao gravado: ${g.detalhe}`) : '(nada a gravar)'}`);
|
|
753
989
|
};
|