ctxloom-pro 1.7.0 → 1.7.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.
package/README.md CHANGED
@@ -69,7 +69,7 @@ The full first-run flow is **one install + one trial + one init per project.** E
69
69
  npm install -g ctxloom-pro
70
70
  ```
71
71
 
72
- > **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.0`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
72
+ > **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.1`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
73
73
 
74
74
  ### 2 — Start your free trial (once per email)
75
75
 
@@ -383,7 +383,7 @@ jobs:
383
383
  # Exact pin (not `@^1`) so future CLI releases that add/remove MCP
384
384
  # tools don't silently desync your reviewer-agent specs. Bump on
385
385
  # every release; see CHANGELOG.md for the live version table.
386
- - run: npm install -g ctxloom-pro@1.7.0
386
+ - run: npm install -g ctxloom-pro@1.7.1
387
387
  - run: ctxloom index
388
388
  - run: ctxloom rules check --json
389
389
  ```
@@ -2909,6 +2909,26 @@ var CallGraphIndex = class _CallGraphIndex {
2909
2909
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
2910
2910
  var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
2911
2911
  var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
2912
+ var CTXLOOM_VERSION = "1.7.2".length > 0 ? "1.7.2" : "dev";
2913
+ var SNAPSHOT_SCHEMA_VERSION = 2;
2914
+ function compareCtxloomVersions(snapshotVer, currentVer) {
2915
+ if (snapshotVer === currentVer) return "same";
2916
+ if (snapshotVer === "dev") return "unknown";
2917
+ if (currentVer === "dev") return "older";
2918
+ const parse = (v) => {
2919
+ const parts = v.split(".").map((s) => Number.parseInt(s, 10));
2920
+ if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;
2921
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
2922
+ };
2923
+ const a = parse(snapshotVer);
2924
+ const b = parse(currentVer);
2925
+ if (!a || !b) return "unknown";
2926
+ for (let i = 0; i < 3; i++) {
2927
+ if (a[i] < b[i]) return "older";
2928
+ if (a[i] > b[i]) return "newer";
2929
+ }
2930
+ return "same";
2931
+ }
2912
2932
  var DependencyGraph = class {
2913
2933
  /** file → set of files it imports (forward edges) */
2914
2934
  forwardEdges = /* @__PURE__ */ new Map();
@@ -3399,7 +3419,12 @@ var DependencyGraph = class {
3399
3419
  fs7.mkdirSync(this.snapshotDir, { recursive: true });
3400
3420
  }
3401
3421
  const data = {
3402
- version: 1,
3422
+ version: SNAPSHOT_SCHEMA_VERSION,
3423
+ // Build-time ctxloom version. The loader uses this to invalidate
3424
+ // snapshots written by an older binary (e.g. one that pre-dated
3425
+ // absolute Python import resolution) so users don't get stuck with
3426
+ // an empty graph after `npm i -g ctxloom-pro@latest`.
3427
+ ctxloomVersion: CTXLOOM_VERSION,
3403
3428
  builtAt: Date.now(),
3404
3429
  fileCount: this.forwardEdges.size,
3405
3430
  forwardEdges: Object.fromEntries(
@@ -3425,6 +3450,7 @@ var DependencyGraph = class {
3425
3450
  if (!data || typeof data !== "object") return false;
3426
3451
  const d = data;
3427
3452
  if (typeof d["version"] !== "number") return false;
3453
+ if (d["ctxloomVersion"] !== void 0 && typeof d["ctxloomVersion"] !== "string") return false;
3428
3454
  if (!d["forwardEdges"] || typeof d["forwardEdges"] !== "object") return false;
3429
3455
  if (!d["reverseEdges"] || typeof d["reverseEdges"] !== "object") return false;
3430
3456
  for (const v of Object.values(d["forwardEdges"])) {
@@ -3445,6 +3471,27 @@ var DependencyGraph = class {
3445
3471
  return false;
3446
3472
  }
3447
3473
  const data = raw;
3474
+ const snapshotVer = data.ctxloomVersion;
3475
+ if (snapshotVer === void 0) {
3476
+ logger.info("Graph snapshot has no ctxloomVersion (legacy v1), rebuilding under current ctxloom", {
3477
+ current: CTXLOOM_VERSION
3478
+ });
3479
+ return false;
3480
+ }
3481
+ const cmp = compareCtxloomVersions(snapshotVer, CTXLOOM_VERSION);
3482
+ if (cmp === "older") {
3483
+ logger.info("Graph snapshot from older ctxloom, rebuilding", {
3484
+ snapshot: snapshotVer,
3485
+ current: CTXLOOM_VERSION
3486
+ });
3487
+ return false;
3488
+ }
3489
+ if (cmp === "newer") {
3490
+ logger.warn("Graph snapshot from newer ctxloom than installed binary; reusing but watch for shape drift", {
3491
+ snapshot: snapshotVer,
3492
+ current: CTXLOOM_VERSION
3493
+ });
3494
+ }
3448
3495
  if (currentFileCount !== void 0 && data.fileCount !== void 0) {
3449
3496
  if (data.fileCount !== currentFileCount) {
3450
3497
  logger.info("Graph snapshot stale, rebuilding", { prev: data.fileCount, curr: currentFileCount });
@@ -12094,7 +12141,7 @@ function resolveTelemetryLevel() {
12094
12141
  }
12095
12142
  var TELEMETRY_LEVEL = resolveTelemetryLevel();
12096
12143
  var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
12097
- var CTXLOOM_VERSION = "1.7.0".length > 0 ? "1.7.0" : "dev";
12144
+ var CTXLOOM_VERSION2 = "1.7.2".length > 0 ? "1.7.2" : "dev";
12098
12145
  var POSTHOG_HOST = "https://eu.i.posthog.com";
12099
12146
  var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
12100
12147
  var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
@@ -12135,7 +12182,7 @@ async function sendPostHog(event, distinctId, props) {
12135
12182
  event,
12136
12183
  properties: {
12137
12184
  $lib: "ctxloom-cli",
12138
- release: CTXLOOM_VERSION,
12185
+ release: CTXLOOM_VERSION2,
12139
12186
  ...props
12140
12187
  }
12141
12188
  }),
@@ -12155,7 +12202,7 @@ async function sendAlias(newId, oldAlias) {
12155
12202
  event: "$create_alias",
12156
12203
  properties: {
12157
12204
  $lib: "ctxloom-cli",
12158
- release: CTXLOOM_VERSION,
12205
+ release: CTXLOOM_VERSION2,
12159
12206
  alias: oldAlias
12160
12207
  }
12161
12208
  }),
@@ -12198,7 +12245,7 @@ async function sendSentry(err, context) {
12198
12245
  ]
12199
12246
  },
12200
12247
  extra: context,
12201
- tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION }
12248
+ tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION2 }
12202
12249
  }),
12203
12250
  signal: AbortSignal.timeout(4e3)
12204
12251
  });
