@fontdata/ai-harness 3.1.1 → 3.1.2

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,8 +1,8 @@
1
1
  {
2
2
  "name": "fontdata",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "mcpServers": {
5
- "banco_dados": { "command": "npx", "args": ["-y", "@fontdata/ai-harness@3.1.1", "banco-dados-mcp"] }
5
+ "banco_dados": { "command": "npx", "args": ["-y", "@fontdata/ai-harness@3.1.2", "banco-dados-mcp"] }
6
6
  },
7
7
  "description": "Harness de engenharia com IA da Fontdata para Claude Code",
8
8
  "author": { "name": "Fontdata" },
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { existsSync, readFileSync } from 'node:fs';
3
3
  import { dirname, join, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { allCommands, loadCatalog } from './catalog.js';
6
+ import { acharRaiz } from './raiz.js';
6
7
  import { runCommand, runnableIds, suggestIds } from './run.js';
7
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
9
  /** Comandos renomeados depois da 2.7.0: o nome antigo aponta o novo em vez de cair em "Comando desconhecido". */
@@ -127,7 +128,7 @@ async function main() {
127
128
  }
128
129
  if (cmd === 'doctor') {
129
130
  const { formatFindings, runDoctor } = await import('./doctor/checks.js');
130
- const root = resolve(process.cwd(), argv[1] ?? '.');
131
+ const root = argv[1] === undefined ? acharRaiz() : resolve(process.cwd(), argv[1]);
131
132
  if (!existsSync(root))
132
133
  throw new Error(`Pasta não encontrada: ${root}`);
133
134
  const findings = runDoctor(root);
@@ -6,6 +6,7 @@ import { suggestFlag } from '../install/flags.js';
6
6
  import { hashContent } from '../install/lock.js';
7
7
  import { executePlan, packageInfo } from '../install/plan.js';
8
8
  import { mergeSettings } from '../install/settings.js';
9
+ import { acharRaiz } from '../raiz.js';
9
10
  import { COMMENTS_BASELINE_PATH, COMMENTS_HOOK_PATH, COMMENTS_RULE_PATH, commentsHooksConfig, ensureCommentsBaseline } from './instalar.js';
10
11
  export { COMMENTS_HOOK_PATH } from './instalar.js';
11
12
  const FLAGS = ['--yes', '-y', '--sim'];
@@ -27,7 +28,7 @@ export function runCommentsCommand(argv) {
27
28
  throw new Error(`Flag desconhecida: ${token}.${suggestion ? ` Você quis dizer ${suggestion}?` : ''}`);
28
29
  }
29
30
  }
30
- const root = resolve(process.cwd(), path ?? '.');
31
+ const root = path === undefined ? acharRaiz() : resolve(process.cwd(), path);
31
32
  if (!existsSync(root))
32
33
  throw new Error(`Pasta não encontrada: ${root}`);
33
34
  const rule = readFileSync(join(templatesDir, 'rules', 'comentarios.md'));
@@ -3,6 +3,7 @@ import { EOL } from 'node:os';
3
3
  import { dirname, join, resolve } from 'node:path';
4
4
  import { ARTIFACT_TYPES, readArtifact, WORKS_DIR } from '../contratos/artefatos.js';
5
5
  import { suggestFlag } from '../install/flags.js';
6
+ import { acharRaiz } from '../raiz.js';
6
7
  export const INDEX_PATH = join('.ai-harness', 'memoria', 'indice.json');
7
8
  export const INDEX_VERSION = 1;
8
9
  const BACKSLASH = String.fromCharCode(92);
@@ -159,7 +160,7 @@ export function runMemoryCommand(argv) {
159
160
  else
160
161
  bugId = value;
161
162
  }
162
- const root = resolve(process.cwd(), path ?? '.');
163
+ const root = path === undefined ? acharRaiz() : resolve(process.cwd(), path);
163
164
  if (!existsSync(root))
164
165
  throw new Error(`Pasta não encontrada: ${root}`);
165
166
  const index = buildIndex(root);
package/dist/raiz.js ADDED
@@ -0,0 +1,21 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ /** Sobe até o diretório mais próximo que tenha o marcador, ou devolve undefined. */
4
+ function subirAte(inicio, marcador) {
5
+ for (let pasta = inicio;; pasta = dirname(pasta)) {
6
+ if (existsSync(join(pasta, marcador)))
7
+ return pasta;
8
+ if (dirname(pasta) === pasta)
9
+ return undefined;
10
+ }
11
+ }
12
+ /**
13
+ * Raiz do projeto para os comandos rodados sem caminho: o Bash dos agentes herda o `cd` de comandos anteriores, então
14
+ * o diretório atual pode ser uma subpasta. Vale o `.ai-harness/` mais próximo, depois o `.git` (arquivo em submódulo e
15
+ * worktree); sem nenhum, o próprio diretório. `CLAUDE_PROJECT_DIR` fica de fora: não é garantida no Bash, e a suíte
16
+ * roda dentro do Claude Code.
17
+ */
18
+ export function acharRaiz(inicio = process.cwd()) {
19
+ const pasta = resolve(inicio);
20
+ return subirAte(pasta, '.ai-harness') ?? subirAte(pasta, '.git') ?? pasta;
21
+ }
@@ -2,6 +2,7 @@ import { join } from 'node:path';
2
2
  import { pathToFileURL } from 'node:url';
3
3
  import { templatesDir } from '../catalog.js';
4
4
  import { suggestFlag } from '../install/flags.js';
5
+ import { acharRaiz } from '../raiz.js';
5
6
  /** O CLI grava pela mesma biblioteca dos hooks, para as duas formas produzirem o mesmo formato. */
6
7
  export async function loadRastroLib() {
7
8
  return (await import(pathToFileURL(join(templatesDir, 'hooks', 'lib', 'rastro.mjs')).href));
@@ -41,6 +42,6 @@ export async function runEventCommand(argv) {
41
42
  }
42
43
  }
43
44
  }
44
- (await loadRastroLib()).recordEvent(process.cwd(), fields);
45
+ (await loadRastroLib()).recordEvent(acharRaiz(), fields);
45
46
  return 0;
46
47
  }
