navori 0.2.2 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/index.js +70 -35
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -946,7 +946,9 @@ function pickPresetCandidate(stack, monorepo) {
946
946
  if (fw === "fastify") return "fastify";
947
947
  if (fw === "hono") return "hono";
948
948
  if (fw === "elysia") return "elysia";
949
- if (stack.worker && (fw === "express" || fw === null)) return "background-worker";
949
+ const usesMongoose = stack.deps.includes("mongoose");
950
+ if (stack.worker && fw === "express" && !usesMongoose) return "background-worker";
951
+ if (stack.worker && fw === null) return "background-worker";
950
952
  if (fw === "express") return "express-mongoose";
951
953
  return "custom";
952
954
  }
@@ -6709,6 +6711,15 @@ import { defineCommand as defineCommand9 } from "citty";
6709
6711
  import * as p9 from "@clack/prompts";
6710
6712
  import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
6711
6713
  import { resolve as resolve17 } from "path";
6714
+ function sameSet(a, b) {
6715
+ if (a.length !== b.length) return false;
6716
+ const seen = new Set(a);
6717
+ return b.every((x) => seen.has(x));
6718
+ }
6719
+ function withProject(current, patch) {
6720
+ const base = current && typeof current === "object" ? current : {};
6721
+ return { ...base, ...patch };
6722
+ }
6712
6723
  function diffConfig(current, detected) {
6713
6724
  const out = [];
6714
6725
  if (current.preset !== detected.suggestedPreset && detected.suggestedPreset !== "custom") {
@@ -6736,6 +6747,21 @@ function diffConfig(current, detected) {
6736
6747
  after: [...current.engines, ...newlyDetected].join(", ")
6737
6748
  });
6738
6749
  }
6750
+ const currentLibs = current.project?.libraries ?? [];
6751
+ if (!sameSet(currentLibs, detected.libraries)) {
6752
+ out.push({
6753
+ field: "project.libraries",
6754
+ before: currentLibs.length ? currentLibs.join(", ") : "(none)",
6755
+ after: detected.libraries.length ? detected.libraries.join(", ") : "(none)"
6756
+ });
6757
+ }
6758
+ const detectedLang = detected.stack.language;
6759
+ if (detectedLang && detectedLang !== "unknown") {
6760
+ const currentLang = current.project?.codeLanguage;
6761
+ if (currentLang !== detectedLang) {
6762
+ out.push({ field: "project.codeLanguage", before: currentLang ?? "(none)", after: detectedLang });
6763
+ }
6764
+ }
6739
6765
  return out;
6740
6766
  }
6741
6767
  function applyDiffs(raw, detected, diffs) {
@@ -6750,6 +6776,10 @@ function applyDiffs(raw, detected, diffs) {
6750
6776
  const currentEngines = new Set(raw.engines ?? []);
6751
6777
  for (const e of detected.existingEngines) currentEngines.add(e);
6752
6778
  raw.engines = [...currentEngines];
6779
+ } else if (d.field === "project.libraries") {
6780
+ raw.project = withProject(raw.project, { libraries: detected.libraries });
6781
+ } else if (d.field === "project.codeLanguage") {
6782
+ raw.project = withProject(raw.project, { codeLanguage: detected.stack.language });
6753
6783
  }
6754
6784
  }
6755
6785
  }
@@ -6779,9 +6809,11 @@ var updateCommand = defineCommand9({
6779
6809
  const config = readConfig(configPath);
6780
6810
  const detected = detectProject(cwd);
6781
6811
  const diffs = diffConfig(config, detected);
6782
- const claudeMd = existsSync24(`${cwd}/CLAUDE.md`) ? readFileSync20(`${cwd}/CLAUDE.md`, "utf-8") : "";
6783
- const plan = computeRenderPlan(claudeMd, config, cwd);
6784
- if (diffs.length === 0 && !plan.changed && plan.updatesAvailable.length === 0) {
6812
+ const preview = runRender(cwd, true);
6813
+ const previewWrites = preview.engineResult?.written ?? [];
6814
+ const previewConflicts = preview.engineResult?.skipped ?? [];
6815
+ const updates = preview.updatesAvailable ?? [];
6816
+ if (diffs.length === 0 && previewWrites.length === 0 && previewConflicts.length === 0) {
6785
6817
  p9.outro("Up to date \u2014 nothing to update");
6786
6818
  return;
6787
6819
  }
@@ -6794,24 +6826,35 @@ ${lines.join("\n")}`);
6794
6826
  } else {
6795
6827
  p9.log.info("Config is in sync with the repo");
6796
6828
  }
6797
- if (plan.updatesAvailable.length > 0) {
6798
- const lines = plan.updatesAvailable.map(
6829
+ if (previewWrites.length > 0) {
6830
+ const shown = previewWrites.slice(0, 12).map((w) => ` ${color.cyan(sym.update)} ${w.path} ${dim(`(${w.status})`)}`);
6831
+ const more = previewWrites.length > 12 ? `
6832
+ ${dim(`\u2026 +${previewWrites.length - 12} m\xE1s`)}` : "";
6833
+ p9.log.info(`Archivos que se actualizar\xEDan (${previewWrites.length}):
6834
+ ${shown.join("\n")}${more}`);
6835
+ }
6836
+ if (updates.length > 0) {
6837
+ const lines = updates.map(
6799
6838
  (u) => ` ${color.cyan(sym.update)} ${u.id} ${dim(`(${u.source} ${u.fromVersion} \u2192 ${u.toVersion})`)}`
6800
6839
  );
6801
- p9.log.info(`Managed block updates available (${plan.updatesAvailable.length}):
6840
+ p9.log.info(`Managed block updates available (${updates.length}):
6802
6841
  ${lines.join("\n")}`);
6803
6842
  }
6804
- const conflicts = plan.entries.filter((e) => e.status === "user-modified-skipped");
6805
- if (conflicts.length > 0) {
6806
- p9.log.warn(`${conflicts.length} conflict(s) in managed blocks \u2014 sync will need a decision`);
6843
+ if (previewConflicts.length > 0) {
6844
+ p9.log.warn(`${previewConflicts.length} archivo(s) con ediciones tuyas \u2014 'navori sync' los resuelve interactivamente`);
6807
6845
  }
6808
6846
  if (args["dry-run"]) {
6847
+ if (diffs.some((d) => d.field === "project.libraries")) {
6848
+ p9.log.message(
6849
+ dim("Nota: aplicar el diff de project.libraries materializa las library skills (el preview de arriba refleja el config actual).")
6850
+ );
6851
+ }
6809
6852
  p9.outro("Dry-run complete (no files written)");
6810
6853
  return;
6811
6854
  }
6812
6855
  if (!args.yes && diffs.length > 0) {
6813
6856
  const ok = await p9.confirm({
6814
- message: `Apply ${diffs.length} config update${diffs.length === 1 ? "" : "s"}?`,
6857
+ message: `Apply ${diffs.length} config update${diffs.length === 1 ? "" : "s"} + re-render?`,
6815
6858
  initialValue: true
6816
6859
  });
6817
6860
  if (p9.isCancel(ok) || !ok) {
@@ -6827,32 +6870,24 @@ ${lines.join("\n")}`);
6827
6870
  p9.log.success(`Updated ${configPath}`);
6828
6871
  }
6829
6872
  if (args["config-only"]) {
6830
- p9.outro("Config updated. Run 'navori sync' when ready to refresh CLAUDE.md.");
6873
+ p9.outro("Config updated. Corre 'navori sync' para refrescar CLAUDE.md + .claude/.");
6831
6874
  return;
6832
6875
  }
6833
- if (plan.changed || plan.updatesAvailable.length > 0 || diffs.length > 0) {
6834
- const freshConfig = readConfig(configPath);
6835
- const claudeMdNow = existsSync24(`${cwd}/CLAUDE.md`) ? readFileSync20(`${cwd}/CLAUDE.md`, "utf-8") : "";
6836
- const freshPlan = computeRenderPlan(claudeMdNow, freshConfig, cwd);
6837
- const fresheConflicts = freshPlan.entries.filter((e) => e.status === "user-modified-skipped");
6838
- if (fresheConflicts.length > 0 && !args.yes) {
6839
- p9.log.warn(
6840
- `${fresheConflicts.length} conflict(s) detected \u2014 run 'navori sync' to resolve interactively`
6841
- );
6842
- p9.outro("Done (config updated, sync deferred due to conflicts)");
6843
- return;
6844
- }
6845
- if (freshPlan.changed) {
6846
- if (existsSync24(`${cwd}/CLAUDE.md`)) {
6847
- const handle = createBackup(cwd, ["CLAUDE.md"]);
6848
- purgeOldBackups();
6849
- p9.log.message(`Backup: ${handle.path}`);
6850
- }
6851
- writeFileAtomic(`${cwd}/CLAUDE.md`, freshPlan.next);
6852
- p9.log.success(`Re-rendered ${cwd}/CLAUDE.md`);
6853
- } else {
6854
- p9.log.info("No re-render needed");
6855
- }
6876
+ const result = runRender(cwd, false);
6877
+ if (!result.ok) {
6878
+ p9.log.error(result.reason ?? "Render failed");
6879
+ p9.outro("Done (config actualizado, pero el render fall\xF3)");
6880
+ return;
6881
+ }
6882
+ const written = result.engineResult?.written ?? [];
6883
+ const skipped = result.engineResult?.skipped ?? [];
6884
+ if (skipped.length > 0) {
6885
+ p9.log.warn(`${skipped.length} archivo(s) con ediciones tuyas no se tocaron \u2014 'navori sync' para resolver`);
6886
+ }
6887
+ if (written.length > 0) {
6888
+ p9.log.success(`Re-rendered ${written.length} archivo(s) (CLAUDE.md + .claude/)`);
6889
+ } else {
6890
+ p9.log.info("No re-render needed");
6856
6891
  }
6857
6892
  p9.outro("Done");
6858
6893
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navori",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Multi-agent harness + SDD scaffolder for Claude Code and other AI engines",
5
5
  "type": "module",
6
6
  "bin": {