@@ -2705,6 +2705,26 @@ var CallGraphIndex = class _CallGraphIndex {
2705
2705
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
2706
2706
  var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
2707
2707
  var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
2708
+ var CTXLOOM_VERSION = "1.7.2".length > 0 ? "1.7.2" : "dev";
2709
+ var SNAPSHOT_SCHEMA_VERSION = 2;
2710
+ function compareCtxloomVersions(snapshotVer, currentVer) {
2711
+ if (snapshotVer === currentVer) return "same";
2712
+ if (snapshotVer === "dev") return "unknown";
2713
+ if (currentVer === "dev") return "older";
2714
+ const parse = (v) => {
2715
+ const parts = v.split(".").map((s) => Number.parseInt(s, 10));
2716
+ if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;
2717
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
2718
+ };
2719
+ const a = parse(snapshotVer);
2720
+ const b = parse(currentVer);
2721
+ if (!a || !b) return "unknown";
2722
+ for (let i = 0; i < 3; i++) {
2723
+ if (a[i] < b[i]) return "older";
2724
+ if (a[i] > b[i]) return "newer";
2725
+ }
2726
+ return "same";
2727
+ }
2708
2728
  var DependencyGraph = class {
2709
2729
  /** file → set of files it imports (forward edges) */
2710
2730
  forwardEdges = /* @__PURE__ */ new Map();
@@ -3195,7 +3215,12 @@ var DependencyGraph = class {
3195
3215
  fs6.mkdirSync(this.snapshotDir, { recursive: true });
3196
3216
  }
3197
3217
  const data = {
3198
- version: 1,
3218
+ version: SNAPSHOT_SCHEMA_VERSION,
3219
+ // Build-time ctxloom version. The loader uses this to invalidate
3220
+ // snapshots written by an older binary (e.g. one that pre-dated
3221
+ // absolute Python import resolution) so users don't get stuck with
3222
+ // an empty graph after `npm i -g ctxloom-pro@latest`.
3223
+ ctxloomVersion: CTXLOOM_VERSION,
3199
3224
  builtAt: Date.now(),
3200
3225
  fileCount: this.forwardEdges.size,
3201
3226
  forwardEdges: Object.fromEntries(
@@ -3221,6 +3246,7 @@ var DependencyGraph = class {
3221
3246
  if (!data || typeof data !== "object") return false;
3222
3247
  const d = data;
3223
3248
  if (typeof d["version"] !== "number") return false;
3249
+ if (d["ctxloomVersion"] !== void 0 && typeof d["ctxloomVersion"] !== "string") return false;
3224
3250
  if (!d["forwardEdges"] || typeof d["forwardEdges"] !== "object") return false;
3225
3251
  if (!d["reverseEdges"] || typeof d["reverseEdges"] !== "object") return false;
3226
3252
  for (const v of Object.values(d["forwardEdges"])) {
@@ -3241,6 +3267,27 @@ var DependencyGraph = class {
3241
3267
  return false;
3242
3268
  }
3243
3269
  const data = raw;
3270
+ const snapshotVer = data.ctxloomVersion;
3271
+ if (snapshotVer === void 0) {
3272
+ logger.info("Graph snapshot has no ctxloomVersion (legacy v1), rebuilding under current ctxloom", {
3273
+ current: CTXLOOM_VERSION
3274
+ });
3275
+ return false;
3276
+ }
3277
+ const cmp = compareCtxloomVersions(snapshotVer, CTXLOOM_VERSION);
3278
+ if (cmp === "older") {
3279
+ logger.info("Graph snapshot from older ctxloom, rebuilding", {
3280
+ snapshot: snapshotVer,
3281
+ current: CTXLOOM_VERSION
3282
+ });
3283
+ return false;
3284
+ }
3285
+ if (cmp === "newer") {
3286
+ logger.warn("Graph snapshot from newer ctxloom than installed binary; reusing but watch for shape drift", {
3287
+ snapshot: snapshotVer,
3288
+ current: CTXLOOM_VERSION
3289
+ });
3290
+ }
3244
3291
  if (currentFileCount !== void 0 && data.fileCount !== void 0) {
3245
3292
  if (data.fileCount !== currentFileCount) {
3246
3293
  logger.info("Graph snapshot stale, rebuilding", { prev: data.fileCount, curr: currentFileCount });
@@ -10912,7 +10959,7 @@ var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
10912
10959
  function getTelemetryLevel() {
10913
10960
  return TELEMETRY_LEVEL;
10914
10961
  }
10915
- var CTXLOOM_VERSION = "1.7.0".length > 0 ? "1.7.0" : "dev";
10962
+ var CTXLOOM_VERSION2 = "1.7.2".length > 0 ? "1.7.2" : "dev";
10916
10963
  var POSTHOG_HOST = "https://eu.i.posthog.com";
10917
10964
  var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
10918
10965
  var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
@@ -10953,7 +11000,7 @@ async function sendPostHog(event, distinctId, props) {
10953
11000
  event,
10954
11001
  properties: {
10955
11002
  $lib: "ctxloom-cli",
10956
- release: CTXLOOM_VERSION,
11003
+ release: CTXLOOM_VERSION2,
10957
11004
  ...props
10958
11005
  }
10959
11006
  }),
@@ -10973,7 +11020,7 @@ async function sendAlias(newId, oldAlias) {
10973
11020
  event: "$create_alias",
10974
11021
  properties: {
10975
11022
  $lib: "ctxloom-cli",
10976
- release: CTXLOOM_VERSION,
11023
+ release: CTXLOOM_VERSION2,
10977
11024
  alias: oldAlias
10978
11025
  }
10979
11026
  }),
@@ -11016,7 +11063,7 @@ async function sendSentry(err, context) {
11016
11063
  ]
11017
11064
  },
11018
11065
  extra: context,
11019
- tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION }
11066
+ tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION2 }
11020
11067
  }),
11021
11068
  signal: AbortSignal.timeout(4e3)
11022
11069
  });