@@ -3,6 +3,7 @@ import { join } from 'node:path';
3
3
  import { setTimeout as sleep } from 'node:timers/promises';
4
4
  import { readArtifact } from '../contratos/artefatos.js';
5
5
  import { suggestFlag } from '../install/flags.js';
6
+ import { acharRaiz } from '../raiz.js';
6
7
  import { loadRastroLib } from '../rastro/command.js';
7
8
  const FINISHED = new Set(['concluido', 'cancelado']);
8
9
  const normalize = (path) => path.trim().replace(/^\.\//, '').replace(/\/+$/, '');
@@ -84,7 +85,7 @@ export async function waitForFreeFiles(root, workId, options) {
84
85
  }
85
86
  const FLAGS = ['--aguardar', '--intervalo'];
86
87
  /** `ai-harness conflitos <id> [--aguardar] [--intervalo <segundos>]` — sai com 1 quando há conflito sem --aguardar. */
87
- export async function runConflictsCommand(argv, root = process.cwd()) {
88
+ export async function runConflictsCommand(argv, root = acharRaiz()) {
88
89
  const [workId, ...rest] = argv;
89
90
  if (!workId || workId.startsWith('-')) {
90
91
  throw new Error('Informe o id do trabalho. Ex.: npx @fontdata/ai-harness conflitos 2026-09-18-login --aguardar');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fontdata/ai-harness",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "description": "Harness de engenharia com IA da Fontdata para Claude Code: roda os slash commands direto na pasta do projeto via npx, sem instalar nada — ou instala-os em .claude/commands.",
5
5
  "type": "module",
6
6
  "bin": {