dd-harness 0.12.0 → 0.14.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Escrita de `.claude/settings.json`, `.mcp.json` e `AGENTS.md`, com merge.
2
+ * Escrita de `.claude/settings.json`, `.mcp.json`, `CLAUDE.md` e `AGENTS.md`, com merge.
3
3
  *
4
4
  * `init` (o comando antigo) so SUGERE esses arquivos — decisao de proposito, porque
5
5
  * mesclar JSON alheio e onde falha silenciosa nasce. `start` (o wizard) reverte essa
@@ -31,11 +31,22 @@ export declare function escreveHook(raiz: string): Promise<ResultadoDaEscrita<"c
31
31
  /** Acrescenta o servidor MCP a `.mcp.json`, sem tocar em outros servidores. */
32
32
  export declare function escreveMcp(raiz: string): Promise<ResultadoDaEscrita<"criado" | "ja-tinha" | "acrescentado">>;
33
33
  /**
34
- * `AGENTS.md` e markdown livre, nao JSONnao ha "mesclar" de verdade. Se o arquivo ja
35
- * existe (com qualquer conteudo), so acrescenta a instrucao no fim; nunca sobrescreve
36
- * o que a pessoa escreveu, porque markdown de outra ferramenta e mais dificil de separar
37
- * do nosso do que uma chave de objeto.
34
+ * Os dois pontos de entrada do repositorio `CLAUDE.md` (Claude Code) e `AGENTS.md`
35
+ * (Codex, Cursor, Gemini CLI, Windsurf) sao ESPELHOS: o mesmo apontamento para o
36
+ * dd-harness, sem regra propria. Nenhum dos dois e opcional, e nao ha pergunta sobre
37
+ * "qual ferramenta voce usa": quem abre o repositorio encontra o protocolo pela porta
38
+ * que a SUA ferramenta le, e as duas dizem a mesma coisa. Regra fica no servico; aqui
39
+ * fica so o ponteiro — por isso espelhar nao duplica nada que possa divergir.
40
+ *
41
+ * Markdown e livre, nao JSON: nao ha "mesclar" de verdade. Se o arquivo ja existe (com
42
+ * qualquer conteudo), so acrescenta a instrucao no fim; nunca sobrescreve o que a pessoa
43
+ * escreveu, porque markdown alheio e mais dificil de separar do nosso do que uma chave
44
+ * de objeto.
38
45
  */
