caveat-cli 0.18.0 → 0.19.1

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/index.js CHANGED
@@ -7,7 +7,6 @@ import {
7
7
  CAVEAT_AUTO_SYNC_ENV,
8
8
  KNOWLEDGE_GITIGNORE,
9
9
  PublishScanError,
10
- SyncError,
11
10
  __commonJS,
12
11
  __export,
13
12
  __toESM,
@@ -76,7 +75,7 @@ import {
76
75
  userPromptSubmitReminderText,
77
76
  writeDigestMarker,
78
77
  writeUserConfigPatch
79
- } from "./chunk-KAULUIC4.js";
78
+ } from "./chunk-NZD3FHU6.js";
80
79
 
81
80
  // ../../node_modules/.pnpm/ajv@8.18.0/node_modules/ajv/dist/compile/codegen/code.js
82
81
  var require_code = __commonJS({
@@ -206,10 +205,10 @@ var require_code = __commonJS({
206
205
  function interpolate(x) {
207
206
  return typeof x == "number" || typeof x == "boolean" || x === null ? x : safeStringify(Array.isArray(x) ? x.join(",") : x);
208
207
  }
209
- function stringify(x) {
208
+ function stringify2(x) {
210
209
  return new _Code(safeStringify(x));
211
210
  }
212
- exports.stringify = stringify;
211
+ exports.stringify = stringify2;
213
212
  function safeStringify(x) {
214
213
  return JSON.stringify(x).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
215
214
  }
@@ -3624,24 +3623,24 @@ var require_fast_uri = __commonJS({
3624
3623
  function normalize(uri, options) {
3625
3624
  if (typeof uri === "string") {
3626
3625
  uri = /** @type {T} */
3627
- serialize(parse3(uri, options), options);
3626
+ serialize(parse4(uri, options), options);
3628
3627
  } else if (typeof uri === "object") {
3629
3628
  uri = /** @type {T} */
3630
- parse3(serialize(uri, options), options);
3629
+ parse4(serialize(uri, options), options);
3631
3630
  }
3632
3631
  return uri;
3633
3632
  }
3634
3633
  function resolve(baseURI, relativeURI, options) {
3635
3634
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3636
- const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
3635
+ const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
3637
3636
  schemelessOptions.skipEscape = true;
3638
3637
  return serialize(resolved, schemelessOptions);
3639
3638
  }
3640
3639
  function resolveComponent(base, relative, options, skipNormalization) {
3641
3640
  const target = {};
3642
3641
  if (!skipNormalization) {
3643
- base = parse3(serialize(base, options), options);
3644
- relative = parse3(serialize(relative, options), options);
3642
+ base = parse4(serialize(base, options), options);
3643
+ relative = parse4(serialize(relative, options), options);
3645
3644
  }
3646
3645
  options = options || {};
3647
3646
  if (!options.tolerant && relative.scheme) {
@@ -3693,13 +3692,13 @@ var require_fast_uri = __commonJS({
3693
3692
  function equal(uriA, uriB, options) {
3694
3693
  if (typeof uriA === "string") {
3695
3694
  uriA = unescape(uriA);
3696
- uriA = serialize(normalizeComponentEncoding(parse3(uriA, options), true), { ...options, skipEscape: true });
3695
+ uriA = serialize(normalizeComponentEncoding(parse4(uriA, options), true), { ...options, skipEscape: true });
3697
3696
  } else if (typeof uriA === "object") {
3698
3697
  uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
3699
3698
  }
3700
3699
  if (typeof uriB === "string") {
3701
3700
  uriB = unescape(uriB);
3702
- uriB = serialize(normalizeComponentEncoding(parse3(uriB, options), true), { ...options, skipEscape: true });
3701
+ uriB = serialize(normalizeComponentEncoding(parse4(uriB, options), true), { ...options, skipEscape: true });
3703
3702
  } else if (typeof uriB === "object") {
3704
3703
  uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
3705
3704
  }
@@ -3768,7 +3767,7 @@ var require_fast_uri = __commonJS({
3768
3767
  return uriTokens.join("");
3769
3768
  }
3770
3769
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
3771
- function parse3(uri, opts) {
3770
+ function parse4(uri, opts) {
3772
3771
  const options = Object.assign({}, opts);
3773
3772
  const parsed = {
3774
3773
  scheme: void 0,
@@ -3862,7 +3861,7 @@ var require_fast_uri = __commonJS({
3862
3861
  resolveComponent,
3863
3862
  equal,
3864
3863
  serialize,
3865
- parse: parse3
3864
+ parse: parse4
3866
3865
  };
3867
3866
  module.exports = fastUri;
3868
3867
  module.exports.default = fastUri;
@@ -6888,18 +6887,18 @@ var stdoutLogger = {
6888
6887
  };
6889
6888
 
6890
6889
  // src/commands/init.ts
6891
- import { spawnSync as spawnSync4 } from "node:child_process";
6892
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readdirSync, renameSync, rmdirSync, writeFileSync as writeFileSync3 } from "node:fs";
6893
- import { dirname as dirname3, join as join9 } from "node:path";
6890
+ import { spawnSync as spawnSync3 } from "node:child_process";
6891
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync, rmdirSync, writeFileSync as writeFileSync3 } from "node:fs";
6892
+ import { dirname as dirname3, join as join10 } from "node:path";
6894
6893
 
6895
6894
  // src/claudeInstall.ts
6896
- import { spawnSync } from "node:child_process";
6897
- import { constants, existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6898
- import { join as join3 } from "node:path";
6895
+ import { constants, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
6896
+ import { join as join4 } from "node:path";
6899
6897
 
6900
6898
  // src/installShared.ts
6901
6899
  import { accessSync, copyFileSync, existsSync, mkdirSync, realpathSync, statSync, writeFileSync } from "node:fs";
6902
- import { dirname as dirname2, isAbsolute } from "node:path";
6900
+ import { dirname as dirname2, isAbsolute, join as join3 } from "node:path";
6901
+ import { homedir as homedir2 } from "node:os";
6903
6902
  function quoteCommandPath(p) {
6904
6903
  return /[\s\\]/.test(p) ? `"${p}"` : p;
6905
6904
  }
@@ -6939,15 +6938,73 @@ function writeJsonWithBackup(path, value) {
6939
6938
  return writeFileWithBackup(path, `${JSON.stringify(value, null, 2)}
6940
6939
  `);
6941
6940
  }
6941
+ function resolveAgentConfigPaths(userHome = homedir2(), env = process.env) {
6942
+ const claudeDir = env.CLAUDE_CONFIG_DIR || join3(userHome, ".claude");
6943
+ return {
6944
+ claudeDir,
6945
+ claudeMcp: claudeMcpConfigPath(claudeDir, env),
6946
+ codexHome: env.CODEX_HOME || join3(userHome, ".codex"),
6947
+ grokHome: env.GROK_HOME || join3(userHome, ".grok"),
6948
+ cursorDir: env.CURSOR_HOME || join3(userHome, ".cursor")
6949
+ };
6950
+ }
6951
+ function claudeMcpConfigPath(claudeDir, env = process.env) {
6952
+ return join3(env.CLAUDE_CONFIG_DIR ? claudeDir : dirname2(claudeDir), ".claude.json");
6953
+ }
6954
+
6955
+ // src/mcpInstall.ts
6956
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6957
+ import { isDeepStrictEqual } from "node:util";
6958
+ import { parse, stringify } from "smol-toml";
6959
+ function object(value) {
6960
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6961
+ }
6962
+ function installMcpClient(options) {
6963
+ return updateMcpClient(options, (previous) => ({
6964
+ ...previous,
6965
+ ...options.client === "claude" ? { type: "stdio", env: previous?.env ?? {} } : {},
6966
+ command: options.nodePath,
6967
+ args: ["--disable-warning=ExperimentalWarning", options.cliScriptPath, "mcp-server"]
6968
+ }));
6969
+ }
6970
+ function uninstallMcpClient(options) {
6971
+ return updateMcpClient(options, () => void 0);
6972
+ }
6973
+ function updateMcpClient(options, update) {
6974
+ const { client, configPath, dryRun } = options;
6975
+ const json2 = client === "cursor" || client === "claude";
6976
+ const decode3 = (text) => json2 ? JSON.parse(text) : parse(text);
6977
+ const current = existsSync2(configPath) ? decode3(readFileSync2(configPath, "utf8")) : {};
6978
+ const key = json2 ? "mcpServers" : "mcp_servers";
6979
+ if (!object(current) || current[key] !== void 0 && !object(current[key])) {
6980
+ throw new Error(`mcp_config_invalid: ${client}\u306EMCP\u8A2D\u5B9A\u304Cobject\u3067\u306F\u3042\u308A\u307E\u305B\u3093`);
6981
+ }
6982
+ const servers = current[key] ?? {};
6983
+ if (servers.caveat !== void 0 && !object(servers.caveat)) {
6984
+ throw new Error(`mcp_config_invalid: ${client}\u306ECaveat\u767B\u9332\u304Cobject\u3067\u306F\u3042\u308A\u307E\u305B\u3093`);
6985
+ }
6986
+ const previous = servers.caveat;
6987
+ const registration = update(previous);
6988
+ if (isDeepStrictEqual(previous, registration)) return "unchanged";
6989
+ if (dryRun) return "dry-run";
6990
+ const nextServers = { ...servers };
6991
+ if (registration === void 0) delete nextServers.caveat;
6992
+ else nextServers.caveat = registration;
6993
+ const next = { ...current, [key]: nextServers };
6994
+ writeFileWithBackup(configPath, json2 ? `${JSON.stringify(next, null, 2)}
6995
+ ` : stringify(next));
6996
+ const observed = decode3(readFileSync2(configPath, "utf8"));
6997
+ if (!isDeepStrictEqual(observed, next)) {
6998
+ throw new Error(`mcp_config_readback_failed: ${client}\u306E\u8A2D\u5B9A\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093`);
6999
+ }
7000
+ return "configured";
7001
+ }
6942
7002
 
6943
7003
  // src/claudeInstall.ts
6944
7004
  var EVENT_USER_PROMPT_SUBMIT = "UserPromptSubmit";
6945
7005
  var EVENT_POST_TOOL_USE = "PostToolUse";
6946
7006
  var EVENT_POST_TOOL_USE_FAILURE = "PostToolUseFailure";
6947
7007
  var EVENT_STOP = "Stop";
6948
- function mcpArgs(cliScriptPath) {
6949
- return ["--disable-warning=ExperimentalWarning", cliScriptPath, "mcp-server"];
6950
- }
6951
7008
  function hookCommand(nodePath, cliScriptPath, event) {
6952
7009
  return `${quoteCommandPath(nodePath)} ${quoteCommandPath(cliScriptPath)} hook ${event}`;
6953
7010
  }
@@ -6999,79 +7056,37 @@ function isCaveatClaudeHookCommand(actual, event) {
6999
7056
  }
7000
7057
  function isCanonicalCaveatClaudeHookCommand(actual, event, nodePath, cliScriptPath) {
7001
7058
  const tokens = commandTokens(actual);
7002
- if (tokens?.length !== 4 || tokens[2] !== "hook" || tokens[3] !== event) return false;
7003
- if (actual !== hookCommand(tokens[0], tokens[1], event)) return false;
7004
- return isCanonicalAsset(tokens[0], nodePath, constants.X_OK) && isCanonicalAsset(tokens[1], cliScriptPath, constants.R_OK);
7059
+ const [actualNodePath, actualCliScriptPath, subcommand, actualEvent] = tokens ?? [];
7060
+ if (tokens?.length !== 4 || actualNodePath === void 0 || actualCliScriptPath === void 0 || subcommand !== "hook" || actualEvent !== event) return false;
7061
+ if (actual !== hookCommand(actualNodePath, actualCliScriptPath, event)) return false;
7062
+ return isCanonicalAsset(actualNodePath, nodePath, constants.X_OK) && isCanonicalAsset(actualCliScriptPath, cliScriptPath, constants.R_OK);
7005
7063
  }
7006
7064
  function isCaveatClaudeMcpRegistration(value, nodePath, cliScriptPath) {
7007
7065
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
7008
7066
  const server = value;
7009
- return Object.keys(server).length === 4 && ["args", "command", "env", "type"].every((key) => Object.hasOwn(server, key)) && server.type === "stdio" && isCanonicalAsset(server.command, nodePath, constants.X_OK) && Array.isArray(server.args) && server.args.length === 3 && server.args[0] === "--disable-warning=ExperimentalWarning" && isCanonicalAsset(server.args[1], cliScriptPath, constants.R_OK) && server.args[2] === "mcp-server" && server.env !== null && typeof server.env === "object" && !Array.isArray(server.env) && Object.keys(server.env).length === 0;
7067
+ return ["args", "command", "env", "type"].every((key) => Object.hasOwn(server, key)) && server.type === "stdio" && isCanonicalAsset(server.command, nodePath, constants.X_OK) && Array.isArray(server.args) && server.args.length === 3 && server.args[0] === "--disable-warning=ExperimentalWarning" && isCanonicalAsset(server.args[1], cliScriptPath, constants.R_OK) && server.args[2] === "mcp-server" && server.env !== null && typeof server.env === "object" && !Array.isArray(server.env) && Object.values(server.env).every((value2) => typeof value2 === "string");
7010
7068
  }
7011
7069
  function readSettings(path) {
7012
- if (!existsSync2(path)) return {};
7013
- return JSON.parse(readFileSync2(path, "utf-8"));
7070
+ if (!existsSync3(path)) return {};
7071
+ return JSON.parse(readFileSync3(path, "utf-8"));
7014
7072
  }
7015
7073
  function writeSettings(path, settings) {
7016
7074
  return writeJsonWithBackup(path, settings);
7017
7075
  }
7018
- var CLAUDE_BIN = "claude";
7019
- function shellQuote(s) {
7020
- return /[\s&|<>^()]/.test(s) ? `"${s}"` : s;
7021
- }
7022
- function runClaude(args) {
7023
- const line = [CLAUDE_BIN, ...args].map(shellQuote).join(" ");
7024
- return spawnSync(line, { shell: true, encoding: "utf-8" });
7025
- }
7026
- function registerMcp(nodePath, cliScriptPath, dryRun, logger) {
7027
- const args = mcpArgs(cliScriptPath);
7028
- if (dryRun) {
7029
- logger.info(
7030
- `[dry-run] claude mcp add --scope user caveat -- ${nodePath} ${args.join(" ")}`
7031
- );
7032
- return { action: "skipped", detail: "dry-run" };
7033
- }
7034
- runClaude(["mcp", "remove", "--scope", "user", "caveat"]);
7035
- const result = runClaude([
7036
- "mcp",
7037
- "add",
7038
- "--scope",
7039
- "user",
7040
- "caveat",
7041
- "--",
7042
- nodePath,
7043
- ...args
7044
- ]);
7045
- if (result.status === 0) {
7046
- return { action: "registered" };
7047
- }
7048
- if (result.error && "code" in result.error && result.error.code === "ENOENT") {
7049
- return {
7050
- action: "skipped",
7051
- detail: "claude CLI not found in PATH; install Claude Code to enable MCP"
7052
- };
7053
- }
7054
- const stderr = typeof result.stderr === "string" ? result.stderr : "";
7055
- const stdout = typeof result.stdout === "string" ? result.stdout : "";
7056
- return {
7057
- action: "failed",
7058
- detail: (stderr || stdout || "unknown error").trim()
7059
- };
7060
- }
7061
- function unregisterMcp(dryRun, logger) {
7062
- if (dryRun) {
7063
- logger.info("[dry-run] claude mcp remove --scope user caveat");
7064
- return { action: "skipped", detail: "dry-run" };
7065
- }
7066
- const result = runClaude(["mcp", "remove", "--scope", "user", "caveat"]);
7067
- if (result.status === 0) return { action: "registered", detail: "removed" };
7068
- if (result.error && "code" in result.error && result.error.code === "ENOENT") {
7069
- return { action: "skipped", detail: "claude CLI not found" };
7076
+ function configureMcp(opts, remove = false) {
7077
+ const configPath = opts.mcpConfigPath ?? claudeMcpConfigPath(opts.claudeDir);
7078
+ try {
7079
+ const options = { client: "claude", configPath, dryRun: opts.dryRun };
7080
+ const action = remove ? uninstallMcpClient(options) : installMcpClient({ ...options, nodePath: opts.nodePath, cliScriptPath: opts.cliScriptPath });
7081
+ const detail = remove && action === "configured" ? "removed" : action;
7082
+ opts.logger.info(`Claude MCP: ${detail}`);
7083
+ return { action: opts.dryRun ? "skipped" : "registered", detail };
7084
+ } catch (error51) {
7085
+ return { action: "failed", detail: error51 instanceof Error ? error51.message : String(error51) };
7070
7086
  }
7071
- return { action: "skipped", detail: "not registered or removal failed" };
7072
7087
  }
7073
7088
  function installClaudeIntegration(opts) {
7074
- const settingsPath = join3(opts.claudeDir, "settings.json");
7089
+ const settingsPath = join4(opts.claudeDir, "settings.json");
7075
7090
  const settings = readSettings(settingsPath);
7076
7091
  const usCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "user-prompt-submit");
7077
7092
  const ptCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "post-tool-use");
@@ -7095,7 +7110,7 @@ function installClaudeIntegration(opts) {
7095
7110
  `[dry-run] would ${userPromptSubmit === "added" ? "add" : "keep"} UserPromptSubmit, ${postToolUse === "added" ? "add" : "keep"} PostToolUse, ${postToolUseFailure === "added" ? "add" : "keep"} PostToolUseFailure, ${stop === "added" ? "add" : "keep"} Stop hook in ${settingsPath}`
7096
7111
  );
7097
7112
  }
7098
- const mcp = opts.skipMcpRegistration ? { action: "skipped", detail: "skipped by caller" } : registerMcp(opts.nodePath, opts.cliScriptPath, opts.dryRun, opts.logger);
7113
+ const mcp = opts.skipMcpRegistration ? { action: "skipped", detail: "skipped by caller" } : configureMcp(opts);
7099
7114
  return {
7100
7115
  mcp,
7101
7116
  hooks: { userPromptSubmit, postToolUse, postToolUseFailure, stop },
@@ -7103,7 +7118,7 @@ function installClaudeIntegration(opts) {
7103
7118
  };
7104
7119
  }
7105
7120
  function uninstallClaudeIntegration(opts) {
7106
- const settingsPath = join3(opts.claudeDir, "settings.json");
7121
+ const settingsPath = join4(opts.claudeDir, "settings.json");
7107
7122
  const settings = readSettings(settingsPath);
7108
7123
  const usCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "user-prompt-submit");
7109
7124
  const ptCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "post-tool-use");
@@ -7117,7 +7132,7 @@ function uninstallClaudeIntegration(opts) {
7117
7132
  const backup = writeSettings(settingsPath, settings);
7118
7133
  if (backup) backupPath = backup;
7119
7134
  }
7120
- const mcp = opts.skipMcpRegistration ? { action: "skipped", detail: "skipped by caller" } : unregisterMcp(opts.dryRun, opts.logger);
7135
+ const mcp = opts.skipMcpRegistration ? { action: "skipped", detail: "skipped by caller" } : configureMcp(opts, true);
7121
7136
  return {
7122
7137
  mcp,
7123
7138
  hooks: {
@@ -7131,8 +7146,8 @@ function uninstallClaudeIntegration(opts) {
7131
7146
  }
7132
7147
 
7133
7148
  // src/codexHookInstall.ts
7134
- import { constants as constants2, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
7135
- import { join as join4 } from "node:path";
7149
+ import { constants as constants2, existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
7150
+ import { join as join5 } from "node:path";
7136
7151
  import { parse as parseToml } from "smol-toml";
7137
7152
  function hookCommand2(nodePath, cliScriptPath, event, platform = process.platform) {
7138
7153
  return `${powershellCallPrefix(platform)}${quoteCommandPath(nodePath)} ${quoteCommandPath(cliScriptPath)} codex-hook ${event}`;
@@ -7168,8 +7183,8 @@ function hasCaveatHook(hooksJson, event, fragment) {
7168
7183
  ) ?? false;
7169
7184
  }
7170
7185
  function readHooks(path) {
7171
- if (!existsSync3(path)) return {};
7172
- return JSON.parse(readFileSync3(path, "utf-8"));
7186
+ if (!existsSync4(path)) return {};
7187
+ return JSON.parse(readFileSync4(path, "utf-8"));
7173
7188
  }
7174
7189
  function upsertHook2(hooksJson, event, command, subcommand) {
7175
7190
  hooksJson.hooks ??= {};
@@ -7393,9 +7408,9 @@ function maskTomlStringsAndComments(raw) {
7393
7408
  return output;
7394
7409
  }
7395
7410
  function installCodexHooks(opts) {
7396
- const hooksPath = join4(opts.codexHome, "hooks.json");
7397
- const configPath = join4(opts.codexHome, "config.toml");
7398
- const rawConfig = existsSync3(configPath) ? readFileSync3(configPath, "utf-8") : "";
7411
+ const hooksPath = join5(opts.codexHome, "hooks.json");
7412
+ const configPath = join5(opts.codexHome, "config.toml");
7413
+ const rawConfig = existsSync4(configPath) ? readFileSync4(configPath, "utf-8") : "";
7399
7414
  const enabled = enableCodexHooksFeature(rawConfig);
7400
7415
  if (enabled.status === "blocked") {
7401
7416
  return {
@@ -7447,7 +7462,7 @@ function installCodexHooks(opts) {
7447
7462
  };
7448
7463
  }
7449
7464
  function uninstallCodexHooks(opts) {
7450
- const hooksPath = join4(opts.codexHome, "hooks.json");
7465
+ const hooksPath = join5(opts.codexHome, "hooks.json");
7451
7466
  const hooksJson = readHooks(hooksPath);
7452
7467
  const userPromptSubmitRemoved = removeHook2(
7453
7468
  hooksJson,
@@ -7485,7 +7500,7 @@ function uninstallCodexHooks(opts) {
7485
7500
  };
7486
7501
  }
7487
7502
  function detectCodexHookInstallation(codexHome) {
7488
- const hooksPath = join4(codexHome, "hooks.json");
7503
+ const hooksPath = join5(codexHome, "hooks.json");
7489
7504
  const hooksJson = readHooks(hooksPath);
7490
7505
  const hooks = {
7491
7506
  userPromptSubmit: hasCaveatHook(
@@ -7513,8 +7528,8 @@ function detectCodexHookInstallation(codexHome) {
7513
7528
  }
7514
7529
 
7515
7530
  // src/cursorInstall.ts
7516
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "node:fs";
7517
- import { join as join5 } from "node:path";
7531
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "node:fs";
7532
+ import { join as join6 } from "node:path";
7518
7533
  import { constants as constants3 } from "node:fs";
7519
7534
  var TIMEOUT_SEC = 10;
7520
7535
  function hookCommand3(nodePath, cliScriptPath, event) {
@@ -7527,9 +7542,18 @@ function isCaveatCursorHookCommand(actual, event) {
7527
7542
  const lower = actual.toLowerCase();
7528
7543
  return lower.includes("caveat") && actual.includes(eventCommandFragment2(event));
7529
7544
  }
7545
+ function isCanonicalCaveatCursorHookCommand(actual, event, nodePath, cliScriptPath) {
7546
+ const tokens = commandTokens(actual);
7547
+ return tokens?.length === 4 && isCanonicalAsset(tokens[0], nodePath, constants3.X_OK) && isCanonicalAsset(tokens[1], cliScriptPath, constants3.R_OK) && tokens[2] === "cursor-hook" && tokens[3] === event;
7548
+ }
7549
+ function isCanonicalCaveatCursorHookEntry(value, event, nodePath, cliScriptPath) {
7550
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
7551
+ const entry = value;
7552
+ return typeof entry.command === "string" && isCanonicalCaveatCursorHookCommand(entry.command, event, nodePath, cliScriptPath) && entry.timeout === TIMEOUT_SEC;
7553
+ }
7530
7554
  function readHooks2(path) {
7531
- if (!existsSync4(path)) return { version: 1, hooks: {} };
7532
- const parsed = JSON.parse(readFileSync4(path, "utf-8"));
7555
+ if (!existsSync5(path)) return { version: 1, hooks: {} };
7556
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
7533
7557
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
7534
7558
  throw new Error(`${path} \u306F object \u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059`);
7535
7559
  }
@@ -7588,7 +7612,7 @@ function hasCaveatHook2(file2, event, fragment) {
7588
7612
  );
7589
7613
  }
7590
7614
  function persist(opts, file2, changed) {
7591
- const hooksPath = join5(opts.cursorDir, "hooks.json");
7615
+ const hooksPath = join6(opts.cursorDir, "hooks.json");
7592
7616
  if (opts.dryRun) {
7593
7617
  opts.logger.info(`[dry-run] would write Cursor hooks to ${hooksPath}`);
7594
7618
  return void 0;
@@ -7600,7 +7624,7 @@ function persist(opts, file2, changed) {
7600
7624
  return backup || void 0;
7601
7625
  }
7602
7626
  function installCursorHooks(opts) {
7603
- const hooksPath = join5(opts.cursorDir, "hooks.json");
7627
+ const hooksPath = join6(opts.cursorDir, "hooks.json");
7604
7628
  const file2 = readHooks2(hooksPath);
7605
7629
  const promptCmd = hookCommand3(opts.nodePath, opts.cliScriptPath, "user-prompt-submit");
7606
7630
  const toolCmd = hookCommand3(opts.nodePath, opts.cliScriptPath, "post-tool-use");
@@ -7616,7 +7640,7 @@ function installCursorHooks(opts) {
7616
7640
  return { hooks, backupPath };
7617
7641
  }
7618
7642
  function uninstallCursorHooks(opts) {
7619
- const hooksPath = join5(opts.cursorDir, "hooks.json");
7643
+ const hooksPath = join6(opts.cursorDir, "hooks.json");
7620
7644
  const file2 = readHooks2(hooksPath);
7621
7645
  const promptCmd = hookCommand3(opts.nodePath, opts.cliScriptPath, "user-prompt-submit");
7622
7646
  const toolCmd = hookCommand3(opts.nodePath, opts.cliScriptPath, "post-tool-use");
@@ -7640,8 +7664,8 @@ function uninstallCursorHooks(opts) {
7640
7664
  };
7641
7665
  }
7642
7666
  function detectCursorHookInstallation(cursorDir) {
7643
- const hooksPath = join5(cursorDir, "hooks.json");
7644
- const file2 = existsSync4(hooksPath) ? readHooks2(hooksPath) : { version: 1, hooks: {} };
7667
+ const hooksPath = join6(cursorDir, "hooks.json");
7668
+ const file2 = existsSync5(hooksPath) ? readHooks2(hooksPath) : { version: 1, hooks: {} };
7645
7669
  const hooks = {
7646
7670
  beforeSubmitPrompt: hasCaveatHook2(file2, "beforeSubmitPrompt", eventCommandFragment2("user-prompt-submit")),
7647
7671
  postToolUse: hasCaveatHook2(file2, "postToolUse", eventCommandFragment2("post-tool-use")),
@@ -7655,12 +7679,44 @@ function detectCursorHookInstallation(cursorDir) {
7655
7679
  hooks
7656
7680
  };
7657
7681
  }
7682
+ function diagnoseCursorHookConnector(cursorDir, nodePath, cliScriptPath) {
7683
+ const ready = () => ({ status: "ready", reason_code: "ready" });
7684
+ const notReady = () => ({ status: "not_ready", reason_code: "not_installed" });
7685
+ const unreadable = () => ({ status: "unverified", reason_code: "config_unreadable" });
7686
+ const unreadableHooks = {
7687
+ before_submit_prompt: unreadable(),
7688
+ post_tool_use: unreadable(),
7689
+ post_tool_use_failure: unreadable(),
7690
+ stop: unreadable()
7691
+ };
7692
+ const hooksPath = join6(cursorDir, "hooks.json");
7693
+ let file2;
7694
+ try {
7695
+ file2 = existsSync5(hooksPath) ? readHooks2(hooksPath) : { version: 1, hooks: {} };
7696
+ } catch {
7697
+ return { compatibility_status: "unverified", hooks: unreadableHooks };
7698
+ }
7699
+ const exact = (event, subcommand) => listFor(file2, event).some(
7700
+ (entry) => isCanonicalCaveatCursorHookEntry(entry, subcommand, nodePath, cliScriptPath)
7701
+ ) ? ready() : notReady();
7702
+ const hooks = {
7703
+ before_submit_prompt: exact("beforeSubmitPrompt", "user-prompt-submit"),
7704
+ post_tool_use: exact("postToolUse", "post-tool-use"),
7705
+ post_tool_use_failure: exact("postToolUseFailure", "post-tool-use"),
7706
+ stop: exact("stop", "stop")
7707
+ };
7708
+ const statuses = Object.values(hooks).map((item) => item.status);
7709
+ return {
7710
+ compatibility_status: statuses.includes("not_ready") ? "not_ready" : statuses.includes("unverified") ? "unverified" : "ready",
7711
+ hooks
7712
+ };
7713
+ }
7658
7714
 
7659
7715
  // src/ghSetup.ts
7660
- import { spawnSync as spawnSync2 } from "node:child_process";
7716
+ import { spawnSync } from "node:child_process";
7661
7717
  import { readSync } from "node:fs";
7662
7718
  function runGh(args) {
7663
- const result = spawnSync2("gh", args, { encoding: "utf-8" });
7719
+ const result = spawnSync("gh", args, { encoding: "utf-8" });
7664
7720
  return { status: result.status, stdout: typeof result.stdout === "string" ? result.stdout : "", stderr: typeof result.stderr === "string" ? result.stderr : "" };
7665
7721
  }
7666
7722
  function commandError(result, fallback) {
@@ -7680,6 +7736,10 @@ function defaultGitHubRepoUrl(opts) {
7680
7736
  throw new Error(`gh is not authenticated; run \`gh auth login\`, then retry \`${opts.retryCommand}\``);
7681
7737
  }
7682
7738
  const login = user.stdout.trim();
7739
+ const setupGit = opts.ghRunner(["auth", "setup-git"]);
7740
+ if (setupGit.status !== 0) {
7741
+ throw commandError(setupGit, "gh auth setup-git failed");
7742
+ }
7683
7743
  const qualifiedName = `${login}/${opts.repositoryName}`;
7684
7744
  const view = opts.ghRunner(["repo", "view", qualifiedName]);
7685
7745
  if (view.status !== 0) {
@@ -7703,8 +7763,8 @@ function askOnce(question) {
7703
7763
  }
7704
7764
 
7705
7765
  // src/nodePath.ts
7706
- import { existsSync as existsSync5, realpathSync as realpathSync2 } from "node:fs";
7707
- import { delimiter, join as join6 } from "node:path";
7766
+ import { existsSync as existsSync6, realpathSync as realpathSync2 } from "node:fs";
7767
+ import { delimiter, join as join7 } from "node:path";
7708
7768
  var defaultRealpath = (path) => realpathSync2.native(path);
7709
7769
  function safeRealpath(path, realpath = defaultRealpath) {
7710
7770
  try {
@@ -7717,7 +7777,7 @@ function resolveHookNodePath({
7717
7777
  env = process.env,
7718
7778
  execPath = process.execPath,
7719
7779
  platform = process.platform,
7720
- exists = existsSync5,
7780
+ exists = existsSync6,
7721
7781
  realpath = defaultRealpath
7722
7782
  } = {}) {
7723
7783
  const execRealpath = safeRealpath(execPath, realpath);
@@ -7725,7 +7785,7 @@ function resolveHookNodePath({
7725
7785
  const names = nodeExecutableNames(platform);
7726
7786
  for (const dir of pathEnv.split(delimiter).filter(Boolean)) {
7727
7787
  for (const name of names) {
7728
- const candidate = join6(dir, name);
7788
+ const candidate = join7(dir, name);
7729
7789
  if (!exists(candidate)) continue;
7730
7790
  const candidateRealpath = safeRealpath(candidate, realpath);
7731
7791
  if (execRealpath && candidateRealpath && candidateRealpath === execRealpath) {
@@ -7737,14 +7797,14 @@ function resolveHookNodePath({
7737
7797
  }
7738
7798
 
7739
7799
  // src/commands/publish.ts
7740
- import { existsSync as existsSync6 } from "node:fs";
7741
- import { join as join8 } from "node:path";
7800
+ import { existsSync as existsSync7 } from "node:fs";
7801
+ import { join as join9 } from "node:path";
7742
7802
 
7743
7803
  // src/commands/codexSidecarAdvisory.ts
7744
- import { spawnSync as spawnSync3 } from "node:child_process";
7745
- import { mkdtempSync, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
7804
+ import { spawnSync as spawnSync2 } from "node:child_process";
7805
+ import { mkdtempSync, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
7746
7806
  import { tmpdir } from "node:os";
7747
- import { join as join7 } from "node:path";
7807
+ import { join as join8 } from "node:path";
7748
7808
  var DEFAULT_HOOK_SIDECAR_TIMEOUT_MS = 12e4;
7749
7809
  var MAX_HOOK_SIDECAR_TIMEOUT_MS = 24e4;
7750
7810
  function resolveHookSidecarTimeoutMs(raw) {
@@ -7800,11 +7860,11 @@ function runCodexSidecarAdvisory(input) {
7800
7860
  let resultDir;
7801
7861
  let advisory;
7802
7862
  try {
7803
- resultDir = mkdtempSync(join7(tmpdir(), "caveat-codex-advisory-"));
7804
- const resultFile = join7(resultDir, "result.json");
7863
+ resultDir = mkdtempSync(join8(tmpdir(), "caveat-codex-advisory-"));
7864
+ const resultFile = join8(resultDir, "result.json");
7805
7865
  args.push("--save-result", resultFile);
7806
7866
  if (input.additionalContext) {
7807
- const additionalContextFile = join7(resultDir, "hook-signal.json");
7867
+ const additionalContextFile = join8(resultDir, "hook-signal.json");
7808
7868
  writeFileSync2(additionalContextFile, JSON.stringify({ context: [input.additionalContext] }) + "\n", { encoding: "utf-8", mode: 384, flag: "wx" });
7809
7869
  args.push("--additional-context-file", additionalContextFile);
7810
7870
  }
@@ -7815,7 +7875,7 @@ function runCodexSidecarAdvisory(input) {
7815
7875
  const command = process.env.CAVEAT_CODEX_SIDECAR_COMMAND;
7816
7876
  if (command) args.push("--command", command);
7817
7877
  }
7818
- const result = spawnSync3(process.execPath, args, {
7878
+ const result = spawnSync2(process.execPath, args, {
7819
7879
  cwd: input.projectRoot,
7820
7880
  encoding: "utf-8",
7821
7881
  // Keep at least one minute between the longest supported model call and
@@ -7832,7 +7892,7 @@ function runCodexSidecarAdvisory(input) {
7832
7892
  message: `sidecar command failed: ${sidecarFailureDetail(detail)}`
7833
7893
  };
7834
7894
  } else {
7835
- const parsed = JSON.parse(readFileSync5(resultFile, "utf-8"));
7895
+ const parsed = JSON.parse(readFileSync6(resultFile, "utf-8"));
7836
7896
  if (parsed.status !== "ok" || typeof parsed.summary !== "string") {
7837
7897
  advisory = {
7838
7898
  status: "failed",
@@ -7900,7 +7960,7 @@ async function runPublish(ctx, opts, dependencies = {}) {
7900
7960
  const isTty = dependencies.isTty ?? (() => Boolean(process.stdin.isTTY));
7901
7961
  const confirm = dependencies.confirm ?? askOnce;
7902
7962
  const projectRoot = process.cwd();
7903
- const hasCodexSidecarConfig = dependencies.hasCodexSidecarConfig ?? ((root) => existsSync6(join8(root, ".codex-sidecar.yml")));
7963
+ const hasCodexSidecarConfig = dependencies.hasCodexSidecarConfig ?? ((root) => existsSync7(join9(root, ".codex-sidecar.yml")));
7904
7964
  const publishAdvisory = hasCodexSidecarConfig(projectRoot) ? (changes) => {
7905
7965
  try {
7906
7966
  return dependencies.runCodexSidecarAdvisory?.(changes, projectRoot) ?? formatCodexSidecarAdvisory(runCodexSidecarAdvisory({
@@ -7955,27 +8015,32 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
7955
8015
  const isTty = dependencies.isTty ?? (() => Boolean(process.stdin.isTTY));
7956
8016
  const confirm = dependencies.confirm ?? askOnce;
7957
8017
  const ghRunner = dependencies.ghRunner ?? runGh;
8018
+ const env = dependencies.env ?? process.env;
8019
+ const { claudeDir, claudeMcp, codexHome, cursorDir, grokHome } = resolveAgentConfigPaths(ctx.userHome, env);
8020
+ const codexAvailable = (dependencies.codexAvailable ?? detectCodexAvailability)();
7958
8021
  let publishTarget = ctx.config.publishTarget;
7959
8022
  let codexHookState = "not-installed";
7960
8023
  let cursorHookState = "not-installed";
7961
- ensureUserConfig(ctx.userConfigPath);
8024
+ if (!opts.dryRun) ensureUserConfig(ctx.userConfigPath);
7962
8025
  ctx.logger.info(`user config: ${ctx.userConfigPath}`);
7963
- if (!existsSync7(ctx.paths.knowledgeRepo)) {
7964
- mkdirSync3(ctx.paths.knowledgeRepo, { recursive: true });
7965
- mkdirSync3(ctx.paths.entriesDir, { recursive: true });
7966
- ctx.logger.info(`knowledge repo scaffolded: ${ctx.paths.knowledgeRepo}`);
8026
+ if (!existsSync8(ctx.paths.knowledgeRepo)) {
8027
+ if (!opts.dryRun) {
8028
+ mkdirSync3(ctx.paths.knowledgeRepo, { recursive: true });
8029
+ mkdirSync3(ctx.paths.entriesDir, { recursive: true });
8030
+ }
8031
+ ctx.logger.info(`${opts.dryRun ? "[dry-run] would scaffold" : "knowledge repo scaffolded"}: ${ctx.paths.knowledgeRepo}`);
7967
8032
  } else {
7968
8033
  ctx.logger.info(`knowledge repo: ${ctx.paths.knowledgeRepo}`);
7969
8034
  }
7970
- migrateLegacyCommunityDir(ctx);
7971
- const gitignorePath = join9(ctx.paths.knowledgeRepo, ".gitignore");
7972
- if (!existsSync7(gitignorePath)) {
7973
- writeFileSync3(gitignorePath, KNOWLEDGE_GITIGNORE, "utf-8");
7974
- ctx.logger.info(`.gitignore created: ${gitignorePath}`);
8035
+ if (!opts.dryRun) migrateLegacyCommunityDir(ctx);
8036
+ const gitignorePath = join10(ctx.paths.knowledgeRepo, ".gitignore");
8037
+ if (!existsSync8(gitignorePath)) {
8038
+ if (!opts.dryRun) writeFileSync3(gitignorePath, KNOWLEDGE_GITIGNORE, "utf-8");
8039
+ ctx.logger.info(`${opts.dryRun ? "[dry-run] would create .gitignore" : ".gitignore created"}: ${gitignorePath}`);
7975
8040
  }
7976
8041
  if (!opts.dryRun) {
7977
8042
  const dbDir = dirname3(ctx.paths.dbPath);
7978
- if (!existsSync7(dbDir)) mkdirSync3(dbDir, { recursive: true });
8043
+ if (!existsSync8(dbDir)) mkdirSync3(dbDir, { recursive: true });
7979
8044
  const keyProvider = createKeyserverKeyProvider({ caveatHome: ctx.caveatHome });
7980
8045
  const failures = await prewarmSealedKeys({ paths: ctx.paths, keyProvider });
7981
8046
  for (const failure of failures) {
@@ -8008,7 +8073,7 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
8008
8073
  );
8009
8074
  let syncRequested = opts.sync !== void 0 && opts.sync !== false;
8010
8075
  let syncNudgeAccepted = false;
8011
- if (opts.sync === void 0 && isTty()) {
8076
+ if (opts.sync === void 0 && !opts.yes && isTty()) {
8012
8077
  syncNudgeAccepted = confirm("private \u540C\u671F\u3092\u4ECA\u3059\u3050\u8A2D\u5B9A\u3059\u308B\uFF1F [y/N]");
8013
8078
  syncRequested = syncNudgeAccepted;
8014
8079
  }
@@ -8018,40 +8083,50 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
8018
8083
  const target = typeof opts.sync === "string" ? opts.sync : "<user>/Caveat-Private";
8019
8084
  ctx.logger.info(`[dry-run] would initialize private sync: ${target}`);
8020
8085
  } else {
8021
- const url2 = typeof opts.sync === "string" ? opts.sync : defaultGitHubRepoUrl({
8022
- repositoryName: "Caveat-Private",
8023
- visibility: "private",
8024
- yes: (opts.yes ?? false) || syncNudgeAccepted,
8025
- retryCommand: "caveat init --sync <url>",
8026
- ghRunner,
8027
- isTty,
8028
- confirm
8029
- });
8030
- const result = await initOwnSync({
8031
- ownDir: ctx.paths.knowledgeRepo,
8032
- url: url2,
8033
- caveatHome: ctx.caveatHome,
8034
- paths: ctx.paths,
8035
- logger: ctx.logger,
8036
- // file: remotes are governed by local filesystem permissions and have
8037
- // no anonymous HTTP surface for the remote-visibility probe to inspect.
8038
- trustRemotePrivate: isFileRemote(url2)
8039
- });
8040
- ctx.logger.info(
8041
- result.remoteWasEmpty ? `initialized private sync remote: ${url2}` : `checked out existing private remote: ${url2} (branch ${result.branch})`
8042
- );
8086
+ const ownGit = join10(ctx.paths.knowledgeRepo, ".git");
8087
+ if (existsSync8(ownGit)) {
8088
+ const remote = gitOutput(["-C", ctx.paths.knowledgeRepo, "remote", "get-url", "origin"]);
8089
+ const result = await syncOwn({
8090
+ ownDir: ctx.paths.knowledgeRepo,
8091
+ caveatHome: ctx.caveatHome,
8092
+ paths: ctx.paths,
8093
+ logger: ctx.logger,
8094
+ trustRemotePrivate: remote !== null && isFileRemote(remote)
8095
+ });
8096
+ const rebased = result.pulled ? ", rebased onto remote" : "";
8097
+ ctx.logger.info(`synced existing private remote: ${result.branch} (${result.changedFiles} local change(s)${rebased})`);
8098
+ } else {
8099
+ const url2 = typeof opts.sync === "string" ? opts.sync : defaultGitHubRepoUrl({
8100
+ repositoryName: "Caveat-Private",
8101
+ visibility: "private",
8102
+ yes: (opts.yes ?? false) || syncNudgeAccepted,
8103
+ retryCommand: "caveat init --sync <url>",
8104
+ ghRunner,
8105
+ isTty,
8106
+ confirm
8107
+ });
8108
+ const result = await initOwnSync({
8109
+ ownDir: ctx.paths.knowledgeRepo,
8110
+ url: url2,
8111
+ caveatHome: ctx.caveatHome,
8112
+ paths: ctx.paths,
8113
+ logger: ctx.logger,
8114
+ // file: remotes are governed by local filesystem permissions and have
8115
+ // no anonymous HTTP surface for the remote-visibility probe to inspect.
8116
+ trustRemotePrivate: isFileRemote(url2)
8117
+ });
8118
+ ctx.logger.info(
8119
+ result.remoteWasEmpty ? `initialized private sync remote: ${url2}` : `checked out existing private remote: ${url2} (branch ${result.branch})`
8120
+ );
8121
+ }
8043
8122
  }
8044
8123
  } catch (err) {
8045
- if (err instanceof SyncError && err.code === "OWN_REPO_EXISTS") {
8046
- ctx.logger.info("private sync already configured (own repo exists); skipped");
8047
- } else {
8048
- ctx.logger.warn(`private sync setup skipped: ${errorMessage(err)}`);
8049
- }
8124
+ throw new Error(`private sync setup failed: ${errorMessage(err)}`, { cause: err });
8050
8125
  }
8051
8126
  }
8052
8127
  let publishRequested = opts.publishTarget !== void 0 && opts.publishTarget !== false;
8053
8128
  let publishNudgeAccepted = false;
8054
- if (opts.publishTarget === void 0 && isTty()) {
8129
+ if (opts.publishTarget === void 0 && !opts.yes && isTty()) {
8055
8130
  publishNudgeAccepted = confirm("\u516C\u958B repo\uFF08\u5C01\u7DD8\u30DF\u30E9\u30FC\uFF09\u3082\u8A2D\u5B9A\u3059\u308B\uFF1F [y/N]");
8056
8131
  publishRequested = publishNudgeAccepted;
8057
8132
  }
@@ -8084,33 +8159,36 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
8084
8159
  if (opts.skipClaude) {
8085
8160
  ctx.logger.info("Claude Code integration skipped (--skip-claude)");
8086
8161
  } else {
8087
- const cliScriptPath = process.argv[1];
8088
- if (!cliScriptPath) {
8162
+ const cliScriptPath2 = process.argv[1];
8163
+ if (!cliScriptPath2) {
8089
8164
  ctx.logger.warn("cannot determine CLI script path; skipping Claude integration");
8090
8165
  } else {
8091
8166
  const result = installClaudeIntegration({
8092
- claudeDir: join9(ctx.userHome, ".claude"),
8093
- cliScriptPath,
8167
+ claudeDir,
8168
+ mcpConfigPath: claudeMcp,
8169
+ cliScriptPath: cliScriptPath2,
8094
8170
  nodePath: resolveHookNodePath(),
8095
8171
  dryRun: opts.dryRun,
8096
8172
  logger: ctx.logger
8097
8173
  });
8098
8174
  reportInstallResult(ctx, result, opts.dryRun);
8175
+ if (result.mcp.action === "failed") {
8176
+ throw new Error(`mcp_setup_failed: Claude Code: ${result.mcp.detail}`);
8177
+ }
8099
8178
  }
8100
8179
  }
8101
8180
  if (opts.skipCodexHook) {
8102
8181
  codexHookState = "skipped";
8103
8182
  ctx.logger.info("Codex hook integration skipped (--skip-codex-hook)");
8104
- } else if ((dependencies.codexAvailable ?? detectCodexAvailability)()) {
8105
- const cliScriptPath = process.argv[1];
8106
- if (!cliScriptPath) {
8183
+ } else if (codexAvailable) {
8184
+ const cliScriptPath2 = process.argv[1];
8185
+ if (!cliScriptPath2) {
8107
8186
  codexHookState = "skipped";
8108
8187
  ctx.logger.warn("cannot determine CLI script path; skipping Codex hook integration");
8109
8188
  } else {
8110
- const codexHome = join9(ctx.userHome, ".codex");
8111
8189
  const result = installCodexHooks({
8112
8190
  codexHome,
8113
- cliScriptPath,
8191
+ cliScriptPath: cliScriptPath2,
8114
8192
  nodePath: resolveHookNodePath(),
8115
8193
  dryRun: opts.dryRun,
8116
8194
  logger: ctx.logger
@@ -8118,7 +8196,7 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
8118
8196
  if (result.feature === "blocked") {
8119
8197
  codexHookState = "skipped";
8120
8198
  ctx.logger.warn(
8121
- `${result.blockedReason}; preserving explicit consent. Set \`hooks = true\` in ${join9(codexHome, "config.toml")}, then rerun \`caveat init\`.`
8199
+ `${result.blockedReason}; preserving explicit consent. Set \`hooks = true\` in ${join10(codexHome, "config.toml")}, then rerun \`caveat init\`.`
8122
8200
  );
8123
8201
  } else if (opts.dryRun) {
8124
8202
  codexHookState = "skipped";
@@ -8131,16 +8209,15 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
8131
8209
  if (opts.skipCursorHook) {
8132
8210
  cursorHookState = "skipped";
8133
8211
  ctx.logger.info("Cursor hook integration skipped (--skip-cursor-hook)");
8134
- } else if (existsSync7(join9(ctx.userHome, ".cursor"))) {
8135
- const cliScriptPath = process.argv[1];
8136
- if (!cliScriptPath) {
8212
+ } else if (existsSync8(cursorDir)) {
8213
+ const cliScriptPath2 = process.argv[1];
8214
+ if (!cliScriptPath2) {
8137
8215
  cursorHookState = "skipped";
8138
8216
  ctx.logger.warn("cannot determine CLI script path; skipping Cursor hook integration");
8139
8217
  } else {
8140
- const cursorDir = join9(ctx.userHome, ".cursor");
8141
8218
  const result = installCursorHooks({
8142
8219
  cursorDir,
8143
- cliScriptPath,
8220
+ cliScriptPath: cliScriptPath2,
8144
8221
  nodePath: resolveHookNodePath(),
8145
8222
  dryRun: opts.dryRun,
8146
8223
  logger: ctx.logger
@@ -8156,10 +8233,21 @@ async function runInit(ctx, opts = { skipClaude: false, dryRun: false }, depende
8156
8233
  }
8157
8234
  }
8158
8235
  }
8236
+ const cliScriptPath = process.argv[1];
8237
+ if (!cliScriptPath) throw new Error("mcp_setup_failed: CLI\u306E\u5B9F\u884C\u30D1\u30B9\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093");
8238
+ for (const [client, configPath, available] of [
8239
+ ["codex", join10(codexHome, "config.toml"), codexAvailable || existsSync8(codexHome)],
8240
+ ["grok", join10(grokHome, "config.toml"), existsSync8(grokHome)],
8241
+ ["cursor", join10(cursorDir, "mcp.json"), existsSync8(cursorDir)]
8242
+ ]) {
8243
+ if (!available) continue;
8244
+ const action = installMcpClient({ client, configPath, cliScriptPath, nodePath: resolveHookNodePath(), dryRun: opts.dryRun });
8245
+ ctx.logger.info(`${client} MCP: ${action}`);
8246
+ }
8159
8247
  reportEnvironmentSummary(ctx, publishTarget, codexHookState, cursorHookState, opts.dryRun);
8160
8248
  }
8161
8249
  function detectCodexAvailability() {
8162
- const result = spawnSync4("codex --version", {
8250
+ const result = spawnSync3("codex --version", {
8163
8251
  shell: true,
8164
8252
  encoding: "utf-8",
8165
8253
  stdio: "ignore"
@@ -8174,14 +8262,14 @@ function isFileRemote(url2) {
8174
8262
  }
8175
8263
  }
8176
8264
  function gitOutput(args) {
8177
- const result = spawnSync4("git", args, { encoding: "utf-8" });
8265
+ const result = spawnSync3("git", args, { encoding: "utf-8" });
8178
8266
  return result.status === 0 && typeof result.stdout === "string" ? result.stdout.trim() : null;
8179
8267
  }
8180
8268
  function reportEnvironmentSummary(ctx, publishTarget, codexHookState, cursorHookState, dryRun) {
8181
8269
  const prefix = dryRun ? "[dry-run] would have " : "";
8182
8270
  const isRepo = gitOutput(["-C", ctx.paths.knowledgeRepo, "rev-parse", "--is-inside-work-tree"]) === "true";
8183
8271
  const remote = isRepo ? gitOutput(["-C", ctx.paths.knowledgeRepo, "config", "--get", "remote.origin.url"]) : null;
8184
- const communityCount = existsSync7(ctx.paths.communityDir) ? readdirSync(ctx.paths.communityDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).length : 0;
8272
+ const communityCount = existsSync8(ctx.paths.communityDir) ? readdirSync(ctx.paths.communityDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).length : 0;
8185
8273
  ctx.logger.info(`${prefix}environment summary:`);
8186
8274
  ctx.logger.info(` own git: ${isRepo ? "repository" : "not initialized"}`);
8187
8275
  ctx.logger.info(` private remote: ${remote || "not configured"}`);
@@ -8194,11 +8282,11 @@ function errorMessage(err) {
8194
8282
  return err instanceof Error ? err.message : String(err);
8195
8283
  }
8196
8284
  function migrateLegacyCommunityDir(ctx) {
8197
- const legacy = join9(ctx.paths.knowledgeRepo, "community");
8285
+ const legacy = join10(ctx.paths.knowledgeRepo, "community");
8198
8286
  const current = ctx.paths.communityDir;
8199
8287
  if (legacy === current) return;
8200
- if (!existsSync7(legacy)) return;
8201
- if (existsSync7(current)) {
8288
+ if (!existsSync8(legacy)) return;
8289
+ if (existsSync8(current)) {
8202
8290
  ctx.logger.warn(
8203
8291
  `legacy community dir still exists at ${legacy} \u2014 remove manually (new location in use)`
8204
8292
  );
@@ -8207,7 +8295,7 @@ function migrateLegacyCommunityDir(ctx) {
8207
8295
  mkdirSync3(current, { recursive: true });
8208
8296
  for (const entry of readdirSync(legacy, { withFileTypes: true })) {
8209
8297
  if (!entry.isDirectory()) continue;
8210
- renameSync(join9(legacy, entry.name), join9(current, entry.name));
8298
+ renameSync(join10(legacy, entry.name), join10(current, entry.name));
8211
8299
  }
8212
8300
  try {
8213
8301
  rmdirSync(legacy);
@@ -8221,13 +8309,16 @@ function runUninstall(ctx, opts) {
8221
8309
  ctx.logger.error("cannot determine CLI script path");
8222
8310
  process.exit(1);
8223
8311
  }
8312
+ const { claudeDir, claudeMcp } = resolveAgentConfigPaths(ctx.userHome);
8224
8313
  const result = uninstallClaudeIntegration({
8225
- claudeDir: join9(ctx.userHome, ".claude"),
8314
+ claudeDir,
8315
+ mcpConfigPath: claudeMcp,
8226
8316
  cliScriptPath,
8227
8317
  nodePath: resolveHookNodePath(),
8228
8318
  dryRun: opts.dryRun,
8229
8319
  logger: ctx.logger
8230
8320
  });
8321
+ if (result.mcp.action === "failed") throw new Error(`mcp_uninstall_failed: Claude Code: ${result.mcp.detail}`);
8231
8322
  ctx.logger.info(
8232
8323
  `MCP: ${result.mcp.action}${result.mcp.detail ? ` (${result.mcp.detail})` : ""}`
8233
8324
  );
@@ -8269,11 +8360,11 @@ function reportInstallResult(ctx, result, dryRun) {
8269
8360
  }
8270
8361
 
8271
8362
  // src/commands/indexCmd.ts
8272
- import { existsSync as existsSync8, mkdirSync as mkdirSync4 } from "node:fs";
8363
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4 } from "node:fs";
8273
8364
  import { dirname as dirname4 } from "node:path";
8274
8365
  async function runIndex(ctx, opts) {
8275
8366
  const dbDir = dirname4(ctx.paths.dbPath);
8276
- if (!existsSync8(dbDir)) mkdirSync4(dbDir, { recursive: true });
8367
+ if (!existsSync9(dbDir)) mkdirSync4(dbDir, { recursive: true });
8277
8368
  const keyProvider = createKeyserverKeyProvider({ caveatHome: ctx.caveatHome });
8278
8369
  const failures = await prewarmSealedKeys({ paths: ctx.paths, keyProvider });
8279
8370
  for (const failure of failures) {
@@ -8457,7 +8548,7 @@ function runStats(ctx) {
8457
8548
 
8458
8549
  // src/commands/serve.ts
8459
8550
  async function runServe(opts) {
8460
- const { startServer } = await import("./server-HKXLHXNN.js");
8551
+ const { startServer } = await import("./server-VOEJV4WH.js");
8461
8552
  const { port, host } = startServer({ port: opts.port });
8462
8553
  process.stdout.write(`[caveat] web portal: http://${host}:${port}/
8463
8554
  `);
@@ -8496,10 +8587,10 @@ var util;
8496
8587
  return obj[e];
8497
8588
  });
8498
8589
  };
8499
- util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object3) => {
8590
+ util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object4) => {
8500
8591
  const keys = [];
8501
- for (const key in object3) {
8502
- if (Object.prototype.hasOwnProperty.call(object3, key)) {
8592
+ for (const key in object4) {
8593
+ if (Object.prototype.hasOwnProperty.call(object4, key)) {
8503
8594
  keys.push(key);
8504
8595
  }
8505
8596
  }
@@ -12600,7 +12691,7 @@ __export(core_exports2, {
12600
12691
  isValidJWT: () => isValidJWT2,
12601
12692
  locales: () => locales_exports,
12602
12693
  meta: () => meta,
12603
- parse: () => parse,
12694
+ parse: () => parse2,
12604
12695
  parseAsync: () => parseAsync,
12605
12696
  prettifyError: () => prettifyError,
12606
12697
  process: () => process2,
@@ -12819,9 +12910,9 @@ function floatSafeRemainder2(val, step) {
12819
12910
  return ratio - roundedRatio;
12820
12911
  }
12821
12912
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
12822
- function defineLazy(object3, key, getter) {
12913
+ function defineLazy(object4, key, getter) {
12823
12914
  let value = void 0;
12824
- Object.defineProperty(object3, key, {
12915
+ Object.defineProperty(object4, key, {
12825
12916
  get() {
12826
12917
  if (value === EVALUATING) {
12827
12918
  return void 0;
@@ -12833,7 +12924,7 @@ function defineLazy(object3, key, getter) {
12833
12924
  return value;
12834
12925
  },
12835
12926
  set(v) {
12836
- Object.defineProperty(object3, key, {
12927
+ Object.defineProperty(object4, key, {
12837
12928
  value: v
12838
12929
  // configurable: true,
12839
12930
  });
@@ -13545,7 +13636,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
13545
13636
  }
13546
13637
  return result.value;
13547
13638
  };
13548
- var parse = /* @__PURE__ */ _parse($ZodRealError);
13639
+ var parse2 = /* @__PURE__ */ _parse($ZodRealError);
13549
13640
  var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
13550
13641
  const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
13551
13642
  let result = schema._zod.run({ value, issues: [] }, ctx);
@@ -16337,10 +16428,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
16337
16428
  throw new Error("implement() must be called with a function");
16338
16429
  }
16339
16430
  return function(...args) {
16340
- const parsedArgs = inst._def.input ? parse(inst._def.input, args) : args;
16431
+ const parsedArgs = inst._def.input ? parse2(inst._def.input, args) : args;
16341
16432
  const result = Reflect.apply(func, this, parsedArgs);
16342
16433
  if (inst._def.output) {
16343
- return parse(inst._def.output, result);
16434
+ return parse2(inst._def.output, result);
16344
16435
  }
16345
16436
  return result;
16346
16437
  };
@@ -24494,7 +24585,7 @@ var ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
24494
24585
  $ZodType.init(inst, def);
24495
24586
  inst.def = def;
24496
24587
  inst.type = def.type;
24497
- inst.parse = (data, params) => parse(inst, data, params, { callee: inst.parse });
24588
+ inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
24498
24589
  inst.safeParse = (data, params) => safeParse(inst, data, params);
24499
24590
  inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
24500
24591
  inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
@@ -24524,7 +24615,7 @@ var ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) =>
24524
24615
  defineLazy(inst, "shape", () => def.shape);
24525
24616
  });
24526
24617
  // @__NO_SIDE_EFFECTS__
24527
- function object(shape, params) {
24618
+ function object2(shape, params) {
24528
24619
  const def = {
24529
24620
  type: "object",
24530
24621
  shape: shape ?? {},
@@ -24541,11 +24632,11 @@ function isZ4Schema(s) {
24541
24632
  function objectFromShape(shape) {
24542
24633
  const values = Object.values(shape);
24543
24634
  if (values.length === 0)
24544
- return object({});
24635
+ return object2({});
24545
24636
  const allV4 = values.every(isZ4Schema);
24546
24637
  const allV3 = values.every((s) => !isZ4Schema(s));
24547
24638
  if (allV4)
24548
- return object(shape);
24639
+ return object2(shape);
24549
24640
  if (allV3)
24550
24641
  return objectType(shape);
24551
24642
  throw new Error("Mixed Zod versions detected in object shape.");
@@ -24857,10 +24948,10 @@ __export(external_exports, {
24857
24948
  nullable: () => nullable,
24858
24949
  nullish: () => nullish2,
24859
24950
  number: () => number2,
24860
- object: () => object2,
24951
+ object: () => object3,
24861
24952
  optional: () => optional,
24862
24953
  overwrite: () => _overwrite,
24863
- parse: () => parse2,
24954
+ parse: () => parse3,
24864
24955
  parseAsync: () => parseAsync2,
24865
24956
  partialRecord: () => partialRecord,
24866
24957
  pipe: () => pipe,
@@ -25054,7 +25145,7 @@ __export(schemas_exports2, {
25054
25145
  nullable: () => nullable,
25055
25146
  nullish: () => nullish2,
25056
25147
  number: () => number2,
25057
- object: () => object2,
25148
+ object: () => object3,
25058
25149
  optional: () => optional,
25059
25150
  partialRecord: () => partialRecord,
25060
25151
  pipe: () => pipe,
@@ -25207,7 +25298,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, {
25207
25298
  });
25208
25299
 
25209
25300
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js
25210
- var parse2 = /* @__PURE__ */ _parse(ZodRealError);
25301
+ var parse3 = /* @__PURE__ */ _parse(ZodRealError);
25211
25302
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
25212
25303
  var safeParse3 = /* @__PURE__ */ _safeParse(ZodRealError);
25213
25304
  var safeParseAsync3 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
@@ -25270,7 +25361,7 @@ var ZodType2 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
25270
25361
  inst.def = def;
25271
25362
  inst.type = def.type;
25272
25363
  Object.defineProperty(inst, "_def", { value: def });
25273
- inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
25364
+ inst.parse = (data, params) => parse3(inst, data, params, { callee: inst.parse });
25274
25365
  inst.safeParse = (data, params) => safeParse3(inst, data, params);
25275
25366
  inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
25276
25367
  inst.safeParseAsync = async (data, params) => safeParseAsync3(inst, data, params);
@@ -25929,7 +26020,7 @@ var ZodObject2 = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
25929
26020
  }
25930
26021
  });
25931
26022
  });
25932
- function object2(shape, params) {
26023
+ function object3(shape, params) {
25933
26024
  const def = {
25934
26025
  type: "object",
25935
26026
  shape: shape ?? {},
@@ -27062,10 +27153,10 @@ var TaskCreationParamsSchema = looseObject({
27062
27153
  */
27063
27154
  pollInterval: number2().optional()
27064
27155
  });
27065
- var TaskMetadataSchema = object2({
27156
+ var TaskMetadataSchema = object3({
27066
27157
  ttl: number2().optional()
27067
27158
  });
27068
- var RelatedTaskMetadataSchema = object2({
27159
+ var RelatedTaskMetadataSchema = object3({
27069
27160
  taskId: string2()
27070
27161
  });
27071
27162
  var RequestMetaSchema = looseObject({
@@ -27078,7 +27169,7 @@ var RequestMetaSchema = looseObject({
27078
27169
  */
27079
27170
  [RELATED_TASK_META_KEY]: RelatedTaskMetadataSchema.optional()
27080
27171
  });
27081
- var BaseRequestParamsSchema = object2({
27172
+ var BaseRequestParamsSchema = object3({
27082
27173
  /**
27083
27174
  * See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.
27084
27175
  */
@@ -27096,18 +27187,18 @@ var TaskAugmentedRequestParamsSchema = BaseRequestParamsSchema.extend({
27096
27187
  task: TaskMetadataSchema.optional()
27097
27188
  });
27098
27189
  var isTaskAugmentedRequestParams = (value) => TaskAugmentedRequestParamsSchema.safeParse(value).success;
27099
- var RequestSchema = object2({
27190
+ var RequestSchema = object3({
27100
27191
  method: string2(),
27101
27192
  params: BaseRequestParamsSchema.loose().optional()
27102
27193
  });
27103
- var NotificationsParamsSchema = object2({
27194
+ var NotificationsParamsSchema = object3({
27104
27195
  /**
27105
27196
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
27106
27197
  * for notes on _meta usage.
27107
27198
  */
27108
27199
  _meta: RequestMetaSchema.optional()
27109
27200
  });
27110
- var NotificationSchema = object2({
27201
+ var NotificationSchema = object3({
27111
27202
  method: string2(),
27112
27203
  params: NotificationsParamsSchema.loose().optional()
27113
27204
  });
@@ -27119,18 +27210,18 @@ var ResultSchema = looseObject({
27119
27210
  _meta: RequestMetaSchema.optional()
27120
27211
  });
27121
27212
  var RequestIdSchema = union([string2(), number2().int()]);
27122
- var JSONRPCRequestSchema = object2({
27213
+ var JSONRPCRequestSchema = object3({
27123
27214
  jsonrpc: literal(JSONRPC_VERSION),
27124
27215
  id: RequestIdSchema,
27125
27216
  ...RequestSchema.shape
27126
27217
  }).strict();
27127
27218
  var isJSONRPCRequest = (value) => JSONRPCRequestSchema.safeParse(value).success;
27128
- var JSONRPCNotificationSchema = object2({
27219
+ var JSONRPCNotificationSchema = object3({
27129
27220
  jsonrpc: literal(JSONRPC_VERSION),
27130
27221
  ...NotificationSchema.shape
27131
27222
  }).strict();
27132
27223
  var isJSONRPCNotification = (value) => JSONRPCNotificationSchema.safeParse(value).success;
27133
- var JSONRPCResultResponseSchema = object2({
27224
+ var JSONRPCResultResponseSchema = object3({
27134
27225
  jsonrpc: literal(JSONRPC_VERSION),
27135
27226
  id: RequestIdSchema,
27136
27227
  result: ResultSchema
@@ -27147,10 +27238,10 @@ var ErrorCode;
27147
27238
  ErrorCode2[ErrorCode2["InternalError"] = -32603] = "InternalError";
27148
27239
  ErrorCode2[ErrorCode2["UrlElicitationRequired"] = -32042] = "UrlElicitationRequired";
27149
27240
  })(ErrorCode || (ErrorCode = {}));
27150
- var JSONRPCErrorResponseSchema = object2({
27241
+ var JSONRPCErrorResponseSchema = object3({
27151
27242
  jsonrpc: literal(JSONRPC_VERSION),
27152
27243
  id: RequestIdSchema.optional(),
27153
- error: object2({
27244
+ error: object3({
27154
27245
  /**
27155
27246
  * The error type that occurred.
27156
27247
  */
@@ -27190,7 +27281,7 @@ var CancelledNotificationSchema = NotificationSchema.extend({
27190
27281
  method: literal("notifications/cancelled"),
27191
27282
  params: CancelledNotificationParamsSchema
27192
27283
  });
27193
- var IconSchema = object2({
27284
+ var IconSchema = object3({
27194
27285
  /**
27195
27286
  * URL or data URI for the icon.
27196
27287
  */
@@ -27215,7 +27306,7 @@ var IconSchema = object2({
27215
27306
  */
27216
27307
  theme: _enum2(["light", "dark"]).optional()
27217
27308
  });
27218
- var IconsSchema = object2({
27309
+ var IconsSchema = object3({
27219
27310
  /**
27220
27311
  * Optional set of sized icons that the client can display in a user interface.
27221
27312
  *
@@ -27229,7 +27320,7 @@ var IconsSchema = object2({
27229
27320
  */
27230
27321
  icons: array(IconSchema).optional()
27231
27322
  });
27232
- var BaseMetadataSchema = object2({
27323
+ var BaseMetadataSchema = object3({
27233
27324
  /** Intended for programmatic or logical use, but used as a display name in past specs or fallback */
27234
27325
  name: string2(),
27235
27326
  /**
@@ -27259,7 +27350,7 @@ var ImplementationSchema = BaseMetadataSchema.extend({
27259
27350
  */
27260
27351
  description: string2().optional()
27261
27352
  });
27262
- var FormElicitationCapabilitySchema = intersection(object2({
27353
+ var FormElicitationCapabilitySchema = intersection(object3({
27263
27354
  applyDefaults: boolean2().optional()
27264
27355
  }), record(string2(), unknown()));
27265
27356
  var ElicitationCapabilitySchema = preprocess((value) => {
@@ -27269,7 +27360,7 @@ var ElicitationCapabilitySchema = preprocess((value) => {
27269
27360
  }
27270
27361
  }
27271
27362
  return value;
27272
- }, intersection(object2({
27363
+ }, intersection(object3({
27273
27364
  form: FormElicitationCapabilitySchema.optional(),
27274
27365
  url: AssertObjectSchema.optional()
27275
27366
  }), record(string2(), unknown()).optional()));
@@ -27321,7 +27412,7 @@ var ServerTasksCapabilitySchema = looseObject({
27321
27412
  }).optional()
27322
27413
  }).optional()
27323
27414
  });
27324
- var ClientCapabilitiesSchema = object2({
27415
+ var ClientCapabilitiesSchema = object3({
27325
27416
  /**
27326
27417
  * Experimental, non-standard capabilities that the client supports.
27327
27418
  */
@@ -27329,7 +27420,7 @@ var ClientCapabilitiesSchema = object2({
27329
27420
  /**
27330
27421
  * Present if the client supports sampling from an LLM.
27331
27422
  */
27332
- sampling: object2({
27423
+ sampling: object3({
27333
27424
  /**
27334
27425
  * Present if the client supports context inclusion via includeContext parameter.
27335
27426
  * If not declared, servers SHOULD only use `includeContext: "none"` (or omit it).
@@ -27347,7 +27438,7 @@ var ClientCapabilitiesSchema = object2({
27347
27438
  /**
27348
27439
  * Present if the client supports listing roots.
27349
27440
  */
27350
- roots: object2({
27441
+ roots: object3({
27351
27442
  /**
27352
27443
  * Whether the client supports issuing notifications for changes to the roots list.
27353
27444
  */
@@ -27374,7 +27465,7 @@ var InitializeRequestSchema = RequestSchema.extend({
27374
27465
  method: literal("initialize"),
27375
27466
  params: InitializeRequestParamsSchema
27376
27467
  });
27377
- var ServerCapabilitiesSchema = object2({
27468
+ var ServerCapabilitiesSchema = object3({
27378
27469
  /**
27379
27470
  * Experimental, non-standard capabilities that the server supports.
27380
27471
  */
@@ -27390,7 +27481,7 @@ var ServerCapabilitiesSchema = object2({
27390
27481
  /**
27391
27482
  * Present if the server offers any prompt templates.
27392
27483
  */
27393
- prompts: object2({
27484
+ prompts: object3({
27394
27485
  /**
27395
27486
  * Whether this server supports issuing notifications for changes to the prompt list.
27396
27487
  */
@@ -27399,7 +27490,7 @@ var ServerCapabilitiesSchema = object2({
27399
27490
  /**
27400
27491
  * Present if the server offers any resources to read.
27401
27492
  */
27402
- resources: object2({
27493
+ resources: object3({
27403
27494
  /**
27404
27495
  * Whether this server supports clients subscribing to resource updates.
27405
27496
  */
@@ -27412,7 +27503,7 @@ var ServerCapabilitiesSchema = object2({
27412
27503
  /**
27413
27504
  * Present if the server offers any tools to call.
27414
27505
  */
27415
- tools: object2({
27506
+ tools: object3({
27416
27507
  /**
27417
27508
  * Whether this server supports issuing notifications for changes to the tool list.
27418
27509
  */
@@ -27449,7 +27540,7 @@ var PingRequestSchema = RequestSchema.extend({
27449
27540
  method: literal("ping"),
27450
27541
  params: BaseRequestParamsSchema.optional()
27451
27542
  });
27452
- var ProgressSchema = object2({
27543
+ var ProgressSchema = object3({
27453
27544
  /**
27454
27545
  * The progress thus far. This should increase every time progress is made, even if the total is unknown.
27455
27546
  */
@@ -27463,7 +27554,7 @@ var ProgressSchema = object2({
27463
27554
  */
27464
27555
  message: optional(string2())
27465
27556
  });
27466
- var ProgressNotificationParamsSchema = object2({
27557
+ var ProgressNotificationParamsSchema = object3({
27467
27558
  ...NotificationsParamsSchema.shape,
27468
27559
  ...ProgressSchema.shape,
27469
27560
  /**
@@ -27493,7 +27584,7 @@ var PaginatedResultSchema = ResultSchema.extend({
27493
27584
  nextCursor: CursorSchema.optional()
27494
27585
  });
27495
27586
  var TaskStatusSchema = _enum2(["working", "input_required", "completed", "failed", "cancelled"]);
27496
- var TaskSchema = object2({
27587
+ var TaskSchema = object3({
27497
27588
  taskId: string2(),
27498
27589
  status: TaskStatusSchema,
27499
27590
  /**
@@ -27550,7 +27641,7 @@ var CancelTaskRequestSchema = RequestSchema.extend({
27550
27641
  })
27551
27642
  });
27552
27643
  var CancelTaskResultSchema = ResultSchema.merge(TaskSchema);
27553
- var ResourceContentsSchema = object2({
27644
+ var ResourceContentsSchema = object3({
27554
27645
  /**
27555
27646
  * The URI of this resource.
27556
27647
  */
@@ -27586,7 +27677,7 @@ var BlobResourceContentsSchema = ResourceContentsSchema.extend({
27586
27677
  blob: Base64Schema
27587
27678
  });
27588
27679
  var RoleSchema = _enum2(["user", "assistant"]);
27589
- var AnnotationsSchema = object2({
27680
+ var AnnotationsSchema = object3({
27590
27681
  /**
27591
27682
  * Intended audience(s) for the resource.
27592
27683
  */
@@ -27600,7 +27691,7 @@ var AnnotationsSchema = object2({
27600
27691
  */
27601
27692
  lastModified: iso_exports2.datetime({ offset: true }).optional()
27602
27693
  });
27603
- var ResourceSchema = object2({
27694
+ var ResourceSchema = object3({
27604
27695
  ...BaseMetadataSchema.shape,
27605
27696
  ...IconsSchema.shape,
27606
27697
  /**
@@ -27633,7 +27724,7 @@ var ResourceSchema = object2({
27633
27724
  */
27634
27725
  _meta: optional(looseObject({}))
27635
27726
  });
27636
- var ResourceTemplateSchema = object2({
27727
+ var ResourceTemplateSchema = object3({
27637
27728
  ...BaseMetadataSchema.shape,
27638
27729
  ...IconsSchema.shape,
27639
27730
  /**
@@ -27712,7 +27803,7 @@ var ResourceUpdatedNotificationSchema = NotificationSchema.extend({
27712
27803
  method: literal("notifications/resources/updated"),
27713
27804
  params: ResourceUpdatedNotificationParamsSchema
27714
27805
  });
27715
- var PromptArgumentSchema = object2({
27806
+ var PromptArgumentSchema = object3({
27716
27807
  /**
27717
27808
  * The name of the argument.
27718
27809
  */
@@ -27726,7 +27817,7 @@ var PromptArgumentSchema = object2({
27726
27817
  */
27727
27818
  required: optional(boolean2())
27728
27819
  });
27729
- var PromptSchema = object2({
27820
+ var PromptSchema = object3({
27730
27821
  ...BaseMetadataSchema.shape,
27731
27822
  ...IconsSchema.shape,
27732
27823
  /**
@@ -27763,7 +27854,7 @@ var GetPromptRequestSchema = RequestSchema.extend({
27763
27854
  method: literal("prompts/get"),
27764
27855
  params: GetPromptRequestParamsSchema
27765
27856
  });
27766
- var TextContentSchema = object2({
27857
+ var TextContentSchema = object3({
27767
27858
  type: literal("text"),
27768
27859
  /**
27769
27860
  * The text content of the message.
@@ -27779,7 +27870,7 @@ var TextContentSchema = object2({
27779
27870
  */
27780
27871
  _meta: record(string2(), unknown()).optional()
27781
27872
  });
27782
- var ImageContentSchema = object2({
27873
+ var ImageContentSchema = object3({
27783
27874
  type: literal("image"),
27784
27875
  /**
27785
27876
  * The base64-encoded image data.
@@ -27799,7 +27890,7 @@ var ImageContentSchema = object2({
27799
27890
  */
27800
27891
  _meta: record(string2(), unknown()).optional()
27801
27892
  });
27802
- var AudioContentSchema = object2({
27893
+ var AudioContentSchema = object3({
27803
27894
  type: literal("audio"),
27804
27895
  /**
27805
27896
  * The base64-encoded audio data.
@@ -27819,7 +27910,7 @@ var AudioContentSchema = object2({
27819
27910
  */
27820
27911
  _meta: record(string2(), unknown()).optional()
27821
27912
  });
27822
- var ToolUseContentSchema = object2({
27913
+ var ToolUseContentSchema = object3({
27823
27914
  type: literal("tool_use"),
27824
27915
  /**
27825
27916
  * The name of the tool to invoke.
@@ -27842,7 +27933,7 @@ var ToolUseContentSchema = object2({
27842
27933
  */
27843
27934
  _meta: record(string2(), unknown()).optional()
27844
27935
  });
27845
- var EmbeddedResourceSchema = object2({
27936
+ var EmbeddedResourceSchema = object3({
27846
27937
  type: literal("resource"),
27847
27938
  resource: union([TextResourceContentsSchema, BlobResourceContentsSchema]),
27848
27939
  /**
@@ -27865,7 +27956,7 @@ var ContentBlockSchema = union([
27865
27956
  ResourceLinkSchema,
27866
27957
  EmbeddedResourceSchema
27867
27958
  ]);
27868
- var PromptMessageSchema = object2({
27959
+ var PromptMessageSchema = object3({
27869
27960
  role: RoleSchema,
27870
27961
  content: ContentBlockSchema
27871
27962
  });
@@ -27880,7 +27971,7 @@ var PromptListChangedNotificationSchema = NotificationSchema.extend({
27880
27971
  method: literal("notifications/prompts/list_changed"),
27881
27972
  params: NotificationsParamsSchema.optional()
27882
27973
  });
27883
- var ToolAnnotationsSchema = object2({
27974
+ var ToolAnnotationsSchema = object3({
27884
27975
  /**
27885
27976
  * A human-readable title for the tool.
27886
27977
  */
@@ -27919,7 +28010,7 @@ var ToolAnnotationsSchema = object2({
27919
28010
  */
27920
28011
  openWorldHint: boolean2().optional()
27921
28012
  });
27922
- var ToolExecutionSchema = object2({
28013
+ var ToolExecutionSchema = object3({
27923
28014
  /**
27924
28015
  * Indicates the tool's preference for task-augmented execution.
27925
28016
  * - "required": Clients MUST invoke the tool as a task
@@ -27930,7 +28021,7 @@ var ToolExecutionSchema = object2({
27930
28021
  */
27931
28022
  taskSupport: _enum2(["required", "optional", "forbidden"]).optional()
27932
28023
  });
27933
- var ToolSchema = object2({
28024
+ var ToolSchema = object3({
27934
28025
  ...BaseMetadataSchema.shape,
27935
28026
  ...IconsSchema.shape,
27936
28027
  /**
@@ -27941,7 +28032,7 @@ var ToolSchema = object2({
27941
28032
  * A JSON Schema 2020-12 object defining the expected parameters for the tool.
27942
28033
  * Must have type: 'object' at the root level per MCP spec.
27943
28034
  */
27944
- inputSchema: object2({
28035
+ inputSchema: object3({
27945
28036
  type: literal("object"),
27946
28037
  properties: record(string2(), AssertObjectSchema).optional(),
27947
28038
  required: array(string2()).optional()
@@ -27951,7 +28042,7 @@ var ToolSchema = object2({
27951
28042
  * returned in the structuredContent field of a CallToolResult.
27952
28043
  * Must have type: 'object' at the root level per MCP spec.
27953
28044
  */
27954
- outputSchema: object2({
28045
+ outputSchema: object3({
27955
28046
  type: literal("object"),
27956
28047
  properties: record(string2(), AssertObjectSchema).optional(),
27957
28048
  required: array(string2()).optional()
@@ -28027,7 +28118,7 @@ var ToolListChangedNotificationSchema = NotificationSchema.extend({
28027
28118
  method: literal("notifications/tools/list_changed"),
28028
28119
  params: NotificationsParamsSchema.optional()
28029
28120
  });
28030
- var ListChangedOptionsBaseSchema = object2({
28121
+ var ListChangedOptionsBaseSchema = object3({
28031
28122
  /**
28032
28123
  * If true, the list will be refreshed automatically when a list changed notification is received.
28033
28124
  * The callback will be called with the updated list.
@@ -28076,13 +28167,13 @@ var LoggingMessageNotificationSchema = NotificationSchema.extend({
28076
28167
  method: literal("notifications/message"),
28077
28168
  params: LoggingMessageNotificationParamsSchema
28078
28169
  });
28079
- var ModelHintSchema = object2({
28170
+ var ModelHintSchema = object3({
28080
28171
  /**
28081
28172
  * A hint for a model name.
28082
28173
  */
28083
28174
  name: string2().optional()
28084
28175
  });
28085
- var ModelPreferencesSchema = object2({
28176
+ var ModelPreferencesSchema = object3({
28086
28177
  /**
28087
28178
  * Optional hints to use for model selection.
28088
28179
  */
@@ -28100,7 +28191,7 @@ var ModelPreferencesSchema = object2({
28100
28191
  */
28101
28192
  intelligencePriority: number2().min(0).max(1).optional()
28102
28193
  });
28103
- var ToolChoiceSchema = object2({
28194
+ var ToolChoiceSchema = object3({
28104
28195
  /**
28105
28196
  * Controls when tools are used:
28106
28197
  * - "auto": Model decides whether to use tools (default)
@@ -28109,11 +28200,11 @@ var ToolChoiceSchema = object2({
28109
28200
  */
28110
28201
  mode: _enum2(["auto", "required", "none"]).optional()
28111
28202
  });
28112
- var ToolResultContentSchema = object2({
28203
+ var ToolResultContentSchema = object3({
28113
28204
  type: literal("tool_result"),
28114
28205
  toolUseId: string2().describe("The unique identifier for the corresponding tool call."),
28115
28206
  content: array(ContentBlockSchema).default([]),
28116
- structuredContent: object2({}).loose().optional(),
28207
+ structuredContent: object3({}).loose().optional(),
28117
28208
  isError: boolean2().optional(),
28118
28209
  /**
28119
28210
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
@@ -28129,7 +28220,7 @@ var SamplingMessageContentBlockSchema = discriminatedUnion("type", [
28129
28220
  ToolUseContentSchema,
28130
28221
  ToolResultContentSchema
28131
28222
  ]);
28132
- var SamplingMessageSchema = object2({
28223
+ var SamplingMessageSchema = object3({
28133
28224
  role: RoleSchema,
28134
28225
  content: union([SamplingMessageContentBlockSchema, array(SamplingMessageContentBlockSchema)]),
28135
28226
  /**
@@ -28229,13 +28320,13 @@ var CreateMessageResultWithToolsSchema = ResultSchema.extend({
28229
28320
  */
28230
28321
  content: union([SamplingMessageContentBlockSchema, array(SamplingMessageContentBlockSchema)])
28231
28322
  });
28232
- var BooleanSchemaSchema = object2({
28323
+ var BooleanSchemaSchema = object3({
28233
28324
  type: literal("boolean"),
28234
28325
  title: string2().optional(),
28235
28326
  description: string2().optional(),
28236
28327
  default: boolean2().optional()
28237
28328
  });
28238
- var StringSchemaSchema = object2({
28329
+ var StringSchemaSchema = object3({
28239
28330
  type: literal("string"),
28240
28331
  title: string2().optional(),
28241
28332
  description: string2().optional(),
@@ -28244,7 +28335,7 @@ var StringSchemaSchema = object2({
28244
28335
  format: _enum2(["email", "uri", "date", "date-time"]).optional(),
28245
28336
  default: string2().optional()
28246
28337
  });
28247
- var NumberSchemaSchema = object2({
28338
+ var NumberSchemaSchema = object3({
28248
28339
  type: _enum2(["number", "integer"]),
28249
28340
  title: string2().optional(),
28250
28341
  description: string2().optional(),
@@ -28252,24 +28343,24 @@ var NumberSchemaSchema = object2({
28252
28343
  maximum: number2().optional(),
28253
28344
  default: number2().optional()
28254
28345
  });
28255
- var UntitledSingleSelectEnumSchemaSchema = object2({
28346
+ var UntitledSingleSelectEnumSchemaSchema = object3({
28256
28347
  type: literal("string"),
28257
28348
  title: string2().optional(),
28258
28349
  description: string2().optional(),
28259
28350
  enum: array(string2()),
28260
28351
  default: string2().optional()
28261
28352
  });
28262
- var TitledSingleSelectEnumSchemaSchema = object2({
28353
+ var TitledSingleSelectEnumSchemaSchema = object3({
28263
28354
  type: literal("string"),
28264
28355
  title: string2().optional(),
28265
28356
  description: string2().optional(),
28266
- oneOf: array(object2({
28357
+ oneOf: array(object3({
28267
28358
  const: string2(),
28268
28359
  title: string2()
28269
28360
  })),
28270
28361
  default: string2().optional()
28271
28362
  });
28272
- var LegacyTitledEnumSchemaSchema = object2({
28363
+ var LegacyTitledEnumSchemaSchema = object3({
28273
28364
  type: literal("string"),
28274
28365
  title: string2().optional(),
28275
28366
  description: string2().optional(),
@@ -28278,26 +28369,26 @@ var LegacyTitledEnumSchemaSchema = object2({
28278
28369
  default: string2().optional()
28279
28370
  });
28280
28371
  var SingleSelectEnumSchemaSchema = union([UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema]);
28281
- var UntitledMultiSelectEnumSchemaSchema = object2({
28372
+ var UntitledMultiSelectEnumSchemaSchema = object3({
28282
28373
  type: literal("array"),
28283
28374
  title: string2().optional(),
28284
28375
  description: string2().optional(),
28285
28376
  minItems: number2().optional(),
28286
28377
  maxItems: number2().optional(),
28287
- items: object2({
28378
+ items: object3({
28288
28379
  type: literal("string"),
28289
28380
  enum: array(string2())
28290
28381
  }),
28291
28382
  default: array(string2()).optional()
28292
28383
  });
28293
- var TitledMultiSelectEnumSchemaSchema = object2({
28384
+ var TitledMultiSelectEnumSchemaSchema = object3({
28294
28385
  type: literal("array"),
28295
28386
  title: string2().optional(),
28296
28387
  description: string2().optional(),
28297
28388
  minItems: number2().optional(),
28298
28389
  maxItems: number2().optional(),
28299
- items: object2({
28300
- anyOf: array(object2({
28390
+ items: object3({
28391
+ anyOf: array(object3({
28301
28392
  const: string2(),
28302
28393
  title: string2()
28303
28394
  }))
@@ -28322,7 +28413,7 @@ var ElicitRequestFormParamsSchema = TaskAugmentedRequestParamsSchema.extend({
28322
28413
  * A restricted subset of JSON Schema.
28323
28414
  * Only top-level properties are allowed, without nesting.
28324
28415
  */
28325
- requestedSchema: object2({
28416
+ requestedSchema: object3({
28326
28417
  type: literal("object"),
28327
28418
  properties: record(string2(), PrimitiveSchemaDefinitionSchema),
28328
28419
  required: array(string2()).optional()
@@ -28378,14 +28469,14 @@ var ElicitResultSchema = ResultSchema.extend({
28378
28469
  */
28379
28470
  content: preprocess((val) => val === null ? void 0 : val, record(string2(), union([string2(), number2(), boolean2(), array(string2())])).optional())
28380
28471
  });
28381
- var ResourceTemplateReferenceSchema = object2({
28472
+ var ResourceTemplateReferenceSchema = object3({
28382
28473
  type: literal("ref/resource"),
28383
28474
  /**
28384
28475
  * The URI or URI template of the resource.
28385
28476
  */
28386
28477
  uri: string2()
28387
28478
  });
28388
- var PromptReferenceSchema = object2({
28479
+ var PromptReferenceSchema = object3({
28389
28480
  type: literal("ref/prompt"),
28390
28481
  /**
28391
28482
  * The name of the prompt or prompt template
@@ -28397,7 +28488,7 @@ var CompleteRequestParamsSchema = BaseRequestParamsSchema.extend({
28397
28488
  /**
28398
28489
  * The argument's information
28399
28490
  */
28400
- argument: object2({
28491
+ argument: object3({
28401
28492
  /**
28402
28493
  * The name of the argument
28403
28494
  */
@@ -28407,7 +28498,7 @@ var CompleteRequestParamsSchema = BaseRequestParamsSchema.extend({
28407
28498
  */
28408
28499
  value: string2()
28409
28500
  }),
28410
- context: object2({
28501
+ context: object3({
28411
28502
  /**
28412
28503
  * Previously-resolved variables in a URI template or prompt.
28413
28504
  */
@@ -28446,7 +28537,7 @@ var CompleteResultSchema = ResultSchema.extend({
28446
28537
  hasMore: optional(boolean2())
28447
28538
  })
28448
28539
  });
28449
- var RootSchema = object2({
28540
+ var RootSchema = object3({
28450
28541
  /**
28451
28542
  * The URI identifying the root. This *must* start with file:// for now.
28452
28543
  */
@@ -29310,11 +29401,11 @@ function parseMapDef(def, refs) {
29310
29401
 
29311
29402
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@4.4.3/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js
29312
29403
  function parseNativeEnumDef(def) {
29313
- const object3 = def.values;
29404
+ const object4 = def.values;
29314
29405
  const actualKeys = Object.keys(def.values).filter((key) => {
29315
- return typeof object3[object3[key]] !== "number";
29406
+ return typeof object4[object4[key]] !== "number";
29316
29407
  });
29317
- const actualValues = actualKeys.map((key) => object3[key]);
29408
+ const actualValues = actualKeys.map((key) => object4[key]);
29318
29409
  const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
29319
29410
  return {
29320
29411
  type: parsedTypes.length === 1 ? parsedTypes[0] === "string" ? "string" : "number" : ["string", "number"],
@@ -32528,8 +32619,8 @@ var StdioServerTransport = class {
32528
32619
  };
32529
32620
 
32530
32621
  // ../mcp/dist/context.js
32531
- import { homedir as homedir2 } from "node:os";
32532
- import { join as join10 } from "node:path";
32622
+ import { homedir as homedir3 } from "node:os";
32623
+ import { join as join11 } from "node:path";
32533
32624
 
32534
32625
  // ../mcp/dist/autoSyncTrigger.js
32535
32626
  function triggerAutoSyncAfterWrite(caveatHome, logger) {
@@ -32546,9 +32637,9 @@ function triggerAutoSyncAfterWrite(caveatHome, logger) {
32546
32637
 
32547
32638
  // ../mcp/dist/context.js
32548
32639
  function buildMcpContext(overrides = {}) {
32549
- const userHome = overrides.userHome ?? homedir2();
32640
+ const userHome = overrides.userHome ?? homedir3();
32550
32641
  const caveatHome = overrides.caveatHome ?? findCaveatHome(userHome);
32551
- const userConfigPath = join10(userHome, ".caveatrc.json");
32642
+ const userConfigPath = join11(userHome, ".caveatrc.json");
32552
32643
  const logger = overrides.logger ?? stderrLogger;
32553
32644
  const config2 = loadConfig(userConfigPath);
32554
32645
  const paths = resolvePaths(caveatHome, config2.knowledgeRepo, userHome);
@@ -32697,12 +32788,12 @@ function handleListRecent(ctx, args) {
32697
32788
  }
32698
32789
 
32699
32790
  // ../mcp/dist/tools/pull.js
32700
- import { existsSync as existsSync9 } from "node:fs";
32791
+ import { existsSync as existsSync10 } from "node:fs";
32701
32792
  var pullInputShape = {};
32702
32793
  async function handlePull(ctx, _args = {}) {
32703
32794
  const pulled = [];
32704
32795
  const indexed = [];
32705
- if (existsSync9(ctx.paths.communityDir)) {
32796
+ if (existsSync10(ctx.paths.communityDir)) {
32706
32797
  const results = await communityPull({
32707
32798
  communityDir: ctx.paths.communityDir,
32708
32799
  logger: ctx.logger
@@ -32858,28 +32949,28 @@ async function runMcpServer() {
32858
32949
  import { spawn as spawn2 } from "node:child_process";
32859
32950
  import {
32860
32951
  chmodSync,
32861
- existsSync as existsSync12,
32952
+ existsSync as existsSync13,
32862
32953
  lstatSync,
32863
32954
  mkdtempSync as mkdtempSync2,
32864
32955
  mkdirSync as mkdirSync6,
32865
32956
  readdirSync as readdirSync2,
32866
- readFileSync as readFileSync7,
32957
+ readFileSync as readFileSync8,
32867
32958
  realpathSync as realpathSync3,
32868
32959
  rmSync as rmSync2,
32869
32960
  writeFileSync as writeFileSync5
32870
32961
  } from "node:fs";
32871
32962
  import { tmpdir as tmpdir2 } from "node:os";
32872
- import { basename, dirname as dirname5, join as join13 } from "node:path";
32963
+ import { basename, dirname as dirname5, join as join14 } from "node:path";
32873
32964
  import { randomBytes } from "node:crypto";
32874
32965
 
32875
32966
  // src/autoReindexTrigger.ts
32876
32967
  import { spawn } from "node:child_process";
32877
- import { existsSync as existsSync10 } from "node:fs";
32878
- import { join as join11 } from "node:path";
32968
+ import { existsSync as existsSync11 } from "node:fs";
32969
+ import { join as join12 } from "node:path";
32879
32970
  function maybeTriggerAutoReindex(ctx) {
32880
32971
  if (process.env.CAVEAT_INDEX_AUTOSYNC === "off") return;
32881
- if (!existsSync10(ctx.paths.dbPath)) return;
32882
- if (existsSync10(join11(ctx.caveatHome, "index", ".reindex-lock"))) return;
32972
+ if (!existsSync11(ctx.paths.dbPath)) return;
32973
+ if (existsSync11(join12(ctx.caveatHome, "index", ".reindex-lock"))) return;
32883
32974
  const current = computeEntriesDigest(ctx.paths);
32884
32975
  const marker = readDigestMarker(ctx.caveatHome);
32885
32976
  if (marker?.digest === current.digest && marker.fileCount === current.fileCount) return;
@@ -32905,8 +32996,8 @@ function maybeTriggerAutoSync(ctx, debounceMs = AUTO_SYNC_DEBOUNCE_MS) {
32905
32996
  }
32906
32997
 
32907
32998
  // src/hookShared.ts
32908
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
32909
- import { join as join12 } from "node:path";
32999
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
33000
+ import { join as join13 } from "node:path";
32910
33001
  import { createHash } from "node:crypto";
32911
33002
  var MAX_CONTEXT_BLOCKS = 3;
32912
33003
  var STOP_REMINDER_PREFIX = "[caveat] \u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u5916\u90E8\u4ED5\u69D8\u306E\u7F60\u306B\u5F53\u305F\u3063\u305F\u53EF\u80FD\u6027\u3092\u793A\u3059\u30B7\u30B0\u30CA\u30EB:";
@@ -32961,7 +33052,7 @@ function searchCaveatsSafely(host, input) {
32961
33052
  let hits;
32962
33053
  try {
32963
33054
  const ctx = buildContextSafely(host);
32964
- if (!ctx || !existsSync11(ctx.paths.dbPath)) return [];
33055
+ if (!ctx || !existsSync12(ctx.paths.dbPath)) return [];
32965
33056
  caveatHome = ctx.caveatHome;
32966
33057
  db = openDb({ path: ctx.paths.dbPath });
32967
33058
  const searchOptions = {
@@ -33047,19 +33138,19 @@ function stopSignalKey(signals, related) {
33047
33138
  return createHash("sha256").update(body).digest("hex");
33048
33139
  }
33049
33140
  function stopStatePath(host, caveatHome, sessionId) {
33050
- return join12(caveatHome, host.stopStateDir, `${sanitizeStateId(sessionId)}.txt`);
33141
+ return join13(caveatHome, host.stopStateDir, `${sanitizeStateId(sessionId)}.txt`);
33051
33142
  }
33052
33143
  function wasStopReminderQueued(host, caveatHome, sessionId, key) {
33053
33144
  const path = stopStatePath(host, caveatHome, sessionId);
33054
33145
  try {
33055
- return readFileSync6(path, "utf-8") === key;
33146
+ return readFileSync7(path, "utf-8") === key;
33056
33147
  } catch {
33057
33148
  return false;
33058
33149
  }
33059
33150
  }
33060
33151
  function markStopReminderQueued(host, caveatHome, sessionId, key) {
33061
33152
  const path = stopStatePath(host, caveatHome, sessionId);
33062
- mkdirSync5(join12(caveatHome, host.stopStateDir), { recursive: true });
33153
+ mkdirSync5(join13(caveatHome, host.stopStateDir), { recursive: true });
33063
33154
  writeFileSync4(path, key, "utf-8");
33064
33155
  }
33065
33156
  function queueStopForSession(host, sessionId, signals, related, buildText) {
@@ -33171,9 +33262,9 @@ function spawnWorker(job) {
33171
33262
  try {
33172
33263
  root = workerRoot();
33173
33264
  sweepStaleWorkerDirs(Date.now(), root);
33174
- workDir = mkdtempSync2(join13(root, "job-"));
33265
+ workDir = mkdtempSync2(join14(root, "job-"));
33175
33266
  chmodSync(workDir, 448);
33176
- workFile = join13(workDir, `${randomBytes(4).toString("hex")}.json`);
33267
+ workFile = join14(workDir, `${randomBytes(4).toString("hex")}.json`);
33177
33268
  writeFileSync5(workFile, JSON.stringify({ ...job, schemaVersion: "caveat-worker-job/v2" }), { encoding: "utf-8", mode: 384, flag: "wx" });
33178
33269
  } catch (err) {
33179
33270
  process.stderr.write(`[caveat:hook] worker writefile error: ${errorMessage4(err)}
@@ -33205,7 +33296,7 @@ function spawnWorker(job) {
33205
33296
  async function runWorker(workFile) {
33206
33297
  let raw;
33207
33298
  try {
33208
- raw = readFileSync7(workFile, "utf-8");
33299
+ raw = readFileSync8(workFile, "utf-8");
33209
33300
  } catch {
33210
33301
  process.exit(0);
33211
33302
  }
@@ -33269,7 +33360,7 @@ function sweepStaleWorkerDirs(now = Date.now(), root = workerRoot()) {
33269
33360
  }
33270
33361
  for (const entry of entries) {
33271
33362
  if (!entry.startsWith("job-")) continue;
33272
- const path = join13(root, entry);
33363
+ const path = join14(root, entry);
33273
33364
  try {
33274
33365
  if (!isOwnedWorkerDir(path, root)) continue;
33275
33366
  const stat = lstatSync(path);
@@ -33281,29 +33372,29 @@ function sweepStaleWorkerDirs(now = Date.now(), root = workerRoot()) {
33281
33372
  }
33282
33373
  }
33283
33374
  function workerRoot(base = tmpdir2()) {
33284
- const root = join13(base, WORKER_ROOT);
33375
+ const root = join14(base, WORKER_ROOT);
33285
33376
  mkdirSync6(root, { recursive: true, mode: 448 });
33286
33377
  const stat = lstatSync(root);
33287
33378
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
33288
33379
  if (!stat.isDirectory() || stat.isSymbolicLink() || !hasPrivateOwnership(stat, uid)) throw new Error("worker root is unsafe");
33289
- const marker = join13(root, WORKER_MARKER);
33380
+ const marker = join14(root, WORKER_MARKER);
33290
33381
  try {
33291
33382
  writeFileSync5(marker, "caveat-worker/v1\n", { mode: 384, flag: "wx" });
33292
33383
  } catch (error51) {
33293
33384
  if (!(error51 && typeof error51 === "object" && "code" in error51 && error51.code === "EEXIST")) throw error51;
33294
33385
  }
33295
33386
  const markerStat = lstatSync(marker);
33296
- if (!markerStat.isFile() || markerStat.isSymbolicLink() || !hasPrivateOwnership(markerStat, uid) || readFileSync7(marker, "utf-8") !== "caveat-worker/v1\n") throw new Error("worker root marker is invalid");
33387
+ if (!markerStat.isFile() || markerStat.isSymbolicLink() || !hasPrivateOwnership(markerStat, uid) || readFileSync8(marker, "utf-8") !== "caveat-worker/v1\n") throw new Error("worker root marker is invalid");
33297
33388
  return root;
33298
33389
  }
33299
33390
  function isStaleWorkerJobDir(path) {
33300
33391
  const entries = readdirSync2(path);
33301
33392
  if (entries.length !== 1 || !entries[0].endsWith(".json")) return false;
33302
- const file2 = join13(path, entries[0]);
33393
+ const file2 = join14(path, entries[0]);
33303
33394
  const stat = lstatSync(file2);
33304
33395
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
33305
33396
  if (!stat.isFile() || stat.isSymbolicLink() || !hasPrivateOwnership(stat, uid)) return false;
33306
- return isKnownStaleWorkerJob(JSON.parse(readFileSync7(file2, "utf-8")));
33397
+ return isKnownStaleWorkerJob(JSON.parse(readFileSync8(file2, "utf-8")));
33307
33398
  }
33308
33399
  function hasPrivateOwnership(stat, uid) {
33309
33400
  return isPrivateOwnerStat(stat, uid);
@@ -33325,7 +33416,7 @@ function isKnownStaleWorkerJob(value) {
33325
33416
  }
33326
33417
  function writeLastReindex(caveatHome, value) {
33327
33418
  try {
33328
- writeFileSync5(join13(caveatHome, "index", ".last-reindex.json"), JSON.stringify(value), "utf-8");
33419
+ writeFileSync5(join14(caveatHome, "index", ".last-reindex.json"), JSON.stringify(value), "utf-8");
33329
33420
  } catch (err) {
33330
33421
  process.stderr.write(`[caveat:hook] reindex status write error: ${errorMessage4(err)}
33331
33422
  `);
@@ -33337,7 +33428,7 @@ async function runReindexWorker() {
33337
33428
  return;
33338
33429
  }
33339
33430
  const ctx = buildContextSafely(CLAUDE_HOST);
33340
- if (!ctx || !existsSync12(ctx.paths.dbPath)) {
33431
+ if (!ctx || !existsSync13(ctx.paths.dbPath)) {
33341
33432
  process.stderr.write("[caveat:hook] auto reindex skipped: index database does not exist\n");
33342
33433
  return;
33343
33434
  }
@@ -33404,7 +33495,7 @@ function buildToolErrorReminder(job, hits) {
33404
33495
  const mode = hookCodexSidecarMode();
33405
33496
  if (mode === "off") return base;
33406
33497
  const projectRoot = process.cwd();
33407
- const hasSidecarConfig = existsSync12(join13(projectRoot, ".codex-sidecar.yml"));
33498
+ const hasSidecarConfig = existsSync13(join14(projectRoot, ".codex-sidecar.yml"));
33408
33499
  if (mode === "auto" && !hasSidecarConfig) return base;
33409
33500
  const advisory = runCodexSidecarAdvisory({
33410
33501
  searchText: job.failureText,
@@ -33440,7 +33531,7 @@ function buildStopReminder(signals, related) {
33440
33531
  const mode = hookCodexSidecarMode();
33441
33532
  if (mode === "off") return base;
33442
33533
  const projectRoot = process.cwd();
33443
- const hasSidecarConfig = existsSync12(join13(projectRoot, ".codex-sidecar.yml"));
33534
+ const hasSidecarConfig = existsSync13(join14(projectRoot, ".codex-sidecar.yml"));
33444
33535
  if (mode === "auto" && !hasSidecarConfig) return base;
33445
33536
  const advisory = runCodexSidecarAdvisory({
33446
33537
  searchText: struggleSearchText(signals),
@@ -33579,10 +33670,10 @@ async function runHook(name, arg) {
33579
33670
  }
33580
33671
 
33581
33672
  // src/commands/codexHookCmd.ts
33582
- import { spawn as spawn3, spawnSync as spawnSync5 } from "node:child_process";
33583
- import { existsSync as existsSync13, readFileSync as readFileSync8, unlinkSync, writeFileSync as writeFileSync6 } from "node:fs";
33584
- import { homedir as homedir3, tmpdir as tmpdir3 } from "node:os";
33585
- import { join as join14 } from "node:path";
33673
+ import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
33674
+ import { existsSync as existsSync14, readFileSync as readFileSync9, unlinkSync, writeFileSync as writeFileSync6 } from "node:fs";
33675
+ import { homedir as homedir4, tmpdir as tmpdir3 } from "node:os";
33676
+ import { join as join15 } from "node:path";
33586
33677
  import { randomBytes as randomBytes2 } from "node:crypto";
33587
33678
  var CODEX_HOST = {
33588
33679
  agent: "codex",
@@ -33612,10 +33703,10 @@ function processExitCodeFromText(text) {
33612
33703
  return m ? Number(m[1]) : null;
33613
33704
  }
33614
33705
  function transcriptToolOutput(transcriptPath, toolUseId) {
33615
- if (!transcriptPath || !toolUseId || !existsSync13(transcriptPath)) return null;
33706
+ if (!transcriptPath || !toolUseId || !existsSync14(transcriptPath)) return null;
33616
33707
  let raw = "";
33617
33708
  try {
33618
- raw = readFileSync8(transcriptPath, "utf-8");
33709
+ raw = readFileSync9(transcriptPath, "utf-8");
33619
33710
  } catch {
33620
33711
  return null;
33621
33712
  }
@@ -33749,7 +33840,7 @@ async function processCodexWorkerJob(job, opts = { waitForTranscript: true }) {
33749
33840
  agent: "codex",
33750
33841
  surface: "tool_error",
33751
33842
  refs: hits
33752
- }), () => toolErrorReminderText(hits));
33843
+ }), () => toolErrorReminderText(hits, "native-cli"));
33753
33844
  } catch {
33754
33845
  process.stderr.write("[caveat:codex-hook] pending reminder build or publish failed\n");
33755
33846
  return;
@@ -33759,7 +33850,7 @@ async function processCodexWorkerJob(job, opts = { waitForTranscript: true }) {
33759
33850
  async function runCodexWorker(workFile) {
33760
33851
  let raw;
33761
33852
  try {
33762
- raw = readFileSync8(workFile, "utf-8");
33853
+ raw = readFileSync9(workFile, "utf-8");
33763
33854
  } catch {
33764
33855
  process.exit(0);
33765
33856
  }
@@ -33776,8 +33867,8 @@ async function runCodexWorker(workFile) {
33776
33867
  await processCodexWorkerJob(job);
33777
33868
  process.exit(0);
33778
33869
  }
33779
- function runDiagnostics(codexHome = process.env.CODEX_HOME ?? join14(homedir3(), ".codex")) {
33780
- const features = spawnSync5("codex", ["features", "list"], {
33870
+ function runDiagnostics(codexHome = process.env.CODEX_HOME ?? join15(homedir4(), ".codex")) {
33871
+ const features = spawnSync4("codex", ["features", "list"], {
33781
33872
  encoding: "utf-8",
33782
33873
  maxBuffer: 1024 * 1024,
33783
33874
  env: codexFeatureListEnv(codexHome)
@@ -33828,7 +33919,7 @@ async function runCodexHook(name, arg) {
33828
33919
  const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
33829
33920
  const hits = searchCaveatsSafely(CODEX_HOST, { topicText: prompt, failureText: prompt, surface: "user_prompt" });
33830
33921
  if (hits.length > 0) {
33831
- contexts.push(userPromptSubmitReminderText(hits));
33922
+ contexts.push(userPromptSubmitReminderText(hits, "native-cli"));
33832
33923
  }
33833
33924
  const compacted = compactContexts(CODEX_HOST, contexts);
33834
33925
  if (compacted.length > 0) {
@@ -33873,7 +33964,7 @@ async function runCodexHook(name, arg) {
33873
33964
  failureText,
33874
33965
  surface: "stop"
33875
33966
  })));
33876
- if (sessionId) queueStopForSession(CODEX_HOST, sessionId, signals, related, () => stopReminderText(signals, related));
33967
+ if (sessionId) queueStopForSession(CODEX_HOST, sessionId, signals, related, () => stopReminderText(signals, related, "native-cli"));
33877
33968
  process.exit(0);
33878
33969
  }
33879
33970
  process.stderr.write(`[caveat:codex-hook] unknown hook name: ${name}
@@ -33882,8 +33973,8 @@ async function runCodexHook(name, arg) {
33882
33973
  }
33883
33974
 
33884
33975
  // src/commands/cursorHookCmd.ts
33885
- import { homedir as homedir4 } from "node:os";
33886
- import { join as join15 } from "node:path";
33976
+ import { homedir as homedir5 } from "node:os";
33977
+ import { join as join16 } from "node:path";
33887
33978
  var CURSOR_HOST = {
33888
33979
  agent: "cursor",
33889
33980
  stderrTag: "caveat:cursor-hook",
@@ -33923,7 +34014,7 @@ function loadSignalsSafely3(path) {
33923
34014
  return null;
33924
34015
  }
33925
34016
  }
33926
- function runDiagnostics2(cursorDir = join15(homedir4(), ".cursor")) {
34017
+ function runDiagnostics2(cursorDir = join16(homedir5(), ".cursor")) {
33927
34018
  const installation = detectCursorHookInstallation(cursorDir);
33928
34019
  process.stdout.write(`${JSON.stringify({
33929
34020
  installation: installation.installation,
@@ -33956,7 +34047,7 @@ async function runCursorHook(name, arg) {
33956
34047
  failureText: prompt,
33957
34048
  surface: "user_prompt"
33958
34049
  });
33959
- if (hits.length > 0) contexts.push(userPromptSubmitReminderText(hits));
34050
+ if (hits.length > 0) contexts.push(userPromptSubmitReminderText(hits, "native-cli"));
33960
34051
  const compacted = compactContexts(CURSOR_HOST, contexts);
33961
34052
  if (compacted.length > 0) {
33962
34053
  process.stdout.write(`${cursorContextOutput(compacted.join("\n\n"))}
@@ -33974,7 +34065,7 @@ async function runCursorHook(name, arg) {
33974
34065
  failureText: errText,
33975
34066
  surface: "tool_error"
33976
34067
  });
33977
- if (hits.length > 0) contexts.push(toolErrorReminderText(hits));
34068
+ if (hits.length > 0) contexts.push(toolErrorReminderText(hits, "native-cli"));
33978
34069
  }
33979
34070
  const compacted = compactContexts(CURSOR_HOST, contexts);
33980
34071
  if (compacted.length > 0) {
@@ -34014,7 +34105,7 @@ async function runCursorHook(name, arg) {
34014
34105
  failureText,
34015
34106
  surface: "stop"
34016
34107
  })));
34017
- queueStopForSession(CURSOR_HOST, sessionId, signals, related, () => stopReminderText(signals, related));
34108
+ queueStopForSession(CURSOR_HOST, sessionId, signals, related, () => stopReminderText(signals, related, "native-cli"));
34018
34109
  process.exit(0);
34019
34110
  }
34020
34111
  process.stderr.write(`[caveat:cursor-hook] unknown hook name: ${name}
@@ -34023,9 +34114,9 @@ async function runCursorHook(name, arg) {
34023
34114
  }
34024
34115
 
34025
34116
  // src/commands/pull.ts
34026
- import { existsSync as existsSync14 } from "node:fs";
34117
+ import { existsSync as existsSync15 } from "node:fs";
34027
34118
  async function runPull(ctx) {
34028
- const hasCommunityDir = existsSync14(ctx.paths.communityDir);
34119
+ const hasCommunityDir = existsSync15(ctx.paths.communityDir);
34029
34120
  if (!hasCommunityDir) {
34030
34121
  ctx.logger.info(
34031
34122
  "no community repos yet \u2014 add one with `caveat community add <github-url>`."
@@ -34124,10 +34215,10 @@ async function runSync(ctx, opts, dependencies = {}) {
34124
34215
  }
34125
34216
 
34126
34217
  // src/commands/codexSidecar.ts
34127
- import { spawnSync as spawnSync6 } from "node:child_process";
34218
+ import { spawnSync as spawnSync5 } from "node:child_process";
34128
34219
  import { closeSync, constants as constants4, fstatSync, lstatSync as lstatSync2, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync3, openSync, readSync as readSync2, realpathSync as realpathSync4, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "node:fs";
34129
34220
  import { tmpdir as tmpdir4 } from "node:os";
34130
- import { basename as basename2, dirname as dirname6, join as join16 } from "node:path";
34221
+ import { basename as basename2, dirname as dirname6, join as join17 } from "node:path";
34131
34222
  import { cwd, exit } from "node:process";
34132
34223
  function runCodexSidecarDiagnostics(logger, opts) {
34133
34224
  const plan = buildCodexSidecarDiagnosticsCommand({
@@ -34159,8 +34250,8 @@ function runCodexSidecarWithCaveats(ctx, workflow, prompt, opts) {
34159
34250
  process.stdout.write(JSON.stringify({ status: "skipped", decision }, null, 2) + "\n");
34160
34251
  exit(0);
34161
34252
  }
34162
- const contextDir = mkdtempSync3(join16(tmpdir4(), "caveat-sidecar-context-"));
34163
- const contextFile = join16(contextDir, "context.json");
34253
+ const contextDir = mkdtempSync3(join17(tmpdir4(), "caveat-sidecar-context-"));
34254
+ const contextFile = join17(contextDir, "context.json");
34164
34255
  let status2 = 1;
34165
34256
  try {
34166
34257
  const blocks = collectCaveatContextBlocks(ctx, {
@@ -34309,7 +34400,7 @@ function defaultPreset(workflow) {
34309
34400
  }
34310
34401
  function executePlan(logger, command, args, options = {}) {
34311
34402
  logger.info(`[codex-sidecar] ${command} ${args.map(shellDisplayQuote).join(" ")}`);
34312
- const result = spawnSync6(command, args, { encoding: "utf-8", stdio: "pipe" });
34403
+ const result = spawnSync5(command, args, { encoding: "utf-8", stdio: "pipe" });
34313
34404
  if (result.stdout) process.stdout.write(result.stdout);
34314
34405
  if (result.stderr) process.stderr.write(result.stderr);
34315
34406
  if (options.saveResult && result.stdout) {
@@ -34412,8 +34503,8 @@ function runCommunityRemove(ctx, handle, opts) {
34412
34503
 
34413
34504
  // src/commands/factoryDiagnostics.ts
34414
34505
  import { execFileSync } from "node:child_process";
34415
- import { existsSync as existsSync15, readFileSync as readFileSync9 } from "node:fs";
34416
- import { join as join17 } from "node:path";
34506
+ import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
34507
+ import { join as join18 } from "node:path";
34417
34508
  import { DatabaseSync } from "node:sqlite";
34418
34509
  import { parse as parseToml2 } from "smol-toml";
34419
34510
  var status = (ok, reason) => ({ status: ok ? "ready" : "not_ready", reason_code: ok ? "ready" : reason });
@@ -34424,20 +34515,19 @@ function hook(present) {
34424
34515
  function isRecord2(value) {
34425
34516
  return typeof value === "object" && value !== null && !Array.isArray(value);
34426
34517
  }
34427
- function claudeRegistration(home, nodePath, cliScriptPath) {
34428
- const path = join17(home, ".claude.json");
34429
- if (!existsSync15(path)) return status(false, "not_registered");
34518
+ function claudeRegistration(path, nodePath, cliScriptPath) {
34519
+ if (!existsSync16(path)) return status(false, "not_registered");
34430
34520
  try {
34431
- const value = JSON.parse(readFileSync9(path, "utf8"));
34521
+ const value = JSON.parse(readFileSync10(path, "utf8"));
34432
34522
  if (!isRecord2(value) || !isRecord2(value.mcpServers)) return status(false, "not_registered");
34433
34523
  return status(isCaveatClaudeMcpRegistration(value.mcpServers.caveat, nodePath, cliScriptPath), "not_registered");
34434
34524
  } catch {
34435
34525
  return unverified("config_unreadable");
34436
34526
  }
34437
34527
  }
34438
- function claudeHooks(home, nodePath, cliScriptPath) {
34528
+ function claudeHooks(claudeDir, nodePath, cliScriptPath) {
34439
34529
  try {
34440
- const settings = JSON.parse(readFileSync9(join17(home, ".claude", "settings.json"), "utf8"));
34530
+ const settings = JSON.parse(readFileSync10(join18(claudeDir, "settings.json"), "utf8"));
34441
34531
  const present = (event, subcommand) => settings.hooks?.[event]?.some((entry) => entry.hooks?.some((item) => typeof item.command === "string" && isCanonicalCaveatClaudeHookCommand(item.command, subcommand, nodePath, cliScriptPath))) ?? false;
34442
34532
  return { user_prompt_submit: hook(present("UserPromptSubmit", "user-prompt-submit")), post_tool_use: hook(present("PostToolUse", "post-tool-use")), post_tool_use_failure: hook(present("PostToolUseFailure", "post-tool-use")), stop: hook(present("Stop", "stop")) };
34443
34533
  } catch {
@@ -34454,12 +34544,12 @@ var EXPECTED_SEARCH_SQL = /* @__PURE__ */ new Map([
34454
34544
  function strictSearchSchema(db) {
34455
34545
  const normalize = (sql) => (sql ?? "").toLowerCase().replace(/\s+/g, " ");
34456
34546
  const objects = db.prepare("SELECT name, sql FROM sqlite_master WHERE name = 'entries_fts' OR (type = 'trigger' AND tbl_name = 'entries')").all();
34457
- if (objects.length !== EXPECTED_SEARCH_SQL.size || objects.some((object3) => normalize(object3.sql) !== EXPECTED_SEARCH_SQL.get(object3.name))) return false;
34547
+ if (objects.length !== EXPECTED_SEARCH_SQL.size || objects.some((object4) => normalize(object4.sql) !== EXPECTED_SEARCH_SQL.get(object4.name))) return false;
34458
34548
  const columns = db.prepare("PRAGMA table_xinfo(entries_fts)").all();
34459
34549
  return columns.map((column) => `${column.name}:${column.hidden}`).join(",") === "id:0,title:0,body:0,tags:0,entries_fts:1,rank:1";
34460
34550
  }
34461
34551
  function database(path) {
34462
- if (!existsSync15(path)) return { status: "not_ready", reason_code: "missing", schema_version: null, supported_schema_version: 3, migration_status: "unverified" };
34552
+ if (!existsSync16(path)) return { status: "not_ready", reason_code: "missing", schema_version: null, supported_schema_version: 3, migration_status: "unverified" };
34463
34553
  try {
34464
34554
  const db = new DatabaseSync(path, { readOnly: true });
34465
34555
  try {
@@ -34484,10 +34574,10 @@ function database(path) {
34484
34574
  }
34485
34575
  }
34486
34576
  function codexFeature(codexHome) {
34487
- const path = join17(codexHome, "config.toml");
34488
- if (!existsSync15(path)) return status(false, "feature_disabled");
34577
+ const path = join18(codexHome, "config.toml");
34578
+ if (!existsSync16(path)) return status(false, "feature_disabled");
34489
34579
  try {
34490
- const config2 = parseToml2(readFileSync9(path, "utf8"));
34580
+ const config2 = parseToml2(readFileSync10(path, "utf8"));
34491
34581
  if (!isRecord2(config2.features)) return status(false, "feature_disabled");
34492
34582
  const features = config2.features;
34493
34583
  return status(features.hooks === true && features.codex_hooks === void 0, "feature_disabled");
@@ -34496,7 +34586,7 @@ function codexFeature(codexHome) {
34496
34586
  }
34497
34587
  }
34498
34588
  function codexHooks(codexHome, nodePath, cliScriptPath) {
34499
- const value = JSON.parse(readFileSync9(join17(codexHome, "hooks.json"), "utf8"));
34589
+ const value = JSON.parse(readFileSync10(join18(codexHome, "hooks.json"), "utf8"));
34500
34590
  if (!isRecord2(value) || !isRecord2(value.hooks)) throw Error("config_unreadable");
34501
34591
  const hooks = value.hooks;
34502
34592
  const present = (event, subcommand) => Array.isArray(hooks[event]) && hooks[event].some((entry) => isRecord2(entry) && Array.isArray(entry.hooks) && entry.hooks.some((item) => isCanonicalCaveatCodexHookEntry(item, subcommand, nodePath, cliScriptPath)));
@@ -34531,7 +34621,8 @@ function sync(own) {
34531
34621
  return unverified("upstream_unavailable");
34532
34622
  }
34533
34623
  }
34534
- function factoryDiagnostics(ctx, codexHome = process.env.CODEX_HOME ?? join17(ctx.userHome, ".codex")) {
34624
+ function factoryDiagnostics(ctx, codexHome = resolveAgentConfigPaths(ctx.userHome).codexHome, requiredConnectors = []) {
34625
+ const { claudeDir, claudeMcp, cursorDir } = resolveAgentConfigPaths(ctx.userHome);
34535
34626
  const nodePath = process.execPath;
34536
34627
  const cliScriptPath = process.argv[1] ?? "";
34537
34628
  const db = database(ctx.paths.dbPath);
@@ -34542,12 +34633,13 @@ function factoryDiagnostics(ctx, codexHome = process.env.CODEX_HOME ?? join17(ct
34542
34633
  } catch {
34543
34634
  }
34544
34635
  const codexHook2 = (present) => present === void 0 ? unverified("config_unreadable") : !present ? hook(false) : feature.status === "ready" ? hook(true) : { ...feature };
34545
- const output = { schema: "caveat.native_factory_diagnostics.v1", product: "caveat", version: CAVEAT_VERSION, overall: { status: "unverified" }, database: db, sync: sync(ctx.paths.knowledgeRepo), connectors: { claude: { status: "unverified", mcp: claudeRegistration(ctx.userHome, nodePath, cliScriptPath), hooks: claudeHooks(ctx.userHome, nodePath, cliScriptPath) }, codex: { status: "unverified", hooks: { user_prompt_submit: codexHook2(installedCodexHooks?.userPromptSubmit), post_tool_use: codexHook2(installedCodexHooks?.postToolUse), stop: codexHook2(installedCodexHooks?.stop) } } } };
34636
+ const output = { schema: "caveat.native_factory_diagnostics.v1", product: "caveat", version: CAVEAT_VERSION, overall: { status: "unverified" }, database: db, sync: sync(ctx.paths.knowledgeRepo), connectors: { claude: { status: "unverified", mcp: claudeRegistration(claudeMcp, nodePath, cliScriptPath), hooks: claudeHooks(claudeDir, nodePath, cliScriptPath) }, codex: { status: "unverified", hooks: { user_prompt_submit: codexHook2(installedCodexHooks?.userPromptSubmit), post_tool_use: codexHook2(installedCodexHooks?.postToolUse), stop: codexHook2(installedCodexHooks?.stop) } }, cursor: diagnoseCursorHookConnector(cursorDir, nodePath, cliScriptPath) } };
34546
34637
  const aggregate = (all) => all.includes("not_ready") ? "not_ready" : all.includes("unverified") ? "unverified" : "ready";
34547
34638
  const connectorStatus = (connector) => aggregate([...Object.values(connector.hooks), ...connector.mcp ? [connector.mcp] : []].map((v) => v.status));
34548
34639
  output.connectors.claude.status = connectorStatus(output.connectors.claude);
34549
34640
  output.connectors.codex.status = connectorStatus(output.connectors.codex);
34550
34641
  const statuses = [output.database.status, output.sync.status, output.connectors.claude.status, output.connectors.codex.status];
34642
+ if (requiredConnectors.includes("cursor")) statuses.push(output.connectors.cursor.compatibility_status);
34551
34643
  output.overall.status = aggregate(statuses);
34552
34644
  return output;
34553
34645
  }
@@ -34572,12 +34664,16 @@ function parseCursor(value) {
34572
34664
 
34573
34665
  // src/index.ts
34574
34666
  var program = new Command();
34667
+ var agentPaths = resolveAgentConfigPaths();
34575
34668
  function collectRepeatable(value, previous) {
34576
34669
  return [...previous, value];
34577
34670
  }
34578
34671
  program.name("caveat").description("External spec gotcha knowledge base CLI").version(CAVEAT_VERSION);
34579
- program.command("factory-diagnostics").description("Emit read-only factory diagnostics").requiredOption("--json", "emit the versioned JSON contract").action((opts) => {
34580
- const output = factoryDiagnostics(buildContext(stdoutLogger));
34672
+ program.command("factory-diagnostics").description("Emit read-only factory diagnostics").requiredOption("--json", "emit the versioned JSON contract").option("--require-connector <name>", "include a connector in overall readiness (repeatable)", collectRepeatable, []).action((opts) => {
34673
+ const unsupported = opts.requireConnector.filter((name) => name !== "cursor");
34674
+ if (unsupported.length > 0) throw new Error(`unsupported factory connector: ${unsupported.join(", ")}`);
34675
+ const requiredConnectors = [...new Set(opts.requireConnector)];
34676
+ const output = factoryDiagnostics(buildContext(stdoutLogger), void 0, requiredConnectors);
34581
34677
  process.stdout.write(`${JSON.stringify(output)}
34582
34678
  `);
34583
34679
  if (output.overall.status !== "ready") process.exitCode = 1;
@@ -34605,7 +34701,7 @@ for (const action of ["resolve", "reopen"]) runtimeErrors.command(`${action} <fi
34605
34701
  `);
34606
34702
  });
34607
34703
  program.command("init").description(
34608
- "Initialize ~/.caveatrc.json, ~/.caveat/, and register Claude Code integration. Add knowledge sources later with `caveat community add <github-url>`."
34704
+ "Initialize Caveat state and available host integrations, with optional private sync. Add knowledge sources later with `caveat community add <github-url>`."
34609
34705
  ).option("--skip-claude", "skip Claude Code MCP + hook registration", false).option("--sync [url]", "initialize private sync (optionally with its URL)").option("--publish-target [url]", "configure the sealed public mirror target").option("--yes", "approve creating conventional GitHub repositories", false).option("--skip-codex-hook", "skip Codex hook installation", false).option("--skip-cursor-hook", "skip Cursor hook installation", false).option("--dry-run", "show planned changes without writing", false).option(
34610
34706
  "--pending-stale-days <days>",
34611
34707
  "sweep `<caveatHome>/pending/<sessionId>/` whose newest entry is older than this (default 7)",
@@ -34695,7 +34791,7 @@ program.command("hook <name> [arg]").description(
34695
34791
  await runHook(name, arg);
34696
34792
  });
34697
34793
  var codexHook = program.command("codex-hook").description("Install or run Codex hooks for Caveat");
34698
- codexHook.command("install").description("Install Caveat hooks into ~/.codex/hooks.json and enable hooks").option("--dry-run", "show planned changes without writing", false).option("--codex-home <path>", "Codex home directory", process.env.CODEX_HOME ?? `${process.env.HOME}/.codex`).action((opts) => {
34794
+ codexHook.command("install").description("Install Caveat hooks into ~/.codex/hooks.json and enable hooks").option("--dry-run", "show planned changes without writing", false).option("--codex-home <path>", "Codex home directory", agentPaths.codexHome).action((opts) => {
34699
34795
  const cliScriptPath = process.argv[1];
34700
34796
  if (!cliScriptPath) {
34701
34797
  process.stderr.write("[caveat:error] cannot determine CLI script path\n");
@@ -34722,7 +34818,7 @@ codexHook.command("install").description("Install Caveat hooks into ~/.codex/hoo
34722
34818
  stdoutLogger.info(`config.toml backed up: ${result.configBackupPath}`);
34723
34819
  }
34724
34820
  });
34725
- codexHook.command("uninstall").description("Remove Caveat-owned Codex hooks from ~/.codex/hooks.json").option("--dry-run", "show planned changes without writing", false).option("--codex-home <path>", "Codex home directory", process.env.CODEX_HOME ?? `${process.env.HOME}/.codex`).action((opts) => {
34821
+ codexHook.command("uninstall").description("Remove Caveat-owned Codex hooks from ~/.codex/hooks.json").option("--dry-run", "show planned changes without writing", false).option("--codex-home <path>", "Codex home directory", agentPaths.codexHome).action((opts) => {
34726
34822
  const cliScriptPath = process.argv[1];
34727
34823
  if (!cliScriptPath) {
34728
34824
  process.stderr.write("[caveat:error] cannot determine CLI script path\n");
@@ -34740,7 +34836,7 @@ codexHook.command("uninstall").description("Remove Caveat-owned Codex hooks from
34740
34836
  stdoutLogger.info(`Stop hook: ${result.hooks.stop === "added" ? "removed" : "not present"}`);
34741
34837
  if (result.backupPath) stdoutLogger.info(`hooks.json backed up: ${result.backupPath}`);
34742
34838
  });
34743
- codexHook.command("diagnostics").description("Check local Codex hook availability").option("--codex-home <path>", "Codex home directory", process.env.CODEX_HOME ?? `${process.env.HOME}/.codex`).action(async (opts) => {
34839
+ codexHook.command("diagnostics").description("Check local Codex hook availability").option("--codex-home <path>", "Codex home directory", agentPaths.codexHome).action(async (opts) => {
34744
34840
  await runCodexHook("diagnostics", opts.codexHome);
34745
34841
  });
34746
34842
  codexHook.command("user-prompt-submit").description("Run the Codex UserPromptSubmit hook").action(async () => {
@@ -34756,7 +34852,7 @@ codexHook.command("worker <workFile>").description("Run the detached Codex hook
34756
34852
  await runCodexHook("worker", workFile);
34757
34853
  });
34758
34854
  var cursorHook = program.command("cursor-hook").description("Install or run Cursor hooks for Caveat");
34759
- cursorHook.command("install").description("Install Caveat hooks into ~/.cursor/hooks.json (factory hooks are kept)").option("--dry-run", "show planned changes without writing", false).option("--cursor-dir <path>", "Cursor home directory", `${process.env.HOME}/.cursor`).action((opts) => {
34855
+ cursorHook.command("install").description("Install Caveat hooks into ~/.cursor/hooks.json (factory hooks are kept)").option("--dry-run", "show planned changes without writing", false).option("--cursor-dir <path>", "Cursor home directory", agentPaths.cursorDir).action((opts) => {
34760
34856
  const cliScriptPath = process.argv[1];
34761
34857
  if (!cliScriptPath) {
34762
34858
  process.stderr.write("[caveat:error] cannot determine CLI script path\n");
@@ -34775,7 +34871,7 @@ cursorHook.command("install").description("Install Caveat hooks into ~/.cursor/h
34775
34871
  stdoutLogger.info(`stop hook: ${result.hooks.stop}`);
34776
34872
  if (result.backupPath) stdoutLogger.info(`hooks.json backed up: ${result.backupPath}`);
34777
34873
  });
34778
- cursorHook.command("uninstall").description("Remove Caveat-owned Cursor hooks from ~/.cursor/hooks.json").option("--dry-run", "show planned changes without writing", false).option("--cursor-dir <path>", "Cursor home directory", `${process.env.HOME}/.cursor`).action((opts) => {
34874
+ cursorHook.command("uninstall").description("Remove Caveat-owned Cursor hooks from ~/.cursor/hooks.json").option("--dry-run", "show planned changes without writing", false).option("--cursor-dir <path>", "Cursor home directory", agentPaths.cursorDir).action((opts) => {
34779
34875
  const cliScriptPath = process.argv[1];
34780
34876
  if (!cliScriptPath) {
34781
34877
  process.stderr.write("[caveat:error] cannot determine CLI script path\n");
@@ -34794,7 +34890,7 @@ cursorHook.command("uninstall").description("Remove Caveat-owned Cursor hooks fr
34794
34890
  stdoutLogger.info(`stop hook: ${result.hooks.stop === "added" ? "removed" : "not present"}`);
34795
34891
  if (result.backupPath) stdoutLogger.info(`hooks.json backed up: ${result.backupPath}`);
34796
34892
  });
34797
- cursorHook.command("diagnostics").description("Check local Cursor hook installation").option("--cursor-dir <path>", "Cursor home directory", `${process.env.HOME}/.cursor`).action(async (opts) => {
34893
+ cursorHook.command("diagnostics").description("Check local Cursor hook installation").option("--cursor-dir <path>", "Cursor home directory", agentPaths.cursorDir).action(async (opts) => {
34798
34894
  await runCursorHook("diagnostics", opts.cursorDir);
34799
34895
  });
34800
34896
  cursorHook.command("user-prompt-submit").description("Run the Cursor beforeSubmitPrompt hook").action(async () => {