@massu/core 1.8.0 → 1.9.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.
package/dist/cli.js CHANGED
@@ -8045,41 +8045,41 @@ var require_queue = __commonJS({
8045
8045
  queue.drained = drained;
8046
8046
  return queue;
8047
8047
  function push(value) {
8048
- var p19 = new Promise(function(resolve38, reject) {
8048
+ var p19 = new Promise(function(resolve40, reject) {
8049
8049
  pushCb(value, function(err, result) {
8050
8050
  if (err) {
8051
8051
  reject(err);
8052
8052
  return;
8053
8053
  }
8054
- resolve38(result);
8054
+ resolve40(result);
8055
8055
  });
8056
8056
  });
8057
8057
  p19.catch(noop);
8058
8058
  return p19;
8059
8059
  }
8060
8060
  function unshift(value) {
8061
- var p19 = new Promise(function(resolve38, reject) {
8061
+ var p19 = new Promise(function(resolve40, reject) {
8062
8062
  unshiftCb(value, function(err, result) {
8063
8063
  if (err) {
8064
8064
  reject(err);
8065
8065
  return;
8066
8066
  }
8067
- resolve38(result);
8067
+ resolve40(result);
8068
8068
  });
8069
8069
  });
8070
8070
  p19.catch(noop);
8071
8071
  return p19;
8072
8072
  }
8073
8073
  function drained() {
8074
- var p19 = new Promise(function(resolve38) {
8074
+ var p19 = new Promise(function(resolve40) {
8075
8075
  process.nextTick(function() {
8076
8076
  if (queue.idle()) {
8077
- resolve38();
8077
+ resolve40();
8078
8078
  } else {
8079
8079
  var previousDrain = queue.drain;
8080
8080
  queue.drain = function() {
8081
8081
  if (typeof previousDrain === "function") previousDrain();
8082
- resolve38();
8082
+ resolve40();
8083
8083
  queue.drain = previousDrain;
8084
8084
  };
8085
8085
  }
@@ -8565,9 +8565,9 @@ var require_stream3 = __commonJS({
8565
8565
  });
8566
8566
  }
8567
8567
  _getStat(filepath) {
8568
- return new Promise((resolve38, reject) => {
8568
+ return new Promise((resolve40, reject) => {
8569
8569
  this._stat(filepath, this._fsStatSettings, (error, stats) => {
8570
- return error === null ? resolve38(stats) : reject(error);
8570
+ return error === null ? resolve40(stats) : reject(error);
8571
8571
  });
8572
8572
  });
8573
8573
  }
@@ -8591,10 +8591,10 @@ var require_async5 = __commonJS({
8591
8591
  this._readerStream = new stream_1.default(this._settings);
8592
8592
  }
8593
8593
  dynamic(root, options) {
8594
- return new Promise((resolve38, reject) => {
8594
+ return new Promise((resolve40, reject) => {
8595
8595
  this._walkAsync(root, options, (error, entries) => {
8596
8596
  if (error === null) {
8597
- resolve38(entries);
8597
+ resolve40(entries);
8598
8598
  } else {
8599
8599
  reject(error);
8600
8600
  }
@@ -8604,10 +8604,10 @@ var require_async5 = __commonJS({
8604
8604
  async static(patterns, options) {
8605
8605
  const entries = [];
8606
8606
  const stream = this._readerStream.static(patterns, options);
8607
- return new Promise((resolve38, reject) => {
8607
+ return new Promise((resolve40, reject) => {
8608
8608
  stream.once("error", reject);
8609
8609
  stream.on("data", (entry) => entries.push(entry));
8610
- stream.once("end", () => resolve38(entries));
8610
+ stream.once("end", () => resolve40(entries));
8611
8611
  });
8612
8612
  }
8613
8613
  };
@@ -14883,13 +14883,252 @@ var init_permissions2 = __esm({
14883
14883
  }
14884
14884
  });
14885
14885
 
14886
+ // src/changelog-generator.ts
14887
+ import { existsSync as existsSync13, readFileSync as readFileSync13, readdirSync as readdirSync12 } from "fs";
14888
+ import { resolve as resolve10 } from "path";
14889
+ function parseCommitsForPlanTokens(subjects) {
14890
+ const tokens = /* @__PURE__ */ new Set();
14891
+ const maintenance = [];
14892
+ for (const subject of subjects) {
14893
+ const m3 = subject.match(PLAN_TOKEN_RE);
14894
+ if (m3 && m3[2]) {
14895
+ tokens.add(m3[2]);
14896
+ } else {
14897
+ maintenance.push(subject);
14898
+ }
14899
+ }
14900
+ return { tokens, maintenance };
14901
+ }
14902
+ function loadPlanSummaries(tokens, planDir) {
14903
+ const result = /* @__PURE__ */ new Map();
14904
+ if (tokens.size === 0) return result;
14905
+ if (!existsSync13(planDir)) {
14906
+ throw new Error(`Plan directory does not exist: ${planDir}`);
14907
+ }
14908
+ const files = readdirSync12(planDir).filter((f2) => f2.endsWith(".md"));
14909
+ for (const token of tokens) {
14910
+ let matchedFile = null;
14911
+ let content = "";
14912
+ for (const file of files) {
14913
+ const path = resolve10(planDir, file);
14914
+ const text18 = readFileSync13(path, "utf-8");
14915
+ const tokenRe = new RegExp(
14916
+ `^\\*\\*Plan Token\\*\\*:\\s*\`?${token.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")}\`?(\\s|$)`,
14917
+ "m"
14918
+ );
14919
+ if (tokenRe.test(text18)) {
14920
+ matchedFile = file;
14921
+ content = text18;
14922
+ break;
14923
+ }
14924
+ }
14925
+ if (!matchedFile) {
14926
+ throw new MissingPlanFileError(token);
14927
+ }
14928
+ const titleMatch = content.match(/^# (.+)$/m);
14929
+ const title = titleMatch ? titleMatch[1].trim() : token;
14930
+ const sectionRe = /^## Changelog Summary\s*\n([\s\S]*?)(?=\n## |\n---|\n# |$)/m;
14931
+ const sectionMatch = content.match(sectionRe);
14932
+ if (!sectionMatch || !sectionMatch[1].trim()) {
14933
+ throw new MissingChangelogSummaryError(token, matchedFile);
14934
+ }
14935
+ const summary = sectionMatch[1].trim();
14936
+ result.set(token, { title, summary });
14937
+ }
14938
+ return result;
14939
+ }
14940
+ function generateChangelogEntry(opts) {
14941
+ const parts = [];
14942
+ parts.push(`## [${opts.version}] - ${opts.date}
14943
+ `);
14944
+ parts.push("");
14945
+ for (const [, planSum] of opts.planSummaries) {
14946
+ parts.push(planSum.summary);
14947
+ parts.push("");
14948
+ }
14949
+ if (opts.maintenance.length > 0) {
14950
+ parts.push("### Maintenance");
14951
+ parts.push("");
14952
+ for (const subject of opts.maintenance) {
14953
+ parts.push(`- ${subject}`);
14954
+ }
14955
+ parts.push("");
14956
+ }
14957
+ return parts.join("\n") + "\n";
14958
+ }
14959
+ function findCoverageGaps(entryText, tokens) {
14960
+ const gaps = [];
14961
+ for (const token of tokens) {
14962
+ if (!entryText.includes(token)) {
14963
+ gaps.push(token);
14964
+ }
14965
+ }
14966
+ return gaps;
14967
+ }
14968
+ var PLAN_TOKEN_RE, MissingPlanFileError, MissingChangelogSummaryError;
14969
+ var init_changelog_generator = __esm({
14970
+ "src/changelog-generator.ts"() {
14971
+ "use strict";
14972
+ PLAN_TOKEN_RE = /^(feat|fix|chore|docs)\((plan-[a-z0-9._-]+)\)/;
14973
+ MissingPlanFileError = class extends Error {
14974
+ constructor(token) {
14975
+ super(`No plan file found in plans directory matching Plan Token: ${token}`);
14976
+ this.name = "MissingPlanFileError";
14977
+ }
14978
+ };
14979
+ MissingChangelogSummaryError = class extends Error {
14980
+ constructor(token, planFile) {
14981
+ super(`Plan file ${planFile} for token ${token} has no '## Changelog Summary' section`);
14982
+ this.name = "MissingChangelogSummaryError";
14983
+ }
14984
+ };
14985
+ }
14986
+ });
14987
+
14988
+ // src/commands/changelog.ts
14989
+ var changelog_exports = {};
14990
+ __export(changelog_exports, {
14991
+ handleChangelogSubcommand: () => handleChangelogSubcommand,
14992
+ printChangelogHelp: () => printChangelogHelp
14993
+ });
14994
+ import { execSync } from "child_process";
14995
+ import { existsSync as existsSync14, readFileSync as readFileSync14 } from "fs";
14996
+ import { resolve as resolve11 } from "path";
14997
+ function resolveRepoRoot() {
14998
+ try {
14999
+ return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
15000
+ } catch {
15001
+ return process.cwd();
15002
+ }
15003
+ }
15004
+ function getLastTag() {
15005
+ try {
15006
+ return execSync("git describe --tags --abbrev=0", { encoding: "utf-8" }).trim();
15007
+ } catch {
15008
+ return null;
15009
+ }
15010
+ }
15011
+ function getCommitSubjects(range) {
15012
+ try {
15013
+ const out = execSync(`git log ${range} --pretty=format:%s`, { encoding: "utf-8" });
15014
+ return out.split("\n").filter((s) => s.length > 0);
15015
+ } catch {
15016
+ return [];
15017
+ }
15018
+ }
15019
+ function getCurrentVersion(repoRoot) {
15020
+ const pkgPath = resolve11(repoRoot, "packages/core/package.json");
15021
+ if (!existsSync14(pkgPath)) return "0.0.0";
15022
+ const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
15023
+ return pkg.version || "0.0.0";
15024
+ }
15025
+ function todayDate() {
15026
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
15027
+ }
15028
+ function getLatestChangelogEntryBody(repoRoot) {
15029
+ const path = resolve11(repoRoot, "CHANGELOG.md");
15030
+ if (!existsSync14(path)) return "";
15031
+ const content = readFileSync14(path, "utf-8");
15032
+ const m3 = content.match(/^## \[[\d.]+\][^\n]*\n([\s\S]*?)(?=\n## \[|$)/m);
15033
+ return m3 ? m3[1] : "";
15034
+ }
15035
+ async function handleChangelogSubcommand(args2) {
15036
+ const sub = args2[0];
15037
+ const repoRoot = resolveRepoRoot();
15038
+ const planDir = resolve11(repoRoot, "docs/plans");
15039
+ switch (sub) {
15040
+ case "generate": {
15041
+ const lastTag = getLastTag();
15042
+ const range = lastTag ? `${lastTag}..HEAD` : "HEAD";
15043
+ const subjects = getCommitSubjects(range);
15044
+ const { tokens, maintenance } = parseCommitsForPlanTokens(subjects);
15045
+ let planSummaries;
15046
+ try {
15047
+ planSummaries = loadPlanSummaries(tokens, planDir);
15048
+ } catch (err) {
15049
+ if (err instanceof MissingPlanFileError || err instanceof MissingChangelogSummaryError) {
15050
+ process.stderr.write(`changelog generate: ${err.message}
15051
+ `);
15052
+ return { exitCode: 2 };
15053
+ }
15054
+ throw err;
15055
+ }
15056
+ const entry = generateChangelogEntry({
15057
+ version: getCurrentVersion(repoRoot),
15058
+ date: todayDate(),
15059
+ planSummaries,
15060
+ maintenance
15061
+ });
15062
+ process.stdout.write(entry);
15063
+ return { exitCode: 0 };
15064
+ }
15065
+ case "verify": {
15066
+ const lastTag = getLastTag();
15067
+ const range = lastTag ? `${lastTag}..HEAD` : "HEAD";
15068
+ const subjects = getCommitSubjects(range);
15069
+ const { tokens } = parseCommitsForPlanTokens(subjects);
15070
+ const entryBody = getLatestChangelogEntryBody(repoRoot);
15071
+ const gaps = findCoverageGaps(entryBody, tokens);
15072
+ if (gaps.length === 0) {
15073
+ process.stdout.write("All plan-tokens referenced.\n");
15074
+ return { exitCode: 0 };
15075
+ }
15076
+ for (const t of gaps) {
15077
+ process.stderr.write(`gap: ${t}
15078
+ `);
15079
+ }
15080
+ return { exitCode: 1 };
15081
+ }
15082
+ case "--help":
15083
+ case "-h":
15084
+ case void 0: {
15085
+ printChangelogHelp();
15086
+ return { exitCode: 0 };
15087
+ }
15088
+ default: {
15089
+ process.stderr.write(`massu: unknown changelog subcommand: ${sub}
15090
+ `);
15091
+ printChangelogHelp();
15092
+ return { exitCode: 1 };
15093
+ }
15094
+ }
15095
+ }
15096
+ function printChangelogHelp() {
15097
+ process.stdout.write(`
15098
+ massu changelog <subcommand>
15099
+
15100
+ Subcommands:
15101
+ generate Emit a draft CHANGELOG.md entry to stdout. Reads commit subjects
15102
+ since the last git tag, groups by (plan-<token>) paren-notation,
15103
+ looks up each plan file's ## Changelog Summary section, and emits
15104
+ a Keep-a-Changelog 1.1.0 entry. Operator pipes/copies into
15105
+ CHANGELOG.md (no forced overwrite).
15106
+
15107
+ verify Read-only check that the latest CHANGELOG.md entry references
15108
+ every plan-token in commits since the last tag. Exit 0 if clean,
15109
+ exit 1 with one 'gap: <token>' per missing.
15110
+
15111
+ Examples:
15112
+ npx massu changelog generate > /tmp/draft-entry.md
15113
+ npx massu changelog verify
15114
+
15115
+ Documentation: https://massu.ai/docs/reference/cli-reference#massu-changelog
15116
+ `);
15117
+ }
15118
+ var init_changelog = __esm({
15119
+ "src/commands/changelog.ts"() {
15120
+ "use strict";
15121
+ init_changelog_generator();
15122
+ }
15123
+ });
15124
+
14886
15125
  // src/commands/show-template.ts
14887
15126
  var show_template_exports = {};
14888
15127
  __export(show_template_exports, {
14889
15128
  runShowTemplate: () => runShowTemplate
14890
15129
  });
14891
- import { existsSync as existsSync13, readFileSync as readFileSync13 } from "fs";
14892
- import { resolve as resolve10 } from "path";
15130
+ import { existsSync as existsSync15, readFileSync as readFileSync15 } from "fs";
15131
+ import { resolve as resolve12 } from "path";
14893
15132
  function normalizeBaseName(input) {
14894
15133
  return input.endsWith(".md") ? input.slice(0, -".md".length) : input;
14895
15134
  }
@@ -14917,14 +15156,14 @@ async function runShowTemplate(args2) {
14917
15156
  return;
14918
15157
  }
14919
15158
  const suffix = choice.kind === "hit" ? choice.suffix : "";
14920
- const file = suffix === "" ? resolve10(sourceDir, `${baseName}.md`) : resolve10(sourceDir, `${baseName}${suffix}.md`);
14921
- if (!existsSync13(file)) {
15159
+ const file = suffix === "" ? resolve12(sourceDir, `${baseName}.md`) : resolve12(sourceDir, `${baseName}${suffix}.md`);
15160
+ if (!existsSync15(file)) {
14922
15161
  process.stderr.write(`massu: resolved template "${file}" no longer exists
14923
15162
  `);
14924
15163
  process.exit(1);
14925
15164
  return;
14926
15165
  }
14927
- process.stdout.write(readFileSync13(file, "utf-8"));
15166
+ process.stdout.write(readFileSync15(file, "utf-8"));
14928
15167
  }
14929
15168
  var init_show_template = __esm({
14930
15169
  "src/commands/show-template.ts"() {
@@ -14977,12 +15216,12 @@ var init_passthrough = __esm({
14977
15216
  });
14978
15217
 
14979
15218
  // src/lib/fileLock.ts
14980
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync14, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
15219
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
14981
15220
  import { dirname as dirname8 } from "path";
14982
15221
  import * as lockfile from "proper-lockfile";
14983
15222
  function readLockHolderPid(lockPath) {
14984
15223
  try {
14985
- const raw = readFileSync14(`${lockPath}.pid`, "utf-8").trim();
15224
+ const raw = readFileSync16(`${lockPath}.pid`, "utf-8").trim();
14986
15225
  const pid = Number.parseInt(raw, 10);
14987
15226
  if (!Number.isFinite(pid) || pid <= 0) return null;
14988
15227
  return pid;
@@ -15069,9 +15308,9 @@ var init_fileLock = __esm({
15069
15308
  });
15070
15309
 
15071
15310
  // src/lib/installLock.ts
15072
- import { resolve as resolve11 } from "path";
15311
+ import { resolve as resolve13 } from "path";
15073
15312
  function withInstallLock(projectRoot, fn, opts = {}) {
15074
- const lockPath = resolve11(projectRoot, ".massu", "installAll.lock");
15313
+ const lockPath = resolve13(projectRoot, ".massu", "installAll.lock");
15075
15314
  return withFileLockSync(
15076
15315
  lockPath,
15077
15316
  fn,
@@ -15107,8 +15346,8 @@ __export(config_refresh_exports, {
15107
15346
  mergeRefresh: () => mergeRefresh,
15108
15347
  runConfigRefresh: () => runConfigRefresh
15109
15348
  });
15110
- import { existsSync as existsSync14, readFileSync as readFileSync15, rmSync as rmSync4 } from "fs";
15111
- import { resolve as resolve12 } from "path";
15349
+ import { existsSync as existsSync16, readFileSync as readFileSync17, rmSync as rmSync4 } from "fs";
15350
+ import { resolve as resolve14 } from "path";
15112
15351
  import { parse as parseYaml5 } from "yaml";
15113
15352
  function flatten(obj, prefix3 = "") {
15114
15353
  const out = {};
@@ -15236,17 +15475,17 @@ function renderDiff(diff) {
15236
15475
  }
15237
15476
  async function runConfigRefresh(opts = {}) {
15238
15477
  const cwd = opts.cwd ?? process.cwd();
15239
- const configPath = resolve12(cwd, "massu.config.yaml");
15478
+ const configPath = resolve14(cwd, "massu.config.yaml");
15240
15479
  const log = opts.silent ? () => {
15241
15480
  } : (s) => process.stdout.write(s);
15242
- if (!existsSync14(configPath)) {
15481
+ if (!existsSync16(configPath)) {
15243
15482
  const message = "massu.config.yaml not found. Run: npx massu init";
15244
15483
  if (!opts.silent) process.stderr.write(message + "\n");
15245
15484
  return { exitCode: 1, applied: false, dryRun: !!opts.dryRun, diff: [], message };
15246
15485
  }
15247
15486
  let existing;
15248
15487
  try {
15249
- const content = readFileSync15(configPath, "utf-8");
15488
+ const content = readFileSync17(configPath, "utf-8");
15250
15489
  const parsed = parseYaml5(content);
15251
15490
  if (!parsed || typeof parsed !== "object") {
15252
15491
  throw new Error("config is not a YAML object");
@@ -15319,8 +15558,8 @@ async function runConfigRefresh(opts = {}) {
15319
15558
  `);
15320
15559
  const stackResolved = installResult.totalInstalled > 0 || installResult.totalUpdated > 0;
15321
15560
  if (stackResolved) {
15322
- const placeholderPath = resolve12(installResult.claudeDir, "commands", "_massu-needs-stack.md");
15323
- if (existsSync14(placeholderPath)) {
15561
+ const placeholderPath = resolve14(installResult.claudeDir, "commands", "_massu-needs-stack.md");
15562
+ if (existsSync16(placeholderPath)) {
15324
15563
  try {
15325
15564
  rmSync4(placeholderPath, { force: true });
15326
15565
  log("Removed _massu-needs-stack.md (stack now declared).\n");
@@ -15429,12 +15668,12 @@ var init_gitToplevel = __esm({
15429
15668
  });
15430
15669
 
15431
15670
  // src/watch/lockfile-detector.ts
15432
- import { existsSync as existsSync15, statSync as statSync8 } from "fs";
15433
- import { resolve as resolve13 } from "path";
15671
+ import { existsSync as existsSync17, statSync as statSync8 } from "fs";
15672
+ import { resolve as resolve15 } from "path";
15434
15673
  function lockfileMidWrite(projectRoot, now = Date.now(), windowMs = LOCKFILE_WINDOW_MS) {
15435
15674
  for (const lf of KNOWN_LOCKFILES) {
15436
- const p19 = resolve13(projectRoot, lf);
15437
- if (!existsSync15(p19)) continue;
15675
+ const p19 = resolve15(projectRoot, lf);
15676
+ if (!existsSync17(p19)) continue;
15438
15677
  try {
15439
15678
  const stat = statSync8(p19);
15440
15679
  const delta = now - stat.mtimeMs;
@@ -15447,7 +15686,7 @@ function lockfileMidWrite(projectRoot, now = Date.now(), windowMs = LOCKFILE_WIN
15447
15686
  function gitMidOperation(projectRoot) {
15448
15687
  const sentinels = ["MERGE_HEAD", "REBASE_HEAD", "CHERRY_PICK_HEAD", "rebase-apply", "rebase-merge"];
15449
15688
  for (const s of sentinels) {
15450
- if (existsSync15(resolve13(projectRoot, ".git", s))) return true;
15689
+ if (existsSync17(resolve15(projectRoot, ".git", s))) return true;
15451
15690
  }
15452
15691
  return false;
15453
15692
  }
@@ -15644,18 +15883,18 @@ var init_paths = __esm({
15644
15883
  });
15645
15884
 
15646
15885
  // src/watch/state.ts
15647
- import { closeSync as closeSync3, existsSync as existsSync16, fsyncSync as fsyncSync3, mkdirSync as mkdirSync7, openSync as openSync3, readFileSync as readFileSync16, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync4, writeSync as writeSync3 } from "fs";
15648
- import { dirname as dirname9, resolve as resolve14 } from "path";
15886
+ import { closeSync as closeSync3, existsSync as existsSync18, fsyncSync as fsyncSync3, mkdirSync as mkdirSync7, openSync as openSync3, readFileSync as readFileSync18, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync4, writeSync as writeSync3 } from "fs";
15887
+ import { dirname as dirname9, resolve as resolve16 } from "path";
15649
15888
  function watchStatePath(projectRoot) {
15650
- return resolve14(projectRoot, ".massu", "watch-state.json");
15889
+ return resolve16(projectRoot, ".massu", "watch-state.json");
15651
15890
  }
15652
15891
  function backupStatePath(projectRoot) {
15653
- return resolve14(projectRoot, ".massu", "watch-state.v0.bak.json");
15892
+ return resolve16(projectRoot, ".massu", "watch-state.v0.bak.json");
15654
15893
  }
15655
15894
  function readState(projectRoot) {
15656
15895
  const path = watchStatePath(projectRoot);
15657
- if (!existsSync16(path)) return { ...DEFAULT_STATE };
15658
- const content = readFileSync16(path, "utf-8");
15896
+ if (!existsSync18(path)) return { ...DEFAULT_STATE };
15897
+ const content = readFileSync18(path, "utf-8");
15659
15898
  let raw;
15660
15899
  try {
15661
15900
  raw = JSON.parse(content);
@@ -15718,7 +15957,7 @@ function writeStateAtomic(projectRoot, state) {
15718
15957
  renameSync4(tmp, path);
15719
15958
  renamed = true;
15720
15959
  } finally {
15721
- if (!renamed && existsSync16(tmp)) {
15960
+ if (!renamed && existsSync18(tmp)) {
15722
15961
  try {
15723
15962
  rmSync5(tmp, { force: true });
15724
15963
  } catch {
@@ -15998,8 +16237,8 @@ __export(watch_exports, {
15998
16237
  runWatch: () => runWatch
15999
16238
  });
16000
16239
  import { spawnSync as spawnSync3 } from "child_process";
16001
- import { basename as basename5, dirname as dirname10, resolve as resolve15 } from "path";
16002
- import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync17 } from "fs";
16240
+ import { basename as basename5, dirname as dirname10, resolve as resolve17 } from "path";
16241
+ import { appendFileSync, existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync19 } from "fs";
16003
16242
  function parseFlags(args2) {
16004
16243
  const out = {
16005
16244
  foreground: false,
@@ -16024,8 +16263,8 @@ function parseFlags(args2) {
16024
16263
  }
16025
16264
  function findClaudeBg() {
16026
16265
  const home = process.env.HOME ?? "";
16027
- const fixed = home ? resolve15(home, ".claude", "bin", "claude-bg") : null;
16028
- if (fixed && existsSync17(fixed)) return fixed;
16266
+ const fixed = home ? resolve17(home, ".claude", "bin", "claude-bg") : null;
16267
+ if (fixed && existsSync19(fixed)) return fixed;
16029
16268
  const which = spawnSync3("which", ["claude-bg"], { encoding: "utf-8" });
16030
16269
  if (which.status === 0 && which.stdout) {
16031
16270
  const p19 = which.stdout.trim();
@@ -16086,7 +16325,7 @@ async function runWatch(args2) {
16086
16325
  }
16087
16326
  function runStatus(root) {
16088
16327
  const path = watchStatePath(root);
16089
- if (!existsSync17(path)) {
16328
+ if (!existsSync19(path)) {
16090
16329
  process.stdout.write("massu watch: not running (no state file)\n");
16091
16330
  return { exitCode: 0 };
16092
16331
  }
@@ -16168,7 +16407,7 @@ async function runForeground(root) {
16168
16407
  }
16169
16408
  throw err;
16170
16409
  }
16171
- return new Promise((resolve38) => {
16410
+ return new Promise((resolve40) => {
16172
16411
  const shutdown = async () => {
16173
16412
  if (stopped) return;
16174
16413
  stopped = true;
@@ -16178,7 +16417,7 @@ async function runForeground(root) {
16178
16417
  process.chdir(priorCwd);
16179
16418
  } catch {
16180
16419
  }
16181
- resolve38({ exitCode: 0 });
16420
+ resolve40({ exitCode: 0 });
16182
16421
  };
16183
16422
  process.on("SIGINT", () => {
16184
16423
  void shutdown();
@@ -16239,7 +16478,7 @@ async function runOnQuiescent(projectRoot) {
16239
16478
  );
16240
16479
  }
16241
16480
  function refreshLogPath(projectRoot) {
16242
- return resolve15(projectRoot, ".massu", "refresh-log.jsonl");
16481
+ return resolve17(projectRoot, ".massu", "refresh-log.jsonl");
16243
16482
  }
16244
16483
  function appendRefreshLog(projectRoot, event) {
16245
16484
  const path = refreshLogPath(projectRoot);
@@ -16251,11 +16490,11 @@ function appendRefreshLog(projectRoot, event) {
16251
16490
  }
16252
16491
  function readRefreshLog(projectRoot, limit = 10, opts = {}) {
16253
16492
  const path = refreshLogPath(projectRoot);
16254
- if (!existsSync17(path)) return [];
16493
+ if (!existsSync19(path)) return [];
16255
16494
  const warn = opts.warn ?? ((s) => {
16256
16495
  process.stderr.write(s);
16257
16496
  });
16258
- const lines = readFileSync17(path, "utf-8").split("\n").filter(Boolean);
16497
+ const lines = readFileSync19(path, "utf-8").split("\n").filter(Boolean);
16259
16498
  const tail = lines.slice(-limit);
16260
16499
  const out = [];
16261
16500
  let corrupt = 0;
@@ -16328,7 +16567,7 @@ var init_refresh_log = __esm({
16328
16567
  import {
16329
16568
  chmodSync as chmodSync3,
16330
16569
  closeSync as closeSync4,
16331
- existsSync as existsSync18,
16570
+ existsSync as existsSync20,
16332
16571
  fsyncSync as fsyncSync4,
16333
16572
  mkdirSync as mkdirSync9,
16334
16573
  openSync as openSync4,
@@ -16342,7 +16581,7 @@ function atomicWrite(path, content, opts = {}) {
16342
16581
  const tmpPath = `${path}.tmp`;
16343
16582
  const parentDir = dirname11(path);
16344
16583
  try {
16345
- if (!existsSync18(parentDir)) {
16584
+ if (!existsSync20(parentDir)) {
16346
16585
  const mkdirOpts = { recursive: true };
16347
16586
  if (opts.ensureParentDirMode !== void 0) {
16348
16587
  mkdirOpts.mode = opts.ensureParentDirMode;
@@ -16364,7 +16603,7 @@ function atomicWrite(path, content, opts = {}) {
16364
16603
  renameSync5(tmpPath, path);
16365
16604
  return { written: true };
16366
16605
  } catch (err) {
16367
- if (existsSync18(tmpPath)) {
16606
+ if (existsSync20(tmpPath)) {
16368
16607
  try {
16369
16608
  rmSync6(tmpPath, { force: true });
16370
16609
  } catch {
@@ -16707,24 +16946,24 @@ var init_fetcher = __esm({
16707
16946
  });
16708
16947
 
16709
16948
  // src/security/manifest-cache.ts
16710
- import { existsSync as existsSync19, readFileSync as readFileSync18, statSync as statSync10 } from "node:fs";
16949
+ import { existsSync as existsSync21, readFileSync as readFileSync20, statSync as statSync10 } from "node:fs";
16711
16950
  import { homedir as homedir5 } from "node:os";
16712
- import { resolve as resolve16 } from "node:path";
16951
+ import { resolve as resolve18 } from "node:path";
16713
16952
  import { z as z4 } from "zod";
16714
16953
  function defaultCachePaths() {
16715
- const dir = resolve16(homedir5(), ".massu");
16954
+ const dir = resolve18(homedir5(), ".massu");
16716
16955
  return {
16717
- cachePath: resolve16(dir, "adapter-manifest.json"),
16718
- lockPath: resolve16(dir, ".adapter-manifest.lock")
16956
+ cachePath: resolve18(dir, "adapter-manifest.json"),
16957
+ lockPath: resolve18(dir, ".adapter-manifest.lock")
16719
16958
  };
16720
16959
  }
16721
16960
  function loadCachedManifest(paths = defaultCachePaths()) {
16722
- if (!existsSync19(paths.cachePath)) {
16961
+ if (!existsSync21(paths.cachePath)) {
16723
16962
  return { kind: "absent" };
16724
16963
  }
16725
16964
  let raw;
16726
16965
  try {
16727
- const content = readFileSync18(paths.cachePath, "utf-8");
16966
+ const content = readFileSync20(paths.cachePath, "utf-8");
16728
16967
  raw = JSON.parse(content);
16729
16968
  } catch (err) {
16730
16969
  return {
@@ -16913,15 +17152,15 @@ var init_adapter_origin = __esm({
16913
17152
  });
16914
17153
 
16915
17154
  // src/security/local-fingerprint.ts
16916
- import { existsSync as existsSync20, readFileSync as readFileSync19, lstatSync as lstatSync5 } from "node:fs";
17155
+ import { existsSync as existsSync22, readFileSync as readFileSync21, lstatSync as lstatSync5 } from "node:fs";
16917
17156
  import { homedir as homedir6 } from "node:os";
16918
- import { resolve as resolve17, isAbsolute } from "node:path";
17157
+ import { resolve as resolve19, isAbsolute } from "node:path";
16919
17158
  import { createHash as createHash7 } from "node:crypto";
16920
17159
  import { z as z5 } from "zod";
16921
17160
  function computeLocalFingerprint(localPaths, projectRoot) {
16922
17161
  const tuples = [];
16923
17162
  for (const p19 of localPaths) {
16924
- const abs = isAbsolute(p19) ? p19 : resolve17(projectRoot, p19);
17163
+ const abs = isAbsolute(p19) ? p19 : resolve19(projectRoot, p19);
16925
17164
  let contentTag;
16926
17165
  try {
16927
17166
  const lst = lstatSync5(abs);
@@ -16930,7 +17169,7 @@ function computeLocalFingerprint(localPaths, projectRoot) {
16930
17169
  } else if (!lst.isFile()) {
16931
17170
  contentTag = "<not-a-file>";
16932
17171
  } else {
16933
- contentTag = createHash7("sha256").update(readFileSync19(abs)).digest("hex");
17172
+ contentTag = createHash7("sha256").update(readFileSync21(abs)).digest("hex");
16934
17173
  }
16935
17174
  } catch {
16936
17175
  contentTag = "<missing>";
@@ -16942,10 +17181,10 @@ function computeLocalFingerprint(localPaths, projectRoot) {
16942
17181
  return createHash7("sha256").update(canonical).digest("hex");
16943
17182
  }
16944
17183
  function readFingerprintSentinel(path = FINGERPRINT_PATH) {
16945
- if (!existsSync20(path)) return null;
17184
+ if (!existsSync22(path)) return null;
16946
17185
  let raw;
16947
17186
  try {
16948
- raw = JSON.parse(readFileSync19(path, "utf-8"));
17187
+ raw = JSON.parse(readFileSync21(path, "utf-8"));
16949
17188
  } catch {
16950
17189
  return null;
16951
17190
  }
@@ -16993,7 +17232,7 @@ var init_local_fingerprint = __esm({
16993
17232
  "use strict";
16994
17233
  init_atomic_write();
16995
17234
  init_manifest_schema();
16996
- FINGERPRINT_PATH = resolve17(homedir6(), ".massu", "adapters-local-fingerprint.json");
17235
+ FINGERPRINT_PATH = resolve19(homedir6(), ".massu", "adapters-local-fingerprint.json");
16997
17236
  FingerprintSentinelSchema = z5.object({
16998
17237
  fingerprint: z5.string().regex(/^[0-9a-f]{64}$/),
16999
17238
  source: z5.enum(["cli", "cli-resync"]),
@@ -17009,15 +17248,15 @@ var init_local_fingerprint = __esm({
17009
17248
  });
17010
17249
 
17011
17250
  // src/security/install-tracking.ts
17012
- import { readFileSync as readFileSync20, readdirSync as readdirSync12, lstatSync as lstatSync6, existsSync as existsSync21 } from "node:fs";
17251
+ import { readFileSync as readFileSync22, readdirSync as readdirSync13, lstatSync as lstatSync6, existsSync as existsSync23 } from "node:fs";
17013
17252
  import { join as join11, relative as relative5, sep } from "node:path";
17014
17253
  import { homedir as homedir7 } from "node:os";
17015
- import { resolve as resolve18 } from "node:path";
17254
+ import { resolve as resolve20 } from "node:path";
17016
17255
  import { createHash as createHash8 } from "node:crypto";
17017
17256
  import { z as z6 } from "zod";
17018
17257
  function containsHiddenDirs(packageDir) {
17019
17258
  for (const hidden of EXCLUDED_DIR_NAMES) {
17020
- if (existsSync21(`${packageDir}/${hidden}`)) {
17259
+ if (existsSync23(`${packageDir}/${hidden}`)) {
17021
17260
  return hidden;
17022
17261
  }
17023
17262
  }
@@ -17029,7 +17268,7 @@ function sha256OfDir(dir, opts = {}) {
17029
17268
  function walk(currentDir) {
17030
17269
  let entries;
17031
17270
  try {
17032
- entries = readdirSync12(currentDir);
17271
+ entries = readdirSync13(currentDir);
17033
17272
  } catch {
17034
17273
  return;
17035
17274
  }
@@ -17063,7 +17302,7 @@ function sha256OfDir(dir, opts = {}) {
17063
17302
  files.sort((a2, b2) => a2.relativePath < b2.relativePath ? -1 : a2.relativePath > b2.relativePath ? 1 : 0);
17064
17303
  const top = createHash8("sha256");
17065
17304
  for (const f2 of files) {
17066
- const fileHash = createHash8("sha256").update(readFileSync20(f2.absPath)).digest("hex");
17305
+ const fileHash = createHash8("sha256").update(readFileSync22(f2.absPath)).digest("hex");
17067
17306
  top.update(f2.relativePath, "utf-8");
17068
17307
  top.update("\0", "utf-8");
17069
17308
  top.update(fileHash, "utf-8");
@@ -17072,10 +17311,10 @@ function sha256OfDir(dir, opts = {}) {
17072
17311
  return top.digest("hex");
17073
17312
  }
17074
17313
  function readInstalledManifest(path = INSTALLED_MANIFEST_PATH) {
17075
- if (!existsSync21(path)) return {};
17314
+ if (!existsSync23(path)) return {};
17076
17315
  let raw;
17077
17316
  try {
17078
- raw = JSON.parse(readFileSync20(path, "utf-8"));
17317
+ raw = JSON.parse(readFileSync22(path, "utf-8"));
17079
17318
  } catch {
17080
17319
  return {};
17081
17320
  }
@@ -17139,7 +17378,7 @@ var init_install_tracking = __esm({
17139
17378
  "src/security/install-tracking.ts"() {
17140
17379
  "use strict";
17141
17380
  init_atomic_write();
17142
- INSTALLED_MANIFEST_PATH = resolve18(homedir7(), ".massu", "adapter-manifest-installed.json");
17381
+ INSTALLED_MANIFEST_PATH = resolve20(homedir7(), ".massu", "adapter-manifest-installed.json");
17143
17382
  DEFAULT_MAX_FILE_BYTES = 64 * 1024 * 1024;
17144
17383
  EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([".git", "node_modules", ".cache", ".tmp"]);
17145
17384
  InstallEntrySchema = z6.object({
@@ -17162,25 +17401,25 @@ var init_install_tracking = __esm({
17162
17401
  });
17163
17402
 
17164
17403
  // src/detect/adapters/discover.ts
17165
- import { existsSync as existsSync22, readdirSync as readdirSync13, readFileSync as readFileSync21, lstatSync as lstatSync7 } from "node:fs";
17166
- import { resolve as resolve19, isAbsolute as isAbsolute2 } from "node:path";
17404
+ import { existsSync as existsSync24, readdirSync as readdirSync14, readFileSync as readFileSync23, lstatSync as lstatSync7 } from "node:fs";
17405
+ import { resolve as resolve21, isAbsolute as isAbsolute2 } from "node:path";
17167
17406
  import { z as z7 } from "zod";
17168
17407
  function walkNodeModules(projectRoot, warnings) {
17169
- const nodeModulesDir = resolve19(projectRoot, "node_modules");
17170
- if (!existsSync22(nodeModulesDir)) {
17408
+ const nodeModulesDir = resolve21(projectRoot, "node_modules");
17409
+ if (!existsSync24(nodeModulesDir)) {
17171
17410
  return [];
17172
17411
  }
17173
17412
  const candidates = [];
17174
17413
  let topLevelEntries;
17175
17414
  try {
17176
- topLevelEntries = readdirSync13(nodeModulesDir);
17415
+ topLevelEntries = readdirSync14(nodeModulesDir);
17177
17416
  } catch (err) {
17178
17417
  warnings.push(`failed to read node_modules: ${err instanceof Error ? err.message : String(err)}`);
17179
17418
  return [];
17180
17419
  }
17181
17420
  for (const entry of topLevelEntries) {
17182
17421
  if (entry.startsWith(".")) continue;
17183
- const entryPath = resolve19(nodeModulesDir, entry);
17422
+ const entryPath = resolve21(nodeModulesDir, entry);
17184
17423
  let entryStat;
17185
17424
  try {
17186
17425
  entryStat = lstatSync7(entryPath);
@@ -17197,12 +17436,12 @@ function walkNodeModules(projectRoot, warnings) {
17197
17436
  if (entry.startsWith("@")) {
17198
17437
  let scopedEntries;
17199
17438
  try {
17200
- scopedEntries = readdirSync13(entryPath);
17439
+ scopedEntries = readdirSync14(entryPath);
17201
17440
  } catch {
17202
17441
  continue;
17203
17442
  }
17204
17443
  for (const sub of scopedEntries) {
17205
- const subPath = resolve19(entryPath, sub);
17444
+ const subPath = resolve21(entryPath, sub);
17206
17445
  let subStat;
17207
17446
  try {
17208
17447
  subStat = lstatSync7(subPath);
@@ -17221,11 +17460,11 @@ function walkNodeModules(projectRoot, warnings) {
17221
17460
  return candidates;
17222
17461
  }
17223
17462
  function tryReadAdapterPackage(packageDir, warnings) {
17224
- const pkgJsonPath = resolve19(packageDir, "package.json");
17225
- if (!existsSync22(pkgJsonPath)) return null;
17463
+ const pkgJsonPath = resolve21(packageDir, "package.json");
17464
+ if (!existsSync24(pkgJsonPath)) return null;
17226
17465
  let raw;
17227
17466
  try {
17228
- raw = JSON.parse(readFileSync21(pkgJsonPath, "utf-8"));
17467
+ raw = JSON.parse(readFileSync23(pkgJsonPath, "utf-8"));
17229
17468
  } catch (err) {
17230
17469
  warnings.push(
17231
17470
  `skipping ${packageDir}: package.json parse failed (${err instanceof Error ? err.message : String(err)})`
@@ -17359,8 +17598,8 @@ function discoverAdapters(opts) {
17359
17598
  const localSet = new Set(opts.configLocalPaths);
17360
17599
  for (const localPath of opts.configLocalPaths) {
17361
17600
  if (seenIds.has(localPath)) continue;
17362
- const absPath = isAbsolute2(localPath) ? localPath : resolve19(opts.projectRoot, localPath);
17363
- if (!existsSync22(absPath)) {
17601
+ const absPath = isAbsolute2(localPath) ? localPath : resolve21(opts.projectRoot, localPath);
17602
+ if (!existsSync24(absPath)) {
17364
17603
  warnings.push(
17365
17604
  `local adapter file not found: ${localPath} (resolved to ${absPath}). Remove via: massu adapters remove-local ${localPath}`
17366
17605
  );
@@ -17441,8 +17680,8 @@ __export(adapters_exports, {
17441
17680
  runAdaptersResyncLocalFingerprint: () => runAdaptersResyncLocalFingerprint,
17442
17681
  runAdaptersSearch: () => runAdaptersSearch
17443
17682
  });
17444
- import { existsSync as existsSync23, readFileSync as readFileSync22 } from "node:fs";
17445
- import { resolve as resolve20 } from "node:path";
17683
+ import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
17684
+ import { resolve as resolve22 } from "node:path";
17446
17685
  import { parseDocument } from "yaml";
17447
17686
  async function handleAdaptersSubcommand(args2) {
17448
17687
  const sub = args2[0];
@@ -17709,8 +17948,8 @@ function mutateLocalArray(mutator, command) {
17709
17948
  );
17710
17949
  return { exitCode: 2 };
17711
17950
  }
17712
- const yamlPath = resolve20(projectRoot, "massu.config.yaml");
17713
- if (!existsSync23(yamlPath)) {
17951
+ const yamlPath = resolve22(projectRoot, "massu.config.yaml");
17952
+ if (!existsSync25(yamlPath)) {
17714
17953
  process.stderr.write(
17715
17954
  `${command}: massu.config.yaml not found at ${yamlPath}. Run \`massu init\` first.
17716
17955
  `
@@ -17719,7 +17958,7 @@ function mutateLocalArray(mutator, command) {
17719
17958
  }
17720
17959
  let yamlText;
17721
17960
  try {
17722
- yamlText = readFileSync22(yamlPath, "utf-8");
17961
+ yamlText = readFileSync24(yamlPath, "utf-8");
17723
17962
  } catch (err) {
17724
17963
  process.stderr.write(`${command}: failed to read ${yamlPath}: ${err instanceof Error ? err.message : String(err)}
17725
17964
  `);
@@ -17740,7 +17979,7 @@ function mutateLocalArray(mutator, command) {
17740
17979
  if (next === null) {
17741
17980
  return { exitCode: 0 };
17742
17981
  }
17743
- const lockPath = resolve20(projectRoot, ".massu", "adapters-local-mutate.lock");
17982
+ const lockPath = resolve22(projectRoot, ".massu", "adapters-local-mutate.lock");
17744
17983
  return withFileLockSync(lockPath, () => {
17745
17984
  doc.setIn(["adapters", "local"], next);
17746
17985
  const newYaml = doc.toString();
@@ -17809,23 +18048,23 @@ async function runAdaptersInstall(args2) {
17809
18048
  `);
17810
18049
  return { exitCode: 1 };
17811
18050
  }
17812
- const packageDir = resolve20(projectRoot, "node_modules", ...packageName.split("/"));
17813
- if (!existsSync23(packageDir)) {
18051
+ const packageDir = resolve22(projectRoot, "node_modules", ...packageName.split("/"));
18052
+ if (!existsSync25(packageDir)) {
17814
18053
  process.stderr.write(
17815
18054
  `install: ${packageName} is not installed in node_modules. Run \`npm install ${packageName}\` first.
17816
18055
  `
17817
18056
  );
17818
18057
  return { exitCode: 1 };
17819
18058
  }
17820
- const pkgJsonPath = resolve20(packageDir, "package.json");
17821
- if (!existsSync23(pkgJsonPath)) {
18059
+ const pkgJsonPath = resolve22(packageDir, "package.json");
18060
+ if (!existsSync25(pkgJsonPath)) {
17822
18061
  process.stderr.write(`install: ${packageName} has no package.json at ${pkgJsonPath}
17823
18062
  `);
17824
18063
  return { exitCode: 1 };
17825
18064
  }
17826
18065
  let pkgJson;
17827
18066
  try {
17828
- pkgJson = JSON.parse(readFileSync22(pkgJsonPath, "utf-8"));
18067
+ pkgJson = JSON.parse(readFileSync24(pkgJsonPath, "utf-8"));
17829
18068
  } catch (err) {
17830
18069
  process.stderr.write(`install: ${packageName} has malformed package.json: ${err instanceof Error ? err.message : String(err)}
17831
18070
  `);
@@ -17944,8 +18183,8 @@ async function runAdaptersResign(_args) {
17944
18183
  removeInstalledManifestEntry(name);
17945
18184
  continue;
17946
18185
  }
17947
- const packageDir = resolve20(projectRoot, "node_modules", ...name.split("/"));
17948
- if (!existsSync23(packageDir)) {
18186
+ const packageDir = resolve22(projectRoot, "node_modules", ...name.split("/"));
18187
+ if (!existsSync25(packageDir)) {
17949
18188
  removed++;
17950
18189
  warnings.push(`${name}@${entry.version}: not present in node_modules \u2014 REMOVED from sidecar`);
17951
18190
  removeInstalledManifestEntry(name);
@@ -18033,10 +18272,10 @@ var init_adapters2 = __esm({
18033
18272
  // src/db.ts
18034
18273
  import Database2 from "better-sqlite3";
18035
18274
  import { dirname as dirname12, join as join12 } from "path";
18036
- import { existsSync as existsSync24, mkdirSync as mkdirSync10, readdirSync as readdirSync14, statSync as statSync11 } from "fs";
18275
+ import { existsSync as existsSync26, mkdirSync as mkdirSync10, readdirSync as readdirSync15, statSync as statSync11 } from "fs";
18037
18276
  function getCodeGraphDb() {
18038
18277
  const dbPath = getResolvedPaths().codegraphDbPath;
18039
- if (!existsSync24(dbPath)) {
18278
+ if (!existsSync26(dbPath)) {
18040
18279
  throw new CodegraphDbNotInitializedError(dbPath);
18041
18280
  }
18042
18281
  const db = new Database2(dbPath, { readonly: true });
@@ -18046,7 +18285,7 @@ function getCodeGraphDb() {
18046
18285
  function getDataDb() {
18047
18286
  const dbPath = getResolvedPaths().dataDbPath;
18048
18287
  const dir = dirname12(dbPath);
18049
- if (!existsSync24(dir)) {
18288
+ if (!existsSync26(dir)) {
18050
18289
  mkdirSync10(dir, { recursive: true });
18051
18290
  }
18052
18291
  const db = new Database2(dbPath);
@@ -18317,7 +18556,7 @@ function isPythonDataStale(dataDb, pythonRoot) {
18317
18556
  const lastBuildTime = new Date(lastBuild.value).getTime();
18318
18557
  function checkDir(dir) {
18319
18558
  try {
18320
- const entries = readdirSync14(dir, { withFileTypes: true });
18559
+ const entries = readdirSync15(dir, { withFileTypes: true });
18321
18560
  for (const entry of entries) {
18322
18561
  const fullPath = join12(dir, entry.name);
18323
18562
  if (entry.isDirectory()) {
@@ -18353,10 +18592,10 @@ var init_db = __esm({
18353
18592
  });
18354
18593
 
18355
18594
  // src/security-utils.ts
18356
- import { resolve as resolve21, normalize } from "path";
18595
+ import { resolve as resolve23, normalize } from "path";
18357
18596
  function ensureWithinRoot(filePath, projectRoot) {
18358
- const resolvedRoot = resolve21(projectRoot);
18359
- const resolvedPath = resolve21(resolvedRoot, filePath);
18597
+ const resolvedRoot = resolve23(projectRoot);
18598
+ const resolvedPath = resolve23(resolvedRoot, filePath);
18360
18599
  const normalizedPath = normalize(resolvedPath);
18361
18600
  const normalizedRoot = normalize(resolvedRoot);
18362
18601
  if (!normalizedPath.startsWith(normalizedRoot + "/") && normalizedPath !== normalizedRoot) {
@@ -18429,8 +18668,8 @@ var init_rules = __esm({
18429
18668
  });
18430
18669
 
18431
18670
  // src/import-resolver.ts
18432
- import { readFileSync as readFileSync23, existsSync as existsSync25, statSync as statSync12 } from "fs";
18433
- import { resolve as resolve22, dirname as dirname13, join as join13 } from "path";
18671
+ import { readFileSync as readFileSync25, existsSync as existsSync27, statSync as statSync12 } from "fs";
18672
+ import { resolve as resolve24, dirname as dirname13, join as join13 } from "path";
18434
18673
  function parseImports(source) {
18435
18674
  const imports = [];
18436
18675
  const lines = source.split("\n");
@@ -18486,23 +18725,23 @@ function resolveImportPath(specifier, fromFile) {
18486
18725
  let basePath;
18487
18726
  if (specifier.startsWith("@/")) {
18488
18727
  const paths = getResolvedPaths();
18489
- basePath = resolve22(paths.pathAlias["@"] ?? paths.srcDir, specifier.slice(2));
18728
+ basePath = resolve24(paths.pathAlias["@"] ?? paths.srcDir, specifier.slice(2));
18490
18729
  } else {
18491
- basePath = resolve22(dirname13(fromFile), specifier);
18730
+ basePath = resolve24(dirname13(fromFile), specifier);
18492
18731
  }
18493
- if (existsSync25(basePath) && !isDirectory(basePath)) {
18732
+ if (existsSync27(basePath) && !isDirectory(basePath)) {
18494
18733
  return toRelative(basePath);
18495
18734
  }
18496
18735
  const resolvedPaths = getResolvedPaths();
18497
18736
  for (const ext of resolvedPaths.extensions) {
18498
18737
  const withExt = basePath + ext;
18499
- if (existsSync25(withExt)) {
18738
+ if (existsSync27(withExt)) {
18500
18739
  return toRelative(withExt);
18501
18740
  }
18502
18741
  }
18503
18742
  for (const indexFile of resolvedPaths.indexFiles) {
18504
18743
  const indexPath = join13(basePath, indexFile);
18505
- if (existsSync25(indexPath)) {
18744
+ if (existsSync27(indexPath)) {
18506
18745
  return toRelative(indexPath);
18507
18746
  }
18508
18747
  }
@@ -18538,11 +18777,11 @@ function buildImportIndex(dataDb, codegraphDb) {
18538
18777
  const batchSize = 500;
18539
18778
  let batch = [];
18540
18779
  for (const file of files) {
18541
- const absPath = ensureWithinRoot(resolve22(projectRoot, file.path), projectRoot);
18542
- if (!existsSync25(absPath)) continue;
18780
+ const absPath = ensureWithinRoot(resolve24(projectRoot, file.path), projectRoot);
18781
+ if (!existsSync27(absPath)) continue;
18543
18782
  let source;
18544
18783
  try {
18545
- source = readFileSync23(absPath, "utf-8");
18784
+ source = readFileSync25(absPath, "utf-8");
18546
18785
  } catch {
18547
18786
  continue;
18548
18787
  }
@@ -18578,15 +18817,15 @@ var init_import_resolver = __esm({
18578
18817
  });
18579
18818
 
18580
18819
  // src/trpc-index.ts
18581
- import { readFileSync as readFileSync24, existsSync as existsSync26, readdirSync as readdirSync15 } from "fs";
18582
- import { resolve as resolve23, join as join14 } from "path";
18820
+ import { readFileSync as readFileSync26, existsSync as existsSync28, readdirSync as readdirSync16 } from "fs";
18821
+ import { resolve as resolve25, join as join14 } from "path";
18583
18822
  function parseRootRouter() {
18584
18823
  const paths = getResolvedPaths();
18585
18824
  const rootPath = paths.rootRouterPath;
18586
- if (!existsSync26(rootPath)) {
18825
+ if (!existsSync28(rootPath)) {
18587
18826
  throw new Error(`Root router not found at ${rootPath}`);
18588
18827
  }
18589
- const source = readFileSync24(rootPath, "utf-8");
18828
+ const source = readFileSync26(rootPath, "utf-8");
18590
18829
  const mappings = [];
18591
18830
  const importMap = /* @__PURE__ */ new Map();
18592
18831
  const importRegex = /import\s+\{[^}]*?(\w+Router)[^}]*\}\s+from\s+['"]\.\/routers\/([^'"]+)['"]/g;
@@ -18594,16 +18833,16 @@ function parseRootRouter() {
18594
18833
  while ((match = importRegex.exec(source)) !== null) {
18595
18834
  const variable = match[1];
18596
18835
  let filePath = match[2];
18597
- const fullPath = resolve23(paths.routersDir, filePath);
18836
+ const fullPath = resolve25(paths.routersDir, filePath);
18598
18837
  for (const ext of [".ts", ".tsx", ""]) {
18599
18838
  const candidate = fullPath + ext;
18600
18839
  const routersRelPath = getConfig().paths.routers ?? "src/server/api/routers";
18601
- if (existsSync26(candidate)) {
18840
+ if (existsSync28(candidate)) {
18602
18841
  filePath = routersRelPath + "/" + filePath + ext;
18603
18842
  break;
18604
18843
  }
18605
18844
  const indexCandidate = join14(fullPath, "index.ts");
18606
- if (existsSync26(indexCandidate)) {
18845
+ if (existsSync28(indexCandidate)) {
18607
18846
  filePath = routersRelPath + "/" + filePath + "/index.ts";
18608
18847
  break;
18609
18848
  }
@@ -18622,9 +18861,9 @@ function parseRootRouter() {
18622
18861
  return mappings;
18623
18862
  }
18624
18863
  function extractProcedures(routerFilePath) {
18625
- const absPath = resolve23(getProjectRoot(), routerFilePath);
18626
- if (!existsSync26(absPath)) return [];
18627
- const source = readFileSync24(absPath, "utf-8");
18864
+ const absPath = resolve25(getProjectRoot(), routerFilePath);
18865
+ if (!existsSync28(absPath)) return [];
18866
+ const source = readFileSync26(absPath, "utf-8");
18628
18867
  const procedures = [];
18629
18868
  const seen = /* @__PURE__ */ new Set();
18630
18869
  const procRegex = /(\w+)\s*:\s*(protected|public)Procedure/g;
@@ -18647,19 +18886,19 @@ function findUICallSites(routerKey, procedureName) {
18647
18886
  const root = getProjectRoot();
18648
18887
  const src = config.paths.source;
18649
18888
  const searchDirs = [
18650
- resolve23(root, config.paths.pages ?? src + "/app"),
18651
- resolve23(root, config.paths.components ?? src + "/components"),
18652
- resolve23(root, config.paths.hooks ?? src + "/hooks")
18889
+ resolve25(root, config.paths.pages ?? src + "/app"),
18890
+ resolve25(root, config.paths.components ?? src + "/components"),
18891
+ resolve25(root, config.paths.hooks ?? src + "/hooks")
18653
18892
  ];
18654
18893
  const searchPattern = `api.${routerKey}.${procedureName}`;
18655
18894
  for (const dir of searchDirs) {
18656
- if (!existsSync26(dir)) continue;
18895
+ if (!existsSync28(dir)) continue;
18657
18896
  searchDirectory(dir, searchPattern, callSites);
18658
18897
  }
18659
18898
  return callSites;
18660
18899
  }
18661
18900
  function searchDirectory(dir, pattern, results) {
18662
- const entries = readdirSync15(dir, { withFileTypes: true });
18901
+ const entries = readdirSync16(dir, { withFileTypes: true });
18663
18902
  for (const entry of entries) {
18664
18903
  const fullPath = join14(dir, entry.name);
18665
18904
  if (entry.isDirectory()) {
@@ -18667,7 +18906,7 @@ function searchDirectory(dir, pattern, results) {
18667
18906
  searchDirectory(fullPath, pattern, results);
18668
18907
  } else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
18669
18908
  try {
18670
- const source = readFileSync24(fullPath, "utf-8");
18909
+ const source = readFileSync26(fullPath, "utf-8");
18671
18910
  const lines = source.split("\n");
18672
18911
  for (let i = 0; i < lines.length; i++) {
18673
18912
  if (lines[i].includes(pattern)) {
@@ -18730,8 +18969,8 @@ var init_trpc_index = __esm({
18730
18969
  });
18731
18970
 
18732
18971
  // src/page-deps.ts
18733
- import { readFileSync as readFileSync25, existsSync as existsSync27 } from "fs";
18734
- import { resolve as resolve24 } from "path";
18972
+ import { readFileSync as readFileSync27, existsSync as existsSync29 } from "fs";
18973
+ import { resolve as resolve26 } from "path";
18735
18974
  function deriveRoute(pageFile) {
18736
18975
  let route = pageFile.replace(/^src\/app/, "").replace(/\/page\.tsx?$/, "").replace(/\/page\.jsx?$/, "");
18737
18976
  return route || "/";
@@ -18769,10 +19008,10 @@ function findRouterCalls(files) {
18769
19008
  const routers = /* @__PURE__ */ new Set();
18770
19009
  const projectRoot = getProjectRoot();
18771
19010
  for (const file of files) {
18772
- const absPath = ensureWithinRoot(resolve24(projectRoot, file), projectRoot);
18773
- if (!existsSync27(absPath)) continue;
19011
+ const absPath = ensureWithinRoot(resolve26(projectRoot, file), projectRoot);
19012
+ if (!existsSync29(absPath)) continue;
18774
19013
  try {
18775
- const source = readFileSync25(absPath, "utf-8");
19014
+ const source = readFileSync27(absPath, "utf-8");
18776
19015
  const apiCallRegex = /api\.(\w+)\.\w+/g;
18777
19016
  let match;
18778
19017
  while ((match = apiCallRegex.exec(source)) !== null) {
@@ -18790,10 +19029,10 @@ function findTablesFromRouters(routerNames, dataDb) {
18790
19029
  "SELECT DISTINCT router_file FROM massu_trpc_procedures WHERE router_name = ?"
18791
19030
  ).all(routerName);
18792
19031
  for (const proc of procs) {
18793
- const absPath = ensureWithinRoot(resolve24(getProjectRoot(), proc.router_file), getProjectRoot());
18794
- if (!existsSync27(absPath)) continue;
19032
+ const absPath = ensureWithinRoot(resolve26(getProjectRoot(), proc.router_file), getProjectRoot());
19033
+ if (!existsSync29(absPath)) continue;
18795
19034
  try {
18796
- const source = readFileSync25(absPath, "utf-8");
19035
+ const source = readFileSync27(absPath, "utf-8");
18797
19036
  const dbPattern = getConfig().dbAccessPattern ?? "ctx.db.{table}";
18798
19037
  const regexStr = dbPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\{table\\}", "(\\w+)");
18799
19038
  const tableRegex = new RegExp(regexStr + "\\.", "g");
@@ -19062,14 +19301,14 @@ var init_domains = __esm({
19062
19301
  });
19063
19302
 
19064
19303
  // src/schema-mapper.ts
19065
- import { readFileSync as readFileSync26, existsSync as existsSync28, readdirSync as readdirSync16 } from "fs";
19304
+ import { readFileSync as readFileSync28, existsSync as existsSync30, readdirSync as readdirSync17 } from "fs";
19066
19305
  import { join as join15 } from "path";
19067
19306
  function parsePrismaSchema() {
19068
19307
  const schemaPath = getResolvedPaths().prismaSchemaPath;
19069
- if (!existsSync28(schemaPath)) {
19308
+ if (!existsSync30(schemaPath)) {
19070
19309
  throw new Error(`Prisma schema not found at ${schemaPath}`);
19071
19310
  }
19072
- const source = readFileSync26(schemaPath, "utf-8");
19311
+ const source = readFileSync28(schemaPath, "utf-8");
19073
19312
  const models = [];
19074
19313
  const sourceLines = source.split("\n");
19075
19314
  let i = 0;
@@ -19127,12 +19366,12 @@ function toSnakeCase(str) {
19127
19366
  function findColumnUsageInRouters(tableName) {
19128
19367
  const usage = /* @__PURE__ */ new Map();
19129
19368
  const routersDir = getResolvedPaths().routersDir;
19130
- if (!existsSync28(routersDir)) return usage;
19369
+ if (!existsSync30(routersDir)) return usage;
19131
19370
  scanDirectory(routersDir, tableName, usage);
19132
19371
  return usage;
19133
19372
  }
19134
19373
  function scanDirectory(dir, tableName, usage) {
19135
- const entries = readdirSync16(dir, { withFileTypes: true });
19374
+ const entries = readdirSync17(dir, { withFileTypes: true });
19136
19375
  for (const entry of entries) {
19137
19376
  const fullPath = join15(dir, entry.name);
19138
19377
  if (entry.isDirectory()) {
@@ -19144,7 +19383,7 @@ function scanDirectory(dir, tableName, usage) {
19144
19383
  }
19145
19384
  function scanFile(absPath, tableName, usage) {
19146
19385
  try {
19147
- const source = readFileSync26(absPath, "utf-8");
19386
+ const source = readFileSync28(absPath, "utf-8");
19148
19387
  if (!source.includes(tableName)) return;
19149
19388
  const relPath = absPath.slice(getProjectRoot().length + 1);
19150
19389
  const lines = source.split("\n");
@@ -19189,15 +19428,15 @@ function detectMismatches(models) {
19189
19428
  }
19190
19429
  function findFilesUsingColumn(dir, column, tableName) {
19191
19430
  const result = [];
19192
- if (!existsSync28(dir)) return result;
19193
- const entries = readdirSync16(dir, { withFileTypes: true });
19431
+ if (!existsSync30(dir)) return result;
19432
+ const entries = readdirSync17(dir, { withFileTypes: true });
19194
19433
  for (const entry of entries) {
19195
19434
  const fullPath = join15(dir, entry.name);
19196
19435
  if (entry.isDirectory()) {
19197
19436
  result.push(...findFilesUsingColumn(fullPath, column, tableName));
19198
19437
  } else if (entry.name.endsWith(".ts")) {
19199
19438
  try {
19200
- const source = readFileSync26(fullPath, "utf-8");
19439
+ const source = readFileSync28(fullPath, "utf-8");
19201
19440
  if (source.includes(tableName) && source.includes(column)) {
19202
19441
  result.push(fullPath.slice(getProjectRoot().length + 1));
19203
19442
  }
@@ -19342,12 +19581,12 @@ var init_import_parser = __esm({
19342
19581
  });
19343
19582
 
19344
19583
  // src/python/import-resolver.ts
19345
- import { readFileSync as readFileSync27, existsSync as existsSync29, readdirSync as readdirSync17 } from "fs";
19346
- import { resolve as resolve26, join as join16, relative as relative6, dirname as dirname14 } from "path";
19584
+ import { readFileSync as readFileSync29, existsSync as existsSync31, readdirSync as readdirSync18 } from "fs";
19585
+ import { resolve as resolve28, join as join16, relative as relative6, dirname as dirname14 } from "path";
19347
19586
  function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
19348
19587
  const projectRoot = getProjectRoot();
19349
19588
  if (level > 0) {
19350
- let baseDir = dirname14(resolve26(projectRoot, fromFile));
19589
+ let baseDir = dirname14(resolve28(projectRoot, fromFile));
19351
19590
  for (let i = 1; i < level; i++) {
19352
19591
  baseDir = dirname14(baseDir);
19353
19592
  }
@@ -19359,17 +19598,17 @@ function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
19359
19598
  return tryResolvePythonPath(baseDir, projectRoot);
19360
19599
  }
19361
19600
  const parts = module.split(".");
19362
- const candidate = join16(resolve26(projectRoot, pythonRoot), ...parts);
19601
+ const candidate = join16(resolve28(projectRoot, pythonRoot), ...parts);
19363
19602
  return tryResolvePythonPath(candidate, projectRoot);
19364
19603
  }
19365
19604
  function tryResolvePythonPath(basePath, projectRoot) {
19366
- if (existsSync29(basePath + ".py")) {
19605
+ if (existsSync31(basePath + ".py")) {
19367
19606
  return relative6(projectRoot, basePath + ".py");
19368
19607
  }
19369
- if (existsSync29(join16(basePath, "__init__.py"))) {
19608
+ if (existsSync31(join16(basePath, "__init__.py"))) {
19370
19609
  return relative6(projectRoot, join16(basePath, "__init__.py"));
19371
19610
  }
19372
- if (basePath.endsWith(".py") && existsSync29(basePath)) {
19611
+ if (basePath.endsWith(".py") && existsSync31(basePath)) {
19373
19612
  return relative6(projectRoot, basePath);
19374
19613
  }
19375
19614
  return null;
@@ -19377,7 +19616,7 @@ function tryResolvePythonPath(basePath, projectRoot) {
19377
19616
  function walkPythonFiles(dir, excludeDirs) {
19378
19617
  const files = [];
19379
19618
  try {
19380
- const entries = readdirSync17(dir, { withFileTypes: true });
19619
+ const entries = readdirSync18(dir, { withFileTypes: true });
19381
19620
  for (const entry of entries) {
19382
19621
  if (entry.isDirectory()) {
19383
19622
  if (excludeDirs.includes(entry.name)) continue;
@@ -19392,7 +19631,7 @@ function walkPythonFiles(dir, excludeDirs) {
19392
19631
  }
19393
19632
  function buildPythonImportIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
19394
19633
  const projectRoot = getProjectRoot();
19395
- const absRoot = resolve26(projectRoot, pythonRoot);
19634
+ const absRoot = resolve28(projectRoot, pythonRoot);
19396
19635
  dataDb.exec("DELETE FROM massu_py_imports");
19397
19636
  const insertStmt = dataDb.prepare(
19398
19637
  "INSERT INTO massu_py_imports (source_file, target_file, import_type, imported_names, line) VALUES (?, ?, ?, ?, ?)"
@@ -19409,7 +19648,7 @@ function buildPythonImportIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__"
19409
19648
  const relFile = relative6(projectRoot, absFile);
19410
19649
  let source;
19411
19650
  try {
19412
- source = readFileSync27(absFile, "utf-8");
19651
+ source = readFileSync29(absFile, "utf-8");
19413
19652
  } catch {
19414
19653
  continue;
19415
19654
  }
@@ -19675,12 +19914,12 @@ var init_route_parser = __esm({
19675
19914
  });
19676
19915
 
19677
19916
  // src/python/route-indexer.ts
19678
- import { readFileSync as readFileSync28, readdirSync as readdirSync18 } from "fs";
19917
+ import { readFileSync as readFileSync30, readdirSync as readdirSync19 } from "fs";
19679
19918
  import { join as join17, relative as relative7 } from "path";
19680
19919
  function walkPyFiles(dir, excludeDirs) {
19681
19920
  const files = [];
19682
19921
  try {
19683
- const entries = readdirSync18(dir, { withFileTypes: true });
19922
+ const entries = readdirSync19(dir, { withFileTypes: true });
19684
19923
  for (const entry of entries) {
19685
19924
  if (entry.isDirectory()) {
19686
19925
  if (excludeDirs.includes(entry.name)) continue;
@@ -19708,7 +19947,7 @@ function buildPythonRouteIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__",
19708
19947
  const relFile = relative7(projectRoot, absFile);
19709
19948
  let source;
19710
19949
  try {
19711
- source = readFileSync28(absFile, "utf-8");
19950
+ source = readFileSync30(absFile, "utf-8");
19712
19951
  } catch {
19713
19952
  continue;
19714
19953
  }
@@ -19919,12 +20158,12 @@ var init_model_parser = __esm({
19919
20158
  });
19920
20159
 
19921
20160
  // src/python/model-indexer.ts
19922
- import { readFileSync as readFileSync29, readdirSync as readdirSync19 } from "fs";
20161
+ import { readFileSync as readFileSync31, readdirSync as readdirSync20 } from "fs";
19923
20162
  import { join as join18, relative as relative8 } from "path";
19924
20163
  function walkPyFiles2(dir, excludeDirs) {
19925
20164
  const files = [];
19926
20165
  try {
19927
- const entries = readdirSync19(dir, { withFileTypes: true });
20166
+ const entries = readdirSync20(dir, { withFileTypes: true });
19928
20167
  for (const entry of entries) {
19929
20168
  if (entry.isDirectory()) {
19930
20169
  if (excludeDirs.includes(entry.name)) continue;
@@ -19955,7 +20194,7 @@ function buildPythonModelIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__",
19955
20194
  const relFile = relative8(projectRoot, absFile);
19956
20195
  let source;
19957
20196
  try {
19958
- source = readFileSync29(absFile, "utf-8");
20197
+ source = readFileSync31(absFile, "utf-8");
19959
20198
  } catch {
19960
20199
  continue;
19961
20200
  }
@@ -20215,7 +20454,7 @@ var init_migration_parser = __esm({
20215
20454
  });
20216
20455
 
20217
20456
  // src/python/migration-indexer.ts
20218
- import { readFileSync as readFileSync30, readdirSync as readdirSync20 } from "fs";
20457
+ import { readFileSync as readFileSync32, readdirSync as readdirSync21 } from "fs";
20219
20458
  import { join as join19, relative as relative9 } from "path";
20220
20459
  function buildPythonMigrationIndex(dataDb, alembicDir) {
20221
20460
  const projectRoot = getProjectRoot();
@@ -20224,10 +20463,10 @@ function buildPythonMigrationIndex(dataDb, alembicDir) {
20224
20463
  const versionsDir = join19(absDir, "versions");
20225
20464
  let files = [];
20226
20465
  try {
20227
- files = readdirSync20(versionsDir).filter((f2) => f2.endsWith(".py")).map((f2) => join19(versionsDir, f2));
20466
+ files = readdirSync21(versionsDir).filter((f2) => f2.endsWith(".py")).map((f2) => join19(versionsDir, f2));
20228
20467
  } catch {
20229
20468
  try {
20230
- files = readdirSync20(absDir).filter((f2) => f2.endsWith(".py") && f2 !== "env.py").map((f2) => join19(absDir, f2));
20469
+ files = readdirSync21(absDir).filter((f2) => f2.endsWith(".py") && f2 !== "env.py").map((f2) => join19(absDir, f2));
20231
20470
  } catch {
20232
20471
  }
20233
20472
  }
@@ -20241,7 +20480,7 @@ function buildPythonMigrationIndex(dataDb, alembicDir) {
20241
20480
  for (const absFile of files) {
20242
20481
  let source;
20243
20482
  try {
20244
- source = readFileSync30(absFile, "utf-8");
20483
+ source = readFileSync32(absFile, "utf-8");
20245
20484
  } catch {
20246
20485
  continue;
20247
20486
  }
@@ -20275,7 +20514,7 @@ var init_migration_indexer = __esm({
20275
20514
  });
20276
20515
 
20277
20516
  // src/python/coupling-detector.ts
20278
- import { readFileSync as readFileSync31, readdirSync as readdirSync21 } from "fs";
20517
+ import { readFileSync as readFileSync33, readdirSync as readdirSync22 } from "fs";
20279
20518
  import { join as join20, relative as relative10 } from "path";
20280
20519
  function buildPythonCouplingIndex(dataDb) {
20281
20520
  const projectRoot = getProjectRoot();
@@ -20312,7 +20551,7 @@ function buildPythonCouplingIndex(dataDb) {
20312
20551
  const relFile = relative10(projectRoot, absFile);
20313
20552
  let source;
20314
20553
  try {
20315
- source = readFileSync31(absFile, "utf-8");
20554
+ source = readFileSync33(absFile, "utf-8");
20316
20555
  } catch {
20317
20556
  continue;
20318
20557
  }
@@ -20340,7 +20579,7 @@ function walkFrontendFiles(dir) {
20340
20579
  const files = [];
20341
20580
  const exclude = ["node_modules", ".next", "dist", ".git", "__pycache__", ".venv", "venv"];
20342
20581
  try {
20343
- const entries = readdirSync21(dir, { withFileTypes: true });
20582
+ const entries = readdirSync22(dir, { withFileTypes: true });
20344
20583
  for (const entry of entries) {
20345
20584
  if (entry.isDirectory()) {
20346
20585
  if (exclude.includes(entry.name)) continue;
@@ -20717,8 +20956,8 @@ var init_memory_tools = __esm({
20717
20956
  });
20718
20957
 
20719
20958
  // src/docs-tools.ts
20720
- import { readFileSync as readFileSync32, existsSync as existsSync30 } from "fs";
20721
- import { resolve as resolve27, basename as basename6 } from "path";
20959
+ import { readFileSync as readFileSync34, existsSync as existsSync32 } from "fs";
20960
+ import { resolve as resolve29, basename as basename6 } from "path";
20722
20961
  function p3(baseName) {
20723
20962
  return `${getConfig().toolPrefix}_${baseName}`;
20724
20963
  }
@@ -20773,10 +21012,10 @@ function handleDocsToolCall(name, args2) {
20773
21012
  }
20774
21013
  function loadDocsMap() {
20775
21014
  const mapPath = getResolvedPaths().docsMapPath;
20776
- if (!existsSync30(mapPath)) {
21015
+ if (!existsSync32(mapPath)) {
20777
21016
  throw new Error(`docs-map.json not found at ${mapPath}`);
20778
21017
  }
20779
- return JSON.parse(readFileSync32(mapPath, "utf-8"));
21018
+ return JSON.parse(readFileSync34(mapPath, "utf-8"));
20780
21019
  }
20781
21020
  function matchesPattern(filePath, pattern) {
20782
21021
  const regexStr = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
@@ -20846,13 +21085,13 @@ function extractFrontmatter(content) {
20846
21085
  }
20847
21086
  function extractProcedureNames(routerPath) {
20848
21087
  const root = getProjectRoot();
20849
- const absPath = ensureWithinRoot(resolve27(getResolvedPaths().srcDir, "..", routerPath), root);
20850
- if (!existsSync30(absPath)) {
20851
- const altPath = ensureWithinRoot(resolve27(getResolvedPaths().srcDir, "../server/api/routers", basename6(routerPath)), root);
20852
- if (!existsSync30(altPath)) return [];
20853
- return extractProcedureNamesFromContent(readFileSync32(altPath, "utf-8"));
21088
+ const absPath = ensureWithinRoot(resolve29(getResolvedPaths().srcDir, "..", routerPath), root);
21089
+ if (!existsSync32(absPath)) {
21090
+ const altPath = ensureWithinRoot(resolve29(getResolvedPaths().srcDir, "../server/api/routers", basename6(routerPath)), root);
21091
+ if (!existsSync32(altPath)) return [];
21092
+ return extractProcedureNamesFromContent(readFileSync34(altPath, "utf-8"));
20854
21093
  }
20855
- return extractProcedureNamesFromContent(readFileSync32(absPath, "utf-8"));
21094
+ return extractProcedureNamesFromContent(readFileSync34(absPath, "utf-8"));
20856
21095
  }
20857
21096
  function extractProcedureNamesFromContent(content) {
20858
21097
  const procRegex = /\.(?:query|mutation)\s*\(/g;
@@ -20892,8 +21131,8 @@ function handleDocsAudit(args2) {
20892
21131
  for (const [mappingId, triggeringFiles] of affectedMappings) {
20893
21132
  const mapping = docsMap.mappings.find((m3) => m3.id === mappingId);
20894
21133
  if (!mapping) continue;
20895
- const helpPagePath = ensureWithinRoot(resolve27(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
20896
- if (!existsSync30(helpPagePath)) {
21134
+ const helpPagePath = ensureWithinRoot(resolve29(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
21135
+ if (!existsSync32(helpPagePath)) {
20897
21136
  results.push({
20898
21137
  helpPage: mapping.helpPage,
20899
21138
  mappingId,
@@ -20905,7 +21144,7 @@ function handleDocsAudit(args2) {
20905
21144
  });
20906
21145
  continue;
20907
21146
  }
20908
- const content = readFileSync32(helpPagePath, "utf-8");
21147
+ const content = readFileSync34(helpPagePath, "utf-8");
20909
21148
  const sections = extractSections(content);
20910
21149
  const frontmatter = extractFrontmatter(content);
20911
21150
  const staleReasons = [];
@@ -20945,9 +21184,9 @@ function handleDocsAudit(args2) {
20945
21184
  });
20946
21185
  for (const [guideName, parentId] of Object.entries(docsMap.userGuideInheritance.examples)) {
20947
21186
  if (parentId === mappingId) {
20948
- const guidePath = ensureWithinRoot(resolve27(getResolvedPaths().helpSitePath, `pages/user-guides/${guideName}/index.mdx`), getProjectRoot());
20949
- if (existsSync30(guidePath)) {
20950
- const guideContent = readFileSync32(guidePath, "utf-8");
21187
+ const guidePath = ensureWithinRoot(resolve29(getResolvedPaths().helpSitePath, `pages/user-guides/${guideName}/index.mdx`), getProjectRoot());
21188
+ if (existsSync32(guidePath)) {
21189
+ const guideContent = readFileSync34(guidePath, "utf-8");
20951
21190
  const guideFrontmatter = extractFrontmatter(guideContent);
20952
21191
  if (!guideFrontmatter?.lastVerified || status === "STALE") {
20953
21192
  results.push({
@@ -20980,14 +21219,14 @@ function handleDocsCoverage(args2) {
20980
21219
  const gaps = [];
20981
21220
  const mappings = filterDomain ? docsMap.mappings.filter((m3) => m3.id === filterDomain) : docsMap.mappings;
20982
21221
  for (const mapping of mappings) {
20983
- const helpPagePath = ensureWithinRoot(resolve27(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
20984
- const exists = existsSync30(helpPagePath);
21222
+ const helpPagePath = ensureWithinRoot(resolve29(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
21223
+ const exists = existsSync32(helpPagePath);
20985
21224
  let hasContent = false;
20986
21225
  let lineCount = 0;
20987
21226
  let lastVerified = null;
20988
21227
  let status = null;
20989
21228
  if (exists) {
20990
- const content = readFileSync32(helpPagePath, "utf-8");
21229
+ const content = readFileSync34(helpPagePath, "utf-8");
20991
21230
  lineCount = content.split("\n").length;
20992
21231
  hasContent = lineCount > 10;
20993
21232
  const frontmatter = extractFrontmatter(content);
@@ -21328,8 +21567,8 @@ var init_observability_tools = __esm({
21328
21567
  });
21329
21568
 
21330
21569
  // src/sentinel-db.ts
21331
- import { existsSync as existsSync31 } from "fs";
21332
- import { resolve as resolve28 } from "path";
21570
+ import { existsSync as existsSync33 } from "fs";
21571
+ import { resolve as resolve30 } from "path";
21333
21572
  function parsePortalScope(raw) {
21334
21573
  if (!raw) return [];
21335
21574
  try {
@@ -21565,23 +21804,23 @@ function validateFeatures(db, domainFilter) {
21565
21804
  const missingProcedures = [];
21566
21805
  const missingPages = [];
21567
21806
  for (const comp of components) {
21568
- const absPath = resolve28(PROJECT_ROOT, comp.component_file);
21569
- if (!existsSync31(absPath)) {
21807
+ const absPath = resolve30(PROJECT_ROOT, comp.component_file);
21808
+ if (!existsSync33(absPath)) {
21570
21809
  missingComponents.push(comp.component_file);
21571
21810
  }
21572
21811
  }
21573
21812
  for (const proc of procedures) {
21574
- const routerPath = resolve28(PROJECT_ROOT, `src/server/api/routers/${proc.router_name}.ts`);
21575
- if (!existsSync31(routerPath)) {
21813
+ const routerPath = resolve30(PROJECT_ROOT, `src/server/api/routers/${proc.router_name}.ts`);
21814
+ if (!existsSync33(routerPath)) {
21576
21815
  missingProcedures.push({ router: proc.router_name, procedure: proc.procedure_name });
21577
21816
  }
21578
21817
  }
21579
21818
  for (const page of pages) {
21580
21819
  const routeToPath = page.page_route.replace(/^\/(portal-[^/]+\/)?/, "src/app/").replace(/\/$/, "") + "/page.tsx";
21581
- const absPath = resolve28(PROJECT_ROOT, routeToPath);
21582
- if (page.page_route.startsWith("/") && !existsSync31(absPath)) {
21583
- const altPath = resolve28(PROJECT_ROOT, `src/app${page.page_route}/page.tsx`);
21584
- if (!existsSync31(altPath)) {
21820
+ const absPath = resolve30(PROJECT_ROOT, routeToPath);
21821
+ if (page.page_route.startsWith("/") && !existsSync33(absPath)) {
21822
+ const altPath = resolve30(PROJECT_ROOT, `src/app${page.page_route}/page.tsx`);
21823
+ if (!existsSync33(altPath)) {
21585
21824
  missingPages.push(page.page_route);
21586
21825
  }
21587
21826
  }
@@ -22105,8 +22344,8 @@ var init_sentinel_tools = __esm({
22105
22344
  });
22106
22345
 
22107
22346
  // src/sentinel-scanner.ts
22108
- import { readFileSync as readFileSync33, existsSync as existsSync32, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
22109
- import { resolve as resolve29, join as join21, basename as basename7, dirname as dirname15, relative as relative11 } from "path";
22347
+ import { readFileSync as readFileSync35, existsSync as existsSync34, readdirSync as readdirSync23, statSync as statSync13 } from "fs";
22348
+ import { resolve as resolve31, join as join21, basename as basename7, dirname as dirname15, relative as relative11 } from "path";
22110
22349
  function inferDomain(filePath) {
22111
22350
  const domains = getConfig().domains;
22112
22351
  const path = filePath.toLowerCase();
@@ -22235,10 +22474,10 @@ function scanComponentExports(dataDb) {
22235
22474
  const projectRoot = getProjectRoot();
22236
22475
  const componentsBase = config.paths.components ?? config.paths.source + "/components";
22237
22476
  const componentDirs = [];
22238
- const basePath = resolve29(projectRoot, componentsBase);
22239
- if (existsSync32(basePath)) {
22477
+ const basePath = resolve31(projectRoot, componentsBase);
22478
+ if (existsSync34(basePath)) {
22240
22479
  try {
22241
- const entries = readdirSync22(basePath, { withFileTypes: true });
22480
+ const entries = readdirSync23(basePath, { withFileTypes: true });
22242
22481
  for (const entry of entries) {
22243
22482
  if (entry.isDirectory()) {
22244
22483
  componentDirs.push(componentsBase + "/" + entry.name);
@@ -22248,12 +22487,12 @@ function scanComponentExports(dataDb) {
22248
22487
  }
22249
22488
  }
22250
22489
  for (const dir of componentDirs) {
22251
- const absDir = resolve29(projectRoot, dir);
22252
- if (!existsSync32(absDir)) continue;
22490
+ const absDir = resolve31(projectRoot, dir);
22491
+ if (!existsSync34(absDir)) continue;
22253
22492
  const files = walkDir2(absDir).filter((f2) => f2.endsWith(".tsx") || f2.endsWith(".ts"));
22254
22493
  for (const file of files) {
22255
22494
  const relPath = relative11(projectRoot, file);
22256
- const source = readFileSync33(file, "utf-8");
22495
+ const source = readFileSync35(file, "utf-8");
22257
22496
  const annotations = parseFeatureAnnotations(source);
22258
22497
  if (annotations.length > 0) {
22259
22498
  for (const ann of annotations) {
@@ -22302,7 +22541,7 @@ function scanComponentExports(dataDb) {
22302
22541
  function walkDir2(dir) {
22303
22542
  const results = [];
22304
22543
  try {
22305
- const entries = readdirSync22(dir);
22544
+ const entries = readdirSync23(dir);
22306
22545
  for (const entry of entries) {
22307
22546
  const fullPath = join21(dir, entry);
22308
22547
  try {
@@ -23292,7 +23531,7 @@ var init_audit_trail = __esm({
23292
23531
  });
23293
23532
 
23294
23533
  // src/validation-engine.ts
23295
- import { existsSync as existsSync33, readFileSync as readFileSync34 } from "fs";
23534
+ import { existsSync as existsSync35, readFileSync as readFileSync36 } from "fs";
23296
23535
  function p10(baseName) {
23297
23536
  return `${getConfig().toolPrefix}_${baseName}`;
23298
23537
  }
@@ -23323,7 +23562,7 @@ function validateFile(filePath, projectRoot) {
23323
23562
  });
23324
23563
  return checks;
23325
23564
  }
23326
- if (!existsSync33(absPath)) {
23565
+ if (!existsSync35(absPath)) {
23327
23566
  checks.push({
23328
23567
  name: "file_exists",
23329
23568
  severity: "error",
@@ -23332,7 +23571,7 @@ function validateFile(filePath, projectRoot) {
23332
23571
  });
23333
23572
  return checks;
23334
23573
  }
23335
- const source = readFileSync34(absPath, "utf-8");
23574
+ const source = readFileSync36(absPath, "utf-8");
23336
23575
  const lines = source.split("\n");
23337
23576
  if (activeChecks.rule_compliance !== false) {
23338
23577
  for (const ruleSet of config.rules) {
@@ -23777,7 +24016,7 @@ var init_adr_generator = __esm({
23777
24016
  });
23778
24017
 
23779
24018
  // src/security-scorer.ts
23780
- import { existsSync as existsSync34, readFileSync as readFileSync35 } from "fs";
24019
+ import { existsSync as existsSync36, readFileSync as readFileSync37 } from "fs";
23781
24020
  function p12(baseName) {
23782
24021
  return `${getConfig().toolPrefix}_${baseName}`;
23783
24022
  }
@@ -23801,12 +24040,12 @@ function scoreFileSecurity(filePath, projectRoot) {
23801
24040
  }]
23802
24041
  };
23803
24042
  }
23804
- if (!existsSync34(absPath)) {
24043
+ if (!existsSync36(absPath)) {
23805
24044
  return { riskScore: 0, findings: [] };
23806
24045
  }
23807
24046
  let source;
23808
24047
  try {
23809
- source = readFileSync35(absPath, "utf-8");
24048
+ source = readFileSync37(absPath, "utf-8");
23810
24049
  } catch {
23811
24050
  return { riskScore: 0, findings: [] };
23812
24051
  }
@@ -24095,8 +24334,8 @@ var init_security_scorer = __esm({
24095
24334
  });
24096
24335
 
24097
24336
  // src/dependency-scorer.ts
24098
- import { existsSync as existsSync35, readFileSync as readFileSync36 } from "fs";
24099
- import { resolve as resolve30 } from "path";
24337
+ import { existsSync as existsSync37, readFileSync as readFileSync38 } from "fs";
24338
+ import { resolve as resolve32 } from "path";
24100
24339
  function p13(baseName) {
24101
24340
  return `${getConfig().toolPrefix}_${baseName}`;
24102
24341
  }
@@ -24128,10 +24367,10 @@ function calculateDepRisk(factors) {
24128
24367
  return Math.min(100, risk);
24129
24368
  }
24130
24369
  function getInstalledPackages(projectRoot) {
24131
- const pkgPath = resolve30(projectRoot, "package.json");
24132
- if (!existsSync35(pkgPath)) return /* @__PURE__ */ new Map();
24370
+ const pkgPath = resolve32(projectRoot, "package.json");
24371
+ if (!existsSync37(pkgPath)) return /* @__PURE__ */ new Map();
24133
24372
  try {
24134
- const pkg = JSON.parse(readFileSync36(pkgPath, "utf-8"));
24373
+ const pkg = JSON.parse(readFileSync38(pkgPath, "utf-8"));
24135
24374
  const packages = /* @__PURE__ */ new Map();
24136
24375
  for (const [name, version] of Object.entries(pkg.dependencies ?? {})) {
24137
24376
  packages.set(name, version);
@@ -24734,8 +24973,8 @@ var init_regression_detector = __esm({
24734
24973
 
24735
24974
  // src/knowledge-indexer.ts
24736
24975
  import { createHash as createHash9 } from "crypto";
24737
- import { readFileSync as readFileSync37, readdirSync as readdirSync23, statSync as statSync14, existsSync as existsSync36 } from "fs";
24738
- import { resolve as resolve31, relative as relative12, basename as basename8, extname as extname2 } from "path";
24976
+ import { readFileSync as readFileSync39, readdirSync as readdirSync24, statSync as statSync14, existsSync as existsSync38 } from "fs";
24977
+ import { resolve as resolve33, relative as relative12, basename as basename8, extname as extname2 } from "path";
24739
24978
  function getKnowledgePaths() {
24740
24979
  const resolved = getResolvedPaths();
24741
24980
  const config = getConfig();
@@ -24761,9 +25000,9 @@ function discoverMarkdownFiles(baseDir) {
24761
25000
  const files = [];
24762
25001
  function walk(dir) {
24763
25002
  try {
24764
- const entries = readdirSync23(dir, { withFileTypes: true });
25003
+ const entries = readdirSync24(dir, { withFileTypes: true });
24765
25004
  for (const entry of entries) {
24766
- const fullPath = resolve31(dir, entry.name);
25005
+ const fullPath = resolve33(dir, entry.name);
24767
25006
  if (entry.isDirectory()) {
24768
25007
  if (entry.name === "archive" && dir.includes("session-state")) continue;
24769
25008
  if (entry.name === "archive" && dir.includes("status")) continue;
@@ -25041,11 +25280,11 @@ function indexAllKnowledge(db) {
25041
25280
  files.push(...memFiles);
25042
25281
  } catch {
25043
25282
  }
25044
- if (existsSync36(paths.plansDir)) {
25283
+ if (existsSync38(paths.plansDir)) {
25045
25284
  const planFiles = discoverMarkdownFiles(paths.plansDir);
25046
25285
  files.push(...planFiles);
25047
25286
  }
25048
- if (existsSync36(paths.docsDir)) {
25287
+ if (existsSync38(paths.docsDir)) {
25049
25288
  const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
25050
25289
  const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
25051
25290
  files.push(...docsFiles);
@@ -25088,8 +25327,8 @@ function indexAllKnowledge(db) {
25088
25327
  } catch {
25089
25328
  }
25090
25329
  for (const filePath of files) {
25091
- if (!existsSync36(filePath)) continue;
25092
- const content = readFileSync37(filePath, "utf-8");
25330
+ if (!existsSync38(filePath)) continue;
25331
+ const content = readFileSync39(filePath, "utf-8");
25093
25332
  const hash = hashContent2(content);
25094
25333
  const relPath = filePath.startsWith(paths.claudeDir) ? relative12(paths.claudeDir, filePath) : filePath.startsWith(paths.plansDir) ? "plans/" + relative12(paths.plansDir, filePath) : filePath.startsWith(paths.docsDir) ? "docs/" + relative12(paths.docsDir, filePath) : filePath.startsWith(paths.memoryDir) ? `memory/${relative12(paths.memoryDir, filePath)}` : basename8(filePath);
25095
25334
  const category = categorizeFile(filePath);
@@ -25209,10 +25448,10 @@ function isKnowledgeStale(db) {
25209
25448
  files.push(...discoverMarkdownFiles(paths.memoryDir));
25210
25449
  } catch {
25211
25450
  }
25212
- if (existsSync36(paths.plansDir)) {
25451
+ if (existsSync38(paths.plansDir)) {
25213
25452
  files.push(...discoverMarkdownFiles(paths.plansDir));
25214
25453
  }
25215
- if (existsSync36(paths.docsDir)) {
25454
+ if (existsSync38(paths.docsDir)) {
25216
25455
  const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
25217
25456
  const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
25218
25457
  files.push(...docsFiles);
@@ -25241,8 +25480,8 @@ var init_knowledge_indexer = __esm({
25241
25480
  });
25242
25481
 
25243
25482
  // src/knowledge-tools.ts
25244
- import { readFileSync as readFileSync38, writeFileSync as writeFileSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync24 } from "fs";
25245
- import { resolve as resolve32, basename as basename9 } from "path";
25483
+ import { readFileSync as readFileSync40, writeFileSync as writeFileSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync25 } from "fs";
25484
+ import { resolve as resolve34, basename as basename9 } from "path";
25246
25485
  function p16(baseName) {
25247
25486
  return `${getConfig().toolPrefix}_${baseName}`;
25248
25487
  }
@@ -25979,7 +26218,7 @@ function handleCorrect(db, args2) {
25979
26218
  if (!wrong || !correction || !rule) {
25980
26219
  return text15("Error: wrong, correction, and rule are all required.");
25981
26220
  }
25982
- const correctionsPath = resolve32(getResolvedPaths().memoryDir, "corrections.md");
26221
+ const correctionsPath = resolve34(getResolvedPaths().memoryDir, "corrections.md");
25983
26222
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
25984
26223
  const title = rule.slice(0, 60);
25985
26224
  const entry = `
@@ -25992,7 +26231,7 @@ ${crRule ? `- **CR**: ${crRule}
25992
26231
  `;
25993
26232
  let existing = "";
25994
26233
  try {
25995
- existing = readFileSync38(correctionsPath, "utf-8");
26234
+ existing = readFileSync40(correctionsPath, "utf-8");
25996
26235
  } catch {
25997
26236
  }
25998
26237
  const archiveIdx = existing.indexOf("## Archived");
@@ -26174,7 +26413,7 @@ function handleGaps(db, args2) {
26174
26413
  } else if (checkType === "routers") {
26175
26414
  try {
26176
26415
  const routersDir = getResolvedPaths().routersDir;
26177
- const routerFiles = readdirSync24(routersDir).filter((f2) => f2.endsWith(".ts") && !f2.startsWith("_"));
26416
+ const routerFiles = readdirSync25(routersDir).filter((f2) => f2.endsWith(".ts") && !f2.startsWith("_"));
26178
26417
  lines.push(`| Router | Knowledge Hits | Status |`);
26179
26418
  lines.push(`|--------|----------------|--------|`);
26180
26419
  for (const file of routerFiles) {
@@ -26331,11 +26570,11 @@ var init_knowledge_tools = __esm({
26331
26570
  // src/knowledge-db.ts
26332
26571
  import Database3 from "better-sqlite3";
26333
26572
  import { dirname as dirname16 } from "path";
26334
- import { existsSync as existsSync38, mkdirSync as mkdirSync11 } from "fs";
26573
+ import { existsSync as existsSync40, mkdirSync as mkdirSync11 } from "fs";
26335
26574
  function getKnowledgeDb() {
26336
26575
  const dbPath = getResolvedPaths().knowledgeDbPath;
26337
26576
  const dir = dirname16(dbPath);
26338
- if (!existsSync38(dir)) {
26577
+ if (!existsSync40(dir)) {
26339
26578
  mkdirSync11(dir, { recursive: true });
26340
26579
  }
26341
26580
  const db = new Database3(dbPath);
@@ -27069,8 +27308,8 @@ var init_python_tools = __esm({
27069
27308
  });
27070
27309
 
27071
27310
  // src/tools.ts
27072
- import { readFileSync as readFileSync39, existsSync as existsSync39 } from "fs";
27073
- import { resolve as resolve33, basename as basename10 } from "path";
27311
+ import { readFileSync as readFileSync41, existsSync as existsSync41 } from "fs";
27312
+ import { resolve as resolve35, basename as basename10 } from "path";
27074
27313
  function prefix2() {
27075
27314
  return getConfig().toolPrefix;
27076
27315
  }
@@ -27105,7 +27344,7 @@ function ensureIndexes(dataDb, codegraphDb, force = false) {
27105
27344
  if (config.python?.root) {
27106
27345
  const pythonRoot = config.python.root;
27107
27346
  const excludeDirs = config.python.exclude_dirs || ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"];
27108
- if (force || isPythonDataStale(dataDb, resolve33(getProjectRoot(), pythonRoot))) {
27347
+ if (force || isPythonDataStale(dataDb, resolve35(getProjectRoot(), pythonRoot))) {
27109
27348
  const pyImports = buildPythonImportIndex(dataDb, pythonRoot, excludeDirs);
27110
27349
  results.push(`Python imports: ${pyImports}`);
27111
27350
  const pyRoutes = buildPythonRouteIndex(dataDb, pythonRoot, excludeDirs);
@@ -27540,9 +27779,9 @@ function handleContext(file, dataDb, codegraphDb) {
27540
27779
  try {
27541
27780
  const resolvedPaths = getResolvedPaths();
27542
27781
  const root = getProjectRoot();
27543
- const absFilePath = ensureWithinRoot(resolve33(resolvedPaths.srcDir, "..", file), root);
27544
- if (existsSync39(absFilePath)) {
27545
- const fileContent = readFileSync39(absFilePath, "utf-8").slice(0, 3e3);
27782
+ const absFilePath = ensureWithinRoot(resolve35(resolvedPaths.srcDir, "..", file), root);
27783
+ if (existsSync41(absFilePath)) {
27784
+ const fileContent = readFileSync41(absFilePath, "utf-8").slice(0, 3e3);
27546
27785
  const keywords = [];
27547
27786
  if (fileContent.includes("ctx.db")) keywords.push("database", "schema");
27548
27787
  if (fileContent.includes("BigInt") || fileContent.includes("Decimal")) keywords.push("BigInt", "serialization");
@@ -27966,11 +28205,11 @@ function handleSchema(args2) {
27966
28205
  lines.push("Checking all column references against Prisma schema...");
27967
28206
  lines.push("");
27968
28207
  const projectRoot = getProjectRoot();
27969
- const absPath = ensureWithinRoot(resolve33(projectRoot, file), projectRoot);
27970
- if (!existsSync39(absPath)) {
28208
+ const absPath = ensureWithinRoot(resolve35(projectRoot, file), projectRoot);
28209
+ if (!existsSync41(absPath)) {
27971
28210
  return text17(`File not found: ${file}`);
27972
28211
  }
27973
- const source = readFileSync39(absPath, "utf-8");
28212
+ const source = readFileSync41(absPath, "utf-8");
27974
28213
  const config = getConfig();
27975
28214
  const dbPattern = config.dbAccessPattern ?? "ctx.db.{table}";
27976
28215
  const regexStr = dbPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\{table\\}", "(\\w+)");
@@ -28339,8 +28578,8 @@ var init_server_dispatch = __esm({
28339
28578
 
28340
28579
  // src/server.ts
28341
28580
  var server_exports = {};
28342
- import { readFileSync as readFileSync40 } from "fs";
28343
- import { resolve as resolve34, dirname as dirname17 } from "path";
28581
+ import { readFileSync as readFileSync42 } from "fs";
28582
+ import { resolve as resolve36, dirname as dirname17 } from "path";
28344
28583
  import { fileURLToPath as fileURLToPath4 } from "url";
28345
28584
  function pruneMemoryOnStartup() {
28346
28585
  try {
@@ -28375,7 +28614,7 @@ var init_server = __esm({
28375
28614
  __dirname4 = dirname17(fileURLToPath4(import.meta.url));
28376
28615
  PKG_VERSION = (() => {
28377
28616
  try {
28378
- const pkg = JSON.parse(readFileSync40(resolve34(__dirname4, "..", "package.json"), "utf-8"));
28617
+ const pkg = JSON.parse(readFileSync42(resolve36(__dirname4, "..", "package.json"), "utf-8"));
28379
28618
  return pkg.version ?? "0.0.0";
28380
28619
  } catch {
28381
28620
  return "0.0.0";
@@ -28661,19 +28900,19 @@ var config_upgrade_exports = {};
28661
28900
  __export(config_upgrade_exports, {
28662
28901
  runConfigUpgrade: () => runConfigUpgrade
28663
28902
  });
28664
- import { existsSync as existsSync40, readFileSync as readFileSync41, writeFileSync as writeFileSync6, copyFileSync, unlinkSync as unlinkSync2 } from "fs";
28665
- import { resolve as resolve35 } from "path";
28903
+ import { existsSync as existsSync42, readFileSync as readFileSync43, writeFileSync as writeFileSync6, copyFileSync, unlinkSync as unlinkSync2 } from "fs";
28904
+ import { resolve as resolve37 } from "path";
28666
28905
  import { parse as parseYaml6 } from "yaml";
28667
28906
  async function runConfigUpgrade(opts = {}) {
28668
28907
  const cwd = opts.cwd ?? process.cwd();
28669
- const configPath = resolve35(cwd, "massu.config.yaml");
28908
+ const configPath = resolve37(cwd, "massu.config.yaml");
28670
28909
  const bakPath = `${configPath}.bak`;
28671
28910
  const log = opts.silent ? () => {
28672
28911
  } : (s) => process.stdout.write(s);
28673
28912
  const err = opts.silent ? () => {
28674
28913
  } : (s) => process.stderr.write(s);
28675
28914
  if (opts.rollback) {
28676
- if (!existsSync40(bakPath)) {
28915
+ if (!existsSync42(bakPath)) {
28677
28916
  const message = `No backup found at ${bakPath}`;
28678
28917
  err(message + "\n");
28679
28918
  return { exitCode: 1, action: "none", message };
@@ -28689,14 +28928,14 @@ async function runConfigUpgrade(opts = {}) {
28689
28928
  return { exitCode: 2, action: "none", message };
28690
28929
  }
28691
28930
  }
28692
- if (!existsSync40(configPath)) {
28931
+ if (!existsSync42(configPath)) {
28693
28932
  const message = "massu.config.yaml not found. Run: npx massu init";
28694
28933
  err(message + "\n");
28695
28934
  return { exitCode: 1, action: "none", message };
28696
28935
  }
28697
28936
  let existing;
28698
28937
  try {
28699
- const content = readFileSync41(configPath, "utf-8");
28938
+ const content = readFileSync43(configPath, "utf-8");
28700
28939
  const parsed = parseYaml6(content);
28701
28940
  if (!parsed || typeof parsed !== "object") {
28702
28941
  throw new Error("config is not a YAML object");
@@ -28719,7 +28958,7 @@ async function runConfigUpgrade(opts = {}) {
28719
28958
  fingerprint: computeFingerprint(detection)
28720
28959
  };
28721
28960
  try {
28722
- const original = readFileSync41(configPath, "utf-8");
28961
+ const original = readFileSync43(configPath, "utf-8");
28723
28962
  writeFileSync6(bakPath, original, "utf-8");
28724
28963
  } catch (e2) {
28725
28964
  const message = `Failed to write backup: ${e2 instanceof Error ? e2.message : String(e2)}`;
@@ -28753,8 +28992,8 @@ var config_check_drift_exports = {};
28753
28992
  __export(config_check_drift_exports, {
28754
28993
  runConfigCheckDrift: () => runConfigCheckDrift
28755
28994
  });
28756
- import { existsSync as existsSync41, readFileSync as readFileSync42 } from "fs";
28757
- import { resolve as resolve36 } from "path";
28995
+ import { existsSync as existsSync43, readFileSync as readFileSync44 } from "fs";
28996
+ import { resolve as resolve38 } from "path";
28758
28997
  import { parse as parseYaml7 } from "yaml";
28759
28998
  function renderChanges(changes) {
28760
28999
  if (changes.length === 0) return "(none)\n";
@@ -28762,12 +29001,12 @@ function renderChanges(changes) {
28762
29001
  }
28763
29002
  async function runConfigCheckDrift(opts = {}) {
28764
29003
  const cwd = opts.cwd ?? process.cwd();
28765
- const configPath = resolve36(cwd, "massu.config.yaml");
29004
+ const configPath = resolve38(cwd, "massu.config.yaml");
28766
29005
  const log = opts.silent ? () => {
28767
29006
  } : (s) => process.stdout.write(s);
28768
29007
  const err = opts.silent ? () => {
28769
29008
  } : (s) => process.stderr.write(s);
28770
- if (!existsSync41(configPath)) {
29009
+ if (!existsSync43(configPath)) {
28771
29010
  const message = "massu.config.yaml not found. Run: npx massu init";
28772
29011
  err(message + "\n");
28773
29012
  return {
@@ -28781,7 +29020,7 @@ async function runConfigCheckDrift(opts = {}) {
28781
29020
  }
28782
29021
  let config;
28783
29022
  try {
28784
- const content = readFileSync42(configPath, "utf-8");
29023
+ const content = readFileSync44(configPath, "utf-8");
28785
29024
  const parsed = parseYaml7(content);
28786
29025
  if (!parsed || typeof parsed !== "object") {
28787
29026
  throw new Error("config is not a YAML object");
@@ -28848,8 +29087,8 @@ var init_config_check_drift = __esm({
28848
29087
  });
28849
29088
 
28850
29089
  // src/cli.ts
28851
- import { readFileSync as readFileSync43 } from "fs";
28852
- import { resolve as resolve37, dirname as dirname18 } from "path";
29090
+ import { readFileSync as readFileSync45 } from "fs";
29091
+ import { resolve as resolve39, dirname as dirname18 } from "path";
28853
29092
  import { fileURLToPath as fileURLToPath5 } from "url";
28854
29093
  var __filename4 = fileURLToPath5(import.meta.url);
28855
29094
  var __dirname5 = dirname18(__filename4);
@@ -28883,6 +29122,12 @@ async function main() {
28883
29122
  process.exit(result.exitCode);
28884
29123
  return;
28885
29124
  }
29125
+ case "changelog": {
29126
+ const { handleChangelogSubcommand: handleChangelogSubcommand2 } = await Promise.resolve().then(() => (init_changelog(), changelog_exports));
29127
+ const result = await handleChangelogSubcommand2(args.slice(1));
29128
+ process.exit(result.exitCode);
29129
+ return;
29130
+ }
28886
29131
  case "show-template": {
28887
29132
  const { runShowTemplate: runShowTemplate2 } = await Promise.resolve().then(() => (init_show_template(), show_template_exports));
28888
29133
  await runShowTemplate2(args.slice(1));
@@ -29002,6 +29247,7 @@ Commands:
29002
29247
  validate-config Validate massu.config.yaml (alias: config validate)
29003
29248
  config <sub> Config lifecycle: refresh | validate | upgrade | doctor | check-drift
29004
29249
  permissions <sub> MCP permission lifecycle: install | verify | check-drift
29250
+ changelog <sub> CHANGELOG generation / verification: generate | verify
29005
29251
  adapters <sub> Third-party adapter registry: list | refresh | search | add-local | remove-local | install | resign
29006
29252
 
29007
29253
  Options:
@@ -29041,7 +29287,7 @@ Examples:
29041
29287
  }
29042
29288
  function printVersion() {
29043
29289
  try {
29044
- const pkg = JSON.parse(readFileSync43(resolve37(__dirname5, "../package.json"), "utf-8"));
29290
+ const pkg = JSON.parse(readFileSync45(resolve39(__dirname5, "../package.json"), "utf-8"));
29045
29291
  console.log(`massu v${pkg.version}`);
29046
29292
  } catch {
29047
29293
  console.log("massu v0.1.0");