claude-nomad 0.68.0 → 0.69.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/CHANGELOG.md +65 -0
- package/README.md +7 -6
- package/dist/nomad.mjs +878 -701
- package/dist/nomad.worker.mjs +1 -1
- package/package.json +5 -4
package/dist/nomad.mjs
CHANGED
|
@@ -41,7 +41,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
41
41
|
mod
|
|
42
42
|
));
|
|
43
43
|
|
|
44
|
-
// src/config.never-sync.ts
|
|
44
|
+
// src/core/config.never-sync.ts
|
|
45
45
|
function stripTrailingDotsAndWhitespace(name) {
|
|
46
46
|
let end = name.length;
|
|
47
47
|
while (end > 0 && (name[end - 1] === "." || /\s/.test(name[end - 1]))) end -= 1;
|
|
@@ -97,7 +97,7 @@ function isNeverSync(path) {
|
|
|
97
97
|
}
|
|
98
98
|
var NEVER_SYNC, CLAUDE_EXTRA_NEVER_SYNC, ALWAYS_NEVER_SYNC, SECRET_FILE_PATTERNS, UNFILTERED_SHARED_REGIONS;
|
|
99
99
|
var init_config_never_sync = __esm({
|
|
100
|
-
"src/config.never-sync.ts"() {
|
|
100
|
+
"src/core/config.never-sync.ts"() {
|
|
101
101
|
"use strict";
|
|
102
102
|
NEVER_SYNC = /* @__PURE__ */ new Set([
|
|
103
103
|
".claude.json",
|
|
@@ -222,10 +222,10 @@ var require_picocolors = __commonJS({
|
|
|
222
222
|
}
|
|
223
223
|
});
|
|
224
224
|
|
|
225
|
-
// src/color.ts
|
|
225
|
+
// src/render/color.ts
|
|
226
226
|
var import_picocolors, enabled, red, yellow, green, cyan, blue, dim, bold, wslNarrowPad, okGlyph, failGlyph, warnGlyph, infoGlyph;
|
|
227
227
|
var init_color = __esm({
|
|
228
|
-
"src/color.ts"() {
|
|
228
|
+
"src/render/color.ts"() {
|
|
229
229
|
"use strict";
|
|
230
230
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
231
231
|
enabled = import_picocolors.default.isColorSupported;
|
|
@@ -244,10 +244,10 @@ var init_color = __esm({
|
|
|
244
244
|
}
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
-
// src/exit-codes.ts
|
|
247
|
+
// src/core/exit-codes.ts
|
|
248
248
|
var EXIT;
|
|
249
249
|
var init_exit_codes = __esm({
|
|
250
|
-
"src/exit-codes.ts"() {
|
|
250
|
+
"src/core/exit-codes.ts"() {
|
|
251
251
|
"use strict";
|
|
252
252
|
EXIT = {
|
|
253
253
|
/** Completed successfully. Also returned when a held lock causes a no-op skip. */
|
|
@@ -269,7 +269,7 @@ var init_exit_codes = __esm({
|
|
|
269
269
|
}
|
|
270
270
|
});
|
|
271
271
|
|
|
272
|
-
// src/utils.ts
|
|
272
|
+
// src/core/utils.ts
|
|
273
273
|
import { execFileSync } from "node:child_process";
|
|
274
274
|
function isProcessExit(err) {
|
|
275
275
|
if (typeof err !== "object" || err === null) return false;
|
|
@@ -304,7 +304,7 @@ function gitOrFatal(args, context, cwd) {
|
|
|
304
304
|
}
|
|
305
305
|
var log, ok, warn, fail, item, NomadFatal, PROCESS_EXIT_BRAND, ProcessExit, die, gitStatusPorcelainZ;
|
|
306
306
|
var init_utils = __esm({
|
|
307
|
-
"src/utils.ts"() {
|
|
307
|
+
"src/core/utils.ts"() {
|
|
308
308
|
"use strict";
|
|
309
309
|
init_color();
|
|
310
310
|
init_exit_codes();
|
|
@@ -349,7 +349,7 @@ var init_utils = __esm({
|
|
|
349
349
|
}
|
|
350
350
|
});
|
|
351
351
|
|
|
352
|
-
// src/config.sharedDirs.guard.ts
|
|
352
|
+
// src/core/config.sharedDirs.guard.ts
|
|
353
353
|
function assertSafeLogical(logical) {
|
|
354
354
|
if (!SAFE_LOGICAL.test(logical) || logical === "." || logical === "..") {
|
|
355
355
|
throw new NomadFatal(
|
|
@@ -419,7 +419,7 @@ function isValidSharedDir(entry) {
|
|
|
419
419
|
}
|
|
420
420
|
var SAFE_LOGICAL, SAFE_SEGMENT, RESERVED_SHARED, RESERVED_SHARED_FOLDED, WIN32_DEVICE_NAMES, UNJOINABLE_REASONS;
|
|
421
421
|
var init_config_sharedDirs_guard = __esm({
|
|
422
|
-
"src/config.sharedDirs.guard.ts"() {
|
|
422
|
+
"src/core/config.sharedDirs.guard.ts"() {
|
|
423
423
|
"use strict";
|
|
424
424
|
init_config_never_sync();
|
|
425
425
|
init_utils();
|
|
@@ -455,10 +455,10 @@ var init_config_sharedDirs_guard = __esm({
|
|
|
455
455
|
}
|
|
456
456
|
});
|
|
457
457
|
|
|
458
|
-
// src/settings-keys.ts
|
|
458
|
+
// src/core/settings-keys.ts
|
|
459
459
|
var SCHEMA_KEYS, APP_ONLY_KEYS, KNOWN_SETTINGS_KEYS;
|
|
460
460
|
var init_settings_keys = __esm({
|
|
461
|
-
"src/settings-keys.ts"() {
|
|
461
|
+
"src/core/settings-keys.ts"() {
|
|
462
462
|
"use strict";
|
|
463
463
|
SCHEMA_KEYS = [
|
|
464
464
|
"$schema",
|
|
@@ -635,7 +635,7 @@ var init_settings_keys = __esm({
|
|
|
635
635
|
}
|
|
636
636
|
});
|
|
637
637
|
|
|
638
|
-
// src/config.ts
|
|
638
|
+
// src/core/config.ts
|
|
639
639
|
import { homedir, hostname } from "node:os";
|
|
640
640
|
import { join, resolve } from "node:path";
|
|
641
641
|
function home() {
|
|
@@ -686,7 +686,7 @@ function sharedDirEntries(map) {
|
|
|
686
686
|
}
|
|
687
687
|
var SETTINGS_SCHEMA_URL, NPM_REGISTRY_LATEST_URL, GITLEAKS_PINNED_VERSION, GITLEAKS_SCAN_TIMEOUT_MS, HOST, SHARED_LINKS, GSD_PREFIX, GSD_DROPPED_NAMES, SUPPORTED_EXTRAS, PUSH_ALLOWED_STATIC;
|
|
688
688
|
var init_config = __esm({
|
|
689
|
-
"src/config.ts"() {
|
|
689
|
+
"src/core/config.ts"() {
|
|
690
690
|
"use strict";
|
|
691
691
|
init_config_sharedDirs_guard();
|
|
692
692
|
init_utils();
|
|
@@ -721,7 +721,7 @@ var init_config = __esm({
|
|
|
721
721
|
}
|
|
722
722
|
});
|
|
723
723
|
|
|
724
|
-
// src/error-text.ts
|
|
724
|
+
// src/core/error-text.ts
|
|
725
725
|
function errorText(err) {
|
|
726
726
|
try {
|
|
727
727
|
const message = err?.message;
|
|
@@ -731,12 +731,12 @@ function errorText(err) {
|
|
|
731
731
|
}
|
|
732
732
|
}
|
|
733
733
|
var init_error_text = __esm({
|
|
734
|
-
"src/error-text.ts"() {
|
|
734
|
+
"src/core/error-text.ts"() {
|
|
735
735
|
"use strict";
|
|
736
736
|
}
|
|
737
737
|
});
|
|
738
738
|
|
|
739
|
-
// src/utils.json.ts
|
|
739
|
+
// src/core/utils.json.ts
|
|
740
740
|
import { readFileSync } from "node:fs";
|
|
741
741
|
function readJson(path) {
|
|
742
742
|
const data = JSON.parse(readFileSync(path, "utf8"));
|
|
@@ -774,10 +774,13 @@ function validatePathMapShape(raw) {
|
|
|
774
774
|
}
|
|
775
775
|
return null;
|
|
776
776
|
}
|
|
777
|
+
function isProtoPollutionKey(key) {
|
|
778
|
+
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
779
|
+
}
|
|
777
780
|
function deepMerge(target, source) {
|
|
778
781
|
const out = { ...target };
|
|
779
782
|
for (const [key, value] of Object.entries(source)) {
|
|
780
|
-
if (key
|
|
783
|
+
if (isProtoPollutionKey(key)) continue;
|
|
781
784
|
const existing = out[key];
|
|
782
785
|
const bothObjects = value !== null && typeof value === "object" && !Array.isArray(value) && existing !== null && typeof existing === "object" && !Array.isArray(existing);
|
|
783
786
|
out[key] = bothObjects ? deepMerge(existing, value) : value;
|
|
@@ -789,6 +792,7 @@ function sortKeysDeep(value) {
|
|
|
789
792
|
if (value !== null && typeof value === "object") {
|
|
790
793
|
const out = {};
|
|
791
794
|
for (const key of Object.keys(value).sort((a, b) => a.localeCompare(b, "en"))) {
|
|
795
|
+
if (isProtoPollutionKey(key)) continue;
|
|
792
796
|
out[key] = sortKeysDeep(value[key]);
|
|
793
797
|
}
|
|
794
798
|
return out;
|
|
@@ -797,7 +801,7 @@ function sortKeysDeep(value) {
|
|
|
797
801
|
}
|
|
798
802
|
var ENCODE_MAX, hashPath, encodePath;
|
|
799
803
|
var init_utils_json = __esm({
|
|
800
|
-
"src/utils.json.ts"() {
|
|
804
|
+
"src/core/utils.json.ts"() {
|
|
801
805
|
"use strict";
|
|
802
806
|
init_config();
|
|
803
807
|
init_utils();
|
|
@@ -815,7 +819,7 @@ var init_utils_json = __esm({
|
|
|
815
819
|
}
|
|
816
820
|
});
|
|
817
821
|
|
|
818
|
-
// src/utils.fs.ts
|
|
822
|
+
// src/core/utils.fs.ts
|
|
819
823
|
import {
|
|
820
824
|
closeSync,
|
|
821
825
|
cpSync as cpSync3,
|
|
@@ -886,6 +890,12 @@ function freshBackupTs(backupRoot) {
|
|
|
886
890
|
while (existsSync3(join5(backupRoot, `${base}-${n}`))) n++;
|
|
887
891
|
return `${base}-${n}`;
|
|
888
892
|
}
|
|
893
|
+
function prunableByAge(dirs, olderThanMs, nowMs) {
|
|
894
|
+
return dirs.filter((d) => nowMs - d.mtimeMs > olderThanMs).map((d) => d.name);
|
|
895
|
+
}
|
|
896
|
+
function prunableByCount(dirs, keep) {
|
|
897
|
+
return dirs.slice(keep).map((d) => d.name);
|
|
898
|
+
}
|
|
889
899
|
function discardEmptyBackupDir(backupRoot) {
|
|
890
900
|
try {
|
|
891
901
|
rmdirSync(backupRoot);
|
|
@@ -926,7 +936,7 @@ function backupExtrasWrite(absPath, ts, projectRoot) {
|
|
|
926
936
|
}
|
|
927
937
|
var RENAME_RETRY_MAX_ATTEMPTS, RENAME_RETRY_BACKOFF_MS;
|
|
928
938
|
var init_utils_fs = __esm({
|
|
929
|
-
"src/utils.fs.ts"() {
|
|
939
|
+
"src/core/utils.fs.ts"() {
|
|
930
940
|
"use strict";
|
|
931
941
|
init_config();
|
|
932
942
|
init_error_text();
|
|
@@ -937,7 +947,7 @@ var init_utils_fs = __esm({
|
|
|
937
947
|
}
|
|
938
948
|
});
|
|
939
949
|
|
|
940
|
-
// src/commands
|
|
950
|
+
// src/commands/pull/wedge.ts
|
|
941
951
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
942
952
|
import { existsSync as existsSync15 } from "node:fs";
|
|
943
953
|
import { join as join21 } from "node:path";
|
|
@@ -1006,23 +1016,54 @@ function orphanedAutostashPresent(repo) {
|
|
|
1006
1016
|
return raw.split("\n").some((line) => /:\s*autostash$/.test(line));
|
|
1007
1017
|
}
|
|
1008
1018
|
var INDEX_PROBE_TIMEOUT_MS;
|
|
1009
|
-
var
|
|
1010
|
-
"src/commands
|
|
1019
|
+
var init_wedge = __esm({
|
|
1020
|
+
"src/commands/pull/wedge.ts"() {
|
|
1011
1021
|
"use strict";
|
|
1012
1022
|
INDEX_PROBE_TIMEOUT_MS = 3e4;
|
|
1013
1023
|
}
|
|
1014
1024
|
});
|
|
1015
1025
|
|
|
1016
|
-
// src/
|
|
1017
|
-
import { existsSync as existsSync16
|
|
1018
|
-
import {
|
|
1019
|
-
import { join as join22 } from "node:path";
|
|
1026
|
+
// src/core/package-root.ts
|
|
1027
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
1028
|
+
import { basename as basename3, dirname as dirname4, join as join22 } from "node:path";
|
|
1020
1029
|
import { fileURLToPath } from "node:url";
|
|
1030
|
+
function packageRoot(from = HERE) {
|
|
1031
|
+
let dir = from;
|
|
1032
|
+
for (; ; ) {
|
|
1033
|
+
if (existsSync16(join22(dir, "package.json"))) return dir;
|
|
1034
|
+
if (basename3(dir) === "node_modules") {
|
|
1035
|
+
throw new Error(`no package.json above ${from} within its own package`);
|
|
1036
|
+
}
|
|
1037
|
+
const parent = dirname4(dir);
|
|
1038
|
+
if (parent === dir) throw new Error(`no package.json above ${from}`);
|
|
1039
|
+
dir = parent;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
var HERE;
|
|
1043
|
+
var init_package_root = __esm({
|
|
1044
|
+
"src/core/package-root.ts"() {
|
|
1045
|
+
"use strict";
|
|
1046
|
+
HERE = dirname4(fileURLToPath(import.meta.url));
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
// src/commands/push/gitleaks.config.ts
|
|
1051
|
+
import { existsSync as existsSync17, mkdtempSync, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
|
|
1052
|
+
import { tmpdir } from "node:os";
|
|
1053
|
+
import { join as join23 } from "node:path";
|
|
1021
1054
|
function resolveTomlPath(repo = repoHome()) {
|
|
1022
|
-
const repoToml =
|
|
1023
|
-
if (
|
|
1024
|
-
|
|
1025
|
-
|
|
1055
|
+
const repoToml = join23(repo, ".gitleaks.toml");
|
|
1056
|
+
if (existsSync17(repoToml)) return repoToml;
|
|
1057
|
+
let root;
|
|
1058
|
+
try {
|
|
1059
|
+
root = packageRoot();
|
|
1060
|
+
} catch {
|
|
1061
|
+
throw new NomadFatal(
|
|
1062
|
+
"claude-nomad install looks incomplete (no package.json above the CLI); reinstall with `npm i -g claude-nomad`"
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
const bundled = join23(root, ".gitleaks.toml");
|
|
1066
|
+
return existsSync17(bundled) ? bundled : null;
|
|
1026
1067
|
}
|
|
1027
1068
|
function assertOverlayAllowlistsScoped(overlayBody) {
|
|
1028
1069
|
if (OVERLAY_INLINE_ALLOWLIST_RE.test(overlayBody)) {
|
|
@@ -1060,17 +1101,17 @@ function buildOverlayTempConfig(overlayBody, bundled) {
|
|
|
1060
1101
|
path = ${JSON.stringify(bundled)}
|
|
1061
1102
|
|
|
1062
1103
|
${overlayBody}`;
|
|
1063
|
-
const tempPath = mkdtempSync(
|
|
1064
|
-
const configPath =
|
|
1104
|
+
const tempPath = mkdtempSync(join23(tmpdir(), "nomad-gitleaks-cfg-"));
|
|
1105
|
+
const configPath = join23(tempPath, "config.toml");
|
|
1065
1106
|
writeFileSync3(configPath, tempBody, { mode: 384, flag: "wx" });
|
|
1066
1107
|
return { configPath, tempPath };
|
|
1067
1108
|
}
|
|
1068
1109
|
function resolveTomlConfig() {
|
|
1069
1110
|
const repo = repoHome();
|
|
1070
|
-
const overlayPath =
|
|
1071
|
-
const repoToml =
|
|
1111
|
+
const overlayPath = join23(repo, ".gitleaks.overlay.toml");
|
|
1112
|
+
const repoToml = join23(repo, ".gitleaks.toml");
|
|
1072
1113
|
const bundled = resolveTomlPath(repo);
|
|
1073
|
-
if (!
|
|
1114
|
+
if (!existsSync17(overlayPath)) {
|
|
1074
1115
|
return { path: bundled, tempPath: null };
|
|
1075
1116
|
}
|
|
1076
1117
|
if (bundled === repoToml) {
|
|
@@ -1101,10 +1142,11 @@ function resolveTomlConfig() {
|
|
|
1101
1142
|
}
|
|
1102
1143
|
}
|
|
1103
1144
|
var OVERLAY_EXTEND_RE, TABLE_HEADER_RE, OVERLAY_ALLOWLIST_HEADER_RE, OVERLAY_INLINE_ALLOWLIST_RE, PATHS_KEY_RE, CATCH_ALL_RE;
|
|
1104
|
-
var
|
|
1105
|
-
"src/push
|
|
1145
|
+
var init_gitleaks_config = __esm({
|
|
1146
|
+
"src/commands/push/gitleaks.config.ts"() {
|
|
1106
1147
|
"use strict";
|
|
1107
1148
|
init_config();
|
|
1149
|
+
init_package_root();
|
|
1108
1150
|
init_utils();
|
|
1109
1151
|
OVERLAY_EXTEND_RE = /^[ \t]*(?:\[[ \t]*extend[ \t]*\]|extend[ \t]*[.=])/m;
|
|
1110
1152
|
TABLE_HEADER_RE = /^\s*\[/;
|
|
@@ -1115,7 +1157,7 @@ var init_push_gitleaks_config = __esm({
|
|
|
1115
1157
|
}
|
|
1116
1158
|
});
|
|
1117
1159
|
|
|
1118
|
-
// src/autostash-guard.ts
|
|
1160
|
+
// src/commands/autostash-guard.ts
|
|
1119
1161
|
function autostashConflictRunbookText(resumeCmd2, stashRetained) {
|
|
1120
1162
|
const head = `${resumeCmd2} reported success, but the autostash pop it ran internally conflicted. The working tree now holds conflict markers and the index is unmerged. Nothing has been copied to ~/.claude/ yet, and there is no rebase or merge in progress to abort.`;
|
|
1121
1163
|
if (stashRetained) {
|
|
@@ -1146,19 +1188,19 @@ function assertNoAutostashConflict(repo, resumeCmd2) {
|
|
|
1146
1188
|
});
|
|
1147
1189
|
}
|
|
1148
1190
|
var init_autostash_guard = __esm({
|
|
1149
|
-
"src/autostash-guard.ts"() {
|
|
1191
|
+
"src/commands/autostash-guard.ts"() {
|
|
1150
1192
|
"use strict";
|
|
1151
|
-
|
|
1193
|
+
init_wedge();
|
|
1152
1194
|
init_exit_codes();
|
|
1153
1195
|
init_utils();
|
|
1154
1196
|
}
|
|
1155
1197
|
});
|
|
1156
1198
|
|
|
1157
|
-
// src/push
|
|
1199
|
+
// src/commands/push/checks.ts
|
|
1158
1200
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
1159
1201
|
import { readdirSync as readdirSync8, rmSync as rmSync7 } from "node:fs";
|
|
1160
1202
|
import { homedir as homedir2, platform } from "node:os";
|
|
1161
|
-
import { delimiter, join as
|
|
1203
|
+
import { delimiter, join as join24 } from "node:path";
|
|
1162
1204
|
function gitleaksInstallHint() {
|
|
1163
1205
|
const head = "gitleaks not on PATH (required for nomad push). Install:";
|
|
1164
1206
|
const plat = platform();
|
|
@@ -1206,7 +1248,7 @@ function findGitlinks(dir) {
|
|
|
1206
1248
|
return;
|
|
1207
1249
|
}
|
|
1208
1250
|
for (const e of entries) {
|
|
1209
|
-
const p =
|
|
1251
|
+
const p = join24(current, e.name);
|
|
1210
1252
|
if (e.name === ".git") {
|
|
1211
1253
|
hits.push(p);
|
|
1212
1254
|
continue;
|
|
@@ -1255,22 +1297,22 @@ function rebaseBeforePush(repo) {
|
|
|
1255
1297
|
}
|
|
1256
1298
|
assertNoAutostashConflict(repo, "nomad push");
|
|
1257
1299
|
}
|
|
1258
|
-
var
|
|
1259
|
-
"src/push
|
|
1300
|
+
var init_checks = __esm({
|
|
1301
|
+
"src/commands/push/checks.ts"() {
|
|
1260
1302
|
"use strict";
|
|
1261
|
-
|
|
1303
|
+
init_gitleaks_config();
|
|
1262
1304
|
init_autostash_guard();
|
|
1263
|
-
|
|
1305
|
+
init_wedge();
|
|
1264
1306
|
init_exit_codes();
|
|
1265
1307
|
init_utils();
|
|
1266
1308
|
}
|
|
1267
1309
|
});
|
|
1268
1310
|
|
|
1269
|
-
// src/push
|
|
1311
|
+
// src/commands/push/gitleaks.scan.ts
|
|
1270
1312
|
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
1271
1313
|
import { mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, rmSync as rmSync8 } from "node:fs";
|
|
1272
1314
|
import { homedir as homedir3 } from "node:os";
|
|
1273
|
-
import { join as
|
|
1315
|
+
import { join as join28 } from "node:path";
|
|
1274
1316
|
function toFinding(entry) {
|
|
1275
1317
|
if (typeof entry !== "object" || entry === null) return null;
|
|
1276
1318
|
const e = entry;
|
|
@@ -1318,9 +1360,9 @@ function resolveScanFailure(reportPath, e, forwardStreams) {
|
|
|
1318
1360
|
return report;
|
|
1319
1361
|
}
|
|
1320
1362
|
function scanStagedTree(repoDir, forwardStreams = false) {
|
|
1321
|
-
const cacheDir =
|
|
1363
|
+
const cacheDir = join28(homedir3(), ".cache", "claude-nomad");
|
|
1322
1364
|
mkdirSync3(cacheDir, { recursive: true });
|
|
1323
|
-
const reportPath =
|
|
1365
|
+
const reportPath = join28(cacheDir, `gitleaks-${nowTimestamp()}-${process.pid}.json`);
|
|
1324
1366
|
const { path: toml, tempPath } = resolveTomlConfig();
|
|
1325
1367
|
const args = [
|
|
1326
1368
|
"protect",
|
|
@@ -1348,14 +1390,14 @@ function scanStagedTree(repoDir, forwardStreams = false) {
|
|
|
1348
1390
|
}
|
|
1349
1391
|
}
|
|
1350
1392
|
function scanFile(filePath, forwardStreams = false, timeoutMs = GITLEAKS_SCAN_TIMEOUT_MS) {
|
|
1351
|
-
const cacheDir =
|
|
1393
|
+
const cacheDir = join28(homedir3(), ".cache", "claude-nomad");
|
|
1352
1394
|
mkdirSync3(cacheDir, { recursive: true });
|
|
1353
1395
|
const { path: toml, tempPath } = resolveTomlConfig();
|
|
1354
1396
|
let reportDir;
|
|
1355
1397
|
let reportPath;
|
|
1356
1398
|
try {
|
|
1357
|
-
reportDir = mkdtempSync2(
|
|
1358
|
-
reportPath =
|
|
1399
|
+
reportDir = mkdtempSync2(join28(cacheDir, `gitleaks-file-${nowTimestamp()}-${process.pid}-`));
|
|
1400
|
+
reportPath = join28(reportDir, "report.json");
|
|
1359
1401
|
const args = [
|
|
1360
1402
|
"detect",
|
|
1361
1403
|
"--no-git",
|
|
@@ -1380,16 +1422,16 @@ function scanFile(filePath, forwardStreams = false, timeoutMs = GITLEAKS_SCAN_TI
|
|
|
1380
1422
|
if (reportDir !== void 0) rmSync8(reportDir, { recursive: true, force: true });
|
|
1381
1423
|
}
|
|
1382
1424
|
}
|
|
1383
|
-
var
|
|
1384
|
-
"src/push
|
|
1425
|
+
var init_gitleaks_scan = __esm({
|
|
1426
|
+
"src/commands/push/gitleaks.scan.ts"() {
|
|
1385
1427
|
"use strict";
|
|
1386
1428
|
init_config();
|
|
1387
|
-
|
|
1429
|
+
init_gitleaks_config();
|
|
1388
1430
|
init_utils_fs();
|
|
1389
1431
|
}
|
|
1390
1432
|
});
|
|
1391
1433
|
|
|
1392
|
-
// src/push
|
|
1434
|
+
// src/commands/push/gitleaks.ts
|
|
1393
1435
|
function findingIdentityKey(f) {
|
|
1394
1436
|
const fp = f.Fingerprint;
|
|
1395
1437
|
return typeof fp === "string" && fp.length > 0 ? fp : `${f.File}:${f.RuleID}:${f.StartLine}:${f.StartColumn}`;
|
|
@@ -1477,13 +1519,13 @@ function buildSessionAwareFatal(bySession, other) {
|
|
|
1477
1519
|
return lines.join("\n");
|
|
1478
1520
|
}
|
|
1479
1521
|
var SESSION_PATH, SUBAGENT_SESSION_PATH, LEGACY_FATAL;
|
|
1480
|
-
var
|
|
1481
|
-
"src/push
|
|
1522
|
+
var init_gitleaks = __esm({
|
|
1523
|
+
"src/commands/push/gitleaks.ts"() {
|
|
1482
1524
|
"use strict";
|
|
1483
1525
|
init_config();
|
|
1484
1526
|
init_exit_codes();
|
|
1485
|
-
|
|
1486
|
-
|
|
1527
|
+
init_checks();
|
|
1528
|
+
init_gitleaks_scan();
|
|
1487
1529
|
init_utils();
|
|
1488
1530
|
SESSION_PATH = /^shared\/projects\/[^/]+\/([^/]+)\.jsonl$/;
|
|
1489
1531
|
SUBAGENT_SESSION_PATH = /^shared\/projects\/[^/]+\/([^/]+)\/.*\.jsonl$/;
|
|
@@ -1491,9 +1533,9 @@ var init_push_gitleaks = __esm({
|
|
|
1491
1533
|
}
|
|
1492
1534
|
});
|
|
1493
1535
|
|
|
1494
|
-
// src/push
|
|
1495
|
-
var
|
|
1496
|
-
__export(
|
|
1536
|
+
// src/commands/push/leak-verdict.ts
|
|
1537
|
+
var leak_verdict_exports = {};
|
|
1538
|
+
__export(leak_verdict_exports, {
|
|
1497
1539
|
failRow: () => failRow,
|
|
1498
1540
|
leakVerdictRow: () => leakVerdictRow,
|
|
1499
1541
|
noLeaksRow: () => noLeaksRow,
|
|
@@ -1566,27 +1608,27 @@ function scanPushVerdict(repo) {
|
|
|
1566
1608
|
return leakFound(findings);
|
|
1567
1609
|
}
|
|
1568
1610
|
var noLeaksRow, failRow;
|
|
1569
|
-
var
|
|
1570
|
-
"src/push
|
|
1611
|
+
var init_leak_verdict = __esm({
|
|
1612
|
+
"src/commands/push/leak-verdict.ts"() {
|
|
1571
1613
|
"use strict";
|
|
1572
1614
|
init_color();
|
|
1573
1615
|
init_exit_codes();
|
|
1574
|
-
|
|
1575
|
-
|
|
1616
|
+
init_checks();
|
|
1617
|
+
init_gitleaks();
|
|
1576
1618
|
noLeaksRow = () => `${green(okGlyph)} no leaks`;
|
|
1577
1619
|
failRow = (text) => `${red(failGlyph)} ${text}`;
|
|
1578
1620
|
}
|
|
1579
1621
|
});
|
|
1580
1622
|
|
|
1581
|
-
// src/commands
|
|
1623
|
+
// src/commands/adopt.ts
|
|
1582
1624
|
import { existsSync as existsSync5, lstatSync as lstatSync7 } from "node:fs";
|
|
1583
1625
|
import { join as join9 } from "node:path";
|
|
1584
1626
|
|
|
1585
|
-
// src/commands
|
|
1627
|
+
// src/commands/adopt.recover.ts
|
|
1586
1628
|
import { rmSync as rmSync4 } from "node:fs";
|
|
1587
1629
|
import { dirname as dirname2, join as join7, resolve as resolve2 } from "node:path";
|
|
1588
1630
|
|
|
1589
|
-
// src/commands
|
|
1631
|
+
// src/commands/adopt.scan.ts
|
|
1590
1632
|
init_config();
|
|
1591
1633
|
init_error_text();
|
|
1592
1634
|
init_exit_codes();
|
|
@@ -1665,17 +1707,17 @@ function refuseDeniedEntries(name, root) {
|
|
|
1665
1707
|
});
|
|
1666
1708
|
}
|
|
1667
1709
|
|
|
1668
|
-
// src/commands
|
|
1710
|
+
// src/commands/adopt.recover.ts
|
|
1669
1711
|
init_config();
|
|
1670
1712
|
init_error_text();
|
|
1671
1713
|
init_exit_codes();
|
|
1672
1714
|
|
|
1673
|
-
// src/extras
|
|
1715
|
+
// src/sync/extras/core.ts
|
|
1674
1716
|
init_config();
|
|
1675
1717
|
import { cpSync as cpSync2, existsSync as existsSync2, lstatSync as lstatSync3, readdirSync as readdirSync3, readFileSync as readFileSync2, rmSync as rmSync2 } from "node:fs";
|
|
1676
1718
|
import { basename as basename2, join as join4, relative as relative2 } from "node:path";
|
|
1677
1719
|
|
|
1678
|
-
// src/extras
|
|
1720
|
+
// src/sync/extras/collision.ts
|
|
1679
1721
|
init_utils();
|
|
1680
1722
|
import { cpSync, existsSync, lstatSync as lstatSync2, readdirSync as readdirSync2, rmSync } from "node:fs";
|
|
1681
1723
|
import { basename, join as join3 } from "node:path";
|
|
@@ -1750,7 +1792,7 @@ function copyExtrasFilteredPreservingBy(src, dst, isPreserved, isRootPreserved)
|
|
|
1750
1792
|
});
|
|
1751
1793
|
}
|
|
1752
1794
|
|
|
1753
|
-
// src/extras
|
|
1795
|
+
// src/sync/extras/guards.ts
|
|
1754
1796
|
init_utils();
|
|
1755
1797
|
init_config_sharedDirs_guard();
|
|
1756
1798
|
import { isAbsolute, normalize, sep } from "node:path";
|
|
@@ -1768,7 +1810,7 @@ function assertSafeLocalRoot(localRoot, logical) {
|
|
|
1768
1810
|
}
|
|
1769
1811
|
}
|
|
1770
1812
|
|
|
1771
|
-
// src/extras
|
|
1813
|
+
// src/sync/extras/core.ts
|
|
1772
1814
|
init_utils();
|
|
1773
1815
|
init_utils_json();
|
|
1774
1816
|
function loadValidatedExtras(opts) {
|
|
@@ -1797,12 +1839,12 @@ function* eachExtrasTarget(v, counts) {
|
|
|
1797
1839
|
counts.unmapped++;
|
|
1798
1840
|
continue;
|
|
1799
1841
|
}
|
|
1800
|
-
for (const
|
|
1801
|
-
if (!whitelist.includes(
|
|
1842
|
+
for (const dirname16 of dirnames) {
|
|
1843
|
+
if (!whitelist.includes(dirname16)) {
|
|
1802
1844
|
counts.skipped++;
|
|
1803
1845
|
continue;
|
|
1804
1846
|
}
|
|
1805
|
-
yield { logical, localRoot, dirname:
|
|
1847
|
+
yield { logical, localRoot, dirname: dirname16 };
|
|
1806
1848
|
}
|
|
1807
1849
|
}
|
|
1808
1850
|
}
|
|
@@ -1844,8 +1886,8 @@ function copyExtrasFileSkipDiverged(src, dst) {
|
|
|
1844
1886
|
}
|
|
1845
1887
|
copyExtras(src, dst);
|
|
1846
1888
|
}
|
|
1847
|
-
function extrasDenySet(
|
|
1848
|
-
return isClaudeExtraName(
|
|
1889
|
+
function extrasDenySet(dirname16) {
|
|
1890
|
+
return isClaudeExtraName(dirname16) ? CLAUDE_EXTRA_NEVER_SYNC : ALWAYS_NEVER_SYNC;
|
|
1849
1891
|
}
|
|
1850
1892
|
function copyExtrasFiltered(src, dst, blockSet) {
|
|
1851
1893
|
rmSync2(dst, { recursive: true, force: true });
|
|
@@ -1888,7 +1930,7 @@ function copyExtrasFilteredPreserving(src, dst, blockSet) {
|
|
|
1888
1930
|
});
|
|
1889
1931
|
}
|
|
1890
1932
|
|
|
1891
|
-
// src/fs-presence.ts
|
|
1933
|
+
// src/core/fs-presence.ts
|
|
1892
1934
|
import { lstatSync as lstatSync4, statSync } from "node:fs";
|
|
1893
1935
|
var ABSENT_CODES = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR", "ENAMETOOLONG"]);
|
|
1894
1936
|
function classifyPresence(p) {
|
|
@@ -1913,14 +1955,110 @@ function lexists(p) {
|
|
|
1913
1955
|
return classifyPresence(p) !== "absent";
|
|
1914
1956
|
}
|
|
1915
1957
|
|
|
1916
|
-
// src/links.ts
|
|
1958
|
+
// src/sync/links.ts
|
|
1917
1959
|
init_config();
|
|
1918
1960
|
import { existsSync as existsSync4, lstatSync as lstatSync6, rmSync as rmSync3 } from "node:fs";
|
|
1919
1961
|
import { join as join6 } from "node:path";
|
|
1920
1962
|
|
|
1921
|
-
// src/
|
|
1963
|
+
// src/commands/capture-settings/core.ts
|
|
1964
|
+
init_utils_json();
|
|
1965
|
+
|
|
1966
|
+
// src/sync/hooks-filter.ts
|
|
1922
1967
|
init_config();
|
|
1923
|
-
|
|
1968
|
+
init_utils_json();
|
|
1969
|
+
|
|
1970
|
+
// src/sync/hooks-filter.command-sub.ts
|
|
1971
|
+
var SUB_START = /^"?(?:\$\(|`)/;
|
|
1972
|
+
function opensSubstitution(token) {
|
|
1973
|
+
return SUB_START.test(token);
|
|
1974
|
+
}
|
|
1975
|
+
function stepChar(token, i, scan) {
|
|
1976
|
+
const c = token[i];
|
|
1977
|
+
const top = scan.stack.at(-1);
|
|
1978
|
+
if (top === "sq") {
|
|
1979
|
+
if (c === "'") scan.stack.pop();
|
|
1980
|
+
return i + 1;
|
|
1981
|
+
}
|
|
1982
|
+
if (scan.escaped) {
|
|
1983
|
+
scan.escaped = false;
|
|
1984
|
+
return i + 1;
|
|
1985
|
+
}
|
|
1986
|
+
if (c === "\\") {
|
|
1987
|
+
scan.escaped = true;
|
|
1988
|
+
return i + 1;
|
|
1989
|
+
}
|
|
1990
|
+
if (c === "$" && token[i + 1] === "(") {
|
|
1991
|
+
scan.stack.push("cmd");
|
|
1992
|
+
scan.depth++;
|
|
1993
|
+
return i + 2;
|
|
1994
|
+
}
|
|
1995
|
+
if (c === "'" && top === "cmd") scan.stack.push("sq");
|
|
1996
|
+
else if (c === "`") toggleBacktick(scan, top);
|
|
1997
|
+
else if (c === '"') toggleDoubleQuote(scan, top);
|
|
1998
|
+
else if (top === "cmd") stepParen(c, scan);
|
|
1999
|
+
return i + 1;
|
|
2000
|
+
}
|
|
2001
|
+
function toggleBacktick(scan, top) {
|
|
2002
|
+
if (top === "bt") scan.stack.pop();
|
|
2003
|
+
else scan.stack.push("bt");
|
|
2004
|
+
}
|
|
2005
|
+
function toggleDoubleQuote(scan, top) {
|
|
2006
|
+
if (top === "dq") scan.stack.pop();
|
|
2007
|
+
else scan.stack.push("dq");
|
|
2008
|
+
}
|
|
2009
|
+
function stepParen(c, scan) {
|
|
2010
|
+
if (c === "(") {
|
|
2011
|
+
scan.stack.push("cmd");
|
|
2012
|
+
scan.depth++;
|
|
2013
|
+
} else if (c === ")") {
|
|
2014
|
+
scan.stack.pop();
|
|
2015
|
+
scan.depth--;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
function skipDollarParen(tokens, start, from) {
|
|
2019
|
+
const scan = { stack: ["cmd"], depth: 1, escaped: false };
|
|
2020
|
+
let i = from;
|
|
2021
|
+
for (let j = start; j < tokens.length; j++) {
|
|
2022
|
+
const token = tokens[j];
|
|
2023
|
+
while (i < token.length) {
|
|
2024
|
+
i = stepChar(token, i, scan);
|
|
2025
|
+
if (scan.depth === 0) return { next: j + 1, rest: token.slice(i) };
|
|
2026
|
+
}
|
|
2027
|
+
i = 0;
|
|
2028
|
+
scan.escaped = false;
|
|
2029
|
+
}
|
|
2030
|
+
return unterminated(tokens, start);
|
|
2031
|
+
}
|
|
2032
|
+
function skipBacktick(tokens, start, from) {
|
|
2033
|
+
let i = from;
|
|
2034
|
+
for (let j = start; j < tokens.length; j++) {
|
|
2035
|
+
const token = tokens[j];
|
|
2036
|
+
while (i < token.length) {
|
|
2037
|
+
if (token[i] === "\\") i += 2;
|
|
2038
|
+
else if (token[i] === "`") return { next: j + 1, rest: token.slice(i + 1) };
|
|
2039
|
+
else i++;
|
|
2040
|
+
}
|
|
2041
|
+
i = 0;
|
|
2042
|
+
}
|
|
2043
|
+
return unterminated(tokens, start);
|
|
2044
|
+
}
|
|
2045
|
+
function unterminated(tokens, start) {
|
|
2046
|
+
return { next: start + 1, rest: tokens[start] };
|
|
2047
|
+
}
|
|
2048
|
+
function skipSubstitution(tokens, start) {
|
|
2049
|
+
const token = tokens[start] ?? "";
|
|
2050
|
+
const paren = token.indexOf("$(");
|
|
2051
|
+
const tick = token.indexOf("`");
|
|
2052
|
+
if (paren < 0 && tick < 0) return { next: start + 1, rest: token };
|
|
2053
|
+
if (tick >= 0 && (paren < 0 || tick < paren)) return skipBacktick(tokens, start, tick + 1);
|
|
2054
|
+
return skipDollarParen(tokens, start, paren + 2);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
// src/sync/hooks-filter.ts
|
|
2058
|
+
var KNOWN_LAUNCHER_BASENAMES = /* @__PURE__ */ new Set(["env", "node", "bash", "sh"]);
|
|
2059
|
+
var SUBSTITUTION_ARTIFACT = /[`()'"]/;
|
|
2060
|
+
var ENV_ASSIGNMENT = /^[A-Za-z_]\w*=/;
|
|
2061
|
+
var SHELL_OPERATORS = /* @__PURE__ */ new Set(["&&", "||", ";", "|", "&"]);
|
|
1924
2062
|
function scriptBasename(token) {
|
|
1925
2063
|
const lastSlash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
|
|
1926
2064
|
return lastSlash >= 0 ? token.slice(lastSlash + 1) : token;
|
|
@@ -1935,25 +2073,56 @@ function stripQuotes(token) {
|
|
|
1935
2073
|
}
|
|
1936
2074
|
return token;
|
|
1937
2075
|
}
|
|
2076
|
+
var NO_CANDIDATE = { index: -1, word: "" };
|
|
2077
|
+
function nextScriptWord(tokens, from, inScriptSlot) {
|
|
2078
|
+
let slot = inScriptSlot;
|
|
2079
|
+
let i = from;
|
|
2080
|
+
while (i < tokens.length) {
|
|
2081
|
+
const token = tokens[i];
|
|
2082
|
+
if (SHELL_OPERATORS.has(token)) {
|
|
2083
|
+
slot = false;
|
|
2084
|
+
i++;
|
|
2085
|
+
} else if (token.startsWith("-")) {
|
|
2086
|
+
i++;
|
|
2087
|
+
} else if (!opensSubstitution(token)) {
|
|
2088
|
+
return { index: i, word: token };
|
|
2089
|
+
} else {
|
|
2090
|
+
const end = skipSubstitution(tokens, i);
|
|
2091
|
+
if (end.rest !== "") return { index: end.next - 1, word: end.rest };
|
|
2092
|
+
if (slot && !SHELL_OPERATORS.has(tokens[end.next] ?? "")) return NO_CANDIDATE;
|
|
2093
|
+
i = end.next;
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
return NO_CANDIDATE;
|
|
2097
|
+
}
|
|
2098
|
+
function resolveScriptWord(tokens, from, underEnv) {
|
|
2099
|
+
let candidate = nextScriptWord(tokens, from, true);
|
|
2100
|
+
while (underEnv && candidate.index >= 0) {
|
|
2101
|
+
const word = stripQuotes(candidate.word);
|
|
2102
|
+
const isBareInterpreter = !word.includes("/") && !word.includes("\\") && KNOWN_LAUNCHER_BASENAMES.has(word);
|
|
2103
|
+
if (!isBareInterpreter && !ENV_ASSIGNMENT.test(word)) return candidate;
|
|
2104
|
+
candidate = nextScriptWord(tokens, candidate.index + 1, true);
|
|
2105
|
+
}
|
|
2106
|
+
return candidate;
|
|
2107
|
+
}
|
|
1938
2108
|
function isGsdHookEntry(command) {
|
|
1939
2109
|
const tokens = command.trim().split(/\s+/);
|
|
1940
|
-
if (tokens
|
|
1941
|
-
const envAssign = /^[A-Za-z_]\w*=/;
|
|
2110
|
+
if (tokens[0] === "") return false;
|
|
1942
2111
|
let i = 0;
|
|
1943
|
-
while (i < tokens.length &&
|
|
2112
|
+
while (i < tokens.length && ENV_ASSIGNMENT.test(tokens[i])) {
|
|
1944
2113
|
i++;
|
|
1945
2114
|
}
|
|
1946
|
-
const
|
|
2115
|
+
const launcher = nextScriptWord(tokens, i, false);
|
|
2116
|
+
if (launcher.index < 0) return false;
|
|
2117
|
+
const first = stripQuotes(launcher.word);
|
|
1947
2118
|
const firstBase = scriptBasename(first);
|
|
1948
2119
|
const firstHasPath = first.includes("/") || first.includes("\\");
|
|
1949
|
-
if (
|
|
2120
|
+
if (!KNOWN_LAUNCHER_BASENAMES.has(firstBase) && (firstHasPath || !SUBSTITUTION_ARTIFACT.test(first))) {
|
|
1950
2121
|
return firstBase.startsWith(GSD_PREFIX);
|
|
1951
2122
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
}
|
|
1956
|
-
return false;
|
|
2123
|
+
const script = resolveScriptWord(tokens, launcher.index + 1, firstBase === "env");
|
|
2124
|
+
if (script.index < 0) return false;
|
|
2125
|
+
return scriptBasename(stripQuotes(script.word)).startsWith(GSD_PREFIX);
|
|
1957
2126
|
}
|
|
1958
2127
|
function filterMatcherEntry(entry) {
|
|
1959
2128
|
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
@@ -1981,24 +2150,26 @@ function filterEventMatchers(matchers) {
|
|
|
1981
2150
|
function stripGsdHookEntries(settings) {
|
|
1982
2151
|
const out = {};
|
|
1983
2152
|
for (const [key, value] of Object.entries(settings)) {
|
|
1984
|
-
if (key
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
}
|
|
1988
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
2153
|
+
if (isProtoPollutionKey(key)) continue;
|
|
2154
|
+
const hooksObj = key === "hooks" ? asPlainObject(value) : null;
|
|
2155
|
+
if (hooksObj === null) {
|
|
1989
2156
|
out[key] = value;
|
|
1990
2157
|
continue;
|
|
1991
2158
|
}
|
|
1992
|
-
const
|
|
1993
|
-
|
|
1994
|
-
for (const [event, matchers] of Object.entries(hooksObj)) {
|
|
1995
|
-
const filtered = filterEventMatchers(matchers);
|
|
1996
|
-
if (filtered !== null) filteredHooks[event] = filtered;
|
|
1997
|
-
}
|
|
1998
|
-
if (Object.keys(filteredHooks).length > 0) out[key] = filteredHooks;
|
|
2159
|
+
const filteredHooks = filterHooksBlock(hooksObj);
|
|
2160
|
+
if (filteredHooks !== null) out[key] = filteredHooks;
|
|
1999
2161
|
}
|
|
2000
2162
|
return out;
|
|
2001
2163
|
}
|
|
2164
|
+
function filterHooksBlock(hooksObj) {
|
|
2165
|
+
const filteredHooks = {};
|
|
2166
|
+
for (const [event, matchers] of Object.entries(hooksObj)) {
|
|
2167
|
+
if (isProtoPollutionKey(event)) continue;
|
|
2168
|
+
const filtered = filterEventMatchers(matchers);
|
|
2169
|
+
if (filtered !== null) filteredHooks[event] = filtered;
|
|
2170
|
+
}
|
|
2171
|
+
return Object.keys(filteredHooks).length > 0 ? filteredHooks : null;
|
|
2172
|
+
}
|
|
2002
2173
|
function keepMatcherEntry(entry) {
|
|
2003
2174
|
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return null;
|
|
2004
2175
|
const entryObj = entry;
|
|
@@ -2028,6 +2199,7 @@ function keepGsdHookEntries(settings) {
|
|
|
2028
2199
|
const hooksObj = hooksVal;
|
|
2029
2200
|
const keptHooks = {};
|
|
2030
2201
|
for (const [event, matchers] of Object.entries(hooksObj)) {
|
|
2202
|
+
if (isProtoPollutionKey(event)) continue;
|
|
2031
2203
|
const kept = keepEventMatchers(matchers);
|
|
2032
2204
|
if (kept !== null) keptHooks[event] = kept;
|
|
2033
2205
|
}
|
|
@@ -2062,7 +2234,7 @@ function graftGsdHookEntries(base, gsdOnly) {
|
|
|
2062
2234
|
const baseHooks = asPlainObject(base.hooks);
|
|
2063
2235
|
const mergedHooks = baseHooks ? { ...baseHooks } : {};
|
|
2064
2236
|
for (const [event, gsdMatchers] of Object.entries(gsdHooks)) {
|
|
2065
|
-
if (!Array.isArray(gsdMatchers)) continue;
|
|
2237
|
+
if (isProtoPollutionKey(event) || !Array.isArray(gsdMatchers)) continue;
|
|
2066
2238
|
const baseMatchers = mergedHooks[event];
|
|
2067
2239
|
mergedHooks[event] = Array.isArray(baseMatchers) ? unionMatcherArrays(baseMatchers, gsdMatchers) : gsdMatchers;
|
|
2068
2240
|
}
|
|
@@ -2093,7 +2265,7 @@ function baseHasGsdHookEntries(settings) {
|
|
|
2093
2265
|
return false;
|
|
2094
2266
|
}
|
|
2095
2267
|
|
|
2096
|
-
// src/commands
|
|
2268
|
+
// src/commands/capture-settings/core.ts
|
|
2097
2269
|
function arraysEqual(a, b) {
|
|
2098
2270
|
if (a.length !== b.length) return false;
|
|
2099
2271
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -2187,6 +2359,7 @@ function normalizeNodePathsDeep(value) {
|
|
|
2187
2359
|
if (value !== null && typeof value === "object") {
|
|
2188
2360
|
const out = {};
|
|
2189
2361
|
for (const [k, v] of Object.entries(value)) {
|
|
2362
|
+
if (isProtoPollutionKey(k)) continue;
|
|
2190
2363
|
out[k] = normalizeNodePathsDeep(v);
|
|
2191
2364
|
}
|
|
2192
2365
|
return out;
|
|
@@ -2205,7 +2378,7 @@ function buildCaptureSubset(merged, settings, opts) {
|
|
|
2205
2378
|
return out;
|
|
2206
2379
|
}
|
|
2207
2380
|
|
|
2208
|
-
// src/links.ts
|
|
2381
|
+
// src/sync/links.ts
|
|
2209
2382
|
init_utils();
|
|
2210
2383
|
init_utils_fs();
|
|
2211
2384
|
init_utils_json();
|
|
@@ -2391,7 +2564,7 @@ function regenerateSettings(ts, opts = {}) {
|
|
|
2391
2564
|
return { label: overrideLabel };
|
|
2392
2565
|
}
|
|
2393
2566
|
|
|
2394
|
-
// src/commands
|
|
2567
|
+
// src/commands/adopt.recover.ts
|
|
2395
2568
|
init_utils();
|
|
2396
2569
|
function isDirectChildOf(root, abs) {
|
|
2397
2570
|
return dirname2(resolve2(abs)) === resolve2(root);
|
|
@@ -2503,14 +2676,14 @@ function reportSourceRemovalFailure(name, linkPath, message, stage) {
|
|
|
2503
2676
|
);
|
|
2504
2677
|
}
|
|
2505
2678
|
|
|
2506
|
-
// src/commands
|
|
2679
|
+
// src/commands/adopt.ts
|
|
2507
2680
|
init_config();
|
|
2508
2681
|
init_config_sharedDirs_guard();
|
|
2509
2682
|
init_exit_codes();
|
|
2510
2683
|
init_utils();
|
|
2511
2684
|
init_utils_fs();
|
|
2512
2685
|
|
|
2513
|
-
// src/utils.lockfile.ts
|
|
2686
|
+
// src/core/utils.lockfile.ts
|
|
2514
2687
|
init_config();
|
|
2515
2688
|
init_utils();
|
|
2516
2689
|
import { closeSync as closeSync2, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
@@ -2623,7 +2796,7 @@ function retryOnce(verb, lp) {
|
|
|
2623
2796
|
}
|
|
2624
2797
|
}
|
|
2625
2798
|
|
|
2626
|
-
// src/commands
|
|
2799
|
+
// src/commands/adopt.ts
|
|
2627
2800
|
init_utils_json();
|
|
2628
2801
|
var ADOPT_PUSH_HINT = "run `nomad push` to share with other hosts";
|
|
2629
2802
|
function readMapIfPresent(repoHome2) {
|
|
@@ -2787,11 +2960,11 @@ function adoptPreflightAndMove(name, linkPath, sharedTarget, repo, backup, dryRu
|
|
|
2787
2960
|
}
|
|
2788
2961
|
}
|
|
2789
2962
|
|
|
2790
|
-
// src/commands
|
|
2963
|
+
// src/commands/allow.ts
|
|
2791
2964
|
init_config();
|
|
2792
2965
|
import { existsSync as existsSync6 } from "node:fs";
|
|
2793
2966
|
|
|
2794
|
-
// src/commands
|
|
2967
|
+
// src/commands/redact/core.ts
|
|
2795
2968
|
import { appendFileSync, readFileSync as readFileSync4 } from "node:fs";
|
|
2796
2969
|
import { join as join10 } from "node:path";
|
|
2797
2970
|
function collectMatchIntervals(content, findings) {
|
|
@@ -2865,7 +3038,7 @@ function appendGitleaksIgnore(fingerprint, repo) {
|
|
|
2865
3038
|
appendFileSync(ignPath, prefix + formatFingerprint(sanitized), "utf8");
|
|
2866
3039
|
}
|
|
2867
3040
|
|
|
2868
|
-
// src/commands
|
|
3041
|
+
// src/commands/allow.ts
|
|
2869
3042
|
init_exit_codes();
|
|
2870
3043
|
init_utils();
|
|
2871
3044
|
function cmdAllow(fingerprints) {
|
|
@@ -2885,7 +3058,7 @@ function cmdAllow(fingerprints) {
|
|
|
2885
3058
|
log(`allowed ${fingerprints.length} fingerprint(s)`);
|
|
2886
3059
|
}
|
|
2887
3060
|
|
|
2888
|
-
// src/commands
|
|
3061
|
+
// src/commands/capture-settings/capture-settings.ts
|
|
2889
3062
|
init_config();
|
|
2890
3063
|
import { existsSync as existsSync7 } from "node:fs";
|
|
2891
3064
|
import { join as join11 } from "node:path";
|
|
@@ -2967,10 +3140,11 @@ async function cmdCaptureSettings(opts) {
|
|
|
2967
3140
|
}
|
|
2968
3141
|
}
|
|
2969
3142
|
|
|
2970
|
-
// src/commands
|
|
3143
|
+
// src/commands/clean.ts
|
|
2971
3144
|
init_config();
|
|
2972
3145
|
init_exit_codes();
|
|
2973
3146
|
init_utils();
|
|
3147
|
+
init_utils_fs();
|
|
2974
3148
|
import { existsSync as existsSync8, lstatSync as lstatSync8, readdirSync as readdirSync4, rmSync as rmSync5, statSync as statSync3 } from "node:fs";
|
|
2975
3149
|
import { join as join12 } from "node:path";
|
|
2976
3150
|
var TS_SHAPE = /^\d{8}-\d{6}(-\d+)?$/;
|
|
@@ -3005,12 +3179,6 @@ function holdsNoContent(dir) {
|
|
|
3005
3179
|
}
|
|
3006
3180
|
return true;
|
|
3007
3181
|
}
|
|
3008
|
-
function prunableByAge(dirs, olderThanMs, nowMs) {
|
|
3009
|
-
return dirs.filter((d) => nowMs - d.mtimeMs > olderThanMs).map((d) => d.name);
|
|
3010
|
-
}
|
|
3011
|
-
function prunableByCount(dirs, keep) {
|
|
3012
|
-
return dirs.slice(keep).map((d) => d.name);
|
|
3013
|
-
}
|
|
3014
3182
|
function safeDelete(backupBase2, name) {
|
|
3015
3183
|
if (!isTsDir(name)) return;
|
|
3016
3184
|
const full = join12(backupBase2, name);
|
|
@@ -3070,7 +3238,7 @@ function pruneBackups(opts, backupBase2) {
|
|
|
3070
3238
|
log(`removed ${targets.length} backup(s)`);
|
|
3071
3239
|
}
|
|
3072
3240
|
|
|
3073
|
-
// src/commands
|
|
3241
|
+
// src/commands/eject.ts
|
|
3074
3242
|
init_config();
|
|
3075
3243
|
init_config_sharedDirs_guard();
|
|
3076
3244
|
init_utils();
|
|
@@ -3270,20 +3438,20 @@ function cmdEject(opts = {}, roots = defaultEjectRoots()) {
|
|
|
3270
3438
|
}
|
|
3271
3439
|
}
|
|
3272
3440
|
|
|
3273
|
-
// src/commands
|
|
3274
|
-
import { existsSync as
|
|
3275
|
-
import { join as
|
|
3441
|
+
// src/commands/doctor/doctor.ts
|
|
3442
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
3443
|
+
import { join as join52 } from "node:path";
|
|
3276
3444
|
|
|
3277
|
-
// src/commands
|
|
3445
|
+
// src/commands/doctor/checks/repo.ts
|
|
3278
3446
|
init_color();
|
|
3279
3447
|
init_config();
|
|
3280
3448
|
import { existsSync as existsSync11, lstatSync as lstatSync10, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
3281
3449
|
import { join as join17 } from "node:path";
|
|
3282
3450
|
|
|
3283
|
-
// src/commands
|
|
3451
|
+
// src/commands/doctor/format.ts
|
|
3284
3452
|
init_color();
|
|
3285
3453
|
|
|
3286
|
-
// src/output-tree.ts
|
|
3454
|
+
// src/render/output-tree.ts
|
|
3287
3455
|
init_color();
|
|
3288
3456
|
var FAIL_GLYPH_BARE = "\u2717";
|
|
3289
3457
|
function section(header, raw = false) {
|
|
@@ -3341,7 +3509,7 @@ function renderTree(sections) {
|
|
|
3341
3509
|
}
|
|
3342
3510
|
var renderDoctor = renderTree;
|
|
3343
3511
|
|
|
3344
|
-
// src/commands
|
|
3512
|
+
// src/commands/doctor/format.ts
|
|
3345
3513
|
init_utils_json();
|
|
3346
3514
|
function readJsonSafe(path, label, section2) {
|
|
3347
3515
|
try {
|
|
@@ -3353,12 +3521,12 @@ function readJsonSafe(path, label, section2) {
|
|
|
3353
3521
|
}
|
|
3354
3522
|
}
|
|
3355
3523
|
|
|
3356
|
-
// src/commands
|
|
3524
|
+
// src/commands/doctor/checks/repo.win32.ts
|
|
3357
3525
|
init_color();
|
|
3358
3526
|
init_config();
|
|
3359
3527
|
import { join as join14, win32 as win32Path } from "node:path";
|
|
3360
3528
|
|
|
3361
|
-
// src/extras
|
|
3529
|
+
// src/sync/extras/diff.ts
|
|
3362
3530
|
init_utils();
|
|
3363
3531
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
3364
3532
|
import { relative as relative4 } from "node:path";
|
|
@@ -3413,7 +3581,7 @@ function listDivergingModified(a, b) {
|
|
|
3413
3581
|
return runNameStatusDiff(a, b, (stdout) => parseModifiedPaths(stdout, a));
|
|
3414
3582
|
}
|
|
3415
3583
|
|
|
3416
|
-
// src/commands
|
|
3584
|
+
// src/commands/doctor/checks/repo.win32.ts
|
|
3417
3585
|
function win32CopyOkRow(name, exempt = 0) {
|
|
3418
3586
|
const note = exempt > 0 ? dim(` (${exempt} never-synced path(s) not compared)`) : "";
|
|
3419
3587
|
return { line: `${green(okGlyph)} ${name}: real copy (win32 copy-sync)${note}`, fail: false };
|
|
@@ -3465,7 +3633,7 @@ function classifyWin32Copy(name, p) {
|
|
|
3465
3633
|
};
|
|
3466
3634
|
}
|
|
3467
3635
|
|
|
3468
|
-
// src/commands
|
|
3636
|
+
// src/commands/doctor/checks/repo.source.ts
|
|
3469
3637
|
init_color();
|
|
3470
3638
|
init_config();
|
|
3471
3639
|
import { join as join15 } from "node:path";
|
|
@@ -3516,7 +3684,7 @@ function repoSourceRow(name, present, absent) {
|
|
|
3516
3684
|
return state === "resolves" ? present : absent;
|
|
3517
3685
|
}
|
|
3518
3686
|
|
|
3519
|
-
// src/init
|
|
3687
|
+
// src/commands/init/classify.ts
|
|
3520
3688
|
init_config();
|
|
3521
3689
|
init_utils_json();
|
|
3522
3690
|
import { existsSync as existsSync10 } from "node:fs";
|
|
@@ -3559,7 +3727,7 @@ function reasonForPartial(repoHome2, host) {
|
|
|
3559
3727
|
return "- partial state (unknown gap)";
|
|
3560
3728
|
}
|
|
3561
3729
|
|
|
3562
|
-
// src/commands
|
|
3730
|
+
// src/commands/doctor/checks/repo.ts
|
|
3563
3731
|
init_utils_json();
|
|
3564
3732
|
function isOverrideActive() {
|
|
3565
3733
|
return Boolean(process.env.NOMAD_REPO);
|
|
@@ -3718,7 +3886,7 @@ function reportDroppedNamesMigration(section2) {
|
|
|
3718
3886
|
}
|
|
3719
3887
|
}
|
|
3720
3888
|
|
|
3721
|
-
// src/commands
|
|
3889
|
+
// src/commands/doctor/checks/settings.ts
|
|
3722
3890
|
init_color();
|
|
3723
3891
|
init_config();
|
|
3724
3892
|
import { existsSync as existsSync12, readdirSync as readdirSync6 } from "node:fs";
|
|
@@ -3779,7 +3947,7 @@ function reportHostOverrides(section2, base, settings) {
|
|
|
3779
3947
|
}
|
|
3780
3948
|
}
|
|
3781
3949
|
|
|
3782
|
-
// src/commands
|
|
3950
|
+
// src/commands/doctor/checks/pathmap.ts
|
|
3783
3951
|
init_color();
|
|
3784
3952
|
init_config();
|
|
3785
3953
|
init_config_sharedDirs_guard();
|
|
@@ -3965,7 +4133,7 @@ function reportNeverSync(section2) {
|
|
|
3965
4133
|
);
|
|
3966
4134
|
}
|
|
3967
4135
|
|
|
3968
|
-
// src/commands
|
|
4136
|
+
// src/commands/doctor/checks/skills.ts
|
|
3969
4137
|
init_color();
|
|
3970
4138
|
import { existsSync as existsSync14 } from "node:fs";
|
|
3971
4139
|
import { join as join20 } from "node:path";
|
|
@@ -4013,15 +4181,15 @@ function reportSkillsDivergence(section2) {
|
|
|
4013
4181
|
}
|
|
4014
4182
|
}
|
|
4015
4183
|
|
|
4016
|
-
// src/commands
|
|
4184
|
+
// src/commands/doctor/checks/git-state.ts
|
|
4017
4185
|
init_color();
|
|
4018
4186
|
init_config();
|
|
4019
4187
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
4020
|
-
import { existsSync as
|
|
4021
|
-
import { join as
|
|
4022
|
-
|
|
4188
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
4189
|
+
import { join as join25, relative as relative5 } from "node:path";
|
|
4190
|
+
init_wedge();
|
|
4023
4191
|
|
|
4024
|
-
// src/git-probe.ts
|
|
4192
|
+
// src/core/git-probe.ts
|
|
4025
4193
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
4026
4194
|
var PROBE_TIMEOUT_MS = 1e4;
|
|
4027
4195
|
var PROBE_MAX_BUFFER = 64 * 1024 * 1024;
|
|
@@ -4038,8 +4206,8 @@ function gitProbe(args, repo) {
|
|
|
4038
4206
|
}
|
|
4039
4207
|
}
|
|
4040
4208
|
|
|
4041
|
-
// src/commands
|
|
4042
|
-
|
|
4209
|
+
// src/commands/doctor/checks/git-state.ts
|
|
4210
|
+
init_checks();
|
|
4043
4211
|
init_utils();
|
|
4044
4212
|
function reportGitleaksProbe(section2) {
|
|
4045
4213
|
try {
|
|
@@ -4060,8 +4228,8 @@ function reportGitleaksProbe(section2) {
|
|
|
4060
4228
|
}
|
|
4061
4229
|
function reportGitlinks(section2) {
|
|
4062
4230
|
const repo = repoHome();
|
|
4063
|
-
const sharedDir =
|
|
4064
|
-
if (
|
|
4231
|
+
const sharedDir = join25(repo, "shared");
|
|
4232
|
+
if (existsSync18(sharedDir)) {
|
|
4065
4233
|
const gitlinks = findGitlinks(sharedDir);
|
|
4066
4234
|
for (const p of gitlinks) {
|
|
4067
4235
|
const rel = relative5(repo, p).replaceAll("\\", "/");
|
|
@@ -4196,10 +4364,10 @@ function reportTrackedDeniedShared(section2) {
|
|
|
4196
4364
|
);
|
|
4197
4365
|
}
|
|
4198
4366
|
|
|
4199
|
-
// src/commands
|
|
4367
|
+
// src/commands/doctor/checks/backups.ts
|
|
4200
4368
|
init_color();
|
|
4201
|
-
import { existsSync as
|
|
4202
|
-
import { join as
|
|
4369
|
+
import { existsSync as existsSync19, lstatSync as lstatSync12, readdirSync as readdirSync9 } from "node:fs";
|
|
4370
|
+
import { join as join26 } from "node:path";
|
|
4203
4371
|
init_config();
|
|
4204
4372
|
var TS_SHAPE2 = /^\d{8}-\d{6}(-\d+)?$/;
|
|
4205
4373
|
function safeReaddir(dir) {
|
|
@@ -4215,7 +4383,7 @@ var BYTES_PER_MB = 1024 * 1024;
|
|
|
4215
4383
|
function dirSizeBytes(dir) {
|
|
4216
4384
|
let bytes = 0;
|
|
4217
4385
|
for (const entry of safeReaddir(dir)) {
|
|
4218
|
-
const full =
|
|
4386
|
+
const full = join26(dir, entry);
|
|
4219
4387
|
const st = lstatSync12(full, { throwIfNoEntry: false });
|
|
4220
4388
|
if (!st) continue;
|
|
4221
4389
|
if (st.isSymbolicLink()) continue;
|
|
@@ -4226,11 +4394,11 @@ function dirSizeBytes(dir) {
|
|
|
4226
4394
|
}
|
|
4227
4395
|
function totalSizeMb(backupBase2, dirs) {
|
|
4228
4396
|
let bytes = 0;
|
|
4229
|
-
for (const name of dirs) bytes += dirSizeBytes(
|
|
4397
|
+
for (const name of dirs) bytes += dirSizeBytes(join26(backupBase2, name));
|
|
4230
4398
|
return bytes / BYTES_PER_MB;
|
|
4231
4399
|
}
|
|
4232
4400
|
function reportBackupsCheck(section2, backupBase2 = backupBase()) {
|
|
4233
|
-
if (!
|
|
4401
|
+
if (!existsSync19(backupBase2)) return;
|
|
4234
4402
|
const dirs = safeReaddir(backupBase2).filter((n) => TS_SHAPE2.test(n));
|
|
4235
4403
|
const count = dirs.length;
|
|
4236
4404
|
const sizeMb = totalSizeMb(backupBase2, dirs);
|
|
@@ -4242,7 +4410,7 @@ function reportBackupsCheck(section2, backupBase2 = backupBase()) {
|
|
|
4242
4410
|
}
|
|
4243
4411
|
}
|
|
4244
4412
|
|
|
4245
|
-
// src/commands
|
|
4413
|
+
// src/commands/doctor/checks/remote.ts
|
|
4246
4414
|
init_color();
|
|
4247
4415
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
4248
4416
|
init_config();
|
|
@@ -4309,13 +4477,13 @@ function reportCheckRemote(section2) {
|
|
|
4309
4477
|
addItem(section2, `${green(okGlyph)} remote: origin/main has shared/ and a valid path-map.json`);
|
|
4310
4478
|
}
|
|
4311
4479
|
|
|
4312
|
-
// src/commands
|
|
4480
|
+
// src/commands/doctor/checks/schema.ts
|
|
4313
4481
|
init_color();
|
|
4314
|
-
import { existsSync as
|
|
4315
|
-
import { join as
|
|
4482
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
4483
|
+
import { join as join27 } from "node:path";
|
|
4316
4484
|
init_config();
|
|
4317
4485
|
|
|
4318
|
-
// src/http-fetch.ts
|
|
4486
|
+
// src/core/http-fetch.ts
|
|
4319
4487
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
4320
4488
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
4321
4489
|
function fetchUrl(url, run = execFileSync8) {
|
|
@@ -4336,7 +4504,7 @@ function fetchUrl(url, run = execFileSync8) {
|
|
|
4336
4504
|
}
|
|
4337
4505
|
}
|
|
4338
4506
|
|
|
4339
|
-
// src/commands
|
|
4507
|
+
// src/commands/doctor/checks/schema.ts
|
|
4340
4508
|
function fetchSchemaKeys() {
|
|
4341
4509
|
try {
|
|
4342
4510
|
const raw = fetchUrl(SETTINGS_SCHEMA_URL);
|
|
@@ -4349,8 +4517,8 @@ function fetchSchemaKeys() {
|
|
|
4349
4517
|
}
|
|
4350
4518
|
}
|
|
4351
4519
|
function reportCheckSchema(section2) {
|
|
4352
|
-
const settingsPath =
|
|
4353
|
-
if (!
|
|
4520
|
+
const settingsPath = join27(claudeHome(), "settings.json");
|
|
4521
|
+
if (!existsSync20(settingsPath)) {
|
|
4354
4522
|
addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json to check`);
|
|
4355
4523
|
return;
|
|
4356
4524
|
}
|
|
@@ -4376,23 +4544,23 @@ function reportCheckSchema(section2) {
|
|
|
4376
4544
|
}
|
|
4377
4545
|
}
|
|
4378
4546
|
|
|
4379
|
-
// src/commands
|
|
4547
|
+
// src/commands/doctor/checks/shared.ts
|
|
4380
4548
|
init_color();
|
|
4381
4549
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
4382
4550
|
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
4383
|
-
import { existsSync as
|
|
4551
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync8, readdirSync as readdirSync12, rmSync as rmSync12 } from "node:fs";
|
|
4384
4552
|
import { homedir as homedir6 } from "node:os";
|
|
4385
|
-
import { join as
|
|
4553
|
+
import { join as join34 } from "node:path";
|
|
4386
4554
|
|
|
4387
|
-
// src/commands
|
|
4555
|
+
// src/commands/doctor/checks/shared.memory.ts
|
|
4388
4556
|
init_color();
|
|
4389
4557
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
4390
4558
|
import { randomBytes } from "node:crypto";
|
|
4391
4559
|
import { mkdirSync as mkdirSync4, rmSync as rmSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
4392
4560
|
import { homedir as homedir4 } from "node:os";
|
|
4393
|
-
import { dirname as
|
|
4561
|
+
import { dirname as dirname5, join as join29 } from "node:path";
|
|
4394
4562
|
init_config();
|
|
4395
|
-
|
|
4563
|
+
init_gitleaks();
|
|
4396
4564
|
init_utils_fs();
|
|
4397
4565
|
var MEMORY_MD_PATH = /^shared\/projects\/([^/]+)\/memory\/[^/]+\.md$/;
|
|
4398
4566
|
function buildMemoryScanTree(tmpRoot) {
|
|
@@ -4423,8 +4591,8 @@ function buildMemoryScanTree(tmpRoot) {
|
|
|
4423
4591
|
incomplete = true;
|
|
4424
4592
|
continue;
|
|
4425
4593
|
}
|
|
4426
|
-
const dest =
|
|
4427
|
-
mkdirSync4(
|
|
4594
|
+
const dest = join29(tmpRoot, rel);
|
|
4595
|
+
mkdirSync4(dirname5(dest), { recursive: true });
|
|
4428
4596
|
writeFileSync4(dest, blob);
|
|
4429
4597
|
logicals.add(m[1]);
|
|
4430
4598
|
}
|
|
@@ -4442,10 +4610,10 @@ function reportMemoryFindings(section2, findings) {
|
|
|
4442
4610
|
function reportCommittedMemory(section2) {
|
|
4443
4611
|
let tmpRoot;
|
|
4444
4612
|
try {
|
|
4445
|
-
const cacheDir =
|
|
4613
|
+
const cacheDir = join29(homedir4(), ".cache", "claude-nomad");
|
|
4446
4614
|
mkdirSync4(cacheDir, { recursive: true });
|
|
4447
4615
|
const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
4448
|
-
tmpRoot =
|
|
4616
|
+
tmpRoot = join29(cacheDir, `check-shared-memory-tree-${stamp}`);
|
|
4449
4617
|
mkdirSync4(tmpRoot, { recursive: true, mode: 448 });
|
|
4450
4618
|
const { staged, incomplete } = buildMemoryScanTree(tmpRoot);
|
|
4451
4619
|
if (incomplete) {
|
|
@@ -4490,14 +4658,14 @@ function reportCommittedMemory(section2) {
|
|
|
4490
4658
|
}
|
|
4491
4659
|
}
|
|
4492
4660
|
|
|
4493
|
-
// src/commands
|
|
4661
|
+
// src/commands/doctor/checks/shared.scan.ts
|
|
4494
4662
|
init_color();
|
|
4495
|
-
import { join as
|
|
4663
|
+
import { join as join30 } from "node:path";
|
|
4496
4664
|
init_config();
|
|
4497
|
-
|
|
4665
|
+
init_gitleaks();
|
|
4498
4666
|
function scrubPath(logical, sid, logicalToEncoded) {
|
|
4499
4667
|
const encoded = logicalToEncoded.get(logical) ?? logical;
|
|
4500
|
-
return
|
|
4668
|
+
return join30(claudeHome(), "projects", encoded, `${sid}.jsonl`);
|
|
4501
4669
|
}
|
|
4502
4670
|
function reportSessionFindings(section2, bySession) {
|
|
4503
4671
|
for (const [sid, counts] of bySession) {
|
|
@@ -4580,15 +4748,15 @@ function scanAndReport(section2, tmpRoot, staged, logicalToEncoded) {
|
|
|
4580
4748
|
emitDescriptionLegend(section2, findings);
|
|
4581
4749
|
}
|
|
4582
4750
|
|
|
4583
|
-
// src/commands
|
|
4751
|
+
// src/commands/doctor/checks/shared.skills.ts
|
|
4584
4752
|
init_color();
|
|
4585
4753
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
4586
4754
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
4587
4755
|
import { mkdirSync as mkdirSync5, rmSync as rmSync10, writeFileSync as writeFileSync5 } from "node:fs";
|
|
4588
4756
|
import { homedir as homedir5 } from "node:os";
|
|
4589
|
-
import { dirname as
|
|
4757
|
+
import { dirname as dirname6, join as join31 } from "node:path";
|
|
4590
4758
|
init_config();
|
|
4591
|
-
|
|
4759
|
+
init_gitleaks();
|
|
4592
4760
|
init_utils_fs();
|
|
4593
4761
|
var SKILL_PATH = /^shared\/skills\/([^/]+)\/(.+)$/;
|
|
4594
4762
|
function buildSkillScanTree(tmpRoot) {
|
|
@@ -4619,8 +4787,8 @@ function buildSkillScanTree(tmpRoot) {
|
|
|
4619
4787
|
incomplete = true;
|
|
4620
4788
|
continue;
|
|
4621
4789
|
}
|
|
4622
|
-
const dest =
|
|
4623
|
-
mkdirSync5(
|
|
4790
|
+
const dest = join31(tmpRoot, rel);
|
|
4791
|
+
mkdirSync5(dirname6(dest), { recursive: true });
|
|
4624
4792
|
writeFileSync5(dest, blob);
|
|
4625
4793
|
names.add(m[1]);
|
|
4626
4794
|
}
|
|
@@ -4642,10 +4810,10 @@ function reportSkillFindings(section2, findings) {
|
|
|
4642
4810
|
function reportCommittedSkills(section2) {
|
|
4643
4811
|
let tmpRoot;
|
|
4644
4812
|
try {
|
|
4645
|
-
const cacheDir =
|
|
4813
|
+
const cacheDir = join31(homedir5(), ".cache", "claude-nomad");
|
|
4646
4814
|
mkdirSync5(cacheDir, { recursive: true });
|
|
4647
4815
|
const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes2(4).toString("hex")}`;
|
|
4648
|
-
tmpRoot =
|
|
4816
|
+
tmpRoot = join31(cacheDir, `check-shared-skills-tree-${stamp}`);
|
|
4649
4817
|
mkdirSync5(tmpRoot, { recursive: true, mode: 448 });
|
|
4650
4818
|
const { staged, incomplete } = buildSkillScanTree(tmpRoot);
|
|
4651
4819
|
if (incomplete) {
|
|
@@ -4690,22 +4858,22 @@ function reportCommittedSkills(section2) {
|
|
|
4690
4858
|
}
|
|
4691
4859
|
}
|
|
4692
4860
|
|
|
4693
|
-
// src/commands
|
|
4861
|
+
// src/commands/doctor/checks/shared.ts
|
|
4694
4862
|
init_config();
|
|
4695
4863
|
|
|
4696
|
-
// src/remap.ts
|
|
4864
|
+
// src/sync/remap.ts
|
|
4697
4865
|
init_config_sharedDirs_guard();
|
|
4698
|
-
import { cpSync as cpSync5, existsSync as
|
|
4699
|
-
import { dirname as
|
|
4866
|
+
import { cpSync as cpSync5, existsSync as existsSync22, lstatSync as lstatSync13, mkdirSync as mkdirSync7, readdirSync as readdirSync11, rmSync as rmSync11, statSync as statSync6 } from "node:fs";
|
|
4867
|
+
import { dirname as dirname8, join as join33, relative as relative6, sep as sep5 } from "node:path";
|
|
4700
4868
|
init_config();
|
|
4701
4869
|
|
|
4702
|
-
// src/push
|
|
4870
|
+
// src/commands/push/manifest.ts
|
|
4703
4871
|
init_config();
|
|
4704
|
-
|
|
4872
|
+
init_gitleaks_config();
|
|
4705
4873
|
init_utils_fs();
|
|
4706
4874
|
import { createHash } from "node:crypto";
|
|
4707
|
-
import { existsSync as
|
|
4708
|
-
import { dirname as
|
|
4875
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync6, readdirSync as readdirSync10, readFileSync as readFileSync7, statSync as statSync5 } from "node:fs";
|
|
4876
|
+
import { dirname as dirname7, join as join32 } from "node:path";
|
|
4709
4877
|
function isChanged(prev, cur, hash) {
|
|
4710
4878
|
if (prev === void 0) return true;
|
|
4711
4879
|
if (prev.size !== cur.size) return true;
|
|
@@ -4746,7 +4914,7 @@ function hashFile(absPath) {
|
|
|
4746
4914
|
}
|
|
4747
4915
|
function enumerateDir(dir, results) {
|
|
4748
4916
|
for (const entry of readdirSync10(dir)) {
|
|
4749
|
-
const fullPath =
|
|
4917
|
+
const fullPath = join32(dir, entry);
|
|
4750
4918
|
const st = statSync5(fullPath);
|
|
4751
4919
|
if (st.isDirectory()) {
|
|
4752
4920
|
enumerateDir(fullPath, results);
|
|
@@ -4758,7 +4926,7 @@ function enumerateDir(dir, results) {
|
|
|
4758
4926
|
function enumerateSourceFiles(projectDir) {
|
|
4759
4927
|
const results = [];
|
|
4760
4928
|
for (const entry of readdirSync10(projectDir)) {
|
|
4761
|
-
const fullPath =
|
|
4929
|
+
const fullPath = join32(projectDir, entry);
|
|
4762
4930
|
const st = statSync5(fullPath);
|
|
4763
4931
|
if (st.isDirectory()) {
|
|
4764
4932
|
enumerateDir(fullPath, results);
|
|
@@ -4770,15 +4938,15 @@ function enumerateSourceFiles(projectDir) {
|
|
|
4770
4938
|
}
|
|
4771
4939
|
function fileIdentity(p) {
|
|
4772
4940
|
if (p === null) return "none::absent";
|
|
4773
|
-
if (!
|
|
4941
|
+
if (!existsSync21(p)) return `${p}::absent`;
|
|
4774
4942
|
return `${p}::${createHash("sha256").update(readFileSync7(p)).digest("hex")}`;
|
|
4775
4943
|
}
|
|
4776
4944
|
function computeConfigHash() {
|
|
4777
4945
|
const repo = repoHome();
|
|
4778
4946
|
const parts = [
|
|
4779
4947
|
fileIdentity(resolveTomlPath(repo)),
|
|
4780
|
-
fileIdentity(
|
|
4781
|
-
fileIdentity(
|
|
4948
|
+
fileIdentity(join32(repo, ".gitleaks.overlay.toml")),
|
|
4949
|
+
fileIdentity(join32(repo, ".gitleaksignore"))
|
|
4782
4950
|
];
|
|
4783
4951
|
return createHash("sha256").update(parts.join("\n")).digest("hex");
|
|
4784
4952
|
}
|
|
@@ -4798,14 +4966,14 @@ function readManifest(path) {
|
|
|
4798
4966
|
}
|
|
4799
4967
|
}
|
|
4800
4968
|
function writeManifest(path, manifest) {
|
|
4801
|
-
mkdirSync6(
|
|
4969
|
+
mkdirSync6(dirname7(path), { recursive: true });
|
|
4802
4970
|
writeJsonAtomic(path, manifest);
|
|
4803
4971
|
}
|
|
4804
4972
|
function buildManifest(files, scannerVersion, configHash) {
|
|
4805
4973
|
return { schema: 1, scannerVersion, configHash, files };
|
|
4806
4974
|
}
|
|
4807
4975
|
|
|
4808
|
-
// src/remap.ts
|
|
4976
|
+
// src/sync/remap.ts
|
|
4809
4977
|
init_utils();
|
|
4810
4978
|
init_utils_fs();
|
|
4811
4979
|
init_utils_json();
|
|
@@ -4822,16 +4990,15 @@ function overlaySessionDir(src, dst) {
|
|
|
4822
4990
|
cpSyncGuarded(src, dst, void 0, "overlaySessionDir");
|
|
4823
4991
|
}
|
|
4824
4992
|
function copyFileAtomic(src, dst) {
|
|
4825
|
-
mkdirSync7(
|
|
4993
|
+
mkdirSync7(dirname8(dst), { recursive: true });
|
|
4826
4994
|
const tmp = `${dst}.tmp.${process.pid}`;
|
|
4827
4995
|
cpSync5(src, tmp, { force: true, preserveTimestamps: true });
|
|
4828
4996
|
renameAtomicRetry(tmp, dst);
|
|
4829
4997
|
}
|
|
4830
4998
|
function hasDeltaForDir(sel, localDir) {
|
|
4831
4999
|
const prefix = `${localDir}${sep5}`;
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
return false;
|
|
5000
|
+
const underDir = (p) => p.startsWith(prefix);
|
|
5001
|
+
return [...sel.changed].some(underDir) || sel.deleted.some(underDir);
|
|
4835
5002
|
}
|
|
4836
5003
|
function skipForSelection(sel, localDir) {
|
|
4837
5004
|
return sel !== void 0 && !hasDeltaForDir(sel, localDir);
|
|
@@ -4840,12 +5007,12 @@ function applySelective(sel, localDir, repoDst) {
|
|
|
4840
5007
|
const prefix = `${localDir}${sep5}`;
|
|
4841
5008
|
for (const src of sel.changed) {
|
|
4842
5009
|
if (!src.startsWith(prefix)) continue;
|
|
4843
|
-
copyFileAtomic(src,
|
|
5010
|
+
copyFileAtomic(src, join33(repoDst, relative6(localDir, src)));
|
|
4844
5011
|
}
|
|
4845
5012
|
for (const src of sel.deleted) {
|
|
4846
5013
|
if (!src.startsWith(prefix)) continue;
|
|
4847
|
-
const dst =
|
|
4848
|
-
if (
|
|
5014
|
+
const dst = join33(repoDst, relative6(localDir, src));
|
|
5015
|
+
if (existsSync22(dst)) rmSync11(dst);
|
|
4849
5016
|
}
|
|
4850
5017
|
}
|
|
4851
5018
|
function copyDirJsonlOnly(src, dst) {
|
|
@@ -4874,15 +5041,15 @@ function remapPull(ts, opts = {}) {
|
|
|
4874
5041
|
const wouldPull = [];
|
|
4875
5042
|
const repo = repoHome();
|
|
4876
5043
|
const claude = claudeHome();
|
|
4877
|
-
const mapPath =
|
|
4878
|
-
const repoProjects =
|
|
4879
|
-
if (!
|
|
5044
|
+
const mapPath = join33(repo, "path-map.json");
|
|
5045
|
+
const repoProjects = join33(repo, "shared", "projects");
|
|
5046
|
+
if (!existsSync22(mapPath) || !existsSync22(repoProjects)) {
|
|
4880
5047
|
const text = "no path-map or repo projects dir; skipping session remap";
|
|
4881
5048
|
emitPreview(opts.onPreview, { kind: "note", text }, text);
|
|
4882
5049
|
return { unmapped: 0, pulled, wouldPull };
|
|
4883
5050
|
}
|
|
4884
5051
|
const map = readPathMap(mapPath);
|
|
4885
|
-
const localProjects =
|
|
5052
|
+
const localProjects = join33(claude, "projects");
|
|
4886
5053
|
if (!dryRun) mkdirSync7(localProjects, { recursive: true });
|
|
4887
5054
|
for (const [logical, hosts] of Object.entries(map.projects)) {
|
|
4888
5055
|
assertSafeLogical(logical);
|
|
@@ -4892,9 +5059,9 @@ function remapPull(ts, opts = {}) {
|
|
|
4892
5059
|
continue;
|
|
4893
5060
|
}
|
|
4894
5061
|
assertSafeLocalRoot(localPath, logical);
|
|
4895
|
-
const src =
|
|
4896
|
-
if (!
|
|
4897
|
-
const dst =
|
|
5062
|
+
const src = join33(repoProjects, logical);
|
|
5063
|
+
if (!existsSync22(src)) continue;
|
|
5064
|
+
const dst = join33(localProjects, encodePath(localPath));
|
|
4898
5065
|
if (dryRun) {
|
|
4899
5066
|
wouldPull.push(logical);
|
|
4900
5067
|
emitPreview(
|
|
@@ -4913,8 +5080,8 @@ function remapPull(ts, opts = {}) {
|
|
|
4913
5080
|
function countLocalOnly(src, dst) {
|
|
4914
5081
|
let count = 0;
|
|
4915
5082
|
for (const name of readdirSync11(dst)) {
|
|
4916
|
-
const dstPath =
|
|
4917
|
-
const srcPath =
|
|
5083
|
+
const dstPath = join33(dst, name);
|
|
5084
|
+
const srcPath = join33(src, name);
|
|
4918
5085
|
if (lstatSync13(dstPath).isDirectory()) {
|
|
4919
5086
|
count += countLocalOnly(srcPath, dstPath);
|
|
4920
5087
|
} else if (lstatSync13(srcPath, { throwIfNoEntry: false }) === void 0) {
|
|
@@ -4926,20 +5093,20 @@ function countLocalOnly(src, dst) {
|
|
|
4926
5093
|
function scanLocalOnly() {
|
|
4927
5094
|
const repo = repoHome();
|
|
4928
5095
|
const claude = claudeHome();
|
|
4929
|
-
const mapPath =
|
|
4930
|
-
const repoProjects =
|
|
4931
|
-
if (!
|
|
5096
|
+
const mapPath = join33(repo, "path-map.json");
|
|
5097
|
+
const repoProjects = join33(repo, "shared", "projects");
|
|
5098
|
+
if (!existsSync22(mapPath) || !existsSync22(repoProjects)) return 0;
|
|
4932
5099
|
const map = readPathMap(mapPath);
|
|
4933
|
-
const localProjects =
|
|
5100
|
+
const localProjects = join33(claude, "projects");
|
|
4934
5101
|
let count = 0;
|
|
4935
5102
|
for (const [logical, hosts] of Object.entries(map.projects)) {
|
|
4936
5103
|
assertSafeLogical(logical);
|
|
4937
5104
|
const localPath = hosts[HOST];
|
|
4938
5105
|
if (!localPath || localPath === "TBD") continue;
|
|
4939
5106
|
assertSafeLocalRoot(localPath, logical);
|
|
4940
|
-
const dst =
|
|
4941
|
-
if (!
|
|
4942
|
-
count += countLocalOnly(
|
|
5107
|
+
const dst = join33(localProjects, encodePath(localPath));
|
|
5108
|
+
if (!existsSync22(dst)) continue;
|
|
5109
|
+
count += countLocalOnly(join33(repoProjects, logical), dst);
|
|
4943
5110
|
}
|
|
4944
5111
|
return count;
|
|
4945
5112
|
}
|
|
@@ -4974,16 +5141,16 @@ function remapPush(ts, opts = {}) {
|
|
|
4974
5141
|
const wouldPush = [];
|
|
4975
5142
|
const repo = repoHome();
|
|
4976
5143
|
const claude = claudeHome();
|
|
4977
|
-
const mapPath =
|
|
4978
|
-
if (!
|
|
5144
|
+
const mapPath = join33(repo, "path-map.json");
|
|
5145
|
+
if (!existsSync22(mapPath)) {
|
|
4979
5146
|
log("no path-map.json; skipping session export");
|
|
4980
5147
|
return { unmapped: 0, collisions: 0, pushed, wouldPush };
|
|
4981
5148
|
}
|
|
4982
5149
|
const map = readPathMap(mapPath);
|
|
4983
|
-
const localProjects =
|
|
4984
|
-
const repoProjects =
|
|
5150
|
+
const localProjects = join33(claude, "projects");
|
|
5151
|
+
const repoProjects = join33(repo, "shared", "projects");
|
|
4985
5152
|
const reverse = buildReverseMap(map);
|
|
4986
|
-
if (!
|
|
5153
|
+
if (!existsSync22(localProjects)) return { unmapped, collisions: 0, pushed, wouldPush };
|
|
4987
5154
|
if (!dryRun) mkdirSync7(repoProjects, { recursive: true });
|
|
4988
5155
|
for (const dir of readdirSync11(localProjects)) {
|
|
4989
5156
|
if (dir.endsWith(TMP_SUFFIX)) continue;
|
|
@@ -4992,8 +5159,8 @@ function remapPush(ts, opts = {}) {
|
|
|
4992
5159
|
unmapped++;
|
|
4993
5160
|
continue;
|
|
4994
5161
|
}
|
|
4995
|
-
const localDir =
|
|
4996
|
-
const repoDst =
|
|
5162
|
+
const localDir = join33(localProjects, dir);
|
|
5163
|
+
const repoDst = join33(repoProjects, logical);
|
|
4997
5164
|
if (skipForSelection(opts.selection, localDir)) continue;
|
|
4998
5165
|
if (dryRun) {
|
|
4999
5166
|
wouldPush.push(logical);
|
|
@@ -5010,15 +5177,15 @@ function remapPush(ts, opts = {}) {
|
|
|
5010
5177
|
return { unmapped, collisions: 0, pushed, wouldPush };
|
|
5011
5178
|
}
|
|
5012
5179
|
|
|
5013
|
-
// src/commands
|
|
5180
|
+
// src/commands/doctor/checks/shared.ts
|
|
5014
5181
|
init_utils_fs();
|
|
5015
5182
|
init_utils_json();
|
|
5016
5183
|
function buildScanTree(tmpRoot) {
|
|
5017
5184
|
const logicalToEncoded = /* @__PURE__ */ new Map();
|
|
5018
5185
|
let staged = 0;
|
|
5019
5186
|
const repo = repoHome();
|
|
5020
|
-
const mapPath =
|
|
5021
|
-
if (!
|
|
5187
|
+
const mapPath = join34(repo, "path-map.json");
|
|
5188
|
+
if (!existsSync23(mapPath)) return { logicalToEncoded, staged, malformed: false };
|
|
5022
5189
|
let map;
|
|
5023
5190
|
try {
|
|
5024
5191
|
map = readJson(mapPath);
|
|
@@ -5035,12 +5202,12 @@ function buildScanTree(tmpRoot) {
|
|
|
5035
5202
|
if (!p || p === "TBD") continue;
|
|
5036
5203
|
reverse.set(encodePath(p), logical);
|
|
5037
5204
|
}
|
|
5038
|
-
const localProjects =
|
|
5039
|
-
if (!
|
|
5205
|
+
const localProjects = join34(claudeHome(), "projects");
|
|
5206
|
+
if (!existsSync23(localProjects)) return { logicalToEncoded, staged, malformed: false };
|
|
5040
5207
|
for (const dir of readdirSync12(localProjects)) {
|
|
5041
5208
|
const logical = reverse.get(dir);
|
|
5042
5209
|
if (!logical) continue;
|
|
5043
|
-
copyDirJsonlOnly(
|
|
5210
|
+
copyDirJsonlOnly(join34(localProjects, dir), join34(tmpRoot, "shared", "projects", logical));
|
|
5044
5211
|
logicalToEncoded.set(logical, dir);
|
|
5045
5212
|
staged++;
|
|
5046
5213
|
}
|
|
@@ -5070,11 +5237,11 @@ function ensureGitleaksReady(section2, gitleaksReady) {
|
|
|
5070
5237
|
return true;
|
|
5071
5238
|
}
|
|
5072
5239
|
function runLocalPreviewScan(section2) {
|
|
5073
|
-
const cacheDir =
|
|
5240
|
+
const cacheDir = join34(homedir6(), ".cache", "claude-nomad");
|
|
5074
5241
|
mkdirSync8(cacheDir, { recursive: true });
|
|
5075
5242
|
const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes3(4).toString("hex")}`;
|
|
5076
|
-
const reportPath =
|
|
5077
|
-
const tmpRoot =
|
|
5243
|
+
const reportPath = join34(cacheDir, `check-shared-${stamp}.json`);
|
|
5244
|
+
const tmpRoot = join34(cacheDir, `check-shared-tree-${stamp}`);
|
|
5078
5245
|
try {
|
|
5079
5246
|
const { logicalToEncoded, staged, malformed } = buildScanTree(tmpRoot);
|
|
5080
5247
|
if (malformed) {
|
|
@@ -5105,10 +5272,10 @@ function reportCheckShared(section2, gitleaksReady) {
|
|
|
5105
5272
|
}
|
|
5106
5273
|
}
|
|
5107
5274
|
|
|
5108
|
-
// src/commands
|
|
5275
|
+
// src/commands/doctor/checks/hooks.scope.ts
|
|
5109
5276
|
init_color();
|
|
5110
|
-
import { existsSync as
|
|
5111
|
-
import { dirname as
|
|
5277
|
+
import { existsSync as existsSync24, readFileSync as readFileSync8, readdirSync as readdirSync13, realpathSync as realpathSync3 } from "node:fs";
|
|
5278
|
+
import { dirname as dirname9, extname, join as join35 } from "node:path";
|
|
5112
5279
|
init_config();
|
|
5113
5280
|
function typeFromPackageJson(pkgPath) {
|
|
5114
5281
|
try {
|
|
@@ -5128,11 +5295,11 @@ function effectiveType(hookPath) {
|
|
|
5128
5295
|
} catch {
|
|
5129
5296
|
return null;
|
|
5130
5297
|
}
|
|
5131
|
-
let dir =
|
|
5298
|
+
let dir = dirname9(real);
|
|
5132
5299
|
for (; ; ) {
|
|
5133
|
-
const pkg =
|
|
5134
|
-
if (
|
|
5135
|
-
const parent =
|
|
5300
|
+
const pkg = join35(dir, "package.json");
|
|
5301
|
+
if (existsSync24(pkg)) return typeFromPackageJson(pkg);
|
|
5302
|
+
const parent = dirname9(dir);
|
|
5136
5303
|
if (parent === dir) return "cjs";
|
|
5137
5304
|
dir = parent;
|
|
5138
5305
|
}
|
|
@@ -5173,15 +5340,15 @@ function safeRead(path) {
|
|
|
5173
5340
|
}
|
|
5174
5341
|
}
|
|
5175
5342
|
function reportHookScopeCheck(section2) {
|
|
5176
|
-
const hooksDir =
|
|
5177
|
-
if (!
|
|
5343
|
+
const hooksDir = join35(claudeHome(), "hooks");
|
|
5344
|
+
if (!existsSync24(hooksDir)) {
|
|
5178
5345
|
addItem(section2, `${dim(infoGlyph)} no ~/.claude/hooks; skipping module-scope check`);
|
|
5179
5346
|
return;
|
|
5180
5347
|
}
|
|
5181
5348
|
let anyWarn = false;
|
|
5182
5349
|
for (const name of safeReaddir2(hooksDir)) {
|
|
5183
5350
|
if (extname(name) !== ".js") continue;
|
|
5184
|
-
const abs =
|
|
5351
|
+
const abs = join35(hooksDir, name);
|
|
5185
5352
|
const eff = effectiveType(abs);
|
|
5186
5353
|
if (eff === null) continue;
|
|
5187
5354
|
const src = safeRead(abs);
|
|
@@ -5199,10 +5366,10 @@ function reportHookScopeCheck(section2) {
|
|
|
5199
5366
|
}
|
|
5200
5367
|
}
|
|
5201
5368
|
|
|
5202
|
-
// src/commands
|
|
5369
|
+
// src/commands/doctor/checks/hooks.ts
|
|
5203
5370
|
init_color();
|
|
5204
|
-
import { existsSync as
|
|
5205
|
-
import { join as
|
|
5371
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
5372
|
+
import { join as join36 } from "node:path";
|
|
5206
5373
|
init_config();
|
|
5207
5374
|
function expandHome(token) {
|
|
5208
5375
|
const h2 = home();
|
|
@@ -5245,7 +5412,7 @@ function checkEventGroups(section2, event, groups) {
|
|
|
5245
5412
|
for (const group of groups) {
|
|
5246
5413
|
for (const cmd of commandsFromGroup(group)) {
|
|
5247
5414
|
for (const resolved of claudePathsIn(cmd)) {
|
|
5248
|
-
if (
|
|
5415
|
+
if (existsSync25(resolved)) continue;
|
|
5249
5416
|
addItem(
|
|
5250
5417
|
section2,
|
|
5251
5418
|
`${red(failGlyph)} hooks/${event}: command target missing: ${resolved} (run nomad pull)`
|
|
@@ -5258,8 +5425,8 @@ function checkEventGroups(section2, event, groups) {
|
|
|
5258
5425
|
return anyFail;
|
|
5259
5426
|
}
|
|
5260
5427
|
function reportHooksTargetCheck(section2) {
|
|
5261
|
-
const settingsPath =
|
|
5262
|
-
if (!
|
|
5428
|
+
const settingsPath = join36(claudeHome(), "settings.json");
|
|
5429
|
+
if (!existsSync25(settingsPath)) {
|
|
5263
5430
|
addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json; skipping hook target check`);
|
|
5264
5431
|
return;
|
|
5265
5432
|
}
|
|
@@ -5280,17 +5447,17 @@ function reportHooksTargetCheck(section2) {
|
|
|
5280
5447
|
}
|
|
5281
5448
|
}
|
|
5282
5449
|
|
|
5283
|
-
// src/commands
|
|
5450
|
+
// src/commands/doctor/checks/hooks.preserve-symlinks.ts
|
|
5284
5451
|
init_color();
|
|
5285
|
-
import { existsSync as
|
|
5286
|
-
import { join as
|
|
5452
|
+
import { existsSync as existsSync27, readFileSync as readFileSync9 } from "node:fs";
|
|
5453
|
+
import { join as join38 } from "node:path";
|
|
5287
5454
|
|
|
5288
|
-
// src/commands
|
|
5289
|
-
import { closeSync as closeSync3, existsSync as
|
|
5290
|
-
import { dirname as
|
|
5455
|
+
// src/commands/doctor/checks/hooks.preserve-symlinks.probe.ts
|
|
5456
|
+
import { closeSync as closeSync3, existsSync as existsSync26, openSync as openSync3, readSync, realpathSync as realpathSync4 } from "node:fs";
|
|
5457
|
+
import { dirname as dirname10, join as join37, resolve as resolve3 } from "node:path";
|
|
5291
5458
|
function suppressedRanges(src) {
|
|
5292
5459
|
const ranges = [];
|
|
5293
|
-
const re = /\/\*[
|
|
5460
|
+
const re = /\/\*[^]*?\*\/|\/\/[^\n]*|(['"`])(?:\\[^]|[^\\])*?\1/g;
|
|
5294
5461
|
let m;
|
|
5295
5462
|
while ((m = re.exec(src)) !== null) {
|
|
5296
5463
|
ranges.push([m.index, m.index + m[0].length]);
|
|
@@ -5303,7 +5470,7 @@ function inSuppressedRange(pos, ranges) {
|
|
|
5303
5470
|
}
|
|
5304
5471
|
return false;
|
|
5305
5472
|
}
|
|
5306
|
-
function
|
|
5473
|
+
function relativeSpecifiers(src) {
|
|
5307
5474
|
const ranges = suppressedRanges(src);
|
|
5308
5475
|
const specifiers = [];
|
|
5309
5476
|
const reqRe = /\brequire\s*\(\s*(['"])(\.\.?\/[^'"]*)\1\s*\)/g;
|
|
@@ -5319,12 +5486,12 @@ function topRelativeSpecifiers(src) {
|
|
|
5319
5486
|
}
|
|
5320
5487
|
function specifierIsMissing(specifier, baseDir) {
|
|
5321
5488
|
const base = resolve3(baseDir, specifier);
|
|
5322
|
-
if (
|
|
5489
|
+
if (existsSync26(base)) return false;
|
|
5323
5490
|
for (const ext of [".js", ".cjs", ".mjs"]) {
|
|
5324
|
-
if (
|
|
5491
|
+
if (existsSync26(base + ext)) return false;
|
|
5325
5492
|
}
|
|
5326
5493
|
for (const idx of ["index.js", "index.cjs", "index.mjs"]) {
|
|
5327
|
-
if (
|
|
5494
|
+
if (existsSync26(join37(base, idx))) return false;
|
|
5328
5495
|
}
|
|
5329
5496
|
return true;
|
|
5330
5497
|
}
|
|
@@ -5348,16 +5515,16 @@ function relativeRequireTargetsBroken(scriptPath) {
|
|
|
5348
5515
|
} catch {
|
|
5349
5516
|
return false;
|
|
5350
5517
|
}
|
|
5351
|
-
const specifiers =
|
|
5518
|
+
const specifiers = relativeSpecifiers(raw);
|
|
5352
5519
|
if (specifiers.length === 0) return false;
|
|
5353
|
-
const baseDir =
|
|
5520
|
+
const baseDir = dirname10(realPath);
|
|
5354
5521
|
for (const spec of specifiers) {
|
|
5355
5522
|
if (specifierIsMissing(spec, baseDir)) return true;
|
|
5356
5523
|
}
|
|
5357
5524
|
return false;
|
|
5358
5525
|
}
|
|
5359
5526
|
|
|
5360
|
-
// src/commands
|
|
5527
|
+
// src/commands/doctor/checks/hooks.preserve-symlinks.ts
|
|
5361
5528
|
init_config();
|
|
5362
5529
|
function expandHome2(token) {
|
|
5363
5530
|
const h2 = home();
|
|
@@ -5379,8 +5546,8 @@ function commandTokens(command) {
|
|
|
5379
5546
|
return tokens;
|
|
5380
5547
|
}
|
|
5381
5548
|
function readPathMapSafe() {
|
|
5382
|
-
const mapPath =
|
|
5383
|
-
if (!
|
|
5549
|
+
const mapPath = join38(repoHome(), "path-map.json");
|
|
5550
|
+
if (!existsSync27(mapPath)) return { projects: {} };
|
|
5384
5551
|
try {
|
|
5385
5552
|
return JSON.parse(readFileSync9(mapPath, "utf8"));
|
|
5386
5553
|
} catch {
|
|
@@ -5454,8 +5621,8 @@ function checkEventForPreserveSymlinks(section2, event, groups, sharedLinkNames)
|
|
|
5454
5621
|
return anyWarn;
|
|
5455
5622
|
}
|
|
5456
5623
|
function reportPreserveSymlinksCheck(section2) {
|
|
5457
|
-
const settingsPath =
|
|
5458
|
-
if (!
|
|
5624
|
+
const settingsPath = join38(claudeHome(), "settings.json");
|
|
5625
|
+
if (!existsSync27(settingsPath)) {
|
|
5459
5626
|
addItem(
|
|
5460
5627
|
section2,
|
|
5461
5628
|
`${dim(infoGlyph)} no ~/.claude/settings.json; skipping preserve-symlinks-main check`
|
|
@@ -5486,10 +5653,10 @@ function reportPreserveSymlinksCheck(section2) {
|
|
|
5486
5653
|
}
|
|
5487
5654
|
}
|
|
5488
5655
|
|
|
5489
|
-
// src/commands
|
|
5656
|
+
// src/commands/doctor/checks/settings-drift.ts
|
|
5490
5657
|
init_color();
|
|
5491
|
-
import { existsSync as
|
|
5492
|
-
import { join as
|
|
5658
|
+
import { existsSync as existsSync28, readFileSync as readFileSync10 } from "node:fs";
|
|
5659
|
+
import { join as join39 } from "node:path";
|
|
5493
5660
|
init_config();
|
|
5494
5661
|
init_utils_json();
|
|
5495
5662
|
function diffMergedSettings(merged, settings) {
|
|
@@ -5507,7 +5674,7 @@ function tryReadJson(filePath) {
|
|
|
5507
5674
|
}
|
|
5508
5675
|
}
|
|
5509
5676
|
function reportHooksBaseSelfCleanNote(section2) {
|
|
5510
|
-
const basePath =
|
|
5677
|
+
const basePath = join39(repoHome(), "shared", "settings.base.json");
|
|
5511
5678
|
const base = tryReadJson(basePath);
|
|
5512
5679
|
if (base === null) return;
|
|
5513
5680
|
if (!baseHasGsdHookEntries(base)) return;
|
|
@@ -5520,14 +5687,14 @@ function reportSettingsDriftCheck(section2) {
|
|
|
5520
5687
|
const claude = claudeHome();
|
|
5521
5688
|
const repo = repoHome();
|
|
5522
5689
|
const host = HOST;
|
|
5523
|
-
const settingsPath =
|
|
5524
|
-
const basePath =
|
|
5525
|
-
const hostPath =
|
|
5526
|
-
if (!
|
|
5690
|
+
const settingsPath = join39(claude, "settings.json");
|
|
5691
|
+
const basePath = join39(repo, "shared", "settings.base.json");
|
|
5692
|
+
const hostPath = join39(repo, "hosts", `${host}.json`);
|
|
5693
|
+
if (!existsSync28(settingsPath)) {
|
|
5527
5694
|
addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json; skipping merge-drift check`);
|
|
5528
5695
|
return;
|
|
5529
5696
|
}
|
|
5530
|
-
if (!
|
|
5697
|
+
if (!existsSync28(basePath)) {
|
|
5531
5698
|
addItem(
|
|
5532
5699
|
section2,
|
|
5533
5700
|
`${dim(infoGlyph)} shared/settings.base.json missing; skipping merge-drift check`
|
|
@@ -5546,7 +5713,7 @@ function reportSettingsDriftCheck(section2) {
|
|
|
5546
5713
|
if (settings === null) {
|
|
5547
5714
|
return;
|
|
5548
5715
|
}
|
|
5549
|
-
const hostExists =
|
|
5716
|
+
const hostExists = existsSync28(hostPath);
|
|
5550
5717
|
const hostObj = hostExists ? tryReadJson(hostPath) : null;
|
|
5551
5718
|
if (hostExists && hostObj === null) {
|
|
5552
5719
|
addItem(
|
|
@@ -5590,19 +5757,20 @@ function emitDriftRows(section2, missing, changed, promotable, excluded, hostFil
|
|
|
5590
5757
|
}
|
|
5591
5758
|
}
|
|
5592
5759
|
|
|
5593
|
-
// src/commands
|
|
5760
|
+
// src/commands/doctor/doctor.ts
|
|
5594
5761
|
init_config();
|
|
5595
5762
|
|
|
5596
|
-
// src/commands
|
|
5763
|
+
// src/commands/doctor/engine.ts
|
|
5597
5764
|
init_color();
|
|
5598
5765
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
5599
|
-
import {
|
|
5766
|
+
import { join as join41 } from "node:path";
|
|
5600
5767
|
|
|
5601
|
-
// src/commands
|
|
5768
|
+
// src/commands/doctor/version.ts
|
|
5602
5769
|
init_color();
|
|
5603
5770
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
5604
|
-
import {
|
|
5771
|
+
import { join as join40 } from "node:path";
|
|
5605
5772
|
init_config();
|
|
5773
|
+
init_package_root();
|
|
5606
5774
|
var STRICT_SEMVER = /^\d+\.\d+\.\d+$/;
|
|
5607
5775
|
var STRICT_SEMVER_PREFIX = /^(\d+\.\d+\.\d+)(?:[-+]|$)/;
|
|
5608
5776
|
function compareSemver(a, b) {
|
|
@@ -5616,7 +5784,7 @@ function compareSemver(a, b) {
|
|
|
5616
5784
|
}
|
|
5617
5785
|
function readLocalVersion() {
|
|
5618
5786
|
try {
|
|
5619
|
-
const pkgPath =
|
|
5787
|
+
const pkgPath = join40(packageRoot(), "package.json");
|
|
5620
5788
|
const parsed = JSON.parse(readFileSync11(pkgPath, "utf8"));
|
|
5621
5789
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
5622
5790
|
return parsed.version;
|
|
@@ -5667,7 +5835,8 @@ function reportVersionCheck(section2) {
|
|
|
5667
5835
|
}
|
|
5668
5836
|
}
|
|
5669
5837
|
|
|
5670
|
-
// src/commands
|
|
5838
|
+
// src/commands/doctor/engine.ts
|
|
5839
|
+
init_package_root();
|
|
5671
5840
|
var ENGINES_GTE = /^>=\s*(\d+\.\d+\.\d+)$/;
|
|
5672
5841
|
function parseMinVersion(spec) {
|
|
5673
5842
|
const m = ENGINES_GTE.exec(spec);
|
|
@@ -5675,7 +5844,7 @@ function parseMinVersion(spec) {
|
|
|
5675
5844
|
}
|
|
5676
5845
|
function readEnginesNode() {
|
|
5677
5846
|
try {
|
|
5678
|
-
const pkgPath =
|
|
5847
|
+
const pkgPath = join41(packageRoot(), "package.json");
|
|
5679
5848
|
const parsed = JSON.parse(readFileSync12(pkgPath, "utf8"));
|
|
5680
5849
|
const node = parsed.engines?.node;
|
|
5681
5850
|
if (typeof node === "string" && node.length > 0) return node;
|
|
@@ -5702,7 +5871,7 @@ function reportNodeEngineCheck(section2) {
|
|
|
5702
5871
|
addItem(section2, `${green(okGlyph)} node: ${process.version}`);
|
|
5703
5872
|
}
|
|
5704
5873
|
|
|
5705
|
-
// src/commands
|
|
5874
|
+
// src/commands/doctor/checks/longpaths.ts
|
|
5706
5875
|
init_color();
|
|
5707
5876
|
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
5708
5877
|
init_config();
|
|
@@ -5760,18 +5929,18 @@ function reportSyncModality(section2) {
|
|
|
5760
5929
|
addItem(section2, `${dim(infoGlyph)} sync modality: ${modality}`);
|
|
5761
5930
|
}
|
|
5762
5931
|
|
|
5763
|
-
// src/commands
|
|
5932
|
+
// src/commands/doctor/checks/crlf.ts
|
|
5764
5933
|
init_color();
|
|
5765
5934
|
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
5766
|
-
import { existsSync as
|
|
5767
|
-
import { join as
|
|
5935
|
+
import { existsSync as existsSync29, readFileSync as readFileSync13 } from "node:fs";
|
|
5936
|
+
import { join as join42 } from "node:path";
|
|
5768
5937
|
init_config();
|
|
5769
5938
|
var PROBE_TIMEOUT_MS3 = 3e3;
|
|
5770
5939
|
var GUARD_LINE = /^\*\s+-text\b/;
|
|
5771
5940
|
function hasGitattributesGuard(repo) {
|
|
5772
5941
|
try {
|
|
5773
|
-
const path =
|
|
5774
|
-
if (!
|
|
5942
|
+
const path = join42(repo, ".gitattributes");
|
|
5943
|
+
if (!existsSync29(path)) return false;
|
|
5775
5944
|
const content = readFileSync13(path, "utf8");
|
|
5776
5945
|
return content.split("\n").map((line) => line.trim()).some((line) => line !== "" && !line.startsWith("#") && GUARD_LINE.test(line));
|
|
5777
5946
|
} catch {
|
|
@@ -5810,24 +5979,24 @@ function reportCrlfGuardCheck(section2, run = execFileSync14) {
|
|
|
5810
5979
|
addExposedRow(section2, repo, probeAutocrlf(repo, run));
|
|
5811
5980
|
}
|
|
5812
5981
|
|
|
5813
|
-
// src/spinner.ts
|
|
5982
|
+
// src/render/spinner.ts
|
|
5814
5983
|
init_color();
|
|
5815
|
-
import { existsSync as
|
|
5816
|
-
import { fileURLToPath as
|
|
5984
|
+
import { existsSync as existsSync34 } from "node:fs";
|
|
5985
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5817
5986
|
import { Worker } from "node:worker_threads";
|
|
5818
5987
|
|
|
5819
|
-
// src/commands
|
|
5988
|
+
// src/commands/push/recovery/recovery.ts
|
|
5820
5989
|
init_config();
|
|
5821
5990
|
import { readFileSync as readFileSync18, rmSync as rmSync15, writeFileSync as writeFileSync9 } from "node:fs";
|
|
5822
|
-
import { join as
|
|
5991
|
+
import { join as join50 } from "node:path";
|
|
5823
5992
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
5824
5993
|
|
|
5825
|
-
// src/commands
|
|
5994
|
+
// src/commands/push/recovery/actions.ts
|
|
5826
5995
|
init_config();
|
|
5827
5996
|
import { readFileSync as readFileSync17 } from "node:fs";
|
|
5828
5997
|
import { isAbsolute as isAbsolute2, resolve as resolve4, sep as sep9 } from "node:path";
|
|
5829
5998
|
|
|
5830
|
-
// src/commands
|
|
5999
|
+
// src/commands/push/recovery/memory.ts
|
|
5831
6000
|
init_config();
|
|
5832
6001
|
init_config_sharedDirs_guard();
|
|
5833
6002
|
import {
|
|
@@ -5839,17 +6008,17 @@ import {
|
|
|
5839
6008
|
statSync as statSync7,
|
|
5840
6009
|
writeFileSync as writeFileSync6
|
|
5841
6010
|
} from "node:fs";
|
|
5842
|
-
import { dirname as
|
|
5843
|
-
|
|
6011
|
+
import { dirname as dirname11, join as join43, sep as sep6 } from "node:path";
|
|
6012
|
+
init_gitleaks_scan();
|
|
5844
6013
|
|
|
5845
|
-
// src/rel-path-guard.ts
|
|
6014
|
+
// src/core/rel-path-guard.ts
|
|
5846
6015
|
function isSafeRelPath(relPath) {
|
|
5847
6016
|
if (relPath.length === 0 || relPath.startsWith("/") || relPath.includes("\\")) return false;
|
|
5848
6017
|
const segments = relPath.split("/");
|
|
5849
6018
|
return segments.every((s) => s.length > 0 && s !== "." && s !== "..");
|
|
5850
6019
|
}
|
|
5851
6020
|
|
|
5852
|
-
// src/commands
|
|
6021
|
+
// src/commands/push/recovery/memory.ts
|
|
5853
6022
|
init_utils_fs();
|
|
5854
6023
|
init_utils_json();
|
|
5855
6024
|
init_utils();
|
|
@@ -5868,8 +6037,8 @@ function resolveMemoryLocalPath(logical, relPath, map) {
|
|
|
5868
6037
|
if (!isSafeRelPath(relPath)) return null;
|
|
5869
6038
|
const abs = map.projects[logical]?.[HOST];
|
|
5870
6039
|
if (abs === void 0) return null;
|
|
5871
|
-
const memoryRoot =
|
|
5872
|
-
const localPath =
|
|
6040
|
+
const memoryRoot = join43(claudeHome(), "projects", encodePath(abs), "memory");
|
|
6041
|
+
const localPath = join43(memoryRoot, ...relPath.split("/"));
|
|
5873
6042
|
if (localPath !== memoryRoot && !localPath.startsWith(memoryRoot + sep6)) return null;
|
|
5874
6043
|
try {
|
|
5875
6044
|
if (lstatSync14(localPath).isSymbolicLink()) return null;
|
|
@@ -5923,13 +6092,13 @@ function applyMemoryRedact(f, ts, map, scan = scanFile) {
|
|
|
5923
6092
|
);
|
|
5924
6093
|
}
|
|
5925
6094
|
writeFileSync6(localPath, after, "utf8");
|
|
5926
|
-
const dest =
|
|
5927
|
-
mkdirSync9(
|
|
6095
|
+
const dest = join43(repoHome(), "shared", "projects", logical, "memory", ...relPath.split("/"));
|
|
6096
|
+
mkdirSync9(dirname11(dest), { recursive: true });
|
|
5928
6097
|
cpSync6(localPath, dest, { force: true });
|
|
5929
6098
|
return true;
|
|
5930
6099
|
}
|
|
5931
6100
|
|
|
5932
|
-
// src/commands
|
|
6101
|
+
// src/commands/push/recovery/skills.ts
|
|
5933
6102
|
init_config();
|
|
5934
6103
|
import {
|
|
5935
6104
|
cpSync as cpSync7,
|
|
@@ -5940,27 +6109,27 @@ import {
|
|
|
5940
6109
|
statSync as statSync8,
|
|
5941
6110
|
writeFileSync as writeFileSync7
|
|
5942
6111
|
} from "node:fs";
|
|
5943
|
-
import { dirname as
|
|
6112
|
+
import { dirname as dirname12, join as join45, sep as sep7 } from "node:path";
|
|
5944
6113
|
|
|
5945
|
-
// src/skills-sync.ts
|
|
6114
|
+
// src/sync/skills-sync.ts
|
|
5946
6115
|
init_config();
|
|
5947
|
-
import { existsSync as
|
|
5948
|
-
import { join as
|
|
6116
|
+
import { existsSync as existsSync30, lstatSync as lstatSync15, mkdirSync as mkdirSync10, readdirSync as readdirSync14, rmSync as rmSync13 } from "node:fs";
|
|
6117
|
+
import { join as join44 } from "node:path";
|
|
5949
6118
|
|
|
5950
|
-
// src/skills-sync.tracked.ts
|
|
6119
|
+
// src/sync/skills-sync.tracked.ts
|
|
5951
6120
|
init_utils();
|
|
5952
|
-
import { basename as
|
|
6121
|
+
import { basename as basename4 } from "node:path";
|
|
5953
6122
|
function trackedRootSkillsAt(ref, repo) {
|
|
5954
6123
|
try {
|
|
5955
6124
|
const raw = gitCaptureRaw(["ls-tree", "--name-only", "-z", ref, "--", "shared/skills/"], repo);
|
|
5956
6125
|
const entries = raw.split("\0").filter((entry) => entry !== "");
|
|
5957
|
-
return new Set(entries.map((entry) =>
|
|
6126
|
+
return new Set(entries.map((entry) => basename4(entry)));
|
|
5958
6127
|
} catch {
|
|
5959
6128
|
return /* @__PURE__ */ new Set();
|
|
5960
6129
|
}
|
|
5961
6130
|
}
|
|
5962
6131
|
|
|
5963
|
-
// src/skills-sync.ts
|
|
6132
|
+
// src/sync/skills-sync.ts
|
|
5964
6133
|
init_utils_fs();
|
|
5965
6134
|
function isGsdOwned(name) {
|
|
5966
6135
|
return name.startsWith(GSD_PREFIX);
|
|
@@ -5980,9 +6149,9 @@ function copySkillsPull(src, dst, isRootPreserved) {
|
|
|
5980
6149
|
copyExtrasFilteredPreservingBy(src, dst, isSkillExcluded, isRootPreserved);
|
|
5981
6150
|
}
|
|
5982
6151
|
function syncSkillsPull(ts, prePostHeads) {
|
|
5983
|
-
const sharedSkills =
|
|
5984
|
-
if (!
|
|
5985
|
-
const localSkills =
|
|
6152
|
+
const sharedSkills = join44(repoHome(), "shared", "skills");
|
|
6153
|
+
if (!existsSync30(sharedSkills)) return;
|
|
6154
|
+
const localSkills = join44(claudeHome(), "skills");
|
|
5986
6155
|
backupBeforeWrite(localSkills, ts);
|
|
5987
6156
|
const dstStat = lstatSync15(localSkills, { throwIfNoEntry: false });
|
|
5988
6157
|
if (dstStat?.isSymbolicLink() === true) {
|
|
@@ -5993,16 +6162,16 @@ function syncSkillsPull(ts, prePostHeads) {
|
|
|
5993
6162
|
copySkillsPull(sharedSkills, localSkills, (name) => !tracked.has(name));
|
|
5994
6163
|
}
|
|
5995
6164
|
function syncSkillsPush() {
|
|
5996
|
-
const localSkills =
|
|
6165
|
+
const localSkills = join44(claudeHome(), "skills");
|
|
5997
6166
|
const stat = lstatSync15(localSkills, { throwIfNoEntry: false });
|
|
5998
6167
|
if (stat === void 0) return;
|
|
5999
6168
|
if (stat.isSymbolicLink()) return;
|
|
6000
|
-
const sharedSkills =
|
|
6169
|
+
const sharedSkills = join44(repoHome(), "shared", "skills");
|
|
6001
6170
|
copySkillsPush(localSkills, sharedSkills);
|
|
6002
6171
|
}
|
|
6003
6172
|
|
|
6004
|
-
// src/commands
|
|
6005
|
-
|
|
6173
|
+
// src/commands/push/recovery/skills.ts
|
|
6174
|
+
init_gitleaks_scan();
|
|
6006
6175
|
init_utils_fs();
|
|
6007
6176
|
init_utils();
|
|
6008
6177
|
var SKILL_FINDING_PATH = /^shared\/skills\/([^/]+)\/(.+)$/;
|
|
@@ -6020,9 +6189,9 @@ function resolveSkillLocalPath(name, relPath) {
|
|
|
6020
6189
|
if (!SAFE_SKILL_NAME.test(name) || name === "." || name === "..") return null;
|
|
6021
6190
|
if (isGsdOwned(name)) return null;
|
|
6022
6191
|
if (!isSafeRelPath(relPath)) return null;
|
|
6023
|
-
const skillsRoot =
|
|
6024
|
-
const skillRoot =
|
|
6025
|
-
const localPath =
|
|
6192
|
+
const skillsRoot = join45(claudeHome(), "skills");
|
|
6193
|
+
const skillRoot = join45(skillsRoot, name);
|
|
6194
|
+
const localPath = join45(skillRoot, ...relPath.split("/"));
|
|
6026
6195
|
if (localPath !== skillRoot && !localPath.startsWith(skillRoot + sep7)) return null;
|
|
6027
6196
|
try {
|
|
6028
6197
|
if (lstatSync16(localPath).isSymbolicLink()) return null;
|
|
@@ -6074,17 +6243,17 @@ function applySkillRedact(f, ts, scan = scanFile) {
|
|
|
6074
6243
|
);
|
|
6075
6244
|
}
|
|
6076
6245
|
writeFileSync7(localPath, after, "utf8");
|
|
6077
|
-
const dest =
|
|
6078
|
-
mkdirSync11(
|
|
6246
|
+
const dest = join45(repoHome(), "shared", "skills", name, ...relPath.split("/"));
|
|
6247
|
+
mkdirSync11(dirname12(dest), { recursive: true });
|
|
6079
6248
|
cpSync7(localPath, dest, { force: true });
|
|
6080
6249
|
return true;
|
|
6081
6250
|
}
|
|
6082
6251
|
|
|
6083
|
-
// src/commands
|
|
6252
|
+
// src/commands/push/recovery/allow-gate.ts
|
|
6084
6253
|
init_utils();
|
|
6085
6254
|
|
|
6086
|
-
// src/commands
|
|
6087
|
-
|
|
6255
|
+
// src/commands/push/recovery/seams.ts
|
|
6256
|
+
init_gitleaks();
|
|
6088
6257
|
function findingKey(f) {
|
|
6089
6258
|
return `${f.File}:${f.StartLine}:${f.StartColumn}:${f.RuleID}`;
|
|
6090
6259
|
}
|
|
@@ -6105,7 +6274,7 @@ function parseAction(raw) {
|
|
|
6105
6274
|
return "skip";
|
|
6106
6275
|
}
|
|
6107
6276
|
|
|
6108
|
-
// src/commands
|
|
6277
|
+
// src/commands/push/recovery/allow-gate.ts
|
|
6109
6278
|
function isCleared(f, state) {
|
|
6110
6279
|
const action = state.actions.get(findingKey(f)) ?? "skip";
|
|
6111
6280
|
if (action === "allow") return true;
|
|
@@ -6149,28 +6318,28 @@ function applyDeferredAllows(findings, state, repo) {
|
|
|
6149
6318
|
}
|
|
6150
6319
|
}
|
|
6151
6320
|
|
|
6152
|
-
// src/commands
|
|
6321
|
+
// src/commands/push/recovery/redact.ts
|
|
6153
6322
|
init_config();
|
|
6154
6323
|
init_config_sharedDirs_guard();
|
|
6155
|
-
import { cpSync as cpSync8, existsSync as
|
|
6156
|
-
import { dirname as
|
|
6324
|
+
import { cpSync as cpSync8, existsSync as existsSync33, mkdirSync as mkdirSync12 } from "node:fs";
|
|
6325
|
+
import { dirname as dirname14, join as join48, sep as sep8 } from "node:path";
|
|
6157
6326
|
|
|
6158
|
-
// src/commands
|
|
6327
|
+
// src/commands/redact/redact.ts
|
|
6159
6328
|
init_config();
|
|
6160
|
-
import { existsSync as
|
|
6161
|
-
import { dirname as
|
|
6329
|
+
import { existsSync as existsSync32 } from "node:fs";
|
|
6330
|
+
import { dirname as dirname13, join as join47 } from "node:path";
|
|
6162
6331
|
|
|
6163
|
-
// src/commands
|
|
6164
|
-
import { existsSync as
|
|
6165
|
-
import { join as
|
|
6332
|
+
// src/commands/redact/subtree.ts
|
|
6333
|
+
import { existsSync as existsSync31, lstatSync as lstatSync17, readFileSync as readFileSync16, readdirSync as readdirSync15, statSync as statSync9, writeFileSync as writeFileSync8 } from "node:fs";
|
|
6334
|
+
import { join as join46 } from "node:path";
|
|
6166
6335
|
init_utils_fs();
|
|
6167
6336
|
init_utils();
|
|
6168
6337
|
function collectFiles(dir, out) {
|
|
6169
|
-
if (!
|
|
6338
|
+
if (!existsSync31(dir)) return;
|
|
6170
6339
|
const st = lstatSync17(dir);
|
|
6171
6340
|
if (!st.isDirectory()) return;
|
|
6172
6341
|
for (const entry of readdirSync15(dir)) {
|
|
6173
|
-
const abs =
|
|
6342
|
+
const abs = join46(dir, entry);
|
|
6174
6343
|
const lst = lstatSync17(abs);
|
|
6175
6344
|
if (lst.isSymbolicLink()) continue;
|
|
6176
6345
|
if (lst.isDirectory()) {
|
|
@@ -6224,7 +6393,7 @@ function applySubtreeRedactions(mainPath, mainFindings, subtreeFiles, rule, ts,
|
|
|
6224
6393
|
return { total, dirty };
|
|
6225
6394
|
}
|
|
6226
6395
|
|
|
6227
|
-
// src/commands
|
|
6396
|
+
// src/commands/pushed-history.ts
|
|
6228
6397
|
init_utils();
|
|
6229
6398
|
import { execFileSync as execFileSync15 } from "node:child_process";
|
|
6230
6399
|
function pushedRef(repo) {
|
|
@@ -6272,23 +6441,23 @@ function warnIfSessionPushed(id, repo) {
|
|
|
6272
6441
|
);
|
|
6273
6442
|
}
|
|
6274
6443
|
|
|
6275
|
-
// src/commands
|
|
6276
|
-
|
|
6444
|
+
// src/commands/redact/redact.ts
|
|
6445
|
+
init_gitleaks_scan();
|
|
6277
6446
|
init_exit_codes();
|
|
6278
6447
|
init_utils_fs();
|
|
6279
6448
|
init_utils_json();
|
|
6280
6449
|
init_utils();
|
|
6281
6450
|
function resolveLiveTranscript(id) {
|
|
6282
6451
|
try {
|
|
6283
|
-
const mapPath =
|
|
6284
|
-
if (!
|
|
6452
|
+
const mapPath = join47(repoHome(), "path-map.json");
|
|
6453
|
+
if (!existsSync32(mapPath)) return null;
|
|
6285
6454
|
const projects = readJson(mapPath).projects;
|
|
6286
6455
|
const claude = claudeHome();
|
|
6287
6456
|
for (const hostMap of Object.values(projects)) {
|
|
6288
6457
|
const abs = hostMap[HOST];
|
|
6289
6458
|
if (abs === void 0) continue;
|
|
6290
|
-
const live =
|
|
6291
|
-
if (
|
|
6459
|
+
const live = join47(claude, "projects", encodePath(abs), `${id}.jsonl`);
|
|
6460
|
+
if (existsSync32(live)) return live;
|
|
6292
6461
|
}
|
|
6293
6462
|
return null;
|
|
6294
6463
|
} catch {
|
|
@@ -6308,17 +6477,17 @@ function cmdRedact(opts, nowMs = Date.now, scan = scanFile) {
|
|
|
6308
6477
|
}
|
|
6309
6478
|
const repo = repoHome();
|
|
6310
6479
|
const backup = backupBase();
|
|
6311
|
-
if (!
|
|
6480
|
+
if (!existsSync32(repo)) die(`repo not cloned at ${repo}`);
|
|
6312
6481
|
const handle = acquireLock("redact");
|
|
6313
6482
|
if (handle === null) process.exit(0);
|
|
6314
6483
|
try {
|
|
6315
6484
|
const localPath = resolveLiveTranscript(id);
|
|
6316
|
-
if (localPath === null || !
|
|
6485
|
+
if (localPath === null || !existsSync32(localPath)) {
|
|
6317
6486
|
fail(`could not resolve local transcript for session ${id} on this host`);
|
|
6318
6487
|
process.exitCode = 1;
|
|
6319
6488
|
return;
|
|
6320
6489
|
}
|
|
6321
|
-
const sessionDir =
|
|
6490
|
+
const sessionDir = join47(dirname13(localPath), id);
|
|
6322
6491
|
const subtreeFiles = listSubtreeFiles(sessionDir);
|
|
6323
6492
|
if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
|
|
6324
6493
|
log(
|
|
@@ -6370,8 +6539,8 @@ ${lines}`);
|
|
|
6370
6539
|
}
|
|
6371
6540
|
}
|
|
6372
6541
|
|
|
6373
|
-
// src/commands
|
|
6374
|
-
|
|
6542
|
+
// src/commands/push/recovery/redact.ts
|
|
6543
|
+
init_gitleaks_scan();
|
|
6375
6544
|
init_utils_json();
|
|
6376
6545
|
init_utils();
|
|
6377
6546
|
function resolveStagedDir(localPath, map, claude, repo) {
|
|
@@ -6379,8 +6548,8 @@ function resolveStagedDir(localPath, map, claude, repo) {
|
|
|
6379
6548
|
assertSafeLogical(logical);
|
|
6380
6549
|
const abs = hostMap[HOST];
|
|
6381
6550
|
if (abs === void 0) continue;
|
|
6382
|
-
if (localPath.startsWith(
|
|
6383
|
-
return
|
|
6551
|
+
if (localPath.startsWith(join48(claude, "projects", encodePath(abs)) + sep8)) {
|
|
6552
|
+
return join48(repo, "shared", "projects", logical);
|
|
6384
6553
|
}
|
|
6385
6554
|
}
|
|
6386
6555
|
return null;
|
|
@@ -6390,7 +6559,7 @@ function preflightRedactable(f, map, nowMs) {
|
|
|
6390
6559
|
if (sid === null) return "a finding has no resolvable session id (not a session transcript)";
|
|
6391
6560
|
const localPath = resolveLiveTranscript(sid);
|
|
6392
6561
|
if (localPath === null) return `session ${sid}: local transcript not found`;
|
|
6393
|
-
const sessionDir =
|
|
6562
|
+
const sessionDir = join48(dirname14(localPath), sid);
|
|
6394
6563
|
const subtreeFiles = listSubtreeFiles(sessionDir);
|
|
6395
6564
|
if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
|
|
6396
6565
|
return `session ${sid}: looks active (modified within the last 5 minutes)`;
|
|
@@ -6419,7 +6588,7 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
|
|
|
6419
6588
|
`could not locate the local transcript for session ${sid}; choose Skip or Drop session.`
|
|
6420
6589
|
);
|
|
6421
6590
|
}
|
|
6422
|
-
const sessionDir =
|
|
6591
|
+
const sessionDir = join48(dirname14(localPath), sid);
|
|
6423
6592
|
const subtreeFiles = listSubtreeFiles(sessionDir);
|
|
6424
6593
|
if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
|
|
6425
6594
|
return refuse(
|
|
@@ -6452,35 +6621,35 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
|
|
|
6452
6621
|
);
|
|
6453
6622
|
}
|
|
6454
6623
|
mkdirSync12(stagedProjectDir, { recursive: true });
|
|
6455
|
-
cpSync8(localPath,
|
|
6456
|
-
if (
|
|
6457
|
-
cpSync8(sessionDir,
|
|
6624
|
+
cpSync8(localPath, join48(stagedProjectDir, `${sid}.jsonl`), { force: true });
|
|
6625
|
+
if (existsSync33(sessionDir)) {
|
|
6626
|
+
cpSync8(sessionDir, join48(stagedProjectDir, sid), { force: true, recursive: true });
|
|
6458
6627
|
}
|
|
6459
6628
|
return true;
|
|
6460
6629
|
}
|
|
6461
6630
|
|
|
6462
|
-
// src/commands
|
|
6631
|
+
// src/commands/push/recovery/drop.ts
|
|
6463
6632
|
init_config();
|
|
6464
6633
|
import { rmSync as rmSync14 } from "node:fs";
|
|
6465
|
-
import { join as
|
|
6634
|
+
import { join as join49 } from "node:path";
|
|
6466
6635
|
function dropSessionFromStaged(sid, map) {
|
|
6467
6636
|
const logicals = Object.keys(map.projects);
|
|
6468
6637
|
if (logicals.length === 0) return false;
|
|
6469
6638
|
const repo = repoHome();
|
|
6470
6639
|
for (const logical of logicals) {
|
|
6471
|
-
const jsonl =
|
|
6472
|
-
const dir =
|
|
6640
|
+
const jsonl = join49(repo, "shared", "projects", logical, `${sid}.jsonl`);
|
|
6641
|
+
const dir = join49(repo, "shared", "projects", logical, sid);
|
|
6473
6642
|
rmSync14(jsonl, { force: true });
|
|
6474
6643
|
rmSync14(dir, { recursive: true, force: true });
|
|
6475
6644
|
}
|
|
6476
6645
|
return true;
|
|
6477
6646
|
}
|
|
6478
6647
|
|
|
6479
|
-
// src/commands
|
|
6480
|
-
|
|
6648
|
+
// src/commands/push/recovery/actions.ts
|
|
6649
|
+
init_gitleaks_scan();
|
|
6481
6650
|
init_utils();
|
|
6482
6651
|
|
|
6483
|
-
// src/commands
|
|
6652
|
+
// src/commands/push/recovery/span-align.ts
|
|
6484
6653
|
var REDACTED_TOKEN = "REDACTED";
|
|
6485
6654
|
var SHIFT_WINDOW = [0, -1, 1, -2, 2];
|
|
6486
6655
|
var ENTROPY_TOLERANCE = 1e-4;
|
|
@@ -6567,7 +6736,7 @@ function alignFindingSpan(finding, buf) {
|
|
|
6567
6736
|
return breakTie(hits, finding);
|
|
6568
6737
|
}
|
|
6569
6738
|
|
|
6570
|
-
// src/commands
|
|
6739
|
+
// src/commands/push/recovery/secret-shape.ts
|
|
6571
6740
|
var VALUE_HEAD = 4;
|
|
6572
6741
|
var VALUE_TAIL = 4;
|
|
6573
6742
|
var MIN_ELIDE_LEN = 16;
|
|
@@ -6663,15 +6832,15 @@ function elideTokenRuns(text) {
|
|
|
6663
6832
|
});
|
|
6664
6833
|
}
|
|
6665
6834
|
|
|
6666
|
-
// src/commands
|
|
6835
|
+
// src/commands/push/recovery/display.ts
|
|
6667
6836
|
var RULE_PAD = 24;
|
|
6668
6837
|
var GROUP_SEP = "\0";
|
|
6669
6838
|
function sessionSuffix(finding) {
|
|
6670
6839
|
const sid = sessionIdFromFinding(finding);
|
|
6671
6840
|
if (sid === null) return "";
|
|
6672
6841
|
const rawBasename = finding.File.replace(/^.*\//, "");
|
|
6673
|
-
const
|
|
6674
|
-
return
|
|
6842
|
+
const basename5 = rawBasename.endsWith(".jsonl") ? rawBasename.slice(0, -".jsonl".length) : rawBasename;
|
|
6843
|
+
return basename5 === sid ? "" : ` (session: ${sid})`;
|
|
6675
6844
|
}
|
|
6676
6845
|
function renderFindingBlock(finding, readLine, siblings = []) {
|
|
6677
6846
|
const lines = [` file: ${finding.File}:${finding.StartLine}${sessionSuffix(finding)}`];
|
|
@@ -6721,7 +6890,7 @@ function buildPromptHeader(group, index, total, readLine, peers = 0, siblings =
|
|
|
6721
6890
|
return ["", headerLine, ...body, menu, ""].join("\n");
|
|
6722
6891
|
}
|
|
6723
6892
|
|
|
6724
|
-
// src/commands
|
|
6893
|
+
// src/commands/push/recovery/actions.ts
|
|
6725
6894
|
function allowAllFindings(findings, repo) {
|
|
6726
6895
|
for (const f of findings) {
|
|
6727
6896
|
appendGitleaksIgnore(f.Fingerprint, repo);
|
|
@@ -6854,8 +7023,8 @@ function dispatchActions(findings, actions, opts) {
|
|
|
6854
7023
|
applyDeferredAllows(findings, ctx, repo);
|
|
6855
7024
|
}
|
|
6856
7025
|
|
|
6857
|
-
// src/commands
|
|
6858
|
-
|
|
7026
|
+
// src/commands/push/recovery/redact-all.ts
|
|
7027
|
+
init_gitleaks_scan();
|
|
6859
7028
|
init_utils();
|
|
6860
7029
|
function redactAllDedupeKey(f) {
|
|
6861
7030
|
const sid = sessionIdFromFinding(f);
|
|
@@ -6920,10 +7089,10 @@ function redactAllFindings(findings, ts, map, nowMs, scan = scanFile) {
|
|
|
6920
7089
|
}
|
|
6921
7090
|
}
|
|
6922
7091
|
|
|
6923
|
-
// src/commands
|
|
7092
|
+
// src/commands/push/recovery/recovery.ts
|
|
6924
7093
|
init_exit_codes();
|
|
6925
|
-
|
|
6926
|
-
|
|
7094
|
+
init_gitleaks_scan();
|
|
7095
|
+
init_gitleaks();
|
|
6927
7096
|
init_utils();
|
|
6928
7097
|
function isTTY(stdin = process.stdin, stdout = process.stdout) {
|
|
6929
7098
|
return stdin.isTTY === true && stdout.isTTY === true;
|
|
@@ -6954,7 +7123,7 @@ function applyThenRescan(scanVerdict, repoHome2) {
|
|
|
6954
7123
|
return next;
|
|
6955
7124
|
}
|
|
6956
7125
|
function allowThenRescan(append, scanVerdict, repoHome2) {
|
|
6957
|
-
const ignPath =
|
|
7126
|
+
const ignPath = join50(repoHome2, ".gitleaksignore");
|
|
6958
7127
|
let before;
|
|
6959
7128
|
try {
|
|
6960
7129
|
before = readFileSync18(ignPath, "utf8");
|
|
@@ -6998,7 +7167,7 @@ async function resolveLeakFindings(verdict, ts, map, deps = {}) {
|
|
|
6998
7167
|
scan = scanFile,
|
|
6999
7168
|
printLegend = printRecoveryLegend
|
|
7000
7169
|
} = deps;
|
|
7001
|
-
const scanVerdict = deps.scanVerdict ?? (await Promise.resolve().then(() => (
|
|
7170
|
+
const scanVerdict = deps.scanVerdict ?? (await Promise.resolve().then(() => (init_leak_verdict(), leak_verdict_exports))).scanPushVerdict;
|
|
7002
7171
|
const repo = repoHome();
|
|
7003
7172
|
let current = verdict;
|
|
7004
7173
|
if (redactAll) {
|
|
@@ -7041,7 +7210,7 @@ async function resolveLeakFindings(verdict, ts, map, deps = {}) {
|
|
|
7041
7210
|
return current;
|
|
7042
7211
|
}
|
|
7043
7212
|
|
|
7044
|
-
// src/spinner.ts
|
|
7213
|
+
// src/render/spinner.ts
|
|
7045
7214
|
function formatElapsed(ms) {
|
|
7046
7215
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
7047
7216
|
}
|
|
@@ -7060,11 +7229,11 @@ function writeAnimatedDone(out, label, ms, useTTY) {
|
|
|
7060
7229
|
`);
|
|
7061
7230
|
}
|
|
7062
7231
|
function resolveWorkerPath(deps = {}) {
|
|
7063
|
-
const check = deps.existsSyncFn ??
|
|
7232
|
+
const check = deps.existsSyncFn ?? existsSync34;
|
|
7064
7233
|
const base = deps.baseUrl ?? import.meta.url;
|
|
7065
|
-
const mjs =
|
|
7234
|
+
const mjs = fileURLToPath2(new URL("./nomad.worker.mjs", base));
|
|
7066
7235
|
if (check(mjs)) return mjs;
|
|
7067
|
-
return
|
|
7236
|
+
return fileURLToPath2(new URL("./spinner.worker.ts", base));
|
|
7068
7237
|
}
|
|
7069
7238
|
function makeRealWorker() {
|
|
7070
7239
|
return new Worker(resolveWorkerPath());
|
|
@@ -7124,11 +7293,11 @@ function withSpinner(label, fn, deps) {
|
|
|
7124
7293
|
}
|
|
7125
7294
|
}
|
|
7126
7295
|
|
|
7127
|
-
// src/commands
|
|
7296
|
+
// src/commands/doctor/gitleaks-version.ts
|
|
7128
7297
|
init_color();
|
|
7129
7298
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
7130
|
-
import { existsSync as
|
|
7131
|
-
import { join as
|
|
7299
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
7300
|
+
import { join as join51 } from "node:path";
|
|
7132
7301
|
init_config();
|
|
7133
7302
|
var SEMVER_MAJOR_MINOR = /^(\d+)\.(\d+)\.\d+$/;
|
|
7134
7303
|
var GITLEAKS_TIMEOUT_MS = 5e3;
|
|
@@ -7137,7 +7306,7 @@ function majorMinorOf(value) {
|
|
|
7137
7306
|
return m === null ? null : [m[1], m[2]];
|
|
7138
7307
|
}
|
|
7139
7308
|
function readGitleaksVersion(run, tomlExists) {
|
|
7140
|
-
const tomlPath =
|
|
7309
|
+
const tomlPath = join51(repoHome(), ".gitleaks.toml");
|
|
7141
7310
|
const args = ["version"];
|
|
7142
7311
|
if (tomlExists(tomlPath)) args.push("--config", tomlPath);
|
|
7143
7312
|
try {
|
|
@@ -7149,7 +7318,7 @@ function readGitleaksVersion(run, tomlExists) {
|
|
|
7149
7318
|
return null;
|
|
7150
7319
|
}
|
|
7151
7320
|
}
|
|
7152
|
-
function reportGitleaksVersionCheck(section2, run = execFileSync16, tomlExists =
|
|
7321
|
+
function reportGitleaksVersionCheck(section2, run = execFileSync16, tomlExists = existsSync35) {
|
|
7153
7322
|
const raw = readGitleaksVersion(run, tomlExists);
|
|
7154
7323
|
if (raw === null) return;
|
|
7155
7324
|
const local = majorMinorOf(raw);
|
|
@@ -7167,7 +7336,7 @@ function reportGitleaksVersionCheck(section2, run = execFileSync16, tomlExists =
|
|
|
7167
7336
|
);
|
|
7168
7337
|
}
|
|
7169
7338
|
|
|
7170
|
-
// src/commands
|
|
7339
|
+
// src/commands/doctor/checks/deps.ts
|
|
7171
7340
|
init_color();
|
|
7172
7341
|
import { execFileSync as execFileSync17 } from "node:child_process";
|
|
7173
7342
|
var VERSION_TOKEN = /(\d{1,9}\.\d{1,9}\.\d{1,9})/;
|
|
@@ -7219,12 +7388,12 @@ function reportOptionalDeps(section2, run = execFileSync17) {
|
|
|
7219
7388
|
reportFetcherRow(section2, run);
|
|
7220
7389
|
}
|
|
7221
7390
|
|
|
7222
|
-
// src/commands
|
|
7391
|
+
// src/commands/doctor/actions-drift.ts
|
|
7223
7392
|
init_color();
|
|
7224
7393
|
import { execFileSync as execFileSync19 } from "node:child_process";
|
|
7225
7394
|
init_config();
|
|
7226
7395
|
|
|
7227
|
-
// src/gh-actions.ts
|
|
7396
|
+
// src/commands/init/gh-actions.ts
|
|
7228
7397
|
import { execFileSync as execFileSync18 } from "node:child_process";
|
|
7229
7398
|
var GH_TIMEOUT_MS = 5e3;
|
|
7230
7399
|
function parseGitHubRemote(remoteUrl) {
|
|
@@ -7284,7 +7453,7 @@ function readOriginRemote(cwd, run = execFileSync18) {
|
|
|
7284
7453
|
}).toString().trim();
|
|
7285
7454
|
}
|
|
7286
7455
|
|
|
7287
|
-
// src/commands
|
|
7456
|
+
// src/commands/doctor/actions-drift.ts
|
|
7288
7457
|
function reportActionsDrift(section2, run = execFileSync19) {
|
|
7289
7458
|
let remote;
|
|
7290
7459
|
try {
|
|
@@ -7316,7 +7485,7 @@ function reportActionsDrift(section2, run = execFileSync19) {
|
|
|
7316
7485
|
);
|
|
7317
7486
|
}
|
|
7318
7487
|
|
|
7319
|
-
// src/commands
|
|
7488
|
+
// src/commands/doctor/verdict.ts
|
|
7320
7489
|
init_color();
|
|
7321
7490
|
function isFailLine(item2) {
|
|
7322
7491
|
return item2.includes(failGlyph);
|
|
@@ -7340,7 +7509,7 @@ function buildVerdictSection(sections) {
|
|
|
7340
7509
|
return summary;
|
|
7341
7510
|
}
|
|
7342
7511
|
|
|
7343
|
-
// src/commands
|
|
7512
|
+
// src/commands/doctor/banner.ts
|
|
7344
7513
|
var NOMAD_BANNER = [
|
|
7345
7514
|
" __",
|
|
7346
7515
|
" ____ ____ ____ ___ ____ _ ____/ /",
|
|
@@ -7354,7 +7523,7 @@ function printBanner(log2, stdout) {
|
|
|
7354
7523
|
log2("");
|
|
7355
7524
|
}
|
|
7356
7525
|
|
|
7357
|
-
// src/commands
|
|
7526
|
+
// src/commands/doctor/compact.ts
|
|
7358
7527
|
init_color();
|
|
7359
7528
|
var ALWAYS_FULL = /* @__PURE__ */ new Set([
|
|
7360
7529
|
"Nomad Version",
|
|
@@ -7396,7 +7565,7 @@ function compactSections(sections) {
|
|
|
7396
7565
|
});
|
|
7397
7566
|
}
|
|
7398
7567
|
|
|
7399
|
-
// src/commands
|
|
7568
|
+
// src/commands/doctor/doctor.ts
|
|
7400
7569
|
function gatherDoctorSections(opts) {
|
|
7401
7570
|
const host = section("Environment");
|
|
7402
7571
|
reportHostAndPaths(host);
|
|
@@ -7406,8 +7575,8 @@ function gatherDoctorSections(opts) {
|
|
|
7406
7575
|
reportLongPathsCheck(host);
|
|
7407
7576
|
reportCrlfGuardCheck(host);
|
|
7408
7577
|
const links = section("Shared links");
|
|
7409
|
-
const mapPath =
|
|
7410
|
-
const rawMap =
|
|
7578
|
+
const mapPath = join52(repoHome(), "path-map.json");
|
|
7579
|
+
const rawMap = existsSync36(mapPath) ? readJsonSafe(mapPath, mapPath, links) : null;
|
|
7411
7580
|
const map = rawMap ?? { projects: {} };
|
|
7412
7581
|
reportSharedLinks(links, map);
|
|
7413
7582
|
reportDroppedNamesMigration(links);
|
|
@@ -7482,7 +7651,7 @@ function cmdDoctor(opts = {}) {
|
|
|
7482
7651
|
renderDoctor(opts.verbose === true ? report : compactSections(report));
|
|
7483
7652
|
}
|
|
7484
7653
|
|
|
7485
|
-
// src/
|
|
7654
|
+
// src/cli/dispatch.doctor.ts
|
|
7486
7655
|
function parseDoctorArgs(args) {
|
|
7487
7656
|
if (args[0] === "--resume-cmd") {
|
|
7488
7657
|
const id = args[1];
|
|
@@ -7503,13 +7672,13 @@ function parseDoctorArgs(args) {
|
|
|
7503
7672
|
return { kind: "run", checkShared, checkSchema, checkRemote, verbose };
|
|
7504
7673
|
}
|
|
7505
7674
|
|
|
7506
|
-
// src/commands
|
|
7675
|
+
// src/commands/drop-session/drop-session.ts
|
|
7507
7676
|
init_config();
|
|
7508
7677
|
import { execFileSync as execFileSync21 } from "node:child_process";
|
|
7509
|
-
import { existsSync as
|
|
7510
|
-
import { join as
|
|
7678
|
+
import { existsSync as existsSync38, readdirSync as readdirSync16, statSync as statSync10 } from "node:fs";
|
|
7679
|
+
import { join as join54, relative as relative7 } from "node:path";
|
|
7511
7680
|
|
|
7512
|
-
// src/commands
|
|
7681
|
+
// src/commands/drop-session/git.ts
|
|
7513
7682
|
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
7514
7683
|
function expandStagedDir(dirRel, repo) {
|
|
7515
7684
|
try {
|
|
@@ -7546,12 +7715,12 @@ function isInIndex(rel, repo) {
|
|
|
7546
7715
|
}
|
|
7547
7716
|
}
|
|
7548
7717
|
|
|
7549
|
-
// src/commands
|
|
7718
|
+
// src/commands/drop-session/scrub-hint.ts
|
|
7550
7719
|
init_config();
|
|
7551
7720
|
init_utils();
|
|
7552
7721
|
init_utils_json();
|
|
7553
|
-
import { existsSync as
|
|
7554
|
-
import { join as
|
|
7722
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
7723
|
+
import { join as join53 } from "node:path";
|
|
7555
7724
|
var SHARED_PROJECT_LOGICAL = /^shared\/projects\/([^/]+)\//;
|
|
7556
7725
|
function reportScrubHint(id, matches) {
|
|
7557
7726
|
const live = resolveLiveTranscript2(id, matches);
|
|
@@ -7567,8 +7736,8 @@ function reportScrubHint(id, matches) {
|
|
|
7567
7736
|
}
|
|
7568
7737
|
function resolveLiveTranscript2(id, matches) {
|
|
7569
7738
|
try {
|
|
7570
|
-
const mapPath =
|
|
7571
|
-
if (!
|
|
7739
|
+
const mapPath = join53(repoHome(), "path-map.json");
|
|
7740
|
+
if (!existsSync37(mapPath)) return null;
|
|
7572
7741
|
const projects = readJson(mapPath).projects;
|
|
7573
7742
|
const claude = claudeHome();
|
|
7574
7743
|
for (const rel of matches) {
|
|
@@ -7576,8 +7745,8 @@ function resolveLiveTranscript2(id, matches) {
|
|
|
7576
7745
|
if (logical === void 0) continue;
|
|
7577
7746
|
const abs = projects[logical]?.[HOST];
|
|
7578
7747
|
if (abs === void 0) continue;
|
|
7579
|
-
const live =
|
|
7580
|
-
if (
|
|
7748
|
+
const live = join53(claude, "projects", encodePath(abs), `${id}.jsonl`);
|
|
7749
|
+
if (existsSync37(live)) return live;
|
|
7581
7750
|
}
|
|
7582
7751
|
return null;
|
|
7583
7752
|
} catch {
|
|
@@ -7585,7 +7754,7 @@ function resolveLiveTranscript2(id, matches) {
|
|
|
7585
7754
|
}
|
|
7586
7755
|
}
|
|
7587
7756
|
|
|
7588
|
-
// src/commands
|
|
7757
|
+
// src/commands/drop-session/drop-session.ts
|
|
7589
7758
|
init_utils();
|
|
7590
7759
|
function cmdDropSession(id) {
|
|
7591
7760
|
if (id.length === 0 || id.length > 128 || !/^[A-Za-z0-9_-]+$/.test(id)) {
|
|
@@ -7593,12 +7762,12 @@ function cmdDropSession(id) {
|
|
|
7593
7762
|
process.exit(1);
|
|
7594
7763
|
}
|
|
7595
7764
|
const repo = repoHome();
|
|
7596
|
-
if (!
|
|
7765
|
+
if (!existsSync38(repo)) die(`repo not cloned at ${repo}`);
|
|
7597
7766
|
const handle = acquireLock("drop-session");
|
|
7598
7767
|
if (handle === null) process.exit(0);
|
|
7599
7768
|
try {
|
|
7600
|
-
const repoProjects =
|
|
7601
|
-
if (!
|
|
7769
|
+
const repoProjects = join54(repo, "shared", "projects");
|
|
7770
|
+
if (!existsSync38(repoProjects)) {
|
|
7602
7771
|
throw new NomadFatal(`no staged session matches ${id}`);
|
|
7603
7772
|
}
|
|
7604
7773
|
const matches = collectMatches(repoProjects, id, repo);
|
|
@@ -7621,12 +7790,12 @@ function cmdDropSession(id) {
|
|
|
7621
7790
|
function collectMatches(repoProjects, id, repo) {
|
|
7622
7791
|
const matches = [];
|
|
7623
7792
|
for (const logical of readdirSync16(repoProjects)) {
|
|
7624
|
-
const candidate =
|
|
7625
|
-
if (
|
|
7793
|
+
const candidate = join54(repoProjects, logical, `${id}.jsonl`);
|
|
7794
|
+
if (existsSync38(candidate)) {
|
|
7626
7795
|
matches.push(relative7(repo, candidate));
|
|
7627
7796
|
}
|
|
7628
|
-
const dir =
|
|
7629
|
-
if (
|
|
7797
|
+
const dir = join54(repoProjects, logical, id);
|
|
7798
|
+
if (existsSync38(dir) && statSync10(dir).isDirectory()) {
|
|
7630
7799
|
const dirRel = relative7(repo, dir);
|
|
7631
7800
|
const staged = expandStagedDir(dirRel, repo);
|
|
7632
7801
|
if (staged.length > 0) matches.push(...staged);
|
|
@@ -7660,15 +7829,15 @@ function unstageOne(rel, repo) {
|
|
|
7660
7829
|
item(`dropped ${rel}`);
|
|
7661
7830
|
}
|
|
7662
7831
|
|
|
7663
|
-
// src/commands
|
|
7832
|
+
// src/commands/pull/pull.ts
|
|
7664
7833
|
init_autostash_guard();
|
|
7665
|
-
import { existsSync as
|
|
7666
|
-
import { join as
|
|
7834
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync14 } from "node:fs";
|
|
7835
|
+
import { join as join65 } from "node:path";
|
|
7667
7836
|
|
|
7668
|
-
// src/commands
|
|
7837
|
+
// src/commands/push/sections.ts
|
|
7669
7838
|
init_color();
|
|
7670
7839
|
|
|
7671
|
-
// src/summary.ts
|
|
7840
|
+
// src/render/summary.ts
|
|
7672
7841
|
init_utils();
|
|
7673
7842
|
function summaryText(verb, unmapped, collisions = 0, extrasSkipped = 0, localOnly = 0) {
|
|
7674
7843
|
const extras = extrasSkipped > 0 ? `, ${extrasSkipped} extras skipped` : "";
|
|
@@ -7693,7 +7862,7 @@ function summaryRow(verb, unmapped, collisions = 0, extrasSkipped = 0, localOnly
|
|
|
7693
7862
|
return text.replace(/^summary: /, "");
|
|
7694
7863
|
}
|
|
7695
7864
|
|
|
7696
|
-
// src/commands
|
|
7865
|
+
// src/commands/push/sections.ts
|
|
7697
7866
|
function collapsedSkipRow(n, noun) {
|
|
7698
7867
|
if (n <= 0) return null;
|
|
7699
7868
|
return `${dim(infoGlyph)} ${n} ${noun}`;
|
|
@@ -7766,23 +7935,23 @@ function renderNoScanTree(st, opts = {}) {
|
|
|
7766
7935
|
renderTree(buildNoScanSections(st, opts));
|
|
7767
7936
|
}
|
|
7768
7937
|
|
|
7769
|
-
// src/commands
|
|
7938
|
+
// src/commands/pull/pull.ts
|
|
7770
7939
|
init_config();
|
|
7771
7940
|
|
|
7772
|
-
// src/extras
|
|
7941
|
+
// src/sync/extras/extras.ts
|
|
7773
7942
|
init_config();
|
|
7774
|
-
import { existsSync as
|
|
7775
|
-
import { join as
|
|
7943
|
+
import { existsSync as existsSync40, statSync as statSync11 } from "node:fs";
|
|
7944
|
+
import { join as join57 } from "node:path";
|
|
7776
7945
|
init_utils();
|
|
7777
7946
|
init_utils_json();
|
|
7778
7947
|
|
|
7779
|
-
// src/extras
|
|
7948
|
+
// src/sync/extras/remap.ts
|
|
7780
7949
|
init_config();
|
|
7781
|
-
import { existsSync as
|
|
7782
|
-
import { dirname as
|
|
7950
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync13, readdirSync as readdirSync17, readFileSync as readFileSync19, realpathSync as realpathSync7, rmSync as rmSync16 } from "node:fs";
|
|
7951
|
+
import { dirname as dirname15, join as join56, sep as sep11 } from "node:path";
|
|
7783
7952
|
|
|
7784
|
-
// src/extras
|
|
7785
|
-
import { join as
|
|
7953
|
+
// src/sync/extras/planning-diff.ts
|
|
7954
|
+
import { join as join55, normalize as normalize2, sep as sep10 } from "node:path";
|
|
7786
7955
|
init_utils();
|
|
7787
7956
|
function processRecord(fields, i, changed, deleted) {
|
|
7788
7957
|
const status = fields[i];
|
|
@@ -7834,7 +8003,7 @@ function planningDeleteTargets(opts) {
|
|
|
7834
8003
|
const { deleted } = parsePlanningDiff(raw);
|
|
7835
8004
|
const logicalPrefix = "shared/extras/" + logical + "/";
|
|
7836
8005
|
const prefix = logicalPrefix + ".planning/";
|
|
7837
|
-
const planningRoot =
|
|
8006
|
+
const planningRoot = join55(localRoot, ".planning");
|
|
7838
8007
|
const planningRootBoundary = planningRoot + sep10;
|
|
7839
8008
|
const targets = [];
|
|
7840
8009
|
for (const repoPath of deleted) {
|
|
@@ -7842,7 +8011,7 @@ function planningDeleteTargets(opts) {
|
|
|
7842
8011
|
continue;
|
|
7843
8012
|
}
|
|
7844
8013
|
const remainder = repoPath.slice(logicalPrefix.length);
|
|
7845
|
-
const candidate =
|
|
8014
|
+
const candidate = join55(localRoot, remainder);
|
|
7846
8015
|
const resolved = normalize2(candidate);
|
|
7847
8016
|
if (!resolved.startsWith(planningRootBoundary)) {
|
|
7848
8017
|
throw new NomadFatal(
|
|
@@ -7854,7 +8023,7 @@ function planningDeleteTargets(opts) {
|
|
|
7854
8023
|
return targets;
|
|
7855
8024
|
}
|
|
7856
8025
|
|
|
7857
|
-
// src/extras
|
|
8026
|
+
// src/sync/extras/remap.ts
|
|
7858
8027
|
init_utils_fs();
|
|
7859
8028
|
init_utils();
|
|
7860
8029
|
function runExtrasOp(v, dryRun, paths, backup, copy) {
|
|
@@ -7863,7 +8032,7 @@ function runExtrasOp(v, dryRun, paths, backup, copy) {
|
|
|
7863
8032
|
const would = [];
|
|
7864
8033
|
for (const t of eachExtrasTarget(v, counts)) {
|
|
7865
8034
|
const { src, dst } = paths(t);
|
|
7866
|
-
if (!
|
|
8035
|
+
if (!existsSync39(src)) continue;
|
|
7867
8036
|
const item2 = `${t.logical}/${t.dirname}`;
|
|
7868
8037
|
if (dryRun) {
|
|
7869
8038
|
would.push(item2);
|
|
@@ -7876,7 +8045,7 @@ function runExtrasOp(v, dryRun, paths, backup, copy) {
|
|
|
7876
8045
|
return { ...counts, done, would };
|
|
7877
8046
|
}
|
|
7878
8047
|
function pruneEmptyAncestors(target, planningRoot) {
|
|
7879
|
-
let dir =
|
|
8048
|
+
let dir = dirname15(target);
|
|
7880
8049
|
while (dir !== planningRoot && dir.startsWith(planningRoot + sep11)) {
|
|
7881
8050
|
try {
|
|
7882
8051
|
if (readdirSync17(dir).length > 0) break;
|
|
@@ -7884,7 +8053,7 @@ function pruneEmptyAncestors(target, planningRoot) {
|
|
|
7884
8053
|
} catch {
|
|
7885
8054
|
break;
|
|
7886
8055
|
}
|
|
7887
|
-
dir =
|
|
8056
|
+
dir = dirname15(dir);
|
|
7888
8057
|
}
|
|
7889
8058
|
}
|
|
7890
8059
|
function tryRealpath(dir) {
|
|
@@ -7898,8 +8067,8 @@ function isInsidePlanningRoot(parentReal, rootReal) {
|
|
|
7898
8067
|
return parentReal === rootReal || parentReal.startsWith(rootReal + sep11);
|
|
7899
8068
|
}
|
|
7900
8069
|
function deletePlanningTarget(target, planningRoot, repoCounterpart) {
|
|
7901
|
-
if (
|
|
7902
|
-
const parentReal = tryRealpath(
|
|
8070
|
+
if (existsSync39(repoCounterpart)) return;
|
|
8071
|
+
const parentReal = tryRealpath(dirname15(target));
|
|
7903
8072
|
if (parentReal === void 0) return;
|
|
7904
8073
|
const rootReal = tryRealpath(planningRoot);
|
|
7905
8074
|
if (rootReal === void 0) return;
|
|
@@ -7908,7 +8077,7 @@ function deletePlanningTarget(target, planningRoot, repoCounterpart) {
|
|
|
7908
8077
|
pruneEmptyAncestors(target, planningRoot);
|
|
7909
8078
|
}
|
|
7910
8079
|
function localDivergesFromPreDelete(target, pre, repoRel, repo) {
|
|
7911
|
-
if (!
|
|
8080
|
+
if (!existsSync39(target)) return false;
|
|
7912
8081
|
try {
|
|
7913
8082
|
const preBlob = gitCaptureBuffer(["show", `${pre}:${repoRel}`], repo);
|
|
7914
8083
|
return !readFileSync19(target).equals(preBlob);
|
|
@@ -7953,7 +8122,7 @@ function keptDeletePreview(v, prePostHeads, repo) {
|
|
|
7953
8122
|
return kept;
|
|
7954
8123
|
}
|
|
7955
8124
|
function propagatePlanningDeletes(v, ts, prePostHeads, repo) {
|
|
7956
|
-
const repoExtras =
|
|
8125
|
+
const repoExtras = join56(repo, "shared", "extras");
|
|
7957
8126
|
for (const t of eachExtrasTarget(v, { unmapped: 0, skipped: 0 })) {
|
|
7958
8127
|
if (t.dirname !== ".planning") continue;
|
|
7959
8128
|
let raw;
|
|
@@ -7968,14 +8137,14 @@ function propagatePlanningDeletes(v, ts, prePostHeads, repo) {
|
|
|
7968
8137
|
}
|
|
7969
8138
|
const pairs = deletePairsFor(t, raw);
|
|
7970
8139
|
if (pairs.length === 0) continue;
|
|
7971
|
-
backupExtrasWrite(
|
|
7972
|
-
const planningRoot =
|
|
8140
|
+
backupExtrasWrite(join56(t.localRoot, t.dirname), ts, t.localRoot);
|
|
8141
|
+
const planningRoot = join56(t.localRoot, ".planning");
|
|
7973
8142
|
for (const { target, relToLocal, repoRel } of pairs) {
|
|
7974
8143
|
if (localDivergesFromPreDelete(target, prePostHeads.pre, repoRel, repo)) {
|
|
7975
8144
|
warn(keptDeleteWarnLine(t.logical, relToLocal));
|
|
7976
8145
|
continue;
|
|
7977
8146
|
}
|
|
7978
|
-
deletePlanningTarget(target, planningRoot,
|
|
8147
|
+
deletePlanningTarget(target, planningRoot, join56(repoExtras, t.logical, relToLocal));
|
|
7979
8148
|
}
|
|
7980
8149
|
}
|
|
7981
8150
|
}
|
|
@@ -7984,14 +8153,14 @@ function remapExtrasPush(ts, opts = {}) {
|
|
|
7984
8153
|
const v = loadValidatedExtras({ missingMsg: "no path-map.json; skipping extras push" });
|
|
7985
8154
|
if (v === null) return { unmapped: 0, skipped: 0, pushed: [], wouldPush: [] };
|
|
7986
8155
|
const repo = repoHome();
|
|
7987
|
-
const repoExtras =
|
|
8156
|
+
const repoExtras = join56(repo, "shared", "extras");
|
|
7988
8157
|
if (!dryRun) mkdirSync13(repoExtras, { recursive: true });
|
|
7989
8158
|
const { unmapped, skipped, done, would } = runExtrasOp(
|
|
7990
8159
|
v,
|
|
7991
8160
|
dryRun,
|
|
7992
|
-
({ localRoot, logical, dirname:
|
|
7993
|
-
src:
|
|
7994
|
-
dst:
|
|
8161
|
+
({ localRoot, logical, dirname: dirname16 }) => ({
|
|
8162
|
+
src: join56(localRoot, dirname16),
|
|
8163
|
+
dst: join56(repoExtras, logical, dirname16)
|
|
7995
8164
|
}),
|
|
7996
8165
|
(dst) => backupRepoWrite(dst, ts, repo),
|
|
7997
8166
|
// Push copy routing per extra type:
|
|
@@ -8000,11 +8169,11 @@ function remapExtrasPush(ts, opts = {}) {
|
|
|
8000
8169
|
// The filter prevents ALWAYS_NEVER_SYNC files from landing in the repo
|
|
8001
8170
|
// working tree before the allow-list gate fires, eliminating the
|
|
8002
8171
|
// "residue wedges repeat push" regression. The allow-list gate
|
|
8003
|
-
// (enforceAllowList in commands
|
|
8172
|
+
// (enforceAllowList in commands/push/allowlist.ts, blockSetFor in
|
|
8004
8173
|
// config.never-sync.ts)
|
|
8005
8174
|
// remains the hard security boundary.
|
|
8006
8175
|
// All others: copyExtrasFiltered with per-extra denylist.
|
|
8007
|
-
(src, dst,
|
|
8176
|
+
(src, dst, dirname16) => dirname16 === ".planning" ? copyExtrasOverlayFiltered(src, dst, extrasDenySet(dirname16)) : copyExtrasFiltered(src, dst, extrasDenySet(dirname16))
|
|
8008
8177
|
);
|
|
8009
8178
|
return { unmapped, skipped, pushed: done, wouldPush: would };
|
|
8010
8179
|
}
|
|
@@ -8020,9 +8189,9 @@ function remapExtrasPull(ts, opts = {}) {
|
|
|
8020
8189
|
const { unmapped, skipped, done, would } = runExtrasOp(
|
|
8021
8190
|
v,
|
|
8022
8191
|
dryRun,
|
|
8023
|
-
({ localRoot, logical, dirname:
|
|
8024
|
-
src:
|
|
8025
|
-
dst:
|
|
8192
|
+
({ localRoot, logical, dirname: dirname16 }) => ({
|
|
8193
|
+
src: join56(repo, "shared", "extras", logical, dirname16),
|
|
8194
|
+
dst: join56(localRoot, dirname16)
|
|
8026
8195
|
}),
|
|
8027
8196
|
// Snapshot the host-side dst BEFORE the copy step touches it. Anchor on
|
|
8028
8197
|
// localRoot so the backup tree mirrors the project layout.
|
|
@@ -8040,12 +8209,12 @@ function remapExtrasPull(ts, opts = {}) {
|
|
|
8040
8209
|
// copyExtrasFileSkipDiverged keeps a locally-edited file rather than
|
|
8041
8210
|
// clobbering it, so the divergence WARN's keep-local promise holds for
|
|
8042
8211
|
// every extra, not just `.planning`.
|
|
8043
|
-
(src, dst,
|
|
8044
|
-
if (
|
|
8045
|
-
return copyExtrasFilteredPreserving(src, dst, extrasDenySet(
|
|
8046
|
-
if (
|
|
8212
|
+
(src, dst, dirname16) => {
|
|
8213
|
+
if (dirname16 === ".claude")
|
|
8214
|
+
return copyExtrasFilteredPreserving(src, dst, extrasDenySet(dirname16));
|
|
8215
|
+
if (dirname16 === ".planning") {
|
|
8047
8216
|
const divergedSet = new Set(listDivergingModified(dst, src));
|
|
8048
|
-
return copyExtrasOverlaySkipDiverged(src, dst, extrasDenySet(
|
|
8217
|
+
return copyExtrasOverlaySkipDiverged(src, dst, extrasDenySet(dirname16), divergedSet);
|
|
8049
8218
|
}
|
|
8050
8219
|
return copyExtrasFileSkipDiverged(src, dst);
|
|
8051
8220
|
}
|
|
@@ -8056,7 +8225,7 @@ function remapExtrasPull(ts, opts = {}) {
|
|
|
8056
8225
|
return { unmapped, skipped, pulled: done, wouldPull: would };
|
|
8057
8226
|
}
|
|
8058
8227
|
|
|
8059
|
-
// src/extras
|
|
8228
|
+
// src/sync/extras/extras.ts
|
|
8060
8229
|
function divergenceWarnLine(o) {
|
|
8061
8230
|
const kind = o.isDir ? "folder" : "file";
|
|
8062
8231
|
const name = o.isDir ? `${o.dirname}/` : o.dirname;
|
|
@@ -8069,20 +8238,20 @@ function divergenceCheckExtras(ts, prePostHeads) {
|
|
|
8069
8238
|
const v = loadValidatedExtras({});
|
|
8070
8239
|
if (v === null) return 0;
|
|
8071
8240
|
const counts = { unmapped: 0, skipped: 0 };
|
|
8072
|
-
const backupRoot =
|
|
8241
|
+
const backupRoot = join57(backupBase(), ts, "extras");
|
|
8073
8242
|
const repo = repoHome();
|
|
8074
8243
|
let divergedCount = 0;
|
|
8075
|
-
for (const { logical, localRoot, dirname:
|
|
8076
|
-
const local =
|
|
8077
|
-
const repoEntry =
|
|
8078
|
-
if (!
|
|
8244
|
+
for (const { logical, localRoot, dirname: dirname16 } of eachExtrasTarget(v, counts)) {
|
|
8245
|
+
const local = join57(localRoot, dirname16);
|
|
8246
|
+
const repoEntry = join57(repo, "shared", "extras", logical, dirname16);
|
|
8247
|
+
if (!existsSync40(local) || !existsSync40(repoEntry)) continue;
|
|
8079
8248
|
const modified = listDivergingModified(local, repoEntry);
|
|
8080
8249
|
if (modified.length === 0) continue;
|
|
8081
8250
|
divergedCount += modified.length;
|
|
8082
|
-
const projectBackupRoot =
|
|
8251
|
+
const projectBackupRoot = join57(backupRoot, encodePath(localRoot));
|
|
8083
8252
|
warn(
|
|
8084
8253
|
divergenceWarnLine({
|
|
8085
|
-
dirname:
|
|
8254
|
+
dirname: dirname16,
|
|
8086
8255
|
logical,
|
|
8087
8256
|
isDir: statSync11(local).isDirectory(),
|
|
8088
8257
|
count: modified.length,
|
|
@@ -8099,10 +8268,10 @@ function divergenceCheckExtras(ts, prePostHeads) {
|
|
|
8099
8268
|
return divergedCount;
|
|
8100
8269
|
}
|
|
8101
8270
|
|
|
8102
|
-
// src/links.baseline.ts
|
|
8271
|
+
// src/sync/links.baseline.ts
|
|
8103
8272
|
init_config();
|
|
8104
8273
|
import { lstatSync as lstatSync18, readdirSync as readdirSync18 } from "node:fs";
|
|
8105
|
-
import { join as
|
|
8274
|
+
import { join as join58, relative as relative8, sep as sep12 } from "node:path";
|
|
8106
8275
|
init_utils();
|
|
8107
8276
|
var SHARED_BASELINE_KIND = "shared-links-baseline/1";
|
|
8108
8277
|
var SHARED_BASELINE_CONFIG_HASH = "not-applicable";
|
|
@@ -8144,7 +8313,7 @@ function collectSharedFiles(dir, claude, scan) {
|
|
|
8144
8313
|
return;
|
|
8145
8314
|
}
|
|
8146
8315
|
for (const entry of entries) {
|
|
8147
|
-
const abs =
|
|
8316
|
+
const abs = join58(dir, entry);
|
|
8148
8317
|
if (isDeniedName(ALWAYS_NEVER_SYNC, entry)) {
|
|
8149
8318
|
scan.declined.push(baselineKey(claude, abs));
|
|
8150
8319
|
continue;
|
|
@@ -8160,7 +8329,7 @@ function enumerateLocalSharedScan(map, opts = {}) {
|
|
|
8160
8329
|
scan.declined.push(name);
|
|
8161
8330
|
continue;
|
|
8162
8331
|
}
|
|
8163
|
-
addLocalPath(
|
|
8332
|
+
addLocalPath(join58(claude, name), claude, scan);
|
|
8164
8333
|
}
|
|
8165
8334
|
return scan;
|
|
8166
8335
|
}
|
|
@@ -8172,7 +8341,7 @@ function buildSharedBaseline(map, opts = {}) {
|
|
|
8172
8341
|
const files = {};
|
|
8173
8342
|
for (const [key, st] of Object.entries(enumerateLocalSharedFiles(map, opts))) {
|
|
8174
8343
|
try {
|
|
8175
|
-
files[key] = { size: st.size, mtime: st.mtime, hash: hashFile(
|
|
8344
|
+
files[key] = { size: st.size, mtime: st.mtime, hash: hashFile(join58(claude, key)) };
|
|
8176
8345
|
} catch {
|
|
8177
8346
|
}
|
|
8178
8347
|
}
|
|
@@ -8187,12 +8356,12 @@ function writeSharedBaseline(map, opts = {}) {
|
|
|
8187
8356
|
}
|
|
8188
8357
|
}
|
|
8189
8358
|
|
|
8190
|
-
// src/commands
|
|
8359
|
+
// src/commands/pull/win32.ts
|
|
8191
8360
|
init_color();
|
|
8192
|
-
import { existsSync as
|
|
8193
|
-
import { join as
|
|
8361
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
8362
|
+
import { join as join63 } from "node:path";
|
|
8194
8363
|
|
|
8195
|
-
// src/commands
|
|
8364
|
+
// src/commands/pull/recovery.git.ts
|
|
8196
8365
|
init_utils();
|
|
8197
8366
|
import { execFileSync as execFileSync22 } from "node:child_process";
|
|
8198
8367
|
function gitCapture(args, cwd) {
|
|
@@ -8231,13 +8400,13 @@ function parseDirtyPaths(repo, opts = {}) {
|
|
|
8231
8400
|
return parsePorcelainZ(gitStatusPorcelainZ(repo, opts));
|
|
8232
8401
|
}
|
|
8233
8402
|
|
|
8234
|
-
// src/commands
|
|
8403
|
+
// src/commands/pull/win32.ts
|
|
8235
8404
|
init_config();
|
|
8236
8405
|
|
|
8237
|
-
// src/links.deletions.ts
|
|
8406
|
+
// src/sync/links.deletions.ts
|
|
8238
8407
|
init_config();
|
|
8239
|
-
import { existsSync as
|
|
8240
|
-
import { join as
|
|
8408
|
+
import { existsSync as existsSync41, lstatSync as lstatSync19, rmSync as rmSync17 } from "node:fs";
|
|
8409
|
+
import { join as join59, relative as relative9, resolve as resolve5, sep as sep13 } from "node:path";
|
|
8241
8410
|
init_utils();
|
|
8242
8411
|
init_utils_fs();
|
|
8243
8412
|
function isUnknown(declined, key) {
|
|
@@ -8247,15 +8416,15 @@ function deletionFor(key, names, claude, sharedRoot) {
|
|
|
8247
8416
|
const segments = key.split("/");
|
|
8248
8417
|
const name = segments[0];
|
|
8249
8418
|
if (!names.has(name)) return null;
|
|
8250
|
-
if (!
|
|
8419
|
+
if (!existsSync41(join59(claude, name))) return null;
|
|
8251
8420
|
if (segments.some((segment) => isDeniedName(ALWAYS_NEVER_SYNC, segment))) return null;
|
|
8252
8421
|
const repoPath = resolve5(sharedRoot, key);
|
|
8253
|
-
const rel = relative9(
|
|
8422
|
+
const rel = relative9(join59(sharedRoot, name), repoPath);
|
|
8254
8423
|
if (rel === "" || rel === ".." || rel.startsWith(`..${sep13}`)) return null;
|
|
8255
8424
|
if (segments.some((segment) => segment === "" || segment === "." || segment === ".."))
|
|
8256
8425
|
return null;
|
|
8257
|
-
if (!
|
|
8258
|
-
return { kind: "deletion", name, localPath:
|
|
8426
|
+
if (!existsSync41(repoPath)) return null;
|
|
8427
|
+
return { kind: "deletion", name, localPath: join59(claude, key), repoPath };
|
|
8259
8428
|
}
|
|
8260
8429
|
function planSharedLinkDeletions(map, opts = {}) {
|
|
8261
8430
|
if (process.platform !== "win32") return [];
|
|
@@ -8263,7 +8432,7 @@ function planSharedLinkDeletions(map, opts = {}) {
|
|
|
8263
8432
|
const baseline = readSharedBaseline();
|
|
8264
8433
|
if (baseline === null) return [];
|
|
8265
8434
|
const claude = claudeHome();
|
|
8266
|
-
const sharedRoot =
|
|
8435
|
+
const sharedRoot = join59(repoHome(), "shared");
|
|
8267
8436
|
const linkNames = opts.linkNames ?? allSharedLinks(map);
|
|
8268
8437
|
const scan = enumerateLocalSharedScan(map, { linkNames });
|
|
8269
8438
|
const present = new Set(Object.keys(scan.files).map((key) => key.toLowerCase()));
|
|
@@ -8295,11 +8464,11 @@ function applySharedLinkDeletions(map, ts, opts = {}) {
|
|
|
8295
8464
|
return removed;
|
|
8296
8465
|
}
|
|
8297
8466
|
|
|
8298
|
-
// src/links.mirror.ts
|
|
8467
|
+
// src/sync/links.mirror.ts
|
|
8299
8468
|
init_config();
|
|
8300
8469
|
init_error_text();
|
|
8301
|
-
import { existsSync as
|
|
8302
|
-
import { join as
|
|
8470
|
+
import { existsSync as existsSync42, lstatSync as lstatSync20, rmSync as rmSync18, statSync as statSync12 } from "node:fs";
|
|
8471
|
+
import { join as join60 } from "node:path";
|
|
8303
8472
|
init_utils();
|
|
8304
8473
|
init_utils_fs();
|
|
8305
8474
|
function emitMirror(onPreview, name, localPath, repoPath) {
|
|
@@ -8313,7 +8482,7 @@ function emitMirrorWet(onPreview, name, localPath, repoPath) {
|
|
|
8313
8482
|
if (onPreview) onPreview({ kind: "mirror", name, localPath, repoPath });
|
|
8314
8483
|
}
|
|
8315
8484
|
function notShared(target) {
|
|
8316
|
-
return !
|
|
8485
|
+
return !existsSync42(target);
|
|
8317
8486
|
}
|
|
8318
8487
|
function warnUnusableSharedTarget(name, dryRun, state) {
|
|
8319
8488
|
const reason = state === "dangling" ? `shared/${name} does not resolve to anything usable in the sync repo. Remove it, or restore what it points at` : `shared/${name} could not be read in the sync repo, so whether it is usable could not be determined. Check its permissions there`;
|
|
@@ -8341,8 +8510,8 @@ function warnUnreadableLocalName(name, target, err, dryRun) {
|
|
|
8341
8510
|
);
|
|
8342
8511
|
}
|
|
8343
8512
|
function mirrorOneSharedName(name, claude, repo, policy, opts) {
|
|
8344
|
-
const localPath =
|
|
8345
|
-
const target =
|
|
8513
|
+
const localPath = join60(claude, name);
|
|
8514
|
+
const target = join60(repo, "shared", name);
|
|
8346
8515
|
let stat;
|
|
8347
8516
|
try {
|
|
8348
8517
|
stat = lstatSync20(localPath, { throwIfNoEntry: false });
|
|
@@ -8402,7 +8571,7 @@ function mirrorSharedNames(map, policy, opts = {}) {
|
|
|
8402
8571
|
if (map === null) return;
|
|
8403
8572
|
const claude = claudeHome();
|
|
8404
8573
|
const repo = repoHome();
|
|
8405
|
-
const sharedPath =
|
|
8574
|
+
const sharedPath = join60(repo, "shared");
|
|
8406
8575
|
const sharedState = classifyPresence(sharedPath);
|
|
8407
8576
|
if (isUnusableTarget(sharedState)) {
|
|
8408
8577
|
warnUnusableSharedDir(opts.dryRun === true, sharedState);
|
|
@@ -8431,7 +8600,7 @@ function presentAt(abs) {
|
|
|
8431
8600
|
}
|
|
8432
8601
|
}
|
|
8433
8602
|
function removeUntrackedDenied(repo, path, segment, ts) {
|
|
8434
|
-
const abs =
|
|
8603
|
+
const abs = join60(repo, path);
|
|
8435
8604
|
const denied = `the path segment "${segment}" is on the never-sync list`;
|
|
8436
8605
|
if (!presentAt(abs)) {
|
|
8437
8606
|
warn(
|
|
@@ -8439,7 +8608,7 @@ function removeUntrackedDenied(repo, path, segment, ts) {
|
|
|
8439
8608
|
);
|
|
8440
8609
|
return;
|
|
8441
8610
|
}
|
|
8442
|
-
const snapshotted =
|
|
8611
|
+
const snapshotted = existsSync42(abs);
|
|
8443
8612
|
try {
|
|
8444
8613
|
backupRepoWrite(abs, ts, repo);
|
|
8445
8614
|
} catch (err) {
|
|
@@ -8475,7 +8644,7 @@ function reportTrackedDenied(repo, path, segment) {
|
|
|
8475
8644
|
);
|
|
8476
8645
|
return;
|
|
8477
8646
|
}
|
|
8478
|
-
if (!
|
|
8647
|
+
if (!existsSync42(join60(repo, path))) return;
|
|
8479
8648
|
warn(
|
|
8480
8649
|
`${path} is tracked and has changes against HEAD: ${denied}. Nothing was changed. Run git checkout HEAD -- "${path}" to put the committed content back, or move the file outside shared/ if you want to keep it. Neither of those takes the committed copy out of the repo: git rm -- "${path}" and a commit does that going forward, and if it holds a real secret, rotate it and rewrite history, because nomad only changes your local worktree and index and cannot scrub what a previous push already sent to the remote`
|
|
8481
8650
|
);
|
|
@@ -8491,10 +8660,10 @@ function revertDeniedMirrorPaths(repo, status, ts) {
|
|
|
8491
8660
|
}
|
|
8492
8661
|
}
|
|
8493
8662
|
|
|
8494
|
-
// src/preview.ts
|
|
8663
|
+
// src/render/preview.ts
|
|
8495
8664
|
init_config();
|
|
8496
|
-
import { existsSync as
|
|
8497
|
-
import { join as
|
|
8665
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
8666
|
+
import { join as join62 } from "node:path";
|
|
8498
8667
|
|
|
8499
8668
|
// node_modules/diff/libesm/diff/base.js
|
|
8500
8669
|
var Diff = class {
|
|
@@ -8746,7 +8915,7 @@ function tokenize(value, options) {
|
|
|
8746
8915
|
return retLines;
|
|
8747
8916
|
}
|
|
8748
8917
|
|
|
8749
|
-
// src/diff-lines.ts
|
|
8918
|
+
// src/render/diff-lines.ts
|
|
8750
8919
|
init_color();
|
|
8751
8920
|
function diffLinesToUnified(oldStr, newStr) {
|
|
8752
8921
|
const parts = diffLines(oldStr, newStr);
|
|
@@ -8767,18 +8936,18 @@ function diffLinesToUnified(oldStr, newStr) {
|
|
|
8767
8936
|
return lines;
|
|
8768
8937
|
}
|
|
8769
8938
|
|
|
8770
|
-
// src/preview.skills.ts
|
|
8939
|
+
// src/render/preview.skills.ts
|
|
8771
8940
|
init_config();
|
|
8772
|
-
import { existsSync as
|
|
8773
|
-
import { join as
|
|
8941
|
+
import { existsSync as existsSync43, readdirSync as readdirSync19 } from "node:fs";
|
|
8942
|
+
import { join as join61 } from "node:path";
|
|
8774
8943
|
function buildSkillsPreviewSection() {
|
|
8775
8944
|
const s = section("Skills");
|
|
8776
|
-
const sharedSkills =
|
|
8777
|
-
if (!
|
|
8945
|
+
const sharedSkills = join61(repoHome(), "shared", "skills");
|
|
8946
|
+
if (!existsSync43(sharedSkills)) return s;
|
|
8778
8947
|
const sharedNames = readdirSync19(sharedSkills, { encoding: "utf8" }).filter((name) => !isSkillExcluded(name)).sort((a, b) => a.localeCompare(b, "en"));
|
|
8779
8948
|
for (const name of sharedNames) addItem(s, name);
|
|
8780
|
-
const localSkills =
|
|
8781
|
-
const localOnly =
|
|
8949
|
+
const localSkills = join61(claudeHome(), "skills");
|
|
8950
|
+
const localOnly = existsSync43(localSkills) ? readdirSync19(localSkills, { encoding: "utf8" }).filter(
|
|
8782
8951
|
(name) => !isSkillExcluded(name) && !sharedNames.includes(name)
|
|
8783
8952
|
).length : 0;
|
|
8784
8953
|
if (localOnly > 0) {
|
|
@@ -8787,7 +8956,7 @@ function buildSkillsPreviewSection() {
|
|
|
8787
8956
|
return s;
|
|
8788
8957
|
}
|
|
8789
8958
|
|
|
8790
|
-
// src/preview.ts
|
|
8959
|
+
// src/render/preview.ts
|
|
8791
8960
|
init_utils_json();
|
|
8792
8961
|
var CANONICAL_ORDER_NOTE = "settings.json will be rewritten in canonical key order; no value changes";
|
|
8793
8962
|
function diffJsonStrings(currentJsonText, newJsonText) {
|
|
@@ -8800,7 +8969,7 @@ function diffJsonStrings(currentJsonText, newJsonText) {
|
|
|
8800
8969
|
return lines.join("\n");
|
|
8801
8970
|
}
|
|
8802
8971
|
function readJsonOrNull(path) {
|
|
8803
|
-
if (!
|
|
8972
|
+
if (!existsSync44(path)) return null;
|
|
8804
8973
|
try {
|
|
8805
8974
|
return readJson(path);
|
|
8806
8975
|
} catch {
|
|
@@ -8814,12 +8983,12 @@ function previewSettings(basePath, hostPath, settingsPath) {
|
|
|
8814
8983
|
}
|
|
8815
8984
|
const notes = [];
|
|
8816
8985
|
const hostOverrides = readJsonOrNull(hostPath);
|
|
8817
|
-
if (hostOverrides === null &&
|
|
8986
|
+
if (hostOverrides === null && existsSync44(hostPath)) {
|
|
8818
8987
|
notes.push(`malformed hosts/${HOST}.json; ignoring overrides`);
|
|
8819
8988
|
}
|
|
8820
8989
|
const merged = stripGsdHookEntries(deepMerge(base, hostOverrides ?? {}));
|
|
8821
8990
|
const current = readJsonOrNull(settingsPath);
|
|
8822
|
-
if (current === null &&
|
|
8991
|
+
if (current === null && existsSync44(settingsPath)) {
|
|
8823
8992
|
return { diff: "", notes: [...notes, "malformed; skipping diff"] };
|
|
8824
8993
|
}
|
|
8825
8994
|
const strippedCurrent = stripGsdHookEntries(current ?? {});
|
|
@@ -8886,9 +9055,9 @@ function computePreview(ts, map, verb = "pull", plans) {
|
|
|
8886
9055
|
onPreview: (e) => addItem(links, formatLinkRow(e))
|
|
8887
9056
|
});
|
|
8888
9057
|
const settingsResult = previewSettings(
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
9058
|
+
join62(repo, "shared", "settings.base.json"),
|
|
9059
|
+
join62(repo, "hosts", `${HOST}.json`),
|
|
9060
|
+
join62(claude, "settings.json")
|
|
8892
9061
|
);
|
|
8893
9062
|
const settingsSection = buildSettingsSectionForPreview(settingsResult);
|
|
8894
9063
|
const sessions = section("Sessions");
|
|
@@ -8904,7 +9073,7 @@ function computePreview(ts, map, verb = "pull", plans) {
|
|
|
8904
9073
|
const extras = section("Extras");
|
|
8905
9074
|
let extrasSkipped = 0;
|
|
8906
9075
|
let extrasUnmapped = 0;
|
|
8907
|
-
if (
|
|
9076
|
+
if (existsSync44(join62(repo, "path-map.json")) && existsSync44(join62(repo, "shared", "extras"))) {
|
|
8908
9077
|
const extrasResult = remapExtrasPull(ts, { dryRun: true });
|
|
8909
9078
|
for (const entry of extrasResult.wouldPull) {
|
|
8910
9079
|
addItem(extras, entry);
|
|
@@ -8921,11 +9090,11 @@ function computePreview(ts, map, verb = "pull", plans) {
|
|
|
8921
9090
|
return { unmapped: remapResult.unmapped, collisions: 0, localOnly };
|
|
8922
9091
|
}
|
|
8923
9092
|
|
|
8924
|
-
// src/commands
|
|
9093
|
+
// src/commands/pull/win32.ts
|
|
8925
9094
|
init_utils();
|
|
8926
9095
|
init_utils_json();
|
|
8927
9096
|
function readMapForMirror(mapPath) {
|
|
8928
|
-
if (!
|
|
9097
|
+
if (!existsSync45(mapPath)) return { projects: {} };
|
|
8929
9098
|
try {
|
|
8930
9099
|
return readPathMap(mapPath);
|
|
8931
9100
|
} catch {
|
|
@@ -8989,7 +9158,7 @@ function reconcileSharedLinksBeforePull(repo, ts) {
|
|
|
8989
9158
|
let namesDerived = false;
|
|
8990
9159
|
let derivedSharedDirs;
|
|
8991
9160
|
try {
|
|
8992
|
-
const map = readMapForMirror(
|
|
9161
|
+
const map = readMapForMirror(join63(repo, "path-map.json"));
|
|
8993
9162
|
if (map !== null) {
|
|
8994
9163
|
linkNames = allSharedLinks(map);
|
|
8995
9164
|
namesDerived = true;
|
|
@@ -9028,7 +9197,7 @@ function buildMirrorSection(events, discard) {
|
|
|
9028
9197
|
function describeSkippedMirrorDiscard(repo, ts) {
|
|
9029
9198
|
if (process.platform !== "win32") return null;
|
|
9030
9199
|
try {
|
|
9031
|
-
const map = readMapForMirror(
|
|
9200
|
+
const map = readMapForMirror(join63(repo, "path-map.json"));
|
|
9032
9201
|
const linkNames = map !== null ? allSharedLinks(map, { quiet: true }) : void 0;
|
|
9033
9202
|
const captures = [];
|
|
9034
9203
|
stageLocalSharedEdits(map, ts, {
|
|
@@ -9037,13 +9206,13 @@ function describeSkippedMirrorDiscard(repo, ts) {
|
|
|
9037
9206
|
linkNames
|
|
9038
9207
|
});
|
|
9039
9208
|
if (captures.length === 0) return null;
|
|
9040
|
-
return { count: captures.length, backupPath:
|
|
9209
|
+
return { count: captures.length, backupPath: join63(backupBase(), ts) };
|
|
9041
9210
|
} catch {
|
|
9042
9211
|
return null;
|
|
9043
9212
|
}
|
|
9044
9213
|
}
|
|
9045
9214
|
function planSharedReconcileBeforePull(repo, ts) {
|
|
9046
|
-
const map = readMapForMirror(
|
|
9215
|
+
const map = readMapForMirror(join63(repo, "path-map.json"));
|
|
9047
9216
|
const captures = [];
|
|
9048
9217
|
const linkNames = process.platform === "win32" && map !== null ? allSharedLinks(map) : void 0;
|
|
9049
9218
|
stageLocalSharedEdits(map, ts, { dryRun: true, onPreview: (e) => captures.push(e), linkNames });
|
|
@@ -9055,11 +9224,11 @@ function planSharedReconcileBeforePull(repo, ts) {
|
|
|
9055
9224
|
};
|
|
9056
9225
|
}
|
|
9057
9226
|
|
|
9058
|
-
// src/commands
|
|
9227
|
+
// src/commands/pull/collision.ts
|
|
9059
9228
|
init_config();
|
|
9060
9229
|
init_exit_codes();
|
|
9061
|
-
import { existsSync as
|
|
9062
|
-
import { join as
|
|
9230
|
+
import { existsSync as existsSync46, lstatSync as lstatSync21, readFileSync as readFileSync20, rmSync as rmSync19 } from "node:fs";
|
|
9231
|
+
import { join as join64 } from "node:path";
|
|
9063
9232
|
init_utils();
|
|
9064
9233
|
var SHARED_PREFIX = /^shared\//;
|
|
9065
9234
|
var EXTENSION = /(\.[^.]+)?$/;
|
|
@@ -9115,15 +9284,15 @@ function isContainedMirrorPath(rel) {
|
|
|
9115
9284
|
}
|
|
9116
9285
|
function matchesLocalOriginal(repo, rel) {
|
|
9117
9286
|
try {
|
|
9118
|
-
const local =
|
|
9119
|
-
return readFileSync20(
|
|
9287
|
+
const local = join64(claudeHome(), rel.replace(SHARED_PREFIX, ""));
|
|
9288
|
+
return readFileSync20(join64(repo, rel)).equals(readFileSync20(local));
|
|
9120
9289
|
} catch {
|
|
9121
9290
|
return false;
|
|
9122
9291
|
}
|
|
9123
9292
|
}
|
|
9124
9293
|
function removeMirroredCopies(repo, repoRelPaths) {
|
|
9125
9294
|
for (const rel of repoRelPaths.filter(isContainedMirrorPath)) {
|
|
9126
|
-
const abs =
|
|
9295
|
+
const abs = join64(repo, rel);
|
|
9127
9296
|
try {
|
|
9128
9297
|
if (lstatSync21(abs, { throwIfNoEntry: false })?.isFile() !== true) continue;
|
|
9129
9298
|
if (!matchesLocalOriginal(repo, rel)) continue;
|
|
@@ -9132,7 +9301,7 @@ function removeMirroredCopies(repo, repoRelPaths) {
|
|
|
9132
9301
|
warn(`could not remove nomad's copy at ${abs}: ${err.message}`);
|
|
9133
9302
|
}
|
|
9134
9303
|
}
|
|
9135
|
-
return repoRelPaths.every((rel) => !
|
|
9304
|
+
return repoRelPaths.every((rel) => !existsSync46(join64(repo, rel)));
|
|
9136
9305
|
}
|
|
9137
9306
|
function pullWithCollisionRunbook(repo, mirrored) {
|
|
9138
9307
|
try {
|
|
@@ -9147,10 +9316,10 @@ function pullWithCollisionRunbook(repo, mirrored) {
|
|
|
9147
9316
|
}
|
|
9148
9317
|
}
|
|
9149
9318
|
|
|
9150
|
-
// src/commands
|
|
9151
|
-
|
|
9319
|
+
// src/commands/pull/pull.ts
|
|
9320
|
+
init_wedge();
|
|
9152
9321
|
|
|
9153
|
-
// src/commands
|
|
9322
|
+
// src/commands/pull/recovery.ts
|
|
9154
9323
|
init_config();
|
|
9155
9324
|
init_utils();
|
|
9156
9325
|
init_utils_fs();
|
|
@@ -9244,9 +9413,9 @@ an ordinary pull.
|
|
|
9244
9413
|
log(buildRecoverySummary(branchName, strandedLog, untracked));
|
|
9245
9414
|
}
|
|
9246
9415
|
|
|
9247
|
-
// src/commands
|
|
9416
|
+
// src/commands/pull/recovery.unmerged.ts
|
|
9248
9417
|
init_exit_codes();
|
|
9249
|
-
|
|
9418
|
+
init_wedge();
|
|
9250
9419
|
init_utils();
|
|
9251
9420
|
function recoverUnmergedIndex(repo) {
|
|
9252
9421
|
const conflicted = new Set(
|
|
@@ -9269,7 +9438,7 @@ function recoverUnmergedIndex(repo) {
|
|
|
9269
9438
|
}
|
|
9270
9439
|
}
|
|
9271
9440
|
|
|
9272
|
-
// src/commands
|
|
9441
|
+
// src/commands/pull/pull.ts
|
|
9273
9442
|
init_exit_codes();
|
|
9274
9443
|
init_utils();
|
|
9275
9444
|
init_utils_fs();
|
|
@@ -9339,7 +9508,7 @@ function runPullCore(opts = {}) {
|
|
|
9339
9508
|
try {
|
|
9340
9509
|
return runPullWithBackupTs(ts, opts);
|
|
9341
9510
|
} finally {
|
|
9342
|
-
discardEmptyBackupDir(
|
|
9511
|
+
discardEmptyBackupDir(join65(backup, ts));
|
|
9343
9512
|
}
|
|
9344
9513
|
}
|
|
9345
9514
|
function runPullWithBackupTs(ts, opts) {
|
|
@@ -9350,7 +9519,7 @@ function runPullWithBackupTs(ts, opts) {
|
|
|
9350
9519
|
const backup = backupBase();
|
|
9351
9520
|
const recovered = handleWedge(repo, forceRemote);
|
|
9352
9521
|
if (!dryRun) {
|
|
9353
|
-
const backupRoot =
|
|
9522
|
+
const backupRoot = join65(backup, ts);
|
|
9354
9523
|
try {
|
|
9355
9524
|
mkdirSync14(backupRoot, { recursive: true });
|
|
9356
9525
|
} catch (err) {
|
|
@@ -9373,8 +9542,8 @@ function runPullWithBackupTs(ts, opts) {
|
|
|
9373
9542
|
pullWithCollisionRunbook(repo, mirrored);
|
|
9374
9543
|
});
|
|
9375
9544
|
assertNoAutostashConflict(repo, "nomad pull");
|
|
9376
|
-
const mapPath =
|
|
9377
|
-
const map =
|
|
9545
|
+
const mapPath = join65(repo, "path-map.json");
|
|
9546
|
+
const map = existsSync47(mapPath) ? readPathMap(mapPath) : { projects: {} };
|
|
9378
9547
|
const divergedKeptLocal = divergenceCheckExtras(ts, dryRun ? prePostHeads : void 0);
|
|
9379
9548
|
if (dryRun) {
|
|
9380
9549
|
computePreview(ts, map, "pull", plansAgainst(sharedPlans, map));
|
|
@@ -9401,8 +9570,8 @@ function runPullWithBackupTs(ts, opts) {
|
|
|
9401
9570
|
}
|
|
9402
9571
|
function cmdPull(opts = {}) {
|
|
9403
9572
|
const repo = repoHome();
|
|
9404
|
-
if (!
|
|
9405
|
-
if (!
|
|
9573
|
+
if (!existsSync47(repo)) die(`repo not cloned at ${repo}`);
|
|
9574
|
+
if (!existsSync47(join65(repo, "shared", "settings.base.json"))) {
|
|
9406
9575
|
die("repo not initialized; run 'nomad init' to scaffold");
|
|
9407
9576
|
}
|
|
9408
9577
|
const handle = acquireLock("pull");
|
|
@@ -9423,15 +9592,15 @@ function cmdPull(opts = {}) {
|
|
|
9423
9592
|
}
|
|
9424
9593
|
}
|
|
9425
9594
|
|
|
9426
|
-
// src/commands
|
|
9595
|
+
// src/commands/push/push.ts
|
|
9427
9596
|
init_config();
|
|
9428
|
-
import { existsSync as
|
|
9429
|
-
import { join as
|
|
9597
|
+
import { existsSync as existsSync51 } from "node:fs";
|
|
9598
|
+
import { join as join70 } from "node:path";
|
|
9430
9599
|
|
|
9431
|
-
// src/commands
|
|
9600
|
+
// src/commands/push/selection.ts
|
|
9432
9601
|
init_config();
|
|
9433
|
-
import { existsSync as
|
|
9434
|
-
import { join as
|
|
9602
|
+
import { existsSync as existsSync48, statSync as statSync13 } from "node:fs";
|
|
9603
|
+
import { join as join66 } from "node:path";
|
|
9435
9604
|
init_utils_json();
|
|
9436
9605
|
function buildCurrentMap(map) {
|
|
9437
9606
|
const current = {};
|
|
@@ -9440,8 +9609,8 @@ function buildCurrentMap(map) {
|
|
|
9440
9609
|
for (const [, hostMap] of Object.entries(map.projects)) {
|
|
9441
9610
|
const localPath = hostMap[HOST];
|
|
9442
9611
|
if (!localPath) continue;
|
|
9443
|
-
const localDir =
|
|
9444
|
-
if (!
|
|
9612
|
+
const localDir = join66(claude, "projects", encodePath(localPath));
|
|
9613
|
+
if (!existsSync48(localDir)) continue;
|
|
9445
9614
|
for (const f of enumerateSourceFiles(localDir)) {
|
|
9446
9615
|
const st = statSync13(f);
|
|
9447
9616
|
current[f] = { size: st.size, mtime: st.mtimeMs };
|
|
@@ -9472,7 +9641,7 @@ function computePushSelection(map, old, scannerVersion, configHash, fullScan) {
|
|
|
9472
9641
|
};
|
|
9473
9642
|
}
|
|
9474
9643
|
function loadSelectionForPush(mapPath, old, scannerVersion, configHash, fullScan) {
|
|
9475
|
-
const map =
|
|
9644
|
+
const map = existsSync48(mapPath) ? readPathMap(mapPath) : null;
|
|
9476
9645
|
const { selection, newManifest } = computePushSelection(
|
|
9477
9646
|
map,
|
|
9478
9647
|
old,
|
|
@@ -9483,7 +9652,7 @@ function loadSelectionForPush(mapPath, old, scannerVersion, configHash, fullScan
|
|
|
9483
9652
|
return { map, selection, newManifest };
|
|
9484
9653
|
}
|
|
9485
9654
|
|
|
9486
|
-
// src/commands
|
|
9655
|
+
// src/commands/push/allowlist.ts
|
|
9487
9656
|
init_config();
|
|
9488
9657
|
init_config_sharedDirs_guard();
|
|
9489
9658
|
init_utils();
|
|
@@ -9558,21 +9727,21 @@ function enforceAllowList(statusPorcelain, map) {
|
|
|
9558
9727
|
fail(`${p} is in NEVER_SYNC and must never be pushed`);
|
|
9559
9728
|
}
|
|
9560
9729
|
for (const p of violations) {
|
|
9561
|
-
fail(`to sync ${p}, add to PUSH_ALLOWED in src/config.ts`);
|
|
9730
|
+
fail(`to sync ${p}, add to PUSH_ALLOWED in src/core/config.ts`);
|
|
9562
9731
|
}
|
|
9563
9732
|
throw new NomadFatal("push allow-list violations");
|
|
9564
9733
|
}
|
|
9565
9734
|
|
|
9566
|
-
// src/commands
|
|
9735
|
+
// src/commands/push/settings.ts
|
|
9567
9736
|
init_config();
|
|
9568
|
-
import { existsSync as
|
|
9569
|
-
import { join as
|
|
9737
|
+
import { existsSync as existsSync49 } from "node:fs";
|
|
9738
|
+
import { join as join67 } from "node:path";
|
|
9570
9739
|
init_utils();
|
|
9571
9740
|
init_utils_fs();
|
|
9572
9741
|
init_utils_json();
|
|
9573
9742
|
function stripGsdHooksFromBase(repo, backup) {
|
|
9574
|
-
const basePath =
|
|
9575
|
-
if (!
|
|
9743
|
+
const basePath = join67(repo, "shared", "settings.base.json");
|
|
9744
|
+
if (!existsSync49(basePath)) return;
|
|
9576
9745
|
let base;
|
|
9577
9746
|
try {
|
|
9578
9747
|
base = readJson(basePath);
|
|
@@ -9586,14 +9755,14 @@ function stripGsdHooksFromBase(repo, backup) {
|
|
|
9586
9755
|
writeJsonAtomic(basePath, stripped);
|
|
9587
9756
|
}
|
|
9588
9757
|
function reportSettingsAheadDrift(repo) {
|
|
9589
|
-
const basePath =
|
|
9590
|
-
if (!
|
|
9591
|
-
const settingsPath =
|
|
9592
|
-
if (!
|
|
9758
|
+
const basePath = join67(repo, "shared", "settings.base.json");
|
|
9759
|
+
if (!existsSync49(basePath)) return;
|
|
9760
|
+
const settingsPath = join67(claudeHome(), "settings.json");
|
|
9761
|
+
if (!existsSync49(settingsPath)) return;
|
|
9593
9762
|
try {
|
|
9594
9763
|
const base = readJson(basePath);
|
|
9595
|
-
const hostPath =
|
|
9596
|
-
const overrides =
|
|
9764
|
+
const hostPath = join67(repo, "hosts", `${HOST}.json`);
|
|
9765
|
+
const overrides = existsSync49(hostPath) ? readJson(hostPath) : {};
|
|
9597
9766
|
const merged = deepMerge(base, overrides);
|
|
9598
9767
|
const settings = readJson(settingsPath);
|
|
9599
9768
|
const { ahead } = classifySettingsDrift(merged, settings);
|
|
@@ -9607,12 +9776,12 @@ function reportSettingsAheadDrift(repo) {
|
|
|
9607
9776
|
}
|
|
9608
9777
|
}
|
|
9609
9778
|
|
|
9610
|
-
// src/commands
|
|
9611
|
-
|
|
9779
|
+
// src/commands/push/guards.ts
|
|
9780
|
+
init_checks();
|
|
9612
9781
|
init_utils();
|
|
9613
|
-
import { join as
|
|
9782
|
+
import { join as join68, relative as relative10 } from "node:path";
|
|
9614
9783
|
function guardGitlinks(repo) {
|
|
9615
|
-
const gitlinks = findGitlinks(
|
|
9784
|
+
const gitlinks = findGitlinks(join68(repo, "shared"));
|
|
9616
9785
|
if (gitlinks.length === 0) return;
|
|
9617
9786
|
for (const p of gitlinks) {
|
|
9618
9787
|
const rel = relative10(repo, p).replaceAll("\\", "/");
|
|
@@ -9639,10 +9808,10 @@ function guardResolutionModeConflicts(dryRun, redactAll, allowAll, allowRule) {
|
|
|
9639
9808
|
}
|
|
9640
9809
|
}
|
|
9641
9810
|
|
|
9642
|
-
// src/commands
|
|
9811
|
+
// src/commands/push/steps.ts
|
|
9643
9812
|
init_config();
|
|
9644
9813
|
|
|
9645
|
-
// src/push
|
|
9814
|
+
// src/commands/push/global-config.ts
|
|
9646
9815
|
init_config();
|
|
9647
9816
|
import { execFileSync as execFileSync23 } from "node:child_process";
|
|
9648
9817
|
var STATUS_LABELS = {
|
|
@@ -9714,19 +9883,19 @@ function collectGlobalConfigChanges(repoHome2, hostname2, opts) {
|
|
|
9714
9883
|
return changes;
|
|
9715
9884
|
}
|
|
9716
9885
|
|
|
9717
|
-
// src/commands
|
|
9718
|
-
|
|
9886
|
+
// src/commands/push/steps.ts
|
|
9887
|
+
init_leak_verdict();
|
|
9719
9888
|
|
|
9720
|
-
// src/push
|
|
9889
|
+
// src/commands/push/preview.ts
|
|
9721
9890
|
init_color();
|
|
9722
9891
|
init_config();
|
|
9723
9892
|
init_config_sharedDirs_guard();
|
|
9724
9893
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
9725
|
-
import { copyFileSync, existsSync as
|
|
9894
|
+
import { copyFileSync, existsSync as existsSync50, lstatSync as lstatSync22, mkdirSync as mkdirSync15, readdirSync as readdirSync20, rmSync as rmSync20 } from "node:fs";
|
|
9726
9895
|
import { homedir as homedir7 } from "node:os";
|
|
9727
|
-
import { join as
|
|
9728
|
-
|
|
9729
|
-
|
|
9896
|
+
import { join as join69, relative as relative11, sep as sep14 } from "node:path";
|
|
9897
|
+
init_leak_verdict();
|
|
9898
|
+
init_gitleaks();
|
|
9730
9899
|
init_utils_fs();
|
|
9731
9900
|
init_utils_json();
|
|
9732
9901
|
var NOTHING_TO_SCAN_ROW = `${dim(infoGlyph)} nothing to scan, no leaks`;
|
|
@@ -9736,7 +9905,7 @@ function stageSessionDir(localDir, dstDir, changed) {
|
|
|
9736
9905
|
const matching = [...changed].filter((p) => p.startsWith(prefix));
|
|
9737
9906
|
if (matching.length === 0) return false;
|
|
9738
9907
|
for (const src of matching) {
|
|
9739
|
-
copyFileAtomic(src,
|
|
9908
|
+
copyFileAtomic(src, join69(dstDir, relative11(localDir, src)));
|
|
9740
9909
|
}
|
|
9741
9910
|
return true;
|
|
9742
9911
|
}
|
|
@@ -9752,14 +9921,14 @@ function stageSessions(tmpRoot, map, changed) {
|
|
|
9752
9921
|
if (!p || p === "TBD") continue;
|
|
9753
9922
|
reverse.set(encodePath(p), logical);
|
|
9754
9923
|
}
|
|
9755
|
-
const localProjects =
|
|
9756
|
-
if (!
|
|
9924
|
+
const localProjects = join69(claudeHome(), "projects");
|
|
9925
|
+
if (!existsSync50(localProjects)) return 0;
|
|
9757
9926
|
let staged = 0;
|
|
9758
9927
|
for (const dir of readdirSync20(localProjects)) {
|
|
9759
9928
|
const logical = reverse.get(dir);
|
|
9760
9929
|
if (!logical) continue;
|
|
9761
|
-
const localDir =
|
|
9762
|
-
const dstDir =
|
|
9930
|
+
const localDir = join69(localProjects, dir);
|
|
9931
|
+
const dstDir = join69(tmpRoot, "shared", "projects", logical);
|
|
9763
9932
|
if (stageSessionDir(localDir, dstDir, changed)) staged++;
|
|
9764
9933
|
}
|
|
9765
9934
|
return staged;
|
|
@@ -9773,11 +9942,11 @@ function stageExtras(tmpRoot, map) {
|
|
|
9773
9942
|
assertSafeLogical(logical);
|
|
9774
9943
|
const localRoot = map.projects[logical]?.[HOST];
|
|
9775
9944
|
if (!localRoot || localRoot === "TBD") continue;
|
|
9776
|
-
for (const
|
|
9777
|
-
if (!whitelist.includes(
|
|
9778
|
-
const src =
|
|
9779
|
-
if (!
|
|
9780
|
-
const dst =
|
|
9945
|
+
for (const dirname16 of dirnames) {
|
|
9946
|
+
if (!whitelist.includes(dirname16)) continue;
|
|
9947
|
+
const src = join69(localRoot, dirname16);
|
|
9948
|
+
if (!existsSync50(src)) continue;
|
|
9949
|
+
const dst = join69(tmpRoot, "shared", "extras", logical, dirname16);
|
|
9781
9950
|
copyExtras(src, dst);
|
|
9782
9951
|
staged++;
|
|
9783
9952
|
}
|
|
@@ -9785,19 +9954,19 @@ function stageExtras(tmpRoot, map) {
|
|
|
9785
9954
|
return staged;
|
|
9786
9955
|
}
|
|
9787
9956
|
function stageSkills(tmpRoot) {
|
|
9788
|
-
const localSkills =
|
|
9957
|
+
const localSkills = join69(claudeHome(), "skills");
|
|
9789
9958
|
const stat = lstatSync22(localSkills, { throwIfNoEntry: false });
|
|
9790
9959
|
if (stat === void 0 || stat.isSymbolicLink()) return 0;
|
|
9791
9960
|
const names = readdirSync20(localSkills, { encoding: "utf8" }).filter((n) => !isSkillExcluded(n));
|
|
9792
9961
|
if (names.length === 0) return 0;
|
|
9793
|
-
copySkillsPush(localSkills,
|
|
9962
|
+
copySkillsPush(localSkills, join69(tmpRoot, "shared", "skills"));
|
|
9794
9963
|
return names.length;
|
|
9795
9964
|
}
|
|
9796
9965
|
function previewPushLeaks(map, opts = {}) {
|
|
9797
|
-
const cacheDir =
|
|
9966
|
+
const cacheDir = join69(homedir7(), ".cache", "claude-nomad");
|
|
9798
9967
|
mkdirSync15(cacheDir, { recursive: true });
|
|
9799
9968
|
const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes4(4).toString("hex")}`;
|
|
9800
|
-
const tmpRoot =
|
|
9969
|
+
const tmpRoot = join69(cacheDir, `push-preview-tree-${stamp}`);
|
|
9801
9970
|
try {
|
|
9802
9971
|
const sessionCount = stageSessions(tmpRoot, map, opts.selection?.changed);
|
|
9803
9972
|
const extrasCount = stageExtras(tmpRoot, map);
|
|
@@ -9805,9 +9974,9 @@ function previewPushLeaks(map, opts = {}) {
|
|
|
9805
9974
|
if (sessionCount + extrasCount + skillCount === 0) {
|
|
9806
9975
|
return { leak: false, verdictRow: NOTHING_TO_SCAN_ROW, recovery: null, findings: [] };
|
|
9807
9976
|
}
|
|
9808
|
-
const ignoreFile =
|
|
9809
|
-
if (
|
|
9810
|
-
copyFileSync(ignoreFile,
|
|
9977
|
+
const ignoreFile = join69(repoHome(), ".gitleaksignore");
|
|
9978
|
+
if (existsSync50(ignoreFile)) {
|
|
9979
|
+
copyFileSync(ignoreFile, join69(tmpRoot, ".gitleaksignore"));
|
|
9811
9980
|
}
|
|
9812
9981
|
let findings;
|
|
9813
9982
|
try {
|
|
@@ -9824,7 +9993,7 @@ function previewPushLeaks(map, opts = {}) {
|
|
|
9824
9993
|
}
|
|
9825
9994
|
}
|
|
9826
9995
|
|
|
9827
|
-
// src/commands
|
|
9996
|
+
// src/commands/push/steps.ts
|
|
9828
9997
|
init_utils();
|
|
9829
9998
|
async function commitAndPush(st, ts, map, resolution, repo, newManifest, render) {
|
|
9830
9999
|
gitOrFatal(["add", "-A"], "git add", repo);
|
|
@@ -9876,8 +10045,8 @@ function runDryRunPreview(st, map, repo, selection) {
|
|
|
9876
10045
|
if (verdict.recovery !== null) fail(verdict.recovery);
|
|
9877
10046
|
}
|
|
9878
10047
|
|
|
9879
|
-
// src/commands
|
|
9880
|
-
|
|
10048
|
+
// src/commands/push/push.ts
|
|
10049
|
+
init_checks();
|
|
9881
10050
|
init_utils();
|
|
9882
10051
|
init_utils_fs();
|
|
9883
10052
|
function aheadOfUpstream(repo) {
|
|
@@ -9935,7 +10104,7 @@ async function runPushCore(opts = {}) {
|
|
|
9935
10104
|
const scannerVersion = probeGitleaks();
|
|
9936
10105
|
const configHash = computeConfigHash();
|
|
9937
10106
|
const old = readManifest(manifestPath());
|
|
9938
|
-
const mapPath =
|
|
10107
|
+
const mapPath = join70(repo, "path-map.json");
|
|
9939
10108
|
const { map, selection, newManifest } = loadSelectionForPush(
|
|
9940
10109
|
mapPath,
|
|
9941
10110
|
old,
|
|
@@ -9988,7 +10157,7 @@ async function cmdPush(opts = {}) {
|
|
|
9988
10157
|
opts.allowRule
|
|
9989
10158
|
);
|
|
9990
10159
|
const repo = repoHome();
|
|
9991
|
-
if (!
|
|
10160
|
+
if (!existsSync51(repo)) die(`repo not cloned at ${repo}`);
|
|
9992
10161
|
const handle = acquireLock("push");
|
|
9993
10162
|
if (handle === null) process.exit(0);
|
|
9994
10163
|
try {
|
|
@@ -10005,9 +10174,9 @@ async function cmdPush(opts = {}) {
|
|
|
10005
10174
|
}
|
|
10006
10175
|
}
|
|
10007
10176
|
|
|
10008
|
-
// src/commands
|
|
10009
|
-
import { existsSync as
|
|
10010
|
-
import { join as
|
|
10177
|
+
// src/commands/sync.ts
|
|
10178
|
+
import { existsSync as existsSync52 } from "node:fs";
|
|
10179
|
+
import { join as join71 } from "node:path";
|
|
10011
10180
|
init_config();
|
|
10012
10181
|
init_color();
|
|
10013
10182
|
init_utils();
|
|
@@ -10148,8 +10317,8 @@ async function cmdSync(opts = {}) {
|
|
|
10148
10317
|
const dryRun = opts.dryRun === true;
|
|
10149
10318
|
const verbose = opts.verbose === true;
|
|
10150
10319
|
const repo = repoHome();
|
|
10151
|
-
if (!
|
|
10152
|
-
if (!
|
|
10320
|
+
if (!existsSync52(repo)) die(`repo not cloned at ${repo}`);
|
|
10321
|
+
if (!existsSync52(join71(repo, "shared", "settings.base.json"))) {
|
|
10153
10322
|
die("repo not initialized; run 'nomad init' to scaffold");
|
|
10154
10323
|
}
|
|
10155
10324
|
const handle = acquireLock("sync");
|
|
@@ -10172,9 +10341,11 @@ async function cmdSync(opts = {}) {
|
|
|
10172
10341
|
}
|
|
10173
10342
|
}
|
|
10174
10343
|
|
|
10175
|
-
// src/commands
|
|
10176
|
-
import { execFileSync as execFileSync24 } from "node:child_process";
|
|
10344
|
+
// src/commands/update.ts
|
|
10177
10345
|
init_utils();
|
|
10346
|
+
import { execFileSync as execFileSync24 } from "node:child_process";
|
|
10347
|
+
var RELEASE_NOTES_TAG_URL = "https://github.com/funkadelic/claude-nomad/releases/tag";
|
|
10348
|
+
var SEMVER = /^\d+\.\d+\.\d+(?:[-+][\w.-]+)?$/;
|
|
10178
10349
|
function readInstalledVersion(run = execFileSync24) {
|
|
10179
10350
|
const isWin = process.platform === "win32";
|
|
10180
10351
|
try {
|
|
@@ -10186,6 +10357,10 @@ function readInstalledVersion(run = execFileSync24) {
|
|
|
10186
10357
|
return null;
|
|
10187
10358
|
}
|
|
10188
10359
|
}
|
|
10360
|
+
function readOwnVersion(run) {
|
|
10361
|
+
const version = readInstalledVersion(run);
|
|
10362
|
+
return version !== null && SEMVER.test(version) ? version : null;
|
|
10363
|
+
}
|
|
10189
10364
|
function cmdUpdate(currentVersion, run = execFileSync24) {
|
|
10190
10365
|
console.log(`Updating claude-nomad v${currentVersion}...`);
|
|
10191
10366
|
const isWin = process.platform === "win32";
|
|
@@ -10209,26 +10384,27 @@ function cmdUpdate(currentVersion, run = execFileSync24) {
|
|
|
10209
10384
|
${detail}` : "";
|
|
10210
10385
|
throw new NomadFatal(`npm update -g claude-nomad failed: ${e.message}${suffix}`);
|
|
10211
10386
|
}
|
|
10212
|
-
const version =
|
|
10387
|
+
const version = readOwnVersion(run);
|
|
10213
10388
|
if (!version) {
|
|
10214
10389
|
console.log('Update complete. Run "nomad --version" to confirm the new version.');
|
|
10215
|
-
|
|
10216
|
-
console.log(`claude-nomad is already at the latest version (v${version}).`);
|
|
10217
|
-
} else {
|
|
10218
|
-
console.log(`claude-nomad is now at v${version}`);
|
|
10390
|
+
return;
|
|
10219
10391
|
}
|
|
10392
|
+
console.log(
|
|
10393
|
+
version === currentVersion ? `claude-nomad is already at the latest version (v${version}).` : `claude-nomad is now at v${version}`
|
|
10394
|
+
);
|
|
10395
|
+
console.log(`Release notes: ${RELEASE_NOTES_TAG_URL}/v${version}`);
|
|
10220
10396
|
}
|
|
10221
10397
|
|
|
10222
10398
|
// src/nomad.ts
|
|
10223
10399
|
init_config();
|
|
10224
10400
|
|
|
10225
|
-
// src/crash-report.write.ts
|
|
10401
|
+
// src/core/crash-report.write.ts
|
|
10226
10402
|
init_config();
|
|
10227
10403
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
10228
10404
|
import { mkdirSync as mkdirSync16, readdirSync as readdirSync21, statSync as statSync14, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "node:fs";
|
|
10229
|
-
import { join as
|
|
10405
|
+
import { join as join73 } from "node:path";
|
|
10230
10406
|
|
|
10231
|
-
// src/crash-report.ts
|
|
10407
|
+
// src/core/crash-report.ts
|
|
10232
10408
|
var CRASH_MAX_STACK_LINES = 50;
|
|
10233
10409
|
var CRASH_MAX_ARGV = 32;
|
|
10234
10410
|
var CRASH_MAX_ARGV_TOKEN_LENGTH = 200;
|
|
@@ -10308,18 +10484,18 @@ function buildCrashReport(input) {
|
|
|
10308
10484
|
return truncateToBytes(scrubbed, CRASH_MAX_REPORT_BYTES);
|
|
10309
10485
|
}
|
|
10310
10486
|
|
|
10311
|
-
// src/crash-report.redact.ts
|
|
10487
|
+
// src/core/crash-report.redact.ts
|
|
10312
10488
|
import { mkdtempSync as mkdtempSync3, rmSync as rmSync21, writeFileSync as writeFileSync10 } from "node:fs";
|
|
10313
10489
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
10314
|
-
import { join as
|
|
10315
|
-
|
|
10490
|
+
import { join as join72 } from "node:path";
|
|
10491
|
+
init_gitleaks_scan();
|
|
10316
10492
|
var CRASH_SCAN_TIMEOUT_MS = 3e3;
|
|
10317
10493
|
var SCAN_UNAVAILABLE_ADVISORY = "\n\n[gitleaks value-based scan unavailable; only structural redaction applied. Review before sharing this file publicly.]\n";
|
|
10318
10494
|
function redactWithGitleaks(text, scan = scanFile) {
|
|
10319
10495
|
let dir;
|
|
10320
10496
|
try {
|
|
10321
|
-
dir = mkdtempSync3(
|
|
10322
|
-
const tmp =
|
|
10497
|
+
dir = mkdtempSync3(join72(tmpdir2(), "nomad-crash-scan-"));
|
|
10498
|
+
const tmp = join72(dir, "crash.txt");
|
|
10323
10499
|
writeFileSync10(tmp, text, { mode: 384 });
|
|
10324
10500
|
const findings = scan(tmp, false, CRASH_SCAN_TIMEOUT_MS);
|
|
10325
10501
|
if (findings === null) return text + SCAN_UNAVAILABLE_ADVISORY;
|
|
@@ -10336,7 +10512,7 @@ function redactWithGitleaks(text, scan = scanFile) {
|
|
|
10336
10512
|
}
|
|
10337
10513
|
}
|
|
10338
10514
|
|
|
10339
|
-
// src/crash-report.write.ts
|
|
10515
|
+
// src/core/crash-report.write.ts
|
|
10340
10516
|
init_utils_fs();
|
|
10341
10517
|
init_utils();
|
|
10342
10518
|
var CRASH_RETENTION_KEEP = 20;
|
|
@@ -10344,7 +10520,7 @@ function listCrashFiles(dir = crashDir()) {
|
|
|
10344
10520
|
try {
|
|
10345
10521
|
return readdirSync21(dir).flatMap((name) => {
|
|
10346
10522
|
try {
|
|
10347
|
-
return [{ name, mtimeMs: statSync14(
|
|
10523
|
+
return [{ name, mtimeMs: statSync14(join73(dir, name)).mtimeMs }];
|
|
10348
10524
|
} catch {
|
|
10349
10525
|
return [];
|
|
10350
10526
|
}
|
|
@@ -10358,7 +10534,7 @@ function pruneCrashDir(dir, keep = CRASH_RETENTION_KEEP) {
|
|
|
10358
10534
|
const targets = prunableByCount(files, keep);
|
|
10359
10535
|
for (const name of targets) {
|
|
10360
10536
|
try {
|
|
10361
|
-
unlinkSync2(
|
|
10537
|
+
unlinkSync2(join73(dir, name));
|
|
10362
10538
|
} catch {
|
|
10363
10539
|
}
|
|
10364
10540
|
}
|
|
@@ -10366,7 +10542,7 @@ function pruneCrashDir(dir, keep = CRASH_RETENTION_KEEP) {
|
|
|
10366
10542
|
function writeCrashReport(text, dir = crashDir()) {
|
|
10367
10543
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
10368
10544
|
const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes5(4).toString("hex")}`;
|
|
10369
|
-
const path =
|
|
10545
|
+
const path = join73(dir, `crash-${stamp}.txt`);
|
|
10370
10546
|
writeFileSync11(path, text, { mode: 384 });
|
|
10371
10547
|
pruneCrashDir(dir);
|
|
10372
10548
|
return path;
|
|
@@ -10396,20 +10572,20 @@ function handleCrash(err, argv, opts) {
|
|
|
10396
10572
|
}
|
|
10397
10573
|
}
|
|
10398
10574
|
|
|
10399
|
-
// src/diff.ts
|
|
10575
|
+
// src/commands/diff.ts
|
|
10400
10576
|
init_config();
|
|
10401
|
-
import { existsSync as
|
|
10402
|
-
import { join as
|
|
10577
|
+
import { existsSync as existsSync53 } from "node:fs";
|
|
10578
|
+
import { join as join74 } from "node:path";
|
|
10403
10579
|
init_utils();
|
|
10404
10580
|
init_utils_fs();
|
|
10405
10581
|
init_utils_json();
|
|
10406
10582
|
function cmdDiff() {
|
|
10407
10583
|
try {
|
|
10408
10584
|
const repo = repoHome();
|
|
10409
|
-
if (!
|
|
10585
|
+
if (!existsSync53(repo)) die(`repo not cloned at ${repo}`);
|
|
10410
10586
|
const ts = freshBackupTs(backupBase());
|
|
10411
|
-
const mapPath =
|
|
10412
|
-
const map =
|
|
10587
|
+
const mapPath = join74(repo, "path-map.json");
|
|
10588
|
+
const map = existsSync53(mapPath) ? readPathMap(mapPath) : { projects: {} };
|
|
10413
10589
|
divergenceCheckExtras(ts);
|
|
10414
10590
|
computePreview(ts, map, "diff");
|
|
10415
10591
|
} catch (err) {
|
|
@@ -10422,12 +10598,12 @@ function cmdDiff() {
|
|
|
10422
10598
|
}
|
|
10423
10599
|
}
|
|
10424
10600
|
|
|
10425
|
-
// src/init.ts
|
|
10601
|
+
// src/commands/init/init.ts
|
|
10426
10602
|
init_config();
|
|
10427
|
-
import { existsSync as
|
|
10428
|
-
import { join as
|
|
10603
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync17, writeFileSync as writeFileSync12 } from "node:fs";
|
|
10604
|
+
import { join as join76 } from "node:path";
|
|
10429
10605
|
|
|
10430
|
-
// src/init
|
|
10606
|
+
// src/commands/init/gh-onboard.ts
|
|
10431
10607
|
init_config();
|
|
10432
10608
|
import { execFileSync as execFileSync25 } from "node:child_process";
|
|
10433
10609
|
init_utils();
|
|
@@ -10502,44 +10678,44 @@ function ensureOriginRepo(repoName, run = execFileSync25) {
|
|
|
10502
10678
|
log(`created private repo ${owner}/${repoName} and wired origin`);
|
|
10503
10679
|
}
|
|
10504
10680
|
|
|
10505
|
-
// src/init
|
|
10681
|
+
// src/commands/init/snapshot.ts
|
|
10506
10682
|
init_config();
|
|
10507
10683
|
init_utils();
|
|
10508
10684
|
init_utils_fs();
|
|
10509
10685
|
init_utils_json();
|
|
10510
|
-
import { copyFileSync as copyFileSync2, cpSync as cpSync9, existsSync as
|
|
10511
|
-
import { join as
|
|
10686
|
+
import { copyFileSync as copyFileSync2, cpSync as cpSync9, existsSync as existsSync54, rmSync as rmSync22, statSync as statSync15 } from "node:fs";
|
|
10687
|
+
import { join as join75 } from "node:path";
|
|
10512
10688
|
function snapshotIntoShared(map) {
|
|
10513
10689
|
const repo = repoHome();
|
|
10514
10690
|
const claude = claudeHome();
|
|
10515
10691
|
for (const name of allSharedLinks(map)) {
|
|
10516
|
-
const src =
|
|
10517
|
-
if (!
|
|
10518
|
-
const dst =
|
|
10692
|
+
const src = join75(claude, name);
|
|
10693
|
+
if (!existsSync54(src)) continue;
|
|
10694
|
+
const dst = join75(repo, "shared", name);
|
|
10519
10695
|
if (statSync15(src).isDirectory()) {
|
|
10520
|
-
const gk =
|
|
10521
|
-
if (
|
|
10696
|
+
const gk = join75(dst, ".gitkeep");
|
|
10697
|
+
if (existsSync54(gk)) rmSync22(gk);
|
|
10522
10698
|
cpSync9(src, dst, { recursive: true, force: false, errorOnExist: true });
|
|
10523
10699
|
} else {
|
|
10524
10700
|
copyFileSync2(src, dst);
|
|
10525
10701
|
}
|
|
10526
10702
|
log(`snapshotted shared/${name} from ${src}`);
|
|
10527
10703
|
}
|
|
10528
|
-
const userSettings =
|
|
10529
|
-
if (
|
|
10704
|
+
const userSettings = join75(claude, "settings.json");
|
|
10705
|
+
if (existsSync54(userSettings)) {
|
|
10530
10706
|
let parsed;
|
|
10531
10707
|
try {
|
|
10532
10708
|
parsed = readJson(userSettings);
|
|
10533
10709
|
} catch (err) {
|
|
10534
10710
|
return die(`malformed ${userSettings}: ${err.message}`);
|
|
10535
10711
|
}
|
|
10536
|
-
const hostFile =
|
|
10712
|
+
const hostFile = join75(repo, "hosts", `${HOST}.json`);
|
|
10537
10713
|
writeJsonAtomic(hostFile, parsed);
|
|
10538
10714
|
log(`snapshotted hosts/${HOST}.json from ${userSettings}`);
|
|
10539
10715
|
}
|
|
10540
10716
|
}
|
|
10541
10717
|
|
|
10542
|
-
// src/init.ts
|
|
10718
|
+
// src/commands/init/init.ts
|
|
10543
10719
|
init_utils();
|
|
10544
10720
|
init_utils_fs();
|
|
10545
10721
|
var SHARED_CLAUDE_MD = "<!-- claude-nomad shared CLAUDE.md; symlinked into ~/.claude/CLAUDE.md by nomad pull -->\n";
|
|
@@ -10547,14 +10723,14 @@ var GITATTRIBUTES = "# nomad: sync content is byte-managed, disable all line-end
|
|
|
10547
10723
|
var SHARED_KEEP_DIRS = ["agents", "skills", "commands", "rules", "hooks"];
|
|
10548
10724
|
function preflightConflict(repoHome2) {
|
|
10549
10725
|
const candidates = [
|
|
10550
|
-
|
|
10551
|
-
|
|
10552
|
-
|
|
10553
|
-
|
|
10554
|
-
|
|
10726
|
+
join76(repoHome2, "shared", "settings.base.json"),
|
|
10727
|
+
join76(repoHome2, "shared", "CLAUDE.md"),
|
|
10728
|
+
join76(repoHome2, "path-map.json"),
|
|
10729
|
+
join76(repoHome2, "hosts"),
|
|
10730
|
+
join76(repoHome2, "shared")
|
|
10555
10731
|
];
|
|
10556
10732
|
for (const c of candidates) {
|
|
10557
|
-
if (
|
|
10733
|
+
if (existsSync55(c)) return c;
|
|
10558
10734
|
}
|
|
10559
10735
|
return null;
|
|
10560
10736
|
}
|
|
@@ -10572,27 +10748,27 @@ function cmdInit(opts = {}) {
|
|
|
10572
10748
|
die(`already initialized; refusing to clobber ${conflict}`);
|
|
10573
10749
|
}
|
|
10574
10750
|
ensureOriginRepo(opts.repoName ?? DEFAULT_REPO_NAME, opts.run);
|
|
10575
|
-
mkdirSync17(
|
|
10576
|
-
mkdirSync17(
|
|
10751
|
+
mkdirSync17(join76(repo, "shared"), { recursive: true });
|
|
10752
|
+
mkdirSync17(join76(repo, "hosts"), { recursive: true });
|
|
10577
10753
|
for (const name of SHARED_KEEP_DIRS) {
|
|
10578
|
-
mkdirSync17(
|
|
10754
|
+
mkdirSync17(join76(repo, "shared", name), { recursive: true });
|
|
10579
10755
|
}
|
|
10580
|
-
const userClaudeMd =
|
|
10581
|
-
if (!snapshot || !
|
|
10582
|
-
writeFileSync12(
|
|
10756
|
+
const userClaudeMd = join76(claude, "CLAUDE.md");
|
|
10757
|
+
if (!snapshot || !existsSync55(userClaudeMd)) {
|
|
10758
|
+
writeFileSync12(join76(repo, "shared", "CLAUDE.md"), SHARED_CLAUDE_MD);
|
|
10583
10759
|
item("created shared/CLAUDE.md");
|
|
10584
10760
|
}
|
|
10585
10761
|
for (const name of SHARED_KEEP_DIRS) {
|
|
10586
|
-
writeFileSync12(
|
|
10762
|
+
writeFileSync12(join76(repo, "shared", name, ".gitkeep"), "");
|
|
10587
10763
|
item(`created shared/${name}/.gitkeep`);
|
|
10588
10764
|
}
|
|
10589
|
-
writeFileSync12(
|
|
10765
|
+
writeFileSync12(join76(repo, "hosts", ".gitkeep"), "");
|
|
10590
10766
|
item("created hosts/.gitkeep");
|
|
10591
|
-
writeJsonAtomic(
|
|
10767
|
+
writeJsonAtomic(join76(repo, "shared", "settings.base.json"), {});
|
|
10592
10768
|
item("created shared/settings.base.json");
|
|
10593
|
-
writeJsonAtomic(
|
|
10769
|
+
writeJsonAtomic(join76(repo, "path-map.json"), { projects: {} });
|
|
10594
10770
|
item("created path-map.json");
|
|
10595
|
-
writeFileSync12(
|
|
10771
|
+
writeFileSync12(join76(repo, ".gitattributes"), GITATTRIBUTES);
|
|
10596
10772
|
item("created .gitattributes");
|
|
10597
10773
|
if (snapshot) {
|
|
10598
10774
|
snapshotIntoShared({ projects: {} });
|
|
@@ -10655,14 +10831,14 @@ function maybeDisableRepoActions(repoHome2, run) {
|
|
|
10655
10831
|
}
|
|
10656
10832
|
}
|
|
10657
10833
|
|
|
10658
|
-
// src/init
|
|
10834
|
+
// src/commands/init/prompt.ts
|
|
10659
10835
|
init_config();
|
|
10660
10836
|
init_utils();
|
|
10661
|
-
import { existsSync as
|
|
10662
|
-
import { join as
|
|
10837
|
+
import { existsSync as existsSync56, readdirSync as readdirSync22, statSync as statSync16 } from "node:fs";
|
|
10838
|
+
import { join as join77 } from "node:path";
|
|
10663
10839
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
10664
10840
|
function nonEmptyExists(path) {
|
|
10665
|
-
if (!
|
|
10841
|
+
if (!existsSync56(path)) return false;
|
|
10666
10842
|
try {
|
|
10667
10843
|
if (statSync16(path).isDirectory()) return readdirSync22(path).length > 0;
|
|
10668
10844
|
return true;
|
|
@@ -10671,8 +10847,8 @@ function nonEmptyExists(path) {
|
|
|
10671
10847
|
}
|
|
10672
10848
|
}
|
|
10673
10849
|
function hasExistingClaudeConfig(claudeHome2) {
|
|
10674
|
-
if (
|
|
10675
|
-
return SHARED_LINKS.some((name) => nonEmptyExists(
|
|
10850
|
+
if (existsSync56(join77(claudeHome2, "settings.json"))) return true;
|
|
10851
|
+
return SHARED_LINKS.some((name) => nonEmptyExists(join77(claudeHome2, name)));
|
|
10676
10852
|
}
|
|
10677
10853
|
async function confirmSnapshotDefault(claudeHome2) {
|
|
10678
10854
|
if (process.stdin.isTTY !== true || process.stdout.isTTY !== true) {
|
|
@@ -10696,7 +10872,7 @@ async function resolveSnapshotChoice(flagSnapshot, claudeHome2, confirm = confir
|
|
|
10696
10872
|
return confirm(claudeHome2);
|
|
10697
10873
|
}
|
|
10698
10874
|
|
|
10699
|
-
// src/
|
|
10875
|
+
// src/cli/dispatch.helpers.ts
|
|
10700
10876
|
var REJECT = { ok: false, advance: 0 };
|
|
10701
10877
|
function applyBool(seen, set) {
|
|
10702
10878
|
if (seen) return REJECT;
|
|
@@ -10709,7 +10885,7 @@ function extractFlagValue(argv, i) {
|
|
|
10709
10885
|
return val;
|
|
10710
10886
|
}
|
|
10711
10887
|
|
|
10712
|
-
// src/
|
|
10888
|
+
// src/cli/dispatch.clean.ts
|
|
10713
10889
|
function applyOlderThan(argv, i, st) {
|
|
10714
10890
|
if (st.olderThan !== void 0) return REJECT;
|
|
10715
10891
|
const val = extractFlagValue(argv, i);
|
|
@@ -10756,7 +10932,7 @@ function parseCleanArgs(argv) {
|
|
|
10756
10932
|
return { dryRun: st.dryRun, olderThan: st.olderThan, keep: st.keep };
|
|
10757
10933
|
}
|
|
10758
10934
|
|
|
10759
|
-
// src/
|
|
10935
|
+
// src/cli/dispatch.capture-settings.ts
|
|
10760
10936
|
function parseCaptureSettingsArgs(argv) {
|
|
10761
10937
|
let host = false;
|
|
10762
10938
|
let dryRun = false;
|
|
@@ -10781,7 +10957,7 @@ function parseCaptureSettingsArgs(argv) {
|
|
|
10781
10957
|
return { host, dryRun, yes };
|
|
10782
10958
|
}
|
|
10783
10959
|
|
|
10784
|
-
// src/
|
|
10960
|
+
// src/cli/dispatch.eject.ts
|
|
10785
10961
|
function parseEjectArgs(argv) {
|
|
10786
10962
|
let dryRun = false;
|
|
10787
10963
|
let i = 3;
|
|
@@ -10798,7 +10974,7 @@ function parseEjectArgs(argv) {
|
|
|
10798
10974
|
return { dryRun };
|
|
10799
10975
|
}
|
|
10800
10976
|
|
|
10801
|
-
// src/
|
|
10977
|
+
// src/cli/dispatch.ts
|
|
10802
10978
|
function applyInitToken(argv, i, st) {
|
|
10803
10979
|
const token = argv[i];
|
|
10804
10980
|
if (token === "--snapshot") {
|
|
@@ -10871,7 +11047,7 @@ function parseRedactArgs(argv) {
|
|
|
10871
11047
|
return { id, rule, dryRun };
|
|
10872
11048
|
}
|
|
10873
11049
|
|
|
10874
|
-
// src/
|
|
11050
|
+
// src/cli/dispatch.allow.ts
|
|
10875
11051
|
function parseAllowArgs(argv) {
|
|
10876
11052
|
const positionals = argv.slice(3);
|
|
10877
11053
|
if (positionals.length === 0) return null;
|
|
@@ -10881,7 +11057,7 @@ function parseAllowArgs(argv) {
|
|
|
10881
11057
|
return positionals;
|
|
10882
11058
|
}
|
|
10883
11059
|
|
|
10884
|
-
// src/
|
|
11060
|
+
// src/cli/dispatch.pull.ts
|
|
10885
11061
|
function parsePullArgs(argv) {
|
|
10886
11062
|
let dryRun = false;
|
|
10887
11063
|
let forceRemote = false;
|
|
@@ -10903,7 +11079,7 @@ function parsePullArgs(argv) {
|
|
|
10903
11079
|
return { dryRun, forceRemote };
|
|
10904
11080
|
}
|
|
10905
11081
|
|
|
10906
|
-
// src/
|
|
11082
|
+
// src/cli/dispatch.push.ts
|
|
10907
11083
|
var RULE_ID_RE = /^\w[\w-]*$/;
|
|
10908
11084
|
function applyAllow(argv, i, st) {
|
|
10909
11085
|
if (st.allowRule !== void 0) return REJECT;
|
|
@@ -10956,7 +11132,7 @@ function parsePushArgs(argv) {
|
|
|
10956
11132
|
};
|
|
10957
11133
|
}
|
|
10958
11134
|
|
|
10959
|
-
// src/
|
|
11135
|
+
// src/cli/dispatch.sync.ts
|
|
10960
11136
|
function parseSyncArgs(argv) {
|
|
10961
11137
|
let dryRun = false;
|
|
10962
11138
|
let verbose = false;
|
|
@@ -10979,7 +11155,7 @@ function parseSyncArgs(argv) {
|
|
|
10979
11155
|
// package.json
|
|
10980
11156
|
var package_default = {
|
|
10981
11157
|
name: "claude-nomad",
|
|
10982
|
-
version: "0.
|
|
11158
|
+
version: "0.69.0",
|
|
10983
11159
|
type: "module",
|
|
10984
11160
|
description: "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
|
|
10985
11161
|
keywords: [
|
|
@@ -11046,7 +11222,8 @@ var package_default = {
|
|
|
11046
11222
|
overrides: {
|
|
11047
11223
|
"@conventional-changelog/git-client": {
|
|
11048
11224
|
"conventional-commits-parser": "^7.0.0"
|
|
11049
|
-
}
|
|
11225
|
+
},
|
|
11226
|
+
"smol-toml": "^1.7.1"
|
|
11050
11227
|
},
|
|
11051
11228
|
devDependencies: {
|
|
11052
11229
|
"@commitlint/cli": "^21.0.1",
|
|
@@ -11055,7 +11232,7 @@ var package_default = {
|
|
|
11055
11232
|
"@stryker-mutator/core": "10.0.0",
|
|
11056
11233
|
"@stryker-mutator/vitest-runner": "10.0.0",
|
|
11057
11234
|
"@types/node": "^22.0.0",
|
|
11058
|
-
"@vitest/coverage-v8": "^
|
|
11235
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
11059
11236
|
"conventional-changelog-conventionalcommits": "^10.2.1",
|
|
11060
11237
|
diff: "^9.0.0",
|
|
11061
11238
|
esbuild: "^0.28.0",
|
|
@@ -11071,11 +11248,11 @@ var package_default = {
|
|
|
11071
11248
|
prettier: "^3.8.3",
|
|
11072
11249
|
typescript: "^6.0.3",
|
|
11073
11250
|
"typescript-eslint": "^8.59.4",
|
|
11074
|
-
vitest: "^
|
|
11251
|
+
vitest: "^5.0.0"
|
|
11075
11252
|
}
|
|
11076
11253
|
};
|
|
11077
11254
|
|
|
11078
|
-
// src/
|
|
11255
|
+
// src/cli/help.ts
|
|
11079
11256
|
var DESC_COL = 26;
|
|
11080
11257
|
var row = (label, desc) => label.padEnd(DESC_COL) + desc;
|
|
11081
11258
|
var cont = (text) => " ".repeat(DESC_COL) + text;
|
|
@@ -11223,19 +11400,19 @@ var DEFAULT_HELP = [
|
|
|
11223
11400
|
"every pull)."
|
|
11224
11401
|
].join("\n");
|
|
11225
11402
|
|
|
11226
|
-
// src/resume.ts
|
|
11403
|
+
// src/sync/resume.ts
|
|
11227
11404
|
init_config();
|
|
11228
11405
|
init_utils();
|
|
11229
11406
|
init_utils_json();
|
|
11230
|
-
import { existsSync as
|
|
11231
|
-
import { join as
|
|
11407
|
+
import { existsSync as existsSync57, readFileSync as readFileSync21, readdirSync as readdirSync23 } from "node:fs";
|
|
11408
|
+
import { join as join78 } from "node:path";
|
|
11232
11409
|
function resumeCmd(sessionId) {
|
|
11233
11410
|
if (!/^[A-Za-z0-9_-]+$/.test(sessionId) || sessionId.length > 128) {
|
|
11234
11411
|
fail(`invalid session id: ${sessionId}`);
|
|
11235
11412
|
process.exit(1);
|
|
11236
11413
|
}
|
|
11237
|
-
const projectsRoot =
|
|
11238
|
-
if (!
|
|
11414
|
+
const projectsRoot = join78(claudeHome(), "projects");
|
|
11415
|
+
if (!existsSync57(projectsRoot)) {
|
|
11239
11416
|
fail(`${projectsRoot} does not exist`);
|
|
11240
11417
|
process.exit(1);
|
|
11241
11418
|
}
|
|
@@ -11249,8 +11426,8 @@ function resumeCmd(sessionId) {
|
|
|
11249
11426
|
fail(`no cwd field found in ${jsonlPath}`);
|
|
11250
11427
|
process.exit(1);
|
|
11251
11428
|
}
|
|
11252
|
-
const mapPath =
|
|
11253
|
-
if (!
|
|
11429
|
+
const mapPath = join78(repoHome(), "path-map.json");
|
|
11430
|
+
if (!existsSync57(mapPath)) {
|
|
11254
11431
|
fail("path-map.json missing");
|
|
11255
11432
|
process.exit(1);
|
|
11256
11433
|
}
|
|
@@ -11273,8 +11450,8 @@ function resumeCmd(sessionId) {
|
|
|
11273
11450
|
}
|
|
11274
11451
|
function findTranscriptPath(projectsRoot, sessionId) {
|
|
11275
11452
|
for (const dir of readdirSync23(projectsRoot)) {
|
|
11276
|
-
const candidate =
|
|
11277
|
-
if (
|
|
11453
|
+
const candidate = join78(projectsRoot, dir, `${sessionId}.jsonl`);
|
|
11454
|
+
if (existsSync57(candidate)) return candidate;
|
|
11278
11455
|
}
|
|
11279
11456
|
return null;
|
|
11280
11457
|
}
|
|
@@ -11307,7 +11484,7 @@ function shQuote(s) {
|
|
|
11307
11484
|
return `'${escaped}'`;
|
|
11308
11485
|
}
|
|
11309
11486
|
|
|
11310
|
-
// src/user-abort.ts
|
|
11487
|
+
// src/core/user-abort.ts
|
|
11311
11488
|
var ABORT_NAMES = /* @__PURE__ */ new Set(["AbortError", "ExitPromptError"]);
|
|
11312
11489
|
var ABORT_CODE = "ABORT_ERR";
|
|
11313
11490
|
function isUserAbort(err) {
|