dd-harness 0.11.0 → 0.13.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/index.js +80 -52
- package/package.json +44 -44
package/dist/index.js
CHANGED
|
@@ -33,55 +33,55 @@ import { subiuOWorker } from "./worker.js";
|
|
|
33
33
|
* em repositorio alheio tem que envelhecer bem, e cada dependencia e uma chance de nao
|
|
34
34
|
* envelhecer.
|
|
35
35
|
*/
|
|
36
|
-
const AJUDA = `dd-harness — a política e o Brain do projeto, no serviço
|
|
37
|
-
|
|
38
|
-
dd-harness start numa pasta vazia: conduz tudo (login,
|
|
39
|
-
espaço, projeto, config) numa tacada
|
|
40
|
-
dd-harness login --token <token> [--api <url>]
|
|
41
|
-
guarda a credencial desta máquina
|
|
42
|
-
dd-harness projeto <slug> --nome "<nome>" [--tenant <t>] [--api <url>]
|
|
43
|
-
cria o projeto no serviço (antes do init)
|
|
44
|
-
dd-harness init --tenant <t> --projeto <p> [--api <url>]
|
|
45
|
-
prepara o repositório (config + CLAUDE.md)
|
|
46
|
-
dd-harness pasta <slug> --definicao "o que entra e o que não entra"
|
|
47
|
-
cria a pasta que o gravar exige
|
|
48
|
-
dd-harness gravar <arquivo.md> registra uma memória a partir de um markdown
|
|
49
|
-
dd-harness editar <arquivo.md> corrige o que já está gravado
|
|
50
|
-
dd-harness arquivar <pasta>/<slug> --motivo <obsoleta|incorreta|fora_dos_filtros>
|
|
51
|
-
[--substituida-por <pasta>/<slug>]
|
|
52
|
-
tira de circulação sem apagar
|
|
53
|
-
dd-harness buscar "<pergunta>" acha memória por relevância, não por arquivo
|
|
54
|
-
dd-harness ler <pasta>/<slug> imprime a memória inteira, no formato de gravar
|
|
55
|
-
dd-harness reancorar <pasta>/<slug> --de "<alvo>" --para "<alvo>"
|
|
56
|
-
troca o alvo de uma âncora que mudou de lugar
|
|
57
|
-
dd-harness check [--commit <sha>] mede as âncoras e reporta a deriva
|
|
58
|
-
dd-harness status só lê: o tamanho do Brain e o que espera julgamento
|
|
59
|
-
dd-harness politica [--hook] imprime a política do serviço
|
|
60
|
-
saída 0 = veio; 3 = projeto sem política;
|
|
61
|
-
1 = não consegui buscar
|
|
62
|
-
--hook: fala o protocolo do SessionStart do
|
|
63
|
-
Claude Code, para pôr a política no contexto
|
|
64
|
-
dd-harness --help
|
|
65
|
-
dd-harness --version qual binário está instalado nesta máquina
|
|
66
|
-
|
|
67
|
-
Nada do dd-harness fica em disco: a política chega pelo hook de sessão, e a
|
|
68
|
-
memória pela busca, na hora.
|
|
36
|
+
const AJUDA = `dd-harness — a política e o Brain do projeto, no serviço
|
|
37
|
+
|
|
38
|
+
dd-harness start numa pasta vazia: conduz tudo (login,
|
|
39
|
+
espaço, projeto, config) numa tacada
|
|
40
|
+
dd-harness login --token <token> [--api <url>]
|
|
41
|
+
guarda a credencial desta máquina
|
|
42
|
+
dd-harness projeto <slug> --nome "<nome>" [--tenant <t>] [--api <url>]
|
|
43
|
+
cria o projeto no serviço (antes do init)
|
|
44
|
+
dd-harness init --tenant <t> --projeto <p> [--api <url>]
|
|
45
|
+
prepara o repositório (config + CLAUDE.md)
|
|
46
|
+
dd-harness pasta <slug> --definicao "o que entra e o que não entra"
|
|
47
|
+
cria a pasta que o gravar exige
|
|
48
|
+
dd-harness gravar <arquivo.md> registra uma memória a partir de um markdown
|
|
49
|
+
dd-harness editar <arquivo.md> corrige o que já está gravado
|
|
50
|
+
dd-harness arquivar <pasta>/<slug> --motivo <obsoleta|incorreta|fora_dos_filtros>
|
|
51
|
+
[--substituida-por <pasta>/<slug>]
|
|
52
|
+
tira de circulação sem apagar
|
|
53
|
+
dd-harness buscar "<pergunta>" acha memória por relevância, não por arquivo
|
|
54
|
+
dd-harness ler <pasta>/<slug> imprime a memória inteira, no formato de gravar
|
|
55
|
+
dd-harness reancorar <pasta>/<slug> --de "<alvo>" --para "<alvo>"
|
|
56
|
+
troca o alvo de uma âncora que mudou de lugar
|
|
57
|
+
dd-harness check [--commit <sha>] mede as âncoras e reporta a deriva
|
|
58
|
+
dd-harness status só lê: o tamanho do Brain e o que espera julgamento
|
|
59
|
+
dd-harness politica [--hook] imprime a política do serviço
|
|
60
|
+
saída 0 = veio; 3 = projeto sem política;
|
|
61
|
+
1 = não consegui buscar
|
|
62
|
+
--hook: fala o protocolo do SessionStart do
|
|
63
|
+
Claude Code, para pôr a política no contexto
|
|
64
|
+
dd-harness --help
|
|
65
|
+
dd-harness --version qual binário está instalado nesta máquina
|
|
66
|
+
|
|
67
|
+
Nada do dd-harness fica em disco: a política chega pelo hook de sessão, e a
|
|
68
|
+
memória pela busca, na hora.
|
|
69
69
|
`;
|
|
70
70
|
/**
|
|
71
71
|
* Os ganchos sao IMPRESSOS, nunca instalados. `.git/hooks` nao e versionado e nao e
|
|
72
72
|
* nosso: escrever la dentro sem a pessoa pedir e o mesmo tipo de invasao que
|
|
73
73
|
* sobrescrever o CLAUDE.md dela. Quem cola, decide.
|
|
74
74
|
*/
|
|
75
|
-
const GANCHOS = `
|
|
76
|
-
Opcional — o gancho que devolve a memória ao code review:
|
|
77
|
-
|
|
78
|
-
.git/hooks/post-commit (avisa quais memórias falam do que você mudou)
|
|
79
|
-
#!/bin/sh
|
|
80
|
-
dd-harness check --commit "$(git rev-parse HEAD)" || true
|
|
81
|
-
|
|
82
|
-
Termina em sucesso mesmo com deriva: avisa, não bloqueia.
|
|
83
|
-
|
|
84
|
-
O hook da política (\`dd-harness politica --hook\`) é outra coisa, e não é
|
|
75
|
+
const GANCHOS = `
|
|
76
|
+
Opcional — o gancho que devolve a memória ao code review:
|
|
77
|
+
|
|
78
|
+
.git/hooks/post-commit (avisa quais memórias falam do que você mudou)
|
|
79
|
+
#!/bin/sh
|
|
80
|
+
dd-harness check --commit "$(git rev-parse HEAD)" || true
|
|
81
|
+
|
|
82
|
+
Termina em sucesso mesmo com deriva: avisa, não bloqueia.
|
|
83
|
+
|
|
84
|
+
O hook da política (\`dd-harness politica --hook\`) é outra coisa, e não é
|
|
85
85
|
opcional — \`dd-harness init\` imprime a linha para o \`.claude/settings.json\`.`;
|
|
86
86
|
function argumento(argv, nome) {
|
|
87
87
|
const i = argv.indexOf(`--${nome}`);
|
|
@@ -151,6 +151,10 @@ function tentaAbrirNavegador(url) {
|
|
|
151
151
|
// Segue sem navegador — a URL impressa antes desta chamada ja resolve.
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
+
/** Token no terminal aparece mascarado: o prefixo basta para reconhecer, o segredo nao precisa ser lido em voz alta. */
|
|
155
|
+
function mascara(token) {
|
|
156
|
+
return token.length <= 16 ? "***" : `${token.slice(0, 12)}...${token.slice(-4)}`;
|
|
157
|
+
}
|
|
154
158
|
/**
|
|
155
159
|
* `dd-harness start` — o wizard para pasta vazia.
|
|
156
160
|
*
|
|
@@ -185,13 +189,27 @@ async function comandoStart() {
|
|
|
185
189
|
"novo — start segue mesmo assim, mas pode faltar correção.\n");
|
|
186
190
|
}
|
|
187
191
|
// 1. Credencial. Sem ela nada do resto e possivel — nem listar tenant.
|
|
192
|
+
// O estado aparece SEMPRE, mesmo quando ja existe credencial: antes o passo era
|
|
193
|
+
// pulado em silencio, e quem rodava `start` com um token velho (ou de outra conta)
|
|
194
|
+
// nao tinha como perceber — o wizard so falhava depois, ao listar espacos.
|
|
188
195
|
let token = await leToken(API_PADRAO);
|
|
196
|
+
if (token) {
|
|
197
|
+
console.log(`Credencial: ${mascara(token)} (${API_PADRAO})`);
|
|
198
|
+
const troca = await pergunta("Usar esta credencial? [S/n]: ");
|
|
199
|
+
if (/^n/i.test(troca))
|
|
200
|
+
token = null;
|
|
201
|
+
}
|
|
189
202
|
if (!token) {
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
const url = `${API_PADRAO}/tokens`;
|
|
204
|
+
console.log(`\nCrie um token pessoal em ${url} — abrindo no navegador...`);
|
|
205
|
+
tentaAbrirNavegador(url);
|
|
206
|
+
token = await pergunta("Cole o token aqui: ");
|
|
207
|
+
if (!token)
|
|
208
|
+
throw new Error("sem token não dá para seguir: `start` fala com o serviço em todos os passos.");
|
|
192
209
|
await guardaToken(API_PADRAO, token);
|
|
193
|
-
console.log("Credencial guardada
|
|
210
|
+
console.log("Credencial guardada.");
|
|
194
211
|
}
|
|
212
|
+
console.log("");
|
|
195
213
|
// 2. Espaco (tenant). Criar um e ato de dono — nunca por aqui — mas ESCOLHER entre
|
|
196
214
|
// os que ja existem e so leitura, e e o que faltava para nao exigir o slug de memoria.
|
|
197
215
|
let tenants = await listaTenants(API_PADRAO, token);
|
|
@@ -203,18 +221,28 @@ async function comandoStart() {
|
|
|
203
221
|
tenants = await listaTenants(API_PADRAO, token);
|
|
204
222
|
}
|
|
205
223
|
const tenant = await escolha("\nEscolha um espaço:", tenants.map((t) => ({ rotulo: `${t.nome} (${t.slug})`, valor: t.slug })));
|
|
206
|
-
// 3. Projeto. Criar e subordinado a estar num espaco
|
|
207
|
-
|
|
224
|
+
// 3. Projeto. Criar e subordinado a estar num espaco - isso o CLI ja faz sozinho.
|
|
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";
|
|
208
234
|
const nome = (await pergunta(`\nNome do projeto [${nomeSugerido}]: `)) || nomeSugerido;
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
|
|
235
|
+
// O slug sai do nome, sem perguntar: e identificador, nao escolha editorial, e quem
|
|
236
|
+
// esta comecando nao tem como saber que ele vira a chave do `.dd-harness.json`.
|
|
237
|
+
// Nome so com caracteres especiais (ex: "!!!") normaliza para string vazia - o
|
|
238
|
+
// fallback evita slug vazio, que o servidor recusaria com erro confuso.
|
|
239
|
+
const slugDoProjeto = nome
|
|
212
240
|
.toLowerCase()
|
|
213
241
|
.normalize("NFD")
|
|
214
242
|
.replace(/[̀-ͯ]/g, "")
|
|
215
243
|
.replace(/[^a-z0-9]+/g, "-")
|
|
216
244
|
.replace(/^-+|-+$/g, "") || "meu-projeto";
|
|
217
|
-
|
|
245
|
+
console.log(`Identificador: ${slugDoProjeto}`);
|
|
218
246
|
const resultadoProjeto = await criaProjeto(process.cwd(), slugDoProjeto, nome, {
|
|
219
247
|
tenant,
|
|
220
248
|
api: API_PADRAO,
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dd-harness",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
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
|
-
"license": "UNLICENSED",
|
|
7
|
-
"author": "Diego Dias",
|
|
8
|
-
"keywords": [
|
|
9
|
-
"claude-code",
|
|
10
|
-
"ai-agents",
|
|
11
|
-
"memory",
|
|
12
|
-
"brain",
|
|
13
|
-
"cli"
|
|
14
|
-
],
|
|
15
|
-
"homepage": "https://dd-harness.vercel.app",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/diegodias93/dd-harness-online.git",
|
|
19
|
-
"directory": "packages/cli"
|
|
20
|
-
},
|
|
21
|
-
"bin": {
|
|
22
|
-
"dd-harness": "dist/index.js"
|
|
23
|
-
},
|
|
24
|
-
"//exports": "Aponta para `dist` porque quem IMPORTA isto em tempo de execucao e o Node, que nao executa TypeScript. Nao aponte para `src`: o Node segue os imports relativos de dentro do arquivo e tenta abrir `./api.js` ao lado do `.ts`, que nao existe. Quem consome no workspace e o `packages/mcp`, e ele compila o fonte do CLI junto (ver o tsconfig.build.json dele) em vez de depender deste campo — assim o build funciona num checkout limpo, sem `dist` previo.",
|
|
25
|
-
"exports": {
|
|
26
|
-
"./api": "./dist/api.js",
|
|
27
|
-
"./buscar": "./dist/buscar.js",
|
|
28
|
-
"./curar": "./dist/curar.js",
|
|
29
|
-
"./gravar": "./dist/gravar.js",
|
|
30
|
-
"./pasta": "./dist/pasta.js",
|
|
31
|
-
"./projeto": "./dist/projeto.js"
|
|
32
|
-
},
|
|
33
|
-
"files": [
|
|
34
|
-
"dist"
|
|
35
|
-
],
|
|
36
|
-
"engines": {
|
|
37
|
-
"node": ">=20"
|
|
38
|
-
},
|
|
39
|
-
"scripts": {
|
|
40
|
-
"typecheck": "tsc -p . --noEmit",
|
|
41
|
-
"build": "tsc -p tsconfig.build.json",
|
|
42
|
-
"prepublishOnly": "npm run build"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dd-harness",
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"type": "module",
|
|
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
|
+
"license": "UNLICENSED",
|
|
7
|
+
"author": "Diego Dias",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"claude-code",
|
|
10
|
+
"ai-agents",
|
|
11
|
+
"memory",
|
|
12
|
+
"brain",
|
|
13
|
+
"cli"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://dd-harness.vercel.app",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/diegodias93/dd-harness-online.git",
|
|
19
|
+
"directory": "packages/cli"
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"dd-harness": "dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"//exports": "Aponta para `dist` porque quem IMPORTA isto em tempo de execucao e o Node, que nao executa TypeScript. Nao aponte para `src`: o Node segue os imports relativos de dentro do arquivo e tenta abrir `./api.js` ao lado do `.ts`, que nao existe. Quem consome no workspace e o `packages/mcp`, e ele compila o fonte do CLI junto (ver o tsconfig.build.json dele) em vez de depender deste campo — assim o build funciona num checkout limpo, sem `dist` previo.",
|
|
25
|
+
"exports": {
|
|
26
|
+
"./api": "./dist/api.js",
|
|
27
|
+
"./buscar": "./dist/buscar.js",
|
|
28
|
+
"./curar": "./dist/curar.js",
|
|
29
|
+
"./gravar": "./dist/gravar.js",
|
|
30
|
+
"./pasta": "./dist/pasta.js",
|
|
31
|
+
"./projeto": "./dist/projeto.js"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=20"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"typecheck": "tsc -p . --noEmit",
|
|
41
|
+
"build": "tsc -p tsconfig.build.json",
|
|
42
|
+
"prepublishOnly": "npm run build"
|
|
43
|
+
}
|
|
44
|
+
}
|