dd-harness 0.36.0 → 0.38.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.
@@ -10,81 +10,81 @@
10
10
  */
11
11
  export const MOLDES_HISTORICOS = [
12
12
  // ca1e529
13
- `## Protocolo do dd-harness
14
-
15
- Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
16
-
17
- **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
18
- \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
19
- de ler código, responder ou planejar.
20
-
21
- - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
22
- avise o usuário e **não modifique nada** até ele resolver.
23
- - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.
24
-
25
- Leia também o briefing com a mesma ferramenta (tipo briefing). Os dois são obrigatórios.
26
-
27
- Depois, \`ler_roadmap\`: se houver uma fase **Agora**, é dela que saem os passos
28
- desta sessão. Lista vazia significa que este projeto não usa roadmap, e isso é
29
- válido — não crie fase sem o usuário pedir.
30
-
31
- E \`listar_skills\`: são os procedimentos deste projeto. **Invoque a que couber
32
- ANTES de fazer o trabalho, não depois** — skill lida no fim vira revisão do que
33
- já saiu errado, e é tarde.
34
-
35
- Vale mesmo quando o pedido parece pequeno: "é só um ajuste" é exatamente a
36
- frase que antecede pular o procedimento. A política diz quais são obrigatórias
13
+ `## Protocolo do dd-harness
14
+
15
+ Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
16
+
17
+ **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
18
+ \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
19
+ de ler código, responder ou planejar.
20
+
21
+ - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
22
+ avise o usuário e **não modifique nada** até ele resolver.
23
+ - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.
24
+
25
+ Leia também o briefing com a mesma ferramenta (tipo briefing). Os dois são obrigatórios.
26
+
27
+ Depois, \`ler_roadmap\`: se houver uma fase **Agora**, é dela que saem os passos
28
+ desta sessão. Lista vazia significa que este projeto não usa roadmap, e isso é
29
+ válido — não crie fase sem o usuário pedir.
30
+
31
+ E \`listar_skills\`: são os procedimentos deste projeto. **Invoque a que couber
32
+ ANTES de fazer o trabalho, não depois** — skill lida no fim vira revisão do que
33
+ já saiu errado, e é tarde.
34
+
35
+ Vale mesmo quando o pedido parece pequeno: "é só um ajuste" é exatamente a
36
+ frase que antecede pular o procedimento. A política diz quais são obrigatórias
37
37
  e quando.`,
38
38
  // 875342e
39
- `## Protocolo do dd-harness
40
-
41
- Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
42
-
43
- **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
44
- \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
45
- de ler código, responder ou planejar.
46
-
47
- - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
48
- avise o usuário e **não modifique nada** até ele resolver.
49
- - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.
50
-
51
- Depois, \`ler_roadmap\`: se houver uma fase **Agora**, é dela que saem os passos
52
- desta sessão. Lista vazia significa que este projeto não usa roadmap, e isso é
53
- válido — não crie fase sem o usuário pedir.
54
-
55
- E \`listar_skills\`: são os procedimentos deste projeto. **Invoque a que couber
56
- ANTES de fazer o trabalho, não depois** — skill lida no fim vira revisão do que
57
- já saiu errado, e é tarde.
58
-
59
- Vale mesmo quando o pedido parece pequeno: "é só um ajuste" é exatamente a
60
- frase que antecede pular o procedimento. A política diz quais são obrigatórias
39
+ `## Protocolo do dd-harness
40
+
41
+ Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
42
+
43
+ **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
44
+ \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
45
+ de ler código, responder ou planejar.
46
+
47
+ - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
48
+ avise o usuário e **não modifique nada** até ele resolver.
49
+ - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.
50
+
51
+ Depois, \`ler_roadmap\`: se houver uma fase **Agora**, é dela que saem os passos
52
+ desta sessão. Lista vazia significa que este projeto não usa roadmap, e isso é
53
+ válido — não crie fase sem o usuário pedir.
54
+
55
+ E \`listar_skills\`: são os procedimentos deste projeto. **Invoque a que couber
56
+ ANTES de fazer o trabalho, não depois** — skill lida no fim vira revisão do que
57
+ já saiu errado, e é tarde.
58
+
59
+ Vale mesmo quando o pedido parece pequeno: "é só um ajuste" é exatamente a
60
+ frase que antecede pular o procedimento. A política diz quais são obrigatórias
61
61
  e quando.`,
62
62
  // f59da48
63
- `## Protocolo do dd-harness
64
-
65
- Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
66
-
67
- **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
68
- \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
69
- de ler código, responder ou planejar.
70
-
71
- - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
72
- avise o usuário e **não modifique nada** até ele resolver.
73
- - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.
74
-
75
- Depois, \`ler_roadmap\`: se houver uma fase **Agora**, é dela que saem os passos
76
- desta sessão. Lista vazia significa que este projeto não usa roadmap, e isso é
63
+ `## Protocolo do dd-harness
64
+
65
+ Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
66
+
67
+ **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
68
+ \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
69
+ de ler código, responder ou planejar.
70
+
71
+ - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
72
+ avise o usuário e **não modifique nada** até ele resolver.
73
+ - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.
74
+
75
+ Depois, \`ler_roadmap\`: se houver uma fase **Agora**, é dela que saem os passos
76
+ desta sessão. Lista vazia significa que este projeto não usa roadmap, e isso é
77
77
  válido — não crie fase sem o usuário pedir.`,
78
78
  // 5fb3f02
79
- `## Protocolo do dd-harness
80
-
81
- Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
82
-
83
- **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
84
- \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
85
- de ler código, responder ou planejar.
86
-
87
- - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
88
- avise o usuário e **não modifique nada** até ele resolver.
79
+ `## Protocolo do dd-harness
80
+
81
+ Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
82
+
83
+ **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
84
+ \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
85
+ de ler código, responder ou planejar.
86
+
87
+ - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
88
+ avise o usuário e **não modifique nada** até ele resolver.
89
89
  - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.`,
90
90
  ];
@@ -1,7 +1,14 @@
1
1
  export declare function pergunta(texto: string): Promise<string>;
2
2
  export declare function fechaPerguntas(): void;
3
- /** Numera as opcoes, pede um numero, devolve o item escolhido. Sem loop de retry: erra, recomeca o comando — start nao e ambiente para validar input ao infinito. */
3
+ /**
4
+ * Escolha de uma opcao: setas e Enter quando ha terminal, numeracao quando nao ha.
5
+ *
6
+ * As setas exigem raw mode, que so existe em TTY — e `start` tambem roda com stdin
7
+ * redirecionado (script, CI, `echo | dd-harness start`). Ali `setRawMode` nem existe, e
8
+ * chama-lo lanca. Por isso a numeracao continua inteira como caminho alternativo: nao e
9
+ * legado, e o modo que funciona quando nao ha quem pressione tecla.
10
+ */
4
11
  export declare function escolha<T>(titulo: string, itens: {
5
12
  rotulo: string;
6
13
  valor: T;
7
- }[]): Promise<T>;
14
+ }[], inicial?: number): Promise<T>;
package/dist/pergunta.js CHANGED
@@ -18,8 +18,21 @@ export function fechaPerguntas() {
18
18
  rl?.close();
19
19
  rl = null;
20
20
  }
21
- /** Numera as opcoes, pede um numero, devolve o item escolhido. Sem loop de retry: erra, recomeca o comando — start nao e ambiente para validar input ao infinito. */
22
- export async function escolha(titulo, itens) {
21
+ /**
22
+ * Escolha de uma opcao: setas e Enter quando ha terminal, numeracao quando nao ha.
23
+ *
24
+ * As setas exigem raw mode, que so existe em TTY — e `start` tambem roda com stdin
25
+ * redirecionado (script, CI, `echo | dd-harness start`). Ali `setRawMode` nem existe, e
26
+ * chama-lo lanca. Por isso a numeracao continua inteira como caminho alternativo: nao e
27
+ * legado, e o modo que funciona quando nao ha quem pressione tecla.
28
+ */
29
+ export async function escolha(titulo, itens, inicial = 0) {
30
+ if (!itens.length)
31
+ throw new Error("escolha: nenhuma opção para escolher.");
32
+ const porTecla = Boolean(process.stdin.isTTY) && typeof process.stdin.setRawMode === "function";
33
+ return porTecla ? porSetas(titulo, itens, inicial) : porNumero(titulo, itens);
34
+ }
35
+ async function porNumero(titulo, itens) {
23
36
  console.log(titulo);
24
37
  itens.forEach((item, i) => console.log(` ${i + 1}) ${item.rotulo}`));
25
38
  const resposta = await pergunta("> ");
@@ -29,3 +42,59 @@ export async function escolha(titulo, itens) {
29
42
  throw new Error(`escolha um número entre 1 e ${itens.length}.`);
30
43
  return escolhido.valor;
31
44
  }
45
+ function porSetas(titulo, itens, inicial) {
46
+ return new Promise((resolve, reject) => {
47
+ // A interface de linha e a das setas disputam o mesmo stdin: com as duas ativas, cada
48
+ // tecla chega duas vezes. Esta fecha e a proxima `pergunta` abre outra.
49
+ fechaPerguntas();
50
+ let atual = Math.min(Math.max(inicial, 0), itens.length - 1);
51
+ let primeiraPintura = true;
52
+ const pinta = () => {
53
+ // Sobe e limpa as linhas da pintura anterior; na primeira vez nao ha o que apagar.
54
+ if (!primeiraPintura)
55
+ process.stdout.write(`\x1b[${itens.length}A\x1b[0J`);
56
+ primeiraPintura = false;
57
+ for (const [i, item] of itens.entries()) {
58
+ const alvo = i === atual;
59
+ // Negrito no selecionado, cinza no resto: a seta sozinha se perde quando a lista
60
+ // passa de tres ou quatro itens.
61
+ process.stdout.write(alvo ? `\x1b[1m❯ ${item.rotulo}\x1b[0m\n` : `\x1b[2m ${item.rotulo}\x1b[0m\n`);
62
+ }
63
+ };
64
+ const encerra = () => {
65
+ process.stdin.setRawMode(false);
66
+ process.stdin.pause();
67
+ process.stdin.off("data", aoTeclar);
68
+ };
69
+ const aoTeclar = (dado) => {
70
+ const tecla = dado.toString();
71
+ // Ctrl+C precisa continuar matando o processo: em raw mode o terminal nao o trata
72
+ // mais sozinho, e sem isto o wizard ficaria impossivel de abortar.
73
+ if (tecla === "\x03") {
74
+ encerra();
75
+ process.stdout.write("\n");
76
+ process.exit(130);
77
+ }
78
+ if (tecla === "\x1b[A" || tecla === "k") {
79
+ atual = (atual - 1 + itens.length) % itens.length;
80
+ pinta();
81
+ }
82
+ else if (tecla === "\x1b[B" || tecla === "j") {
83
+ atual = (atual + 1) % itens.length;
84
+ pinta();
85
+ }
86
+ else if (tecla === "\r" || tecla === "\n") {
87
+ encerra();
88
+ const escolhido = itens[atual];
89
+ if (!escolhido)
90
+ return reject(new Error("escolha: índice fora da lista."));
91
+ resolve(escolhido.valor);
92
+ }
93
+ };
94
+ console.log(titulo);
95
+ pinta();
96
+ process.stdin.setRawMode(true);
97
+ process.stdin.resume();
98
+ process.stdin.on("data", aoTeclar);
99
+ });
100
+ }
@@ -1,12 +1,12 @@
1
1
  /** Regra do produto, entregue junto da política sem reescrever o artefato no serviço. */
2
- export const REGRA_DE_COMMITS = `## Identificação do agente nos commits
3
-
4
- Todo commit feito por agente começa com [IDENTIFICAÇÃO] - tipo: descrição.
5
- Exemplos: [CODEX] - feat: nova funcionalidade; [CLAUDE] - fix: corrige a busca;
6
- [GEMINI] - docs: atualiza o guia. Outro agente usa seu nome em maiúsculas entre colchetes.
7
- Identifique o agente/modelo que efetivamente realizou o commit, não apenas o editor:
8
- Claude no Antigravity continua [CLAUDE]; Gemini usa [GEMINI]; Codex usa [CODEX].
9
- Não invente a identidade. A regra não concede autorização para commitar, não altera
2
+ export const REGRA_DE_COMMITS = `## Identificação do agente nos commits
3
+
4
+ Todo commit feito por agente começa com [IDENTIFICAÇÃO] - tipo: descrição.
5
+ Exemplos: [CODEX] - feat: nova funcionalidade; [CLAUDE] - fix: corrige a busca;
6
+ [GEMINI] - docs: atualiza o guia. Outro agente usa seu nome em maiúsculas entre colchetes.
7
+ Identifique o agente/modelo que efetivamente realizou o commit, não apenas o editor:
8
+ Claude no Antigravity continua [CLAUDE]; Gemini usa [GEMINI]; Codex usa [CODEX].
9
+ Não invente a identidade. A regra não concede autorização para commitar, não altera
10
10
  o autor do Git e não pede reescrita de commits antigos.`;
11
11
  export function politicaParaSessao(conteudo) {
12
12
  if (!conteudo.trim() || conteudo.includes(REGRA_DE_COMMITS))