gnosys 5.9.4 → 5.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +31 -777
  2. package/dist/cli.js +114 -4
  3. package/dist/cli.js.map +1 -1
  4. package/dist/lib/dashboard.d.ts.map +1 -1
  5. package/dist/lib/dashboard.js +5 -1
  6. package/dist/lib/dashboard.js.map +1 -1
  7. package/dist/lib/db.d.ts +24 -0
  8. package/dist/lib/db.d.ts.map +1 -1
  9. package/dist/lib/db.js +122 -8
  10. package/dist/lib/db.js.map +1 -1
  11. package/dist/lib/dream.js +1 -1
  12. package/dist/lib/dream.js.map +1 -1
  13. package/dist/lib/federated.d.ts +2 -1
  14. package/dist/lib/federated.d.ts.map +1 -1
  15. package/dist/lib/federated.js +6 -3
  16. package/dist/lib/federated.js.map +1 -1
  17. package/dist/lib/ingest.js +1 -1
  18. package/dist/lib/ingest.js.map +1 -1
  19. package/dist/lib/machineConfig.d.ts +87 -0
  20. package/dist/lib/machineConfig.d.ts.map +1 -0
  21. package/dist/lib/machineConfig.js +146 -0
  22. package/dist/lib/machineConfig.js.map +1 -0
  23. package/dist/lib/machineMigrate.d.ts +39 -0
  24. package/dist/lib/machineMigrate.d.ts.map +1 -0
  25. package/dist/lib/machineMigrate.js +103 -0
  26. package/dist/lib/machineMigrate.js.map +1 -0
  27. package/dist/lib/paths.d.ts +11 -0
  28. package/dist/lib/paths.d.ts.map +1 -1
  29. package/dist/lib/paths.js +13 -0
  30. package/dist/lib/paths.js.map +1 -1
  31. package/dist/lib/portfolio.d.ts.map +1 -1
  32. package/dist/lib/portfolio.js +10 -2
  33. package/dist/lib/portfolio.js.map +1 -1
  34. package/dist/lib/projectPaths.d.ts +60 -0
  35. package/dist/lib/projectPaths.d.ts.map +1 -0
  36. package/dist/lib/projectPaths.js +100 -0
  37. package/dist/lib/projectPaths.js.map +1 -0
  38. package/dist/lib/projectScan.d.ts +40 -0
  39. package/dist/lib/projectScan.d.ts.map +1 -0
  40. package/dist/lib/projectScan.js +97 -0
  41. package/dist/lib/projectScan.js.map +1 -0
  42. package/dist/lib/remote.d.ts +5 -0
  43. package/dist/lib/remote.d.ts.map +1 -1
  44. package/dist/lib/remote.js +29 -5
  45. package/dist/lib/remote.js.map +1 -1
  46. package/dist/lib/setup.js +1 -1
  47. package/dist/lib/setup.js.map +1 -1
  48. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4715,6 +4715,101 @@ program
4715
4715
  function isDeadProjectDir(dir) {
4716
4716
  return !existsSync(dir);
4717
4717
  }
4718
+ const machineCmd = program
4719
+ .command("machine")
4720
+ .description("Manage this machine's local config (machine.json: machineId, roots, remote)");
4721
+ machineCmd
4722
+ .command("show")
4723
+ .description("Show this machine's machine.json")
4724
+ .option("--json", "Output as JSON")
4725
+ .action(async (opts) => {
4726
+ const { readMachineConfig } = await import("./lib/machineConfig.js");
4727
+ const { getMachineConfigPath } = await import("./lib/paths.js");
4728
+ const cfg = readMachineConfig();
4729
+ if (!cfg) {
4730
+ console.log(`No machine.json yet (${getMachineConfigPath()}).`);
4731
+ console.log("Run 'gnosys machine migrate' (existing setup) or 'gnosys scan' to create it.");
4732
+ return;
4733
+ }
4734
+ outputResult(!!opts.json, cfg, () => {
4735
+ console.log(`machine.json: ${getMachineConfigPath()}`);
4736
+ console.log(` machineId: ${cfg.machineId}`);
4737
+ console.log(` hostname: ${cfg.hostname}`);
4738
+ console.log(` roots: ${JSON.stringify(cfg.roots)}`);
4739
+ console.log(` remote: ${cfg.remote.enabled ? (cfg.remote.path ?? "(enabled, no path)") : "(disabled)"}`);
4740
+ });
4741
+ });
4742
+ machineCmd
4743
+ .command("migrate")
4744
+ .description("Move machine-local config (machineId, remote) out of the synced DB into machine.json, set roots, and scan")
4745
+ .option("--root <dir>", "Set the 'dev' root for this machine (default: derived from the registry)")
4746
+ .option("--no-scan", "Skip the project scan after migrating")
4747
+ .action(async (opts) => {
4748
+ const { migrateMachine } = await import("./lib/machineMigrate.js");
4749
+ const { getMachineConfigPath } = await import("./lib/paths.js");
4750
+ const db = GnosysDB.openLocal();
4751
+ if (!db.isAvailable()) {
4752
+ console.error("Central DB not available (better-sqlite3 missing).");
4753
+ process.exit(1);
4754
+ }
4755
+ const res = await migrateMachine(db, { root: opts.root, scan: opts.scan });
4756
+ db.close();
4757
+ console.log(`✓ machine.json written: ${getMachineConfigPath()}`);
4758
+ const idNote = res.adoptedMachineId
4759
+ ? " (adopted from synced meta)"
4760
+ : res.regeneratedMachineId ? " (regenerated)" : "";
4761
+ console.log(` machineId: ${res.machineId}${idNote}`);
4762
+ if (res.adoptedRemotePath) {
4763
+ console.log(" remote: adopted remote_path from synced meta (removed from shared DB)");
4764
+ }
4765
+ console.log(` roots: ${JSON.stringify(res.rootsConfigured)}`);
4766
+ if (res.scan) {
4767
+ console.log(` scanned ${res.scan.entries.length} project(s):`);
4768
+ for (const e of res.scan.entries)
4769
+ console.log(` ${e.name} [${e.mode}] ${e.absPath}`);
4770
+ }
4771
+ else {
4772
+ console.log(" (scan skipped — set a root in machine.json, then run 'gnosys scan')");
4773
+ }
4774
+ });
4775
+ program
4776
+ .command("scan")
4777
+ .description("Discover projects under this machine's roots (machine.json) and record their machine-portable locations")
4778
+ .option("--json", "Output as JSON")
4779
+ .action(async (opts) => {
4780
+ const { ensureMachineConfig } = await import("./lib/machineConfig.js");
4781
+ const { getMachineConfigPath } = await import("./lib/paths.js");
4782
+ const { scanProjects } = await import("./lib/projectScan.js");
4783
+ const ens = ensureMachineConfig();
4784
+ const machine = ens.config;
4785
+ if (Object.keys(machine.roots).length === 0) {
4786
+ console.error("No project roots configured for this machine.");
4787
+ console.error(`Add roots to ${getMachineConfigPath()}, e.g.`);
4788
+ console.error(' { "roots": { "dev": "/Users/edward/MSDev/projects" } }');
4789
+ process.exit(1);
4790
+ }
4791
+ const db = GnosysDB.openCentral();
4792
+ if (!db.isAvailable()) {
4793
+ console.error("Central DB not available (better-sqlite3 missing).");
4794
+ process.exit(1);
4795
+ }
4796
+ const result = await scanProjects(db, machine);
4797
+ db.close();
4798
+ outputResult(!!opts.json, {
4799
+ machineId: machine.machineId,
4800
+ roots: result.roots,
4801
+ count: result.entries.length,
4802
+ entries: result.entries,
4803
+ }, () => {
4804
+ if (ens.regenerated) {
4805
+ console.log("⚠ machine.json hostname mismatch — regenerated machineId for this machine.\n");
4806
+ }
4807
+ console.log(`Scanned ${result.roots.length} root(s); registered ${result.entries.length} project(s):`);
4808
+ for (const e of result.entries) {
4809
+ console.log(` ${e.name} [${e.mode}] ${e.absPath}`);
4810
+ }
4811
+ });
4812
+ });
4718
4813
  program
4719
4814
  .command("projects")
4720
4815
  .description("List registered projects from the central DB")
@@ -4732,6 +4827,16 @@ program
4732
4827
  process.exit(1);
4733
4828
  }
4734
4829
  const allProjects = centralDb.getAllProjects();
4830
+ // v5.11: resolve each project's path for THIS machine (machine.json),
4831
+ // falling back to working_directory when machine.json is absent.
4832
+ const { readMachineConfig } = await import("./lib/machineConfig.js");
4833
+ const { effectiveProjectPath } = await import("./lib/projectPaths.js");
4834
+ const machine = readMachineConfig();
4835
+ const resolvedDirOf = (p) => effectiveProjectPath(centralDb, p, machine);
4836
+ const isNotHere = (p) => {
4837
+ const ep = resolvedDirOf(p);
4838
+ return ep === null || !existsSync(ep);
4839
+ };
4735
4840
  if (opts.prune) {
4736
4841
  // Find dead projects first — never just delete without showing
4737
4842
  // them. v5.7.0 adds confirmation by default; --yes skips for
@@ -4776,10 +4881,10 @@ program
4776
4881
  });
4777
4882
  return;
4778
4883
  }
4779
- // Normal listing — filter dead projects by default
4884
+ // Normal listing — filter dead / not-on-this-machine projects by default
4780
4885
  const visibleProjects = opts.all
4781
4886
  ? allProjects
4782
- : allProjects.filter((p) => !isDeadProjectDir(p.working_directory));
4887
+ : allProjects.filter((p) => !isNotHere(p));
4783
4888
  if (visibleProjects.length === 0) {
4784
4889
  const deadCount = allProjects.length;
4785
4890
  outputResult(!!opts.json, {
@@ -4800,6 +4905,7 @@ program
4800
4905
  }
4801
4906
  const projectData = visibleProjects.map((p) => ({
4802
4907
  ...p,
4908
+ resolvedDir: resolvedDirOf(p) ?? "(not on this machine)",
4803
4909
  memoryCount: centralDb.getMemoriesByProject(p.id).length,
4804
4910
  }));
4805
4911
  const deadCount = allProjects.length - visibleProjects.length;
@@ -4816,7 +4922,7 @@ program
4816
4922
  for (const p of projectData) {
4817
4923
  console.log(` ${p.name}`);
4818
4924
  console.log(` ID: ${p.id}`);
4819
- console.log(` Directory: ${p.working_directory}`);
4925
+ console.log(` Directory: ${p.resolvedDir}`);
4820
4926
  console.log(` Memories: ${p.memoryCount}`);
4821
4927
  console.log(` Created: ${p.created}`);
4822
4928
  console.log();
@@ -6416,7 +6522,11 @@ if (!isTestEnv()) {
6416
6522
  const centralDb = GnosysDB.openCentral();
6417
6523
  if (centralDb.isAvailable()) {
6418
6524
  const lastVersion = centralDb.getMeta("app_version");
6419
- const currentVersion = pkg.version;
6525
+ // GNOSYS_FORCE_VERSION lets the upgrade-nag tests pin a synthetic
6526
+ // "running" version independent of the real release number, so a .0
6527
+ // minor release can't break the patch/minor scenarios. Production
6528
+ // always falls through to pkg.version.
6529
+ const currentVersion = process.env.GNOSYS_FORCE_VERSION || pkg.version;
6420
6530
  const isUpgradeCmd = process.argv.slice(2).some(a => a === "upgrade");
6421
6531
  const isSetupSyncCmd = process.argv.slice(2).join(" ").includes("setup sync-projects");
6422
6532
  // CRITICAL: `serve` writes JSON-RPC to stdout for MCP transport. Any