@pathbit/agentdevkit 0.0.6 → 0.0.7

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.
@@ -114,6 +114,52 @@ function rootProbes(root, roots) {
114
114
  return roots.filter(path => { const item = localStat(join(root, path)); return !item || item.isDirectory(); }).map(path => `${path}/.agentdevkit-ignore-probe`);
115
115
  }
116
116
 
117
+ function artifactPolicy(templateFile) {
118
+ const adjacent = join(dirname(templateFile), 'agents.ignore');
119
+ const source = checkedLocalPath(localStat(adjacent) ? adjacent : fileURLToPath(new URL('../../templates/gitignore/agents.ignore', import.meta.url)));
120
+ const content = readFileSync(source, 'utf8');
121
+ const section = content.split(/^## Resultados e arquivos temporarios\r?$/m)[1]?.split(/^## /m)[0];
122
+ const patterns = section?.split(/\r?\n/).map(line => line.trim()).filter(line => line && !line.startsWith('#'));
123
+ if (!patterns?.length || patterns.some(pattern => !pattern.startsWith('**/') || /[!\\\x00-\x1f]/.test(pattern) || pattern.split('/').includes('..'))) throw new Error('Secao de artefatos invalida em agents.ignore.');
124
+ return patterns;
125
+ }
126
+
127
+ function artifactProbes(root, patterns) {
128
+ const probes = new Set();
129
+ for (const pattern of patterns) {
130
+ const stem = pattern.slice(3).replace(/\/$/, '').replace(/\[([^\]]+)\]/g, (_match, letters) => letters[0]).replace(/\?/g, 'x');
131
+ const names = stem.includes('*') ? ['', '-mcp', '-report', '-cache', '-agentdevkit'].map(suffix => stem.replace(/\*/g, suffix)) : [stem];
132
+ for (const name of names) for (const variant of new Set([name, name.toLowerCase()])) {
133
+ const leaves = stem.includes('*') ? ['.agentdevkit-artifact-probe', '.cache/.agentdevkit-artifact-probe'] : ['.agentdevkit-artifact-probe'];
134
+ for (const leaf of leaves) for (const path of [`${variant}/${leaf}`, `.agentdevkit-ignore-probes/${variant}/${leaf}`]) {
135
+ let parent = root, safe = true;
136
+ for (const part of path.split('/').slice(0, -1)) {
137
+ parent = join(parent, part); const item = localStat(parent);
138
+ if (item && !item.isDirectory()) { safe = false; break; }
139
+ }
140
+ if (safe) probes.add(path);
141
+ }
142
+ }
143
+ }
144
+ return [...probes];
145
+ }
146
+
147
+ function localIgnoreSource(location, source) {
148
+ const path = resolve(location.top, source);
149
+ if (path === location.exclude) return true;
150
+ const inside = relative(location.top, path);
151
+ return basename(path) === '.gitignore' && !isAbsolute(inside) && inside !== '..' && !inside.startsWith(`..${sep}`);
152
+ }
153
+
154
+ function ignoreMatches(location, probes) {
155
+ const paths = probes.map(path => location.prefix ? `${location.prefix}/${path}` : path);
156
+ const result = gitCommand(location.top, ['-c', 'core.excludesFile=', 'check-ignore', '--verbose', '--no-index', '--stdin', '-z'], paths.join('\0') + '\0');
157
+ if (result.error || ![0, 1].includes(result.status)) throw new Error(result.error?.message || result.stderr || 'Falha ao conferir exclusoes Git.');
158
+ const values = result.stdout.split('\0'), matches = new Map();
159
+ for (let index = 0; index + 3 < values.length; index += 4) matches.set(values[index + 3], { source: values[index], line: Number(values[index + 1]), pattern: values[index + 2] });
160
+ return { paths, matches };
161
+ }
162
+
117
163
  function localRoot(value) {
118
164
  const missing = []; let parent = resolve(value);
119
165
  while (!localStat(parent)) { missing.unshift(parent.slice(dirname(parent).length + 1)); parent = dirname(parent); }
@@ -128,6 +174,7 @@ export function planLocalIgnore(root, { outputs = [], templateRoot } = {}) {
128
174
  const localTemplate = join(root, '.pbai4devs/templates/gitignore/local.ignore');
129
175
  const templateFile = checkedLocalPath(templateRoot ? join(templateRoot, '.pbai4devs/templates/gitignore/local.ignore') : localStat(localTemplate) ? localTemplate : fileURLToPath(new URL('../../templates/gitignore/local.ignore', import.meta.url)));
130
176
  const template = readFileSync(templateFile, 'utf8');
177
+ const artifacts = artifactPolicy(templateFile);
131
178
  if (template.split('{{OUTPUTS}}').length !== 2) throw new Error('local.ignore exige um unico {{OUTPUTS}}.');
132
179
  if (template.split('{{ROOTS}}').length > 2) throw new Error('local.ignore permite um unico {{ROOTS}}.');
133
180
  const localPolicy = join(templateRoot || root, '.pbai4devs/templates/clients/ADAPTERS.json');
@@ -152,16 +199,18 @@ export function planLocalIgnore(root, { outputs = [], templateRoot } = {}) {
152
199
  }
153
200
  const id = createHash('sha256').update(root).digest('hex').slice(0, 16);
154
201
  const first = `# BEGIN AGENTDEVKIT LOCAL ${id}`, last = `# END AGENTDEVKIT LOCAL ${id}`;
155
- const fixed = template.replace('{{ROOTS}}', roots.map(path => `/${path}/`).join('\n')).replace('{{OUTPUTS}}', paths.filter(path => !roots.some(root => path === root || path.startsWith(root + '/'))).map(path => `/${escapePattern(path)}`).join('\n'));
202
+ const fixed = template.replace('{{ROOTS}}', roots.map(path => `/${path}/`).join('\n')).replace('{{OUTPUTS}}', paths.filter(path => !roots.some(root => path === root || path.startsWith(root + '/'))).map(path => `/${escapePattern(path)}`).join('\n'))
203
+ + '\n# Resultados e arquivos temporarios\n' + artifacts.map(pattern => `/${pattern}`).join('\n') + '\n';
156
204
  const body = fixed.split(/\r?\n/).map(line => location?.prefix && line.startsWith('/') ? `/${escapePattern(location.prefix)}${line}` : line).join('\n');
157
205
  const target = location?.exclude ?? checkedLocalPath(join(root, '.gitignore'));
158
206
  const before = localRead(target), after = localBlock(before, first, last, body);
159
207
  const edits = before === after ? [] : [{ path: target, before, after }];
160
208
  const probes = [...paths, ...rootProbes(root, roots)];
209
+ const artifactPaths = artifactProbes(root, artifacts);
161
210
  const wanted = new Set(probes.map(path => location?.prefix ? `${location.prefix}/${path}` : path));
162
211
  if (location && !before?.includes(first) && !localRead(join(root, '.gitignore'))?.includes(first)) {
163
- const ignored = gitCommand(location.top, ['check-ignore', '--no-index', '--stdin', '-z'], [...wanted].join('\0') + '\0');
164
- if (!ignored.error && [0, 1].includes(ignored.status) && ignored.stdout.split('\0').filter(Boolean).length === wanted.size) edits.length = 0;
212
+ const ignored = ignoreMatches(location, [...probes, ...artifactPaths]);
213
+ if (ignored.paths.every(path => { const match = ignored.matches.get(path); return match && !match.pattern.startsWith('!') && localIgnoreSource(location, match.source); })) edits.length = 0;
165
214
  }
166
215
  if (location) {
167
216
  const fallback = checkedLocalPath(join(root, '.gitignore'));
@@ -169,7 +218,7 @@ export function planLocalIgnore(root, { outputs = [], templateRoot } = {}) {
169
218
  if (old !== null && old !== next) edits.push({ path: fallback, before: old, after: next });
170
219
  }
171
220
  const tracked = location ? gitCommand(location.top, ['ls-files', '-z']).stdout.split('\0').filter(path => wanted.has(path)).map(path => location.prefix ? path.slice(location.prefix.length + 1) : path) : [];
172
- return { root, status: location ? 'git' : 'fallback', location, paths, roots, edits, trackedOutputs: tracked, first, last };
221
+ return { root, status: location ? 'git' : 'fallback', location, paths, roots, artifactProbes: artifactPaths, edits, trackedOutputs: tracked, first, last };
173
222
  }
174
223
 
175
224
  export function checkLocalIgnore(plan, { replacedBlocks = [] } = {}) {
@@ -185,19 +234,16 @@ export function checkLocalIgnore(plan, { replacedBlocks = [] } = {}) {
185
234
  if (createHash('sha256').update(block).digest('hex') !== item.sha256) throw new Error('Bloco de ignore mudou antes da verificacao.');
186
235
  return { ...item, path };
187
236
  });
188
- if (plan.location && plan.paths.length) {
189
- const probes = [...plan.paths, ...rootProbes(plan.root, plan.roots || [])];
190
- const relativePaths = probes.map(path => plan.location.prefix ? `${plan.location.prefix}/${path}` : path);
191
- const result = gitCommand(plan.location.top, ['check-ignore', '--verbose', '--no-index', '--stdin', '-z'], relativePaths.join('\0') + '\0');
192
- if (result.error || ![0, 1].includes(result.status)) throw new Error(result.error?.message || result.stderr || 'Falha ao conferir exclusoes Git.');
193
- const values = result.stdout.split('\0'), matches = new Map();
194
- for (let index = 0; index + 3 < values.length; index += 4) matches.set(values[index + 3], { source: values[index], line: Number(values[index + 1]), pattern: values[index + 2] });
237
+ if (plan.location && (plan.paths.length || plan.artifactProbes?.length)) {
238
+ const probes = [...plan.paths, ...rootProbes(plan.root, plan.roots || []), ...(plan.artifactProbes || [])];
239
+ const { paths: relativePaths, matches } = ignoreMatches(plan.location, probes);
195
240
  for (let index = 0; index < relativePaths.length; index++) {
196
241
  const match = matches.get(relativePaths[index]);
197
242
  const negative = match?.pattern.startsWith('!');
198
- const humanOverride = negative && /(?:^|[\\/])\.gitignore$/.test(match.source);
243
+ const local = match && localIgnoreSource(plan.location, match.source);
244
+ const humanOverride = negative && local && /(?:^|[\\/])\.gitignore$/.test(match.source);
199
245
  const replaced = negative && replacements.some(item => item.path === canonicalExisting(resolve(plan.location.top, match.source)) && match.line >= item.firstLine && match.line <= item.lastLine);
200
- if (!replaced && ((!plan.edits.length && (!match || negative)) || humanOverride)) missing.push(probes[index]);
246
+ if (!replaced && ((!plan.edits.length && (!match || negative || !local)) || humanOverride)) missing.push(probes[index]);
201
247
  }
202
248
  }
203
249
  return { ok: plan.edits.length === 0 && missing.length === 0 && plan.trackedOutputs.length === 0, status: plan.status, missing, trackedOutputs: plan.trackedOutputs, changed: plan.edits.length };
@@ -212,6 +258,8 @@ export function assertLocalIgnoreUnchanged(plan) {
212
258
 
213
259
  export function applyLocalIgnore(plan) {
214
260
  assertLocalIgnoreUnchanged(plan);
261
+ const before = checkLocalIgnore(plan);
262
+ if (before.missing.length) throw new Error(`Regras humanas reabrem derivados locais: ${before.missing.join(', ')}`);
215
263
  const written = [];
216
264
  try {
217
265
  for (const edit of plan.edits) {
@@ -129,6 +129,72 @@ test('raízes dedicadas são locais, enquanto configurações de GitHub e VS Cod
129
129
  assert.ok(tracked.includes('.github/settings.json')); assert.ok(tracked.includes('.vscode/settings.json'));
130
130
  });
131
131
 
132
+ test('artefatos vêm da política compartilhada e não entram na lista de outputs', t => {
133
+ const root = fixture(t); git(root, ['init', '-q']);
134
+ put(root, '.agent-tests/human.txt', 'evidência humana'); git(root, ['add', '-f', '.agent-tests/human.txt']);
135
+ const plan = planLocalIgnore(root, { outputs: ['AGENTS.md'] });
136
+ assert.ok(plan.artifactProbes.some(path => path.startsWith('.agent-tests/')));
137
+ assert.ok(plan.artifactProbes.some(path => path.startsWith('.agentdevkit-ignore-probes/')));
138
+ assert.ok(plan.paths.every(path => !plan.artifactProbes.includes(path)));
139
+ assert.ok(!plan.trackedOutputs.includes('.agent-tests/human.txt'));
140
+ applyLocalIgnore(plan);
141
+ for (const path of ['.agent-tests/x', 'TMP/x', 'nested/TeMp/x', '.PlAyWrIgHt-McP/x', 'nested/playwright-report/x', 'TEST-RESULTS/x', 'nested/TestResults/x', 'BLOB-REPORT/x']) {
142
+ assert.equal(git(root, ['check-ignore', '--no-index', path]).trim(), path);
143
+ }
144
+ assert.equal(git(root, ['ls-files', '.agent-tests/human.txt']).trim(), '.agent-tests/human.txt');
145
+ assert.equal(readFileSync(join(root, '.agent-tests/human.txt'), 'utf8'), 'evidência humana');
146
+ assert.equal(checkLocalIgnore(planLocalIgnore(root, { outputs: ['AGENTS.md'] })).ok, true);
147
+ });
148
+
149
+ test('regras de artefatos são limitadas ao projeto dentro do monorepo', t => {
150
+ const root = fixture(t); git(root, ['init', '-q']);
151
+ const child = join(root, 'apps', 'my project'); mkdirSync(child, { recursive: true });
152
+ applyLocalIgnore(planLocalIgnore(child, { outputs: ['AGENTS.md'] }));
153
+ for (const path of ['apps/my project/.agent-tests/x', 'apps/my project/nested/.Playwright-MCP/x', 'apps/my project/sub/test-results/x']) {
154
+ assert.equal(git(root, ['check-ignore', '--no-index', path]).trim(), path);
155
+ }
156
+ for (const path of ['apps/other/.agent-tests/x', 'apps/other/tmp/x', '.agent-tests/x']) {
157
+ const result = spawnSync('git', ['-C', root, 'check-ignore', '--no-index', path], { encoding: 'utf8' });
158
+ assert.equal(result.status, 1, path + result.stderr);
159
+ }
160
+ });
161
+
162
+ test('ignore global não mascara a ausência das regras locais de artefatos', t => {
163
+ const root = fixture(t), outside = fixture(t); git(root, ['init', '-q']);
164
+ put(outside, 'global.ignore', '*\n');
165
+ git(root, ['config', 'core.excludesFile', join(outside, 'global.ignore')]);
166
+ const plan = planLocalIgnore(root, { outputs: ['AGENTS.md'] });
167
+ assert.equal(plan.edits.length, 1);
168
+ const missing = checkLocalIgnore({ ...plan, edits: [] });
169
+ assert.ok(missing.missing.some(path => path.startsWith('.agent-tests/')));
170
+ applyLocalIgnore(plan);
171
+ assert.equal(checkLocalIgnore(planLocalIgnore(root, { outputs: ['AGENTS.md'] })).ok, true);
172
+ });
173
+
174
+ test('negação humana de artefatos bloqueia aplicação sem modificar regras ou índice', t => {
175
+ const root = fixture(t); git(root, ['init', '-q']);
176
+ const human = '!/.agent-tests/**\n'; put(root, '.gitignore', human);
177
+ const exclude = readFileSync(join(root, '.git/info/exclude'));
178
+ const plan = planLocalIgnore(root, { outputs: ['AGENTS.md'] });
179
+ assert.ok(checkLocalIgnore(plan).missing.some(path => path.startsWith('.agent-tests/')));
180
+ assert.throws(() => applyLocalIgnore(plan), /Regras humanas/);
181
+ assert.deepEqual(readFileSync(join(root, '.git/info/exclude')), exclude);
182
+ assert.equal(readFileSync(join(root, '.gitignore'), 'utf8'), human);
183
+ });
184
+
185
+ test('probes reconhecem exceções humanas para nomes reais de Playwright', async t => {
186
+ for (const path of ['.playwright-mcp', 'playwright-report', 'playwright/.cache']) await t.test(path, subtest => {
187
+ const root = fixture(subtest); git(root, ['init', '-q']);
188
+ const prefixes = path.split('/').map((_part, index, parts) => '!/' + parts.slice(0, index + 1).join('/') + '/');
189
+ const human = [...prefixes, `!/${path}/**`, ''].join('\n'); put(root, '.gitignore', human);
190
+ const before = readFileSync(join(root, '.git/info/exclude'));
191
+ const plan = planLocalIgnore(root, { outputs: ['AGENTS.md'] });
192
+ assert.ok(checkLocalIgnore(plan).missing.some(probe => probe.startsWith(path + '/')));
193
+ assert.throws(() => applyLocalIgnore(plan), /Regras humanas/);
194
+ assert.deepEqual(readFileSync(join(root, '.git/info/exclude')), before);
195
+ });
196
+ });
197
+
132
198
  test('milhares de caminhos usam stdin e não ampliam metadata de área já ignorada', t => {
133
199
  const root = fixture(t); git(root, ['init', '-q']); put(root, '.gitignore', '/ignored/\n');
134
200
  const before = readFileSync(join(root, '.git/info/exclude'), 'utf8');
package/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ description: Alterações verificáveis por versão do AgentDevKit.
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## 0.0.7 — 2026-11-11
8
+
9
+ - Artefatos de testes e pastas temporárias protegidos em projetos existentes.
10
+ - Regras locais respeitam o escopo do projeto e as exceções do usuário.
11
+ - Teste opt-in em clones reais, com commits fixos e comparação de arquivos.
12
+ - Relato explícito de bloqueios por links simbólicos preexistentes.
13
+
7
14
  ## 0.0.6 — 2026-11-11
8
15
 
9
16
  - Metadados npm com autoria PathBit, palavras-chave e licença MIT.
package/README.en.md CHANGED
@@ -34,7 +34,7 @@ Then open the project in your coding agent and ask:
34
34
 
35
35
  See [installation](docs/guides/installation.md) for Windows, missing Node, previews
36
36
  and updates. Install and update through the [public npm package][packages]; the
37
- [v0.0.6 release][release] retains artifacts and checksums for verification.
37
+ [v0.0.7 release][release] retains artifacts and checksums for verification.
38
38
  No global installation is required.
39
39
  The CLI supports `pt`, `en` and `es`; it saves your selection per project.
40
40
 
@@ -78,7 +78,7 @@ forms. See [how to participate](docs/maintainers/community.md).
78
78
  agent to read `AGENTS.md`.
79
79
 
80
80
  [clients]: .pbai4devs/COMPATIBILIDADE.md
81
- [release]: https://github.com/pathbit/AgentDevKit/releases/tag/v0.0.6
81
+ [release]: https://github.com/pathbit/AgentDevKit/releases/tag/v0.0.7
82
82
  [npm-package]: https://www.npmjs.com/package/@pathbit/agentdevkit
83
83
  [npm-badge]: https://img.shields.io/npm/v/%40pathbit%2Fagentdevkit
84
84
  [license-badge]: https://img.shields.io/badge/license-MIT-blue
package/README.es.md CHANGED
@@ -35,7 +35,7 @@ Después, abre el proyecto en tu agente y pide:
35
35
  La [guía de instalación](docs/guides/installation.md) incluye Windows, Node ausente,
36
36
  simulación y actualización. Instala y actualiza mediante el
37
37
  [paquete npm público][packages];
38
- la [release v0.0.6][release] conserva artefactos y checksums para verificarlos.
38
+ la [release v0.0.7][release] conserva artefactos y checksums para verificarlos.
39
39
  No requiere instalación global.
40
40
  La CLI guarda el idioma `pt`, `en` o `es` por proyecto.
41
41
 
@@ -80,7 +80,7 @@ formularios. Consulta [cómo participar](docs/maintainers/community.md).
80
80
  al agente que lea `AGENTS.md`.
81
81
 
82
82
  [clients]: .pbai4devs/COMPATIBILIDADE.md
83
- [release]: https://github.com/pathbit/AgentDevKit/releases/tag/v0.0.6
83
+ [release]: https://github.com/pathbit/AgentDevKit/releases/tag/v0.0.7
84
84
  [npm-package]: https://www.npmjs.com/package/@pathbit/agentdevkit
85
85
  [npm-badge]: https://img.shields.io/npm/v/%40pathbit%2Fagentdevkit
86
86
  [license-badge]: https://img.shields.io/badge/license-MIT-blue
package/README.md CHANGED
@@ -32,7 +32,7 @@ Depois, abra o projeto no seu agente e peça:
32
32
 
33
33
  Windows, instalação sem Node, simulação e atualização estão no
34
34
  [guia de instalação](https://github.com/pathbit/AgentDevKit/blob/master/docs/guides/installation.md). A distribuição usa a
35
- versão publicada no [npm público][packages] e na [release v0.0.6][release],
35
+ versão publicada no [npm público][packages] e na [release v0.0.7][release],
36
36
  sem instalação global. Instalação e atualização usam o pacote do registro;
37
37
  os arquivos da release servem para conferir os artefatos publicados.
38
38
  O idioma da CLI pode ser `pt`, `en` ou `es`.
@@ -89,7 +89,7 @@ ao seu agente para ler `AGENTS.md`.
89
89
  [help]: https://github.com/pathbit/AgentDevKit/blob/master/docs/guides/troubleshooting.md
90
90
  [issues]: https://github.com/pathbit/AgentDevKit/issues/new/choose
91
91
  [packages]: https://github.com/pathbit/AgentDevKit/blob/master/docs/maintainers/packages.md
92
- [release]: https://github.com/pathbit/AgentDevKit/releases/tag/v0.0.6
92
+ [release]: https://github.com/pathbit/AgentDevKit/releases/tag/v0.0.7
93
93
  [npm-package]: https://www.npmjs.com/package/@pathbit/agentdevkit
94
94
  [npm-badge]: https://img.shields.io/npm/v/%40pathbit%2Fagentdevkit
95
95
  [license-badge]: https://img.shields.io/badge/license-MIT-blue
@@ -60,6 +60,11 @@ workflows, formulários de issues ou configurações humanas em `.github`.
60
60
  Sem Git, uma proteção no `.gitignore` da raiz evita incluir os derivados
61
61
  quando o repositório for iniciado.
62
62
 
63
+ O bloco local também protege `.agent-tests`, `tmp`, `temp`, `.playwright*`
64
+ e relatórios de testes, inclusive com letras maiúsculas e em subpastas.
65
+ O `.gitignore` existente e seus arquivos rastreados são preservados;
66
+ uma exceção humana que conflite com essa proteção é informada como conflito.
67
+
63
68
  Arquivos já rastreados exigem migração do índice: apenas saídas identificadas
64
69
  do kit podem deixar de ser rastreadas, preservando seus bytes no disco.
65
70
  Revise o plano e os conflitos em um projeto existente; use `--dry-run` antes
@@ -77,10 +82,14 @@ gerenciados alterados geram conflito; use `--force` somente após revisar o
77
82
  backup e o conteúdo que será substituído. Preserve os dados locais, as
78
83
  configurações próprias e os commits do projeto.
79
84
 
85
+ Links simbólicos em caminhos usados pela instalação podem bloquear a operação.
86
+ O kit informa o caminho e não converte nem remove o link automaticamente.
87
+ Use a simulação para identificar esse caso antes de aplicar.
88
+
80
89
  O [fluxo de trabalho](workflow.md) orienta a próxima etapa do projeto.
81
90
  Se houver erro, consulte [solução de problemas](troubleshooting.md).
82
91
 
83
- [Wiki](../README.md) · [Spec v0.0.6][spec]
92
+ [Wiki](../README.md) · [Spec v0.0.7][spec]
84
93
 
85
94
  [bootstrap]: ../../.pbai4devs/scripts/preparar-ferramentas/BOOTSTRAP.md
86
- [spec]: ../specs/v0.0.6/SPEC.md
95
+ [spec]: ../specs/v0.0.7/SPEC.md
@@ -64,7 +64,7 @@ existir; a primeira publicação pode usar o secret `NPMJS_TOKEN`.
64
64
  Para publicar somente o pacote de uma tag que já tem artefato aprovado:
65
65
 
66
66
  ```console
67
- gh workflow run release.yml --ref master -f tag=v0.0.6 -F package_only=true
67
+ gh workflow run release.yml --ref master -f tag=v0.0.7 -F package_only=true
68
68
  ```
69
69
 
70
70
  Se o artefato expirou, reexecute o CI original da tag antes da publicação.
@@ -17,6 +17,7 @@ status: vigente
17
17
  | Estrutura e exemplos v0.0.4 | CLI, distribuição e gerador | [Spec][layout]. |
18
18
  | Instalação pelo registro v0.0.5 | Pacote publicado | [Spec][registry]. |
19
19
  | Apresentação e licença v0.0.6 | Distribuição e atualização | [Spec][public]. |
20
+ | Compatibilidade real v0.0.7 | Testes em clones existentes | [Spec][oss]. |
20
21
 
21
22
  A primeira entrega segue a [spec v0.0.1](../specs/v0.0.1/SPEC.md), disponível
22
23
  na [release v0.0.1][release]. Os detalhes de mudanças estão no
@@ -36,3 +37,4 @@ comportamento existente, sem alterar a versão de uma release já publicada.
36
37
  [layout]: ../specs/v0.0.4/SPEC.md
37
38
  [registry]: ../specs/v0.0.5/SPEC.md
38
39
  [public]: ../specs/v0.0.6/SPEC.md
40
+ [oss]: ../specs/v0.0.7/SPEC.md
@@ -11,6 +11,7 @@ description: Incrementos verificáveis do AgentDevKit.
11
11
  - [v0.0.4](v0.0.4/SPEC.md): estrutura padrão e exemplos na raiz.
12
12
  - [v0.0.5](v0.0.5/SPEC.md): instalação pelo registro em todos os fluxos.
13
13
  - [v0.0.6](v0.0.6/SPEC.md): apresentação pública, licença e atualização segura.
14
+ - [v0.0.7](v0.0.7/SPEC.md): projetos reais e proteção local de artefatos.
14
15
 
15
16
  Cada incremento vincula requisitos, critérios, testes e evidências locais.
16
17
 
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: Compatibilidade do pacote com projetos open source existentes.
3
+ ---
4
+
5
+ # Versão 0.0.7
6
+
7
+ A [spec](SPEC.md) define testes em clones reais e a correção das exclusões
8
+ locais de artefatos, preservando os arquivos e as decisões dos projetos.
9
+
10
+ [Specs](../README.md)
@@ -0,0 +1,59 @@
1
+ ---
2
+ description: Testes em projetos reais e proteção de artefatos locais.
3
+ status: aprovado
4
+ version: 0.0.7
5
+ ---
6
+
7
+ # Compatibilidade com projetos existentes
8
+
9
+ ## Objetivo e autorização
10
+
11
+ Atender ao pedido de testar o pacote publicado em projetos open source com
12
+ conteúdo real, usando clones em `tmp/` ignorado. Corrigir a falta de proteção
13
+ de artefatos revelada em projetos que não tinham as regras do AgentDevKit.
14
+
15
+ O trabalho usa o [PRD](../../product/prd.md),
16
+ o [design](../../product/design.md) e a
17
+ [distribuição pública](../v0.0.6/SPEC.md). Não altera as aplicações clonadas.
18
+
19
+ ## Contrato
20
+
21
+ - Clonar commits fixos de Express, Zod e Chi; preservar os projetos originais.
22
+ - Comparar bytes, tipos, permissões, links, HEAD e alterações staged.
23
+ - Verificar instalação, atualização, repetição, skill própria e conflitos.
24
+ - Proteger artefatos no ignore local sem reescrever o `.gitignore` do usuário
25
+ nem desindexar arquivos humanos. Respeitar projetos irmãos e exceções.
26
+ - Manter as recusas de links simbólicos. Um bloqueio seguro não comprova
27
+ instalação bem-sucedida; relatá-lo e verificar ausência de alterações.
28
+ - Versionar o teste; guardar clones, logs e resultados somente em `tmp/`.
29
+ - Publicar correções como nova versão estável; repetir a prova pública.
30
+
31
+ ## Critérios de aceite
32
+
33
+ | ID | Resultado observável |
34
+ | --- | --- |
35
+ | AC-001 | Matriz real registra resultado e preservação por projeto. |
36
+ | AC-002 | Artefatos são ignorados sem alterar fontes ou projetos irmãos. |
37
+ | AC-003 | Regressões e revisão independente aprovam a correção. |
38
+ | AC-004 | Pacote estável publicado repete os resultados e atualiza o router. |
39
+
40
+ ## Verificação
41
+
42
+ - **AC-001:** executar o runner contra o npm, incluindo caso staged e bloqueios;
43
+ registrar commits, versão e hashes. Não confundir com testes das aplicações.
44
+ - **AC-002:** testar Git, instalação sem Git, projeto aninhado, caixa mista,
45
+ exceções humanas e artefatos já rastreados. Não forçar sobrescritas.
46
+ - **AC-003:** executar testes do pacote, infraestrutura, lint e distribuição.
47
+ Comparar testes nativos do Express antes e depois, sem modificar suas fontes.
48
+ - **AC-004:** conferir release, `latest`, checksum e instalação anônima; repetir
49
+ matriz com o pacote publicado e atualizar o router com backup e diagnóstico.
50
+
51
+ Evidências dos clones ficam em `tmp/oss-compatibility/`; o relatório de revisão
52
+ em `.agent-tests/oss-compatibility/` referencia cópias dessas provas.
53
+ Zod e Chi não terão testes nativos sem os runtimes/gerenciadores exigidos.
54
+ Não concluir compatibilidade universal a partir desta matriz.
55
+
56
+ ## Documentação afetada
57
+
58
+ Atualizar instalação, testes, changelog, índices e roadmap. Documentar a
59
+ proteção de artefatos locais e os limites de configurações preexistentes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pathbit/agentdevkit",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Shared skills, specifications and workflows for AI coding agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -50,7 +50,8 @@
50
50
  "pack:release": "node scripts/release/assets.mjs",
51
51
  "ci:full": "node scripts/release/pipeline.mjs full",
52
52
  "ci:portable": "node scripts/release/pipeline.mjs portable",
53
- "ci:smoke": "node scripts/release/pipeline.mjs smoke"
53
+ "ci:smoke": "node scripts/release/pipeline.mjs smoke",
54
+ "test:oss": "node tests/oss-compatibility.mjs"
54
55
  },
55
56
  "author": {
56
57
  "name": "PathBit",