dd-harness 0.34.0 → 0.36.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/atualizar.js CHANGED
@@ -4,6 +4,9 @@ import { analisa } from "./bloco.js";
4
4
  import { MOLDES_HISTORICOS } from "./moldes-historicos.js";
5
5
  import { COMANDO_DO_CINTO, COMANDO_DO_HOOK, SUGESTAO_AGENTS, VERSAO_DO_MOLDE, escreveHook, escrevePonteiro } from "./escreve-config.js";
6
6
  import { versaoDoPacote } from "./versao.js";
7
+ import { criaSkill, escrevePonteirosDeSkills, leSkills } from "./skill.js";
8
+ import { hostsInstalados } from "./hosts.js";
9
+ import { SKILLS_INICIAIS } from "./skills-iniciais.js";
7
10
  /**
8
11
  * `aplicar` e o que esta funcao pode fazer sozinha com seguranca; `perguntar` exige o dono
9
12
  * do arquivo; `manual` e o que nao se resolve de dentro do repositorio (o CLI global e por
@@ -64,8 +67,74 @@ export async function diagnosticaAtualizacao(raiz, versaoInstalada, versaoPublic
64
67
  ? { o_que: "hooks", situacao: "sessão e cinto declarados", acao: "em-dia" }
65
68
  : { o_que: "hooks", situacao: settings ? "incompletos ou legados" : "ausentes", acao: "aplicar",
66
69
  detalhe: "acrescenta sem duplicar nem tocar em hook de terceiro" });
70
+ // 4. Skills iniciais que nasceram depois deste projeto.
71
+ //
72
+ // A semeadura so roda em projeto SEM skill alguma, e o efeito colateral e que skill NOVA
73
+ // nunca alcanca projeto que ja existe: um projeto de dois meses atras ficou com as seis
74
+ // daquela epoca, e as que vieram depois so existiam em projeto criado do zero. Este item
75
+ // e o caminho que faltava.
76
+ //
77
+ // Skill inicial que falta e skill que NASCEU DEPOIS deste projeto — as padrao nao se
78
+ // apagam, entao ausencia aqui nao e decisao de ninguem, e recria-la nao desfaz nada.
79
+ // Por isso `aplicar`: e o mesmo caso do hook que faltava, e nao o do CLAUDE.md editado.
80
+ //
81
+ // A skill do projeto continua editavel: criar a que falta nao mexe em nenhuma existente,
82
+ // e o `criaSkill` erra de proposito se o slug ja existir.
83
+ try {
84
+ const existentes = new Set((await leSkills(raiz)).map(s => s.slug));
85
+ const faltando = SKILLS_INICIAIS.filter(s => !existentes.has(s.slug)).map(s => s.slug);
86
+ itens.push(faltando.length === 0
87
+ ? { o_que: "skills", situacao: `${existentes.size} no projeto; nenhuma inicial faltando`, acao: "em-dia" }
88
+ : {
89
+ o_que: "skills",
90
+ situacao: `${faltando.length} skill(s) inicial(is) nasceram depois deste projeto`,
91
+ acao: "aplicar",
92
+ detalhe: `${faltando.join(", ")} — serão criadas no serviço; as existentes não são tocadas`,
93
+ });
94
+ }
95
+ catch {
96
+ // Sem rede ou sem credencial: o resto do diagnostico continua valendo, e skill faltando
97
+ // nao e urgente o bastante para derrubar a checagem inteira.
98
+ itens.push({ o_que: "skills", situacao: "não consegui consultar o serviço", acao: "manual",
99
+ detalhe: "confira com `dd-harness skills` quando o serviço responder" });
100
+ }
67
101
  return itens;
68
102
  }
103
+ /** Cria no serviço as skills iniciais que este projeto ainda não tem. */
104
+ async function criaSkillsFaltantes(raiz) {
105
+ const existentes = new Set((await leSkills(raiz)).map(s => s.slug));
106
+ const faltando = SKILLS_INICIAIS.filter(s => !existentes.has(s.slug));
107
+ const criadas = [];
108
+ const falharam = [];
109
+ for (const inicial of faltando) {
110
+ try {
111
+ await criaSkill(raiz, inicial);
112
+ criadas.push(inicial.slug);
113
+ }
114
+ catch {
115
+ // Uma que nao entrou nao impede as outras: metade criada e melhor que nenhuma, e a
116
+ // linha de retorno diz exatamente qual faltou.
117
+ falharam.push(inicial.slug);
118
+ }
119
+ }
120
+ let ponteiros = "";
121
+ // A skill no servico nao e descoberta por host nenhum sem o ponteiro em disco: o Claude
122
+ // Code le `.claude/skills/*/SKILL.md` na abertura da sessao, e MCP nao fornece skill.
123
+ // Criar no servico e parar aqui entregaria uma skill que so aparece no boot seguinte.
124
+ if (criadas.length) {
125
+ try {
126
+ const hosts = await hostsInstalados(raiz);
127
+ const destinos = [...new Set(hosts.map(h => h === "claude" ? ".claude" : ".agents"))];
128
+ const r = await escrevePonteirosDeSkills(raiz, await leSkills(raiz), destinos.length ? destinos : [".claude"]);
129
+ ponteiros = `; ${r.escritos} ponteiro(s) em disco`;
130
+ }
131
+ catch {
132
+ ponteiros = "; ponteiros NÃO escritos — rode `dd-harness integrar` ou reabra a sessão";
133
+ }
134
+ }
135
+ return `skills: ${criadas.length} criada(s)${criadas.length ? " — " + criadas.join(", ") : ""}` +
136
+ (falharam.length ? `; FALHARAM: ${falharam.join(", ")}` : "") + ponteiros;
137
+ }
69
138
  /**
70
139
  * Aplica so os itens marcados `aplicar`. Os de `perguntar` ficam intactos de proposito —
71
140
  * quem decide sobre arquivo editado a mao e o dono dele.
@@ -83,6 +152,14 @@ export async function aplicaAtualizacao(raiz, itens) {
83
152
  // um projeto que continua sem o cinto.
84
153
  feitos.push(r.ok ? `hooks: ${r.estado}` : `hooks: NÃO aplicado (${r.motivo})`);
85
154
  }
155
+ else if (item.o_que === "skills") {
156
+ try {
157
+ feitos.push(await criaSkillsFaltantes(raiz));
158
+ }
159
+ catch (erro) {
160
+ feitos.push(`skills: NÃO aplicado (${erro instanceof Error ? erro.message : String(erro)})`);
161
+ }
162
+ }
86
163
  }
87
164
  return feitos;
88
165
  }
@@ -575,4 +575,129 @@ que estava fora do bloco continua intacto** — é a garantia que o usuário que
575
575
  Se o projeto tem git, sugira conferir o diff antes de commitar. Não commite: o projeto é
576
576
  do usuário e as regras de commit dele são dele.`,
577
577
  },
578
+ {
579
+ slug: "revisar-memoria",
580
+ descricao: `Investiga se memórias antigas do Brain ainda são verdadeiras e traz um parecer com evidência, para você decidir. Invoque quando quiser fazer uma faxina do Brain, quando o status mostrar revisão vencida, ou quando desconfiar que alguma decisão registrada envelheceu. Só investiga e relata — nunca edita, arquiva ou apaga nada.`,
581
+ ferramentas: ["mcp__dd-harness__ler_memoria", "mcp__dd-harness__buscar_memoria", "Read", "Grep", "Glob", "WebSearch", "WebFetch", "Bash(dd-harness status:*)", "Bash(dd-harness check:*)", "Bash(dd-harness ler:*)", "Bash(git log:*)", "Bash(git diff:*)"],
582
+ so_por_comando: true,
583
+ dica_de_argumento: "[pasta/slug para revisar uma só, ou vazio para varrer o acervo]",
584
+ conteudo: `# Revisar memória
585
+
586
+ A deriva pega a memória cujo **código** mudou. Esta skill existe para a outra — a que
587
+ ninguém olha há muito tempo e cuja **razão** pode ter morrido sem deixar rastro no
588
+ repositório: o fornecedor mudou o limite, o bug de terceiro foi corrigido, a exigência de
589
+ compliance caiu, a lib passou a fazer nativamente o que a memória ensina a contornar.
590
+
591
+ Nenhum \`check\` acusa isso. O alvo está intacto; é o mundo que mudou.
592
+
593
+ ## A regra que não se quebra
594
+
595
+ **Você não edita, não arquiva e não apaga. Nada.** Esta skill investiga e apresenta o
596
+ caso; quem decide é o usuário, na conversa.
597
+
598
+ Isso não é cautela decorativa: arquivar tira a memória de circulação, e quem vier depois
599
+ não saberá que ela existiu se você errar. O custo dos dois erros é assimétrico — manter
600
+ uma memória morta custa uma linha de índice; apagar uma viva custa o incidente que ela
601
+ evitava, e ninguém vai ligar uma coisa à outra.
602
+
603
+ ## Idade não é veredito
604
+
605
+ O critério tentador é "ninguém revisitou há muito tempo, logo não serve". **Está errado, e
606
+ o ROADMAP deste projeto já registra por quê:** contagem baixa correlaciona com *raridade*,
607
+ não com inutilidade — a memória que protege contra o erro raro e catastrófico é a que tem
608
+ a contagem mais baixa de todas.
609
+
610
+ Então idade é **motivo para olhar**, nunca argumento no parecer. Se o único fundamento que
611
+ você tiver para propor a saída de uma memória for "é antiga", **você não tem fundamento**:
612
+ relate como "continua valendo" e siga.
613
+
614
+ ## 1. Escolha as candidatas
615
+
616
+ Com \`pasta/slug\` no argumento, é aquela — pule para o passo 2.
617
+
618
+ Sem argumento, monte a lista nesta ordem:
619
+
620
+ 1. \`dd-harness status\` — as que ele já aponta como **revisão vencida** entram primeiro
621
+ 2. Memórias antigas que **nunca** tiveram deriva (código estável ao redor: é exatamente
622
+ onde esta skill enxerga o que o \`check\` não vê)
623
+ 3. As que citam **coisa de fora** — versão, fornecedor, limite, prazo, bug de terceiro:
624
+ são as que envelhecem sem avisar
625
+
626
+ **Teto de cinco por rodada.** Cada memória é uma investigação de verdade; trazer quinze
627
+ pareceres rasos é pior que trazer três com evidência, e o usuário não consegue decidir
628
+ sobre quinze de uma vez.
629
+
630
+ ## 2. Leia a memória inteira — o porquê, não o título
631
+
632
+ \`ler_memoria\`. A pergunta que governa tudo:
633
+
634
+ > A razão que fez esta memória existir continua verdadeira **hoje**?
635
+
636
+ Identifique de que tipo é a afirmação, porque cada uma se verifica num lugar diferente:
637
+
638
+ | Tipo | Onde se confere |
639
+ |---|---|
640
+ | Sobre o código deste projeto | o próprio repositório |
641
+ | Sobre lib, versão ou API | changelog, release notes, a doc atual |
642
+ | Sobre fornecedor, limite ou contrato | a doc do fornecedor |
643
+ | Sobre bug de terceiro | o issue: foi corrigido? |
644
+ | Sobre decisão interna | o projeto ainda funciona assim? |
645
+
646
+ ## 3. Vá conferir — não opine
647
+
648
+ Este é o passo que separa esta skill de um chute fundamentado.
649
+
650
+ - **No repositório:** a âncora existe? O código ainda faz o que a memória descreve?
651
+ \`git log\` no alvo mostra que alguém mexeu naquilo?
652
+ - **Fora:** quando a razão é externa, **procure a fonte**. Um \`WebSearch\` pela versão atual
653
+ da lib, pelo limite atual da API, pelo issue citado. Se a memória diz "a v3 não suporta
654
+ X" e a v5 suporta, isso é achado — e sem ir olhar você nunca saberia.
655
+
656
+ Se não conseguir verificar, **diga que não conseguiu.** "Não achei fonte para confirmar o
657
+ limite atual" é um parecer honesto e útil. Inventar uma conclusão para parecer produtivo é
658
+ o pior resultado possível desta skill.
659
+
660
+ ## 4. Traga o parecer
661
+
662
+ Um bloco por memória, na conversa. Curto, com a evidência à mostra:
663
+
664
+ \`\`\`
665
+ pasta/slug — Título
666
+
667
+ Diz: [a afirmação, em uma linha]
668
+ Verifiquei: [o que você foi olhar, com link/caminho/commit]
669
+ Achei: [o que encontrou de fato]
670
+ Parecer: continua valendo | envelheceu no texto | a razão pode ter morrido
671
+ Por quê: [o fundamento — nunca "é antiga"]
672
+ \`\`\`
673
+
674
+ Três pareceres possíveis, e nenhum é uma ação:
675
+
676
+ **Continua valendo** — a razão está de pé. Diga isso e siga; não há trabalho a fazer.
677
+
678
+ **Envelheceu no texto** — a razão continua, a descrição não bate mais. Mostre o trecho
679
+ que está errado e o que seria o texto certo. O usuário decide se manda editar.
680
+
681
+ **A razão pode ter morrido** — você encontrou evidência de que o motivo acabou. Mostre a
682
+ evidência. Use "pode": você investigou, não sentenciou; pode haver contexto que a memória
683
+ não registrou e o usuário conhece.
684
+
685
+ Ao fim, uma linha só: quantas revisou, quantas continuam valendo, quantas merecem a
686
+ atenção dele. Se nenhuma mereceu, **diga exatamente isso** — "revisei cinco, todas
687
+ continuam valendo" é um resultado bom, não uma rodada perdida.
688
+
689
+ ## Nunca faça
690
+
691
+ **Não proponha saída em lote.** Cinco memórias são cinco perguntas; um "essas cinco podem
692
+ sair" é o mesmo que não ter investigado nenhuma.
693
+
694
+ **Não use a data de revisão como argumento.** Ela é agenda, não julgamento. Uma memória
695
+ vencida que você verificou e continua verdadeira é "continua valendo" — não "vencida".
696
+
697
+ **Não confunda com deriva.** Se o achado é "o arquivo ancorado sumiu", isso é trabalho da
698
+ \`resolver-deriva\`; diga ao usuário e aponte para lá em vez de resolver aqui.
699
+
700
+ **Não vá pelo acervo inteiro.** O teto de cinco é o que mantém cada parecer com evidência.
701
+ Fila é para ser processada aos poucos, e ela não vai a lugar nenhum.`,
702
+ },
578
703
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-harness",
3
- "version": "0.34.0",
3
+ "version": "0.36.0",
4
4
  "type": "module",
5
5
  "description": "Política, memória e integrações de Claude Code, Codex e Antigravity. CLI sem dependências de runtime.",
6
6
  "license": "UNLICENSED",