dd-harness 0.15.0 → 0.17.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/check.d.ts CHANGED
@@ -29,6 +29,11 @@ export type ResultadoDoCheck = {
29
29
  * rename a cruzar, e a lista de ausentes continua sendo tudo o que se pode dizer.
30
30
  */
31
31
  reancoragens: Reancoragem[];
32
+ /**
33
+ * Pediram `--commit` e o cruzamento nao aconteceu — e por que. `undefined` quando
34
+ * aconteceu, ou quando nao se pediu commit nenhum.
35
+ */
36
+ semGit?: "sem-repositorio" | "commit-desconhecido" | "git-indisponivel";
32
37
  };
33
38
  export type ResultadoDoStatus = {
34
39
  /**
package/dist/check.js CHANGED
@@ -99,6 +99,7 @@ export async function check(raiz, commit) {
99
99
  fechadas: 0,
100
100
  tocadas,
101
101
  reancoragens,
102
+ semGit: mudancas.semGit,
102
103
  };
103
104
  }
104
105
  const envio = await pede(`${config.api}/api/v1/deriva`, {
@@ -127,5 +128,6 @@ export async function check(raiz, commit) {
127
128
  fechadas: julgamento.fechadas ?? 0,
128
129
  tocadas,
129
130
  reancoragens,
131
+ semGit: mudancas.semGit,
130
132
  };
131
133
  }
package/dist/diff.d.ts CHANGED
@@ -19,6 +19,16 @@ export type Rename = {
19
19
  export type MudancasDoCommit = {
20
20
  caminhos: string[];
21
21
  renames: Rename[];
22
+ /**
23
+ * Por que o cruzamento nao aconteceu. `undefined` = aconteceu (mesmo que o commit nao
24
+ * tenha tocado nada que uma ancora guarda).
25
+ *
26
+ * Sem isto, "o commit nao mexeu em nada indexado" e "o git nem rodou" saem identicos —
27
+ * uma lista vazia. Uma rodada de teste com agente-cobaia passou `--commit` com um SHA
28
+ * inventado, fora de um repositorio git, e recebeu exit 0 e a mesma saida de sempre: o
29
+ * cruzamento que ela queria exercitar simplesmente nao existiu, sem uma linha dizendo.
30
+ */
31
+ semGit?: "sem-repositorio" | "commit-desconhecido" | "git-indisponivel";
22
32
  };