39
- export declare function escreveAgents(raiz: string): Promise<{
46
+ export declare function escrevePonteiro(raiz: string, arquivo: "AGENTS.md" | "CLAUDE.md"): Promise<{
47
+ estado: "criado" | "ja-tinha" | "acrescentado";
48
+ }>;
49
+ /** Compatibilidade: `init` ainda chama pelo nome antigo. */
50
+ export declare const escreveAgents: (raiz: string) => Promise<{
40
51
  estado: "criado" | "ja-tinha" | "acrescentado";
41
52
  }>;
@@ -63,13 +63,20 @@ export async function escreveMcp(raiz) {
63
63
  return { ok: true, estado: eraVazio ? "criado" : "acrescentado" };
64
64
  }
65
65
  /**
66
- * `AGENTS.md` e markdown livre, nao JSONnao ha "mesclar" de verdade. Se o arquivo ja
67
- * existe (com qualquer conteudo), so acrescenta a instrucao no fim; nunca sobrescreve
68
- * o que a pessoa escreveu, porque markdown de outra ferramenta e mais dificil de separar
69
- * do nosso do que uma chave de objeto.
66
+ * Os dois pontos de entrada do repositorio `CLAUDE.md` (Claude Code) e `AGENTS.md`
67
+ * (Codex, Cursor, Gemini CLI, Windsurf) sao ESPELHOS: o mesmo apontamento para o
68
+ * dd-harness, sem regra propria. Nenhum dos dois e opcional, e nao ha pergunta sobre
69
+ * "qual ferramenta voce usa": quem abre o repositorio encontra o protocolo pela porta
70
+ * que a SUA ferramenta le, e as duas dizem a mesma coisa. Regra fica no servico; aqui
71
+ * fica so o ponteiro — por isso espelhar nao duplica nada que possa divergir.
72
+ *
73
+ * Markdown e livre, nao JSON: nao ha "mesclar" de verdade. Se o arquivo ja existe (com
74
+ * qualquer conteudo), so acrescenta a instrucao no fim; nunca sobrescreve o que a pessoa
75
+ * escreveu, porque markdown alheio e mais dificil de separar do nosso do que uma chave
76
+ * de objeto.
70
77
  */
71
- export async function escreveAgents(raiz) {
72
- const caminho = join(raiz, "AGENTS.md");
78
+ export async function escrevePonteiro(raiz, arquivo) {
79
+ const caminho = join(raiz, arquivo);
73
80
  const instrucao = SUGESTAO_AGENTS;
74
81
  let atual = null;
75
82
  try {
@@ -88,14 +95,16 @@ export async function escreveAgents(raiz) {
88
95
  await writeFile(caminho, `${atual}${separador}${instrucao}\n`, "utf8");
89
96
  return { estado: "acrescentado" };
90
97
  }
91
- const SUGESTAO_AGENTS = `## Protocolo do dd-harness
92
-
93
- Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
94
-
95
- **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
96
- \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
97
- de ler código, responder ou planejar.
98
-
99
- - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
100
- avise o usuário e **não modifique nada** até ele resolver.
98
+ /** Compatibilidade: `init` ainda chama pelo nome antigo. */
99
+ export const escreveAgents = (raiz) => escrevePonteiro(raiz, "AGENTS.md");
100
+ const SUGESTAO_AGENTS = `## Protocolo do dd-harness
101
+
102
+ Este projeto tem um protocolo de trabalho que **não está neste arquivo**.
103
+
104
+ **ANTES de qualquer outra coisa**, chame a ferramenta MCP \`ler_artefato\` com
105
+ \`tipo: "politica"\` e siga o que ela devolver. É a primeira ação da sessão, antes
106
+ de ler código, responder ou planejar.
107
+
108
+ - Se a ferramenta não existir, o servidor MCP do dd-harness não está declarado:
109
+ avise o usuário e **não modifique nada** até ele resolver.
101
110
  - Se ela devolver vazio, este projeto nunca foi briefado — diga isso ao usuário.`;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ process.removeAllListeners("warning");
14
14
  import { termosDaConsulta } from "./argv.js";
15
15
  import { check, status } from "./check.js";
16
16
  import { CAMINHO_CONFIG, guardaConfigDaMaquina, guardaToken, leConfigDaMaquina, leConfigDoRepo, leToken, } from "./config.js";
17
- import { escreveAgents, escreveHook, escreveMcp } from "./escreve-config.js";
17
+ import { escreveHook, escreveMcp, escrevePonteiro } from "./escreve-config.js";
18
18
  import { grava } from "./gravar.js";
19
19
  import { init, SUGESTAO_AGENTS, SUGESTAO_HOOK, SUGESTAO_MCP } from "./init.js";
20
20
  import { pergunta, escolha, fechaPerguntas } from "./pergunta.js";
@@ -222,7 +222,15 @@ async function comandoStart() {
222
222
  }
223
223
  const tenant = await escolha("\nEscolha um espaço:", tenants.map((t) => ({ rotulo: `${t.nome} (${t.slug})`, valor: t.slug })));
224
224
  // 3. Projeto. Criar e subordinado a estar num espaco - isso o CLI ja faz sozinho.
225
- const nomeSugerido = process.cwd().split(/[\\/]/).pop() ?? "meu-projeto";
225
+ // A pasta se chama `tiktok-drawer`; o projeto se chama `TikTok Drawer`. Sugerir o
226
+ // nome da pasta cru fazia o wizard propor um identificador onde se pede um titulo —
227
+ // e o slug, que e quem precisa daquele formato, ja sai daqui de baixo sozinho.
228
+ const pasta = process.cwd().split(/[\\/]/).pop() ?? "meu-projeto";
229
+ const nomeSugerido = pasta
230
+ .replace(/[-_]+/g, " ")
231
+ .replace(/\s+/g, " ")
232
+ .trim()
233
+ .replace(/\b\w/g, (c) => c.toUpperCase()) || "Meu Projeto";
226
234
  const nome = (await pergunta(`\nNome do projeto [${nomeSugerido}]: `)) || nomeSugerido;
227
235
  // O slug sai do nome, sem perguntar: e identificador, nao escolha editorial, e quem
228
236
  // esta comecando nao tem como saber que ele vira a chave do `.dd-harness.json`.
@@ -279,15 +287,18 @@ async function comandoStart() {
279
287
  "conexão do Claude Code pode demorar ou falhar; se falhar, abra uma nova sessão " +
280
288
  "e tente de novo.");
281
289
  }
282
- // 6. AGENTS.md — so quem usa outra ferramenta alem do Claude Code precisa.
283
- const outraFerramenta = await pergunta("\nVai abrir este projeto em Codex, Cursor ou outra ferramenta além do Claude " +
284
- "Code? [s/N]: ");
285
- if (/^s/i.test(outraFerramenta)) {
286
- const agents = await escreveAgents(process.cwd());
287
- console.log({ criado: "criado AGENTS.md",
288
- "ja-tinha": "mantido AGENTS.md — já apontava para a política",
289
- acrescentado: "atualizado AGENTS.md (instrução acrescentada ao que já existia)",
290
- }[agents.estado]);
290
+ // 6. CLAUDE.md e AGENTS.md — os dois SEMPRE, sem perguntar. Sao espelhos: o mesmo
291
+ // apontamento para o servico, cada um na porta que uma familia de ferramenta le. A
292
+ // pergunta "usa outra ferramenta?" saiu porque a resposta nao muda nada que valha a
293
+ // pena — quem responde "nao" hoje abre o repositorio no Cursor semana que vem e nao
294
+ // encontra protocolo nenhum, e o custo de ja ter o arquivo e um ponteiro de 8 linhas.
295
+ console.log("");
296
+ for (const arquivo of ["CLAUDE.md", "AGENTS.md"]) {
297
+ const r = await escrevePonteiro(process.cwd(), arquivo);
298
+ console.log({ criado: `criado ${arquivo}`,
299
+ "ja-tinha": `mantido ${arquivo} — já apontava para a política`,
300
+ acrescentado: `atualizado ${arquivo} (apontamento acrescentado ao que já existia)`,
301
+ }[r.estado]);
291
302
  }
292
303
  // 7. Onde esta o monorepo do worker nesta maquina? So pergunta uma vez, e so importa
293
304
  // se houver memoria na fila agora — pular aqui nao trava nada, so avisa mais vezes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-harness",
3
- "version": "0.12.0",
3
+ "version": "0.14.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",