dd-harness 0.6.0 → 0.8.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.
package/dist/brain.d.ts CHANGED
@@ -37,6 +37,8 @@ export type Brain = {
37
37
  };
38
38
  politica?: string | null;
39
39
  briefing?: string | null;
40
+ /** Politica E briefing tem conteudo real? Calculado no servico, nunca inferido aqui. */
41
+ briefado?: boolean;
40
42
  pastas: {
41
43
  slug: string;
42
44
  definicao: string;
package/dist/curar.d.ts CHANGED
@@ -25,6 +25,12 @@ export type MemoriaDoServico = {
25
25
  valor: string;
26
26
  sha: string | null;
27
27
  }[];
28
+ /**
29
+ * Os OUTROS projetos (slugs do mesmo tenant) que esta memoria tambem alcanca. Sem este
30
+ * campo no round-trip ler->editar->enviar, o vinculo transversal se perdia em silencio
31
+ * — achado numa rodada de teste real.
32
+ */
33
+ projetos?: string[];
28
34
  };
29
35
  /**
30
36
  * A memoria inteira, no markdown que `gravar` e `editar` consomem.
package/dist/curar.js CHANGED
@@ -30,6 +30,9 @@ export function comoMarkdown(m) {
30
30
  `description: ${m.resumo}`,
31
31
  `pasta: ${m.pasta}`,
32
32
  ...(m.revisar_ate ? [`revisar-ate: ${m.revisar_ate.slice(0, 10)}`] : []),
33
+ // So aparece quando ha vinculo — omitir e "so este projeto", igual a `gravar` sem
34
+ // `projetos:`. Formato inline (`a, b`), que e o que `interpreta` ja sabe ler.
35
+ ...(m.projetos?.length ? [`projetos: ${m.projetos.join(", ")}`] : []),
33
36
  "---",
34
37
  "",
35
38
  m.corpo.trim(),
@@ -62,6 +65,10 @@ export async function edita(raiz, caminho) {
62
65
  invisibilidade: memoria.invisibilidade,
63
66
  externalidade: memoria.externalidade,
64
67
  ancoras: memoria.ancoras,
68
+ // So manda quando o arquivo TINHA a chave `projetos:` — omitida, o servico
69
+ // mantem os vinculos como estao. `le` sempre escreve a chave quando ha vinculo,
70
+ // entao editar o arquivo que veio de `le` preserva o round-trip.
71
+ ...(memoria.tambemEmInformado ? { projetos: memoria.tambemEm } : {}),
65
72
  }),
66
73
  });
67
74
  if (!resposta.ok)
package/dist/gravar.d.ts CHANGED
@@ -16,6 +16,14 @@ export type MemoriaLida = {
16
16
  externalidade: string;
17
17
  ancoras: string[];
18
18
  tambemEm: string[];
19
+ /**
20
+ * O frontmatter TINHA a chave `projetos:`? `gravar` nao usa isto (chave ausente e
21
+ * `projetos: ` vazio significam a mesma coisa ali: "so este projeto"). `editar` usa —
22
+ * la a ausencia da chave precisa significar "nao estou informando vinculos", diferente
23
+ * de uma lista vazia explicita, senao editar sem tocar em `projetos:` apagaria o
24
+ * vinculo transversal por omissao.
25
+ */
26
+ tambemEmInformado: boolean;
19
27
  };
20
28
  export declare function interpreta(texto: string): MemoriaLida;
21
29
  export declare function grava(raiz: string, caminho: string): Promise<{
package/dist/gravar.js CHANGED
@@ -151,6 +151,7 @@ export function interpreta(texto) {
151
151
  .split(",")
152
152
  .map((s) => s.trim())
153
153
  .filter(Boolean),
154
+ tambemEmInformado: campos.has("projetos"),
154
155
  };
155
156
  }
156
157
  export async function grava(raiz, caminho) {
package/dist/index.js CHANGED
@@ -271,7 +271,12 @@ async function comandoCheck(argv) {
271
271
  console.log(`${r.fechadas} deriva(s) fechada(s): o alvo voltou a bater com a linha de base.`);
272
272
  }
273
273
  if (!r.ausentes.length && r.novas === 0 && r.jaAbertas === 0 && r.fechadas === 0) {
274
- console.log("nenhuma deriva: o mundo ainda bate com o que as memórias dizem.");
274
+ // "Nenhuma deriva" e nao "o mundo bate com o que a memoria diz": isto mede se a
275
+ // ANCORA (localizacao/conteudo) mudou, nunca se o COMPORTAMENTO ainda corresponde ao
276
+ // texto. Dois agentes-cobaia independentes leram a frase antiga como garantia
277
+ // semantica que o mecanismo nao da — trocar quebra e proposital comportamento
278
+ // continuar identico ao de antes.
279
+ console.log("nenhuma âncora mudou de lugar ou de conteúdo desde a última medição.");
275
280
  }
276
281
  // O cruzamento com o diff e outra coisa que deriva: e "voce acabou de mexer no que
277
282
  // esta memoria guarda". Vale mesmo quando a memoria continua valendo — e o revisor
@@ -311,7 +316,9 @@ async function comandoPolitica(argv) {
311
316
  return;
312
317
  }
313
318
  if (r.estado === "sem-politica") {
314
- console.error("Este projeto ainda não tem política — nunca foi briefado. Rode `/briefar`.");
319
+ console.error("Este projeto ainda não tem política e/ou briefing os dois são obrigatórios. " +
320
+ "Rode uma sessão com `--hook` (ou converse com o agente): ele vai conduzir o " +
321
+ "briefing agora e escrever os dois.");
315
322
  process.exitCode = 3;
316
323
  return;
317
324
  }
@@ -340,9 +347,23 @@ function contextoDaSessao(r, worker) {
340
347
  if (r.estado === "sem-politica") {
341
348
  return {
342
349
  ...base,
343
- additionalContext: "AVISO DO DD-HARNESS: este projeto existe no serviço mas **nunca foi briefado** " +
344
- "— não política.\n\nIsto não é uma falha: é um projeto novo. Antes de " +
345
- "implementar qualquer coisa, diga isso ao usuário e proponha rodar `/briefar`." +
350
+ additionalContext: "AVISO DO DD-HARNESS: este projeto existe no serviço mas política e/ou " +
351
+ "briefing **estão faltando** os dois são obrigatórios.\n\n" +
352
+ "Isto não é uma falha: é um projeto novo. Antes de implementar qualquer " +
353
+ "coisa, conduza o briefing agora, nesta sessão:\n\n" +
354
+ "1. Se houver um `CLAUDE.md` na raiz deste repositório, leia-o primeiro — o " +
355
+ "que ele já diz é ponto de partida, não é para ser ignorado.\n" +
356
+ "2. Pergunte ao usuário o que o código e o `CLAUDE.md` não revelarem: " +
357
+ "objetivo do projeto, stack principal, restrições e convenções.\n" +
358
+ "3. Mostre o rascunho da política e do briefing e espere a confirmação " +
359
+ "explícita do usuário antes de escrever.\n" +
360
+ "4. Escreva os dois com a ferramenta MCP `escrever_artefato` " +
361
+ "(`tipo: \"politica\"` e `tipo: \"briefing\"`, uma chamada cada). Se essa " +
362
+ "ferramenta não estiver disponível nesta sessão, pare e diga ao usuário que " +
363
+ "o servidor MCP do dd-harness precisa estar conectado para isto.\n" +
364
+ "5. Depois de escrever os dois, sobrescreva o `CLAUDE.md` da raiz com um " +
365
+ "ponteiro curto para a política deste serviço — a verdade passa a morar " +
366
+ "aqui, e o `CLAUDE.md` local nunca mais precisa ser editado à mão." +
346
367
  fila,
347
368
  };
348
369
  }
@@ -5,9 +5,10 @@
5
5
  * nenhuma sessao abre sem protocolo. Por isso o retorno separa TRES situacoes que um
6
6
  * "deu erro" colapsaria — e cada uma pede uma reacao diferente de quem chamou:
7
7
  *
8
- * - `ok`: a politica existe e veio. Segue a sessao.
9
- * - `sem-politica`: o projeto existe e nunca foi briefado. NAO e falha: a saida e rodar o
10
- * briefing. Tratar como erro faria todo projeto novo parecer quebrado.
8
+ * - `ok`: politica E briefing existem. Segue a sessao.
9
+ * - `sem-politica`: falta politica OU briefing (os dois sao obrigatorios). NAO e falha: a
10
+ * saida e conduzir o briefing agora, na sessao. Tratar como erro faria todo projeto
11
+ * novo parecer quebrado.
11
12
  * - `inalcancavel`: rede, timeout, 5xx, credencial, projeto inexistente. A politica pode
12
13
  * existir e nao chegou — e ai a sessao precisa PARAR, porque seguir sem ela e
13
14
  * exatamente a falha que este projeto combate.
package/dist/politica.js CHANGED
@@ -24,9 +24,13 @@ export async function buscaPolitica(raiz) {
24
24
  const payload = (await resposta.json());
25
25
  const conteudo = payload.politica?.trim();
26
26
  const esperandoIndexacao = payload.esperando_indexacao ?? 0;
27
- // Vazio e nulo sao a mesma coisa aqui, e os dois significam "nunca foi escrita".
28
- if (!conteudo)
27
+ // `briefado` e do SERVICO, nao inferido aqui: exige politica E briefing, os dois
28
+ // obrigatorios. So checar `politica` vazia deixava passar o caso de politica
29
+ // existir sem briefing — a sessao seguia como "ok" com metade do briefing faltando,
30
+ // e nada acionava o fluxo que devia completa-lo.
31
+ if (!conteudo || payload.briefado === false) {
29
32
  return { estado: "sem-politica", esperandoIndexacao };
33
+ }
30
34
  return { estado: "ok", conteudo, esperandoIndexacao };
31
35
  }
32
36
  catch (erro) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-harness",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "Cliente do dd-harness: politica no inicio da sessao, e memoria por busca — nada em disco. Sem dependencia: fetch, crypto e fs sao do Node.",
6
6
  "license": "UNLICENSED",