23
33
  /**
24
34
  * O que um commit mudou: caminhos tocados e renames detectados.
package/dist/diff.js CHANGED
@@ -17,10 +17,34 @@ export async function caminhosDoCommit(raiz, commit) {
17
17
  const { stdout } = await roda("git", ["diff-tree", "--no-commit-id", "-r", "-M", "--name-status", commit], { cwd: raiz });
18
18
  return interpretaNameStatus(stdout);
19
19
  }
20
- catch {
21
- return { caminhos: [], renames: [] };
20
+ catch (erro) {
21
+ // Continua sem lancar o gancho `post-commit` nao pode falhar por causa de um aviso.
22
+ // O que muda e que a razao volta junto, para quem chamou poder dize-la em vez de
23
+ // mostrar "nenhuma mudanca" quando na verdade nada foi consultado.
24
+ return { caminhos: [], renames: [], semGit: classificaFalhaDoGit(erro) };
22
25
  }
23
26
  }
27
+ /**
28
+ * Traduz a falha do `git diff-tree` nos tres casos que pedem respostas diferentes de quem
29
+ * chamou: consertar o repositorio, conferir o SHA, ou instalar o git.
30
+ *
31
+ * A leitura e do stderr porque o `git` usa o mesmo codigo de saida (128) para "not a git
32
+ * repository" e para "bad object" — o texto e o unico jeito de separar os dois.
33
+ */
34
+ function classificaFalhaDoGit(erro) {
35
+ const e = erro;
36
+ if (e.code === "ENOENT")
37
+ return "git-indisponivel";
38
+ const stderr = e.stderr ?? "";
39
+ if (/not a git repository/i.test(stderr))
40
+ return "sem-repositorio";
41
+ if (/bad object|unknown revision|ambiguous argument/i.test(stderr)) {
42
+ return "commit-desconhecido";
43
+ }
44
+ // Falha que nao sabemos nomear: ainda e melhor avisar que o cruzamento nao aconteceu do
45
+ // que deixar passar como silencio.
46
+ return "git-indisponivel";
47
+ }
24
48
  /**
25
49
  * Le a saida de `--name-status`: uma letra de status, TAB, e um ou dois caminhos.
26
50
  *
package/dist/index.js CHANGED
@@ -553,8 +553,29 @@ async function comandoReancorar(argv) {
553
553
  console.log(` para ${r.para}`);
554
554
  console.log(" Rode `dd-harness check --commit <sha>` para medir a base nova.");
555
555
  }
556
+ /**
557
+ * Pediram `--commit` e o cruzamento com o diff nao aconteceu. Avisa ANTES do resto: sem
558
+ * isto a saida e identica a de um commit que nao tocou em nada indexado, e quem pediu o
559
+ * cruzamento nao tem como saber que ele nao existiu.
560
+ *
561
+ * Aviso, nao erro: o gancho `post-commit` termina em sucesso mesmo assim, e a medicao das
562
+ * ancoras (que nao depende de git) continua valendo.
563
+ */
564
+ function avisaSemGit(motivo) {
565
+ const texto = {
566
+ "sem-repositorio": "esta pasta não é um repositório git — não há diff para cruzar com as âncoras.",
567
+ "commit-desconhecido": "o git não reconhece este commit — confira o SHA.",
568
+ "git-indisponivel": "não consegui rodar o git aqui.",
569
+ }[motivo];
570
+ console.log(`AVISO: ${texto}`);
571
+ console.log(" As âncoras foram medidas assim mesmo; só o cruzamento com o");
572
+ console.log(" commit ficou de fora.");
573
+ console.log("");
574
+ }
556
575
  async function comandoCheck(argv) {
557
576
  const r = await check(process.cwd(), argumento(argv, "commit"));
577
+ if (r.semGit)
578
+ avisaSemGit(r.semGit);
558
579
  if (r.medidas === 0) {
559
580
  console.log("nenhuma âncora para medir.");
560
581
  return;
@@ -693,9 +714,24 @@ function contextoDaSessao(r, worker) {
693
714
  "(`tipo: \"politica\"` e `tipo: \"briefing\"`, uma chamada cada). Se essa " +
694
715
  "ferramenta não estiver disponível nesta sessão, pare e diga ao usuário que " +
695
716
  "o servidor MCP do dd-harness precisa estar conectado para isto.\n" +
717
+ // A politica e escrita do zero pelo agente, e este texto e o unico lugar que diz o
718
+ // que ela precisa conter. Sem esta linha, o roadmap chega ao contexto e nao obriga
719
+ // a nada: informacao passiva, que e como uma feature existe sem ser usada.
720
+ " Na política, inclua uma linha sobre o roadmap: a fase **Agora** é o foco da " +
721
+ "sessão, e ao terminá-la o agente **propõe** concluí-la (`editar_fase` com " +
722
+ "`status: \"concluida\"`) — nunca conclui por conta própria, porque quem decide " +
723
+ "que uma fase acabou é o usuário.\n" +
696
724
  "5. Depois de escrever os dois, sobrescreva o `CLAUDE.md` da raiz com um " +
697
725
  "ponteiro curto para a política deste serviço — a verdade passa a morar " +
698
- "aqui, e o `CLAUDE.md` local nunca mais precisa ser editado à mão." +
726
+ "aqui, e o `CLAUDE.md` local nunca mais precisa ser editado à mão.\n" +
727
+ // O momento certo de perguntar: quem acabou de descrever o projeto tem o contexto
728
+ // fresco para dizer por onde ele vai. Depois disso, ninguem mais pergunta — e uma
729
+ // feature que so se descobre lendo a lista de ferramentas nao se descobre.
730
+ "6. Por fim, pergunte se o trabalho deste projeto tem **fases** — algo que " +
731
+ "atravessa sessões, com ordem entre as partes. Se tiver, proponha as primeiras e " +
732
+ "crie-as com `criar_fase`; a de menor ordem vira o foco de cada sessão, e " +
733
+ "concluí-la a move para o changelog sozinha. Se for um projeto pequeno, diga que " +
734
+ "roadmap é opcional e siga sem ele — não insista." +
699
735
  fila,
700
736
  };
701
737
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-harness",
3
- "version": "0.15.0",
3
+ "version": "0.17.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",