opencode-codebase-index 0.20.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -658,9 +658,11 @@ var require_eventemitter3 = __commonJS({
658
658
  // src/index.ts
659
659
  var index_exports = {};
660
660
  __export(index_exports, {
661
- default: () => index_default
661
+ default: () => opencode_default
662
662
  });
663
663
  module.exports = __toCommonJS(index_exports);
664
+
665
+ // src/adapters/opencode.ts
664
666
  var path26 = __toESM(require("path"), 1);
665
667
  var import_url = require("url");
666
668
 
@@ -1070,12 +1072,12 @@ var autoDetectProviders = AUTO_DETECT_PROVIDER_ORDER.filter(
1070
1072
 
1071
1073
  // src/config/merger.ts
1072
1074
  var import_fs4 = require("fs");
1073
- var path6 = __toESM(require("path"), 1);
1075
+ var path7 = __toESM(require("path"), 1);
1074
1076
 
1075
1077
  // src/config/paths.ts
1076
1078
  var import_fs3 = require("fs");
1077
1079
  var os = __toESM(require("os"), 1);
1078
- var path3 = __toESM(require("path"), 1);
1080
+ var path4 = __toESM(require("path"), 1);
1079
1081
 
1080
1082
  // src/git/index.ts
1081
1083
  var import_fs2 = require("fs");
@@ -1214,15 +1216,125 @@ function getHeadPath(repoRoot) {
1214
1216
  return path2.join(repoRoot, ".git", "HEAD");
1215
1217
  }
1216
1218
 
1219
+ // src/utils/canonical-path.ts
1220
+ var crypto = __toESM(require("crypto"), 1);
1221
+ var fs = __toESM(require("fs"), 1);
1222
+ var path3 = __toESM(require("path"), 1);
1223
+
1224
+ // node_modules/unicode-case-folding/index.js
1225
+ var FOLDING_MAP = /* @__PURE__ */ new Map([[65, [97]], [66, [98]], [67, [99]], [68, [100]], [69, [101]], [70, [102]], [71, [103]], [72, [104]], [73, [105]], [74, [106]], [75, [107]], [76, [108]], [77, [109]], [78, [110]], [79, [111]], [80, [112]], [81, [113]], [82, [114]], [83, [115]], [84, [116]], [85, [117]], [86, [118]], [87, [119]], [88, [120]], [89, [121]], [90, [122]], [181, [956]], [192, [224]], [193, [225]], [194, [226]], [195, [227]], [196, [228]], [197, [229]], [198, [230]], [199, [231]], [200, [232]], [201, [233]], [202, [234]], [203, [235]], [204, [236]], [205, [237]], [206, [238]], [207, [239]], [208, [240]], [209, [241]], [210, [242]], [211, [243]], [212, [244]], [213, [245]], [214, [246]], [216, [248]], [217, [249]], [218, [250]], [219, [251]], [220, [252]], [221, [253]], [222, [254]], [223, [115, 115]], [256, [257]], [258, [259]], [260, [261]], [262, [263]], [264, [265]], [266, [267]], [268, [269]], [270, [271]], [272, [273]], [274, [275]], [276, [277]], [278, [279]], [280, [281]], [282, [283]], [284, [285]], [286, [287]], [288, [289]], [290, [291]], [292, [293]], [294, [295]], [296, [297]], [298, [299]], [300, [301]], [302, [303]], [304, [105, 775]], [306, [307]], [308, [309]], [310, [311]], [313, [314]], [315, [316]], [317, [318]], [319, [320]], [321, [322]], [323, [324]], [325, [326]], [327, [328]], [329, [700, 110]], [330, [331]], [332, [333]], [334, [335]], [336, [337]], [338, [339]], [340, [341]], [342, [343]], [344, [345]], [346, [347]], [348, [349]], [350, [351]], [352, [353]], [354, [355]], [356, [357]], [358, [359]], [360, [361]], [362, [363]], [364, [365]], [366, [367]], [368, [369]], [370, [371]], [372, [373]], [374, [375]], [376, [255]], [377, [378]], [379, [380]], [381, [382]], [383, [115]], [385, [595]], [386, [387]], [388, [389]], [390, [596]], [391, [392]], [393, [598]], [394, [599]], [395, [396]], [398, [477]], [399, [601]], [400, [603]], [401, [402]], [403, [608]], [404, [611]], [406, [617]], [407, [616]], [408, [409]], [412, [623]], [413, [626]], [415, [629]], [416, [417]], [418, [419]], [420, [421]], [422, [640]], [423, [424]], [425, [643]], [428, [429]], [430, [648]], [431, [432]], [433, [650]], [434, [651]], [435, [436]], [437, [438]], [439, [658]], [440, [441]], [444, [445]], [452, [454]], [453, [454]], [455, [457]], [456, [457]], [458, [460]], [459, [460]], [461, [462]], [463, [464]], [465, [466]], [467, [468]], [469, [470]], [471, [472]], [473, [474]], [475, [476]], [478, [479]], [480, [481]], [482, [483]], [484, [485]], [486, [487]], [488, [489]], [490, [491]], [492, [493]], [494, [495]], [496, [106, 780]], [497, [499]], [498, [499]], [500, [501]], [502, [405]], [503, [447]], [504, [505]], [506, [507]], [508, [509]], [510, [511]], [512, [513]], [514, [515]], [516, [517]], [518, [519]], [520, [521]], [522, [523]], [524, [525]], [526, [527]], [528, [529]], [530, [531]], [532, [533]], [534, [535]], [536, [537]], [538, [539]], [540, [541]], [542, [543]], [544, [414]], [546, [547]], [548, [549]], [550, [551]], [552, [553]], [554, [555]], [556, [557]], [558, [559]], [560, [561]], [562, [563]], [570, [11365]], [571, [572]], [573, [410]], [574, [11366]], [577, [578]], [579, [384]], [580, [649]], [581, [652]], [582, [583]], [584, [585]], [586, [587]], [588, [589]], [590, [591]], [837, [953]], [880, [881]], [882, [883]], [886, [887]], [895, [1011]], [902, [940]], [904, [941]], [905, [942]], [906, [943]], [908, [972]], [910, [973]], [911, [974]], [912, [953, 776, 769]], [913, [945]], [914, [946]], [915, [947]], [916, [948]], [917, [949]], [918, [950]], [919, [951]], [920, [952]], [921, [953]], [922, [954]], [923, [955]], [924, [956]], [925, [957]], [926, [958]], [927, [959]], [928, [960]], [929, [961]], [931, [963]], [932, [964]], [933, [965]], [934, [966]], [935, [967]], [936, [968]], [937, [969]], [938, [970]], [939, [971]], [944, [965, 776, 769]], [962, [963]], [975, [983]], [976, [946]], [977, [952]], [981, [966]], [982, [960]], [984, [985]], [986, [987]], [988, [989]], [990, [991]], [992, [993]], [994, [995]], [996, [997]], [998, [999]], [1e3, [1001]], [1002, [1003]], [1004, [1005]], [1006, [1007]], [1008, [954]], [1009, [961]], [1012, [952]], [1013, [949]], [1015, [1016]], [1017, [1010]], [1018, [1019]], [1021, [891]], [1022, [892]], [1023, [893]], [1024, [1104]], [1025, [1105]], [1026, [1106]], [1027, [1107]], [1028, [1108]], [1029, [1109]], [1030, [1110]], [1031, [1111]], [1032, [1112]], [1033, [1113]], [1034, [1114]], [1035, [1115]], [1036, [1116]], [1037, [1117]], [1038, [1118]], [1039, [1119]], [1040, [1072]], [1041, [1073]], [1042, [1074]], [1043, [1075]], [1044, [1076]], [1045, [1077]], [1046, [1078]], [1047, [1079]], [1048, [1080]], [1049, [1081]], [1050, [1082]], [1051, [1083]], [1052, [1084]], [1053, [1085]], [1054, [1086]], [1055, [1087]], [1056, [1088]], [1057, [1089]], [1058, [1090]], [1059, [1091]], [1060, [1092]], [1061, [1093]], [1062, [1094]], [1063, [1095]], [1064, [1096]], [1065, [1097]], [1066, [1098]], [1067, [1099]], [1068, [1100]], [1069, [1101]], [1070, [1102]], [1071, [1103]], [1120, [1121]], [1122, [1123]], [1124, [1125]], [1126, [1127]], [1128, [1129]], [1130, [1131]], [1132, [1133]], [1134, [1135]], [1136, [1137]], [1138, [1139]], [1140, [1141]], [1142, [1143]], [1144, [1145]], [1146, [1147]], [1148, [1149]], [1150, [1151]], [1152, [1153]], [1162, [1163]], [1164, [1165]], [1166, [1167]], [1168, [1169]], [1170, [1171]], [1172, [1173]], [1174, [1175]], [1176, [1177]], [1178, [1179]], [1180, [1181]], [1182, [1183]], [1184, [1185]], [1186, [1187]], [1188, [1189]], [1190, [1191]], [1192, [1193]], [1194, [1195]], [1196, [1197]], [1198, [1199]], [1200, [1201]], [1202, [1203]], [1204, [1205]], [1206, [1207]], [1208, [1209]], [1210, [1211]], [1212, [1213]], [1214, [1215]], [1216, [1231]], [1217, [1218]], [1219, [1220]], [1221, [1222]], [1223, [1224]], [1225, [1226]], [1227, [1228]], [1229, [1230]], [1232, [1233]], [1234, [1235]], [1236, [1237]], [1238, [1239]], [1240, [1241]], [1242, [1243]], [1244, [1245]], [1246, [1247]], [1248, [1249]], [1250, [1251]], [1252, [1253]], [1254, [1255]], [1256, [1257]], [1258, [1259]], [1260, [1261]], [1262, [1263]], [1264, [1265]], [1266, [1267]], [1268, [1269]], [1270, [1271]], [1272, [1273]], [1274, [1275]], [1276, [1277]], [1278, [1279]], [1280, [1281]], [1282, [1283]], [1284, [1285]], [1286, [1287]], [1288, [1289]], [1290, [1291]], [1292, [1293]], [1294, [1295]], [1296, [1297]], [1298, [1299]], [1300, [1301]], [1302, [1303]], [1304, [1305]], [1306, [1307]], [1308, [1309]], [1310, [1311]], [1312, [1313]], [1314, [1315]], [1316, [1317]], [1318, [1319]], [1320, [1321]], [1322, [1323]], [1324, [1325]], [1326, [1327]], [1329, [1377]], [1330, [1378]], [1331, [1379]], [1332, [1380]], [1333, [1381]], [1334, [1382]], [1335, [1383]], [1336, [1384]], [1337, [1385]], [1338, [1386]], [1339, [1387]], [1340, [1388]], [1341, [1389]], [1342, [1390]], [1343, [1391]], [1344, [1392]], [1345, [1393]], [1346, [1394]], [1347, [1395]], [1348, [1396]], [1349, [1397]], [1350, [1398]], [1351, [1399]], [1352, [1400]], [1353, [1401]], [1354, [1402]], [1355, [1403]], [1356, [1404]], [1357, [1405]], [1358, [1406]], [1359, [1407]], [1360, [1408]], [1361, [1409]], [1362, [1410]], [1363, [1411]], [1364, [1412]], [1365, [1413]], [1366, [1414]], [1415, [1381, 1410]], [4256, [11520]], [4257, [11521]], [4258, [11522]], [4259, [11523]], [4260, [11524]], [4261, [11525]], [4262, [11526]], [4263, [11527]], [4264, [11528]], [4265, [11529]], [4266, [11530]], [4267, [11531]], [4268, [11532]], [4269, [11533]], [4270, [11534]], [4271, [11535]], [4272, [11536]], [4273, [11537]], [4274, [11538]], [4275, [11539]], [4276, [11540]], [4277, [11541]], [4278, [11542]], [4279, [11543]], [4280, [11544]], [4281, [11545]], [4282, [11546]], [4283, [11547]], [4284, [11548]], [4285, [11549]], [4286, [11550]], [4287, [11551]], [4288, [11552]], [4289, [11553]], [4290, [11554]], [4291, [11555]], [4292, [11556]], [4293, [11557]], [4295, [11559]], [4301, [11565]], [5112, [5104]], [5113, [5105]], [5114, [5106]], [5115, [5107]], [5116, [5108]], [5117, [5109]], [7296, [1074]], [7297, [1076]], [7298, [1086]], [7299, [1089]], [7300, [1090]], [7301, [1090]], [7302, [1098]], [7303, [1123]], [7304, [42571]], [7305, [7306]], [7312, [4304]], [7313, [4305]], [7314, [4306]], [7315, [4307]], [7316, [4308]], [7317, [4309]], [7318, [4310]], [7319, [4311]], [7320, [4312]], [7321, [4313]], [7322, [4314]], [7323, [4315]], [7324, [4316]], [7325, [4317]], [7326, [4318]], [7327, [4319]], [7328, [4320]], [7329, [4321]], [7330, [4322]], [7331, [4323]], [7332, [4324]], [7333, [4325]], [7334, [4326]], [7335, [4327]], [7336, [4328]], [7337, [4329]], [7338, [4330]], [7339, [4331]], [7340, [4332]], [7341, [4333]], [7342, [4334]], [7343, [4335]], [7344, [4336]], [7345, [4337]], [7346, [4338]], [7347, [4339]], [7348, [4340]], [7349, [4341]], [7350, [4342]], [7351, [4343]], [7352, [4344]], [7353, [4345]], [7354, [4346]], [7357, [4349]], [7358, [4350]], [7359, [4351]], [7680, [7681]], [7682, [7683]], [7684, [7685]], [7686, [7687]], [7688, [7689]], [7690, [7691]], [7692, [7693]], [7694, [7695]], [7696, [7697]], [7698, [7699]], [7700, [7701]], [7702, [7703]], [7704, [7705]], [7706, [7707]], [7708, [7709]], [7710, [7711]], [7712, [7713]], [7714, [7715]], [7716, [7717]], [7718, [7719]], [7720, [7721]], [7722, [7723]], [7724, [7725]], [7726, [7727]], [7728, [7729]], [7730, [7731]], [7732, [7733]], [7734, [7735]], [7736, [7737]], [7738, [7739]], [7740, [7741]], [7742, [7743]], [7744, [7745]], [7746, [7747]], [7748, [7749]], [7750, [7751]], [7752, [7753]], [7754, [7755]], [7756, [7757]], [7758, [7759]], [7760, [7761]], [7762, [7763]], [7764, [7765]], [7766, [7767]], [7768, [7769]], [7770, [7771]], [7772, [7773]], [7774, [7775]], [7776, [7777]], [7778, [7779]], [7780, [7781]], [7782, [7783]], [7784, [7785]], [7786, [7787]], [7788, [7789]], [7790, [7791]], [7792, [7793]], [7794, [7795]], [7796, [7797]], [7798, [7799]], [7800, [7801]], [7802, [7803]], [7804, [7805]], [7806, [7807]], [7808, [7809]], [7810, [7811]], [7812, [7813]], [7814, [7815]], [7816, [7817]], [7818, [7819]], [7820, [7821]], [7822, [7823]], [7824, [7825]], [7826, [7827]], [7828, [7829]], [7830, [104, 817]], [7831, [116, 776]], [7832, [119, 778]], [7833, [121, 778]], [7834, [97, 702]], [7835, [7777]], [7838, [115, 115]], [7840, [7841]], [7842, [7843]], [7844, [7845]], [7846, [7847]], [7848, [7849]], [7850, [7851]], [7852, [7853]], [7854, [7855]], [7856, [7857]], [7858, [7859]], [7860, [7861]], [7862, [7863]], [7864, [7865]], [7866, [7867]], [7868, [7869]], [7870, [7871]], [7872, [7873]], [7874, [7875]], [7876, [7877]], [7878, [7879]], [7880, [7881]], [7882, [7883]], [7884, [7885]], [7886, [7887]], [7888, [7889]], [7890, [7891]], [7892, [7893]], [7894, [7895]], [7896, [7897]], [7898, [7899]], [7900, [7901]], [7902, [7903]], [7904, [7905]], [7906, [7907]], [7908, [7909]], [7910, [7911]], [7912, [7913]], [7914, [7915]], [7916, [7917]], [7918, [7919]], [7920, [7921]], [7922, [7923]], [7924, [7925]], [7926, [7927]], [7928, [7929]], [7930, [7931]], [7932, [7933]], [7934, [7935]], [7944, [7936]], [7945, [7937]], [7946, [7938]], [7947, [7939]], [7948, [7940]], [7949, [7941]], [7950, [7942]], [7951, [7943]], [7960, [7952]], [7961, [7953]], [7962, [7954]], [7963, [7955]], [7964, [7956]], [7965, [7957]], [7976, [7968]], [7977, [7969]], [7978, [7970]], [7979, [7971]], [7980, [7972]], [7981, [7973]], [7982, [7974]], [7983, [7975]], [7992, [7984]], [7993, [7985]], [7994, [7986]], [7995, [7987]], [7996, [7988]], [7997, [7989]], [7998, [7990]], [7999, [7991]], [8008, [8e3]], [8009, [8001]], [8010, [8002]], [8011, [8003]], [8012, [8004]], [8013, [8005]], [8016, [965, 787]], [8018, [965, 787, 768]], [8020, [965, 787, 769]], [8022, [965, 787, 834]], [8025, [8017]], [8027, [8019]], [8029, [8021]], [8031, [8023]], [8040, [8032]], [8041, [8033]], [8042, [8034]], [8043, [8035]], [8044, [8036]], [8045, [8037]], [8046, [8038]], [8047, [8039]], [8064, [7936, 953]], [8065, [7937, 953]], [8066, [7938, 953]], [8067, [7939, 953]], [8068, [7940, 953]], [8069, [7941, 953]], [8070, [7942, 953]], [8071, [7943, 953]], [8072, [7936, 953]], [8073, [7937, 953]], [8074, [7938, 953]], [8075, [7939, 953]], [8076, [7940, 953]], [8077, [7941, 953]], [8078, [7942, 953]], [8079, [7943, 953]], [8080, [7968, 953]], [8081, [7969, 953]], [8082, [7970, 953]], [8083, [7971, 953]], [8084, [7972, 953]], [8085, [7973, 953]], [8086, [7974, 953]], [8087, [7975, 953]], [8088, [7968, 953]], [8089, [7969, 953]], [8090, [7970, 953]], [8091, [7971, 953]], [8092, [7972, 953]], [8093, [7973, 953]], [8094, [7974, 953]], [8095, [7975, 953]], [8096, [8032, 953]], [8097, [8033, 953]], [8098, [8034, 953]], [8099, [8035, 953]], [8100, [8036, 953]], [8101, [8037, 953]], [8102, [8038, 953]], [8103, [8039, 953]], [8104, [8032, 953]], [8105, [8033, 953]], [8106, [8034, 953]], [8107, [8035, 953]], [8108, [8036, 953]], [8109, [8037, 953]], [8110, [8038, 953]], [8111, [8039, 953]], [8114, [8048, 953]], [8115, [945, 953]], [8116, [940, 953]], [8118, [945, 834]], [8119, [945, 834, 953]], [8120, [8112]], [8121, [8113]], [8122, [8048]], [8123, [8049]], [8124, [945, 953]], [8126, [953]], [8130, [8052, 953]], [8131, [951, 953]], [8132, [942, 953]], [8134, [951, 834]], [8135, [951, 834, 953]], [8136, [8050]], [8137, [8051]], [8138, [8052]], [8139, [8053]], [8140, [951, 953]], [8146, [953, 776, 768]], [8147, [953, 776, 769]], [8150, [953, 834]], [8151, [953, 776, 834]], [8152, [8144]], [8153, [8145]], [8154, [8054]], [8155, [8055]], [8162, [965, 776, 768]], [8163, [965, 776, 769]], [8164, [961, 787]], [8166, [965, 834]], [8167, [965, 776, 834]], [8168, [8160]], [8169, [8161]], [8170, [8058]], [8171, [8059]], [8172, [8165]], [8178, [8060, 953]], [8179, [969, 953]], [8180, [974, 953]], [8182, [969, 834]], [8183, [969, 834, 953]], [8184, [8056]], [8185, [8057]], [8186, [8060]], [8187, [8061]], [8188, [969, 953]], [8486, [969]], [8490, [107]], [8491, [229]], [8498, [8526]], [8544, [8560]], [8545, [8561]], [8546, [8562]], [8547, [8563]], [8548, [8564]], [8549, [8565]], [8550, [8566]], [8551, [8567]], [8552, [8568]], [8553, [8569]], [8554, [8570]], [8555, [8571]], [8556, [8572]], [8557, [8573]], [8558, [8574]], [8559, [8575]], [8579, [8580]], [9398, [9424]], [9399, [9425]], [9400, [9426]], [9401, [9427]], [9402, [9428]], [9403, [9429]], [9404, [9430]], [9405, [9431]], [9406, [9432]], [9407, [9433]], [9408, [9434]], [9409, [9435]], [9410, [9436]], [9411, [9437]], [9412, [9438]], [9413, [9439]], [9414, [9440]], [9415, [9441]], [9416, [9442]], [9417, [9443]], [9418, [9444]], [9419, [9445]], [9420, [9446]], [9421, [9447]], [9422, [9448]], [9423, [9449]], [11264, [11312]], [11265, [11313]], [11266, [11314]], [11267, [11315]], [11268, [11316]], [11269, [11317]], [11270, [11318]], [11271, [11319]], [11272, [11320]], [11273, [11321]], [11274, [11322]], [11275, [11323]], [11276, [11324]], [11277, [11325]], [11278, [11326]], [11279, [11327]], [11280, [11328]], [11281, [11329]], [11282, [11330]], [11283, [11331]], [11284, [11332]], [11285, [11333]], [11286, [11334]], [11287, [11335]], [11288, [11336]], [11289, [11337]], [11290, [11338]], [11291, [11339]], [11292, [11340]], [11293, [11341]], [11294, [11342]], [11295, [11343]], [11296, [11344]], [11297, [11345]], [11298, [11346]], [11299, [11347]], [11300, [11348]], [11301, [11349]], [11302, [11350]], [11303, [11351]], [11304, [11352]], [11305, [11353]], [11306, [11354]], [11307, [11355]], [11308, [11356]], [11309, [11357]], [11310, [11358]], [11311, [11359]], [11360, [11361]], [11362, [619]], [11363, [7549]], [11364, [637]], [11367, [11368]], [11369, [11370]], [11371, [11372]], [11373, [593]], [11374, [625]], [11375, [592]], [11376, [594]], [11378, [11379]], [11381, [11382]], [11390, [575]], [11391, [576]], [11392, [11393]], [11394, [11395]], [11396, [11397]], [11398, [11399]], [11400, [11401]], [11402, [11403]], [11404, [11405]], [11406, [11407]], [11408, [11409]], [11410, [11411]], [11412, [11413]], [11414, [11415]], [11416, [11417]], [11418, [11419]], [11420, [11421]], [11422, [11423]], [11424, [11425]], [11426, [11427]], [11428, [11429]], [11430, [11431]], [11432, [11433]], [11434, [11435]], [11436, [11437]], [11438, [11439]], [11440, [11441]], [11442, [11443]], [11444, [11445]], [11446, [11447]], [11448, [11449]], [11450, [11451]], [11452, [11453]], [11454, [11455]], [11456, [11457]], [11458, [11459]], [11460, [11461]], [11462, [11463]], [11464, [11465]], [11466, [11467]], [11468, [11469]], [11470, [11471]], [11472, [11473]], [11474, [11475]], [11476, [11477]], [11478, [11479]], [11480, [11481]], [11482, [11483]], [11484, [11485]], [11486, [11487]], [11488, [11489]], [11490, [11491]], [11499, [11500]], [11501, [11502]], [11506, [11507]], [42560, [42561]], [42562, [42563]], [42564, [42565]], [42566, [42567]], [42568, [42569]], [42570, [42571]], [42572, [42573]], [42574, [42575]], [42576, [42577]], [42578, [42579]], [42580, [42581]], [42582, [42583]], [42584, [42585]], [42586, [42587]], [42588, [42589]], [42590, [42591]], [42592, [42593]], [42594, [42595]], [42596, [42597]], [42598, [42599]], [42600, [42601]], [42602, [42603]], [42604, [42605]], [42624, [42625]], [42626, [42627]], [42628, [42629]], [42630, [42631]], [42632, [42633]], [42634, [42635]], [42636, [42637]], [42638, [42639]], [42640, [42641]], [42642, [42643]], [42644, [42645]], [42646, [42647]], [42648, [42649]], [42650, [42651]], [42786, [42787]], [42788, [42789]], [42790, [42791]], [42792, [42793]], [42794, [42795]], [42796, [42797]], [42798, [42799]], [42802, [42803]], [42804, [42805]], [42806, [42807]], [42808, [42809]], [42810, [42811]], [42812, [42813]], [42814, [42815]], [42816, [42817]], [42818, [42819]], [42820, [42821]], [42822, [42823]], [42824, [42825]], [42826, [42827]], [42828, [42829]], [42830, [42831]], [42832, [42833]], [42834, [42835]], [42836, [42837]], [42838, [42839]], [42840, [42841]], [42842, [42843]], [42844, [42845]], [42846, [42847]], [42848, [42849]], [42850, [42851]], [42852, [42853]], [42854, [42855]], [42856, [42857]], [42858, [42859]], [42860, [42861]], [42862, [42863]], [42873, [42874]], [42875, [42876]], [42877, [7545]], [42878, [42879]], [42880, [42881]], [42882, [42883]], [42884, [42885]], [42886, [42887]], [42891, [42892]], [42893, [613]], [42896, [42897]], [42898, [42899]], [42902, [42903]], [42904, [42905]], [42906, [42907]], [42908, [42909]], [42910, [42911]], [42912, [42913]], [42914, [42915]], [42916, [42917]], [42918, [42919]], [42920, [42921]], [42922, [614]], [42923, [604]], [42924, [609]], [42925, [620]], [42926, [618]], [42928, [670]], [42929, [647]], [42930, [669]], [42931, [43859]], [42932, [42933]], [42934, [42935]], [42936, [42937]], [42938, [42939]], [42940, [42941]], [42942, [42943]], [42944, [42945]], [42946, [42947]], [42948, [42900]], [42949, [642]], [42950, [7566]], [42951, [42952]], [42953, [42954]], [42955, [612]], [42956, [42957]], [42958, [42959]], [42960, [42961]], [42962, [42963]], [42964, [42965]], [42966, [42967]], [42968, [42969]], [42970, [42971]], [42972, [411]], [42997, [42998]], [43888, [5024]], [43889, [5025]], [43890, [5026]], [43891, [5027]], [43892, [5028]], [43893, [5029]], [43894, [5030]], [43895, [5031]], [43896, [5032]], [43897, [5033]], [43898, [5034]], [43899, [5035]], [43900, [5036]], [43901, [5037]], [43902, [5038]], [43903, [5039]], [43904, [5040]], [43905, [5041]], [43906, [5042]], [43907, [5043]], [43908, [5044]], [43909, [5045]], [43910, [5046]], [43911, [5047]], [43912, [5048]], [43913, [5049]], [43914, [5050]], [43915, [5051]], [43916, [5052]], [43917, [5053]], [43918, [5054]], [43919, [5055]], [43920, [5056]], [43921, [5057]], [43922, [5058]], [43923, [5059]], [43924, [5060]], [43925, [5061]], [43926, [5062]], [43927, [5063]], [43928, [5064]], [43929, [5065]], [43930, [5066]], [43931, [5067]], [43932, [5068]], [43933, [5069]], [43934, [5070]], [43935, [5071]], [43936, [5072]], [43937, [5073]], [43938, [5074]], [43939, [5075]], [43940, [5076]], [43941, [5077]], [43942, [5078]], [43943, [5079]], [43944, [5080]], [43945, [5081]], [43946, [5082]], [43947, [5083]], [43948, [5084]], [43949, [5085]], [43950, [5086]], [43951, [5087]], [43952, [5088]], [43953, [5089]], [43954, [5090]], [43955, [5091]], [43956, [5092]], [43957, [5093]], [43958, [5094]], [43959, [5095]], [43960, [5096]], [43961, [5097]], [43962, [5098]], [43963, [5099]], [43964, [5100]], [43965, [5101]], [43966, [5102]], [43967, [5103]], [64256, [102, 102]], [64257, [102, 105]], [64258, [102, 108]], [64259, [102, 102, 105]], [64260, [102, 102, 108]], [64261, [115, 116]], [64262, [115, 116]], [64275, [1396, 1398]], [64276, [1396, 1381]], [64277, [1396, 1387]], [64278, [1406, 1398]], [64279, [1396, 1389]], [65313, [65345]], [65314, [65346]], [65315, [65347]], [65316, [65348]], [65317, [65349]], [65318, [65350]], [65319, [65351]], [65320, [65352]], [65321, [65353]], [65322, [65354]], [65323, [65355]], [65324, [65356]], [65325, [65357]], [65326, [65358]], [65327, [65359]], [65328, [65360]], [65329, [65361]], [65330, [65362]], [65331, [65363]], [65332, [65364]], [65333, [65365]], [65334, [65366]], [65335, [65367]], [65336, [65368]], [65337, [65369]], [65338, [65370]], [66560, [66600]], [66561, [66601]], [66562, [66602]], [66563, [66603]], [66564, [66604]], [66565, [66605]], [66566, [66606]], [66567, [66607]], [66568, [66608]], [66569, [66609]], [66570, [66610]], [66571, [66611]], [66572, [66612]], [66573, [66613]], [66574, [66614]], [66575, [66615]], [66576, [66616]], [66577, [66617]], [66578, [66618]], [66579, [66619]], [66580, [66620]], [66581, [66621]], [66582, [66622]], [66583, [66623]], [66584, [66624]], [66585, [66625]], [66586, [66626]], [66587, [66627]], [66588, [66628]], [66589, [66629]], [66590, [66630]], [66591, [66631]], [66592, [66632]], [66593, [66633]], [66594, [66634]], [66595, [66635]], [66596, [66636]], [66597, [66637]], [66598, [66638]], [66599, [66639]], [66736, [66776]], [66737, [66777]], [66738, [66778]], [66739, [66779]], [66740, [66780]], [66741, [66781]], [66742, [66782]], [66743, [66783]], [66744, [66784]], [66745, [66785]], [66746, [66786]], [66747, [66787]], [66748, [66788]], [66749, [66789]], [66750, [66790]], [66751, [66791]], [66752, [66792]], [66753, [66793]], [66754, [66794]], [66755, [66795]], [66756, [66796]], [66757, [66797]], [66758, [66798]], [66759, [66799]], [66760, [66800]], [66761, [66801]], [66762, [66802]], [66763, [66803]], [66764, [66804]], [66765, [66805]], [66766, [66806]], [66767, [66807]], [66768, [66808]], [66769, [66809]], [66770, [66810]], [66771, [66811]], [66928, [66967]], [66929, [66968]], [66930, [66969]], [66931, [66970]], [66932, [66971]], [66933, [66972]], [66934, [66973]], [66935, [66974]], [66936, [66975]], [66937, [66976]], [66938, [66977]], [66940, [66979]], [66941, [66980]], [66942, [66981]], [66943, [66982]], [66944, [66983]], [66945, [66984]], [66946, [66985]], [66947, [66986]], [66948, [66987]], [66949, [66988]], [66950, [66989]], [66951, [66990]], [66952, [66991]], [66953, [66992]], [66954, [66993]], [66956, [66995]], [66957, [66996]], [66958, [66997]], [66959, [66998]], [66960, [66999]], [66961, [67e3]], [66962, [67001]], [66964, [67003]], [66965, [67004]], [68736, [68800]], [68737, [68801]], [68738, [68802]], [68739, [68803]], [68740, [68804]], [68741, [68805]], [68742, [68806]], [68743, [68807]], [68744, [68808]], [68745, [68809]], [68746, [68810]], [68747, [68811]], [68748, [68812]], [68749, [68813]], [68750, [68814]], [68751, [68815]], [68752, [68816]], [68753, [68817]], [68754, [68818]], [68755, [68819]], [68756, [68820]], [68757, [68821]], [68758, [68822]], [68759, [68823]], [68760, [68824]], [68761, [68825]], [68762, [68826]], [68763, [68827]], [68764, [68828]], [68765, [68829]], [68766, [68830]], [68767, [68831]], [68768, [68832]], [68769, [68833]], [68770, [68834]], [68771, [68835]], [68772, [68836]], [68773, [68837]], [68774, [68838]], [68775, [68839]], [68776, [68840]], [68777, [68841]], [68778, [68842]], [68779, [68843]], [68780, [68844]], [68781, [68845]], [68782, [68846]], [68783, [68847]], [68784, [68848]], [68785, [68849]], [68786, [68850]], [68944, [68976]], [68945, [68977]], [68946, [68978]], [68947, [68979]], [68948, [68980]], [68949, [68981]], [68950, [68982]], [68951, [68983]], [68952, [68984]], [68953, [68985]], [68954, [68986]], [68955, [68987]], [68956, [68988]], [68957, [68989]], [68958, [68990]], [68959, [68991]], [68960, [68992]], [68961, [68993]], [68962, [68994]], [68963, [68995]], [68964, [68996]], [68965, [68997]], [71840, [71872]], [71841, [71873]], [71842, [71874]], [71843, [71875]], [71844, [71876]], [71845, [71877]], [71846, [71878]], [71847, [71879]], [71848, [71880]], [71849, [71881]], [71850, [71882]], [71851, [71883]], [71852, [71884]], [71853, [71885]], [71854, [71886]], [71855, [71887]], [71856, [71888]], [71857, [71889]], [71858, [71890]], [71859, [71891]], [71860, [71892]], [71861, [71893]], [71862, [71894]], [71863, [71895]], [71864, [71896]], [71865, [71897]], [71866, [71898]], [71867, [71899]], [71868, [71900]], [71869, [71901]], [71870, [71902]], [71871, [71903]], [93760, [93792]], [93761, [93793]], [93762, [93794]], [93763, [93795]], [93764, [93796]], [93765, [93797]], [93766, [93798]], [93767, [93799]], [93768, [93800]], [93769, [93801]], [93770, [93802]], [93771, [93803]], [93772, [93804]], [93773, [93805]], [93774, [93806]], [93775, [93807]], [93776, [93808]], [93777, [93809]], [93778, [93810]], [93779, [93811]], [93780, [93812]], [93781, [93813]], [93782, [93814]], [93783, [93815]], [93784, [93816]], [93785, [93817]], [93786, [93818]], [93787, [93819]], [93788, [93820]], [93789, [93821]], [93790, [93822]], [93791, [93823]], [93856, [93883]], [93857, [93884]], [93858, [93885]], [93859, [93886]], [93860, [93887]], [93861, [93888]], [93862, [93889]], [93863, [93890]], [93864, [93891]], [93865, [93892]], [93866, [93893]], [93867, [93894]], [93868, [93895]], [93869, [93896]], [93870, [93897]], [93871, [93898]], [93872, [93899]], [93873, [93900]], [93874, [93901]], [93875, [93902]], [93876, [93903]], [93877, [93904]], [93878, [93905]], [93879, [93906]], [93880, [93907]], [125184, [125218]], [125185, [125219]], [125186, [125220]], [125187, [125221]], [125188, [125222]], [125189, [125223]], [125190, [125224]], [125191, [125225]], [125192, [125226]], [125193, [125227]], [125194, [125228]], [125195, [125229]], [125196, [125230]], [125197, [125231]], [125198, [125232]], [125199, [125233]], [125200, [125234]], [125201, [125235]], [125202, [125236]], [125203, [125237]], [125204, [125238]], [125205, [125239]], [125206, [125240]], [125207, [125241]], [125208, [125242]], [125209, [125243]], [125210, [125244]], [125211, [125245]], [125212, [125246]], [125213, [125247]], [125214, [125248]], [125215, [125249]], [125216, [125250]], [125217, [125251]]]);
1226
+ function caseFold(input) {
1227
+ if (typeof input !== "string") {
1228
+ throw new TypeError("Input must be a string");
1229
+ }
1230
+ let result = [];
1231
+ for (const char of input) {
1232
+ const codePoint = char.codePointAt(0);
1233
+ const mapping = FOLDING_MAP.get(codePoint);
1234
+ result.push(mapping ? String.fromCodePoint(...mapping) : char);
1235
+ }
1236
+ return result.join("");
1237
+ }
1238
+
1239
+ // src/utils/canonical-path.ts
1240
+ function alternateAsciiCase(value) {
1241
+ const index = value.search(/[A-Za-z]/);
1242
+ if (index === -1) return null;
1243
+ const character = value[index];
1244
+ const alternate = character === character.toLowerCase() ? character.toUpperCase() : character.toLowerCase();
1245
+ return `${value.slice(0, index)}${alternate}${value.slice(index + 1)}`;
1246
+ }
1247
+ function probeEntryCaseSensitivity(entryPath) {
1248
+ const alternateName = alternateAsciiCase(path3.basename(entryPath));
1249
+ if (!alternateName) return void 0;
1250
+ try {
1251
+ const canonicalPath = fs.realpathSync.native(entryPath);
1252
+ const alternatePath = fs.realpathSync.native(path3.join(path3.dirname(entryPath), alternateName));
1253
+ return canonicalPath === alternatePath;
1254
+ } catch (error) {
1255
+ const code = error.code;
1256
+ if (code === "ENOENT" || code === "ENOTDIR") return false;
1257
+ return void 0;
1258
+ }
1259
+ }
1260
+ function probeEmptyWindowsDirectory(existingAncestor) {
1261
+ const probePath = path3.join(
1262
+ existingAncestor,
1263
+ `.codebase-index-case-probe-${crypto.randomBytes(8).toString("hex")}`
1264
+ );
1265
+ let created = false;
1266
+ try {
1267
+ const descriptor = fs.openSync(probePath, "wx", 384);
1268
+ created = true;
1269
+ fs.closeSync(descriptor);
1270
+ return probeEntryCaseSensitivity(probePath);
1271
+ } catch {
1272
+ return void 0;
1273
+ } finally {
1274
+ if (created) fs.unlinkSync(probePath);
1275
+ }
1276
+ }
1277
+ function detectCaseInsensitiveFileSystem(existingAncestor) {
1278
+ try {
1279
+ if (fs.statSync(existingAncestor).isDirectory()) {
1280
+ const directory = fs.opendirSync(existingAncestor);
1281
+ try {
1282
+ let entry = directory.readSync();
1283
+ while (entry) {
1284
+ if (!entry.isSymbolicLink() && alternateAsciiCase(entry.name)) {
1285
+ const result = probeEntryCaseSensitivity(path3.join(existingAncestor, entry.name));
1286
+ if (result !== void 0) return result;
1287
+ }
1288
+ entry = directory.readSync();
1289
+ }
1290
+ } finally {
1291
+ directory.closeSync();
1292
+ }
1293
+ }
1294
+ } catch {
1295
+ return void 0;
1296
+ }
1297
+ if (process.platform === "darwin") {
1298
+ return probeEntryCaseSensitivity(existingAncestor);
1299
+ }
1300
+ if (process.platform === "win32") {
1301
+ return probeEmptyWindowsDirectory(existingAncestor);
1302
+ }
1303
+ return void 0;
1304
+ }
1305
+ function foldMissingPathComponent(component) {
1306
+ return caseFold(component);
1307
+ }
1308
+ function canonicalizePathForComparison(targetPath, options = {}) {
1309
+ const resolved = path3.resolve(targetPath);
1310
+ const missingParts = [];
1311
+ let candidate = resolved;
1312
+ while (true) {
1313
+ try {
1314
+ const existingAncestor = fs.realpathSync.native(candidate);
1315
+ const isCaseInsensitive = missingParts.length > 0 ? (options.isCaseInsensitive ?? detectCaseInsensitiveFileSystem)(existingAncestor) : false;
1316
+ const suffix = isCaseInsensitive === true ? missingParts.map(foldMissingPathComponent) : missingParts;
1317
+ return path3.join(existingAncestor, ...suffix);
1318
+ } catch (error) {
1319
+ const code = error.code;
1320
+ if (code !== "ENOENT" && code !== "ENOTDIR") throw error;
1321
+ const parent = path3.dirname(candidate);
1322
+ if (parent === candidate) return resolved;
1323
+ missingParts.unshift(path3.basename(candidate));
1324
+ candidate = parent;
1325
+ }
1326
+ }
1327
+ }
1328
+
1217
1329
  // src/config/paths.ts
1218
- var OPENCODE_PROJECT_CONFIG_RELATIVE_PATH = path3.join(".opencode", "codebase-index.json");
1219
- var OPENCODE_PROJECT_INDEX_RELATIVE_PATH = path3.join(".opencode", "index");
1330
+ var OPENCODE_PROJECT_CONFIG_RELATIVE_PATH = path4.join(".opencode", "codebase-index.json");
1331
+ var OPENCODE_PROJECT_INDEX_RELATIVE_PATH = path4.join(".opencode", "index");
1220
1332
  var CODEBASE_INDEX_DIR = ".codebase-index";
1221
- var CODEBASE_PROJECT_CONFIG_RELATIVE_PATH = path3.join(CODEBASE_INDEX_DIR, "config.json");
1222
- var CODEBASE_PROJECT_INDEX_RELATIVE_PATH = path3.join(CODEBASE_INDEX_DIR, "index");
1333
+ var CODEBASE_PROJECT_CONFIG_RELATIVE_PATH = path4.join(CODEBASE_INDEX_DIR, "config.json");
1334
+ var CODEBASE_PROJECT_INDEX_RELATIVE_PATH = path4.join(CODEBASE_INDEX_DIR, "index");
1223
1335
  var CLAUDE_DIR = ".claude";
1224
- var CLAUDE_PROJECT_CONFIG_RELATIVE_PATH = path3.join(CLAUDE_DIR, "codebase-index.json");
1225
- var CLAUDE_PROJECT_INDEX_RELATIVE_PATH = path3.join(CLAUDE_DIR, "index");
1336
+ var CLAUDE_PROJECT_CONFIG_RELATIVE_PATH = path4.join(CLAUDE_DIR, "codebase-index.json");
1337
+ var CLAUDE_PROJECT_INDEX_RELATIVE_PATH = path4.join(CLAUDE_DIR, "index");
1226
1338
  function getProjectConfigRelativePath(host) {
1227
1339
  switch (host) {
1228
1340
  case "opencode":
@@ -1248,42 +1360,71 @@ function resolveWorktreeFallbackPath(projectRoot, relativePath) {
1248
1360
  if (!mainRepoRoot) {
1249
1361
  return null;
1250
1362
  }
1251
- const fallbackPath = path3.join(mainRepoRoot, relativePath);
1363
+ const fallbackPath = path4.join(mainRepoRoot, relativePath);
1252
1364
  return (0, import_fs3.existsSync)(fallbackPath) ? fallbackPath : null;
1253
1365
  }
1254
1366
  function getHostProjectConfigRelativePath(host) {
1255
1367
  return getProjectConfigRelativePath(host);
1256
1368
  }
1257
- function getHostProjectIndexRelativePath(host) {
1258
- return getProjectIndexRelativePath(host);
1369
+ function getProjectConfigCandidatePaths(projectRoot, host) {
1370
+ const candidates = [path4.join(projectRoot, getProjectConfigRelativePath(host))];
1371
+ if (host !== "opencode") {
1372
+ candidates.push(path4.join(projectRoot, OPENCODE_PROJECT_CONFIG_RELATIVE_PATH));
1373
+ }
1374
+ const mainRepoRoot = resolveWorktreeMainRepoRoot(projectRoot);
1375
+ if (mainRepoRoot) {
1376
+ candidates.push(path4.join(mainRepoRoot, getProjectConfigRelativePath(host)));
1377
+ if (host !== "opencode") {
1378
+ candidates.push(path4.join(mainRepoRoot, OPENCODE_PROJECT_CONFIG_RELATIVE_PATH));
1379
+ }
1380
+ }
1381
+ return [...new Set(candidates)];
1382
+ }
1383
+ function isProjectIndexPathOwnedByProject(projectRoot, indexPath, host) {
1384
+ const projectRoots = [projectRoot];
1385
+ const mainRepoRoot = resolveWorktreeMainRepoRoot(projectRoot);
1386
+ if (mainRepoRoot) {
1387
+ projectRoots.push(mainRepoRoot);
1388
+ }
1389
+ const ownedIndexPaths = projectRoots.flatMap((root) => {
1390
+ const indexPaths = [path4.join(root, getProjectIndexRelativePath(host))];
1391
+ if (host !== "opencode") {
1392
+ indexPaths.push(path4.join(root, OPENCODE_PROJECT_INDEX_RELATIVE_PATH));
1393
+ }
1394
+ return indexPaths;
1395
+ });
1396
+ const canonicalIndexPath = canonicalizePathForComparison(indexPath);
1397
+ return ownedIndexPaths.some(
1398
+ (ownedPath) => canonicalizePathForComparison(ownedPath) === canonicalIndexPath
1399
+ );
1259
1400
  }
1260
1401
  function hasHostProjectConfig(projectRoot, host) {
1261
- return (0, import_fs3.existsSync)(path3.join(projectRoot, getProjectConfigRelativePath(host)));
1402
+ return (0, import_fs3.existsSync)(path4.join(projectRoot, getProjectConfigRelativePath(host)));
1262
1403
  }
1263
1404
  function hasHostGlobalConfig(host) {
1264
1405
  return (0, import_fs3.existsSync)(getGlobalConfigPath(host));
1265
1406
  }
1266
- function getGlobalIndexPath(host = "opencode") {
1407
+ function getGlobalIndexPath(host) {
1267
1408
  switch (host) {
1268
1409
  case "opencode":
1269
- return path3.join(os.homedir(), ".opencode", "global-index");
1410
+ return path4.join(os.homedir(), ".opencode", "global-index");
1270
1411
  case "claude":
1271
- return path3.join(os.homedir(), ".claude", "global-index");
1412
+ return path4.join(os.homedir(), ".claude", "global-index");
1272
1413
  default:
1273
- return path3.join(os.homedir(), ".codebase-index", "global-index");
1414
+ return path4.join(os.homedir(), ".codebase-index", "global-index");
1274
1415
  }
1275
1416
  }
1276
- function getGlobalConfigPath(host = "opencode") {
1417
+ function getGlobalConfigPath(host) {
1277
1418
  switch (host) {
1278
1419
  case "opencode":
1279
- return path3.join(os.homedir(), ".config", "opencode", "codebase-index.json");
1420
+ return path4.join(os.homedir(), ".config", "opencode", "codebase-index.json");
1280
1421
  case "claude":
1281
- return path3.join(os.homedir(), ".claude", "codebase-index.json");
1422
+ return path4.join(os.homedir(), ".claude", "codebase-index.json");
1282
1423
  default:
1283
- return path3.join(os.homedir(), ".config", "codebase-index", "config.json");
1424
+ return path4.join(os.homedir(), ".config", "codebase-index", "config.json");
1284
1425
  }
1285
1426
  }
1286
- function resolveGlobalConfigPath(host = "opencode") {
1427
+ function resolveGlobalConfigPath(host) {
1287
1428
  const hostConfigPath = getGlobalConfigPath(host);
1288
1429
  if ((0, import_fs3.existsSync)(hostConfigPath)) {
1289
1430
  return hostConfigPath;
@@ -1296,7 +1437,7 @@ function resolveGlobalConfigPath(host = "opencode") {
1296
1437
  }
1297
1438
  return hostConfigPath;
1298
1439
  }
1299
- function resolveGlobalIndexPath(host = "opencode") {
1440
+ function resolveGlobalIndexPath(host) {
1300
1441
  const hostIndexPath = getGlobalIndexPath(host);
1301
1442
  if ((0, import_fs3.existsSync)(hostIndexPath)) {
1302
1443
  return hostIndexPath;
@@ -1312,42 +1453,43 @@ function resolveGlobalIndexPath(host = "opencode") {
1312
1453
  }
1313
1454
  return hostIndexPath;
1314
1455
  }
1315
- function resolveProjectConfigPath(projectRoot, host = "opencode") {
1316
- const hostConfigPath = path3.join(projectRoot, getProjectConfigRelativePath(host));
1317
- if ((0, import_fs3.existsSync)(hostConfigPath)) {
1318
- return hostConfigPath;
1319
- }
1320
- if (host !== "opencode") {
1321
- const legacyConfigPath = path3.join(projectRoot, OPENCODE_PROJECT_CONFIG_RELATIVE_PATH);
1322
- if ((0, import_fs3.existsSync)(legacyConfigPath)) {
1323
- return legacyConfigPath;
1324
- }
1325
- }
1326
- const hostFallback = resolveWorktreeFallbackPath(projectRoot, getProjectConfigRelativePath(host));
1327
- if (hostFallback) {
1328
- return hostFallback;
1329
- }
1330
- if (host !== "opencode") {
1331
- const legacyFallback = resolveWorktreeFallbackPath(projectRoot, OPENCODE_PROJECT_CONFIG_RELATIVE_PATH);
1332
- if (legacyFallback) {
1333
- return legacyFallback;
1334
- }
1335
- }
1336
- return hostConfigPath;
1456
+ function resolveProjectConfigPath(projectRoot, host) {
1457
+ const candidates = getProjectConfigCandidatePaths(projectRoot, host);
1458
+ return candidates.find((candidate) => (0, import_fs3.existsSync)(candidate)) ?? path4.join(projectRoot, getProjectConfigRelativePath(host));
1337
1459
  }
1338
- function resolveWritableProjectConfigPath(projectRoot, host = "opencode") {
1339
- return path3.join(projectRoot, getProjectConfigRelativePath(host));
1460
+ function resolveWritableProjectConfigPath(projectRoot, host) {
1461
+ return path4.join(projectRoot, getProjectConfigRelativePath(host));
1340
1462
  }
1341
- function resolveProjectIndexPath(projectRoot, scope, host = "opencode") {
1463
+ function resolveProjectIndexPath(projectRoot, scope, host) {
1342
1464
  if (scope === "global") {
1343
1465
  return resolveGlobalIndexPath(host);
1344
1466
  }
1345
- const localIndexPath = path3.join(projectRoot, getProjectIndexRelativePath(host));
1467
+ const localIndexPath = path4.join(projectRoot, getProjectIndexRelativePath(host));
1468
+ const mainRepoRoot = resolveWorktreeMainRepoRoot(projectRoot);
1469
+ if (mainRepoRoot) {
1470
+ if (hasHostProjectConfig(projectRoot, host)) {
1471
+ return localIndexPath;
1472
+ }
1473
+ if (host !== "opencode") {
1474
+ const localLegacyConfigPath = path4.join(projectRoot, OPENCODE_PROJECT_CONFIG_RELATIVE_PATH);
1475
+ if ((0, import_fs3.existsSync)(localLegacyConfigPath)) {
1476
+ return path4.join(projectRoot, OPENCODE_PROJECT_INDEX_RELATIVE_PATH);
1477
+ }
1478
+ const mainHostConfigPath = path4.join(mainRepoRoot, getProjectConfigRelativePath(host));
1479
+ const mainHostIndexPath = path4.join(mainRepoRoot, getProjectIndexRelativePath(host));
1480
+ const mainLegacyConfigPath = path4.join(mainRepoRoot, OPENCODE_PROJECT_CONFIG_RELATIVE_PATH);
1481
+ const mainLegacyIndexPath = path4.join(mainRepoRoot, OPENCODE_PROJECT_INDEX_RELATIVE_PATH);
1482
+ if (!(0, import_fs3.existsSync)(mainHostConfigPath) && !(0, import_fs3.existsSync)(mainHostIndexPath) && ((0, import_fs3.existsSync)(mainLegacyConfigPath) || (0, import_fs3.existsSync)(mainLegacyIndexPath))) {
1483
+ return mainLegacyIndexPath;
1484
+ }
1485
+ }
1486
+ return path4.join(mainRepoRoot, getProjectIndexRelativePath(host));
1487
+ }
1346
1488
  if ((0, import_fs3.existsSync)(localIndexPath)) {
1347
1489
  return localIndexPath;
1348
1490
  }
1349
1491
  if (host !== "opencode") {
1350
- const legacyIndexPath = path3.join(projectRoot, OPENCODE_PROJECT_INDEX_RELATIVE_PATH);
1492
+ const legacyIndexPath = path4.join(projectRoot, OPENCODE_PROJECT_INDEX_RELATIVE_PATH);
1351
1493
  if ((0, import_fs3.existsSync)(legacyIndexPath) && !hasHostProjectConfig(projectRoot, host)) {
1352
1494
  return legacyIndexPath;
1353
1495
  }
@@ -1355,9 +1497,6 @@ function resolveProjectIndexPath(projectRoot, scope, host = "opencode") {
1355
1497
  if (hasHostProjectConfig(projectRoot, host)) {
1356
1498
  return localIndexPath;
1357
1499
  }
1358
- if (resolveWorktreeMainRepoRoot(projectRoot)) {
1359
- return localIndexPath;
1360
- }
1361
1500
  const hostFallback = resolveWorktreeFallbackPath(projectRoot, getProjectIndexRelativePath(host));
1362
1501
  if (hostFallback) {
1363
1502
  return hostFallback;
@@ -1372,10 +1511,10 @@ function resolveProjectIndexPath(projectRoot, scope, host = "opencode") {
1372
1511
  }
1373
1512
 
1374
1513
  // src/config/rebase.ts
1375
- var path5 = __toESM(require("path"), 1);
1514
+ var path6 = __toESM(require("path"), 1);
1376
1515
 
1377
1516
  // src/utils/paths.ts
1378
- var path4 = __toESM(require("path"), 1);
1517
+ var path5 = __toESM(require("path"), 1);
1379
1518
  function normalizePathSeparators(value) {
1380
1519
  return value.replace(/\\/g, "/");
1381
1520
  }
@@ -1385,7 +1524,7 @@ function isHiddenPathSegment(part) {
1385
1524
  function isBuildPathSegment(part) {
1386
1525
  return part.toLowerCase().includes("build");
1387
1526
  }
1388
- function hasFilteredPathSegment(relativePath, separator = path4.sep) {
1527
+ function hasFilteredPathSegment(relativePath, separator = path5.sep) {
1389
1528
  return relativePath.split(separator).some(
1390
1529
  (part) => isHiddenPathSegment(part) || isBuildPathSegment(part)
1391
1530
  );
@@ -1411,7 +1550,7 @@ var RESTRICTED_DIRECTORIES = /* @__PURE__ */ new Set([
1411
1550
  "program files (x86)",
1412
1551
  "$recycle.bin"
1413
1552
  ]);
1414
- function isRestrictedDirectory(relativePath, separator = path4.sep) {
1553
+ function isRestrictedDirectory(relativePath, separator = path5.sep) {
1415
1554
  const firstSegment = relativePath.split(separator)[0];
1416
1555
  if (!firstSegment) return false;
1417
1556
  return RESTRICTED_DIRECTORIES.has(firstSegment.toLowerCase());
@@ -1419,8 +1558,8 @@ function isRestrictedDirectory(relativePath, separator = path4.sep) {
1419
1558
 
1420
1559
  // src/config/rebase.ts
1421
1560
  function isWithinRoot(rootDir, targetPath) {
1422
- const relativePath = path5.relative(rootDir, targetPath);
1423
- return relativePath === "" || !relativePath.startsWith("..") && !path5.isAbsolute(relativePath);
1561
+ const relativePath = path6.relative(rootDir, targetPath);
1562
+ return relativePath === "" || !relativePath.startsWith("..") && !path6.isAbsolute(relativePath);
1424
1563
  }
1425
1564
  function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
1426
1565
  if (!Array.isArray(values)) {
@@ -1431,17 +1570,17 @@ function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
1431
1570
  if (!trimmed) {
1432
1571
  return trimmed;
1433
1572
  }
1434
- if (path5.isAbsolute(trimmed)) {
1573
+ if (path6.isAbsolute(trimmed)) {
1435
1574
  if (isWithinRoot(sourceRoot, trimmed)) {
1436
- return normalizePathSeparators(path5.normalize(path5.relative(sourceRoot, trimmed) || "."));
1575
+ return normalizePathSeparators(path6.normalize(path6.relative(sourceRoot, trimmed) || "."));
1437
1576
  }
1438
- return path5.normalize(trimmed);
1577
+ return path6.normalize(trimmed);
1439
1578
  }
1440
- const resolvedFromSource = path5.resolve(sourceRoot, trimmed);
1579
+ const resolvedFromSource = path6.resolve(sourceRoot, trimmed);
1441
1580
  if (isWithinRoot(sourceRoot, resolvedFromSource)) {
1442
- return normalizePathSeparators(path5.normalize(trimmed));
1581
+ return normalizePathSeparators(path6.normalize(trimmed));
1443
1582
  }
1444
- return normalizePathSeparators(path5.normalize(path5.relative(targetRoot, resolvedFromSource)));
1583
+ return normalizePathSeparators(path6.normalize(path6.relative(targetRoot, resolvedFromSource)));
1445
1584
  }).filter(Boolean);
1446
1585
  }
1447
1586
 
@@ -1479,8 +1618,8 @@ function mergeUniqueStringArray(values) {
1479
1618
  return [...new Set(values.map((value) => String(value).trim()))];
1480
1619
  }
1481
1620
  function normalizeKnowledgeBasePath(value) {
1482
- let normalized = path6.normalize(String(value).trim());
1483
- const root = path6.parse(normalized).root;
1621
+ let normalized = path7.normalize(String(value).trim());
1622
+ const root = path7.parse(normalized).root;
1484
1623
  while (normalized.length > root.length && /[\\/]$/.test(normalized)) {
1485
1624
  normalized = normalized.slice(0, -1);
1486
1625
  }
@@ -1531,14 +1670,14 @@ function loadJsonFile(filePath) {
1531
1670
  function loadConfigFile(filePath) {
1532
1671
  return loadJsonFile(filePath);
1533
1672
  }
1534
- function loadProjectConfigLayer(projectRoot, host = "opencode") {
1673
+ function loadProjectConfigLayer(projectRoot, host) {
1535
1674
  const projectConfigPath = resolveProjectConfigPath(projectRoot, host);
1536
1675
  const projectConfig = loadJsonFile(projectConfigPath);
1537
1676
  if (!projectConfig) {
1538
1677
  return {};
1539
1678
  }
1540
1679
  const normalizedConfig = { ...projectConfig };
1541
- const projectConfigBaseDir = path6.dirname(path6.dirname(projectConfigPath));
1680
+ const projectConfigBaseDir = path7.dirname(path7.dirname(projectConfigPath));
1542
1681
  if (Array.isArray(normalizedConfig.knowledgeBases)) {
1543
1682
  normalizedConfig.knowledgeBases = resolveInheritedKnowledgeBaseEntries(
1544
1683
  normalizedConfig.knowledgeBases,
@@ -1548,7 +1687,7 @@ function loadProjectConfigLayer(projectRoot, host = "opencode") {
1548
1687
  }
1549
1688
  return normalizedConfig;
1550
1689
  }
1551
- function loadMergedConfig(projectRoot, host = "opencode") {
1690
+ function loadMergedConfig(projectRoot, host) {
1552
1691
  const globalConfigPath = resolveGlobalConfigPath(host);
1553
1692
  const projectConfigPath = resolveProjectConfigPath(projectRoot, host);
1554
1693
  let globalConfig = null;
@@ -1606,43 +1745,43 @@ var import_fs13 = require("fs");
1606
1745
  var path19 = __toESM(require("path"), 1);
1607
1746
 
1608
1747
  // src/tools/knowledge-base-paths.ts
1609
- var path7 = __toESM(require("path"), 1);
1748
+ var path8 = __toESM(require("path"), 1);
1610
1749
  function resolveConfigPathValue(value, baseDir) {
1611
1750
  const trimmed = value.trim();
1612
1751
  if (!trimmed) {
1613
1752
  return trimmed;
1614
1753
  }
1615
- const absolutePath = path7.isAbsolute(trimmed) ? trimmed : path7.resolve(baseDir, trimmed);
1616
- return path7.normalize(absolutePath);
1754
+ const absolutePath = path8.isAbsolute(trimmed) ? trimmed : path8.resolve(baseDir, trimmed);
1755
+ return path8.normalize(absolutePath);
1617
1756
  }
1618
1757
  function serializeConfigPathValue(value, baseDir) {
1619
1758
  const trimmed = value.trim();
1620
1759
  if (!trimmed) {
1621
1760
  return trimmed;
1622
1761
  }
1623
- if (!path7.isAbsolute(trimmed)) {
1624
- return normalizePathSeparators(path7.normalize(trimmed));
1762
+ if (!path8.isAbsolute(trimmed)) {
1763
+ return normalizePathSeparators(path8.normalize(trimmed));
1625
1764
  }
1626
- const relativePath = path7.relative(baseDir, trimmed);
1627
- if (!relativePath || !relativePath.startsWith("..") && !path7.isAbsolute(relativePath)) {
1628
- return normalizePathSeparators(path7.normalize(relativePath || "."));
1765
+ const relativePath = path8.relative(baseDir, trimmed);
1766
+ if (!relativePath || !relativePath.startsWith("..") && !path8.isAbsolute(relativePath)) {
1767
+ return normalizePathSeparators(path8.normalize(relativePath || "."));
1629
1768
  }
1630
- return path7.normalize(trimmed);
1769
+ return path8.normalize(trimmed);
1631
1770
  }
1632
1771
  function resolveKnowledgeBasePath(value, projectRoot) {
1633
- return path7.isAbsolute(value) ? value : path7.resolve(projectRoot, value);
1772
+ return path8.isAbsolute(value) ? value : path8.resolve(projectRoot, value);
1634
1773
  }
1635
1774
  function normalizeKnowledgeBasePath2(value, projectRoot) {
1636
- return path7.normalize(resolveKnowledgeBasePath(value, projectRoot));
1775
+ return path8.normalize(resolveKnowledgeBasePath(value, projectRoot));
1637
1776
  }
1638
1777
  function hasMatchingKnowledgeBasePath(knowledgeBases, inputPath, projectRoot) {
1639
- const normalizedInput = path7.normalize(inputPath);
1778
+ const normalizedInput = path8.normalize(inputPath);
1640
1779
  return knowledgeBases.some((kb) => normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput);
1641
1780
  }
1642
1781
  function findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot) {
1643
- const normalizedInput = path7.normalize(inputPath);
1782
+ const normalizedInput = path8.normalize(inputPath);
1644
1783
  return knowledgeBases.findIndex(
1645
- (kb) => path7.normalize(kb) === normalizedInput || normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput
1784
+ (kb) => path8.normalize(kb) === normalizedInput || normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput
1646
1785
  );
1647
1786
  }
1648
1787
 
@@ -2925,13 +3064,13 @@ function formatEffectivenessMetrics(snapshot) {
2925
3064
  // src/utils/auto-index.ts
2926
3065
  var import_fs7 = require("fs");
2927
3066
  var os3 = __toESM(require("os"), 1);
2928
- var path10 = __toESM(require("path"), 1);
3067
+ var path11 = __toESM(require("path"), 1);
2929
3068
 
2930
3069
  // src/indexer/index-lock.ts
2931
3070
  var import_crypto = require("crypto");
2932
3071
  var import_fs5 = require("fs");
2933
3072
  var os2 = __toESM(require("os"), 1);
2934
- var path8 = __toESM(require("path"), 1);
3073
+ var path9 = __toESM(require("path"), 1);
2935
3074
  var OWNER_FILE_NAME = "owner.json";
2936
3075
  var RECLAIM_DIRECTORY_NAME = "reclaiming";
2937
3076
  var RECOVERY_MARKER_PREFIX = "indexing.lock.recovery.";
@@ -2988,7 +3127,7 @@ function parseReclaimOwner(value) {
2988
3127
  }
2989
3128
  function readJsonDirectory(directoryPath, parser) {
2990
3129
  try {
2991
- return parser(JSON.parse((0, import_fs5.readFileSync)(path8.join(directoryPath, OWNER_FILE_NAME), "utf-8")));
3130
+ return parser(JSON.parse((0, import_fs5.readFileSync)(path9.join(directoryPath, OWNER_FILE_NAME), "utf-8")));
2992
3131
  } catch {
2993
3132
  return null;
2994
3133
  }
@@ -3045,7 +3184,7 @@ function publishJsonDirectory(finalPath, value) {
3045
3184
  throw error;
3046
3185
  }
3047
3186
  try {
3048
- (0, import_fs5.writeFileSync)(path8.join(candidatePath, OWNER_FILE_NAME), JSON.stringify(value), {
3187
+ (0, import_fs5.writeFileSync)(path9.join(candidatePath, OWNER_FILE_NAME), JSON.stringify(value), {
3049
3188
  encoding: "utf-8",
3050
3189
  flag: "wx",
3051
3190
  mode: 384
@@ -3076,7 +3215,7 @@ function createOwner(operation) {
3076
3215
  };
3077
3216
  }
3078
3217
  function recoveryMarkerPath(indexPath, owner) {
3079
- return path8.join(indexPath, `${RECOVERY_MARKER_PREFIX}${owner.token}`);
3218
+ return path9.join(indexPath, `${RECOVERY_MARKER_PREFIX}${owner.token}`);
3080
3219
  }
3081
3220
  function publishRecoveryMarker(indexPath, owner) {
3082
3221
  const markerPath = recoveryMarkerPath(indexPath, owner);
@@ -3095,7 +3234,7 @@ function getPendingRecoveries(indexPath) {
3095
3234
  return UUID_PATTERN.test(name.slice(RECOVERY_MARKER_PREFIX.length));
3096
3235
  }).sort();
3097
3236
  for (const markerName of markerNames) {
3098
- const markerPath = path8.join(indexPath, markerName);
3237
+ const markerPath = path9.join(indexPath, markerName);
3099
3238
  const markerToken = markerName.slice(RECOVERY_MARKER_PREFIX.length);
3100
3239
  let markerStats;
3101
3240
  try {
@@ -3127,11 +3266,11 @@ function cleanupDeadPublicationCandidates(indexPath) {
3127
3266
  const pid = Number(match[1]);
3128
3267
  if (!Number.isInteger(pid) || pid <= 0) continue;
3129
3268
  if (getOwnerLiveness({ pid, hostname: os2.hostname() }) !== "dead") continue;
3130
- (0, import_fs5.rmSync)(path8.join(indexPath, entry), { recursive: true, force: true });
3269
+ (0, import_fs5.rmSync)(path9.join(indexPath, entry), { recursive: true, force: true });
3131
3270
  }
3132
3271
  }
3133
3272
  function removeDeadReclaimMarker(lockPath, expectedOwner) {
3134
- const markerPath = path8.join(lockPath, RECLAIM_DIRECTORY_NAME);
3273
+ const markerPath = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
3135
3274
  const marker = readReclaimOwner(markerPath);
3136
3275
  if (!marker || marker.expectedOwnerToken !== expectedOwner.token || getOwnerLiveness(marker) !== "dead") {
3137
3276
  return false;
@@ -3159,7 +3298,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
3159
3298
  return true;
3160
3299
  }
3161
3300
  function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
3162
- const reclaimPath = path8.join(lockPath, RECLAIM_DIRECTORY_NAME);
3301
+ const reclaimPath = path9.join(lockPath, RECLAIM_DIRECTORY_NAME);
3163
3302
  const reclaimOwner = {
3164
3303
  pid: process.pid,
3165
3304
  hostname: os2.hostname(),
@@ -3217,7 +3356,7 @@ function isTransientIndexLockContention(error) {
3217
3356
  function acquireIndexLock(indexPath, operation) {
3218
3357
  (0, import_fs5.mkdirSync)(indexPath, { recursive: true });
3219
3358
  const canonicalIndexPath = import_fs5.realpathSync.native(indexPath);
3220
- const lockPath = path8.join(canonicalIndexPath, "indexing.lock");
3359
+ const lockPath = path9.join(canonicalIndexPath, "indexing.lock");
3221
3360
  cleanupDeadPublicationCandidates(canonicalIndexPath);
3222
3361
  for (let attempt = 0; attempt < 6; attempt += 1) {
3223
3362
  const owner = createOwner(operation);
@@ -3303,7 +3442,7 @@ function recoverLeaseArtifacts(indexPath, owner, backupTargets) {
3303
3442
  const temporaryOwnerMarker = `.tmp.${owner.pid}.${owner.token}.`;
3304
3443
  for (const entry of (0, import_fs5.readdirSync)(indexPath)) {
3305
3444
  if (!entry.includes(temporaryOwnerMarker)) continue;
3306
- (0, import_fs5.rmSync)(path8.join(indexPath, entry), { recursive: true, force: true });
3445
+ (0, import_fs5.rmSync)(path9.join(indexPath, entry), { recursive: true, force: true });
3307
3446
  }
3308
3447
  }
3309
3448
  function completeLeaseRecovery(lease) {
@@ -3321,7 +3460,7 @@ function completeLeaseRecovery(lease) {
3321
3460
  // src/utils/files.ts
3322
3461
  var import_ignore = __toESM(require_ignore(), 1);
3323
3462
  var import_fs6 = require("fs");
3324
- var path9 = __toESM(require("path"), 1);
3463
+ var path10 = __toESM(require("path"), 1);
3325
3464
  var PROJECT_MARKERS = [
3326
3465
  ".git",
3327
3466
  "package.json",
@@ -3339,7 +3478,7 @@ var PROJECT_MARKERS = [
3339
3478
  ];
3340
3479
  function hasProjectMarker(projectRoot) {
3341
3480
  for (const marker of PROJECT_MARKERS) {
3342
- if ((0, import_fs6.existsSync)(path9.join(projectRoot, marker))) {
3481
+ if ((0, import_fs6.existsSync)(path10.join(projectRoot, marker))) {
3343
3482
  return true;
3344
3483
  }
3345
3484
  }
@@ -3366,7 +3505,7 @@ function createIgnoreFilter(projectRoot) {
3366
3505
  "**/*build*/**"
3367
3506
  ];
3368
3507
  ig.add(defaultIgnores);
3369
- const gitignorePath = path9.join(projectRoot, ".gitignore");
3508
+ const gitignorePath = path10.join(projectRoot, ".gitignore");
3370
3509
  if ((0, import_fs6.existsSync)(gitignorePath)) {
3371
3510
  const gitignoreContent = (0, import_fs6.readFileSync)(gitignorePath, "utf-8");
3372
3511
  ig.add(gitignoreContent);
@@ -3374,8 +3513,8 @@ function createIgnoreFilter(projectRoot) {
3374
3513
  return ig;
3375
3514
  }
3376
3515
  function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
3377
- const relativePath = path9.relative(projectRoot, filePath);
3378
- if (hasFilteredPathSegment(relativePath, path9.sep)) {
3516
+ const relativePath = path10.relative(projectRoot, filePath);
3517
+ if (hasFilteredPathSegment(relativePath, path10.sep)) {
3379
3518
  return false;
3380
3519
  }
3381
3520
  if (ignoreFilter.ignores(relativePath)) {
@@ -3413,8 +3552,8 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3413
3552
  const filesInDir = [];
3414
3553
  const subdirs = [];
3415
3554
  for (const entry of entries) {
3416
- const fullPath = path9.join(dir, entry.name);
3417
- const relativePath = path9.relative(projectRoot, fullPath);
3555
+ const fullPath = path10.join(dir, entry.name);
3556
+ const relativePath = path10.relative(projectRoot, fullPath);
3418
3557
  if (isHiddenPathSegment(entry.name)) {
3419
3558
  if (entry.isDirectory()) {
3420
3559
  skipped.push({ path: relativePath, reason: "excluded" });
@@ -3463,7 +3602,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
3463
3602
  yield f;
3464
3603
  }
3465
3604
  for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
3466
- skipped.push({ path: path9.relative(projectRoot, filesInDir[i].path), reason: "excluded" });
3605
+ skipped.push({ path: path10.relative(projectRoot, filesInDir[i].path), reason: "excluded" });
3467
3606
  }
3468
3607
  const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
3469
3608
  if (canRecurse) {
@@ -3503,8 +3642,8 @@ async function collectFiles(projectRoot, includePatterns, excludePatterns, maxFi
3503
3642
  if (additionalRoots && additionalRoots.length > 0) {
3504
3643
  const normalizedRoots = /* @__PURE__ */ new Set();
3505
3644
  for (const kbRoot of additionalRoots) {
3506
- const resolved = path9.normalize(
3507
- path9.isAbsolute(kbRoot) ? kbRoot : path9.resolve(projectRoot, kbRoot)
3645
+ const resolved = path10.normalize(
3646
+ path10.isAbsolute(kbRoot) ? kbRoot : path10.resolve(projectRoot, kbRoot)
3508
3647
  );
3509
3648
  normalizedRoots.add(resolved);
3510
3649
  }
@@ -3648,7 +3787,7 @@ function now() {
3648
3787
  return (/* @__PURE__ */ new Date()).toISOString();
3649
3788
  }
3650
3789
  function canonicalizePath(targetPath) {
3651
- const resolved = path10.resolve(targetPath);
3790
+ const resolved = path11.resolve(targetPath);
3652
3791
  if ((0, import_fs7.existsSync)(resolved)) {
3653
3792
  try {
3654
3793
  return import_fs7.realpathSync.native(resolved);
@@ -3656,9 +3795,9 @@ function canonicalizePath(targetPath) {
3656
3795
  return resolved;
3657
3796
  }
3658
3797
  }
3659
- const parent = path10.dirname(resolved);
3798
+ const parent = path11.dirname(resolved);
3660
3799
  if (parent === resolved) return resolved;
3661
- return path10.join(canonicalizePath(parent), path10.basename(resolved));
3800
+ return path11.join(canonicalizePath(parent), path11.basename(resolved));
3662
3801
  }
3663
3802
  function isHomeDirectory(projectRoot) {
3664
3803
  return canonicalizePath(projectRoot) === canonicalizePath(os3.homedir());
@@ -4177,10 +4316,10 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
4177
4316
  }
4178
4317
  coordinatorKeysByProject.set(projectKey, key);
4179
4318
  }
4180
- function startAutoIndex(projectRoot, host = "opencode", source = "startup") {
4319
+ function startAutoIndex(projectRoot, host, source = "startup") {
4181
4320
  return getCoordinator(projectRoot, host)?.start(source) ?? null;
4182
4321
  }
4183
- function requestBackgroundIndex(projectRoot, host = "opencode") {
4322
+ function requestBackgroundIndex(projectRoot, host) {
4184
4323
  return getCoordinator(projectRoot, host)?.request({
4185
4324
  checkFreshness: false,
4186
4325
  force: false,
@@ -4195,14 +4334,14 @@ function runCoordinatedIndex(projectRoot, host, force, onProgress) {
4195
4334
  source: "manual"
4196
4335
  }) ?? null;
4197
4336
  }
4198
- function getAutoIndexStatus(projectRoot, host = "opencode") {
4337
+ function getAutoIndexStatus(projectRoot, host) {
4199
4338
  return getCoordinator(projectRoot, host)?.snapshot() ?? {
4200
4339
  enabled: false,
4201
4340
  state: "idle",
4202
4341
  updatedAt: now()
4203
4342
  };
4204
4343
  }
4205
- async function waitForAutoIndexForRetrieval(projectRoot, host = "opencode") {
4344
+ async function waitForAutoIndexForRetrieval(projectRoot, host) {
4206
4345
  const coordinator = getCoordinator(projectRoot, host);
4207
4346
  if (!coordinator) return { ready: true };
4208
4347
  const initial = coordinator.snapshot();
@@ -4260,7 +4399,7 @@ async function hasReadableCurrentIndex(coordinator) {
4260
4399
 
4261
4400
  // src/tools/config-state.ts
4262
4401
  var import_fs8 = require("fs");
4263
- var path11 = __toESM(require("path"), 1);
4402
+ var path12 = __toESM(require("path"), 1);
4264
4403
  function normalizeKnowledgeBasePaths(config, projectRoot) {
4265
4404
  const normalized = { ...config };
4266
4405
  if (Array.isArray(normalized.knowledgeBases)) {
@@ -4276,19 +4415,19 @@ function toConfigRecord(rawConfig) {
4276
4415
  }
4277
4416
  return { ...rawConfig };
4278
4417
  }
4279
- function getConfigPath(projectRoot, host = "opencode") {
4418
+ function getConfigPath(projectRoot, host) {
4280
4419
  return resolveWritableProjectConfigPath(projectRoot, host);
4281
4420
  }
4282
- function loadRuntimeConfig(projectRoot, host = "opencode") {
4421
+ function loadRuntimeConfig(projectRoot, host) {
4283
4422
  return normalizeKnowledgeBasePaths(toConfigRecord(loadMergedConfig(projectRoot, host)), projectRoot);
4284
4423
  }
4285
- function loadEditableConfig(projectRoot, host = "opencode") {
4424
+ function loadEditableConfig(projectRoot, host) {
4286
4425
  return normalizeKnowledgeBasePaths(toConfigRecord(loadProjectConfigLayer(projectRoot, host)), projectRoot);
4287
4426
  }
4288
- function saveConfig(projectRoot, config, host = "opencode") {
4427
+ function saveConfig(projectRoot, config, host) {
4289
4428
  const configPath = getConfigPath(projectRoot, host);
4290
- const configDir = path11.dirname(configPath);
4291
- const configBaseDir = path11.dirname(configDir);
4429
+ const configDir = path12.dirname(configPath);
4430
+ const configBaseDir = path12.dirname(configDir);
4292
4431
  if (!(0, import_fs8.existsSync)(configDir)) {
4293
4432
  (0, import_fs8.mkdirSync)(configDir, { recursive: true });
4294
4433
  }
@@ -5354,10 +5493,10 @@ async function pRetry(input, options = {}) {
5354
5493
 
5355
5494
  // src/embeddings/detector.ts
5356
5495
  var import_fs9 = require("fs");
5357
- var path12 = __toESM(require("path"), 1);
5496
+ var path13 = __toESM(require("path"), 1);
5358
5497
  var os4 = __toESM(require("os"), 1);
5359
5498
  function getOpenCodeAuthPath() {
5360
- return path12.join(os4.homedir(), ".local", "share", "opencode", "auth.json");
5499
+ return path13.join(os4.homedir(), ".local", "share", "opencode", "auth.json");
5361
5500
  }
5362
5501
  function loadOpenCodeAuth() {
5363
5502
  const authPath = getOpenCodeAuthPath();
@@ -6764,43 +6903,81 @@ function extractParamNames(params) {
6764
6903
 
6765
6904
  // src/native/binding.ts
6766
6905
  var os5 = __toESM(require("os"), 1);
6767
- var path13 = __toESM(require("path"), 1);
6906
+ var path14 = __toESM(require("path"), 1);
6768
6907
  var module2 = __toESM(require("module"), 1);
6769
6908
  var import_node_url = require("url");
6909
+
6910
+ // src/identity-catalog.json
6911
+ var identity_catalog_default = {
6912
+ product: {
6913
+ current: {
6914
+ productName: "opencode-codebase-index",
6915
+ packageName: "opencode-codebase-index",
6916
+ repository: "https://github.com/Helweg/opencode-codebase-index",
6917
+ mcpBinary: "opencode-codebase-index-mcp",
6918
+ mcpServerName: "opencode-codebase-index"
6919
+ },
6920
+ future: {
6921
+ productName: "open-codebase-index",
6922
+ packageName: "open-codebase-index",
6923
+ repository: "https://github.com/Helweg/open-codebase-index",
6924
+ mcpBinary: "open-codebase-index-mcp",
6925
+ mcpServerName: "open-codebase-index"
6926
+ }
6927
+ },
6928
+ native: {
6929
+ binaryName: "codebase-index-native"
6930
+ }
6931
+ };
6932
+
6933
+ // src/identity-catalog.ts
6934
+ var IDENTITY_CATALOG = identity_catalog_default;
6935
+ var CURRENT_PRODUCT = IDENTITY_CATALOG.product.current;
6936
+ var FUTURE_PRODUCT = IDENTITY_CATALOG.product.future;
6937
+ var MCP_SERVER_CURRENT_NAME = CURRENT_PRODUCT.mcpServerName;
6938
+ var MCP_BINARY_CURRENT_NAME = CURRENT_PRODUCT.mcpBinary;
6939
+ var STABLE_NATIVE_BINARY_NAME = IDENTITY_CATALOG.native.binaryName;
6940
+
6941
+ // src/native/binding.ts
6770
6942
  var import_meta = {};
6771
- function getNativeBinding() {
6772
- const platform2 = os5.platform();
6773
- const arch2 = os5.arch();
6774
- let bindingName;
6943
+ function getNativeBindingFilename(platform2 = os5.platform(), arch2 = os5.arch()) {
6775
6944
  if (platform2 === "darwin" && arch2 === "arm64") {
6776
- bindingName = "codebase-index-native.darwin-arm64.node";
6777
- } else if (platform2 === "darwin" && arch2 === "x64") {
6778
- bindingName = "codebase-index-native.darwin-x64.node";
6779
- } else if (platform2 === "linux" && arch2 === "x64") {
6780
- bindingName = "codebase-index-native.linux-x64-gnu.node";
6781
- } else if (platform2 === "linux" && arch2 === "arm64") {
6782
- bindingName = "codebase-index-native.linux-arm64-gnu.node";
6783
- } else if (platform2 === "win32" && arch2 === "x64") {
6784
- bindingName = "codebase-index-native.win32-x64-msvc.node";
6785
- } else {
6786
- throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
6945
+ return `${STABLE_NATIVE_BINARY_NAME}.darwin-arm64.node`;
6946
+ }
6947
+ if (platform2 === "darwin" && arch2 === "x64") {
6948
+ return `${STABLE_NATIVE_BINARY_NAME}.darwin-x64.node`;
6787
6949
  }
6950
+ if (platform2 === "linux" && arch2 === "x64") {
6951
+ return `${STABLE_NATIVE_BINARY_NAME}.linux-x64-gnu.node`;
6952
+ }
6953
+ if (platform2 === "linux" && arch2 === "arm64") {
6954
+ return `${STABLE_NATIVE_BINARY_NAME}.linux-arm64-gnu.node`;
6955
+ }
6956
+ if (platform2 === "win32" && arch2 === "x64") {
6957
+ return `${STABLE_NATIVE_BINARY_NAME}.win32-x64-msvc.node`;
6958
+ }
6959
+ throw new Error(`Unsupported platform: ${platform2}-${arch2}`);
6960
+ }
6961
+ function resolveNativeBindingPath(packageRoot, platform2 = os5.platform(), arch2 = os5.arch()) {
6962
+ return path14.join(packageRoot, "native", getNativeBindingFilename(platform2, arch2));
6963
+ }
6964
+ function getNativeBinding() {
6788
6965
  let currentDir;
6789
6966
  let requireTarget;
6790
6967
  if (typeof import_meta !== "undefined" && import_meta.url) {
6791
- currentDir = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
6968
+ currentDir = path14.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
6792
6969
  requireTarget = import_meta.url;
6793
6970
  } else if (typeof __dirname !== "undefined") {
6794
6971
  currentDir = __dirname;
6795
6972
  requireTarget = __filename;
6796
6973
  } else {
6797
6974
  currentDir = process.cwd();
6798
- requireTarget = path13.join(currentDir, "index.js");
6975
+ requireTarget = path14.join(currentDir, "index.js");
6799
6976
  }
6800
6977
  const normalizedDir = currentDir.replace(/\\/g, "/");
6801
- const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path13.join("src", "native"));
6802
- const packageRoot = isDevMode ? path13.resolve(currentDir, "../..") : path13.resolve(currentDir, "..");
6803
- const nativePath = path13.join(packageRoot, "native", bindingName);
6978
+ const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path14.join("src", "native"));
6979
+ const packageRoot = isDevMode ? path14.resolve(currentDir, "../..") : path14.resolve(currentDir, "..");
6980
+ const nativePath = resolveNativeBindingPath(packageRoot);
6804
6981
  const require2 = module2.createRequire(requireTarget);
6805
6982
  return require2(nativePath);
6806
6983
  }
@@ -7360,116 +7537,6 @@ var import_fs10 = require("fs");
7360
7537
  var os6 = __toESM(require("os"), 1);
7361
7538
  var path15 = __toESM(require("path"), 1);
7362
7539
 
7363
- // src/utils/canonical-path.ts
7364
- var crypto = __toESM(require("crypto"), 1);
7365
- var fs = __toESM(require("fs"), 1);
7366
- var path14 = __toESM(require("path"), 1);
7367
-
7368
- // node_modules/unicode-case-folding/index.js
7369
- var FOLDING_MAP = /* @__PURE__ */ new Map([[65, [97]], [66, [98]], [67, [99]], [68, [100]], [69, [101]], [70, [102]], [71, [103]], [72, [104]], [73, [105]], [74, [106]], [75, [107]], [76, [108]], [77, [109]], [78, [110]], [79, [111]], [80, [112]], [81, [113]], [82, [114]], [83, [115]], [84, [116]], [85, [117]], [86, [118]], [87, [119]], [88, [120]], [89, [121]], [90, [122]], [181, [956]], [192, [224]], [193, [225]], [194, [226]], [195, [227]], [196, [228]], [197, [229]], [198, [230]], [199, [231]], [200, [232]], [201, [233]], [202, [234]], [203, [235]], [204, [236]], [205, [237]], [206, [238]], [207, [239]], [208, [240]], [209, [241]], [210, [242]], [211, [243]], [212, [244]], [213, [245]], [214, [246]], [216, [248]], [217, [249]], [218, [250]], [219, [251]], [220, [252]], [221, [253]], [222, [254]], [223, [115, 115]], [256, [257]], [258, [259]], [260, [261]], [262, [263]], [264, [265]], [266, [267]], [268, [269]], [270, [271]], [272, [273]], [274, [275]], [276, [277]], [278, [279]], [280, [281]], [282, [283]], [284, [285]], [286, [287]], [288, [289]], [290, [291]], [292, [293]], [294, [295]], [296, [297]], [298, [299]], [300, [301]], [302, [303]], [304, [105, 775]], [306, [307]], [308, [309]], [310, [311]], [313, [314]], [315, [316]], [317, [318]], [319, [320]], [321, [322]], [323, [324]], [325, [326]], [327, [328]], [329, [700, 110]], [330, [331]], [332, [333]], [334, [335]], [336, [337]], [338, [339]], [340, [341]], [342, [343]], [344, [345]], [346, [347]], [348, [349]], [350, [351]], [352, [353]], [354, [355]], [356, [357]], [358, [359]], [360, [361]], [362, [363]], [364, [365]], [366, [367]], [368, [369]], [370, [371]], [372, [373]], [374, [375]], [376, [255]], [377, [378]], [379, [380]], [381, [382]], [383, [115]], [385, [595]], [386, [387]], [388, [389]], [390, [596]], [391, [392]], [393, [598]], [394, [599]], [395, [396]], [398, [477]], [399, [601]], [400, [603]], [401, [402]], [403, [608]], [404, [611]], [406, [617]], [407, [616]], [408, [409]], [412, [623]], [413, [626]], [415, [629]], [416, [417]], [418, [419]], [420, [421]], [422, [640]], [423, [424]], [425, [643]], [428, [429]], [430, [648]], [431, [432]], [433, [650]], [434, [651]], [435, [436]], [437, [438]], [439, [658]], [440, [441]], [444, [445]], [452, [454]], [453, [454]], [455, [457]], [456, [457]], [458, [460]], [459, [460]], [461, [462]], [463, [464]], [465, [466]], [467, [468]], [469, [470]], [471, [472]], [473, [474]], [475, [476]], [478, [479]], [480, [481]], [482, [483]], [484, [485]], [486, [487]], [488, [489]], [490, [491]], [492, [493]], [494, [495]], [496, [106, 780]], [497, [499]], [498, [499]], [500, [501]], [502, [405]], [503, [447]], [504, [505]], [506, [507]], [508, [509]], [510, [511]], [512, [513]], [514, [515]], [516, [517]], [518, [519]], [520, [521]], [522, [523]], [524, [525]], [526, [527]], [528, [529]], [530, [531]], [532, [533]], [534, [535]], [536, [537]], [538, [539]], [540, [541]], [542, [543]], [544, [414]], [546, [547]], [548, [549]], [550, [551]], [552, [553]], [554, [555]], [556, [557]], [558, [559]], [560, [561]], [562, [563]], [570, [11365]], [571, [572]], [573, [410]], [574, [11366]], [577, [578]], [579, [384]], [580, [649]], [581, [652]], [582, [583]], [584, [585]], [586, [587]], [588, [589]], [590, [591]], [837, [953]], [880, [881]], [882, [883]], [886, [887]], [895, [1011]], [902, [940]], [904, [941]], [905, [942]], [906, [943]], [908, [972]], [910, [973]], [911, [974]], [912, [953, 776, 769]], [913, [945]], [914, [946]], [915, [947]], [916, [948]], [917, [949]], [918, [950]], [919, [951]], [920, [952]], [921, [953]], [922, [954]], [923, [955]], [924, [956]], [925, [957]], [926, [958]], [927, [959]], [928, [960]], [929, [961]], [931, [963]], [932, [964]], [933, [965]], [934, [966]], [935, [967]], [936, [968]], [937, [969]], [938, [970]], [939, [971]], [944, [965, 776, 769]], [962, [963]], [975, [983]], [976, [946]], [977, [952]], [981, [966]], [982, [960]], [984, [985]], [986, [987]], [988, [989]], [990, [991]], [992, [993]], [994, [995]], [996, [997]], [998, [999]], [1e3, [1001]], [1002, [1003]], [1004, [1005]], [1006, [1007]], [1008, [954]], [1009, [961]], [1012, [952]], [1013, [949]], [1015, [1016]], [1017, [1010]], [1018, [1019]], [1021, [891]], [1022, [892]], [1023, [893]], [1024, [1104]], [1025, [1105]], [1026, [1106]], [1027, [1107]], [1028, [1108]], [1029, [1109]], [1030, [1110]], [1031, [1111]], [1032, [1112]], [1033, [1113]], [1034, [1114]], [1035, [1115]], [1036, [1116]], [1037, [1117]], [1038, [1118]], [1039, [1119]], [1040, [1072]], [1041, [1073]], [1042, [1074]], [1043, [1075]], [1044, [1076]], [1045, [1077]], [1046, [1078]], [1047, [1079]], [1048, [1080]], [1049, [1081]], [1050, [1082]], [1051, [1083]], [1052, [1084]], [1053, [1085]], [1054, [1086]], [1055, [1087]], [1056, [1088]], [1057, [1089]], [1058, [1090]], [1059, [1091]], [1060, [1092]], [1061, [1093]], [1062, [1094]], [1063, [1095]], [1064, [1096]], [1065, [1097]], [1066, [1098]], [1067, [1099]], [1068, [1100]], [1069, [1101]], [1070, [1102]], [1071, [1103]], [1120, [1121]], [1122, [1123]], [1124, [1125]], [1126, [1127]], [1128, [1129]], [1130, [1131]], [1132, [1133]], [1134, [1135]], [1136, [1137]], [1138, [1139]], [1140, [1141]], [1142, [1143]], [1144, [1145]], [1146, [1147]], [1148, [1149]], [1150, [1151]], [1152, [1153]], [1162, [1163]], [1164, [1165]], [1166, [1167]], [1168, [1169]], [1170, [1171]], [1172, [1173]], [1174, [1175]], [1176, [1177]], [1178, [1179]], [1180, [1181]], [1182, [1183]], [1184, [1185]], [1186, [1187]], [1188, [1189]], [1190, [1191]], [1192, [1193]], [1194, [1195]], [1196, [1197]], [1198, [1199]], [1200, [1201]], [1202, [1203]], [1204, [1205]], [1206, [1207]], [1208, [1209]], [1210, [1211]], [1212, [1213]], [1214, [1215]], [1216, [1231]], [1217, [1218]], [1219, [1220]], [1221, [1222]], [1223, [1224]], [1225, [1226]], [1227, [1228]], [1229, [1230]], [1232, [1233]], [1234, [1235]], [1236, [1237]], [1238, [1239]], [1240, [1241]], [1242, [1243]], [1244, [1245]], [1246, [1247]], [1248, [1249]], [1250, [1251]], [1252, [1253]], [1254, [1255]], [1256, [1257]], [1258, [1259]], [1260, [1261]], [1262, [1263]], [1264, [1265]], [1266, [1267]], [1268, [1269]], [1270, [1271]], [1272, [1273]], [1274, [1275]], [1276, [1277]], [1278, [1279]], [1280, [1281]], [1282, [1283]], [1284, [1285]], [1286, [1287]], [1288, [1289]], [1290, [1291]], [1292, [1293]], [1294, [1295]], [1296, [1297]], [1298, [1299]], [1300, [1301]], [1302, [1303]], [1304, [1305]], [1306, [1307]], [1308, [1309]], [1310, [1311]], [1312, [1313]], [1314, [1315]], [1316, [1317]], [1318, [1319]], [1320, [1321]], [1322, [1323]], [1324, [1325]], [1326, [1327]], [1329, [1377]], [1330, [1378]], [1331, [1379]], [1332, [1380]], [1333, [1381]], [1334, [1382]], [1335, [1383]], [1336, [1384]], [1337, [1385]], [1338, [1386]], [1339, [1387]], [1340, [1388]], [1341, [1389]], [1342, [1390]], [1343, [1391]], [1344, [1392]], [1345, [1393]], [1346, [1394]], [1347, [1395]], [1348, [1396]], [1349, [1397]], [1350, [1398]], [1351, [1399]], [1352, [1400]], [1353, [1401]], [1354, [1402]], [1355, [1403]], [1356, [1404]], [1357, [1405]], [1358, [1406]], [1359, [1407]], [1360, [1408]], [1361, [1409]], [1362, [1410]], [1363, [1411]], [1364, [1412]], [1365, [1413]], [1366, [1414]], [1415, [1381, 1410]], [4256, [11520]], [4257, [11521]], [4258, [11522]], [4259, [11523]], [4260, [11524]], [4261, [11525]], [4262, [11526]], [4263, [11527]], [4264, [11528]], [4265, [11529]], [4266, [11530]], [4267, [11531]], [4268, [11532]], [4269, [11533]], [4270, [11534]], [4271, [11535]], [4272, [11536]], [4273, [11537]], [4274, [11538]], [4275, [11539]], [4276, [11540]], [4277, [11541]], [4278, [11542]], [4279, [11543]], [4280, [11544]], [4281, [11545]], [4282, [11546]], [4283, [11547]], [4284, [11548]], [4285, [11549]], [4286, [11550]], [4287, [11551]], [4288, [11552]], [4289, [11553]], [4290, [11554]], [4291, [11555]], [4292, [11556]], [4293, [11557]], [4295, [11559]], [4301, [11565]], [5112, [5104]], [5113, [5105]], [5114, [5106]], [5115, [5107]], [5116, [5108]], [5117, [5109]], [7296, [1074]], [7297, [1076]], [7298, [1086]], [7299, [1089]], [7300, [1090]], [7301, [1090]], [7302, [1098]], [7303, [1123]], [7304, [42571]], [7305, [7306]], [7312, [4304]], [7313, [4305]], [7314, [4306]], [7315, [4307]], [7316, [4308]], [7317, [4309]], [7318, [4310]], [7319, [4311]], [7320, [4312]], [7321, [4313]], [7322, [4314]], [7323, [4315]], [7324, [4316]], [7325, [4317]], [7326, [4318]], [7327, [4319]], [7328, [4320]], [7329, [4321]], [7330, [4322]], [7331, [4323]], [7332, [4324]], [7333, [4325]], [7334, [4326]], [7335, [4327]], [7336, [4328]], [7337, [4329]], [7338, [4330]], [7339, [4331]], [7340, [4332]], [7341, [4333]], [7342, [4334]], [7343, [4335]], [7344, [4336]], [7345, [4337]], [7346, [4338]], [7347, [4339]], [7348, [4340]], [7349, [4341]], [7350, [4342]], [7351, [4343]], [7352, [4344]], [7353, [4345]], [7354, [4346]], [7357, [4349]], [7358, [4350]], [7359, [4351]], [7680, [7681]], [7682, [7683]], [7684, [7685]], [7686, [7687]], [7688, [7689]], [7690, [7691]], [7692, [7693]], [7694, [7695]], [7696, [7697]], [7698, [7699]], [7700, [7701]], [7702, [7703]], [7704, [7705]], [7706, [7707]], [7708, [7709]], [7710, [7711]], [7712, [7713]], [7714, [7715]], [7716, [7717]], [7718, [7719]], [7720, [7721]], [7722, [7723]], [7724, [7725]], [7726, [7727]], [7728, [7729]], [7730, [7731]], [7732, [7733]], [7734, [7735]], [7736, [7737]], [7738, [7739]], [7740, [7741]], [7742, [7743]], [7744, [7745]], [7746, [7747]], [7748, [7749]], [7750, [7751]], [7752, [7753]], [7754, [7755]], [7756, [7757]], [7758, [7759]], [7760, [7761]], [7762, [7763]], [7764, [7765]], [7766, [7767]], [7768, [7769]], [7770, [7771]], [7772, [7773]], [7774, [7775]], [7776, [7777]], [7778, [7779]], [7780, [7781]], [7782, [7783]], [7784, [7785]], [7786, [7787]], [7788, [7789]], [7790, [7791]], [7792, [7793]], [7794, [7795]], [7796, [7797]], [7798, [7799]], [7800, [7801]], [7802, [7803]], [7804, [7805]], [7806, [7807]], [7808, [7809]], [7810, [7811]], [7812, [7813]], [7814, [7815]], [7816, [7817]], [7818, [7819]], [7820, [7821]], [7822, [7823]], [7824, [7825]], [7826, [7827]], [7828, [7829]], [7830, [104, 817]], [7831, [116, 776]], [7832, [119, 778]], [7833, [121, 778]], [7834, [97, 702]], [7835, [7777]], [7838, [115, 115]], [7840, [7841]], [7842, [7843]], [7844, [7845]], [7846, [7847]], [7848, [7849]], [7850, [7851]], [7852, [7853]], [7854, [7855]], [7856, [7857]], [7858, [7859]], [7860, [7861]], [7862, [7863]], [7864, [7865]], [7866, [7867]], [7868, [7869]], [7870, [7871]], [7872, [7873]], [7874, [7875]], [7876, [7877]], [7878, [7879]], [7880, [7881]], [7882, [7883]], [7884, [7885]], [7886, [7887]], [7888, [7889]], [7890, [7891]], [7892, [7893]], [7894, [7895]], [7896, [7897]], [7898, [7899]], [7900, [7901]], [7902, [7903]], [7904, [7905]], [7906, [7907]], [7908, [7909]], [7910, [7911]], [7912, [7913]], [7914, [7915]], [7916, [7917]], [7918, [7919]], [7920, [7921]], [7922, [7923]], [7924, [7925]], [7926, [7927]], [7928, [7929]], [7930, [7931]], [7932, [7933]], [7934, [7935]], [7944, [7936]], [7945, [7937]], [7946, [7938]], [7947, [7939]], [7948, [7940]], [7949, [7941]], [7950, [7942]], [7951, [7943]], [7960, [7952]], [7961, [7953]], [7962, [7954]], [7963, [7955]], [7964, [7956]], [7965, [7957]], [7976, [7968]], [7977, [7969]], [7978, [7970]], [7979, [7971]], [7980, [7972]], [7981, [7973]], [7982, [7974]], [7983, [7975]], [7992, [7984]], [7993, [7985]], [7994, [7986]], [7995, [7987]], [7996, [7988]], [7997, [7989]], [7998, [7990]], [7999, [7991]], [8008, [8e3]], [8009, [8001]], [8010, [8002]], [8011, [8003]], [8012, [8004]], [8013, [8005]], [8016, [965, 787]], [8018, [965, 787, 768]], [8020, [965, 787, 769]], [8022, [965, 787, 834]], [8025, [8017]], [8027, [8019]], [8029, [8021]], [8031, [8023]], [8040, [8032]], [8041, [8033]], [8042, [8034]], [8043, [8035]], [8044, [8036]], [8045, [8037]], [8046, [8038]], [8047, [8039]], [8064, [7936, 953]], [8065, [7937, 953]], [8066, [7938, 953]], [8067, [7939, 953]], [8068, [7940, 953]], [8069, [7941, 953]], [8070, [7942, 953]], [8071, [7943, 953]], [8072, [7936, 953]], [8073, [7937, 953]], [8074, [7938, 953]], [8075, [7939, 953]], [8076, [7940, 953]], [8077, [7941, 953]], [8078, [7942, 953]], [8079, [7943, 953]], [8080, [7968, 953]], [8081, [7969, 953]], [8082, [7970, 953]], [8083, [7971, 953]], [8084, [7972, 953]], [8085, [7973, 953]], [8086, [7974, 953]], [8087, [7975, 953]], [8088, [7968, 953]], [8089, [7969, 953]], [8090, [7970, 953]], [8091, [7971, 953]], [8092, [7972, 953]], [8093, [7973, 953]], [8094, [7974, 953]], [8095, [7975, 953]], [8096, [8032, 953]], [8097, [8033, 953]], [8098, [8034, 953]], [8099, [8035, 953]], [8100, [8036, 953]], [8101, [8037, 953]], [8102, [8038, 953]], [8103, [8039, 953]], [8104, [8032, 953]], [8105, [8033, 953]], [8106, [8034, 953]], [8107, [8035, 953]], [8108, [8036, 953]], [8109, [8037, 953]], [8110, [8038, 953]], [8111, [8039, 953]], [8114, [8048, 953]], [8115, [945, 953]], [8116, [940, 953]], [8118, [945, 834]], [8119, [945, 834, 953]], [8120, [8112]], [8121, [8113]], [8122, [8048]], [8123, [8049]], [8124, [945, 953]], [8126, [953]], [8130, [8052, 953]], [8131, [951, 953]], [8132, [942, 953]], [8134, [951, 834]], [8135, [951, 834, 953]], [8136, [8050]], [8137, [8051]], [8138, [8052]], [8139, [8053]], [8140, [951, 953]], [8146, [953, 776, 768]], [8147, [953, 776, 769]], [8150, [953, 834]], [8151, [953, 776, 834]], [8152, [8144]], [8153, [8145]], [8154, [8054]], [8155, [8055]], [8162, [965, 776, 768]], [8163, [965, 776, 769]], [8164, [961, 787]], [8166, [965, 834]], [8167, [965, 776, 834]], [8168, [8160]], [8169, [8161]], [8170, [8058]], [8171, [8059]], [8172, [8165]], [8178, [8060, 953]], [8179, [969, 953]], [8180, [974, 953]], [8182, [969, 834]], [8183, [969, 834, 953]], [8184, [8056]], [8185, [8057]], [8186, [8060]], [8187, [8061]], [8188, [969, 953]], [8486, [969]], [8490, [107]], [8491, [229]], [8498, [8526]], [8544, [8560]], [8545, [8561]], [8546, [8562]], [8547, [8563]], [8548, [8564]], [8549, [8565]], [8550, [8566]], [8551, [8567]], [8552, [8568]], [8553, [8569]], [8554, [8570]], [8555, [8571]], [8556, [8572]], [8557, [8573]], [8558, [8574]], [8559, [8575]], [8579, [8580]], [9398, [9424]], [9399, [9425]], [9400, [9426]], [9401, [9427]], [9402, [9428]], [9403, [9429]], [9404, [9430]], [9405, [9431]], [9406, [9432]], [9407, [9433]], [9408, [9434]], [9409, [9435]], [9410, [9436]], [9411, [9437]], [9412, [9438]], [9413, [9439]], [9414, [9440]], [9415, [9441]], [9416, [9442]], [9417, [9443]], [9418, [9444]], [9419, [9445]], [9420, [9446]], [9421, [9447]], [9422, [9448]], [9423, [9449]], [11264, [11312]], [11265, [11313]], [11266, [11314]], [11267, [11315]], [11268, [11316]], [11269, [11317]], [11270, [11318]], [11271, [11319]], [11272, [11320]], [11273, [11321]], [11274, [11322]], [11275, [11323]], [11276, [11324]], [11277, [11325]], [11278, [11326]], [11279, [11327]], [11280, [11328]], [11281, [11329]], [11282, [11330]], [11283, [11331]], [11284, [11332]], [11285, [11333]], [11286, [11334]], [11287, [11335]], [11288, [11336]], [11289, [11337]], [11290, [11338]], [11291, [11339]], [11292, [11340]], [11293, [11341]], [11294, [11342]], [11295, [11343]], [11296, [11344]], [11297, [11345]], [11298, [11346]], [11299, [11347]], [11300, [11348]], [11301, [11349]], [11302, [11350]], [11303, [11351]], [11304, [11352]], [11305, [11353]], [11306, [11354]], [11307, [11355]], [11308, [11356]], [11309, [11357]], [11310, [11358]], [11311, [11359]], [11360, [11361]], [11362, [619]], [11363, [7549]], [11364, [637]], [11367, [11368]], [11369, [11370]], [11371, [11372]], [11373, [593]], [11374, [625]], [11375, [592]], [11376, [594]], [11378, [11379]], [11381, [11382]], [11390, [575]], [11391, [576]], [11392, [11393]], [11394, [11395]], [11396, [11397]], [11398, [11399]], [11400, [11401]], [11402, [11403]], [11404, [11405]], [11406, [11407]], [11408, [11409]], [11410, [11411]], [11412, [11413]], [11414, [11415]], [11416, [11417]], [11418, [11419]], [11420, [11421]], [11422, [11423]], [11424, [11425]], [11426, [11427]], [11428, [11429]], [11430, [11431]], [11432, [11433]], [11434, [11435]], [11436, [11437]], [11438, [11439]], [11440, [11441]], [11442, [11443]], [11444, [11445]], [11446, [11447]], [11448, [11449]], [11450, [11451]], [11452, [11453]], [11454, [11455]], [11456, [11457]], [11458, [11459]], [11460, [11461]], [11462, [11463]], [11464, [11465]], [11466, [11467]], [11468, [11469]], [11470, [11471]], [11472, [11473]], [11474, [11475]], [11476, [11477]], [11478, [11479]], [11480, [11481]], [11482, [11483]], [11484, [11485]], [11486, [11487]], [11488, [11489]], [11490, [11491]], [11499, [11500]], [11501, [11502]], [11506, [11507]], [42560, [42561]], [42562, [42563]], [42564, [42565]], [42566, [42567]], [42568, [42569]], [42570, [42571]], [42572, [42573]], [42574, [42575]], [42576, [42577]], [42578, [42579]], [42580, [42581]], [42582, [42583]], [42584, [42585]], [42586, [42587]], [42588, [42589]], [42590, [42591]], [42592, [42593]], [42594, [42595]], [42596, [42597]], [42598, [42599]], [42600, [42601]], [42602, [42603]], [42604, [42605]], [42624, [42625]], [42626, [42627]], [42628, [42629]], [42630, [42631]], [42632, [42633]], [42634, [42635]], [42636, [42637]], [42638, [42639]], [42640, [42641]], [42642, [42643]], [42644, [42645]], [42646, [42647]], [42648, [42649]], [42650, [42651]], [42786, [42787]], [42788, [42789]], [42790, [42791]], [42792, [42793]], [42794, [42795]], [42796, [42797]], [42798, [42799]], [42802, [42803]], [42804, [42805]], [42806, [42807]], [42808, [42809]], [42810, [42811]], [42812, [42813]], [42814, [42815]], [42816, [42817]], [42818, [42819]], [42820, [42821]], [42822, [42823]], [42824, [42825]], [42826, [42827]], [42828, [42829]], [42830, [42831]], [42832, [42833]], [42834, [42835]], [42836, [42837]], [42838, [42839]], [42840, [42841]], [42842, [42843]], [42844, [42845]], [42846, [42847]], [42848, [42849]], [42850, [42851]], [42852, [42853]], [42854, [42855]], [42856, [42857]], [42858, [42859]], [42860, [42861]], [42862, [42863]], [42873, [42874]], [42875, [42876]], [42877, [7545]], [42878, [42879]], [42880, [42881]], [42882, [42883]], [42884, [42885]], [42886, [42887]], [42891, [42892]], [42893, [613]], [42896, [42897]], [42898, [42899]], [42902, [42903]], [42904, [42905]], [42906, [42907]], [42908, [42909]], [42910, [42911]], [42912, [42913]], [42914, [42915]], [42916, [42917]], [42918, [42919]], [42920, [42921]], [42922, [614]], [42923, [604]], [42924, [609]], [42925, [620]], [42926, [618]], [42928, [670]], [42929, [647]], [42930, [669]], [42931, [43859]], [42932, [42933]], [42934, [42935]], [42936, [42937]], [42938, [42939]], [42940, [42941]], [42942, [42943]], [42944, [42945]], [42946, [42947]], [42948, [42900]], [42949, [642]], [42950, [7566]], [42951, [42952]], [42953, [42954]], [42955, [612]], [42956, [42957]], [42958, [42959]], [42960, [42961]], [42962, [42963]], [42964, [42965]], [42966, [42967]], [42968, [42969]], [42970, [42971]], [42972, [411]], [42997, [42998]], [43888, [5024]], [43889, [5025]], [43890, [5026]], [43891, [5027]], [43892, [5028]], [43893, [5029]], [43894, [5030]], [43895, [5031]], [43896, [5032]], [43897, [5033]], [43898, [5034]], [43899, [5035]], [43900, [5036]], [43901, [5037]], [43902, [5038]], [43903, [5039]], [43904, [5040]], [43905, [5041]], [43906, [5042]], [43907, [5043]], [43908, [5044]], [43909, [5045]], [43910, [5046]], [43911, [5047]], [43912, [5048]], [43913, [5049]], [43914, [5050]], [43915, [5051]], [43916, [5052]], [43917, [5053]], [43918, [5054]], [43919, [5055]], [43920, [5056]], [43921, [5057]], [43922, [5058]], [43923, [5059]], [43924, [5060]], [43925, [5061]], [43926, [5062]], [43927, [5063]], [43928, [5064]], [43929, [5065]], [43930, [5066]], [43931, [5067]], [43932, [5068]], [43933, [5069]], [43934, [5070]], [43935, [5071]], [43936, [5072]], [43937, [5073]], [43938, [5074]], [43939, [5075]], [43940, [5076]], [43941, [5077]], [43942, [5078]], [43943, [5079]], [43944, [5080]], [43945, [5081]], [43946, [5082]], [43947, [5083]], [43948, [5084]], [43949, [5085]], [43950, [5086]], [43951, [5087]], [43952, [5088]], [43953, [5089]], [43954, [5090]], [43955, [5091]], [43956, [5092]], [43957, [5093]], [43958, [5094]], [43959, [5095]], [43960, [5096]], [43961, [5097]], [43962, [5098]], [43963, [5099]], [43964, [5100]], [43965, [5101]], [43966, [5102]], [43967, [5103]], [64256, [102, 102]], [64257, [102, 105]], [64258, [102, 108]], [64259, [102, 102, 105]], [64260, [102, 102, 108]], [64261, [115, 116]], [64262, [115, 116]], [64275, [1396, 1398]], [64276, [1396, 1381]], [64277, [1396, 1387]], [64278, [1406, 1398]], [64279, [1396, 1389]], [65313, [65345]], [65314, [65346]], [65315, [65347]], [65316, [65348]], [65317, [65349]], [65318, [65350]], [65319, [65351]], [65320, [65352]], [65321, [65353]], [65322, [65354]], [65323, [65355]], [65324, [65356]], [65325, [65357]], [65326, [65358]], [65327, [65359]], [65328, [65360]], [65329, [65361]], [65330, [65362]], [65331, [65363]], [65332, [65364]], [65333, [65365]], [65334, [65366]], [65335, [65367]], [65336, [65368]], [65337, [65369]], [65338, [65370]], [66560, [66600]], [66561, [66601]], [66562, [66602]], [66563, [66603]], [66564, [66604]], [66565, [66605]], [66566, [66606]], [66567, [66607]], [66568, [66608]], [66569, [66609]], [66570, [66610]], [66571, [66611]], [66572, [66612]], [66573, [66613]], [66574, [66614]], [66575, [66615]], [66576, [66616]], [66577, [66617]], [66578, [66618]], [66579, [66619]], [66580, [66620]], [66581, [66621]], [66582, [66622]], [66583, [66623]], [66584, [66624]], [66585, [66625]], [66586, [66626]], [66587, [66627]], [66588, [66628]], [66589, [66629]], [66590, [66630]], [66591, [66631]], [66592, [66632]], [66593, [66633]], [66594, [66634]], [66595, [66635]], [66596, [66636]], [66597, [66637]], [66598, [66638]], [66599, [66639]], [66736, [66776]], [66737, [66777]], [66738, [66778]], [66739, [66779]], [66740, [66780]], [66741, [66781]], [66742, [66782]], [66743, [66783]], [66744, [66784]], [66745, [66785]], [66746, [66786]], [66747, [66787]], [66748, [66788]], [66749, [66789]], [66750, [66790]], [66751, [66791]], [66752, [66792]], [66753, [66793]], [66754, [66794]], [66755, [66795]], [66756, [66796]], [66757, [66797]], [66758, [66798]], [66759, [66799]], [66760, [66800]], [66761, [66801]], [66762, [66802]], [66763, [66803]], [66764, [66804]], [66765, [66805]], [66766, [66806]], [66767, [66807]], [66768, [66808]], [66769, [66809]], [66770, [66810]], [66771, [66811]], [66928, [66967]], [66929, [66968]], [66930, [66969]], [66931, [66970]], [66932, [66971]], [66933, [66972]], [66934, [66973]], [66935, [66974]], [66936, [66975]], [66937, [66976]], [66938, [66977]], [66940, [66979]], [66941, [66980]], [66942, [66981]], [66943, [66982]], [66944, [66983]], [66945, [66984]], [66946, [66985]], [66947, [66986]], [66948, [66987]], [66949, [66988]], [66950, [66989]], [66951, [66990]], [66952, [66991]], [66953, [66992]], [66954, [66993]], [66956, [66995]], [66957, [66996]], [66958, [66997]], [66959, [66998]], [66960, [66999]], [66961, [67e3]], [66962, [67001]], [66964, [67003]], [66965, [67004]], [68736, [68800]], [68737, [68801]], [68738, [68802]], [68739, [68803]], [68740, [68804]], [68741, [68805]], [68742, [68806]], [68743, [68807]], [68744, [68808]], [68745, [68809]], [68746, [68810]], [68747, [68811]], [68748, [68812]], [68749, [68813]], [68750, [68814]], [68751, [68815]], [68752, [68816]], [68753, [68817]], [68754, [68818]], [68755, [68819]], [68756, [68820]], [68757, [68821]], [68758, [68822]], [68759, [68823]], [68760, [68824]], [68761, [68825]], [68762, [68826]], [68763, [68827]], [68764, [68828]], [68765, [68829]], [68766, [68830]], [68767, [68831]], [68768, [68832]], [68769, [68833]], [68770, [68834]], [68771, [68835]], [68772, [68836]], [68773, [68837]], [68774, [68838]], [68775, [68839]], [68776, [68840]], [68777, [68841]], [68778, [68842]], [68779, [68843]], [68780, [68844]], [68781, [68845]], [68782, [68846]], [68783, [68847]], [68784, [68848]], [68785, [68849]], [68786, [68850]], [68944, [68976]], [68945, [68977]], [68946, [68978]], [68947, [68979]], [68948, [68980]], [68949, [68981]], [68950, [68982]], [68951, [68983]], [68952, [68984]], [68953, [68985]], [68954, [68986]], [68955, [68987]], [68956, [68988]], [68957, [68989]], [68958, [68990]], [68959, [68991]], [68960, [68992]], [68961, [68993]], [68962, [68994]], [68963, [68995]], [68964, [68996]], [68965, [68997]], [71840, [71872]], [71841, [71873]], [71842, [71874]], [71843, [71875]], [71844, [71876]], [71845, [71877]], [71846, [71878]], [71847, [71879]], [71848, [71880]], [71849, [71881]], [71850, [71882]], [71851, [71883]], [71852, [71884]], [71853, [71885]], [71854, [71886]], [71855, [71887]], [71856, [71888]], [71857, [71889]], [71858, [71890]], [71859, [71891]], [71860, [71892]], [71861, [71893]], [71862, [71894]], [71863, [71895]], [71864, [71896]], [71865, [71897]], [71866, [71898]], [71867, [71899]], [71868, [71900]], [71869, [71901]], [71870, [71902]], [71871, [71903]], [93760, [93792]], [93761, [93793]], [93762, [93794]], [93763, [93795]], [93764, [93796]], [93765, [93797]], [93766, [93798]], [93767, [93799]], [93768, [93800]], [93769, [93801]], [93770, [93802]], [93771, [93803]], [93772, [93804]], [93773, [93805]], [93774, [93806]], [93775, [93807]], [93776, [93808]], [93777, [93809]], [93778, [93810]], [93779, [93811]], [93780, [93812]], [93781, [93813]], [93782, [93814]], [93783, [93815]], [93784, [93816]], [93785, [93817]], [93786, [93818]], [93787, [93819]], [93788, [93820]], [93789, [93821]], [93790, [93822]], [93791, [93823]], [93856, [93883]], [93857, [93884]], [93858, [93885]], [93859, [93886]], [93860, [93887]], [93861, [93888]], [93862, [93889]], [93863, [93890]], [93864, [93891]], [93865, [93892]], [93866, [93893]], [93867, [93894]], [93868, [93895]], [93869, [93896]], [93870, [93897]], [93871, [93898]], [93872, [93899]], [93873, [93900]], [93874, [93901]], [93875, [93902]], [93876, [93903]], [93877, [93904]], [93878, [93905]], [93879, [93906]], [93880, [93907]], [125184, [125218]], [125185, [125219]], [125186, [125220]], [125187, [125221]], [125188, [125222]], [125189, [125223]], [125190, [125224]], [125191, [125225]], [125192, [125226]], [125193, [125227]], [125194, [125228]], [125195, [125229]], [125196, [125230]], [125197, [125231]], [125198, [125232]], [125199, [125233]], [125200, [125234]], [125201, [125235]], [125202, [125236]], [125203, [125237]], [125204, [125238]], [125205, [125239]], [125206, [125240]], [125207, [125241]], [125208, [125242]], [125209, [125243]], [125210, [125244]], [125211, [125245]], [125212, [125246]], [125213, [125247]], [125214, [125248]], [125215, [125249]], [125216, [125250]], [125217, [125251]]]);
7370
- function caseFold(input) {
7371
- if (typeof input !== "string") {
7372
- throw new TypeError("Input must be a string");
7373
- }
7374
- let result = [];
7375
- for (const char of input) {
7376
- const codePoint = char.codePointAt(0);
7377
- const mapping = FOLDING_MAP.get(codePoint);
7378
- result.push(mapping ? String.fromCodePoint(...mapping) : char);
7379
- }
7380
- return result.join("");
7381
- }
7382
-
7383
- // src/utils/canonical-path.ts
7384
- function alternateAsciiCase(value) {
7385
- const index = value.search(/[A-Za-z]/);
7386
- if (index === -1) return null;
7387
- const character = value[index];
7388
- const alternate = character === character.toLowerCase() ? character.toUpperCase() : character.toLowerCase();
7389
- return `${value.slice(0, index)}${alternate}${value.slice(index + 1)}`;
7390
- }
7391
- function probeEntryCaseSensitivity(entryPath) {
7392
- const alternateName = alternateAsciiCase(path14.basename(entryPath));
7393
- if (!alternateName) return void 0;
7394
- try {
7395
- const canonicalPath = fs.realpathSync.native(entryPath);
7396
- const alternatePath = fs.realpathSync.native(path14.join(path14.dirname(entryPath), alternateName));
7397
- return canonicalPath === alternatePath;
7398
- } catch (error) {
7399
- const code = error.code;
7400
- if (code === "ENOENT" || code === "ENOTDIR") return false;
7401
- return void 0;
7402
- }
7403
- }
7404
- function probeEmptyWindowsDirectory(existingAncestor) {
7405
- const probePath = path14.join(
7406
- existingAncestor,
7407
- `.codebase-index-case-probe-${crypto.randomBytes(8).toString("hex")}`
7408
- );
7409
- let created = false;
7410
- try {
7411
- const descriptor = fs.openSync(probePath, "wx", 384);
7412
- created = true;
7413
- fs.closeSync(descriptor);
7414
- return probeEntryCaseSensitivity(probePath);
7415
- } catch {
7416
- return void 0;
7417
- } finally {
7418
- if (created) fs.unlinkSync(probePath);
7419
- }
7420
- }
7421
- function detectCaseInsensitiveFileSystem(existingAncestor) {
7422
- try {
7423
- if (fs.statSync(existingAncestor).isDirectory()) {
7424
- const directory = fs.opendirSync(existingAncestor);
7425
- try {
7426
- let entry = directory.readSync();
7427
- while (entry) {
7428
- if (!entry.isSymbolicLink() && alternateAsciiCase(entry.name)) {
7429
- const result = probeEntryCaseSensitivity(path14.join(existingAncestor, entry.name));
7430
- if (result !== void 0) return result;
7431
- }
7432
- entry = directory.readSync();
7433
- }
7434
- } finally {
7435
- directory.closeSync();
7436
- }
7437
- }
7438
- } catch {
7439
- return void 0;
7440
- }
7441
- if (process.platform === "darwin") {
7442
- return probeEntryCaseSensitivity(existingAncestor);
7443
- }
7444
- if (process.platform === "win32") {
7445
- return probeEmptyWindowsDirectory(existingAncestor);
7446
- }
7447
- return void 0;
7448
- }
7449
- function foldMissingPathComponent(component) {
7450
- return caseFold(component);
7451
- }
7452
- function canonicalizePathForComparison(targetPath, options = {}) {
7453
- const resolved = path14.resolve(targetPath);
7454
- const missingParts = [];
7455
- let candidate = resolved;
7456
- while (true) {
7457
- try {
7458
- const existingAncestor = fs.realpathSync.native(candidate);
7459
- const isCaseInsensitive = missingParts.length > 0 ? (options.isCaseInsensitive ?? detectCaseInsensitiveFileSystem)(existingAncestor) : false;
7460
- const suffix = isCaseInsensitive === true ? missingParts.map(foldMissingPathComponent) : missingParts;
7461
- return path14.join(existingAncestor, ...suffix);
7462
- } catch (error) {
7463
- const code = error.code;
7464
- if (code !== "ENOENT" && code !== "ENOTDIR") throw error;
7465
- const parent = path14.dirname(candidate);
7466
- if (parent === candidate) return resolved;
7467
- missingParts.unshift(path14.basename(candidate));
7468
- candidate = parent;
7469
- }
7470
- }
7471
- }
7472
-
7473
7540
  // src/git/branch-resolution.ts
7474
7541
  var import_child_process = require("child_process");
7475
7542
  var import_crypto2 = require("crypto");
@@ -9103,6 +9170,8 @@ function hasBlameMetadata(metadata) {
9103
9170
  return blameFromMetadata(metadata) !== void 0;
9104
9171
  }
9105
9172
  var INDEX_METADATA_VERSION = "1";
9173
+ var PROJECT_PATH_STORAGE_VERSION = "2";
9174
+ var GLOBAL_PATH_STORAGE_VERSION = "1";
9106
9175
  var EMBEDDING_STRATEGY_VERSION = "2";
9107
9176
  var SWIFT_PARSER_VERSION = "1";
9108
9177
  var METAL_PARSER_VERSION = "1";
@@ -9433,18 +9502,20 @@ function selectIndexableChunks(chunks, limit, semanticOnly) {
9433
9502
  const indexableChunks = semanticOnly ? chunks.filter((chunk) => chunk.chunkType !== "other") : chunks;
9434
9503
  return selectChunksWithFileCoverage(indexableChunks, limit);
9435
9504
  }
9436
- function matchesHardSearchFilters(candidate, options) {
9505
+ function matchesHardSearchFilters(candidate, options, projectRoot) {
9437
9506
  if (options?.fileType) {
9438
9507
  const ext = candidate.metadata.filePath.split(".").pop()?.toLowerCase();
9439
9508
  const requestedExtension = options.fileType.trim().toLowerCase().replace(/^\./, "");
9440
9509
  if (ext !== requestedExtension) return false;
9441
9510
  }
9442
9511
  if (options?.directory) {
9443
- const normalizedPath = candidate.metadata.filePath.replace(/\\/g, "/");
9444
- const normalizedDir = options.directory.trim().replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
9445
- const isAbsoluteDirectory = normalizedDir.startsWith("/");
9446
- const matchesDirectory = isAbsoluteDirectory ? normalizedPath === normalizedDir || normalizedPath.startsWith(`${normalizedDir}/`) : normalizedPath === normalizedDir || normalizedPath.startsWith(`${normalizedDir}/`) || normalizedPath.includes(`/${normalizedDir}/`) || normalizedPath.endsWith(`/${normalizedDir}`);
9447
- if (!matchesDirectory) return false;
9512
+ const candidatePath = canonicalizePathForComparison(
9513
+ path18.resolve(projectRoot, candidate.metadata.filePath.replace(/\\/g, path18.sep))
9514
+ );
9515
+ const directoryPath = canonicalizePathForComparison(
9516
+ path18.resolve(projectRoot, options.directory.trim().replace(/\\/g, path18.sep))
9517
+ );
9518
+ if (!isPathWithinRoot2(candidatePath, directoryPath)) return false;
9448
9519
  }
9449
9520
  if (options?.chunkType && candidate.metadata.chunkType !== options.chunkType) {
9450
9521
  return false;
@@ -9466,8 +9537,8 @@ function matchesHardSearchFilters(candidate, options) {
9466
9537
  }
9467
9538
  return true;
9468
9539
  }
9469
- function matchesSearchFilters(candidate, options, minScore) {
9470
- return candidate.score >= minScore && matchesHardSearchFilters(candidate, options);
9540
+ function matchesSearchFilters(candidate, options, minScore, projectRoot) {
9541
+ return candidate.score >= minScore && matchesHardSearchFilters(candidate, options, projectRoot);
9471
9542
  }
9472
9543
  function unionCandidates(semanticCandidates, keywordCandidates) {
9473
9544
  const byId = /* @__PURE__ */ new Map();
@@ -9518,7 +9589,7 @@ var Indexer = class _Indexer {
9518
9589
  readerArtifactFingerprint = null;
9519
9590
  writerArtifactFingerprint = null;
9520
9591
  readerArtifactRetryAfter = /* @__PURE__ */ new Map();
9521
- constructor(projectRoot, config, host = "opencode", runtimeOptions = {}) {
9592
+ constructor(projectRoot, config, host, runtimeOptions = {}) {
9522
9593
  this.projectRoot = projectRoot;
9523
9594
  this.projectIdentityHash = hashContent(this.getCanonicalPath(projectRoot)).slice(0, 16);
9524
9595
  this.materializedProjectRoot = runtimeOptions.materializedProjectRoot ?? projectRoot;
@@ -9531,37 +9602,90 @@ var Indexer = class _Indexer {
9531
9602
  this.indexPathOverride = runtimeOptions.indexPath;
9532
9603
  this.config = config;
9533
9604
  this.host = host;
9605
+ if (isGitRepo(this.materializedProjectRoot)) {
9606
+ this.currentBranch = this.branchNameOverride ?? getBranchOrDefault(this.materializedProjectRoot);
9607
+ this.baseBranch = getBaseBranch(this.materializedProjectRoot);
9608
+ } else {
9609
+ this.currentBranch = "default";
9610
+ this.baseBranch = "default";
9611
+ }
9534
9612
  this.indexPath = this.getIndexPath();
9535
- this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
9536
- this.failedBatchesPath = this.getRuntimeArtifactPath("failed-batches.json");
9613
+ this.refreshRuntimeArtifactPaths();
9537
9614
  this.logger = initializeLogger(config.debug);
9538
9615
  }
9539
9616
  getIndexPath() {
9540
9617
  return this.indexPathOverride ?? resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
9541
9618
  }
9542
9619
  toCanonicalFilePath(filePath) {
9620
+ if (!path18.isAbsolute(filePath)) {
9621
+ return this.resolveStoredFilePath(filePath, this.projectRoot);
9622
+ }
9543
9623
  if (path18.resolve(this.materializedProjectRoot) === path18.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.materializedProjectRoot)) {
9544
9624
  return filePath;
9545
9625
  }
9546
9626
  return path18.resolve(this.projectRoot, path18.relative(this.materializedProjectRoot, filePath));
9547
9627
  }
9548
- toMaterializedFilePath(filePath) {
9549
- if (path18.resolve(this.materializedProjectRoot) === path18.resolve(this.projectRoot) || !isPathWithinRoot2(filePath, this.projectRoot)) {
9628
+ toStoredFilePath(filePath) {
9629
+ const canonicalFilePath = this.toCanonicalFilePath(filePath);
9630
+ if (this.config.scope !== "project" || !isPathWithinRoot2(canonicalFilePath, this.projectRoot)) {
9631
+ return canonicalFilePath;
9632
+ }
9633
+ return path18.relative(this.projectRoot, canonicalFilePath).split(path18.sep).join("/");
9634
+ }
9635
+ resolveStoredFilePath(filePath, rootPath = this.projectRoot) {
9636
+ if (path18.isAbsolute(filePath)) {
9550
9637
  return filePath;
9551
9638
  }
9552
- return path18.resolve(this.materializedProjectRoot, path18.relative(this.projectRoot, filePath));
9639
+ const resolvedPath = path18.resolve(rootPath, ...filePath.split("/"));
9640
+ if (!isPathWithinRoot2(resolvedPath, rootPath)) {
9641
+ throw new Error(`Stored project path escapes project root: ${JSON.stringify(filePath)}`);
9642
+ }
9643
+ return resolvedPath;
9644
+ }
9645
+ getCanonicalStoredFilePath(filePath) {
9646
+ return this.getCanonicalPath(this.resolveStoredFilePath(filePath));
9647
+ }
9648
+ resolveFilePathRecord(record) {
9649
+ return {
9650
+ ...record,
9651
+ filePath: this.resolveStoredFilePath(record.filePath)
9652
+ };
9653
+ }
9654
+ resolveCallEdgeFilePath(edge) {
9655
+ if (!edge.fromSymbolFilePath) return edge;
9656
+ return {
9657
+ ...edge,
9658
+ fromSymbolFilePath: this.resolveStoredFilePath(edge.fromSymbolFilePath)
9659
+ };
9660
+ }
9661
+ toMaterializedFilePath(filePath) {
9662
+ const storedFilePath = this.toStoredFilePath(filePath);
9663
+ if (path18.isAbsolute(storedFilePath)) {
9664
+ return storedFilePath;
9665
+ }
9666
+ return this.resolveStoredFilePath(storedFilePath, this.materializedProjectRoot);
9553
9667
  }
9554
9668
  getPreparedBranchNamespace() {
9555
9669
  if (!this.branchNameOverride && !this.catalogIdentityOverride) return null;
9556
9670
  return hashContent(this.getBranchCatalogKey()).slice(0, 16);
9557
9671
  }
9672
+ getRuntimeArtifactNamespace() {
9673
+ if (this.config.scope !== "project" || this.getBranchCatalogIdentity() === "default") {
9674
+ return this.getPreparedBranchNamespace();
9675
+ }
9676
+ return hashContent(this.getBranchCatalogKey()).slice(0, 16);
9677
+ }
9558
9678
  getRuntimeArtifactPath(fileName) {
9559
- const namespace = this.getPreparedBranchNamespace();
9679
+ const namespace = this.getRuntimeArtifactNamespace();
9560
9680
  if (!namespace) return path18.join(this.indexPath, fileName);
9561
9681
  const extension = path18.extname(fileName);
9562
9682
  const baseName = fileName.slice(0, fileName.length - extension.length);
9563
9683
  return path18.join(this.indexPath, `${baseName}.${namespace}${extension}`);
9564
9684
  }
9685
+ refreshRuntimeArtifactPaths() {
9686
+ this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
9687
+ this.failedBatchesPath = this.getRuntimeArtifactPath("failed-batches.json");
9688
+ }
9565
9689
  getPreparedChunkId(chunkId) {
9566
9690
  const namespace = this.getPreparedBranchNamespace();
9567
9691
  return namespace ? `${chunkId}_${namespace}` : chunkId;
@@ -9587,19 +9711,8 @@ var Indexer = class _Indexer {
9587
9711
  return path18.resolve(targetPath);
9588
9712
  }
9589
9713
  }
9590
- isLocalProjectIndexPath() {
9591
- const localProjectIndexPaths = [path18.join(this.projectRoot, getHostProjectIndexRelativePath(this.host))];
9592
- if (this.host !== "opencode") {
9593
- localProjectIndexPaths.push(path18.join(this.projectRoot, getHostProjectIndexRelativePath("opencode")));
9594
- }
9595
- return localProjectIndexPaths.some((localPath) => {
9596
- if (!(0, import_fs12.existsSync)(localPath) || !(0, import_fs12.existsSync)(this.indexPath)) {
9597
- return path18.resolve(this.indexPath) === path18.resolve(localPath);
9598
- }
9599
- const indexStats = (0, import_fs12.statSync)(this.indexPath);
9600
- const localStats = (0, import_fs12.statSync)(localPath);
9601
- return indexStats.dev === localStats.dev && indexStats.ino === localStats.ino;
9602
- });
9714
+ isProjectOwnedIndexPath() {
9715
+ return isProjectIndexPathOwnedByProject(this.projectRoot, this.indexPath, this.host);
9603
9716
  }
9604
9717
  resetLoadedIndexState(retireDatabase = false) {
9605
9718
  if (this.database) {
@@ -9634,10 +9747,10 @@ var Indexer = class _Indexer {
9634
9747
  this.readerArtifactRetryAfter.clear();
9635
9748
  }
9636
9749
  async withIndexMutationLease(operation, callback) {
9750
+ this.refreshBranchInfo();
9637
9751
  const lease = acquireIndexLock(this.indexPath, operation);
9638
9752
  this.indexPath = lease.canonicalIndexPath;
9639
- this.fileHashCachePath = this.getRuntimeArtifactPath("file-hashes.json");
9640
- this.failedBatchesPath = this.getRuntimeArtifactPath("failed-batches.json");
9753
+ this.refreshRuntimeArtifactPaths();
9641
9754
  this.activeIndexLease = lease;
9642
9755
  let result;
9643
9756
  let callbackError;
@@ -9809,29 +9922,24 @@ var Indexer = class _Indexer {
9809
9922
  getProjectForceReembedMetadataKey() {
9810
9923
  return `index.forceReembed.${this.projectIdentityHash}`;
9811
9924
  }
9812
- getCallGraphResolutionMetadataKey() {
9813
- if (this.config.scope !== "global") {
9814
- return "index.callGraphResolutionVersion";
9815
- }
9816
- return `index.callGraphResolutionVersion.${this.projectIdentityHash}`;
9925
+ getBranchMigrationMetadataKey(prefix, catalogIdentity = this.getBranchCatalogIdentity()) {
9926
+ const branchKey = this.getBranchCatalogKeyFor(catalogIdentity);
9927
+ return `${prefix}.${hashContent(branchKey).slice(0, 24)}`;
9817
9928
  }
9818
- getSwiftParserVersionMetadataKey() {
9819
- const key = "index.parser.swiftVersion";
9820
- if (this.config.scope !== "global") {
9821
- return key;
9822
- }
9823
- return `${key}.${this.projectIdentityHash}`;
9929
+ getCallGraphResolutionMetadataKey(catalogIdentity = this.getBranchCatalogIdentity()) {
9930
+ return this.getBranchMigrationMetadataKey("index.callGraphResolutionVersion", catalogIdentity);
9824
9931
  }
9825
- getMetalParserVersionMetadataKey() {
9826
- const key = "index.parser.metalVersion";
9827
- if (this.config.scope !== "global") {
9828
- return key;
9829
- }
9830
- return `${key}.${this.projectIdentityHash}`;
9932
+ getSwiftParserVersionMetadataKey(catalogIdentity = this.getBranchCatalogIdentity()) {
9933
+ return this.getBranchMigrationMetadataKey("index.parser.swiftVersion", catalogIdentity);
9934
+ }
9935
+ getMetalParserVersionMetadataKey(catalogIdentity = this.getBranchCatalogIdentity()) {
9936
+ return this.getBranchMigrationMetadataKey("index.parser.metalVersion", catalogIdentity);
9831
9937
  }
9832
9938
  getSymbolExtractorVersionMetadataKey(catalogIdentity = this.getBranchCatalogIdentity()) {
9833
- const branchKey = this.getBranchCatalogKeyFor(catalogIdentity);
9834
- return `index.symbolExtractorVersion.${hashContent(branchKey).slice(0, 24)}`;
9939
+ return this.getBranchMigrationMetadataKey("index.symbolExtractorVersion", catalogIdentity);
9940
+ }
9941
+ areBranchMigrationVersionsCurrent(database, catalogIdentity = this.getBranchCatalogIdentity()) {
9942
+ return database.getMetadata(this.getCallGraphResolutionMetadataKey(catalogIdentity)) === CALL_GRAPH_RESOLUTION_VERSION && database.getMetadata(this.getSwiftParserVersionMetadataKey(catalogIdentity)) === SWIFT_PARSER_VERSION && database.getMetadata(this.getMetalParserVersionMetadataKey(catalogIdentity)) === METAL_PARSER_VERSION && database.getMetadata(this.getSymbolExtractorVersionMetadataKey(catalogIdentity)) === SYMBOL_EXTRACTOR_VERSION;
9835
9943
  }
9836
9944
  hasProjectForceReembedPending() {
9837
9945
  return this.config.scope === "global" && this.database?.getMetadata(this.getProjectForceReembedMetadataKey()) === "true";
@@ -9966,13 +10074,14 @@ var Indexer = class _Indexer {
9966
10074
  return Array.from(keys);
9967
10075
  }
9968
10076
  isFileInCurrentScope(filePath, roots) {
9969
- if (roots.some((root) => isPathWithinRoot2(filePath, root))) return true;
9970
- const canonicalFilePath = this.getCanonicalPath(filePath);
10077
+ const canonicalFilePath = this.getCanonicalStoredFilePath(filePath);
9971
10078
  return roots.some((root) => isPathWithinRoot2(canonicalFilePath, root));
9972
10079
  }
9973
10080
  isFileInProjectRoot(filePath) {
9974
- if (isPathWithinRoot2(filePath, this.projectRoot)) return true;
9975
- return isPathWithinRoot2(this.getCanonicalPath(filePath), this.getCanonicalPath(this.projectRoot));
10081
+ return isPathWithinRoot2(
10082
+ this.getCanonicalStoredFilePath(filePath),
10083
+ this.getCanonicalPath(this.projectRoot)
10084
+ );
9976
10085
  }
9977
10086
  clearScopedFileHashCache(roots) {
9978
10087
  for (const filePath of Array.from(this.fileHashCache.keys())) {
@@ -10373,7 +10482,10 @@ var Indexer = class _Indexer {
10373
10482
  const intent = isLikelyImplementationPath2(candidate.metadata.filePath) ? "implementation" : "doc_or_test";
10374
10483
  parts.push(`intent_hint: ${intent}`);
10375
10484
  try {
10376
- const fileContent = await import_fs12.promises.readFile(candidate.metadata.filePath, "utf-8");
10485
+ const fileContent = await import_fs12.promises.readFile(
10486
+ this.toMaterializedFilePath(candidate.metadata.filePath),
10487
+ "utf-8"
10488
+ );
10377
10489
  const lines = fileContent.split("\n");
10378
10490
  const snippetStartLine = Math.max(1, candidate.metadata.startLine);
10379
10491
  const snippetEndLine = Math.min(lines.length, candidate.metadata.endLine);
@@ -10442,7 +10554,7 @@ var Indexer = class _Indexer {
10442
10554
  if (this.config.scope === "global") {
10443
10555
  return "Shared vector index could not be read. Restore or repair the complete fingerprinted shared vector artifacts; automatic reset is disabled for global scope.";
10444
10556
  }
10445
- if (!this.isLocalProjectIndexPath()) {
10557
+ if (!this.isProjectOwnedIndexPath()) {
10446
10558
  return "Vector index could not be read from an inherited project index. Restore or fingerprint it from the checkout that owns the index; do not remove or rebuild it from this worktree.";
10447
10559
  }
10448
10560
  return "Vector index could not be read. Run index_codebase after the active writer finishes to fingerprint a structurally valid legacy pair, or remove this checkout's local index directory and run index_codebase to rebuild it.";
@@ -10451,7 +10563,7 @@ var Indexer = class _Indexer {
10451
10563
  if (this.config.scope === "global") {
10452
10564
  return "Shared keyword index could not be read; semantic search remains available. Restore or repair the shared keyword artifact; automatic reset is disabled for global scope.";
10453
10565
  }
10454
- if (!this.isLocalProjectIndexPath()) {
10566
+ if (!this.isProjectOwnedIndexPath()) {
10455
10567
  return "Keyword index could not be read from an inherited project index; semantic search remains available. Restore or repair it from the checkout that owns the index; do not rebuild it from this worktree.";
10456
10568
  }
10457
10569
  return "Keyword index could not be read; semantic search remains available. Restore a readable published keyword index, or run index_codebase with force=true after the active writer finishes.";
@@ -10460,10 +10572,10 @@ var Indexer = class _Indexer {
10460
10572
  if (this.config.scope === "global") {
10461
10573
  return "Shared index database could not be read. Restore or repair the shared SQLite database; automatic reset is disabled for global scope.";
10462
10574
  }
10463
- if (!this.isLocalProjectIndexPath()) {
10575
+ if (!this.isProjectOwnedIndexPath()) {
10464
10576
  return "Index database could not be read from an inherited project index. Restore or repair it from the checkout that owns the index; do not migrate or rebuild it from this worktree.";
10465
10577
  }
10466
- return "Index database could not be read. Run index_codebase after the active writer finishes to repair or migrate it under the writer lease.";
10578
+ return "Index database could not be read. Run index_codebase with force=true to rebuild a legacy absolute-path schema, or repair the database after the active writer finishes.";
10467
10579
  }
10468
10580
  getReaderFileFingerprint(filePath, identityOnly = false) {
10469
10581
  try {
@@ -10643,7 +10755,7 @@ var Indexer = class _Indexer {
10643
10755
  const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
10644
10756
  if (mode === "writer") {
10645
10757
  await import_fs12.promises.mkdir(this.indexPath, { recursive: true });
10646
- if (recoveredOwners.length > 0 && this.config.scope === "project" && !this.isLocalProjectIndexPath()) {
10758
+ if (recoveredOwners.length > 0 && this.config.scope === "project" && !this.isProjectOwnedIndexPath()) {
10647
10759
  throw new Error(
10648
10760
  "Interrupted indexing recovery is unsafe while using an inherited worktree index. Run index_codebase with force=true to create a local project index boundary."
10649
10761
  );
@@ -10744,6 +10856,7 @@ var Indexer = class _Indexer {
10744
10856
  this.baseBranch = "default";
10745
10857
  this.logger.branch("debug", "Not a git repository, using default branch");
10746
10858
  }
10859
+ this.refreshRuntimeArtifactPaths();
10747
10860
  if (mode === "writer" && recoveredOwners.length > 0) {
10748
10861
  await this.recoverFromInterruptedIndexingUnlocked(recoveredOwners);
10749
10862
  }
@@ -10899,6 +11012,14 @@ var Indexer = class _Indexer {
10899
11012
  }
10900
11013
  return `Detected a corrupted local SQLite index at ${dbPath} and reset the local index. Run index_codebase to rebuild search data.`;
10901
11014
  }
11015
+ async removeProjectRuntimeStateArtifacts() {
11016
+ if (!(0, import_fs12.existsSync)(this.indexPath)) return;
11017
+ const names = await import_fs12.promises.readdir(this.indexPath);
11018
+ const runtimeStatePattern = /^(?:file-hashes|failed-batches)(?:\.[a-f0-9]{16})?\.json$/;
11019
+ await Promise.all(
11020
+ names.filter((name) => runtimeStatePattern.test(name)).map((name) => import_fs12.promises.rm(path18.join(this.indexPath, name), { force: true }))
11021
+ );
11022
+ }
10902
11023
  async resetLocalIndexArtifacts() {
10903
11024
  this.store = null;
10904
11025
  this.invertedIndex = null;
@@ -10918,11 +11039,10 @@ var Indexer = class _Indexer {
10918
11039
  path18.join(this.indexPath, "vectors"),
10919
11040
  path18.join(this.indexPath, "vectors.usearch"),
10920
11041
  path18.join(this.indexPath, "vectors.meta.json"),
10921
- path18.join(this.indexPath, "inverted-index.json"),
10922
- path18.join(this.indexPath, "file-hashes.json"),
10923
- path18.join(this.indexPath, "failed-batches.json")
11042
+ path18.join(this.indexPath, "inverted-index.json")
10924
11043
  ];
10925
11044
  await Promise.all(resetPaths.map((targetPath) => import_fs12.promises.rm(targetPath, { recursive: true, force: true })));
11045
+ await this.removeProjectRuntimeStateArtifacts();
10926
11046
  await import_fs12.promises.mkdir(this.indexPath, { recursive: true });
10927
11047
  }
10928
11048
  async tryResetCorruptedIndex(stage, error) {
@@ -10972,12 +11092,20 @@ var Indexer = class _Indexer {
10972
11092
  }
10973
11093
  this.database.addChunksToBranchBatch(this.getBranchCatalogKey(), chunkIds);
10974
11094
  }
11095
+ getExpectedPathStorageVersion() {
11096
+ return this.config.scope === "project" ? PROJECT_PATH_STORAGE_VERSION : GLOBAL_PATH_STORAGE_VERSION;
11097
+ }
11098
+ hasStoredIndexData() {
11099
+ const stats = this.database?.getStats();
11100
+ return (this.store?.count() ?? 0) > 0 || (stats?.chunkCount ?? 0) > 0 || (stats?.symbolCount ?? 0) > 0 || this.fileHashCache.size > 0;
11101
+ }
10975
11102
  loadIndexMetadata() {
10976
11103
  if (!this.database) return null;
10977
11104
  const version = this.database.getMetadata("index.version");
10978
11105
  if (!version) return null;
10979
11106
  return {
10980
11107
  indexVersion: version,
11108
+ pathStorageVersion: this.database.getMetadata("index.pathStorageVersion") ?? GLOBAL_PATH_STORAGE_VERSION,
10981
11109
  embeddingProvider: this.database.getMetadata("index.embeddingProvider") ?? "",
10982
11110
  embeddingModel: this.database.getMetadata("index.embeddingModel") ?? "",
10983
11111
  embeddingDimensions: parseInt(this.database.getMetadata("index.embeddingDimensions") ?? "0", 10),
@@ -10992,6 +11120,7 @@ var Indexer = class _Indexer {
10992
11120
  const existingCreatedAt = this.database.getMetadata("index.createdAt");
10993
11121
  const completeProjectEmbeddingStrategyReset = !this.hasProjectForceReembedPending();
10994
11122
  this.database.setMetadata("index.version", INDEX_METADATA_VERSION);
11123
+ this.database.setMetadata("index.pathStorageVersion", this.getExpectedPathStorageVersion());
10995
11124
  this.database.setMetadata("index.embeddingProvider", provider.provider);
10996
11125
  this.database.setMetadata("index.embeddingModel", provider.modelInfo.model);
10997
11126
  this.database.setMetadata("index.embeddingDimensions", provider.modelInfo.dimensions.toString());
@@ -11014,6 +11143,16 @@ var Indexer = class _Indexer {
11014
11143
  }
11015
11144
  validateIndexCompatibility(provider) {
11016
11145
  const storedMetadata = this.loadIndexMetadata();
11146
+ const storedPathStorageVersion = this.database?.getMetadata("index.pathStorageVersion") ?? GLOBAL_PATH_STORAGE_VERSION;
11147
+ const expectedPathStorageVersion = this.getExpectedPathStorageVersion();
11148
+ if (this.hasStoredIndexData() && storedPathStorageVersion !== expectedPathStorageVersion) {
11149
+ return {
11150
+ compatible: false,
11151
+ code: "PATH_STORAGE_MISMATCH" /* PATH_STORAGE_MISMATCH */,
11152
+ reason: `Path storage format mismatch: index uses v${storedPathStorageVersion} checkout-absolute paths, but this project requires portable v${expectedPathStorageVersion} paths. Run index_codebase with force=true to rebuild the shared project index once.`,
11153
+ storedMetadata: storedMetadata ?? void 0
11154
+ };
11155
+ }
11017
11156
  if (!storedMetadata) {
11018
11157
  return { compatible: true };
11019
11158
  }
@@ -11065,6 +11204,7 @@ var Indexer = class _Indexer {
11065
11204
  return this.indexCompatibility;
11066
11205
  }
11067
11206
  async ensureInitialized() {
11207
+ this.refreshBranchInfo();
11068
11208
  let initializedReader = false;
11069
11209
  while (true) {
11070
11210
  if (this.initializationPromise) {
@@ -11172,8 +11312,8 @@ var Indexer = class _Indexer {
11172
11312
  }
11173
11313
  const branchKey = this.getBranchCatalogKey();
11174
11314
  const alreadyIndexed = database.getBranchChunkIds(branchKey).length > 0 && database.getBranchSymbolIds(branchKey).length > 0;
11175
- const symbolsCurrent = database.getMetadata(this.getSymbolExtractorVersionMetadataKey()) === SYMBOL_EXTRACTOR_VERSION;
11176
- if (alreadyIndexed && symbolsCurrent && this.getStoredBranchCommit(database) === normalizedCommit) {
11315
+ const migrationsCurrent = this.areBranchMigrationVersionsCurrent(database);
11316
+ if (alreadyIndexed && migrationsCurrent && this.getStoredBranchCommit(database) === normalizedCommit) {
11177
11317
  return { prepared: false };
11178
11318
  }
11179
11319
  const stats = await this.indexUnlocked(onProgress, [], true);
@@ -11267,21 +11407,21 @@ var Indexer = class _Indexer {
11267
11407
  const currentFileHashes = /* @__PURE__ */ new Map();
11268
11408
  const needsCallGraphResolutionMigration = database.getMetadata(this.getCallGraphResolutionMetadataKey()) !== CALL_GRAPH_RESOLUTION_VERSION;
11269
11409
  for (const f of files) {
11270
- const canonicalPath = this.toCanonicalFilePath(f.path);
11410
+ const storedPath = this.toStoredFilePath(f.path);
11271
11411
  const currentHash = hashFile(f.path);
11272
- currentFileHashes.set(canonicalPath, currentHash);
11273
- const cachedHashMatches = this.fileHashCache.get(canonicalPath) === currentHash;
11274
- const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(canonicalPath).some(
11412
+ currentFileHashes.set(storedPath, currentHash);
11413
+ const cachedHashMatches = this.fileHashCache.get(storedPath) === currentHash;
11414
+ const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(storedPath).some(
11275
11415
  (chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
11276
11416
  );
11277
- const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path18.extname(canonicalPath).toLowerCase() === ".swift";
11278
- const requiresMetalParserUpgrade = reparseCachedMetalFiles && path18.extname(canonicalPath).toLowerCase() === ".metal";
11417
+ const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path18.extname(storedPath).toLowerCase() === ".swift";
11418
+ const requiresMetalParserUpgrade = reparseCachedMetalFiles && path18.extname(storedPath).toLowerCase() === ".metal";
11279
11419
  if (cachedHashMatches && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
11280
- unchangedFilePaths.add(canonicalPath);
11420
+ unchangedFilePaths.add(storedPath);
11281
11421
  this.logger.recordCacheHit();
11282
11422
  } else {
11283
11423
  const content = await import_fs12.promises.readFile(f.path, "utf-8");
11284
- changedFiles.push({ path: canonicalPath, content, hash: currentHash });
11424
+ changedFiles.push({ path: storedPath, content, hash: currentHash });
11285
11425
  this.logger.recordCacheMiss();
11286
11426
  }
11287
11427
  }
@@ -11386,8 +11526,7 @@ var Indexer = class _Indexer {
11386
11526
  for (const parsed of parsedFiles) {
11387
11527
  currentFilePaths.add(parsed.path);
11388
11528
  if (parsed.chunks.length === 0) {
11389
- const relativePath = path18.relative(this.projectRoot, parsed.path);
11390
- stats.parseFailures.push(relativePath);
11529
+ stats.parseFailures.push(path18.isAbsolute(parsed.path) ? path18.relative(this.projectRoot, parsed.path) : parsed.path);
11391
11530
  }
11392
11531
  let chunksToProcess = parsed.chunks;
11393
11532
  if (this.config.indexing.fallbackToTextOnMaxChunks && chunksToProcess.length > this.config.indexing.maxChunksPerFile) {
@@ -12028,6 +12167,43 @@ var Indexer = class _Indexer {
12028
12167
  const union = a.size + b.size - intersection;
12029
12168
  return intersection / union;
12030
12169
  }
12170
+ getBranchPrefilterState(database, branchChunkIds) {
12171
+ const hasInitializedBranchCatalog = branchChunkIds !== null && database.getAllBranches().length > 0;
12172
+ return {
12173
+ hasInitializedBranchCatalog,
12174
+ shouldPrefilterByBranch: branchChunkIds !== null && (this.config.scope === "global" || hasInitializedBranchCatalog)
12175
+ };
12176
+ }
12177
+ searchCandidatesWithBranchPrefilter(initialLimit, totalCount, branchChunkIds, shouldPrefilterByBranch, search, getChunkId) {
12178
+ const normalizedLimit = Math.max(0, Math.floor(initialLimit));
12179
+ if (normalizedLimit === 0) return [];
12180
+ if (!shouldPrefilterByBranch || !branchChunkIds) {
12181
+ return search(normalizedLimit);
12182
+ }
12183
+ const targetCount = Math.min(normalizedLimit, branchChunkIds.size);
12184
+ if (targetCount === 0 || totalCount === 0) return [];
12185
+ let requestedLimit = Math.min(normalizedLimit, totalCount);
12186
+ while (true) {
12187
+ const results = search(requestedLimit);
12188
+ const branchResults = results.filter((candidate) => branchChunkIds.has(getChunkId(candidate)));
12189
+ if (branchResults.length >= targetCount || results.length < requestedLimit || requestedLimit >= totalCount) {
12190
+ return branchResults;
12191
+ }
12192
+ const nextLimit = Math.min(totalCount, Math.max(requestedLimit + 1, requestedLimit * 2));
12193
+ if (nextLimit === requestedLimit) return branchResults;
12194
+ requestedLimit = nextLimit;
12195
+ }
12196
+ }
12197
+ searchSemanticCandidates(store, embedding, initialLimit, branchChunkIds, shouldPrefilterByBranch) {
12198
+ return this.searchCandidatesWithBranchPrefilter(
12199
+ initialLimit,
12200
+ store.count(),
12201
+ branchChunkIds,
12202
+ shouldPrefilterByBranch,
12203
+ (requestedLimit) => store.search(embedding, requestedLimit),
12204
+ (candidate) => candidate.id
12205
+ );
12206
+ }
12031
12207
  async search(query, limit, options) {
12032
12208
  const { store, provider, invertedIndex, database, readIssues, compatibility } = await this.ensureInitialized();
12033
12209
  this.requireReadableComponents(readIssues, "vectors", "database");
@@ -12072,12 +12248,7 @@ var Indexer = class _Indexer {
12072
12248
  });
12073
12249
  }
12074
12250
  const embeddingMs = import_perf_hooks.performance.now() - embeddingStartTime;
12075
- const vectorStartTime = import_perf_hooks.performance.now();
12076
- const semanticResults = embedding ? store.search(embedding, maxResults * 4) : [];
12077
- const vectorMs = import_perf_hooks.performance.now() - vectorStartTime;
12078
- const keywordStartTime = import_perf_hooks.performance.now();
12079
- const keywordResults = await this.keywordSearch(query, maxResults * 4, store, invertedIndex);
12080
- const keywordMs = import_perf_hooks.performance.now() - keywordStartTime;
12251
+ const prefilterStartTime = import_perf_hooks.performance.now();
12081
12252
  let branchChunkIds = null;
12082
12253
  let branchSymbolIds = null;
12083
12254
  if (filterByBranch && (this.config.scope === "global" || this.currentBranch !== "default")) {
@@ -12085,35 +12256,38 @@ var Indexer = class _Indexer {
12085
12256
  branchChunkIds = new Set(branchCatalogKeys.flatMap((branchKey) => database.getBranchChunkIds(branchKey)));
12086
12257
  branchSymbolIds = new Set(branchCatalogKeys.flatMap((branchKey) => database.getBranchSymbolIds(branchKey)));
12087
12258
  }
12088
- const prefilterStartTime = import_perf_hooks.performance.now();
12089
- const shouldPrefilterByBranch = branchChunkIds !== null && (this.config.scope === "global" || branchChunkIds.size > 0);
12090
- const allowBranchPrefilterFallback = this.config.scope !== "global";
12091
- const prefilteredSemantic = shouldPrefilterByBranch && branchChunkIds ? semanticResults.filter((r) => branchChunkIds.has(r.id)) : semanticResults;
12092
- const prefilteredKeyword = shouldPrefilterByBranch && branchChunkIds ? keywordResults.filter((r) => branchChunkIds.has(r.id)) : keywordResults;
12093
- const semanticCandidates = allowBranchPrefilterFallback && shouldPrefilterByBranch && semanticResults.length > 0 && prefilteredSemantic.length === 0 ? semanticResults : prefilteredSemantic;
12094
- const keywordCandidates = allowBranchPrefilterFallback && shouldPrefilterByBranch && keywordResults.length > 0 && prefilteredKeyword.length === 0 ? keywordResults : prefilteredKeyword;
12259
+ const { hasInitializedBranchCatalog, shouldPrefilterByBranch } = this.getBranchPrefilterState(database, branchChunkIds);
12260
+ const prefilterMs = import_perf_hooks.performance.now() - prefilterStartTime;
12261
+ const vectorStartTime = import_perf_hooks.performance.now();
12262
+ const semanticCandidates = embedding ? this.searchSemanticCandidates(
12263
+ store,
12264
+ embedding,
12265
+ maxResults * 4,
12266
+ branchChunkIds,
12267
+ shouldPrefilterByBranch
12268
+ ) : [];
12269
+ const vectorMs = import_perf_hooks.performance.now() - vectorStartTime;
12270
+ const keywordStartTime = import_perf_hooks.performance.now();
12271
+ const keywordCandidates = await this.keywordSearch(
12272
+ query,
12273
+ maxResults * 4,
12274
+ store,
12275
+ invertedIndex,
12276
+ branchChunkIds,
12277
+ shouldPrefilterByBranch
12278
+ );
12279
+ const keywordMs = import_perf_hooks.performance.now() - keywordStartTime;
12095
12280
  const scopedSemanticCandidates = semanticCandidates.filter(
12096
- (candidate) => matchesHardSearchFilters(candidate, options)
12281
+ (candidate) => matchesHardSearchFilters(candidate, options, this.projectRoot)
12097
12282
  );
12098
12283
  const scopedKeywordCandidates = keywordCandidates.filter(
12099
- (candidate) => matchesHardSearchFilters(candidate, options)
12284
+ (candidate) => matchesHardSearchFilters(candidate, options, this.projectRoot)
12100
12285
  );
12101
- const prefilterMs = import_perf_hooks.performance.now() - prefilterStartTime;
12102
- if (this.config.scope !== "global" && branchChunkIds && branchChunkIds.size === 0) {
12286
+ if (this.config.scope !== "global" && branchChunkIds && !hasInitializedBranchCatalog) {
12103
12287
  this.logger.search("warn", "Branch prefilter skipped because branch catalog is empty", {
12104
12288
  branch: this.currentBranch
12105
12289
  });
12106
12290
  }
12107
- if (allowBranchPrefilterFallback && shouldPrefilterByBranch && semanticResults.length > 0 && prefilteredSemantic.length === 0) {
12108
- this.logger.search("warn", "Branch prefilter produced no semantic overlap, using unfiltered semantic candidates", {
12109
- branch: this.currentBranch
12110
- });
12111
- }
12112
- if (allowBranchPrefilterFallback && shouldPrefilterByBranch && keywordResults.length > 0 && prefilteredKeyword.length === 0) {
12113
- this.logger.search("warn", "Branch prefilter produced no keyword overlap, using unfiltered keyword candidates", {
12114
- branch: this.currentBranch
12115
- });
12116
- }
12117
12291
  const fusionStartTime = import_perf_hooks.performance.now();
12118
12292
  const rankingHybridWeight = embedding === void 0 && fusionStrategy === "weighted" ? 1 : effectiveHybridWeight;
12119
12293
  const combined = rankHybridResults(query, scopedSemanticCandidates, scopedKeywordCandidates, {
@@ -12164,12 +12338,14 @@ var Indexer = class _Indexer {
12164
12338
  const primaryLane = mergeTieredResults(prePrimaryLane, symbolLane, maxResults * 4);
12165
12339
  const tiered = mergeTieredResults(primaryLane, rescued, maxResults * 4);
12166
12340
  const hasCodeHints = extractCodeTermHints(query).length > 0 || identifierHints.length > 0;
12167
- const baseFiltered = tiered.filter((r) => matchesSearchFilters(r, options, this.config.search.minScore));
12341
+ const baseFiltered = tiered.filter(
12342
+ (r) => matchesSearchFilters(r, options, this.config.search.minScore, this.projectRoot)
12343
+ );
12168
12344
  const implementationOnly = baseFiltered.filter(
12169
12345
  (r) => isLikelyImplementationPath2(r.metadata.filePath) && isImplementationChunkType(r.metadata.chunkType)
12170
12346
  );
12171
12347
  const filtered = (sourceIntent && hasCodeHints && implementationOnly.length > 0 ? implementationOnly : baseFiltered).slice(0, maxResults);
12172
- const identifierFallback = !options?.definitionIntent && filtered.length === 0 && identifierHints.length > 0 ? buildSymbolDefinitionLane(query, database, branchChunkIds, branchSymbolIds, maxResults, union, true).filter((r) => matchesSearchFilters(r, options, this.config.search.minScore)).slice(0, maxResults) : [];
12348
+ const identifierFallback = !options?.definitionIntent && filtered.length === 0 && identifierHints.length > 0 ? buildSymbolDefinitionLane(query, database, branchChunkIds, branchSymbolIds, maxResults, union, true).filter((r) => matchesSearchFilters(r, options, this.config.search.minScore, this.projectRoot)).slice(0, maxResults) : [];
12173
12349
  const finalResults = filtered.length > 0 ? filtered : identifierFallback;
12174
12350
  const totalSearchMs = import_perf_hooks.performance.now() - searchStartTime;
12175
12351
  this.logger.recordSearch(totalSearchMs, {
@@ -12194,10 +12370,11 @@ var Indexer = class _Indexer {
12194
12370
  let content = "";
12195
12371
  let contextStartLine = r.metadata.startLine;
12196
12372
  let contextEndLine = r.metadata.endLine;
12373
+ const resolvedFilePath = this.resolveStoredFilePath(r.metadata.filePath);
12197
12374
  if (!metadataOnly && this.config.search.includeContext) {
12198
12375
  try {
12199
12376
  const fileContent = await import_fs12.promises.readFile(
12200
- r.metadata.filePath,
12377
+ resolvedFilePath,
12201
12378
  "utf-8"
12202
12379
  );
12203
12380
  const lines = fileContent.split("\n");
@@ -12210,7 +12387,7 @@ var Indexer = class _Indexer {
12210
12387
  }
12211
12388
  }
12212
12389
  return {
12213
- filePath: r.metadata.filePath,
12390
+ filePath: resolvedFilePath,
12214
12391
  startLine: contextStartLine,
12215
12392
  endLine: contextEndLine,
12216
12393
  content,
@@ -12222,8 +12399,18 @@ var Indexer = class _Indexer {
12222
12399
  })
12223
12400
  );
12224
12401
  }
12225
- async keywordSearch(query, limit, store, invertedIndex) {
12226
- const scores = invertedIndex.search(query);
12402
+ async keywordSearch(query, limit, store, invertedIndex, branchChunkIds = null, shouldPrefilterByBranch = false) {
12403
+ const normalizedLimit = Math.max(0, Math.floor(limit));
12404
+ if (normalizedLimit === 0) return [];
12405
+ const scoreEntries = this.searchCandidatesWithBranchPrefilter(
12406
+ normalizedLimit,
12407
+ invertedIndex.getDocumentCount(),
12408
+ branchChunkIds,
12409
+ shouldPrefilterByBranch,
12410
+ (requestedLimit) => Array.from(invertedIndex.search(query, requestedLimit)),
12411
+ ([chunkId]) => chunkId
12412
+ );
12413
+ const scores = new Map(scoreEntries);
12227
12414
  if (scores.size === 0) {
12228
12415
  return [];
12229
12416
  }
@@ -12237,7 +12424,7 @@ var Indexer = class _Indexer {
12237
12424
  }
12238
12425
  }
12239
12426
  results.sort((a, b) => b.score - a.score);
12240
- return results.slice(0, limit);
12427
+ return results.slice(0, normalizedLimit);
12241
12428
  }
12242
12429
  async getStatus() {
12243
12430
  const { store, configuredProviderInfo, database, readIssues, compatibility } = await this.ensureInitialized();
@@ -12304,7 +12491,7 @@ var Indexer = class _Indexer {
12304
12491
  );
12305
12492
  const currentFileHashes = /* @__PURE__ */ new Map();
12306
12493
  for (const file of files) {
12307
- currentFileHashes.set(this.toCanonicalFilePath(file.path), hashFile(file.path));
12494
+ currentFileHashes.set(this.toStoredFilePath(file.path), hashFile(file.path));
12308
12495
  }
12309
12496
  const scopedRoots = this.config.scope === "global" ? this.getScopedRoots() : null;
12310
12497
  const cachedFileHashes = scopedRoots ? new Map(Array.from(this.fileHashCache).filter(([filePath]) => this.isFileInCurrentScope(filePath, scopedRoots))) : this.fileHashCache;
@@ -12316,17 +12503,7 @@ var Indexer = class _Indexer {
12316
12503
  return { readable: true, current: false, reason: "files-changed" };
12317
12504
  }
12318
12505
  }
12319
- const hasSwiftFiles = Array.from(currentFileHashes.keys()).some(
12320
- (filePath) => path18.extname(filePath).toLowerCase() === ".swift"
12321
- );
12322
- const hasMetalFiles = Array.from(currentFileHashes.keys()).some(
12323
- (filePath) => path18.extname(filePath).toLowerCase() === ".metal"
12324
- );
12325
- const hasCallGraphMigrationFiles = Array.from(currentFileHashes.keys()).some((filePath) => {
12326
- const extension = path18.extname(filePath).toLowerCase();
12327
- return extension === ".php" || extension === ".c" || extension === ".cc" || extension === ".cpp" || extension === ".cxx";
12328
- });
12329
- if (hasSwiftFiles && database.getMetadata(this.getSwiftParserVersionMetadataKey()) !== SWIFT_PARSER_VERSION || hasMetalFiles && database.getMetadata(this.getMetalParserVersionMetadataKey()) !== METAL_PARSER_VERSION || database.getMetadata(this.getSymbolExtractorVersionMetadataKey()) !== SYMBOL_EXTRACTOR_VERSION || hasCallGraphMigrationFiles && database.getMetadata(this.getCallGraphResolutionMetadataKey()) !== CALL_GRAPH_RESOLUTION_VERSION) {
12506
+ if (!this.areBranchMigrationVersionsCurrent(database)) {
12330
12507
  return { readable: true, current: false, reason: "migration-required" };
12331
12508
  }
12332
12509
  if (isGitRepo(this.materializedProjectRoot)) {
@@ -12386,6 +12563,7 @@ var Indexer = class _Indexer {
12386
12563
  this.deleteBranchCommitMetadata(database, clearedBranchKeys2);
12387
12564
  this.saveFailedBatches([]);
12388
12565
  database.deleteMetadata("index.version");
12566
+ database.deleteMetadata("index.pathStorageVersion");
12389
12567
  database.deleteMetadata("index.embeddingProvider");
12390
12568
  database.deleteMetadata("index.embeddingModel");
12391
12569
  database.deleteMetadata("index.embeddingDimensions");
@@ -12404,7 +12582,7 @@ var Indexer = class _Indexer {
12404
12582
  this.indexCompatibility = compatibility;
12405
12583
  return;
12406
12584
  }
12407
- if (!this.isLocalProjectIndexPath()) {
12585
+ if (!this.isProjectOwnedIndexPath()) {
12408
12586
  throw new Error(
12409
12587
  "Project-scoped force rebuild is unsafe while using an inherited worktree index. Create a local project config boundary before clearing the index."
12410
12588
  );
@@ -12415,11 +12593,11 @@ var Indexer = class _Indexer {
12415
12593
  invertedIndex.clear();
12416
12594
  this.saveInvertedIndex(invertedIndex);
12417
12595
  this.fileHashCache.clear();
12418
- this.saveFileHashCache();
12596
+ await this.removeProjectRuntimeStateArtifacts();
12419
12597
  database.clearAllIndexedData();
12420
12598
  this.deleteBranchCommitMetadata(database, clearedBranchKeys);
12421
- this.saveFailedBatches([]);
12422
12599
  database.deleteMetadata("index.version");
12600
+ database.deleteMetadata("index.pathStorageVersion");
12423
12601
  database.deleteMetadata("index.embeddingProvider");
12424
12602
  database.deleteMetadata("index.embeddingModel");
12425
12603
  database.deleteMetadata("index.embeddingDimensions");
@@ -12447,32 +12625,46 @@ var Indexer = class _Indexer {
12447
12625
  existing.push(key);
12448
12626
  filePathsToChunkKeys.set(metadata.filePath, existing);
12449
12627
  }
12450
- const removedFilePaths = [];
12451
- const removedChunkKeys = [];
12628
+ const missingStoredFilePaths = [];
12629
+ const missingChunkKeys = [];
12452
12630
  const chunkKeysByRemovedFile = /* @__PURE__ */ new Map();
12453
12631
  for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
12454
- if (!(0, import_fs12.existsSync)(filePath)) {
12632
+ if (!(0, import_fs12.existsSync)(this.toMaterializedFilePath(filePath))) {
12455
12633
  chunkKeysByRemovedFile.set(filePath, chunkKeys);
12456
12634
  for (const key of chunkKeys) {
12457
- removedChunkKeys.push(key);
12635
+ missingChunkKeys.push(key);
12458
12636
  }
12459
- removedFilePaths.push(filePath);
12637
+ missingStoredFilePaths.push(filePath);
12460
12638
  }
12461
12639
  }
12640
+ const branchCatalogKeys = this.getBranchCatalogKeys();
12641
+ for (const branchKey of branchCatalogKeys) {
12642
+ database.deleteBranchChunksForBranch(branchKey, missingChunkKeys);
12643
+ }
12644
+ const referencedChunkKeys = new Set(database.getReferencedChunkIds(missingChunkKeys));
12645
+ const removedChunkKeys = missingChunkKeys.filter((key) => !referencedChunkKeys.has(key));
12462
12646
  if (removedChunkKeys.length > 0) {
12463
12647
  this.rebuildVectorStoreExcludingChunkIds(store, database, removedChunkKeys);
12464
12648
  for (const key of removedChunkKeys) {
12465
12649
  invertedIndex.removeChunk(key);
12466
12650
  }
12651
+ database.deleteChunksByIds(removedChunkKeys);
12467
12652
  }
12468
- for (const filePath of removedFilePaths) {
12469
- const fileChunkKeys = chunkKeysByRemovedFile.get(filePath) ?? [];
12470
- if (fileChunkKeys.length > 0) {
12471
- database.deleteChunksByIds(fileChunkKeys);
12472
- }
12473
- database.deleteCallEdgesByFile(filePath);
12474
- database.deleteSymbolsByFile(filePath);
12475
- }
12653
+ const missingSymbolIds = Array.from(new Set(
12654
+ missingStoredFilePaths.flatMap(
12655
+ (filePath) => database.getSymbolsByFile(filePath).map((symbol) => symbol.id)
12656
+ )
12657
+ ));
12658
+ for (const branchKey of branchCatalogKeys) {
12659
+ database.deleteBranchSymbolsForBranch(branchKey, missingSymbolIds);
12660
+ }
12661
+ const referencedSymbolIds = new Set(database.getReferencedSymbolIds(missingSymbolIds));
12662
+ const removedSymbolIds = missingSymbolIds.filter((symbolId) => !referencedSymbolIds.has(symbolId));
12663
+ database.clearCallEdgeTargetsForSymbols(removedSymbolIds);
12664
+ const removedChunkKeySet = new Set(removedChunkKeys);
12665
+ const removedStoredFilePaths = missingStoredFilePaths.filter(
12666
+ (filePath) => (chunkKeysByRemovedFile.get(filePath) ?? []).some((key) => removedChunkKeySet.has(key))
12667
+ );
12476
12668
  const removedCount = removedChunkKeys.length;
12477
12669
  if (removedCount > 0) {
12478
12670
  store.save();
@@ -12508,9 +12700,16 @@ var Indexer = class _Indexer {
12508
12700
  removedStale: removedCount,
12509
12701
  orphanEmbeddings: gcOrphanEmbeddings,
12510
12702
  orphanChunks: gcOrphanChunks,
12511
- removedFiles: removedFilePaths.length
12703
+ removedFiles: removedStoredFilePaths.length
12512
12704
  });
12513
- return { removed: removedCount, filePaths: removedFilePaths, gcOrphanEmbeddings, gcOrphanChunks, gcOrphanSymbols, gcOrphanCallEdges };
12705
+ return {
12706
+ removed: removedCount,
12707
+ filePaths: removedStoredFilePaths.map((filePath) => this.resolveStoredFilePath(filePath)),
12708
+ gcOrphanEmbeddings,
12709
+ gcOrphanChunks,
12710
+ gcOrphanSymbols,
12711
+ gcOrphanCallEdges
12712
+ };
12514
12713
  }
12515
12714
  async retryFailedBatches() {
12516
12715
  return this.withIndexMutationLease("retry-failed-batches", async (recoveredOwners) => {
@@ -12705,9 +12904,18 @@ var Indexer = class _Indexer {
12705
12904
  return this.baseBranch;
12706
12905
  }
12707
12906
  refreshBranchInfo() {
12907
+ const previousBranch = this.currentBranch;
12708
12908
  if (isGitRepo(this.materializedProjectRoot)) {
12709
12909
  this.currentBranch = this.branchNameOverride ?? getBranchOrDefault(this.materializedProjectRoot);
12710
12910
  this.baseBranch = getBaseBranch(this.materializedProjectRoot);
12911
+ } else {
12912
+ this.currentBranch = "default";
12913
+ this.baseBranch = "default";
12914
+ }
12915
+ if (this.currentBranch !== previousBranch) {
12916
+ this.refreshRuntimeArtifactPaths();
12917
+ this.fileHashCache.clear();
12918
+ this.loadFileHashCache();
12711
12919
  }
12712
12920
  }
12713
12921
  async getDatabaseStats() {
@@ -12732,6 +12940,7 @@ var Indexer = class _Indexer {
12732
12940
  return [];
12733
12941
  }
12734
12942
  const filterByBranch = options?.filterByBranch ?? true;
12943
+ const excludedStoredFile = options?.excludeFile ? this.toStoredFilePath(options.excludeFile) : void 0;
12735
12944
  this.logger.search("debug", "Starting find similar", {
12736
12945
  codeLength: code.length,
12737
12946
  limit,
@@ -12741,31 +12950,29 @@ var Indexer = class _Indexer {
12741
12950
  const { embedding, tokensUsed } = await provider.embedDocument(code);
12742
12951
  const embeddingMs = import_perf_hooks.performance.now() - embeddingStartTime;
12743
12952
  this.logger.recordEmbeddingApiCall(tokensUsed);
12744
- const vectorStartTime = import_perf_hooks.performance.now();
12745
- const semanticResults = store.search(embedding, limit * 2);
12746
- const vectorMs = import_perf_hooks.performance.now() - vectorStartTime;
12953
+ const prefilterStartTime = import_perf_hooks.performance.now();
12747
12954
  let branchChunkIds = null;
12748
12955
  if (filterByBranch && (this.config.scope === "global" || this.currentBranch !== "default")) {
12749
12956
  branchChunkIds = new Set(
12750
12957
  this.getBranchCatalogKeys().flatMap((branchKey) => database.getBranchChunkIds(branchKey))
12751
12958
  );
12752
12959
  }
12753
- const prefilterStartTime = import_perf_hooks.performance.now();
12754
- const shouldPrefilterByBranch = branchChunkIds !== null && (this.config.scope === "global" || branchChunkIds.size > 0);
12755
- const allowBranchPrefilterFallback = this.config.scope !== "global";
12756
- const prefilteredSemantic = shouldPrefilterByBranch && branchChunkIds ? semanticResults.filter((r) => branchChunkIds.has(r.id)) : semanticResults;
12757
- const semanticCandidates = allowBranchPrefilterFallback && shouldPrefilterByBranch && semanticResults.length > 0 && prefilteredSemantic.length === 0 ? semanticResults : prefilteredSemantic;
12960
+ const { hasInitializedBranchCatalog, shouldPrefilterByBranch } = this.getBranchPrefilterState(database, branchChunkIds);
12758
12961
  const prefilterMs = import_perf_hooks.performance.now() - prefilterStartTime;
12759
- if (this.config.scope !== "global" && branchChunkIds && branchChunkIds.size === 0) {
12962
+ const vectorStartTime = import_perf_hooks.performance.now();
12963
+ const semanticCandidates = this.searchSemanticCandidates(
12964
+ store,
12965
+ embedding,
12966
+ limit * 2,
12967
+ branchChunkIds,
12968
+ shouldPrefilterByBranch
12969
+ );
12970
+ const vectorMs = import_perf_hooks.performance.now() - vectorStartTime;
12971
+ if (this.config.scope !== "global" && branchChunkIds && !hasInitializedBranchCatalog) {
12760
12972
  this.logger.search("warn", "Branch prefilter skipped because branch catalog is empty", {
12761
12973
  branch: this.currentBranch
12762
12974
  });
12763
12975
  }
12764
- if (allowBranchPrefilterFallback && shouldPrefilterByBranch && semanticResults.length > 0 && prefilteredSemantic.length === 0) {
12765
- this.logger.search("warn", "Branch prefilter produced no semantic overlap, using unfiltered semantic candidates", {
12766
- branch: this.currentBranch
12767
- });
12768
- }
12769
12976
  const rerankTopN = this.config.search.rerankTopN;
12770
12977
  const ranked = rankSemanticOnlyResults(code, semanticCandidates, {
12771
12978
  rerankTopN,
@@ -12774,21 +12981,10 @@ var Indexer = class _Indexer {
12774
12981
  });
12775
12982
  const filtered = ranked.filter((r) => {
12776
12983
  if (r.score < this.config.search.minScore) return false;
12777
- if (options?.excludeFile) {
12778
- if (r.metadata.filePath === options.excludeFile) return false;
12779
- }
12780
- if (options?.fileType) {
12781
- const ext = r.metadata.filePath.split(".").pop()?.toLowerCase();
12782
- if (ext !== options.fileType.toLowerCase().replace(/^\./, "")) return false;
12783
- }
12784
- if (options?.directory) {
12785
- const normalizedDir = options.directory.replace(/^\/|\/$/g, "");
12786
- if (!r.metadata.filePath.includes(`/${normalizedDir}/`) && !r.metadata.filePath.includes(`${normalizedDir}/`)) return false;
12787
- }
12788
- if (options?.chunkType) {
12789
- if (r.metadata.chunkType !== options.chunkType) return false;
12984
+ if (excludedStoredFile) {
12985
+ if (r.metadata.filePath === excludedStoredFile) return false;
12790
12986
  }
12791
- return true;
12987
+ return matchesHardSearchFilters(r, options, this.projectRoot);
12792
12988
  }).slice(0, limit);
12793
12989
  const totalSearchMs = import_perf_hooks.performance.now() - searchStartTime;
12794
12990
  this.logger.recordSearch(totalSearchMs, {
@@ -12808,10 +13004,11 @@ var Indexer = class _Indexer {
12808
13004
  return Promise.all(
12809
13005
  filtered.map(async (r) => {
12810
13006
  let content = "";
13007
+ const resolvedFilePath = this.resolveStoredFilePath(r.metadata.filePath);
12811
13008
  if (this.config.search.includeContext) {
12812
13009
  try {
12813
13010
  const fileContent = await import_fs12.promises.readFile(
12814
- r.metadata.filePath,
13011
+ resolvedFilePath,
12815
13012
  "utf-8"
12816
13013
  );
12817
13014
  const lines = fileContent.split("\n");
@@ -12821,7 +13018,7 @@ var Indexer = class _Indexer {
12821
13018
  }
12822
13019
  }
12823
13020
  return {
12824
- filePath: r.metadata.filePath,
13021
+ filePath: resolvedFilePath,
12825
13022
  startLine: r.metadata.startLine,
12826
13023
  endLine: r.metadata.endLine,
12827
13024
  content,
@@ -12842,7 +13039,7 @@ var Indexer = class _Indexer {
12842
13039
  for (const edge of database.getCallersWithContext(targetName, branchKey, callTypeFilter)) {
12843
13040
  if (!seen.has(edge.id)) {
12844
13041
  seen.add(edge.id);
12845
- results.push(edge);
13042
+ results.push(this.resolveCallEdgeFilePath(edge));
12846
13043
  }
12847
13044
  }
12848
13045
  }
@@ -12861,7 +13058,7 @@ var Indexer = class _Indexer {
12861
13058
  const safelyMatchesUnresolvedSymbol = includeUnresolved && !edge.toSymbolId;
12862
13059
  if (!matchesResolvedSymbol && !safelyMatchesUnresolvedSymbol || seen.has(edge.id)) continue;
12863
13060
  seen.add(edge.id);
12864
- results.push(edge);
13061
+ results.push(this.resolveCallEdgeFilePath(edge));
12865
13062
  }
12866
13063
  }
12867
13064
  return results;
@@ -12875,7 +13072,7 @@ var Indexer = class _Indexer {
12875
13072
  for (const edge of database.getCallees(symbolId, branchKey, callTypeFilter)) {
12876
13073
  if (!seen.has(edge.id)) {
12877
13074
  seen.add(edge.id);
12878
- results.push(edge);
13075
+ results.push(this.resolveCallEdgeFilePath(edge));
12879
13076
  }
12880
13077
  }
12881
13078
  }
@@ -12891,7 +13088,7 @@ var Indexer = class _Indexer {
12891
13088
  shortest = path27;
12892
13089
  }
12893
13090
  }
12894
- return shortest;
13091
+ return shortest.map((hop) => this.resolveFilePathRecord(hop));
12895
13092
  }
12896
13093
  async findCallPathBySymbolIds(fromSymbolId, toSymbolId, maxDepth = 10) {
12897
13094
  const { database, readIssues } = await this.ensureInitialized();
@@ -12957,7 +13154,7 @@ var Indexer = class _Indexer {
12957
13154
  shortest = path27;
12958
13155
  }
12959
13156
  }
12960
- return shortest;
13157
+ return shortest.map((hop) => this.resolveFilePathRecord(hop));
12961
13158
  }
12962
13159
  async getCallGraphSymbols() {
12963
13160
  const { database, readIssues } = await this.ensureInitialized();
@@ -12965,7 +13162,7 @@ var Indexer = class _Indexer {
12965
13162
  const symbols = /* @__PURE__ */ new Map();
12966
13163
  for (const branchKey of this.getBranchCatalogKeys()) {
12967
13164
  for (const symbol of database.getSymbolsForBranch(branchKey)) {
12968
- symbols.set(symbol.id, symbol);
13165
+ symbols.set(symbol.id, this.resolveFilePathRecord(symbol));
12969
13166
  }
12970
13167
  }
12971
13168
  return [...symbols.values()];
@@ -12974,31 +13171,32 @@ var Indexer = class _Indexer {
12974
13171
  const { database, readIssues } = await this.ensureInitialized();
12975
13172
  this.requireReadableComponents(readIssues, "database");
12976
13173
  const resolvedBranch = branch ?? this.getBranchCatalogKey();
12977
- return database.getSymbolsForBranch(resolvedBranch);
13174
+ return database.getSymbolsForBranch(resolvedBranch).map((symbol) => this.resolveFilePathRecord(symbol));
12978
13175
  }
12979
13176
  async getSymbolsForFiles(filePaths, branch) {
12980
13177
  const { database, readIssues } = await this.ensureInitialized();
12981
13178
  this.requireReadableComponents(readIssues, "database");
12982
13179
  const resolvedBranch = branch ?? this.getBranchCatalogKey();
12983
- return database.getSymbolsForFiles(filePaths, resolvedBranch);
13180
+ const storedFilePaths = filePaths.map((filePath) => this.toStoredFilePath(filePath));
13181
+ return database.getSymbolsForFiles(storedFilePaths, resolvedBranch).map((symbol) => this.resolveFilePathRecord(symbol));
12984
13182
  }
12985
13183
  async getTransitiveReachability(rootSymbolIds, direction, maxDepth) {
12986
13184
  const { database, readIssues } = await this.ensureInitialized();
12987
13185
  this.requireReadableComponents(readIssues, "database");
12988
13186
  const branch = this.getBranchCatalogKey();
12989
- return database.getTransitiveReachability(rootSymbolIds, branch, direction, maxDepth);
13187
+ return database.getTransitiveReachability(rootSymbolIds, branch, direction, maxDepth).map((entry) => this.resolveFilePathRecord(entry));
12990
13188
  }
12991
13189
  async detectCommunities(branch, symbolIds) {
12992
13190
  const { database, readIssues } = await this.ensureInitialized();
12993
13191
  this.requireReadableComponents(readIssues, "database");
12994
13192
  const resolvedBranch = branch ?? this.getBranchCatalogKey();
12995
- return database.detectCommunities(resolvedBranch, symbolIds);
13193
+ return database.detectCommunities(resolvedBranch, symbolIds).map((entry) => this.resolveFilePathRecord(entry));
12996
13194
  }
12997
13195
  async computeCentrality(branch) {
12998
13196
  const { database, readIssues } = await this.ensureInitialized();
12999
13197
  this.requireReadableComponents(readIssues, "database");
13000
13198
  const resolvedBranch = branch ?? this.getBranchCatalogKey();
13001
- return database.computeCentrality(resolvedBranch);
13199
+ return database.computeCentrality(resolvedBranch).map((entry) => this.resolveFilePathRecord(entry));
13002
13200
  }
13003
13201
  async getPrImpact(opts, onPreparationProgress) {
13004
13202
  const initialState = await this.ensureInitialized();
@@ -13034,10 +13232,8 @@ var Indexer = class _Indexer {
13034
13232
  const requestedRef = opts.pr !== void 0 ? expectedCommit : headRefName ?? resolvedBranch;
13035
13233
  const storedCommit = this.getStoredBranchCommit(database, catalogIdentity);
13036
13234
  const catalogIdentityMatches = storedCommit === expectedCommit;
13037
- const symbolsCurrent = database.getMetadata(
13038
- this.getSymbolExtractorVersionMetadataKey(catalogIdentity)
13039
- ) === SYMBOL_EXTRACTOR_VERSION;
13040
- if (branchSymbols.length === 0 || !catalogIdentityMatches || !symbolsCurrent) {
13235
+ const migrationsCurrent = this.areBranchMigrationVersionsCurrent(database, catalogIdentity);
13236
+ if (branchSymbols.length === 0 || !catalogIdentityMatches || !migrationsCurrent) {
13041
13237
  if (!resolvedBranch || resolvedBranch === "default") {
13042
13238
  throw new Error("Run index_codebase first to build the call graph and symbol index for this project.");
13043
13239
  }
@@ -13093,8 +13289,9 @@ var Indexer = class _Indexer {
13093
13289
  );
13094
13290
  }
13095
13291
  }
13096
- const absoluteChangedFiles = changedFiles.map((f) => path18.resolve(this.projectRoot, f));
13097
- const directSymbols = database.getSymbolsForFiles(absoluteChangedFiles, branchKey);
13292
+ const toStoredChangedFiles = (filePaths) => filePaths.map((filePath) => this.toStoredFilePath(path18.resolve(this.projectRoot, filePath)));
13293
+ const storedChangedFiles = toStoredChangedFiles(changedFiles);
13294
+ const directSymbols = database.getSymbolsForFiles(storedChangedFiles, branchKey);
13098
13295
  const directIds = directSymbols.map((s) => s.id);
13099
13296
  const direction = opts.direction ?? "both";
13100
13297
  const maxDepth = opts.maxDepth ?? 5;
@@ -13136,7 +13333,7 @@ var Indexer = class _Indexer {
13136
13333
  id: c.symbolId,
13137
13334
  name: c.symbolName,
13138
13335
  callerCount: c.callerCount,
13139
- filePath: c.filePath
13336
+ filePath: this.resolveStoredFilePath(c.filePath)
13140
13337
  }));
13141
13338
  const totalAffected = allAffectedIds.length;
13142
13339
  let riskLevel;
@@ -13176,9 +13373,9 @@ var Indexer = class _Indexer {
13176
13373
  projectRoot: this.projectRoot,
13177
13374
  baseBranch: this.baseBranch
13178
13375
  });
13179
- const otherAbsolute = otherChanged.files.map((f) => path18.resolve(this.projectRoot, f));
13376
+ const otherStored = toStoredChangedFiles(otherChanged.files);
13180
13377
  const prBranchKey = this.getBranchCatalogKeyFor(otherChanged.catalogIdentity);
13181
- const otherSymbols = database.getSymbolsForFiles(otherAbsolute, prBranchKey);
13378
+ const otherSymbols = database.getSymbolsForFiles(otherStored, prBranchKey);
13182
13379
  const otherLabels = /* @__PURE__ */ new Set();
13183
13380
  for (const sym of otherSymbols) {
13184
13381
  const label = symbolToCommunity.get(structuralKey(sym.filePath, sym.name));
@@ -13209,12 +13406,12 @@ var Indexer = class _Indexer {
13209
13406
  id: s.id,
13210
13407
  name: s.name,
13211
13408
  kind: s.kind,
13212
- filePath: s.filePath
13409
+ filePath: this.resolveStoredFilePath(s.filePath)
13213
13410
  })),
13214
13411
  transitiveCallers: transitiveCallers.map((c) => ({
13215
13412
  id: c.symbolId,
13216
13413
  name: c.symbolName,
13217
- filePath: c.filePath,
13414
+ filePath: this.resolveStoredFilePath(c.filePath),
13218
13415
  depth: c.depth
13219
13416
  })),
13220
13417
  totalAffected,
@@ -13244,7 +13441,7 @@ var Indexer = class _Indexer {
13244
13441
  const absoluteDirectoryFilter = directory ? path18.resolve(this.projectRoot, directory) : void 0;
13245
13442
  for (const filePath of filePaths) {
13246
13443
  if (directory) {
13247
- const absoluteFilePath = path18.resolve(filePath);
13444
+ const absoluteFilePath = this.resolveStoredFilePath(filePath);
13248
13445
  const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
13249
13446
  const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path18.sep));
13250
13447
  if (!matchesRelative && !matchesProjectRelative) {
@@ -13253,14 +13450,14 @@ var Indexer = class _Indexer {
13253
13450
  }
13254
13451
  for (const sym of database.getSymbolsByFile(filePath)) {
13255
13452
  if (symbolIdSet.has(sym.id) && !seenSymbols.has(sym.id)) {
13256
- seenSymbols.set(sym.id, sym);
13453
+ seenSymbols.set(sym.id, this.resolveFilePathRecord(sym));
13257
13454
  }
13258
13455
  }
13259
13456
  }
13260
13457
  for (const symbolId of seenSymbols.keys()) {
13261
13458
  for (const edge of database.getCallees(symbolId, branchKey)) {
13262
13459
  if (!seenEdges.has(edge.id)) {
13263
- seenEdges.set(edge.id, edge);
13460
+ seenEdges.set(edge.id, this.resolveCallEdgeFilePath(edge));
13264
13461
  }
13265
13462
  }
13266
13463
  }
@@ -13367,14 +13564,14 @@ function getOrCreateIndexer(projectRoot, host) {
13367
13564
  configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
13368
13565
  return indexer;
13369
13566
  }
13370
- function initializeTools(projectRoot, config, host = "opencode") {
13567
+ function initializeTools(projectRoot, config, host) {
13371
13568
  defaultProjectRoots.set(host, projectRoot);
13372
13569
  const key = getIndexerCacheKey(projectRoot, host);
13373
13570
  configCache.set(key, config);
13374
13571
  indexerCache.set(key, new Indexer(projectRoot, config, host));
13375
13572
  configureAutoIndex(projectRoot, host, config, () => getOrCreateIndexer(projectRoot, host));
13376
13573
  }
13377
- function getIndexerForProject(projectRoot, host = "opencode") {
13574
+ function getIndexerForProject(projectRoot, host) {
13378
13575
  const root = getProjectRoot(projectRoot, host);
13379
13576
  return getOrCreateIndexer(root, host);
13380
13577
  }
@@ -13382,7 +13579,7 @@ function recordToolEffectiveness(projectRoot, host, event) {
13382
13579
  if (!isToolEffectivenessEnabled(projectRoot, host)) return;
13383
13580
  safelyRecordToolEffectiveness(event);
13384
13581
  }
13385
- function refreshIndexerForDirectory(projectRoot, host = "opencode", config = parseConfig(loadRuntimeConfig(projectRoot, host))) {
13582
+ function refreshIndexerForDirectory(projectRoot, host, config = parseConfig(loadRuntimeConfig(projectRoot, host))) {
13386
13583
  const key = getIndexerCacheKey(projectRoot, host);
13387
13584
  configCache.set(key, config);
13388
13585
  indexerCache.set(key, new Indexer(projectRoot, config, host));
@@ -13890,6 +14087,9 @@ Run /index to rebuild the index without the removed knowledge base.`;
13890
14087
  return result;
13891
14088
  }
13892
14089
 
14090
+ // src/watcher/file-watcher.ts
14091
+ var import_fs14 = require("fs");
14092
+
13893
14093
  // node_modules/chokidar/index.js
13894
14094
  var import_node_events = require("events");
13895
14095
  var import_node_fs2 = require("fs");
@@ -14057,10 +14257,10 @@ var ReaddirpStream = class extends import_node_stream.Readable {
14057
14257
  }
14058
14258
  async _formatEntry(dirent, path27) {
14059
14259
  let entry;
14060
- const basename7 = this._isDirent ? dirent.name : dirent;
14260
+ const basename8 = this._isDirent ? dirent.name : dirent;
14061
14261
  try {
14062
- const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path27, basename7));
14063
- entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename7 };
14262
+ const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path27, basename8));
14263
+ entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename8 };
14064
14264
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
14065
14265
  } catch (err) {
14066
14266
  this._onError(err);
@@ -14601,9 +14801,9 @@ var NodeFsHandler = class {
14601
14801
  _watchWithNodeFs(path27, listener) {
14602
14802
  const opts = this.fsw.options;
14603
14803
  const directory = sp.dirname(path27);
14604
- const basename7 = sp.basename(path27);
14804
+ const basename8 = sp.basename(path27);
14605
14805
  const parent = this.fsw._getWatchedDir(directory);
14606
- parent.add(basename7);
14806
+ parent.add(basename8);
14607
14807
  const absolutePath = sp.resolve(path27);
14608
14808
  const options = {
14609
14809
  persistent: opts.persistent
@@ -14613,7 +14813,7 @@ var NodeFsHandler = class {
14613
14813
  let closer;
14614
14814
  if (opts.usePolling) {
14615
14815
  const enableBin = opts.interval !== opts.binaryInterval;
14616
- options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
14816
+ options.interval = enableBin && isBinaryPath(basename8) ? opts.binaryInterval : opts.interval;
14617
14817
  closer = setFsWatchFileListener(path27, absolutePath, options, {
14618
14818
  listener,
14619
14819
  rawEmitter: this.fsw._emitRaw
@@ -14635,11 +14835,11 @@ var NodeFsHandler = class {
14635
14835
  if (this.fsw.closed) {
14636
14836
  return;
14637
14837
  }
14638
- const dirname13 = sp.dirname(file);
14639
- const basename7 = sp.basename(file);
14640
- const parent = this.fsw._getWatchedDir(dirname13);
14838
+ const dirname14 = sp.dirname(file);
14839
+ const basename8 = sp.basename(file);
14840
+ const parent = this.fsw._getWatchedDir(dirname14);
14641
14841
  let prevStats = stats;
14642
- if (parent.has(basename7))
14842
+ if (parent.has(basename8))
14643
14843
  return;
14644
14844
  const listener = async (path27, newStats) => {
14645
14845
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
@@ -14664,9 +14864,9 @@ var NodeFsHandler = class {
14664
14864
  prevStats = newStats2;
14665
14865
  }
14666
14866
  } catch (error) {
14667
- this.fsw._remove(dirname13, basename7);
14867
+ this.fsw._remove(dirname14, basename8);
14668
14868
  }
14669
- } else if (parent.has(basename7)) {
14869
+ } else if (parent.has(basename8)) {
14670
14870
  const at = newStats.atimeMs;
14671
14871
  const mt = newStats.mtimeMs;
14672
14872
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -15628,8 +15828,8 @@ var FileWatcher = class {
15628
15828
  watcher = null;
15629
15829
  projectRoot;
15630
15830
  config;
15631
- host;
15632
15831
  configPath;
15832
+ projectConfigPaths;
15633
15833
  pendingChanges = /* @__PURE__ */ new Map();
15634
15834
  debounceTimer = null;
15635
15835
  debounceMs = 1e3;
@@ -15638,11 +15838,11 @@ var FileWatcher = class {
15638
15838
  resolveReady = null;
15639
15839
  pollingFallbackAttempted = false;
15640
15840
  pendingClose = null;
15641
- constructor(projectRoot, config, host = "opencode", options = {}) {
15841
+ constructor(projectRoot, config, host, options = {}) {
15642
15842
  this.projectRoot = projectRoot;
15643
15843
  this.config = config;
15644
- this.host = host;
15645
15844
  this.configPath = options.configPath;
15845
+ this.projectConfigPaths = options.configPath ? [options.configPath] : getProjectConfigCandidatePaths(projectRoot, host);
15646
15846
  }
15647
15847
  start(handler) {
15648
15848
  if (this.watcher) {
@@ -15660,7 +15860,19 @@ var FileWatcher = class {
15660
15860
  }
15661
15861
  createWatcher(usePolling = false) {
15662
15862
  const ignoreFilter = createIgnoreFilter(this.projectRoot);
15663
- const watchTargets = this.configPath ? [this.projectRoot, this.configPath] : this.projectRoot;
15863
+ let watchTargets = this.projectRoot;
15864
+ if (this.configPath) {
15865
+ watchTargets = [this.projectRoot, this.configPath];
15866
+ } else {
15867
+ const externalConfigTargets = this.projectConfigPaths.filter((projectConfigPath) => {
15868
+ const relativeConfigPath = path20.relative(this.projectRoot, projectConfigPath);
15869
+ return this.isOutsideProjectPath(relativeConfigPath);
15870
+ }).map((projectConfigPath) => (0, import_fs14.existsSync)(projectConfigPath) ? projectConfigPath : this.getNearestExistingDirectory(path20.dirname(projectConfigPath)));
15871
+ const uniqueExternalConfigTargets = [...new Set(externalConfigTargets)];
15872
+ if (uniqueExternalConfigTargets.length > 0) {
15873
+ watchTargets = [this.projectRoot, ...uniqueExternalConfigTargets];
15874
+ }
15875
+ }
15664
15876
  const watcherOptions = {
15665
15877
  ignored: (filePath) => {
15666
15878
  const relativePath = path20.relative(this.projectRoot, filePath);
@@ -15668,6 +15880,9 @@ var FileWatcher = class {
15668
15880
  if (this.isProjectConfigPathOrAncestor(relativePath)) {
15669
15881
  return false;
15670
15882
  }
15883
+ if (this.isOutsideProjectPath(relativePath)) {
15884
+ return true;
15885
+ }
15671
15886
  if (hasFilteredPathSegment(relativePath, path20.sep)) {
15672
15887
  return true;
15673
15888
  }
@@ -15770,14 +15985,22 @@ var FileWatcher = class {
15770
15985
  (configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path20.sep}`)
15771
15986
  );
15772
15987
  }
15773
- getProjectConfigRelativePaths() {
15774
- if (this.configPath) {
15775
- return [path20.normalize(path20.relative(this.projectRoot, this.configPath))];
15988
+ isOutsideProjectPath(relativePath) {
15989
+ return relativePath === ".." || relativePath.startsWith(`..${path20.sep}`) || path20.isAbsolute(relativePath);
15990
+ }
15991
+ getNearestExistingDirectory(directoryPath) {
15992
+ let candidate = directoryPath;
15993
+ while (!(0, import_fs14.existsSync)(candidate)) {
15994
+ const parent = path20.dirname(candidate);
15995
+ if (parent === candidate) break;
15996
+ candidate = parent;
15776
15997
  }
15777
- return [
15778
- resolveProjectConfigPath(this.projectRoot, this.host),
15779
- resolveWritableProjectConfigPath(this.projectRoot, this.host)
15780
- ].map((configPath) => path20.normalize(path20.relative(this.projectRoot, configPath)));
15998
+ return candidate;
15999
+ }
16000
+ getProjectConfigRelativePaths() {
16001
+ return this.projectConfigPaths.map(
16002
+ (configPath) => path20.normalize(path20.relative(this.projectRoot, configPath))
16003
+ );
15781
16004
  }
15782
16005
  scheduleFlush() {
15783
16006
  if (this.debounceTimer) {
@@ -15904,8 +16127,9 @@ var GitHeadWatcher = class {
15904
16127
  };
15905
16128
 
15906
16129
  // src/watcher/index.ts
15907
- function createWatcherWithIndexer(getIndexer, projectRoot, config, host = "opencode", options = {}) {
16130
+ function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options = {}) {
15908
16131
  const fileWatcher = new FileWatcher(projectRoot, config, host, options);
16132
+ const configPaths = getConfigPaths(projectRoot, host, options);
15909
16133
  configureAutoIndex(projectRoot, host, parseConfig(config), getIndexer);
15910
16134
  let stopped = false;
15911
16135
  const requestReindex = () => {
@@ -15922,7 +16146,6 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host = "openc
15922
16146
  );
15923
16147
  const hasDelete = changes.some((c) => c.type === "unlink");
15924
16148
  if (hasAddOrChange || hasDelete) {
15925
- const configPaths = getConfigPaths(projectRoot, host, options);
15926
16149
  if (changes.some((change) => configPaths.includes(pathNormalize(change.path)))) {
15927
16150
  const parsedConfig = options.configPath ? parseConfig(loadConfigFile(options.configPath)) : void 0;
15928
16151
  const refreshedConfig = refreshIndexerForDirectory(projectRoot, host, parsedConfig);
@@ -15937,7 +16160,9 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host = "openc
15937
16160
  if (isGitRepo(projectRoot)) {
15938
16161
  gitWatcher = new GitHeadWatcher(projectRoot);
15939
16162
  gitWatcher.start(async (oldBranch, newBranch) => {
15940
- getIndexer().getLogger().branch("info", "Branch changed", {
16163
+ const indexer = getIndexer();
16164
+ indexer.refreshBranchInfo();
16165
+ indexer.getLogger().branch("info", "Branch changed", {
15941
16166
  oldBranch,
15942
16167
  newBranch
15943
16168
  });
@@ -15963,10 +16188,9 @@ function getConfigPaths(projectRoot, host, options) {
15963
16188
  if (options.configPath) {
15964
16189
  return [pathNormalize(options.configPath)];
15965
16190
  }
15966
- return [
15967
- resolveProjectConfigPath(projectRoot, host),
15968
- resolveWritableProjectConfigPath(projectRoot, host)
15969
- ].map((configPath) => pathNormalize(configPath));
16191
+ return getProjectConfigCandidatePaths(projectRoot, host).map(
16192
+ (configPath) => pathNormalize(configPath)
16193
+ );
15970
16194
  }
15971
16195
 
15972
16196
  // node_modules/@opencode-ai/plugin/dist/tool.js
@@ -16058,7 +16282,7 @@ function formatPrImpact(result) {
16058
16282
  return lines.join("\n");
16059
16283
  }
16060
16284
 
16061
- // src/tools/pr-impact.ts
16285
+ // src/adapters/opencode/pr-impact.ts
16062
16286
  var z2 = tool.schema;
16063
16287
  var AUTOMATIC_PREPARATION_POLICY = "Uses configured maxFileSize, maxChunksPerFile, maxDepth, and maxFilesPerDirectory guards. No separate aggregate token or cost ceiling is configured; maxDepth=-1 remains unlimited.";
16064
16288
  var pr_impact = tool({
@@ -16755,8 +16979,8 @@ async function executeCallGraphPath(projectRoot, host, args) {
16755
16979
  return { text: formatCallGraphPathResult(path27) };
16756
16980
  }
16757
16981
 
16758
- // src/tools/index.ts
16759
- var import_fs14 = require("fs");
16982
+ // src/adapters/opencode/tools.ts
16983
+ var import_fs15 = require("fs");
16760
16984
  var os7 = __toESM(require("os"), 1);
16761
16985
  var path24 = __toESM(require("path"), 1);
16762
16986
 
@@ -17463,7 +17687,7 @@ function transformForVisualization(symbols, edges, options = {}) {
17463
17687
  };
17464
17688
  }
17465
17689
 
17466
- // src/tools/index.ts
17690
+ // src/adapters/opencode/tools.ts
17467
17691
  var z3 = tool.schema;
17468
17692
  var DEFAULT_HOST = "opencode";
17469
17693
  var CHUNK_TYPE_VALUES = CHUNK_TYPES;
@@ -17710,7 +17934,7 @@ var index_visualize = tool({
17710
17934
  }
17711
17935
  const html = generateVisualizationHtml(vizData);
17712
17936
  const outputPath = path24.join(os7.tmpdir(), `call-graph-${Date.now()}.html`);
17713
- (0, import_fs14.writeFileSync)(outputPath, html, "utf-8");
17937
+ (0, import_fs15.writeFileSync)(outputPath, html, "utf-8");
17714
17938
  let result = `Temporal call graph visualization generated: ${outputPath}
17715
17939
 
17716
17940
  `;
@@ -17730,8 +17954,84 @@ var index_visualize = tool({
17730
17954
  }
17731
17955
  });
17732
17956
 
17957
+ // src/tools/tool-names.ts
17958
+ var TOOL_NAME = {
17959
+ CODEBASE_CONTEXT: "codebase_context",
17960
+ CODEBASE_SEARCH: "codebase_search",
17961
+ CODEBASE_PEEK: "codebase_peek",
17962
+ FIND_SIMILAR: "find_similar",
17963
+ IMPLEMENTATION_LOOKUP: "implementation_lookup",
17964
+ INDEX_CODEBASE: "index_codebase",
17965
+ INDEX_STATUS: "index_status",
17966
+ INDEX_HEALTH_CHECK: "index_health_check",
17967
+ INDEX_METRICS: "index_metrics",
17968
+ INDEX_LOGS: "index_logs",
17969
+ CALL_GRAPH: "call_graph",
17970
+ CALL_GRAPH_PATH: "call_graph_path",
17971
+ PR_IMPACT: "pr_impact",
17972
+ ADD_KNOWLEDGE_BASE: "add_knowledge_base",
17973
+ LIST_KNOWLEDGE_BASES: "list_knowledge_bases",
17974
+ REMOVE_KNOWLEDGE_BASE: "remove_knowledge_base",
17975
+ PI_KNOWLEDGE_BASE_ADD: "knowledge_base_add",
17976
+ PI_KNOWLEDGE_BASE_LIST: "knowledge_base_list",
17977
+ PI_KNOWLEDGE_BASE_REMOVE: "knowledge_base_remove",
17978
+ INDEX_VISUALIZE: "index_visualize"
17979
+ };
17980
+ var PORTABLE_TOOL_NAMES = [
17981
+ TOOL_NAME.CODEBASE_CONTEXT,
17982
+ TOOL_NAME.CODEBASE_SEARCH,
17983
+ TOOL_NAME.CODEBASE_PEEK,
17984
+ TOOL_NAME.INDEX_CODEBASE,
17985
+ TOOL_NAME.INDEX_STATUS,
17986
+ TOOL_NAME.INDEX_HEALTH_CHECK,
17987
+ TOOL_NAME.INDEX_METRICS,
17988
+ TOOL_NAME.INDEX_LOGS,
17989
+ TOOL_NAME.FIND_SIMILAR,
17990
+ TOOL_NAME.IMPLEMENTATION_LOOKUP,
17991
+ TOOL_NAME.CALL_GRAPH,
17992
+ TOOL_NAME.CALL_GRAPH_PATH,
17993
+ TOOL_NAME.PR_IMPACT
17994
+ ];
17995
+ var OPENCODE_TOOL_NAMES = [
17996
+ TOOL_NAME.CODEBASE_CONTEXT,
17997
+ TOOL_NAME.CODEBASE_SEARCH,
17998
+ TOOL_NAME.CODEBASE_PEEK,
17999
+ TOOL_NAME.INDEX_CODEBASE,
18000
+ TOOL_NAME.INDEX_STATUS,
18001
+ TOOL_NAME.INDEX_HEALTH_CHECK,
18002
+ TOOL_NAME.INDEX_METRICS,
18003
+ TOOL_NAME.INDEX_LOGS,
18004
+ TOOL_NAME.FIND_SIMILAR,
18005
+ TOOL_NAME.CALL_GRAPH,
18006
+ TOOL_NAME.CALL_GRAPH_PATH,
18007
+ TOOL_NAME.IMPLEMENTATION_LOOKUP,
18008
+ TOOL_NAME.ADD_KNOWLEDGE_BASE,
18009
+ TOOL_NAME.LIST_KNOWLEDGE_BASES,
18010
+ TOOL_NAME.REMOVE_KNOWLEDGE_BASE,
18011
+ TOOL_NAME.PR_IMPACT,
18012
+ TOOL_NAME.INDEX_VISUALIZE
18013
+ ];
18014
+ var PI_TOOL_NAMES = [
18015
+ TOOL_NAME.CODEBASE_CONTEXT,
18016
+ TOOL_NAME.CODEBASE_SEARCH,
18017
+ TOOL_NAME.CODEBASE_PEEK,
18018
+ TOOL_NAME.FIND_SIMILAR,
18019
+ TOOL_NAME.IMPLEMENTATION_LOOKUP,
18020
+ TOOL_NAME.INDEX_CODEBASE,
18021
+ TOOL_NAME.INDEX_STATUS,
18022
+ TOOL_NAME.INDEX_HEALTH_CHECK,
18023
+ TOOL_NAME.INDEX_METRICS,
18024
+ TOOL_NAME.INDEX_LOGS,
18025
+ TOOL_NAME.CALL_GRAPH,
18026
+ TOOL_NAME.CALL_GRAPH_PATH,
18027
+ TOOL_NAME.PR_IMPACT,
18028
+ TOOL_NAME.PI_KNOWLEDGE_BASE_LIST,
18029
+ TOOL_NAME.PI_KNOWLEDGE_BASE_ADD,
18030
+ TOOL_NAME.PI_KNOWLEDGE_BASE_REMOVE
18031
+ ];
18032
+
17733
18033
  // src/commands/loader.ts
17734
- var import_fs15 = require("fs");
18034
+ var import_fs16 = require("fs");
17735
18035
  var path25 = __toESM(require("path"), 1);
17736
18036
  function parseFrontmatter(content) {
17737
18037
  const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
@@ -17753,15 +18053,15 @@ function parseFrontmatter(content) {
17753
18053
  }
17754
18054
  function loadCommandsFromDirectory(commandsDir) {
17755
18055
  const commands = /* @__PURE__ */ new Map();
17756
- if (!(0, import_fs15.existsSync)(commandsDir)) {
18056
+ if (!(0, import_fs16.existsSync)(commandsDir)) {
17757
18057
  return commands;
17758
18058
  }
17759
- const files = (0, import_fs15.readdirSync)(commandsDir).filter((f) => f.endsWith(".md"));
18059
+ const files = (0, import_fs16.readdirSync)(commandsDir).filter((f) => f.endsWith(".md"));
17760
18060
  for (const file of files) {
17761
18061
  const filePath = path25.join(commandsDir, file);
17762
18062
  let content;
17763
18063
  try {
17764
- content = (0, import_fs15.readFileSync)(filePath, "utf-8");
18064
+ content = (0, import_fs16.readFileSync)(filePath, "utf-8");
17765
18065
  } catch (error) {
17766
18066
  const message = error instanceof Error ? error.message : String(error);
17767
18067
  throw new Error(`Failed to load command file ${filePath}: ${message}`);
@@ -18099,7 +18399,7 @@ var RoutingHintController = class {
18099
18399
  }
18100
18400
  };
18101
18401
 
18102
- // src/index.ts
18402
+ // src/adapters/opencode.ts
18103
18403
  var import_meta2 = {};
18104
18404
  var activeWatchers = /* @__PURE__ */ new Map();
18105
18405
  function replaceActiveWatcher(projectRoot, nextWatcher) {
@@ -18117,7 +18417,8 @@ function getCommandsDir() {
18117
18417
  if (typeof import_meta2 !== "undefined" && import_meta2.url) {
18118
18418
  currentDir = path26.dirname((0, import_url.fileURLToPath)(import_meta2.url));
18119
18419
  }
18120
- return path26.join(currentDir, "..", "commands");
18420
+ const packageRoot = path26.basename(currentDir) === "adapters" ? path26.join(currentDir, "..", "..") : path26.join(currentDir, "..");
18421
+ return path26.join(packageRoot, "commands");
18121
18422
  }
18122
18423
  function appendRoutingHints(output, hints, preferredRole) {
18123
18424
  const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
@@ -18138,7 +18439,7 @@ function resolveProjectRoot(directory, worktree) {
18138
18439
  var plugin = async ({ directory, worktree }) => {
18139
18440
  try {
18140
18441
  const projectRoot = resolveProjectRoot(directory, worktree);
18141
- const rawConfig = loadMergedConfig(projectRoot);
18442
+ const rawConfig = loadMergedConfig(projectRoot, "opencode");
18142
18443
  const config = parseConfig(rawConfig);
18143
18444
  initializeTools2(projectRoot, config);
18144
18445
  const getProjectIndexer = () => getIndexerForProject2(projectRoot);
@@ -18164,23 +18465,23 @@ var plugin = async ({ directory, worktree }) => {
18164
18465
  }
18165
18466
  return {
18166
18467
  tool: {
18167
- codebase_context,
18168
- codebase_search,
18169
- codebase_peek,
18170
- index_codebase,
18171
- index_status,
18172
- index_health_check,
18173
- index_metrics,
18174
- index_logs,
18175
- find_similar,
18176
- call_graph,
18177
- call_graph_path,
18178
- implementation_lookup,
18179
- add_knowledge_base,
18180
- list_knowledge_bases,
18181
- remove_knowledge_base,
18182
- pr_impact,
18183
- index_visualize
18468
+ [TOOL_NAME.CODEBASE_CONTEXT]: codebase_context,
18469
+ [TOOL_NAME.CODEBASE_SEARCH]: codebase_search,
18470
+ [TOOL_NAME.CODEBASE_PEEK]: codebase_peek,
18471
+ [TOOL_NAME.INDEX_CODEBASE]: index_codebase,
18472
+ [TOOL_NAME.INDEX_STATUS]: index_status,
18473
+ [TOOL_NAME.INDEX_HEALTH_CHECK]: index_health_check,
18474
+ [TOOL_NAME.INDEX_METRICS]: index_metrics,
18475
+ [TOOL_NAME.INDEX_LOGS]: index_logs,
18476
+ [TOOL_NAME.FIND_SIMILAR]: find_similar,
18477
+ [TOOL_NAME.CALL_GRAPH]: call_graph,
18478
+ [TOOL_NAME.CALL_GRAPH_PATH]: call_graph_path,
18479
+ [TOOL_NAME.IMPLEMENTATION_LOOKUP]: implementation_lookup,
18480
+ [TOOL_NAME.ADD_KNOWLEDGE_BASE]: add_knowledge_base,
18481
+ [TOOL_NAME.LIST_KNOWLEDGE_BASES]: list_knowledge_bases,
18482
+ [TOOL_NAME.REMOVE_KNOWLEDGE_BASE]: remove_knowledge_base,
18483
+ [TOOL_NAME.PR_IMPACT]: pr_impact,
18484
+ [TOOL_NAME.INDEX_VISUALIZE]: index_visualize
18184
18485
  },
18185
18486
  async "chat.message"(input, output) {
18186
18487
  routingHints?.observeUserMessage(input.sessionID, output.parts);
@@ -18220,7 +18521,7 @@ var plugin = async ({ directory, worktree }) => {
18220
18521
  };
18221
18522
  }
18222
18523
  };
18223
- var index_default = plugin;
18524
+ var opencode_default = plugin;
18224
18525
  /*! Bundled license information:
18225
18526
 
18226
18527
  chokidar/index.js: