memorix 0.6.2 → 0.6.4

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.
@@ -611,6 +611,20 @@ function renderGraph(graph) {
611
611
  ctx.fillStyle = colors.edgeLabel;
612
612
  ctx.textAlign = 'center';
613
613
  ctx.fillText(edge.type, mx + ox, my + oy - 6);
614
+
615
+ // Flowing particle animation along active edges
616
+ const particleCount = 2;
617
+ for (let p = 0; p < particleCount; p++) {
618
+ const t = ((pulsePhase * 0.5 + p / particleCount) % 1);
619
+ // Quadratic bezier interpolation: source → control → target
620
+ const cx = mx + ox, cy = my + oy;
621
+ const px = (1 - t) * (1 - t) * edge.source.x + 2 * (1 - t) * t * cx + t * t * edge.target.x;
622
+ const py = (1 - t) * (1 - t) * edge.source.y + 2 * (1 - t) * t * cy + t * t * edge.target.y;
623
+ ctx.beginPath();
624
+ ctx.arc(px, py, 3, 0, Math.PI * 2);
625
+ ctx.fillStyle = (edge.source.color || '#00d4ff') + 'cc';
626
+ ctx.fill();
627
+ }
614
628
  }
615
629
  }
616
630
 
package/dist/index.js CHANGED
@@ -52,6 +52,9 @@ function sanitizeProjectId(projectId) {
52
52
  return projectId.replace(/\//g, "--").replace(/[<>:"|?*\\]/g, "_");
53
53
  }
54
54
  async function getProjectDataDir(projectId, baseDir) {
55
+ if (projectId === "__invalid__") {
56
+ throw new Error("Cannot create data directory for invalid project");
57
+ }
55
58
  const base = baseDir ?? DEFAULT_DATA_DIR;
56
59
  const dirName = sanitizeProjectId(projectId);
57
60
  const dataDir = path2.join(base, dirName);
@@ -613,7 +616,7 @@ __export(installers_exports, {
613
616
  });
614
617
  import * as fs3 from "fs/promises";
615
618
  import * as path5 from "path";
616
- import * as os2 from "os";
619
+ import * as os3 from "os";
617
620
  import { createRequire } from "module";
618
621
  function resolveHookCommand() {
619
622
  if (process.platform === "win32") {
@@ -718,7 +721,7 @@ function getProjectConfigPath(agent, projectRoot) {
718
721
  }
719
722
  }
720
723
  function getGlobalConfigPath(agent) {
721
- const home = os2.homedir();
724
+ const home = os3.homedir();
722
725
  switch (agent) {
723
726
  case "claude":
724
727
  case "copilot":
@@ -733,7 +736,7 @@ function getGlobalConfigPath(agent) {
733
736
  }
734
737
  async function detectInstalledAgents() {
735
738
  const agents = [];
736
- const home = os2.homedir();
739
+ const home = os3.homedir();
737
740
  const claudeDir = path5.join(home, ".claude");
738
741
  try {
739
742
  await fs3.access(claudeDir);
@@ -858,7 +861,7 @@ async function installAgentRules(agent, projectRoot) {
858
861
  rulesPath = path5.join(projectRoot, "AGENTS.md");
859
862
  break;
860
863
  case "kiro":
861
- rulesPath = path5.join(projectRoot, ".kiro", "rules", "memorix.md");
864
+ rulesPath = path5.join(projectRoot, ".kiro", "steering", "memorix.md");
862
865
  break;
863
866
  default:
864
867
  rulesPath = path5.join(projectRoot, ".agent", "rules", "memorix.md");
@@ -1965,6 +1968,7 @@ async function compactDetail(ids) {
1965
1968
  init_esm_shims();
1966
1969
  import { execSync } from "child_process";
1967
1970
  import { existsSync } from "fs";
1971
+ import os2 from "os";
1968
1972
  import path3 from "path";
1969
1973
  function detectProject(cwd) {
1970
1974
  const basePath = cwd ?? process.cwd();
@@ -1975,11 +1979,77 @@ function detectProject(cwd) {
1975
1979
  const name2 = id2.split("/").pop() ?? path3.basename(rootPath);
1976
1980
  return { id: id2, name: name2, gitRemote, rootPath };
1977
1981
  }
1982
+ if (!isValidProjectRoot(rootPath)) {
1983
+ console.error(`[memorix] Skipped invalid project root: ${rootPath}`);
1984
+ return { id: "__invalid__", name: "unknown", rootPath };
1985
+ }
1978
1986
  const name = path3.basename(rootPath);
1979
1987
  const id = `local/${name}`;
1980
1988
  console.error(`[memorix] Warning: no git remote found at ${rootPath}, using fallback projectId: ${id}`);
1981
1989
  return { id, name, rootPath };
1982
1990
  }
1991
+ function isValidProjectRoot(dirPath) {
1992
+ const resolved = path3.resolve(dirPath);
1993
+ const home = path3.resolve(os2.homedir());
1994
+ if (resolved === home) return false;
1995
+ if (resolved === path3.parse(resolved).root) return false;
1996
+ const basename2 = path3.basename(resolved).toLowerCase();
1997
+ const knownNonProjectDirs = /* @__PURE__ */ new Set([
1998
+ // IDE / editor config dirs
1999
+ ".vscode",
2000
+ ".cursor",
2001
+ ".windsurf",
2002
+ ".kiro",
2003
+ ".codex",
2004
+ ".gemini",
2005
+ ".claude",
2006
+ ".github",
2007
+ ".git",
2008
+ // OS / system dirs
2009
+ "desktop",
2010
+ "documents",
2011
+ "downloads",
2012
+ "pictures",
2013
+ "videos",
2014
+ "music",
2015
+ "appdata",
2016
+ "application data",
2017
+ "library",
2018
+ // Package manager / tool dirs
2019
+ "node_modules",
2020
+ ".npm",
2021
+ ".yarn",
2022
+ ".pnpm-store",
2023
+ ".config",
2024
+ ".local",
2025
+ ".cache",
2026
+ ".ssh",
2027
+ ".memorix"
2028
+ ]);
2029
+ if (knownNonProjectDirs.has(basename2)) {
2030
+ const parent = path3.resolve(path3.dirname(resolved));
2031
+ if (parent === home || parent === path3.parse(parent).root) {
2032
+ return false;
2033
+ }
2034
+ }
2035
+ const projectIndicators = [
2036
+ "package.json",
2037
+ "Cargo.toml",
2038
+ "go.mod",
2039
+ "pyproject.toml",
2040
+ "setup.py",
2041
+ "pom.xml",
2042
+ "build.gradle",
2043
+ "Makefile",
2044
+ "CMakeLists.txt",
2045
+ "composer.json",
2046
+ "Gemfile",
2047
+ ".git",
2048
+ "README.md",
2049
+ "README"
2050
+ ];
2051
+ return projectIndicators.some((f) => existsSync(path3.join(resolved, f)));
2052
+ }
1983
2053
  function findPackageRoot(cwd) {
1984
2054
  let dir = path3.resolve(cwd);
1985
2055
  const root = path3.parse(dir).root;