navori 0.2.3 → 0.2.6

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 CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { defineCommand as defineCommand16, runMain } from "citty";
5
- import { readFileSync as readFileSync21 } from "fs";
6
- import { dirname as dirname9, resolve as resolve24 } from "path";
5
+ import { readFileSync as readFileSync22 } from "fs";
6
+ import { dirname as dirname10, resolve as resolve24 } from "path";
7
7
  import { fileURLToPath as fileURLToPath2 } from "url";
8
8
 
9
9
  // src/commands/init.ts
10
10
  import { defineCommand as defineCommand2 } from "citty";
11
11
  import * as p2 from "@clack/prompts";
12
- import { resolve as resolve11, join as join11, dirname as dirname6, relative as relative3 } from "path";
13
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, chmodSync as chmodSync2 } from "fs";
12
+ import { resolve as resolve11, join as join12, dirname as dirname7, relative as relative3 } from "path";
13
+ import { existsSync as existsSync16, mkdirSync as mkdirSync6, chmodSync as chmodSync2 } from "fs";
14
14
  import { spawnSync as spawnSync2 } from "child_process";
15
15
 
16
16
  // src/lib/config.ts
@@ -1374,7 +1374,7 @@ function writeWorkspace(workspace) {
1374
1374
  // src/commands/render.ts
1375
1375
  import { defineCommand } from "citty";
1376
1376
  import * as p from "@clack/prompts";
1377
- import { existsSync as existsSync12 } from "fs";
1377
+ import { existsSync as existsSync13 } from "fs";
1378
1378
  import { resolve as resolve9 } from "path";
1379
1379
 
1380
1380
  // src/engines/claude/index.ts
@@ -1653,6 +1653,51 @@ function extractManagedContent(existing, id, commentStyle = "html") {
1653
1653
  const match = findMarker(existing, id, syntax);
1654
1654
  return match ? match.content : null;
1655
1655
  }
1656
+ function locateManagedBlocks(content, syntax) {
1657
+ const openRegex = new RegExp(
1658
+ `${escapeRegex(syntax.openPrefix)}\\s+id="([^"]+)"${syntax.attrsAndTerminatorPattern}`,
1659
+ "g"
1660
+ );
1661
+ const blocks = [];
1662
+ for (const m of content.matchAll(openRegex)) {
1663
+ if (m.index === void 0) continue;
1664
+ const id = m[1];
1665
+ const close = closeMarker(id, syntax);
1666
+ const closeStart = content.indexOf(close, m.index + m[0].length);
1667
+ if (closeStart < 0) continue;
1668
+ blocks.push({ id, openStart: m.index, closeEnd: closeStart + close.length });
1669
+ }
1670
+ return blocks;
1671
+ }
1672
+ function reorderManagedBlocks(content, canonicalOrder, commentStyle = "html") {
1673
+ const syntax = syntaxFor(commentStyle);
1674
+ const blocks = locateManagedBlocks(content, syntax);
1675
+ if (blocks.length < 2) {
1676
+ return { output: content, reordered: false, blockedByInterleaving: false };
1677
+ }
1678
+ const rank = /* @__PURE__ */ new Map();
1679
+ canonicalOrder.forEach((id, i) => {
1680
+ if (!rank.has(id)) rank.set(id, i);
1681
+ });
1682
+ const unknownBase = canonicalOrder.length;
1683
+ const desired = blocks.map((b, i) => ({ b, i, key: rank.has(b.id) ? rank.get(b.id) : unknownBase + i })).sort((a, z8) => a.key - z8.key || a.i - z8.i).map((x) => x.b);
1684
+ if (desired.every((b, i) => b === blocks[i])) {
1685
+ return { output: content, reordered: false, blockedByInterleaving: false };
1686
+ }
1687
+ for (let i = 0; i < blocks.length - 1; i++) {
1688
+ const gap = content.slice(blocks[i].closeEnd, blocks[i + 1].openStart);
1689
+ if (gap.trim() !== "") {
1690
+ return { output: content, reordered: false, blockedByInterleaving: true };
1691
+ }
1692
+ }
1693
+ const first = blocks[0];
1694
+ const last = blocks[blocks.length - 1];
1695
+ const preamble = content.slice(0, first.openStart);
1696
+ const suffix = content.slice(last.closeEnd);
1697
+ const body = desired.map((b) => content.slice(b.openStart, b.closeEnd)).join("\n\n");
1698
+ const pre = preamble === "" ? "" : preamble.replace(/\n*$/, "\n\n");
1699
+ return { output: pre + body + suffix, reordered: true, blockedByInterleaving: false };
1700
+ }
1656
1701
  function resolveCondition(config, path) {
1657
1702
  const segments = path.split(".");
1658
1703
  let cursor = config;
@@ -1677,6 +1722,7 @@ function placeholderFallback(path) {
1677
1722
  // src/lib/render-plan.ts
1678
1723
  var CORE_SOURCE_ID = "@navori/core";
1679
1724
  var CORE_MANAGED_ASSETS = [
1725
+ { id: "orquestacion", relPath: "core-assets/managed/orquestacion.md", availableLanguages: ["es"] },
1680
1726
  { id: "idioma-rol", relPath: "core-assets/managed/idioma-rol.md", availableLanguages: ["es"] },
1681
1727
  { id: "formato-respuesta", relPath: "core-assets/managed/formato-respuesta.md", availableLanguages: ["es"] },
1682
1728
  { id: "tipado-fuerte", relPath: "core-assets/managed/tipado-fuerte.md", availableLanguages: ["es"], condition: "project.typedLanguage" },
@@ -1884,6 +1930,16 @@ function computeRenderPlan(existing, inputConfig, repoRoot, options = {}) {
1884
1930
  updatesAvailable
1885
1931
  };
1886
1932
  }
1933
+ var CLAUDE_COMPUTED_BLOCK_IDS = [
1934
+ "skills-index",
1935
+ "agentes-disponibles",
1936
+ "contexto-proyecto"
1937
+ ];
1938
+ function canonicalManagedOrder(config, repoRoot) {
1939
+ const plan = computeRenderPlan("", config, repoRoot);
1940
+ const ids = plan.entries.filter((entry) => entry.newContent !== null).map((entry) => entry.asset.id);
1941
+ return [...ids, ...CLAUDE_COMPUTED_BLOCK_IDS];
1942
+ }
1887
1943
 
1888
1944
  // src/engines/claude/settings-detection.ts
1889
1945
  var NAVORI_OWNERSHIP_MARKER = "$navori";
@@ -2339,6 +2395,34 @@ function buildSkillsIndexBody(config, localSkills, repoRoot) {
2339
2395
  ""
2340
2396
  ].join("\n");
2341
2397
  }
2398
+ var AGENTS_INDEX_ID = "agentes-disponibles";
2399
+ var AGENT_WHEN = {
2400
+ implementer: "Escribe c\xF3digo y tests de UNA tarea acotada con scope claro.",
2401
+ reviewer: "Valida un diff contra spec y calidad antes de cerrar (APPROVED / CHANGES_REQUESTED).",
2402
+ researcher: "Responde una pregunta concreta del repo (\xBFpasa Y? \xBFqu\xE9 consume X?) con evidencia citada.",
2403
+ explorer: "Mapea un \xE1rea o m\xF3dulo amplio: estructura, entry points, dependencias.",
2404
+ "ticket-audit": "Analiza a fondo un ticket complejo (bug cr\xEDtico, migraci\xF3n, feature multi-capa) antes de descomponer.",
2405
+ "commit-pr-pilot": "Redacta commits Conventional y abre el PR tras la aprobaci\xF3n del reviewer."
2406
+ };
2407
+ function buildAgentsIndexBody(config) {
2408
+ const rows = [];
2409
+ for (const agent of CORE_AGENTS) {
2410
+ if (agent.id === "leader") continue;
2411
+ if (!isAgentEnabled(config, agent.harnessKey)) continue;
2412
+ const when = AGENT_WHEN[agent.id];
2413
+ if (!when) continue;
2414
+ rows.push(`- \`${agent.id}\` \u2014 ${when}`);
2415
+ }
2416
+ if (rows.length === 0) return null;
2417
+ return [
2418
+ "## Agentes disponibles",
2419
+ "",
2420
+ 'Subagentes que puedes lanzar v\xEDa la tool `Agent` (t\xFA eres el orquestador; ver "## Rol: orquestador"). Investigaci\xF3n y review son read-only \u2192 paralel\xEDzalos sin miedo.',
2421
+ "",
2422
+ ...rows,
2423
+ ""
2424
+ ].join("\n");
2425
+ }
2342
2426
  var CONTEXTO_PROYECTO_ID = "contexto-proyecto";
2343
2427
  function buildContextoProyectoBody(config) {
2344
2428
  const proj = config.project ?? {};
@@ -2422,6 +2506,26 @@ function renderClaudeEngine(cwd, inputConfig, options = {}) {
2422
2506
  } else {
2423
2507
  claudeMdContent = removeManagedSection(claudeMdContent, SKILLS_INDEX_ID);
2424
2508
  }
2509
+ const agentsIndexBody = buildAgentsIndexBody(config);
2510
+ if (agentsIndexBody !== null) {
2511
+ const result = injectManagedSection(
2512
+ claudeMdContent,
2513
+ AGENTS_INDEX_ID,
2514
+ agentsIndexBody,
2515
+ CORE_META,
2516
+ "html",
2517
+ options.forceIds?.has(AGENTS_INDEX_ID) ?? false
2518
+ );
2519
+ claudeMdContent = result.output;
2520
+ claudeMdPlan.entries.push({
2521
+ asset: { id: AGENTS_INDEX_ID, relPath: "(computed)" },
2522
+ source: "core",
2523
+ status: result.status,
2524
+ newContent: null
2525
+ });
2526
+ } else {
2527
+ claudeMdContent = removeManagedSection(claudeMdContent, AGENTS_INDEX_ID);
2528
+ }
2425
2529
  const contextoBody = buildContextoProyectoBody(config);
2426
2530
  if (contextoBody !== null) {
2427
2531
  const result = injectManagedSection(
@@ -2442,6 +2546,13 @@ function renderClaudeEngine(cwd, inputConfig, options = {}) {
2442
2546
  } else {
2443
2547
  claudeMdContent = removeManagedSection(claudeMdContent, CONTEXTO_PROYECTO_ID);
2444
2548
  }
2549
+ const reorder = reorderManagedBlocks(claudeMdContent, canonicalManagedOrder(config, repoRoot));
2550
+ claudeMdContent = reorder.output;
2551
+ if (reorder.blockedByInterleaving) {
2552
+ warnings.push(
2553
+ "CLAUDE.md: los bloques managed est\xE1n fuera del orden can\xF3nico, pero hay texto tuyo intercalado entre bloques, as\xED que no los reorden\xE9. Mueve ese texto arriba del primer bloque managed o abajo del \xFAltimo para que navori pueda ordenarlos."
2554
+ );
2555
+ }
2445
2556
  if (claudeMdContent !== claudeMdExisting) {
2446
2557
  pending.push({
2447
2558
  path: claudeMdPath,
@@ -2846,6 +2957,96 @@ function planPluginScript(cwd, script, config) {
2846
2957
  };
2847
2958
  }
2848
2959
 
2960
+ // src/engines/agents-md/index.ts
2961
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync12 } from "fs";
2962
+ import { basename as basename4, dirname as dirname6, join as join10 } from "path";
2963
+ var MANAGED_ID = "navori-agents";
2964
+ var CORE_META2 = { source: "@navori/core", version: readBundledCoreVersion() };
2965
+ var CORE_SKILLS2 = ["verify-before-done", "loop-back-debug", "review-diff"];
2966
+ var HEADER = "# AGENTS.md\n";
2967
+ var USER_SECTION = "\n<!-- navori:user-section -->\n## Reglas del repo (tuyas)\n\n<!-- Agrega ac\xE1 lo espec\xEDfico de tu repo; navori no toca esta secci\xF3n. -->\n";
2968
+ function buildSkillsSection(config, repoRoot) {
2969
+ const rows = [];
2970
+ const listed = /* @__PURE__ */ new Set();
2971
+ for (const id of CORE_SKILLS2) {
2972
+ rows.push(`- \`${id}\` \u2014 navori`);
2973
+ listed.add(id);
2974
+ }
2975
+ if (config.preset && config.preset !== "custom") {
2976
+ try {
2977
+ const loaded = loadPreset(config.preset, repoRoot);
2978
+ for (const e of loaded?.def.extras.skills ?? []) {
2979
+ if (e.condition) continue;
2980
+ const name = basename4(e.destRelPath).replace(/\.md$/, "");
2981
+ if (listed.has(name)) continue;
2982
+ rows.push(`- \`${name}\` \u2014 preset (\`${config.preset}\`)`);
2983
+ listed.add(name);
2984
+ }
2985
+ } catch {
2986
+ }
2987
+ }
2988
+ for (const id of config.project?.libraries ?? []) {
2989
+ if (listed.has(id) || !librarySkillById(id)) continue;
2990
+ rows.push(`- \`${id}\` \u2014 library (detected)`);
2991
+ listed.add(id);
2992
+ }
2993
+ if (rows.length === 0) return null;
2994
+ return ["## Skills disponibles", "", ...rows, ""].join("\n");
2995
+ }
2996
+ function buildWorkflowSection() {
2997
+ return [
2998
+ "## Flujo de trabajo",
2999
+ "",
3000
+ "- Para tareas no triviales: an\xE1lisis \u2192 plan \u2192 implementaci\xF3n. De una en una.",
3001
+ "- Antes de codear: \xBFes lo m\xE1s simple? \xBFlegible en 6 meses? \xBFmantiene el patr\xF3n existente?",
3002
+ "- Busca con herramientas read-only (no leas el repo entero); cita `archivo:l\xEDnea`.",
3003
+ "- Cierra con el quality gate del proyecto en verde antes de dar por terminado.",
3004
+ ""
3005
+ ].join("\n");
3006
+ }
3007
+ function buildManagedBody(config, repoRoot) {
3008
+ const plan = computeRenderPlan("", config, repoRoot);
3009
+ const ruleBlocks = plan.entries.filter(
3010
+ (e) => e.newContent != null && e.status !== "removed-condition-false" && e.asset.id !== "orquestacion" && (e.source === "core" || e.source === config.preset)
3011
+ ).map((e) => e.newContent.trim());
3012
+ const skills = buildSkillsSection(config, repoRoot);
3013
+ const sections = [
3014
+ "> Contexto del proyecto generado por navori. Lo leen Cursor, Codex, Gemini y Copilot.",
3015
+ ...ruleBlocks,
3016
+ ...skills ? [skills] : [],
3017
+ buildWorkflowSection()
3018
+ ];
3019
+ return sections.join("\n\n").trim() + "\n";
3020
+ }
3021
+ function renderAgentsMdEngine(cwd, inputConfig, options = {}) {
3022
+ const config = effectiveConfig(inputConfig);
3023
+ const repoRoot = options.repoRoot ?? cwd;
3024
+ const agentsMdPath = join10(cwd, "AGENTS.md");
3025
+ const firstRender = !existsSync12(agentsMdPath);
3026
+ const existing = firstRender ? HEADER : readFileSync12(agentsMdPath, "utf-8");
3027
+ const body = buildManagedBody(config, repoRoot);
3028
+ const result = injectManagedSection(existing, MANAGED_ID, body, CORE_META2, "html");
3029
+ const output = firstRender ? result.output + USER_SECTION : result.output;
3030
+ const written = [];
3031
+ const skipped = [];
3032
+ let backupPath = null;
3033
+ if (result.status === "user-modified-skipped") {
3034
+ skipped.push({ path: "AGENTS.md", reason: "managed block edited by hand" });
3035
+ } else if (result.status === "unchanged") {
3036
+ } else {
3037
+ written.push({ path: "AGENTS.md", status: result.status });
3038
+ if (!options.dryRun) {
3039
+ if (!firstRender) {
3040
+ const handle = createBackup(cwd, ["AGENTS.md"]);
3041
+ if (handle.files.length > 0) backupPath = handle.path;
3042
+ }
3043
+ mkdirSync5(dirname6(agentsMdPath), { recursive: true });
3044
+ writeFileAtomic(agentsMdPath, output);
3045
+ }
3046
+ }
3047
+ return { written, skipped, warnings: [], backupPath };
3048
+ }
3049
+
2849
3050
  // src/lib/style.ts
2850
3051
  import pc from "picocolors";
2851
3052
  var color = pc;
@@ -2923,6 +3124,25 @@ function effectiveConfigForWorkspace(root, workspace) {
2923
3124
  }
2924
3125
 
2925
3126
  // src/commands/render.ts
3127
+ function renderNonClaudeEngines(cwd, config, engines, dryRun) {
3128
+ const out = [];
3129
+ for (const eng of engines) {
3130
+ if (eng === "claude") continue;
3131
+ if (eng === "agents-md") {
3132
+ const r = renderAgentsMdEngine(cwd, config, { dryRun, repoRoot: cwd });
3133
+ out.push({ engine: eng, ...r });
3134
+ } else {
3135
+ out.push({
3136
+ engine: eng,
3137
+ written: [],
3138
+ skipped: [],
3139
+ warnings: [`El engine '${eng}' todav\xEDa no tiene adapter en navori; se omiti\xF3.`],
3140
+ backupPath: null
3141
+ });
3142
+ }
3143
+ }
3144
+ return out;
3145
+ }
2926
3146
  function runRender(cwd, dryRunOrOptions = false, force = false) {
2927
3147
  const opts = typeof dryRunOrOptions === "boolean" ? { dryRun: dryRunOrOptions, force } : dryRunOrOptions;
2928
3148
  const dryRun = Boolean(opts.dryRun);
@@ -2930,7 +3150,7 @@ function runRender(cwd, dryRunOrOptions = false, force = false) {
2930
3150
  const workspaceFilter = opts.workspaceFilter ?? null;
2931
3151
  const configPath = `${cwd}/navori.config.json`;
2932
3152
  const claudeMdPath = `${cwd}/CLAUDE.md`;
2933
- if (!existsSync12(configPath)) {
3153
+ if (!existsSync13(configPath)) {
2934
3154
  return {
2935
3155
  ok: false,
2936
3156
  reason: `No navori.config.json at ${configPath}`,
@@ -3006,38 +3226,44 @@ function runRender(cwd, dryRunOrOptions = false, force = false) {
3006
3226
  ]
3007
3227
  };
3008
3228
  }
3009
- const engineResult = renderClaudeEngine(cwd, config, { dryRun, force: forceFlag });
3229
+ const engines = config.engines ?? ["claude"];
3230
+ const renderClaude = engines.includes("claude");
3231
+ const engineResult = renderClaude ? renderClaudeEngine(cwd, config, { dryRun, force: forceFlag }) : void 0;
3010
3232
  const workspaces = [];
3011
- for (const ws of config.monorepo?.workspaces ?? []) {
3012
- const wsCwd = resolve9(cwd, ws.path);
3013
- const wsConfig = effectiveConfigForWorkspace(config, ws);
3014
- const wsResult = renderClaudeEngine(wsCwd, wsConfig, {
3015
- dryRun,
3016
- force: forceFlag,
3017
- repoRoot: cwd
3018
- });
3019
- workspaces.push({
3020
- workspacePath: ws.path,
3021
- workspaceName: ws.name,
3022
- filePath: `${wsCwd}/CLAUDE.md`,
3023
- entries: wsResult.claudeMdEntries,
3024
- written: wsResult.written.length > 0,
3025
- languageFallbacks: wsResult.languageFallbacks,
3026
- updatesAvailable: wsResult.updatesAvailable,
3027
- backupPath: wsResult.backupPath,
3028
- engineResult: wsResult
3029
- });
3233
+ if (renderClaude) {
3234
+ for (const ws of config.monorepo?.workspaces ?? []) {
3235
+ const wsCwd = resolve9(cwd, ws.path);
3236
+ const wsConfig = effectiveConfigForWorkspace(config, ws);
3237
+ const wsResult = renderClaudeEngine(wsCwd, wsConfig, {
3238
+ dryRun,
3239
+ force: forceFlag,
3240
+ repoRoot: cwd
3241
+ });
3242
+ workspaces.push({
3243
+ workspacePath: ws.path,
3244
+ workspaceName: ws.name,
3245
+ filePath: `${wsCwd}/CLAUDE.md`,
3246
+ entries: wsResult.claudeMdEntries,
3247
+ written: wsResult.written.length > 0,
3248
+ languageFallbacks: wsResult.languageFallbacks,
3249
+ updatesAvailable: wsResult.updatesAvailable,
3250
+ backupPath: wsResult.backupPath,
3251
+ engineResult: wsResult
3252
+ });
3253
+ }
3030
3254
  }
3255
+ const extraEngines = renderNonClaudeEngines(cwd, config, engines, dryRun);
3031
3256
  return {
3032
3257
  ok: true,
3033
3258
  filePath: claudeMdPath,
3034
- entries: engineResult.claudeMdEntries,
3035
- written: engineResult.written.length > 0,
3036
- languageFallbacks: engineResult.languageFallbacks,
3037
- updatesAvailable: engineResult.updatesAvailable,
3038
- backupPath: engineResult.backupPath,
3259
+ entries: engineResult?.claudeMdEntries ?? [],
3260
+ written: (engineResult?.written.length ?? 0) > 0,
3261
+ languageFallbacks: engineResult?.languageFallbacks ?? [],
3262
+ updatesAvailable: engineResult?.updatesAvailable ?? [],
3263
+ backupPath: engineResult?.backupPath ?? null,
3039
3264
  engineResult,
3040
- workspaces
3265
+ workspaces,
3266
+ extraEngines
3041
3267
  };
3042
3268
  }
3043
3269
  var renderCommand = defineCommand({
@@ -3068,7 +3294,7 @@ var renderCommand = defineCommand({
3068
3294
  benchStart();
3069
3295
  const cwd = resolve9(args.cwd ?? process.cwd());
3070
3296
  p.intro(brand("render"));
3071
- if (!existsSync12(cwd)) {
3297
+ if (!existsSync13(cwd)) {
3072
3298
  p.cancel(`Directory not found: ${cwd}`);
3073
3299
  process.exit(1);
3074
3300
  }
@@ -3113,8 +3339,17 @@ var renderCommand = defineCommand({
3113
3339
  p.log.message(`${dim("Backup:")} ${ws.backupPath}`);
3114
3340
  }
3115
3341
  }
3342
+ for (const ee of result.extraEngines ?? []) {
3343
+ p.log.message(`${dim("engine")} ${color.cyan(ee.engine)}`);
3344
+ for (const w of ee.written) {
3345
+ p.log.message(` ${renderStatusSymbol(w.status)} ${w.path} ${dim("(")}${renderStatusLabel(w.status)}${dim(")")}`);
3346
+ }
3347
+ for (const s of ee.skipped) p.log.warn(` ${s.path}: ${s.reason}`);
3348
+ for (const warn of ee.warnings) p.log.warn(` ${warn}`);
3349
+ if (ee.backupPath) p.log.message(` ${dim("Backup:")} ${ee.backupPath}`);
3350
+ }
3116
3351
  const allEntries = result.entries.concat(...result.workspaces.map((w) => w.entries));
3117
- const anyPending = result.written || result.workspaces.some((w) => w.written);
3352
+ const anyPending = result.written || result.workspaces.some((w) => w.written) || (result.extraEngines ?? []).some((e) => e.written.length > 0);
3118
3353
  const summary = summarize(allEntries);
3119
3354
  if (preview) {
3120
3355
  if (anyPending) {
@@ -3480,7 +3715,7 @@ function formatWorkspaceSummary(ws, lang = "es") {
3480
3715
  }
3481
3716
 
3482
3717
  // src/engines/claude/prompts-loader.ts
3483
- import { readFileSync as readFileSync12, existsSync as existsSync13 } from "fs";
3718
+ import { readFileSync as readFileSync13, existsSync as existsSync14 } from "fs";
3484
3719
  import { resolve as resolve10 } from "path";
3485
3720
  import { z as z7 } from "zod";
3486
3721
  var SelectOptionSchema = z7.object({
@@ -3520,10 +3755,10 @@ function loadPrompts(enabledPlugins) {
3520
3755
  }
3521
3756
  function loadCorePrompts(warnings) {
3522
3757
  const path = resolve10(getCoreRoot(), CORE_PROMPTS_REL);
3523
- if (!existsSync13(path)) return [];
3758
+ if (!existsSync14(path)) return [];
3524
3759
  let parsed;
3525
3760
  try {
3526
- parsed = JSON.parse(readFileSync12(path, "utf-8"));
3761
+ parsed = JSON.parse(readFileSync13(path, "utf-8"));
3527
3762
  } catch (err) {
3528
3763
  warnings.push(`core prompts.json no parsea: ${err.message}`);
3529
3764
  return [];
@@ -3537,8 +3772,8 @@ function loadCorePrompts(warnings) {
3537
3772
  }
3538
3773
 
3539
3774
  // src/lib/scan.ts
3540
- import { existsSync as existsSync14, readdirSync as readdirSync6 } from "fs";
3541
- import { join as join10 } from "path";
3775
+ import { existsSync as existsSync15, readdirSync as readdirSync6 } from "fs";
3776
+ import { join as join11 } from "path";
3542
3777
  function scanMonorepoWorkspaces(cwd) {
3543
3778
  const patterns = collectWorkspacePatterns(cwd);
3544
3779
  if (patterns.length === 0) return [];
@@ -3565,9 +3800,9 @@ function walk(cwd, accum, remaining) {
3565
3800
  }
3566
3801
  const [head, ...tail] = remaining;
3567
3802
  const currentRel = accum.join("/");
3568
- const currentAbs = currentRel ? join10(cwd, currentRel) : cwd;
3803
+ const currentAbs = currentRel ? join11(cwd, currentRel) : cwd;
3569
3804
  if (head === "*") {
3570
- if (!existsSync14(currentAbs)) return [];
3805
+ if (!existsSync15(currentAbs)) return [];
3571
3806
  let entries;
3572
3807
  try {
3573
3808
  entries = readdirSync6(currentAbs, { withFileTypes: true });
@@ -3576,8 +3811,8 @@ function walk(cwd, accum, remaining) {
3576
3811
  }
3577
3812
  return entries.filter((d) => d.isDirectory() && !d.name.startsWith(".")).flatMap((d) => walk(cwd, [...accum, d.name], tail));
3578
3813
  }
3579
- const next = join10(currentAbs, head);
3580
- if (!existsSync14(next)) return [];
3814
+ const next = join11(currentAbs, head);
3815
+ if (!existsSync15(next)) return [];
3581
3816
  return walk(cwd, [...accum, head], tail);
3582
3817
  }
3583
3818
  function diffWorkspaces(detected, configured) {
@@ -3589,8 +3824,8 @@ function diffWorkspaces(detected, configured) {
3589
3824
  return { added, existing, orphan };
3590
3825
  }
3591
3826
  function describeWorkspace(cwd, relPath) {
3592
- const abs = join10(cwd, relPath);
3593
- if (!existsSync14(join10(abs, "package.json"))) return null;
3827
+ const abs = join11(cwd, relPath);
3828
+ if (!existsSync15(join11(abs, "package.json"))) return null;
3594
3829
  const project = detectProject(abs);
3595
3830
  return {
3596
3831
  name: project.name ?? relPath.split("/").pop(),
@@ -3671,11 +3906,11 @@ var initCommand = defineCommand2({
3671
3906
  p2.intro(brand("init"));
3672
3907
  const bootstrapLang = normalizeLang(args.lang) ?? "es";
3673
3908
  const bootstrapT = t(bootstrapLang);
3674
- if (!existsSync15(cwd)) {
3909
+ if (!existsSync16(cwd)) {
3675
3910
  p2.cancel(bootstrapT.dirNotFound(cwd));
3676
3911
  process.exit(1);
3677
3912
  }
3678
- if (existsSync15(configPath)) {
3913
+ if (existsSync16(configPath)) {
3679
3914
  p2.cancel(bootstrapT.configExists(configPath));
3680
3915
  process.exit(1);
3681
3916
  }
@@ -4289,7 +4524,7 @@ ${lines}${more}`);
4289
4524
  }
4290
4525
  }
4291
4526
  async function offerPreCommitHook(cwd, opts) {
4292
- if (!existsSync15(join11(cwd, ".git"))) return;
4527
+ if (!existsSync16(join12(cwd, ".git"))) return;
4293
4528
  let wanted = opts.force;
4294
4529
  if (!wanted && !opts.autoYes) {
4295
4530
  const answer = await p2.confirm({
@@ -4308,10 +4543,10 @@ async function offerPreCommitHook(cwd, opts) {
4308
4543
  }
4309
4544
  }
4310
4545
  function writePreCommitHook(cwd) {
4311
- const huskyDir = join11(cwd, ".husky");
4312
- const hookPath = existsSync15(huskyDir) ? join11(huskyDir, "pre-commit") : join11(cwd, ".git", "hooks", "pre-commit");
4546
+ const huskyDir = join12(cwd, ".husky");
4547
+ const hookPath = existsSync16(huskyDir) ? join12(huskyDir, "pre-commit") : join12(cwd, ".git", "hooks", "pre-commit");
4313
4548
  const relPath = relative3(cwd, hookPath);
4314
- if (existsSync15(hookPath)) return { ok: false, path: relPath };
4549
+ if (existsSync16(hookPath)) return { ok: false, path: relPath };
4315
4550
  const body = [
4316
4551
  "#!/usr/bin/env sh",
4317
4552
  "# navori pre-commit drift gate \u2014 scaffolded by 'navori init' (opt-in).",
@@ -4323,7 +4558,7 @@ function writePreCommitHook(cwd) {
4323
4558
  "fi",
4324
4559
  ""
4325
4560
  ].join("\n");
4326
- mkdirSync5(dirname6(hookPath), { recursive: true });
4561
+ mkdirSync6(dirname7(hookPath), { recursive: true });
4327
4562
  writeFileAtomic(hookPath, body);
4328
4563
  try {
4329
4564
  chmodSync2(hookPath, 493);
@@ -4548,15 +4783,15 @@ function formatProjectValue(v) {
4548
4783
  // src/commands/doctor.ts
4549
4784
  import { defineCommand as defineCommand3 } from "citty";
4550
4785
  import * as p3 from "@clack/prompts";
4551
- import { existsSync as existsSync17, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "fs";
4552
- import { join as join13, resolve as resolve12, relative as relative4 } from "path";
4786
+ import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync8 } from "fs";
4787
+ import { join as join14, resolve as resolve12, relative as relative4 } from "path";
4553
4788
 
4554
4789
  // src/lib/health.ts
4555
- import { existsSync as existsSync16, readFileSync as readFileSync13, readdirSync as readdirSync7 } from "fs";
4556
- import { join as join12 } from "path";
4790
+ import { existsSync as existsSync17, readFileSync as readFileSync14, readdirSync as readdirSync7 } from "fs";
4791
+ import { join as join13 } from "path";
4557
4792
  function listMarkers(filePath) {
4558
- if (!existsSync16(filePath)) return [];
4559
- const content = readFileSync13(filePath, "utf-8");
4793
+ if (!existsSync17(filePath)) return [];
4794
+ const content = readFileSync14(filePath, "utf-8");
4560
4795
  const re = /<!-- navori:managed [^>]*-->/g;
4561
4796
  const result = [];
4562
4797
  for (const match of content.matchAll(re)) {
@@ -4601,10 +4836,10 @@ function scanManagedDrift(cwd, config) {
4601
4836
  }
4602
4837
  }
4603
4838
  const files = [];
4604
- if (existsSync16(join12(cwd, "CLAUDE.md"))) files.push("CLAUDE.md");
4839
+ if (existsSync17(join13(cwd, "CLAUDE.md"))) files.push("CLAUDE.md");
4605
4840
  for (const dir of [".claude/agents", ".claude/skills"]) {
4606
- const absDir = join12(cwd, dir);
4607
- if (!existsSync16(absDir)) continue;
4841
+ const absDir = join13(cwd, dir);
4842
+ if (!existsSync17(absDir)) continue;
4608
4843
  try {
4609
4844
  for (const file of readdirSync7(absDir)) {
4610
4845
  if (file.endsWith(".md")) files.push(`${dir}/${file}`);
@@ -4614,10 +4849,10 @@ function scanManagedDrift(cwd, config) {
4614
4849
  }
4615
4850
  }
4616
4851
  for (const rel of files) {
4617
- const abs = join12(cwd, rel);
4852
+ const abs = join13(cwd, rel);
4618
4853
  const fileContent = (() => {
4619
4854
  try {
4620
- return readFileSync13(abs, "utf-8");
4855
+ return readFileSync14(abs, "utf-8");
4621
4856
  } catch {
4622
4857
  return null;
4623
4858
  }
@@ -4658,21 +4893,45 @@ function scanManagedDrift(cwd, config) {
4658
4893
  }
4659
4894
  return out;
4660
4895
  }
4896
+ function scanManagedOrder(cwd, config) {
4897
+ const claudeMdPath = join13(cwd, "CLAUDE.md");
4898
+ if (!existsSync17(claudeMdPath)) return null;
4899
+ const content = readFileSync14(claudeMdPath, "utf-8");
4900
+ const current = listMarkers(claudeMdPath).map((m) => m.id);
4901
+ if (current.length < 2) return null;
4902
+ const canonical = canonicalManagedOrder(config, cwd);
4903
+ const result = reorderManagedBlocks(content, canonical);
4904
+ if (!result.reordered && !result.blockedByInterleaving) return null;
4905
+ const rank = /* @__PURE__ */ new Map();
4906
+ canonical.forEach((id, i) => {
4907
+ if (!rank.has(id)) rank.set(id, i);
4908
+ });
4909
+ const expected = current.map((id, i) => ({ id, i, key: rank.has(id) ? rank.get(id) : canonical.length + i })).sort((a, z8) => a.key - z8.key || a.i - z8.i).map((x) => x.id);
4910
+ return { current, expected, interleaved: result.blockedByInterleaving };
4911
+ }
4661
4912
  function suggestNextSteps(state) {
4662
4913
  const steps = [];
4663
4914
  if (!state.claudeMdExists) {
4664
- steps.push("Corr\xE9 'navori render --apply' para generar CLAUDE.md + .claude/.");
4915
+ steps.push("Corre 'navori render --apply' para generar CLAUDE.md + .claude/.");
4665
4916
  }
4666
4917
  if (state.missingPlugins.length > 0) {
4667
4918
  steps.push(
4668
- `Resolv\xE9 ${state.missingPlugins.length} plugin(s) faltante(s): instalalos o quitalos del config.`
4919
+ `Resuelve ${state.missingPlugins.length} plugin(s) faltante(s): inst\xE1lalos o qu\xEDtalos del config.`
4669
4920
  );
4670
4921
  }
4671
4922
  if (state.drifts.some((d) => d.kind === "content")) {
4672
- steps.push("Corr\xE9 'navori sync --interactive' para resolver bloques editados a mano.");
4923
+ steps.push("Corre 'navori sync --interactive' para resolver bloques editados a mano.");
4673
4924
  }
4674
4925
  if (state.drifts.some((d) => d.kind === "version")) {
4675
- steps.push("Corr\xE9 'navori render --apply' para traer los bloques a la \xFAltima versi\xF3n.");
4926
+ steps.push("Corre 'navori render --apply' para traer los bloques a la \xFAltima versi\xF3n.");
4927
+ }
4928
+ if (state.orderReport && !state.orderReport.interleaved) {
4929
+ steps.push("Corre 'navori render --apply' para reordenar los bloques de CLAUDE.md al orden can\xF3nico.");
4930
+ }
4931
+ if (state.orderReport?.interleaved) {
4932
+ steps.push(
4933
+ "Mueve el texto que tienes entre bloques managed de CLAUDE.md arriba del primer bloque o abajo del \xFAltimo; luego corre 'navori render --apply' para reordenarlos."
4934
+ );
4676
4935
  }
4677
4936
  if (steps.length === 0) {
4678
4937
  steps.push("Todo al d\xEDa \u2014 sin acciones pendientes.");
@@ -4699,7 +4958,7 @@ var doctorCommand = defineCommand3({
4699
4958
  const configPath = `${cwd}/navori.config.json`;
4700
4959
  const claudeMdPath = `${cwd}/CLAUDE.md`;
4701
4960
  if (!args.json) p3.intro(brand("doctor"));
4702
- if (!existsSync17(cwd)) {
4961
+ if (!existsSync18(cwd)) {
4703
4962
  if (args.json) {
4704
4963
  console.log(JSON.stringify({ ok: false, error: "directory-missing", cwd }));
4705
4964
  } else {
@@ -4707,7 +4966,7 @@ var doctorCommand = defineCommand3({
4707
4966
  }
4708
4967
  process.exit(1);
4709
4968
  }
4710
- if (!existsSync17(configPath)) {
4969
+ if (!existsSync18(configPath)) {
4711
4970
  if (args.json) {
4712
4971
  console.log(JSON.stringify({ ok: false, error: "config-missing", configPath }));
4713
4972
  } else {
@@ -4737,6 +4996,7 @@ var doctorCommand = defineCommand3({
4737
4996
  const markers = listMarkers(claudeMdPath);
4738
4997
  const missingPlugins = collectMissingPlugins(config);
4739
4998
  const drifts = scanManagedDrift(cwd, config);
4999
+ const orderReport = scanManagedOrder(cwd, config);
4740
5000
  const corruptedSettings = scanCorruptedSettings(cwd);
4741
5001
  const missingInvariants = scanMissingInvariants(cwd, config);
4742
5002
  const resolvedPreset = config.preset !== "custom" ? resolvePreset(config.preset, cwd) : null;
@@ -4753,14 +5013,15 @@ var doctorCommand = defineCommand3({
4753
5013
  configPath,
4754
5014
  config,
4755
5015
  checks: {
4756
- claudeMdExists: existsSync17(claudeMdPath),
4757
- agentsMdExists: existsSync17(`${cwd}/AGENTS.md`),
4758
- claudeDirExists: existsSync17(`${cwd}/.claude`),
4759
- progressDirExists: existsSync17(`${cwd}/${config.progress?.dir ?? "progress"}`)
5016
+ claudeMdExists: existsSync18(claudeMdPath),
5017
+ agentsMdExists: existsSync18(`${cwd}/AGENTS.md`),
5018
+ claudeDirExists: existsSync18(`${cwd}/.claude`),
5019
+ progressDirExists: existsSync18(`${cwd}/${config.progress?.dir ?? "progress"}`)
4760
5020
  },
4761
5021
  managedBlocks: markers,
4762
5022
  missingPlugins,
4763
5023
  drifts,
5024
+ orderReport,
4764
5025
  corruptedSettings,
4765
5026
  missingInvariants,
4766
5027
  missingPreset,
@@ -4844,7 +5105,7 @@ ${lines.join("\n")}`
4844
5105
  );
4845
5106
  }
4846
5107
  const missingLocalSkills = (config.project?.localSkills ?? []).filter(
4847
- (name) => !existsSync17(join13(cwd, ".claude/skills", `${name}.md`))
5108
+ (name) => !existsSync18(join14(cwd, ".claude/skills", `${name}.md`))
4848
5109
  );
4849
5110
  if (missingLocalSkills.length > 0) {
4850
5111
  const lines = missingLocalSkills.map(
@@ -4884,10 +5145,26 @@ ${lines.join("\n")}`
4884
5145
  ${lines.join("\n")}`
4885
5146
  );
4886
5147
  }
5148
+ if (orderReport) {
5149
+ if (orderReport.interleaved) {
5150
+ p3.log.warn(
5151
+ `Bloques managed de CLAUDE.md fuera del orden can\xF3nico \u2014 NO se pueden reordenar autom\xE1ticamente porque hay texto tuyo entre bloques. Mueve ese texto arriba del primer bloque managed o abajo del \xFAltimo; luego corre 'navori render --apply'.
5152
+ orden actual: ${orderReport.current.join(", ")}
5153
+ orden can\xF3nico: ${orderReport.expected.join(", ")}`
5154
+ );
5155
+ } else {
5156
+ p3.log.warn(
5157
+ `Bloques managed de CLAUDE.md fuera del orden can\xF3nico \u2014 corre 'navori render --apply' o 'navori sync' para reordenarlos (el primer bloque marca el centro de gravedad del harness).
5158
+ orden actual: ${orderReport.current.join(", ")}
5159
+ orden can\xF3nico: ${orderReport.expected.join(", ")}`
5160
+ );
5161
+ }
5162
+ }
4887
5163
  const nextSteps = suggestNextSteps({
4888
5164
  claudeMdExists: report.checks.claudeMdExists,
4889
5165
  missingPlugins,
4890
- drifts
5166
+ drifts,
5167
+ orderReport
4891
5168
  });
4892
5169
  p3.note(
4893
5170
  nextSteps.map((s) => ` ${color.cyan(sym.bullet)} ${s}`).join("\n"),
@@ -4903,10 +5180,10 @@ ${lines.join("\n")}`
4903
5180
  }
4904
5181
  });
4905
5182
  function scanCorruptedSettings(cwd) {
4906
- const path = join13(cwd, ".claude/settings.json");
4907
- if (!existsSync17(path)) return [];
5183
+ const path = join14(cwd, ".claude/settings.json");
5184
+ if (!existsSync18(path)) return [];
4908
5185
  try {
4909
- JSON.parse(readFileSync14(path, "utf-8"));
5186
+ JSON.parse(readFileSync15(path, "utf-8"));
4910
5187
  return [];
4911
5188
  } catch (err) {
4912
5189
  return [{ path: ".claude/settings.json", error: err.message }];
@@ -4926,7 +5203,7 @@ function scanMissingPresetFiles(cwd, config) {
4926
5203
  const missing = [];
4927
5204
  for (const e of [...managed, ...agents, ...skills, ...hooks]) {
4928
5205
  const abs = resolve12(loaded.assetRoot, e.relPath);
4929
- if (!existsSync17(abs)) missing.push({ id: e.id, path: relative4(cwd, abs) });
5206
+ if (!existsSync18(abs)) missing.push({ id: e.id, path: relative4(cwd, abs) });
4930
5207
  }
4931
5208
  return missing;
4932
5209
  }
@@ -4962,15 +5239,15 @@ function scanMissingInvariants(cwd, config) {
4962
5239
  }
4963
5240
  function readRenderedText(cwd) {
4964
5241
  const parts = [];
4965
- const claudeMd = join13(cwd, "CLAUDE.md");
4966
- if (existsSync17(claudeMd)) {
5242
+ const claudeMd = join14(cwd, "CLAUDE.md");
5243
+ if (existsSync18(claudeMd)) {
4967
5244
  try {
4968
- parts.push(readFileSync14(claudeMd, "utf-8"));
5245
+ parts.push(readFileSync15(claudeMd, "utf-8"));
4969
5246
  } catch {
4970
5247
  }
4971
5248
  }
4972
- const claudeDir = join13(cwd, ".claude");
4973
- if (existsSync17(claudeDir)) collectText(claudeDir, parts);
5249
+ const claudeDir = join14(cwd, ".claude");
5250
+ if (existsSync18(claudeDir)) collectText(claudeDir, parts);
4974
5251
  return parts.join("\n");
4975
5252
  }
4976
5253
  function collectText(dir, parts) {
@@ -4981,12 +5258,12 @@ function collectText(dir, parts) {
4981
5258
  return;
4982
5259
  }
4983
5260
  for (const entry of entries) {
4984
- const abs = join13(dir, entry.name);
5261
+ const abs = join14(dir, entry.name);
4985
5262
  if (entry.isDirectory()) {
4986
5263
  collectText(abs, parts);
4987
5264
  } else if (entry.isFile() && TEXT_EXTENSIONS.some((e) => entry.name.endsWith(e))) {
4988
5265
  try {
4989
- parts.push(readFileSync14(abs, "utf-8"));
5266
+ parts.push(readFileSync15(abs, "utf-8"));
4990
5267
  } catch {
4991
5268
  }
4992
5269
  }
@@ -5018,8 +5295,8 @@ function collectAssignments(config) {
5018
5295
  // src/commands/sync.ts
5019
5296
  import { defineCommand as defineCommand4 } from "citty";
5020
5297
  import * as p4 from "@clack/prompts";
5021
- import { existsSync as existsSync18, readFileSync as readFileSync15 } from "fs";
5022
- import { resolve as resolve13, join as join14 } from "path";
5298
+ import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
5299
+ import { resolve as resolve13, join as join15 } from "path";
5023
5300
 
5024
5301
  // src/lib/diff.ts
5025
5302
  function formatLineDiff(current, proposed, _options = {}) {
@@ -5064,11 +5341,11 @@ var syncCommand = defineCommand4({
5064
5341
  const cwd = resolve13(args.cwd ?? process.cwd());
5065
5342
  const configPath = `${cwd}/navori.config.json`;
5066
5343
  p4.intro(brand("sync"));
5067
- if (!existsSync18(cwd)) {
5344
+ if (!existsSync19(cwd)) {
5068
5345
  p4.cancel(`Directory not found: ${cwd}`);
5069
5346
  process.exit(1);
5070
5347
  }
5071
- if (!existsSync18(configPath)) {
5348
+ if (!existsSync19(configPath)) {
5072
5349
  p4.cancel(`No navori.config.json at ${configPath}. Run 'navori init' first.`);
5073
5350
  process.exit(1);
5074
5351
  }
@@ -5223,8 +5500,8 @@ async function resolveConflictsInteractively(plans) {
5223
5500
  (e) => e.status === "user-modified-skipped"
5224
5501
  );
5225
5502
  if (cmConflicts.length === 0) continue;
5226
- const claudeMdPath = join14(tp.target.cwd, "CLAUDE.md");
5227
- const existing = existsSync18(claudeMdPath) ? readFileSync15(claudeMdPath, "utf-8") : "";
5503
+ const claudeMdPath = join15(tp.target.cwd, "CLAUDE.md");
5504
+ const existing = existsSync19(claudeMdPath) ? readFileSync16(claudeMdPath, "utf-8") : "";
5228
5505
  const skipIds = /* @__PURE__ */ new Set();
5229
5506
  const forceIds = /* @__PURE__ */ new Set();
5230
5507
  for (const e of cmConflicts) {
@@ -5316,13 +5593,13 @@ function summarize2(writtenCount, conflictCount) {
5316
5593
  // src/commands/add.ts
5317
5594
  import { defineCommand as defineCommand5 } from "citty";
5318
5595
  import * as p5 from "@clack/prompts";
5319
- import { existsSync as existsSync20, readFileSync as readFileSync16 } from "fs";
5596
+ import { existsSync as existsSync21, readFileSync as readFileSync17 } from "fs";
5320
5597
  import { resolve as resolve14 } from "path";
5321
5598
  import { spawnSync as spawnSync3 } from "child_process";
5322
5599
 
5323
5600
  // src/lib/which.ts
5324
- import { existsSync as existsSync19, statSync as statSync6 } from "fs";
5325
- import { join as join15 } from "path";
5601
+ import { existsSync as existsSync20, statSync as statSync6 } from "fs";
5602
+ import { join as join16 } from "path";
5326
5603
  function hasBinary(name) {
5327
5604
  const pathEnv = process.env.PATH ?? "";
5328
5605
  const sep2 = process.platform === "win32" ? ";" : ":";
@@ -5330,8 +5607,8 @@ function hasBinary(name) {
5330
5607
  const exts = process.platform === "win32" ? (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";") : [""];
5331
5608
  for (const dir of dirs) {
5332
5609
  for (const ext of exts) {
5333
- const candidate = join15(dir, name + ext);
5334
- if (existsSync19(candidate)) {
5610
+ const candidate = join16(dir, name + ext);
5611
+ if (existsSync20(candidate)) {
5335
5612
  try {
5336
5613
  if (statSync6(candidate).isFile()) return true;
5337
5614
  } catch {
@@ -5407,11 +5684,11 @@ var addCommand = defineCommand5({
5407
5684
  } else {
5408
5685
  p5.intro(brand(`add ${accent(args.plugin)}`));
5409
5686
  }
5410
- if (!existsSync20(cwd)) {
5687
+ if (!existsSync21(cwd)) {
5411
5688
  p5.cancel(`Directory not found: ${cwd}`);
5412
5689
  process.exit(1);
5413
5690
  }
5414
- if (!existsSync20(configPath)) {
5691
+ if (!existsSync21(configPath)) {
5415
5692
  p5.cancel(`No navori.config.json at ${configPath}. Run 'navori init' first.`);
5416
5693
  process.exit(1);
5417
5694
  }
@@ -5445,7 +5722,7 @@ var addCommand = defineCommand5({
5445
5722
  ...config.plugins ?? {},
5446
5723
  [plugin.manifest.id]: { enabled: true }
5447
5724
  };
5448
- const raw = JSON.parse(readFileSync16(configPath, "utf-8"));
5725
+ const raw = JSON.parse(readFileSync17(configPath, "utf-8"));
5449
5726
  writeConfig(configPath, { ...raw, plugins: updatedPlugins });
5450
5727
  p5.log.success(`Added '${plugin.manifest.id}' to ${configPath}`);
5451
5728
  }
@@ -5530,8 +5807,8 @@ function printSuggestions(cwd, configPath) {
5530
5807
  // src/commands/workspace.ts
5531
5808
  import { defineCommand as defineCommand6 } from "citty";
5532
5809
  import * as p6 from "@clack/prompts";
5533
- import { existsSync as existsSync21 } from "fs";
5534
- import { join as join16 } from "path";
5810
+ import { existsSync as existsSync22 } from "fs";
5811
+ import { join as join17 } from "path";
5535
5812
 
5536
5813
  // src/lib/workspace-defaults.ts
5537
5814
  var VALID_DEFAULT_KEYS = "branchBase, prTarget, commits, language, engines, plugins.<id>.enabled";
@@ -5567,8 +5844,8 @@ function applyDefault(current, key, rawValue) {
5567
5844
 
5568
5845
  // src/commands/workspace.ts
5569
5846
  function readRepoConfigName(repoPath) {
5570
- const cfgPath = join16(repoPath, "navori.config.json");
5571
- if (!existsSync21(cfgPath)) return null;
5847
+ const cfgPath = join17(repoPath, "navori.config.json");
5848
+ if (!existsSync22(cfgPath)) return null;
5572
5849
  try {
5573
5850
  return readConfig(cfgPath).name;
5574
5851
  } catch {
@@ -5592,7 +5869,7 @@ var initSubCommand = defineCommand6({
5592
5869
  process.exit(1);
5593
5870
  }
5594
5871
  const path = workspacePath(name);
5595
- if (existsSync21(path)) {
5872
+ if (existsSync22(path)) {
5596
5873
  console.error(`Workspace '${name}' already exists at ${path}`);
5597
5874
  process.exit(1);
5598
5875
  }
@@ -5833,14 +6110,14 @@ var deleteSubCommand = defineCommand6({
5833
6110
  return;
5834
6111
  }
5835
6112
  }
5836
- const { renameSync: renameSync3, existsSync: existsSync31, mkdirSync: mkdirSync10 } = await import("fs");
6113
+ const { renameSync: renameSync3, existsSync: existsSync32, mkdirSync: mkdirSync11 } = await import("fs");
5837
6114
  const { join: joinPath } = await import("path");
5838
6115
  const { homedir: homedir2 } = await import("os");
5839
6116
  const trashRoot = joinPath(homedir2(), ".navori", ".trash");
5840
- mkdirSync10(trashRoot, { recursive: true });
6117
+ mkdirSync11(trashRoot, { recursive: true });
5841
6118
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5842
6119
  const dest = joinPath(trashRoot, `${name}-${ts}`);
5843
- if (existsSync31(dir)) renameSync3(dir, dest);
6120
+ if (existsSync32(dir)) renameSync3(dir, dest);
5844
6121
  p6.outro(`Moved to ${dest}. Restore manually if needed.`);
5845
6122
  }
5846
6123
  });
@@ -5948,7 +6225,7 @@ var renderSubCommand = defineCommand6({
5948
6225
  }
5949
6226
  const rows = [];
5950
6227
  for (const repo of ws.repos) {
5951
- if (!existsSync21(repo.path)) {
6228
+ if (!existsSync22(repo.path)) {
5952
6229
  rows.push({ name: repo.name, status: "missing", detail: repo.path });
5953
6230
  continue;
5954
6231
  }
@@ -6022,11 +6299,11 @@ var workspaceCommand = defineCommand6({
6022
6299
  // src/commands/ticket.ts
6023
6300
  import { defineCommand as defineCommand7 } from "citty";
6024
6301
  import * as p7 from "@clack/prompts";
6025
- import { readFileSync as readFileSync18 } from "fs";
6302
+ import { readFileSync as readFileSync19 } from "fs";
6026
6303
 
6027
6304
  // src/lib/tickets.ts
6028
- import { existsSync as existsSync22, readFileSync as readFileSync17, readdirSync as readdirSync9, statSync as statSync7, mkdirSync as mkdirSync6, renameSync as renameSync2, rmSync as rmSync5 } from "fs";
6029
- import { join as join17, resolve as resolve15 } from "path";
6305
+ import { existsSync as existsSync23, readFileSync as readFileSync18, readdirSync as readdirSync9, statSync as statSync7, mkdirSync as mkdirSync7, renameSync as renameSync2, rmSync as rmSync5 } from "fs";
6306
+ import { join as join18, resolve as resolve15 } from "path";
6030
6307
  var TicketError = class extends NavoriError {
6031
6308
  constructor(message) {
6032
6309
  super("ticket-error", message);
@@ -6035,11 +6312,11 @@ var TicketError = class extends NavoriError {
6035
6312
  function ticketsDir(workspaceName) {
6036
6313
  const ws = loadWorkspace(workspaceName);
6037
6314
  if (!ws) throw new TicketError(`Workspace '${workspaceName}' not found`);
6038
- return join17(workspaceDirectory(workspaceName), ws.ticketsDir);
6315
+ return join18(workspaceDirectory(workspaceName), ws.ticketsDir);
6039
6316
  }
6040
6317
  function readTitle(path) {
6041
6318
  try {
6042
- const content = readFileSync17(path, "utf-8").split("\n");
6319
+ const content = readFileSync18(path, "utf-8").split("\n");
6043
6320
  for (const line of content) {
6044
6321
  const trimmed = line.trim();
6045
6322
  if (!trimmed) continue;
@@ -6052,13 +6329,13 @@ function readTitle(path) {
6052
6329
  }
6053
6330
  function listTickets(workspaceName) {
6054
6331
  const dir = ticketsDir(workspaceName);
6055
- if (!existsSync22(dir)) return [];
6332
+ if (!existsSync23(dir)) return [];
6056
6333
  const out = [];
6057
6334
  const collect = (folder, state) => {
6058
- if (!existsSync22(folder)) return;
6335
+ if (!existsSync23(folder)) return;
6059
6336
  for (const entry of readdirSync9(folder)) {
6060
6337
  if (!entry.endsWith(".md")) continue;
6061
- const full = join17(folder, entry);
6338
+ const full = join18(folder, entry);
6062
6339
  try {
6063
6340
  if (!statSync7(full).isFile()) continue;
6064
6341
  } catch {
@@ -6073,7 +6350,7 @@ function listTickets(workspaceName) {
6073
6350
  }
6074
6351
  };
6075
6352
  collect(dir, "active");
6076
- collect(join17(dir, "_archive"), "archive");
6353
+ collect(join18(dir, "_archive"), "archive");
6077
6354
  return out;
6078
6355
  }
6079
6356
  function findTicket(workspaceName, id) {
@@ -6108,9 +6385,9 @@ function archiveTicket(workspaceName, id) {
6108
6385
  if (!summary) throw new TicketError(`Ticket '${id}' not found in workspace '${workspaceName}'`);
6109
6386
  if (summary.state === "archive") return summary;
6110
6387
  const dir = ticketsDir(workspaceName);
6111
- const archiveDir = join17(dir, "_archive");
6112
- mkdirSync6(archiveDir, { recursive: true });
6113
- const dest = join17(archiveDir, `${id}.md`);
6388
+ const archiveDir = join18(dir, "_archive");
6389
+ mkdirSync7(archiveDir, { recursive: true });
6390
+ const dest = join18(archiveDir, `${id}.md`);
6114
6391
  renameSync2(summary.path, dest);
6115
6392
  return { id, path: dest, title: summary.title, state: "archive" };
6116
6393
  }
@@ -6124,9 +6401,9 @@ function createTicket(workspaceName, id, title) {
6124
6401
  throw new TicketError(`Invalid ticket id '${id}'. Use letters, digits, hyphens, underscores.`);
6125
6402
  }
6126
6403
  const dir = ticketsDir(workspaceName);
6127
- if (!existsSync22(dir)) throw new TicketError(`Tickets directory does not exist: ${dir}`);
6128
- const path = join17(dir, `${id}.md`);
6129
- if (existsSync22(path)) throw new TicketError(`Ticket '${id}' already exists at ${path}`);
6404
+ if (!existsSync23(dir)) throw new TicketError(`Tickets directory does not exist: ${dir}`);
6405
+ const path = join18(dir, `${id}.md`);
6406
+ if (existsSync23(path)) throw new TicketError(`Ticket '${id}' already exists at ${path}`);
6130
6407
  const finalTitle = title?.trim() || id;
6131
6408
  writeFileAtomic(path, defaultTemplate(id, finalTitle));
6132
6409
  return {
@@ -6141,10 +6418,10 @@ function findReferencingRepos(repoPaths, ticketId) {
6141
6418
  const idPattern = new RegExp(`\\b${ticketId}\\b`);
6142
6419
  for (const repoPath of repoPaths) {
6143
6420
  const abs = resolve15(repoPath);
6144
- const current = join17(abs, "progress", "current.md");
6145
- if (!existsSync22(current)) continue;
6421
+ const current = join18(abs, "progress", "current.md");
6422
+ if (!existsSync23(current)) continue;
6146
6423
  try {
6147
- const content = readFileSync17(current, "utf-8");
6424
+ const content = readFileSync18(current, "utf-8");
6148
6425
  const matches = [];
6149
6426
  for (const line of content.split("\n")) {
6150
6427
  if (idPattern.test(line)) matches.push(line.trim());
@@ -6231,7 +6508,7 @@ Create it with: navori ticket new ${args.workspace} ${args.id}
6231
6508
  const repoPaths = (ws?.repos ?? []).map((r) => r.path);
6232
6509
  const referencing = findReferencingRepos(repoPaths, args.id);
6233
6510
  if (args.json) {
6234
- const content = readFileSync18(ticket.path, "utf-8");
6511
+ const content = readFileSync19(ticket.path, "utf-8");
6235
6512
  console.log(JSON.stringify({ ticket, referencing, content }, null, 2));
6236
6513
  return;
6237
6514
  }
@@ -6243,7 +6520,7 @@ Create it with: navori ticket new ${args.workspace} ${args.id}
6243
6520
  ["path", ticket.path]
6244
6521
  ])
6245
6522
  );
6246
- p7.note(readFileSync18(ticket.path, "utf-8"), "Content");
6523
+ p7.note(readFileSync19(ticket.path, "utf-8"), "Content");
6247
6524
  if (referencing.length === 0) {
6248
6525
  p7.log.message(dim("Referenced in: (no repo's progress/current.md mentions this ticket)"));
6249
6526
  } else {
@@ -6377,7 +6654,7 @@ var ticketCommand = defineCommand7({
6377
6654
  // src/commands/configure.ts
6378
6655
  import { defineCommand as defineCommand8 } from "citty";
6379
6656
  import * as p8 from "@clack/prompts";
6380
- import { existsSync as existsSync23, readFileSync as readFileSync19 } from "fs";
6657
+ import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
6381
6658
  import { resolve as resolve16 } from "path";
6382
6659
  var ENGINE_OPTIONS2 = [
6383
6660
  { value: "claude", label: "Claude Code (.claude/)" },
@@ -6391,11 +6668,11 @@ function fail(msg) {
6391
6668
  process.exit(1);
6392
6669
  }
6393
6670
  function loadOrExit(cwd) {
6394
- if (!existsSync23(cwd)) fail(`Directory not found: ${cwd}`);
6671
+ if (!existsSync24(cwd)) fail(`Directory not found: ${cwd}`);
6395
6672
  const configPath = resolve16(cwd, "navori.config.json");
6396
- if (!existsSync23(configPath)) fail(`No navori.config.json at ${configPath}. Run 'navori init' first.`);
6673
+ if (!existsSync24(configPath)) fail(`No navori.config.json at ${configPath}. Run 'navori init' first.`);
6397
6674
  const config = readConfig(configPath);
6398
- const raw = JSON.parse(readFileSync19(configPath, "utf-8"));
6675
+ const raw = JSON.parse(readFileSync20(configPath, "utf-8"));
6399
6676
  return { config, path: configPath, raw };
6400
6677
  }
6401
6678
  function persist(path, raw) {
@@ -6709,7 +6986,7 @@ var configureCommand = defineCommand8({
6709
6986
  // src/commands/update.ts
6710
6987
  import { defineCommand as defineCommand9 } from "citty";
6711
6988
  import * as p9 from "@clack/prompts";
6712
- import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
6989
+ import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
6713
6990
  import { resolve as resolve17 } from "path";
6714
6991
  function sameSet(a, b) {
6715
6992
  if (a.length !== b.length) return false;
@@ -6798,11 +7075,11 @@ var updateCommand = defineCommand9({
6798
7075
  const cwd = resolve17(args.cwd ?? process.cwd());
6799
7076
  const configPath = `${cwd}/navori.config.json`;
6800
7077
  p9.intro(brand("update"));
6801
- if (!existsSync24(cwd)) {
7078
+ if (!existsSync25(cwd)) {
6802
7079
  p9.cancel(`Directory not found: ${cwd}`);
6803
7080
  process.exit(1);
6804
7081
  }
6805
- if (!existsSync24(configPath)) {
7082
+ if (!existsSync25(configPath)) {
6806
7083
  p9.cancel(`No navori.config.json at ${configPath}. Run 'navori init' first.`);
6807
7084
  process.exit(1);
6808
7085
  }
@@ -6863,7 +7140,7 @@ ${lines.join("\n")}`);
6863
7140
  }
6864
7141
  }
6865
7142
  if (diffs.length > 0) {
6866
- const raw = JSON.parse(readFileSync20(configPath, "utf-8"));
7143
+ const raw = JSON.parse(readFileSync21(configPath, "utf-8"));
6867
7144
  delete raw.$schema;
6868
7145
  applyDiffs(raw, detected, diffs);
6869
7146
  writeConfig(configPath, raw);
@@ -6896,14 +7173,14 @@ ${lines.join("\n")}`);
6896
7173
  // src/commands/backup.ts
6897
7174
  import { defineCommand as defineCommand10 } from "citty";
6898
7175
  import * as p10 from "@clack/prompts";
6899
- import { existsSync as existsSync25, readdirSync as readdirSync10, statSync as statSync8, copyFileSync as copyFileSync4, mkdirSync as mkdirSync7 } from "fs";
6900
- import { join as join18, relative as relative5, resolve as resolve18, dirname as dirname7 } from "path";
7176
+ import { existsSync as existsSync26, readdirSync as readdirSync10, statSync as statSync8, copyFileSync as copyFileSync4, mkdirSync as mkdirSync8 } from "fs";
7177
+ import { join as join19, relative as relative5, resolve as resolve18, dirname as dirname8 } from "path";
6901
7178
  function listBackups() {
6902
7179
  const root = backupRoot();
6903
- if (!existsSync25(root)) return [];
7180
+ if (!existsSync26(root)) return [];
6904
7181
  const entries = [];
6905
7182
  for (const name of readdirSync10(root)) {
6906
- const full = join18(root, name);
7183
+ const full = join19(root, name);
6907
7184
  try {
6908
7185
  const stat = statSync8(full);
6909
7186
  if (!stat.isDirectory()) continue;
@@ -6918,7 +7195,7 @@ function listBackups() {
6918
7195
  function collectFiles(root, dir) {
6919
7196
  const out = [];
6920
7197
  for (const entry of readdirSync10(dir)) {
6921
- const full = join18(dir, entry);
7198
+ const full = join19(dir, entry);
6922
7199
  try {
6923
7200
  const stat = statSync8(full);
6924
7201
  if (stat.isDirectory()) {
@@ -6984,9 +7261,9 @@ var restoreSubCommand = defineCommand10({
6984
7261
  async run({ args }) {
6985
7262
  const ts = args.timestamp;
6986
7263
  const cwd = resolve18(args.cwd ?? process.cwd());
6987
- const backupDir = join18(backupRoot(), ts);
7264
+ const backupDir = join19(backupRoot(), ts);
6988
7265
  p10.intro(brand(`backup restore ${accent(ts)}`));
6989
- if (!existsSync25(backupDir)) {
7266
+ if (!existsSync26(backupDir)) {
6990
7267
  p10.cancel(`Backup not found: ${backupDir}`);
6991
7268
  process.exit(1);
6992
7269
  }
@@ -7008,9 +7285,9 @@ var restoreSubCommand = defineCommand10({
7008
7285
  }
7009
7286
  }
7010
7287
  for (const rel of files) {
7011
- const src = join18(backupDir, rel);
7012
- const dest = join18(cwd, rel);
7013
- mkdirSync7(dirname7(dest), { recursive: true });
7288
+ const src = join19(backupDir, rel);
7289
+ const dest = join19(cwd, rel);
7290
+ mkdirSync8(dirname8(dest), { recursive: true });
7014
7291
  copyFileSync4(src, dest);
7015
7292
  }
7016
7293
  p10.outro(`Restored ${files.length} file(s)`);
@@ -7040,19 +7317,19 @@ var backupCommand = defineCommand10({
7040
7317
  // src/commands/migrations.ts
7041
7318
  import { defineCommand as defineCommand11 } from "citty";
7042
7319
  import * as p11 from "@clack/prompts";
7043
- import { existsSync as existsSync26, readdirSync as readdirSync11, statSync as statSync9, copyFileSync as copyFileSync5, mkdirSync as mkdirSync8 } from "fs";
7044
- import { join as join19, relative as relative6, resolve as resolve19, dirname as dirname8 } from "path";
7320
+ import { existsSync as existsSync27, readdirSync as readdirSync11, statSync as statSync9, copyFileSync as copyFileSync5, mkdirSync as mkdirSync9 } from "fs";
7321
+ import { join as join20, relative as relative6, resolve as resolve19, dirname as dirname9 } from "path";
7045
7322
  function listMigrations() {
7046
7323
  const root = migrationsRoot();
7047
- if (!existsSync26(root)) return [];
7324
+ if (!existsSync27(root)) return [];
7048
7325
  const entries = [];
7049
7326
  for (const ts of readdirSync11(root)) {
7050
- const tsDir = join19(root, ts);
7327
+ const tsDir = join20(root, ts);
7051
7328
  try {
7052
7329
  const stat = statSync9(tsDir);
7053
7330
  if (!stat.isDirectory()) continue;
7054
7331
  for (const repoName of readdirSync11(tsDir)) {
7055
- const repoDir = join19(tsDir, repoName);
7332
+ const repoDir = join20(tsDir, repoName);
7056
7333
  try {
7057
7334
  const repoStat = statSync9(repoDir);
7058
7335
  if (!repoStat.isDirectory()) continue;
@@ -7070,7 +7347,7 @@ function listMigrations() {
7070
7347
  function collectFiles2(root, dir) {
7071
7348
  const out = [];
7072
7349
  for (const entry of readdirSync11(dir)) {
7073
- const full = join19(dir, entry);
7350
+ const full = join20(dir, entry);
7074
7351
  try {
7075
7352
  const stat = statSync9(full);
7076
7353
  if (stat.isDirectory()) {
@@ -7139,9 +7416,9 @@ var restoreSubCommand2 = defineCommand11({
7139
7416
  const ts = args.timestamp;
7140
7417
  const repoName = args.repo;
7141
7418
  const cwd = resolve19(args.cwd ?? process.cwd());
7142
- const migrationDir = join19(migrationsRoot(), ts, repoName);
7419
+ const migrationDir = join20(migrationsRoot(), ts, repoName);
7143
7420
  p11.intro(brand(`migrations restore ${accent(`${ts}/${repoName}`)}`));
7144
- if (!existsSync26(migrationDir)) {
7421
+ if (!existsSync27(migrationDir)) {
7145
7422
  p11.cancel(`Migration not found: ${migrationDir}`);
7146
7423
  process.exit(1);
7147
7424
  }
@@ -7164,9 +7441,9 @@ var restoreSubCommand2 = defineCommand11({
7164
7441
  }
7165
7442
  }
7166
7443
  for (const rel of files) {
7167
- const src = join19(migrationDir, rel);
7168
- const dest = join19(cwd, rel);
7169
- mkdirSync8(dirname8(dest), { recursive: true });
7444
+ const src = join20(migrationDir, rel);
7445
+ const dest = join20(cwd, rel);
7446
+ mkdirSync9(dirname9(dest), { recursive: true });
7170
7447
  copyFileSync5(src, dest);
7171
7448
  }
7172
7449
  p11.outro(`Restored ${files.length} file(s)`);
@@ -7197,8 +7474,8 @@ var migrationsCommand = defineCommand11({
7197
7474
  // src/commands/preset.ts
7198
7475
  import { defineCommand as defineCommand12 } from "citty";
7199
7476
  import * as p12 from "@clack/prompts";
7200
- import { existsSync as existsSync27, mkdirSync as mkdirSync9 } from "fs";
7201
- import { join as join20, resolve as resolve20 } from "path";
7477
+ import { existsSync as existsSync28, mkdirSync as mkdirSync10 } from "fs";
7478
+ import { join as join21, resolve as resolve20 } from "path";
7202
7479
  var PRESET_ID_RE = /^[a-z0-9][a-z0-9-]*$/;
7203
7480
  function stackTemplate(id) {
7204
7481
  return [
@@ -7266,7 +7543,7 @@ var initSubCommand2 = defineCommand12({
7266
7543
  process.exit(1);
7267
7544
  }
7268
7545
  const presetDir = resolve20(cwd, ".navori/presets", id);
7269
- if (existsSync27(presetDir)) {
7546
+ if (existsSync28(presetDir)) {
7270
7547
  p12.cancel(
7271
7548
  `Ya existe .navori/presets/${id}/ \u2014 b\xF3rralo o usa otro id si quieres regenerarlo.`
7272
7549
  );
@@ -7292,11 +7569,11 @@ var initSubCommand2 = defineCommand12({
7292
7569
  },
7293
7570
  invariants: []
7294
7571
  };
7295
- mkdirSync9(join20(presetDir, "managed"), { recursive: true });
7296
- mkdirSync9(join20(presetDir, "skills"), { recursive: true });
7297
- writeFileAtomic(join20(presetDir, `${id}.json`), JSON.stringify(manifest, null, 2) + "\n");
7298
- writeFileAtomic(join20(presetDir, "managed", "stack.md"), stackTemplate(id));
7299
- writeFileAtomic(join20(presetDir, "skills", `${skillId}.md`), skillTemplate(skillId));
7572
+ mkdirSync10(join21(presetDir, "managed"), { recursive: true });
7573
+ mkdirSync10(join21(presetDir, "skills"), { recursive: true });
7574
+ writeFileAtomic(join21(presetDir, `${id}.json`), JSON.stringify(manifest, null, 2) + "\n");
7575
+ writeFileAtomic(join21(presetDir, "managed", "stack.md"), stackTemplate(id));
7576
+ writeFileAtomic(join21(presetDir, "skills", `${skillId}.md`), skillTemplate(skillId));
7300
7577
  p12.log.success(`Creado .navori/presets/${id}/`);
7301
7578
  p12.log.message(
7302
7579
  [
@@ -7305,8 +7582,8 @@ var initSubCommand2 = defineCommand12({
7305
7582
  ` ${dim("\xB7")} skills/${skillId}.md`
7306
7583
  ].join("\n")
7307
7584
  );
7308
- const configPath = join20(cwd, "navori.config.json");
7309
- if (existsSync27(configPath)) {
7585
+ const configPath = join21(cwd, "navori.config.json");
7586
+ if (existsSync28(configPath)) {
7310
7587
  const config = readConfig(configPath);
7311
7588
  writeConfig(configPath, { ...config, preset: id });
7312
7589
  p12.log.success(`navori.config.json \u2192 preset: ${accent(id)}`);
@@ -7333,10 +7610,10 @@ var presetCommand = defineCommand12({
7333
7610
  import { defineCommand as defineCommand13 } from "citty";
7334
7611
  import * as p13 from "@clack/prompts";
7335
7612
  import { resolve as resolve21 } from "path";
7336
- import { existsSync as existsSync28 } from "fs";
7613
+ import { existsSync as existsSync29 } from "fs";
7337
7614
  function runScan(opts) {
7338
7615
  const configPath = resolve21(opts.cwd, "navori.config.json");
7339
- if (!existsSync28(configPath)) {
7616
+ if (!existsSync29(configPath)) {
7340
7617
  return { kind: "no-config", configPath };
7341
7618
  }
7342
7619
  const config = readConfig(configPath);
@@ -7507,7 +7784,7 @@ async function collectPresetOverrides(added) {
7507
7784
  // src/commands/status.ts
7508
7785
  import { defineCommand as defineCommand14 } from "citty";
7509
7786
  import * as p14 from "@clack/prompts";
7510
- import { existsSync as existsSync29 } from "fs";
7787
+ import { existsSync as existsSync30 } from "fs";
7511
7788
  import { resolve as resolve22 } from "path";
7512
7789
  var statusCommand = defineCommand14({
7513
7790
  meta: {
@@ -7521,7 +7798,7 @@ var statusCommand = defineCommand14({
7521
7798
  async run({ args }) {
7522
7799
  const cwd = resolve22(args.cwd ?? process.cwd());
7523
7800
  const configPath = `${cwd}/navori.config.json`;
7524
- if (!existsSync29(configPath)) {
7801
+ if (!existsSync30(configPath)) {
7525
7802
  if (args.json) {
7526
7803
  console.log(JSON.stringify({ ok: false, error: "config-missing", configPath }));
7527
7804
  } else {
@@ -7545,7 +7822,7 @@ var statusCommand = defineCommand14({
7545
7822
  }
7546
7823
  throw err;
7547
7824
  }
7548
- const claudeMdExists = existsSync29(`${cwd}/CLAUDE.md`);
7825
+ const claudeMdExists = existsSync30(`${cwd}/CLAUDE.md`);
7549
7826
  const missingPlugins = collectMissingPlugins(config);
7550
7827
  const drifts = scanManagedDrift(cwd, config);
7551
7828
  const enabledPlugins = Object.entries(config.plugins ?? {}).filter(([, v]) => v.enabled === true).map(([k]) => k);
@@ -7593,7 +7870,7 @@ var statusCommand = defineCommand14({
7593
7870
  import { defineCommand as defineCommand15 } from "citty";
7594
7871
  import * as p15 from "@clack/prompts";
7595
7872
  import { performance as performance2 } from "perf_hooks";
7596
- import { existsSync as existsSync30 } from "fs";
7873
+ import { existsSync as existsSync31 } from "fs";
7597
7874
  import { resolve as resolve23 } from "path";
7598
7875
  var benchCommand = defineCommand15({
7599
7876
  meta: {
@@ -7607,7 +7884,7 @@ var benchCommand = defineCommand15({
7607
7884
  async run({ args }) {
7608
7885
  const cwd = resolve23(args.cwd ?? process.cwd());
7609
7886
  p15.intro(brand("bench"));
7610
- if (!existsSync30(`${cwd}/navori.config.json`)) {
7887
+ if (!existsSync31(`${cwd}/navori.config.json`)) {
7611
7888
  p15.cancel(`No navori.config.json at ${cwd}. Run 'navori init' first.`);
7612
7889
  process.exit(1);
7613
7890
  }
@@ -7638,13 +7915,13 @@ var benchCommand = defineCommand15({
7638
7915
 
7639
7916
  // src/index.ts
7640
7917
  function readVersion() {
7641
- const here = dirname9(fileURLToPath2(import.meta.url));
7918
+ const here = dirname10(fileURLToPath2(import.meta.url));
7642
7919
  for (const candidate of [
7643
7920
  resolve24(here, "..", "package.json"),
7644
7921
  resolve24(here, "package.json")
7645
7922
  ]) {
7646
7923
  try {
7647
- const pkg = JSON.parse(readFileSync21(candidate, "utf-8"));
7924
+ const pkg = JSON.parse(readFileSync22(candidate, "utf-8"));
7648
7925
  if (pkg.version) return pkg.version;
7649
7926
  } catch {
7650
7927
  }