@@ -12588,4 +12635,4 @@ export {
12588
12635
  skillFilePath,
12589
12636
  installHarness
12590
12637
  };
12591
- //# sourceMappingURL=chunk-FFCLVZCO.js.map
12638
+ //# sourceMappingURL=chunk-QL5UJTQL.js.map
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ import {
47
47
  validateDefaultRoot,
48
48
  wrapWithIndexingEnvelope,
49
49
  writeCODEOWNERS
50
- } from "./chunk-FFCLVZCO.js";
50
+ } from "./chunk-QL5UJTQL.js";
51
51
  import {
52
52
  addCtxloomToConfig,
53
53
  detectInstalledClients
@@ -631,7 +631,7 @@ jobs:
631
631
  with:
632
632
  fetch-depth: 0 # required: pr-bot reads git history for co-change overlay
633
633
 
634
- - uses: kodiii/ctxloom/apps/pr-bot@${ref}
634
+ - uses: kodiii/ctxloom-pr-bot@${ref}
635
635
  `;
636
636
  }
637
637
  function installPrBotWorkflow(opts = {}) {
@@ -1039,7 +1039,7 @@ try {
1039
1039
  } catch {
1040
1040
  }
1041
1041
  var args = process.argv.slice(2);
1042
- var ctxloomVersion = "1.7.0".length > 0 ? "1.7.0" : "dev";
1042
+ var ctxloomVersion = "1.7.2".length > 0 ? "1.7.2" : "dev";
1043
1043
  if (args.includes("--version") || args.includes("-v")) {
1044
1044
  process.stdout.write(`ctxloom ${ctxloomVersion}
1045
1045
  `);
@@ -1112,7 +1112,7 @@ async function checkLicense() {
1112
1112
  if (command !== void 0 && LICENSE_GATE_BYPASS_COMMANDS.has(command)) return;
1113
1113
  const ciKey = process.env["CTXLOOM_LICENSE_KEY"];
1114
1114
  if (ciKey) {
1115
- const { ApiClient } = await import("./src-QAYZWPSL.js");
1115
+ const { ApiClient } = await import("./src-GTPLDFUS.js");
1116
1116
  const client = new ApiClient(process.env["CTXLOOM_API_BASE"]);
1117
1117
  try {
1118
1118
  const result = await client.validate(ciKey, "ci-ephemeral");
@@ -1447,7 +1447,7 @@ async function main() {
1447
1447
  process.stdout.write(success(`Created ${result.path}`));
1448
1448
  process.stdout.write(` ${style.dim(`Default branch: ${result.defaultBranch}`)}
1449
1449
  `);
1450
- process.stdout.write(` ${style.dim(`Pinned to: kodiii/ctxloom/apps/pr-bot@${ref}`)}
1450
+ process.stdout.write(` ${style.dim(`Pinned to: kodiii/ctxloom-pr-bot@${ref}`)}
1451
1451
 
1452
1452
  `);
1453
1453
  process.stdout.write(
@@ -1490,7 +1490,7 @@ async function main() {
1490
1490
  }
1491
1491
  if (!skipHarness) {
1492
1492
  process.stdout.write("\n");
1493
- const { installHarness } = await import("./src-QAYZWPSL.js");
1493
+ const { installHarness } = await import("./src-GTPLDFUS.js");
1494
1494
  const h = installHarness({ cwd: initRoot, dryRun, force, extraHosts });
1495
1495
  const harnessFiles = [
1496
1496
  h.claudeMd,
@@ -1553,7 +1553,7 @@ async function main() {
1553
1553
  process.exit(1);
1554
1554
  }
1555
1555
  if (alias !== void 0) {
1556
- const { validateAlias } = await import("./src-QAYZWPSL.js");
1556
+ const { validateAlias } = await import("./src-GTPLDFUS.js");
1557
1557
  const v = validateAlias(alias);
1558
1558
  if (!v.ok) {
1559
1559
  console.error(`[ctxloom] Invalid alias: ${v.reason}`);
@@ -1912,7 +1912,7 @@ Suggested reviewers for ${files.length} file(s):`);
1912
1912
  process.stderr.write("[ctxloom] --limit must be a non-negative integer (0 for unlimited)\n");
1913
1913
  process.exit(2);
1914
1914
  }
1915
- const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-QAYZWPSL.js");
1915
+ const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-GTPLDFUS.js");
1916
1916
  let config;
1917
1917
  try {
1918
1918
  config = await loadRulesConfig(root);
@@ -1936,7 +1936,7 @@ Suggested reviewers for ${files.length} file(s):`);
1936
1936
  }
1937
1937
  let graph;
1938
1938
  if (useSnapshot) {
1939
- const { DependencyGraph: DG } = await import("./src-QAYZWPSL.js");
1939
+ const { DependencyGraph: DG } = await import("./src-GTPLDFUS.js");
1940
1940
  graph = new DG();
1941
1941
  const loaded = await graph.loadSnapshotOnly(root);
1942
1942
  if (!loaded) {
@@ -1945,7 +1945,7 @@ Suggested reviewers for ${files.length} file(s):`);
1945
1945
  }
1946
1946
  } else {
1947
1947
  process.stderr.write("[ctxloom] Building dependency graph...\n");
1948
- const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-QAYZWPSL.js");
1948
+ const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-GTPLDFUS.js");
1949
1949
  let parser;
1950
1950
  try {
1951
1951
  parser = new ASTParser2();
@@ -132,7 +132,7 @@ import {
132
132
  wrapBlock,
133
133
  wrapWithIndexingEnvelope,
134
134
  writeCODEOWNERS
135
- } from "./chunk-FFCLVZCO.js";
135
+ } from "./chunk-QL5UJTQL.js";
136
136
  import {
137
137
  VectorStore
138
138
  } from "./chunk-7S2ELKNU.js";
@@ -300,4 +300,4 @@ export {
300
300
  wrapWithIndexingEnvelope,
301
301
  writeCODEOWNERS
302
302
  };
303
- //# sourceMappingURL=src-QAYZWPSL.js.map
303
+ //# sourceMappingURL=src-GTPLDFUS.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxloom-pro",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "ctxloom — The Universal Code Context Engine. A local-first MCP server providing intelligent code context via hybrid Vector + AST + Graph search with Skeletonization (92% token reduction).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",