codebyplan 1.13.56 → 1.13.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +930 -575
- package/package.json +1 -1
- package/templates/hooks/cbp-statusline.mjs +25 -18
- package/templates/hooks/cbp-statusline.py +13 -0
- package/templates/hooks/cbp-statusline.sh +12 -0
package/dist/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ var VERSION, PACKAGE_NAME;
|
|
|
39
39
|
var init_version = __esm({
|
|
40
40
|
"src/lib/version.ts"() {
|
|
41
41
|
"use strict";
|
|
42
|
-
VERSION = "1.13.
|
|
42
|
+
VERSION = "1.13.57";
|
|
43
43
|
PACKAGE_NAME = "codebyplan";
|
|
44
44
|
}
|
|
45
45
|
});
|
|
@@ -113,8 +113,8 @@ async function readLocalConfig(projectPath, onMigrationNotice) {
|
|
|
113
113
|
}
|
|
114
114
|
async function writeLocalConfig(projectPath, config) {
|
|
115
115
|
const content = { device_id: config.device_id };
|
|
116
|
-
const
|
|
117
|
-
const dirPath = dirname(
|
|
116
|
+
const path22 = localConfigPath(projectPath);
|
|
117
|
+
const dirPath = dirname(path22);
|
|
118
118
|
let phase = "stat config directory";
|
|
119
119
|
try {
|
|
120
120
|
try {
|
|
@@ -134,7 +134,7 @@ async function writeLocalConfig(projectPath, config) {
|
|
|
134
134
|
phase = "create config directory";
|
|
135
135
|
await mkdir(dirPath, { recursive: true });
|
|
136
136
|
phase = "write local config";
|
|
137
|
-
await writeFile(
|
|
137
|
+
await writeFile(path22, JSON.stringify(content, null, 2) + "\n", "utf-8");
|
|
138
138
|
} catch (err) {
|
|
139
139
|
const code = err.code;
|
|
140
140
|
if (code === "LEGACY_FILE_BLOCKS_DIR") {
|
|
@@ -652,8 +652,8 @@ var init_gitignore_block = __esm({
|
|
|
652
652
|
// src/lib/worktree.ts
|
|
653
653
|
import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile6 } from "node:fs/promises";
|
|
654
654
|
import { join as join6 } from "node:path";
|
|
655
|
-
function defaultExists(
|
|
656
|
-
return readFile6(
|
|
655
|
+
function defaultExists(path22) {
|
|
656
|
+
return readFile6(path22, "utf-8").then(() => true).catch(() => false);
|
|
657
657
|
}
|
|
658
658
|
async function writeRepoJson(codebyplanDir, selectedRepo, deps) {
|
|
659
659
|
const repoJson = {
|
|
@@ -774,9 +774,9 @@ var init_worktree = __esm({
|
|
|
774
774
|
init_local_config();
|
|
775
775
|
init_gitignore_block();
|
|
776
776
|
defaultFsDeps = {
|
|
777
|
-
mkdir: (
|
|
778
|
-
writeFile: (
|
|
779
|
-
readFile: (
|
|
777
|
+
mkdir: (path22, opts) => mkdir3(path22, opts).then(() => void 0),
|
|
778
|
+
writeFile: (path22, data, encoding) => writeFile4(path22, data, encoding),
|
|
779
|
+
readFile: (path22, encoding) => readFile6(path22, encoding),
|
|
780
780
|
exists: defaultExists
|
|
781
781
|
};
|
|
782
782
|
}
|
|
@@ -844,12 +844,12 @@ async function readFallback(filename) {
|
|
|
844
844
|
}
|
|
845
845
|
}
|
|
846
846
|
async function writeFallback(filename, data) {
|
|
847
|
-
const
|
|
848
|
-
await mkdir4(dirname2(
|
|
849
|
-
await writeFile5(
|
|
847
|
+
const path22 = fallbackFile(filename);
|
|
848
|
+
await mkdir4(dirname2(path22), { recursive: true });
|
|
849
|
+
await writeFile5(path22, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
850
850
|
if (platform() !== "win32") {
|
|
851
851
|
try {
|
|
852
|
-
await chmod(
|
|
852
|
+
await chmod(path22, 384);
|
|
853
853
|
} catch {
|
|
854
854
|
}
|
|
855
855
|
}
|
|
@@ -1143,8 +1143,8 @@ async function validateConnectivity() {
|
|
|
1143
1143
|
);
|
|
1144
1144
|
}
|
|
1145
1145
|
}
|
|
1146
|
-
function buildUrl(
|
|
1147
|
-
const url = new URL(`${baseUrl()}/api${
|
|
1146
|
+
function buildUrl(path22, params) {
|
|
1147
|
+
const url = new URL(`${baseUrl()}/api${path22}`);
|
|
1148
1148
|
if (params) {
|
|
1149
1149
|
for (const [key, value] of Object.entries(params)) {
|
|
1150
1150
|
if (value !== void 0) {
|
|
@@ -1163,8 +1163,8 @@ function isRetryable(err) {
|
|
|
1163
1163
|
function delay(ms) {
|
|
1164
1164
|
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
1165
1165
|
}
|
|
1166
|
-
async function request(method,
|
|
1167
|
-
const url = buildUrl(
|
|
1166
|
+
async function request(method, path22, options) {
|
|
1167
|
+
const url = buildUrl(path22, options?.params);
|
|
1168
1168
|
const auth = await getAuthHeaders();
|
|
1169
1169
|
let lastError;
|
|
1170
1170
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
@@ -1184,7 +1184,7 @@ async function request(method, path21, options) {
|
|
|
1184
1184
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
1185
1185
|
});
|
|
1186
1186
|
if (!res.ok) {
|
|
1187
|
-
let message = `API ${method} ${
|
|
1187
|
+
let message = `API ${method} ${path22} failed with status ${res.status}`;
|
|
1188
1188
|
let code;
|
|
1189
1189
|
try {
|
|
1190
1190
|
const body = await res.json();
|
|
@@ -1218,20 +1218,20 @@ async function request(method, path21, options) {
|
|
|
1218
1218
|
}
|
|
1219
1219
|
throw lastError;
|
|
1220
1220
|
}
|
|
1221
|
-
async function apiGet(
|
|
1222
|
-
return request("GET",
|
|
1221
|
+
async function apiGet(path22, params) {
|
|
1222
|
+
return request("GET", path22, { params });
|
|
1223
1223
|
}
|
|
1224
|
-
async function apiPost(
|
|
1225
|
-
return request("POST",
|
|
1224
|
+
async function apiPost(path22, body) {
|
|
1225
|
+
return request("POST", path22, { body });
|
|
1226
1226
|
}
|
|
1227
|
-
async function apiPut(
|
|
1228
|
-
return request("PUT",
|
|
1227
|
+
async function apiPut(path22, body) {
|
|
1228
|
+
return request("PUT", path22, { body });
|
|
1229
1229
|
}
|
|
1230
|
-
async function apiPatch(
|
|
1231
|
-
return request("PATCH",
|
|
1230
|
+
async function apiPatch(path22, body) {
|
|
1231
|
+
return request("PATCH", path22, { body });
|
|
1232
1232
|
}
|
|
1233
|
-
async function apiDelete(
|
|
1234
|
-
await request("DELETE",
|
|
1233
|
+
async function apiDelete(path22, params) {
|
|
1234
|
+
await request("DELETE", path22, { params });
|
|
1235
1235
|
}
|
|
1236
1236
|
async function callMcpTool(toolName, params) {
|
|
1237
1237
|
const url = mcpEndpoint();
|
|
@@ -2229,9 +2229,229 @@ var init_templates_dir = __esm({
|
|
|
2229
2229
|
}
|
|
2230
2230
|
});
|
|
2231
2231
|
|
|
2232
|
+
// src/lib/gitignore-detect.ts
|
|
2233
|
+
import * as path5 from "node:path";
|
|
2234
|
+
import { readFile as readFile9, writeFile as writeFile7 } from "node:fs/promises";
|
|
2235
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
2236
|
+
function defaultGitCheckIgnore(projectDir) {
|
|
2237
|
+
const result = spawnSync3(
|
|
2238
|
+
"git",
|
|
2239
|
+
["check-ignore", "-v", "--", ".claude/settings.json"],
|
|
2240
|
+
{
|
|
2241
|
+
cwd: projectDir,
|
|
2242
|
+
encoding: "utf-8",
|
|
2243
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2244
|
+
}
|
|
2245
|
+
);
|
|
2246
|
+
if (result.error) {
|
|
2247
|
+
return { exitCode: 128, stdout: "", stderr: "" };
|
|
2248
|
+
}
|
|
2249
|
+
return {
|
|
2250
|
+
exitCode: result.status,
|
|
2251
|
+
stdout: (result.stdout ?? "").toString(),
|
|
2252
|
+
stderr: (result.stderr ?? "").toString()
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
function defaultGitLsFiles(projectDir) {
|
|
2256
|
+
const result = spawnSync3(
|
|
2257
|
+
"git",
|
|
2258
|
+
["ls-files", "--error-unmatch", "--", ".claude/settings.json"],
|
|
2259
|
+
{
|
|
2260
|
+
cwd: projectDir,
|
|
2261
|
+
encoding: "utf-8",
|
|
2262
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2263
|
+
}
|
|
2264
|
+
);
|
|
2265
|
+
if (result.error) {
|
|
2266
|
+
return 128;
|
|
2267
|
+
}
|
|
2268
|
+
return result.status ?? 1;
|
|
2269
|
+
}
|
|
2270
|
+
async function defaultPromptRemoveIgnore(displayLine, opts) {
|
|
2271
|
+
if (opts.yes) {
|
|
2272
|
+
return true;
|
|
2273
|
+
}
|
|
2274
|
+
const readline2 = await import("node:readline");
|
|
2275
|
+
if (!process.stdin.isTTY) {
|
|
2276
|
+
throw new Error(
|
|
2277
|
+
"@codebyplan/claude: interactive prompts require a TTY. Re-run with --yes to accept defaults."
|
|
2278
|
+
);
|
|
2279
|
+
}
|
|
2280
|
+
const rl = readline2.createInterface({
|
|
2281
|
+
input: process.stdin,
|
|
2282
|
+
output: process.stdout
|
|
2283
|
+
});
|
|
2284
|
+
try {
|
|
2285
|
+
while (true) {
|
|
2286
|
+
const answer = await new Promise((resolve16) => {
|
|
2287
|
+
rl.question(
|
|
2288
|
+
`The following gitignore rule matches .claude/settings.json:
|
|
2289
|
+
${displayLine}
|
|
2290
|
+
Remove this line?
|
|
2291
|
+
[r] remove [k] keep
|
|
2292
|
+
> `,
|
|
2293
|
+
(input) => {
|
|
2294
|
+
resolve16(input.trim().toLowerCase());
|
|
2295
|
+
}
|
|
2296
|
+
);
|
|
2297
|
+
});
|
|
2298
|
+
if (answer === "r" || answer === "remove") return true;
|
|
2299
|
+
if (answer === "k" || answer === "keep") return false;
|
|
2300
|
+
console.error(`Unknown answer: ${answer || "(empty)"} \u2014 try again.`);
|
|
2301
|
+
}
|
|
2302
|
+
} finally {
|
|
2303
|
+
rl.close();
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
function patternTargetsSettingsJson(pattern) {
|
|
2307
|
+
const trimmed = pattern.trim();
|
|
2308
|
+
if (trimmed === "" || trimmed.startsWith("!")) return false;
|
|
2309
|
+
const lastSegment = trimmed.split("/").filter(Boolean).pop() ?? "";
|
|
2310
|
+
return lastSegment === "settings.json" && !trimmed.endsWith("/");
|
|
2311
|
+
}
|
|
2312
|
+
function parseCheckIgnoreLine(line) {
|
|
2313
|
+
const tabIdx = line.indexOf(" ");
|
|
2314
|
+
if (tabIdx === -1) return null;
|
|
2315
|
+
const meta = line.slice(0, tabIdx);
|
|
2316
|
+
const matchedPath = line.slice(tabIdx + 1);
|
|
2317
|
+
const m = /^(.*):(\d+):(.*)$/.exec(meta);
|
|
2318
|
+
if (!m) return null;
|
|
2319
|
+
return {
|
|
2320
|
+
sourceFile: m[1] ?? "",
|
|
2321
|
+
lineNum: parseInt(m[2] ?? "0", 10),
|
|
2322
|
+
pattern: m[3] ?? "",
|
|
2323
|
+
matchedPath
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
async function detectAndHealSettingsGitignore(projectDir, opts, deps = {}) {
|
|
2327
|
+
const gitCheckIgnore = deps.gitCheckIgnore ?? defaultGitCheckIgnore;
|
|
2328
|
+
const readFileFn = deps.readFileFn ?? ((p) => readFile9(p, "utf-8"));
|
|
2329
|
+
const writeFileFn = deps.writeFileFn ?? ((p, content) => writeFile7(p, content, "utf-8"));
|
|
2330
|
+
const promptFn = deps.promptRemoveIgnore ?? defaultPromptRemoveIgnore;
|
|
2331
|
+
const printWarning = deps.printWarning ?? ((msg) => console.warn(msg));
|
|
2332
|
+
const printInfo = deps.printInfo ?? ((msg) => console.log(msg));
|
|
2333
|
+
let ciResult;
|
|
2334
|
+
try {
|
|
2335
|
+
ciResult = gitCheckIgnore(projectDir);
|
|
2336
|
+
} catch {
|
|
2337
|
+
return { healed: false, skipped: "non-git" };
|
|
2338
|
+
}
|
|
2339
|
+
if (ciResult.exitCode === 128 || ciResult.exitCode === null) {
|
|
2340
|
+
return { healed: false, skipped: "non-git" };
|
|
2341
|
+
}
|
|
2342
|
+
if (ciResult.exitCode !== 0) {
|
|
2343
|
+
return { healed: false, skipped: "not-ignored" };
|
|
2344
|
+
}
|
|
2345
|
+
const rawLine = ciResult.stdout.trim().split(/\r?\n/)[0] ?? "";
|
|
2346
|
+
const parsed = parseCheckIgnoreLine(rawLine);
|
|
2347
|
+
if (!parsed) {
|
|
2348
|
+
return { healed: false, skipped: "not-ignored" };
|
|
2349
|
+
}
|
|
2350
|
+
const gitignorePath = path5.isAbsolute(parsed.sourceFile) ? parsed.sourceFile : path5.join(projectDir, parsed.sourceFile);
|
|
2351
|
+
let gitignoreContent;
|
|
2352
|
+
try {
|
|
2353
|
+
gitignoreContent = await readFileFn(gitignorePath);
|
|
2354
|
+
} catch {
|
|
2355
|
+
return { healed: false, skipped: "not-ignored" };
|
|
2356
|
+
}
|
|
2357
|
+
const nl = gitignoreContent.includes("\r\n") ? "\r\n" : "\n";
|
|
2358
|
+
const lines = gitignoreContent.split(/\r?\n/);
|
|
2359
|
+
const startIdx = lines.findIndex((l) => l === GITIGNORE_BLOCK_START);
|
|
2360
|
+
const endIdx = lines.findIndex((l) => l === GITIGNORE_BLOCK_END);
|
|
2361
|
+
const lineIdx = parsed.lineNum - 1;
|
|
2362
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx && lineIdx > startIdx && lineIdx < endIdx) {
|
|
2363
|
+
return { healed: false, skipped: "managed-block" };
|
|
2364
|
+
}
|
|
2365
|
+
const offendingLine = lines[lineIdx] ?? parsed.pattern;
|
|
2366
|
+
const displayLine = `${parsed.sourceFile}:${parsed.lineNum}: ${offendingLine}`;
|
|
2367
|
+
if (patternTargetsSettingsJson(parsed.pattern)) {
|
|
2368
|
+
printInfo(
|
|
2369
|
+
`codebyplan: ${opts.dryRun ? "(dry-run) would remove" : "removing"} gitignore rule "${offendingLine}" (${parsed.sourceFile}:${parsed.lineNum}) \u2014 .claude/settings.json must be committed.`
|
|
2370
|
+
);
|
|
2371
|
+
} else {
|
|
2372
|
+
let accepted;
|
|
2373
|
+
try {
|
|
2374
|
+
accepted = await promptFn(displayLine, opts);
|
|
2375
|
+
} catch (err) {
|
|
2376
|
+
printWarning(
|
|
2377
|
+
`codebyplan: could not prompt to remove gitignore line (${err instanceof Error ? err.message : String(err)}). Manual fix: remove "${offendingLine}" from ${parsed.sourceFile}, then git add .claude/settings.json.`
|
|
2378
|
+
);
|
|
2379
|
+
return { healed: false, skipped: "user-declined" };
|
|
2380
|
+
}
|
|
2381
|
+
if (!accepted) {
|
|
2382
|
+
printWarning(
|
|
2383
|
+
`codebyplan: .claude/settings.json is gitignored by "${offendingLine}" in ${parsed.sourceFile}:${parsed.lineNum}. To fix manually: remove that line and run \`git add .claude/settings.json\`.`
|
|
2384
|
+
);
|
|
2385
|
+
return { healed: false, skipped: "user-declined" };
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
if (!opts.dryRun) {
|
|
2389
|
+
const newLines = lines.filter((_l, idx) => idx !== lineIdx);
|
|
2390
|
+
const newContent = newLines.join(nl);
|
|
2391
|
+
try {
|
|
2392
|
+
await writeFileFn(gitignorePath, newContent);
|
|
2393
|
+
} catch (err) {
|
|
2394
|
+
printWarning(
|
|
2395
|
+
`codebyplan: failed to write ${parsed.sourceFile}: ${err instanceof Error ? err.message : String(err)}`
|
|
2396
|
+
);
|
|
2397
|
+
return { healed: false, skipped: "user-declined" };
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
return { healed: true };
|
|
2401
|
+
}
|
|
2402
|
+
function detectSettingsIgnored(projectDir, deps) {
|
|
2403
|
+
const gitCheckIgnoreFn = deps?.gitCheckIgnore ?? defaultGitCheckIgnore;
|
|
2404
|
+
let ciResult;
|
|
2405
|
+
try {
|
|
2406
|
+
ciResult = gitCheckIgnoreFn(projectDir);
|
|
2407
|
+
} catch {
|
|
2408
|
+
return { status: "non-git" };
|
|
2409
|
+
}
|
|
2410
|
+
if (ciResult.exitCode === 128 || ciResult.exitCode === null) {
|
|
2411
|
+
return { status: "non-git" };
|
|
2412
|
+
}
|
|
2413
|
+
if (ciResult.exitCode !== 0) {
|
|
2414
|
+
return { status: "not-ignored" };
|
|
2415
|
+
}
|
|
2416
|
+
const rawLine = ciResult.stdout.trim().split(/\r?\n/)[0] ?? "";
|
|
2417
|
+
const parsed = parseCheckIgnoreLine(rawLine);
|
|
2418
|
+
if (!parsed) {
|
|
2419
|
+
return { status: "not-ignored" };
|
|
2420
|
+
}
|
|
2421
|
+
return {
|
|
2422
|
+
status: "ignored",
|
|
2423
|
+
info: {
|
|
2424
|
+
sourceFile: parsed.sourceFile,
|
|
2425
|
+
lineNum: parsed.lineNum,
|
|
2426
|
+
pattern: parsed.pattern
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
function checkSettingsUntracked(projectDir, deps = {}) {
|
|
2431
|
+
const lsFn = deps.gitLsFiles ?? defaultGitLsFiles;
|
|
2432
|
+
const code = lsFn(projectDir);
|
|
2433
|
+
if (code === 0) return "tracked";
|
|
2434
|
+
if (code === 128) return "non-git";
|
|
2435
|
+
return "untracked";
|
|
2436
|
+
}
|
|
2437
|
+
function warnIfSettingsUntracked(projectDir, deps = {}) {
|
|
2438
|
+
const status = checkSettingsUntracked(projectDir, deps);
|
|
2439
|
+
if (status === "untracked") {
|
|
2440
|
+
console.warn(
|
|
2441
|
+
"codebyplan: .claude/settings.json is untracked \u2014 run `git add .claude/settings.json` and commit it."
|
|
2442
|
+
);
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
var init_gitignore_detect = __esm({
|
|
2446
|
+
"src/lib/gitignore-detect.ts"() {
|
|
2447
|
+
"use strict";
|
|
2448
|
+
init_gitignore_block();
|
|
2449
|
+
}
|
|
2450
|
+
});
|
|
2451
|
+
|
|
2232
2452
|
// src/lib/tech-detect.ts
|
|
2233
|
-
import { readFile as
|
|
2234
|
-
import { join as
|
|
2453
|
+
import { readFile as readFile10, access, readdir } from "node:fs/promises";
|
|
2454
|
+
import { join as join12, relative as relative2 } from "node:path";
|
|
2235
2455
|
async function fileExists(filePath) {
|
|
2236
2456
|
try {
|
|
2237
2457
|
await access(filePath);
|
|
@@ -2244,8 +2464,8 @@ async function discoverMonorepoApps(projectPath) {
|
|
|
2244
2464
|
const apps = [];
|
|
2245
2465
|
const patterns = [];
|
|
2246
2466
|
try {
|
|
2247
|
-
const raw = await
|
|
2248
|
-
|
|
2467
|
+
const raw = await readFile10(
|
|
2468
|
+
join12(projectPath, "pnpm-workspace.yaml"),
|
|
2249
2469
|
"utf-8"
|
|
2250
2470
|
);
|
|
2251
2471
|
const matches = raw.match(/^\s*-\s*['"]?([^'"#\n]+)['"]?/gm);
|
|
@@ -2259,7 +2479,7 @@ async function discoverMonorepoApps(projectPath) {
|
|
|
2259
2479
|
}
|
|
2260
2480
|
if (patterns.length === 0) {
|
|
2261
2481
|
try {
|
|
2262
|
-
const raw = await
|
|
2482
|
+
const raw = await readFile10(join12(projectPath, "package.json"), "utf-8");
|
|
2263
2483
|
const pkg = JSON.parse(raw);
|
|
2264
2484
|
const ws = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages;
|
|
2265
2485
|
if (ws) patterns.push(...ws);
|
|
@@ -2269,14 +2489,14 @@ async function discoverMonorepoApps(projectPath) {
|
|
|
2269
2489
|
for (const pattern of patterns) {
|
|
2270
2490
|
if (pattern.endsWith("/*")) {
|
|
2271
2491
|
const dir = pattern.slice(0, -2);
|
|
2272
|
-
const absDir =
|
|
2492
|
+
const absDir = join12(projectPath, dir);
|
|
2273
2493
|
try {
|
|
2274
2494
|
const entries = await readdir(absDir, { withFileTypes: true });
|
|
2275
2495
|
for (const entry of entries) {
|
|
2276
2496
|
if (entry.isDirectory()) {
|
|
2277
|
-
const relPath =
|
|
2278
|
-
const absPath =
|
|
2279
|
-
if (await fileExists(
|
|
2497
|
+
const relPath = join12(dir, entry.name);
|
|
2498
|
+
const absPath = join12(absDir, entry.name);
|
|
2499
|
+
if (await fileExists(join12(absPath, "package.json"))) {
|
|
2280
2500
|
apps.push({ name: entry.name, path: relPath, absPath });
|
|
2281
2501
|
}
|
|
2282
2502
|
}
|
|
@@ -2295,7 +2515,7 @@ async function hasJsxFile(dir, depth = 0) {
|
|
|
2295
2515
|
const name = entry.name;
|
|
2296
2516
|
if (entry.isDirectory()) {
|
|
2297
2517
|
if (SKIP_DIRS.has(name) || JSX_SKIP_DIRS.has(name)) continue;
|
|
2298
|
-
if (await hasJsxFile(
|
|
2518
|
+
if (await hasJsxFile(join12(dir, name), depth + 1)) return true;
|
|
2299
2519
|
} else if (entry.isFile()) {
|
|
2300
2520
|
if (JSX_TEST_PATTERN.test(name)) continue;
|
|
2301
2521
|
if (name.endsWith(".tsx") || name.endsWith(".jsx")) return true;
|
|
@@ -2314,7 +2534,7 @@ async function hasJsxFile(dir, depth = 0) {
|
|
|
2314
2534
|
async function detectCapabilities(dirPath, pkgJson) {
|
|
2315
2535
|
const caps = /* @__PURE__ */ new Set();
|
|
2316
2536
|
for (const sub of JSX_SCAN_DIRS) {
|
|
2317
|
-
if (await hasJsxFile(
|
|
2537
|
+
if (await hasJsxFile(join12(dirPath, sub))) {
|
|
2318
2538
|
caps.add("jsx");
|
|
2319
2539
|
break;
|
|
2320
2540
|
}
|
|
@@ -2336,7 +2556,7 @@ async function detectCapabilities(dirPath, pkgJson) {
|
|
|
2336
2556
|
}
|
|
2337
2557
|
}
|
|
2338
2558
|
}
|
|
2339
|
-
if (!caps.has("node-server") && await fileExists(
|
|
2559
|
+
if (!caps.has("node-server") && await fileExists(join12(dirPath, "src", "main.ts"))) {
|
|
2340
2560
|
caps.add("node-server");
|
|
2341
2561
|
}
|
|
2342
2562
|
if (pkgJson && pkgJson.bin) {
|
|
@@ -2352,7 +2572,7 @@ async function detectFromDirectory(dirPath) {
|
|
|
2352
2572
|
const seen = /* @__PURE__ */ new Map();
|
|
2353
2573
|
let pkgJson = null;
|
|
2354
2574
|
try {
|
|
2355
|
-
const raw = await
|
|
2575
|
+
const raw = await readFile10(join12(dirPath, "package.json"), "utf-8");
|
|
2356
2576
|
pkgJson = JSON.parse(raw);
|
|
2357
2577
|
const allDeps = {
|
|
2358
2578
|
...pkgJson.dependencies ?? {},
|
|
@@ -2384,7 +2604,7 @@ async function detectFromDirectory(dirPath) {
|
|
|
2384
2604
|
}
|
|
2385
2605
|
for (const { file, rule } of CONFIG_FILE_MAP) {
|
|
2386
2606
|
const key = rule.name.toLowerCase();
|
|
2387
|
-
if (!seen.has(key) && await fileExists(
|
|
2607
|
+
if (!seen.has(key) && await fileExists(join12(dirPath, file))) {
|
|
2388
2608
|
seen.set(key, { name: rule.name, category: rule.category });
|
|
2389
2609
|
}
|
|
2390
2610
|
}
|
|
@@ -2562,7 +2782,7 @@ function categorizeDependency(depName) {
|
|
|
2562
2782
|
async function findPackageJsonFiles(dir, projectPath, depth = 0) {
|
|
2563
2783
|
if (depth > 4) return [];
|
|
2564
2784
|
const results = [];
|
|
2565
|
-
const pkgPath =
|
|
2785
|
+
const pkgPath = join12(dir, "package.json");
|
|
2566
2786
|
if (await fileExists(pkgPath)) {
|
|
2567
2787
|
results.push(pkgPath);
|
|
2568
2788
|
}
|
|
@@ -2571,7 +2791,7 @@ async function findPackageJsonFiles(dir, projectPath, depth = 0) {
|
|
|
2571
2791
|
for (const entry of entries) {
|
|
2572
2792
|
if (!entry.isDirectory() || SKIP_DIRS.has(entry.name)) continue;
|
|
2573
2793
|
const subResults = await findPackageJsonFiles(
|
|
2574
|
-
|
|
2794
|
+
join12(dir, entry.name),
|
|
2575
2795
|
projectPath,
|
|
2576
2796
|
depth + 1
|
|
2577
2797
|
);
|
|
@@ -2586,7 +2806,7 @@ async function scanAllDependencies(projectPath) {
|
|
|
2586
2806
|
const dependencies = [];
|
|
2587
2807
|
for (const pkgPath of packageJsonPaths) {
|
|
2588
2808
|
try {
|
|
2589
|
-
const raw = await
|
|
2809
|
+
const raw = await readFile10(pkgPath, "utf-8");
|
|
2590
2810
|
const pkg = JSON.parse(raw);
|
|
2591
2811
|
const sourcePath = relative2(projectPath, pkgPath);
|
|
2592
2812
|
const depSections = [
|
|
@@ -2825,7 +3045,7 @@ var init_tech_detect = __esm({
|
|
|
2825
3045
|
});
|
|
2826
3046
|
|
|
2827
3047
|
// src/lib/lsp-detect.ts
|
|
2828
|
-
import { spawnSync as
|
|
3048
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2829
3049
|
function mapTechStackToLsp(detectedNames) {
|
|
2830
3050
|
const pluginIndex = new Map(
|
|
2831
3051
|
LSP_TABLE.map((s) => [s.plugin, s])
|
|
@@ -2847,7 +3067,7 @@ function binaryOnPath(binary) {
|
|
|
2847
3067
|
}
|
|
2848
3068
|
function probeWith(probe, binary) {
|
|
2849
3069
|
try {
|
|
2850
|
-
const result =
|
|
3070
|
+
const result = spawnSync4(probe, [binary], {
|
|
2851
3071
|
encoding: "utf-8",
|
|
2852
3072
|
timeout: 5e3
|
|
2853
3073
|
});
|
|
@@ -2988,9 +3208,9 @@ __export(lsp_exports, {
|
|
|
2988
3208
|
runLsp: () => runLsp,
|
|
2989
3209
|
runLspFull: () => runLspFull
|
|
2990
3210
|
});
|
|
2991
|
-
import { readFile as
|
|
2992
|
-
import { join as
|
|
2993
|
-
import { spawnSync as
|
|
3211
|
+
import { readFile as readFile11, writeFile as writeFile8, mkdir as mkdir5, unlink as unlink2, access as access2 } from "node:fs/promises";
|
|
3212
|
+
import { join as join13 } from "node:path";
|
|
3213
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
2994
3214
|
async function fileExists2(filePath) {
|
|
2995
3215
|
try {
|
|
2996
3216
|
await access2(filePath);
|
|
@@ -3001,7 +3221,7 @@ async function fileExists2(filePath) {
|
|
|
3001
3221
|
}
|
|
3002
3222
|
async function readJsonFile(filePath) {
|
|
3003
3223
|
try {
|
|
3004
|
-
const raw = await
|
|
3224
|
+
const raw = await readFile11(filePath, "utf-8");
|
|
3005
3225
|
return JSON.parse(raw);
|
|
3006
3226
|
} catch {
|
|
3007
3227
|
return null;
|
|
@@ -3009,7 +3229,7 @@ async function readJsonFile(filePath) {
|
|
|
3009
3229
|
}
|
|
3010
3230
|
function tryNpmInstallGlobal(pkg) {
|
|
3011
3231
|
try {
|
|
3012
|
-
const result =
|
|
3232
|
+
const result = spawnSync5("npm", ["i", "-g", pkg], {
|
|
3013
3233
|
encoding: "utf-8",
|
|
3014
3234
|
timeout: 6e4,
|
|
3015
3235
|
// "pipe" (not "inherit"): inheriting the parent's fds can surface EPIPE/EIO
|
|
@@ -3042,7 +3262,7 @@ async function runLspFull(projectPath, opts = {}) {
|
|
|
3042
3262
|
` Detected LSP servers: ${servers.map((s) => s.plugin).join(", ")}
|
|
3043
3263
|
`
|
|
3044
3264
|
);
|
|
3045
|
-
const settingsLocalPath =
|
|
3265
|
+
const settingsLocalPath = join13(projectPath, ".claude", "settings.local.json");
|
|
3046
3266
|
let settings = {};
|
|
3047
3267
|
const existingSettingsRaw = await readJsonFile(settingsLocalPath);
|
|
3048
3268
|
if (existingSettingsRaw) {
|
|
@@ -3055,15 +3275,15 @@ async function runLspFull(projectPath, opts = {}) {
|
|
|
3055
3275
|
if (dryRun) {
|
|
3056
3276
|
console.log(` [dry-run] would update ${settingsLocalPath}`);
|
|
3057
3277
|
} else {
|
|
3058
|
-
await mkdir5(
|
|
3059
|
-
await
|
|
3278
|
+
await mkdir5(join13(projectPath, ".claude"), { recursive: true });
|
|
3279
|
+
await writeFile8(
|
|
3060
3280
|
settingsLocalPath,
|
|
3061
3281
|
JSON.stringify(settings, null, 2) + "\n",
|
|
3062
3282
|
"utf-8"
|
|
3063
3283
|
);
|
|
3064
3284
|
console.log(` Updated ${settingsLocalPath}`);
|
|
3065
3285
|
}
|
|
3066
|
-
const lspJsonPath =
|
|
3286
|
+
const lspJsonPath = join13(projectPath, ".codebyplan", "lsp.json");
|
|
3067
3287
|
const lspJsonContent = {
|
|
3068
3288
|
servers: servers.map((s) => ({
|
|
3069
3289
|
plugin: s.plugin,
|
|
@@ -3074,15 +3294,15 @@ async function runLspFull(projectPath, opts = {}) {
|
|
|
3074
3294
|
if (dryRun) {
|
|
3075
3295
|
console.log(` [dry-run] would write ${lspJsonPath}`);
|
|
3076
3296
|
} else {
|
|
3077
|
-
await mkdir5(
|
|
3078
|
-
await
|
|
3297
|
+
await mkdir5(join13(projectPath, ".codebyplan"), { recursive: true });
|
|
3298
|
+
await writeFile8(
|
|
3079
3299
|
lspJsonPath,
|
|
3080
3300
|
JSON.stringify(lspJsonContent, null, 2) + "\n",
|
|
3081
3301
|
"utf-8"
|
|
3082
3302
|
);
|
|
3083
3303
|
console.log(` Wrote ${lspJsonPath}`);
|
|
3084
3304
|
}
|
|
3085
|
-
const todoDir =
|
|
3305
|
+
const todoDir = join13(projectPath, ".codebyplan", "todo", "session-start");
|
|
3086
3306
|
const autoInstalled = [];
|
|
3087
3307
|
const nudged = [];
|
|
3088
3308
|
for (const server of servers) {
|
|
@@ -3105,10 +3325,10 @@ async function runLspFull(projectPath, opts = {}) {
|
|
|
3105
3325
|
` npm install failed for ${server.npmPackage}. Writing nudge file.`
|
|
3106
3326
|
);
|
|
3107
3327
|
await mkdir5(todoDir, { recursive: true });
|
|
3108
|
-
const nudgeFile =
|
|
3328
|
+
const nudgeFile = join13(todoDir, `install-${server.binary}.md`);
|
|
3109
3329
|
const nudgeContent = `Run \`${server.installHint}\` to enable ${server.language} LSP support in Claude Code.
|
|
3110
3330
|
`;
|
|
3111
|
-
await
|
|
3331
|
+
await writeFile8(nudgeFile, nudgeContent, "utf-8");
|
|
3112
3332
|
nudged.push(server.binary);
|
|
3113
3333
|
}
|
|
3114
3334
|
} else {
|
|
@@ -3117,10 +3337,10 @@ async function runLspFull(projectPath, opts = {}) {
|
|
|
3117
3337
|
nudged.push(server.binary);
|
|
3118
3338
|
} else {
|
|
3119
3339
|
await mkdir5(todoDir, { recursive: true });
|
|
3120
|
-
const nudgeFile =
|
|
3340
|
+
const nudgeFile = join13(todoDir, `install-${server.binary}.md`);
|
|
3121
3341
|
const nudgeContent = `Run \`${server.installHint}\` to enable ${server.language} LSP support in Claude Code.
|
|
3122
3342
|
`;
|
|
3123
|
-
await
|
|
3343
|
+
await writeFile8(nudgeFile, nudgeContent, "utf-8");
|
|
3124
3344
|
nudged.push(server.binary);
|
|
3125
3345
|
}
|
|
3126
3346
|
}
|
|
@@ -3154,19 +3374,19 @@ async function runLspFull(projectPath, opts = {}) {
|
|
|
3154
3374
|
`);
|
|
3155
3375
|
}
|
|
3156
3376
|
async function runLspCheck(projectPath) {
|
|
3157
|
-
const lspJsonPath =
|
|
3377
|
+
const lspJsonPath = join13(projectPath, ".codebyplan", "lsp.json");
|
|
3158
3378
|
const lspJson = await readJsonFile(lspJsonPath);
|
|
3159
3379
|
if (!lspJson || !Array.isArray(lspJson.servers)) {
|
|
3160
3380
|
return;
|
|
3161
3381
|
}
|
|
3162
|
-
const todoDir =
|
|
3382
|
+
const todoDir = join13(projectPath, ".codebyplan", "todo", "session-start");
|
|
3163
3383
|
const stillMissing = [];
|
|
3164
3384
|
for (const entry of lspJson.servers) {
|
|
3165
3385
|
const { binary, plugin } = entry;
|
|
3166
3386
|
const found = binaryOnPath(binary);
|
|
3167
3387
|
const fullServer = LSP_TABLE.find((s) => s.plugin === plugin);
|
|
3168
3388
|
if (found) {
|
|
3169
|
-
const nudgeFile =
|
|
3389
|
+
const nudgeFile = join13(todoDir, `install-${binary}.md`);
|
|
3170
3390
|
if (await fileExists2(nudgeFile)) {
|
|
3171
3391
|
try {
|
|
3172
3392
|
await unlink2(nudgeFile);
|
|
@@ -3212,7 +3432,7 @@ __export(install_exports, {
|
|
|
3212
3432
|
});
|
|
3213
3433
|
import * as fs4 from "node:fs";
|
|
3214
3434
|
import * as os2 from "node:os";
|
|
3215
|
-
import * as
|
|
3435
|
+
import * as path6 from "node:path";
|
|
3216
3436
|
async function runInstall(opts, deps = {}) {
|
|
3217
3437
|
await Promise.resolve();
|
|
3218
3438
|
const scope = opts.scope ?? "project";
|
|
@@ -3240,14 +3460,14 @@ async function runInstall(opts, deps = {}) {
|
|
|
3240
3460
|
const files = walkTemplates(templatesDir);
|
|
3241
3461
|
const manifestEntries = [];
|
|
3242
3462
|
for (const f of files) {
|
|
3243
|
-
const absDest =
|
|
3244
|
-
const absSrc =
|
|
3463
|
+
const absDest = path6.join(projectDir, ".claude", f.dest);
|
|
3464
|
+
const absSrc = path6.join(templatesDir, f.src);
|
|
3245
3465
|
if (opts.dryRun) {
|
|
3246
3466
|
if (opts.verbose) {
|
|
3247
3467
|
console.log(`[dry-run] would copy ${f.src} \u2192 .claude/${f.dest}`);
|
|
3248
3468
|
}
|
|
3249
3469
|
} else {
|
|
3250
|
-
fs4.mkdirSync(
|
|
3470
|
+
fs4.mkdirSync(path6.dirname(absDest), { recursive: true });
|
|
3251
3471
|
fs4.copyFileSync(absSrc, absDest);
|
|
3252
3472
|
if (opts.verbose) {
|
|
3253
3473
|
console.log(`copied ${f.src} \u2192 .claude/${f.dest}`);
|
|
@@ -3255,14 +3475,14 @@ async function runInstall(opts, deps = {}) {
|
|
|
3255
3475
|
}
|
|
3256
3476
|
manifestEntries.push({ src: f.src, dest: f.dest, hash: f.hash });
|
|
3257
3477
|
}
|
|
3258
|
-
const hooksJsonPath =
|
|
3259
|
-
const baseSettingsPath =
|
|
3478
|
+
const hooksJsonPath = path6.join(templatesDir, "hooks", "hooks.json");
|
|
3479
|
+
const baseSettingsPath = path6.join(
|
|
3260
3480
|
templatesDir,
|
|
3261
3481
|
"settings.project.base.json"
|
|
3262
3482
|
);
|
|
3263
3483
|
const hasHooks = fs4.existsSync(hooksJsonPath);
|
|
3264
3484
|
const hasBase = fs4.existsSync(baseSettingsPath);
|
|
3265
|
-
const settingsPath =
|
|
3485
|
+
const settingsPath = path6.join(projectDir, ".claude", "settings.json");
|
|
3266
3486
|
const existingSettings = fs4.existsSync(settingsPath) ? JSON.parse(fs4.readFileSync(settingsPath, "utf8")) : {};
|
|
3267
3487
|
if (hasBase) {
|
|
3268
3488
|
const base = JSON.parse(
|
|
@@ -3283,8 +3503,13 @@ async function runInstall(opts, deps = {}) {
|
|
|
3283
3503
|
) : void 0
|
|
3284
3504
|
);
|
|
3285
3505
|
}
|
|
3506
|
+
await detectAndHealSettingsGitignore(
|
|
3507
|
+
projectDir,
|
|
3508
|
+
{ yes: opts.yes, dryRun: opts.dryRun },
|
|
3509
|
+
deps.detectHealDeps
|
|
3510
|
+
);
|
|
3286
3511
|
if (!opts.dryRun) {
|
|
3287
|
-
fs4.mkdirSync(
|
|
3512
|
+
fs4.mkdirSync(path6.dirname(settingsPath), { recursive: true });
|
|
3288
3513
|
fs4.writeFileSync(
|
|
3289
3514
|
settingsPath,
|
|
3290
3515
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
@@ -3292,16 +3517,19 @@ async function runInstall(opts, deps = {}) {
|
|
|
3292
3517
|
);
|
|
3293
3518
|
} else if (opts.verbose) {
|
|
3294
3519
|
console.log(
|
|
3295
|
-
`[dry-run] would merge settings into ${
|
|
3520
|
+
`[dry-run] would merge settings into ${path6.relative(projectDir, settingsPath)}`
|
|
3296
3521
|
);
|
|
3297
3522
|
}
|
|
3523
|
+
if (!opts.dryRun) {
|
|
3524
|
+
warnIfSettingsUntracked(projectDir, deps.lsFilesDep);
|
|
3525
|
+
}
|
|
3298
3526
|
const gitignoreAction = await ensureManagedGitignoreBlock(
|
|
3299
3527
|
projectDir,
|
|
3300
3528
|
opts.dryRun
|
|
3301
3529
|
);
|
|
3302
3530
|
if (opts.verbose && gitignoreAction !== "unchanged") {
|
|
3303
3531
|
console.log(
|
|
3304
|
-
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${
|
|
3532
|
+
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${path6.relative(projectDir, path6.join(projectDir, ".gitignore"))}`
|
|
3305
3533
|
);
|
|
3306
3534
|
}
|
|
3307
3535
|
if (!opts.dryRun) {
|
|
@@ -3339,9 +3567,9 @@ function runInstallUser(opts, deps) {
|
|
|
3339
3567
|
return;
|
|
3340
3568
|
}
|
|
3341
3569
|
try {
|
|
3342
|
-
const userDir = deps.userDir ??
|
|
3343
|
-
const settingsPath =
|
|
3344
|
-
const userBaseSettingsPath =
|
|
3570
|
+
const userDir = deps.userDir ?? path6.join(os2.homedir(), ".claude");
|
|
3571
|
+
const settingsPath = path6.join(userDir, "settings.json");
|
|
3572
|
+
const userBaseSettingsPath = path6.join(
|
|
3345
3573
|
templatesDir,
|
|
3346
3574
|
"settings.user.base.json"
|
|
3347
3575
|
);
|
|
@@ -3383,7 +3611,7 @@ function runInstallUser(opts, deps) {
|
|
|
3383
3611
|
}
|
|
3384
3612
|
}
|
|
3385
3613
|
function countHookEntries(templatesDir) {
|
|
3386
|
-
const p =
|
|
3614
|
+
const p = path6.join(templatesDir, "hooks", "hooks.json");
|
|
3387
3615
|
if (!fs4.existsSync(p)) return 0;
|
|
3388
3616
|
try {
|
|
3389
3617
|
const j = JSON.parse(fs4.readFileSync(p, "utf8"));
|
|
@@ -3408,6 +3636,7 @@ var init_install = __esm({
|
|
|
3408
3636
|
init_settings_merge();
|
|
3409
3637
|
init_statusline_config();
|
|
3410
3638
|
init_templates_dir();
|
|
3639
|
+
init_gitignore_detect();
|
|
3411
3640
|
}
|
|
3412
3641
|
});
|
|
3413
3642
|
|
|
@@ -3416,17 +3645,17 @@ var setup_exports = {};
|
|
|
3416
3645
|
__export(setup_exports, {
|
|
3417
3646
|
runSetup: () => runSetup
|
|
3418
3647
|
});
|
|
3419
|
-
import { readFile as
|
|
3648
|
+
import { readFile as readFile12, writeFile as writeFile9 } from "node:fs/promises";
|
|
3420
3649
|
import { homedir as homedir4 } from "node:os";
|
|
3421
|
-
import { join as
|
|
3650
|
+
import { join as join15 } from "node:path";
|
|
3422
3651
|
import { stdin, stdout as stdout2 } from "node:process";
|
|
3423
3652
|
import { createInterface } from "node:readline/promises";
|
|
3424
3653
|
function getConfigPath(scope) {
|
|
3425
|
-
return scope === "user" ?
|
|
3654
|
+
return scope === "user" ? join15(homedir4(), ".claude.json") : join15(process.cwd(), ".mcp.json");
|
|
3426
3655
|
}
|
|
3427
|
-
async function readConfig(
|
|
3656
|
+
async function readConfig(path22) {
|
|
3428
3657
|
try {
|
|
3429
|
-
const raw = await
|
|
3658
|
+
const raw = await readFile12(path22, "utf-8");
|
|
3430
3659
|
const parsed = JSON.parse(raw);
|
|
3431
3660
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3432
3661
|
return parsed;
|
|
@@ -3446,7 +3675,7 @@ async function writeMcpConfig(scope) {
|
|
|
3446
3675
|
config.mcpServers = {};
|
|
3447
3676
|
}
|
|
3448
3677
|
config.mcpServers.codebyplan = buildMcpEntry();
|
|
3449
|
-
await
|
|
3678
|
+
await writeFile9(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3450
3679
|
return configPath;
|
|
3451
3680
|
}
|
|
3452
3681
|
async function fetchRepos(auth) {
|
|
@@ -3851,15 +4080,15 @@ var upgrade_auth_exports = {};
|
|
|
3851
4080
|
__export(upgrade_auth_exports, {
|
|
3852
4081
|
runUpgradeAuth: () => runUpgradeAuth
|
|
3853
4082
|
});
|
|
3854
|
-
import { readFile as
|
|
4083
|
+
import { readFile as readFile13, writeFile as writeFile10 } from "node:fs/promises";
|
|
3855
4084
|
import { homedir as homedir5 } from "node:os";
|
|
3856
|
-
import { join as
|
|
4085
|
+
import { join as join16 } from "node:path";
|
|
3857
4086
|
function configPaths() {
|
|
3858
|
-
return [
|
|
4087
|
+
return [join16(homedir5(), ".claude.json"), join16(process.cwd(), ".mcp.json")];
|
|
3859
4088
|
}
|
|
3860
|
-
async function readConfig2(
|
|
4089
|
+
async function readConfig2(path22) {
|
|
3861
4090
|
try {
|
|
3862
|
-
const raw = await
|
|
4091
|
+
const raw = await readFile13(path22, "utf-8");
|
|
3863
4092
|
const parsed = JSON.parse(raw);
|
|
3864
4093
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3865
4094
|
return parsed;
|
|
@@ -3873,7 +4102,7 @@ function entryHasLegacyApiKey(entry) {
|
|
|
3873
4102
|
if (!entry || !entry.headers) return false;
|
|
3874
4103
|
return "x-api-key" in entry.headers;
|
|
3875
4104
|
}
|
|
3876
|
-
async function rewriteConfig(
|
|
4105
|
+
async function rewriteConfig(path22, config, newUrl) {
|
|
3877
4106
|
const servers = config.mcpServers;
|
|
3878
4107
|
if (!servers) return false;
|
|
3879
4108
|
const entry = servers.codebyplan;
|
|
@@ -3881,7 +4110,7 @@ async function rewriteConfig(path21, config, newUrl) {
|
|
|
3881
4110
|
if (!entryHasLegacyApiKey(entry) && entry.url === newUrl && entry.type === "http")
|
|
3882
4111
|
return false;
|
|
3883
4112
|
servers.codebyplan = { type: "http", url: newUrl };
|
|
3884
|
-
await
|
|
4113
|
+
await writeFile10(path22, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3885
4114
|
return true;
|
|
3886
4115
|
}
|
|
3887
4116
|
async function runUpgradeAuth() {
|
|
@@ -3889,12 +4118,12 @@ async function runUpgradeAuth() {
|
|
|
3889
4118
|
await runLogin();
|
|
3890
4119
|
const newUrl = mcpEndpoint();
|
|
3891
4120
|
let migrated = 0;
|
|
3892
|
-
for (const
|
|
3893
|
-
const config = await readConfig2(
|
|
4121
|
+
for (const path22 of configPaths()) {
|
|
4122
|
+
const config = await readConfig2(path22);
|
|
3894
4123
|
if (!config) continue;
|
|
3895
|
-
const changed = await rewriteConfig(
|
|
4124
|
+
const changed = await rewriteConfig(path22, config, newUrl);
|
|
3896
4125
|
if (changed) {
|
|
3897
|
-
console.log(` Updated ${
|
|
4126
|
+
console.log(` Updated ${path22}`);
|
|
3898
4127
|
migrated++;
|
|
3899
4128
|
}
|
|
3900
4129
|
}
|
|
@@ -4347,8 +4576,8 @@ __export(eslint_exports, {
|
|
|
4347
4576
|
eslintInit: () => eslintInit,
|
|
4348
4577
|
runEslint: () => runEslint
|
|
4349
4578
|
});
|
|
4350
|
-
import { readFile as
|
|
4351
|
-
import { join as
|
|
4579
|
+
import { readFile as readFile14, writeFile as writeFile11, access as access3, readdir as readdir2 } from "node:fs/promises";
|
|
4580
|
+
import { join as join17, relative as relative4 } from "node:path";
|
|
4352
4581
|
async function fileExists3(filePath) {
|
|
4353
4582
|
try {
|
|
4354
4583
|
await access3(filePath);
|
|
@@ -4359,7 +4588,7 @@ async function fileExists3(filePath) {
|
|
|
4359
4588
|
}
|
|
4360
4589
|
async function autoDetectIgnorePatterns(absPath) {
|
|
4361
4590
|
const patterns = [];
|
|
4362
|
-
if (await fileExists3(
|
|
4591
|
+
if (await fileExists3(join17(absPath, "esbuild.js"))) {
|
|
4363
4592
|
patterns.push("esbuild.js");
|
|
4364
4593
|
}
|
|
4365
4594
|
let entries = [];
|
|
@@ -4379,19 +4608,19 @@ async function autoDetectIgnorePatterns(absPath) {
|
|
|
4379
4608
|
}
|
|
4380
4609
|
for (const ext of ["ts", "mts", "js", "mjs"]) {
|
|
4381
4610
|
const candidate = `vitest.config.${ext}`;
|
|
4382
|
-
if (await fileExists3(
|
|
4611
|
+
if (await fileExists3(join17(absPath, candidate))) {
|
|
4383
4612
|
patterns.push(candidate);
|
|
4384
4613
|
break;
|
|
4385
4614
|
}
|
|
4386
4615
|
}
|
|
4387
4616
|
for (const ext of ["ts", "mts", "js", "mjs"]) {
|
|
4388
4617
|
const candidate = `vite.config.${ext}`;
|
|
4389
|
-
if (await fileExists3(
|
|
4618
|
+
if (await fileExists3(join17(absPath, candidate))) {
|
|
4390
4619
|
patterns.push(candidate);
|
|
4391
4620
|
break;
|
|
4392
4621
|
}
|
|
4393
4622
|
}
|
|
4394
|
-
if (await fileExists3(
|
|
4623
|
+
if (await fileExists3(join17(absPath, "tauri.conf.json"))) {
|
|
4395
4624
|
patterns.push("src-tauri/**");
|
|
4396
4625
|
patterns.push("**/*.d.ts");
|
|
4397
4626
|
}
|
|
@@ -4399,14 +4628,14 @@ async function autoDetectIgnorePatterns(absPath) {
|
|
|
4399
4628
|
}
|
|
4400
4629
|
function detectPackageManager(projectPath) {
|
|
4401
4630
|
return (async () => {
|
|
4402
|
-
if (await fileExists3(
|
|
4403
|
-
if (await fileExists3(
|
|
4631
|
+
if (await fileExists3(join17(projectPath, "pnpm-lock.yaml"))) return "pnpm";
|
|
4632
|
+
if (await fileExists3(join17(projectPath, "yarn.lock"))) return "yarn";
|
|
4404
4633
|
return "npm";
|
|
4405
4634
|
})();
|
|
4406
4635
|
}
|
|
4407
4636
|
async function getInstalledDeps(pkgJsonPath) {
|
|
4408
4637
|
try {
|
|
4409
|
-
const raw = await
|
|
4638
|
+
const raw = await readFile14(pkgJsonPath, "utf-8");
|
|
4410
4639
|
const pkg = JSON.parse(raw);
|
|
4411
4640
|
const all = /* @__PURE__ */ new Set();
|
|
4412
4641
|
for (const name of Object.keys(pkg.dependencies ?? {})) all.add(name);
|
|
@@ -4519,7 +4748,7 @@ async function eslintInit(repoId, projectPath) {
|
|
|
4519
4748
|
ignorePatterns: detectedIgnores
|
|
4520
4749
|
});
|
|
4521
4750
|
const hash = hashConfig(content);
|
|
4522
|
-
const configPath =
|
|
4751
|
+
const configPath = join17(target.absPath, "eslint.config.mjs");
|
|
4523
4752
|
configsToWrite.push({
|
|
4524
4753
|
target,
|
|
4525
4754
|
presets,
|
|
@@ -4541,11 +4770,11 @@ async function eslintInit(repoId, projectPath) {
|
|
|
4541
4770
|
return;
|
|
4542
4771
|
}
|
|
4543
4772
|
const pm = await detectPackageManager(projectPath);
|
|
4544
|
-
const rootPkgJsonPath =
|
|
4773
|
+
const rootPkgJsonPath = join17(projectPath, "package.json");
|
|
4545
4774
|
const installed = await getInstalledDeps(rootPkgJsonPath);
|
|
4546
4775
|
if (isMonorepo2) {
|
|
4547
4776
|
for (const { target } of configsToWrite) {
|
|
4548
|
-
const appPkgJson =
|
|
4777
|
+
const appPkgJson = join17(target.absPath, "package.json");
|
|
4549
4778
|
const appDeps = await getInstalledDeps(appPkgJson);
|
|
4550
4779
|
for (const dep of appDeps) {
|
|
4551
4780
|
installed.add(dep);
|
|
@@ -4597,7 +4826,7 @@ async function eslintInit(repoId, projectPath) {
|
|
|
4597
4826
|
} of configsToWrite) {
|
|
4598
4827
|
if (await fileExists3(configPath)) {
|
|
4599
4828
|
try {
|
|
4600
|
-
const existing = await
|
|
4829
|
+
const existing = await readFile14(configPath, "utf-8");
|
|
4601
4830
|
const existingHash = hashConfig(existing);
|
|
4602
4831
|
if (existingHash === hash) {
|
|
4603
4832
|
console.log(
|
|
@@ -4617,7 +4846,7 @@ async function eslintInit(repoId, projectPath) {
|
|
|
4617
4846
|
}
|
|
4618
4847
|
}
|
|
4619
4848
|
try {
|
|
4620
|
-
await
|
|
4849
|
+
await writeFile11(configPath, content, "utf-8");
|
|
4621
4850
|
} catch (err) {
|
|
4622
4851
|
console.error(
|
|
4623
4852
|
` ${target.name}: Failed to write config: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -4670,16 +4899,16 @@ var init_eslint = __esm({
|
|
|
4670
4899
|
});
|
|
4671
4900
|
|
|
4672
4901
|
// src/lib/worktree-cache.ts
|
|
4673
|
-
import { mkdir as mkdir6, readFile as
|
|
4674
|
-
import { dirname as dirname7, join as
|
|
4902
|
+
import { mkdir as mkdir6, readFile as readFile15, writeFile as writeFile12 } from "node:fs/promises";
|
|
4903
|
+
import { dirname as dirname7, join as join18 } from "node:path";
|
|
4675
4904
|
function worktreeCachePath(repoRoot) {
|
|
4676
|
-
return
|
|
4905
|
+
return join18(repoRoot, ".codebyplan", "worktree.local.json");
|
|
4677
4906
|
}
|
|
4678
4907
|
async function readCachedWorktreeId(repoRoot, currentBranch) {
|
|
4679
4908
|
const cachePath = worktreeCachePath(repoRoot);
|
|
4680
4909
|
let raw;
|
|
4681
4910
|
try {
|
|
4682
|
-
raw = await
|
|
4911
|
+
raw = await readFile15(cachePath, "utf-8");
|
|
4683
4912
|
} catch (err) {
|
|
4684
4913
|
const code = err.code;
|
|
4685
4914
|
if (code === "ENOENT") {
|
|
@@ -4725,7 +4954,7 @@ async function writeWorktreeCache(repoRoot, data) {
|
|
|
4725
4954
|
};
|
|
4726
4955
|
try {
|
|
4727
4956
|
await mkdir6(dirPath, { recursive: true });
|
|
4728
|
-
await
|
|
4957
|
+
await writeFile12(
|
|
4729
4958
|
cachePath,
|
|
4730
4959
|
JSON.stringify(payload, null, 2) + "\n",
|
|
4731
4960
|
"utf-8"
|
|
@@ -4767,25 +4996,25 @@ __export(state_store_exports, {
|
|
|
4767
4996
|
import { createHash as createHash4 } from "node:crypto";
|
|
4768
4997
|
import {
|
|
4769
4998
|
mkdir as mkdir7,
|
|
4770
|
-
readFile as
|
|
4771
|
-
writeFile as
|
|
4999
|
+
readFile as readFile16,
|
|
5000
|
+
writeFile as writeFile13,
|
|
4772
5001
|
unlink as unlink3,
|
|
4773
5002
|
readdir as readdir3,
|
|
4774
5003
|
stat as stat2,
|
|
4775
5004
|
rm
|
|
4776
5005
|
} from "node:fs/promises";
|
|
4777
|
-
import { join as
|
|
5006
|
+
import { join as join19, dirname as dirname8 } from "node:path";
|
|
4778
5007
|
function stateDir(repoRoot) {
|
|
4779
|
-
return
|
|
5008
|
+
return join19(repoRoot, ".codebyplan", "state");
|
|
4780
5009
|
}
|
|
4781
5010
|
function cursorPath(repoRoot) {
|
|
4782
|
-
return
|
|
5011
|
+
return join19(stateDir(repoRoot), "_cursor.json");
|
|
4783
5012
|
}
|
|
4784
5013
|
function checkpointPath(repoRoot, checkpointId) {
|
|
4785
|
-
return
|
|
5014
|
+
return join19(stateDir(repoRoot), "checkpoints", `${checkpointId}.json`);
|
|
4786
5015
|
}
|
|
4787
5016
|
function taskPath(repoRoot, checkpointId, taskId) {
|
|
4788
|
-
return
|
|
5017
|
+
return join19(
|
|
4789
5018
|
stateDir(repoRoot),
|
|
4790
5019
|
"checkpoints",
|
|
4791
5020
|
checkpointId,
|
|
@@ -4794,7 +5023,7 @@ function taskPath(repoRoot, checkpointId, taskId) {
|
|
|
4794
5023
|
);
|
|
4795
5024
|
}
|
|
4796
5025
|
function roundPath(repoRoot, checkpointId, taskId, roundId) {
|
|
4797
|
-
return
|
|
5026
|
+
return join19(
|
|
4798
5027
|
stateDir(repoRoot),
|
|
4799
5028
|
"checkpoints",
|
|
4800
5029
|
checkpointId,
|
|
@@ -4805,19 +5034,19 @@ function roundPath(repoRoot, checkpointId, taskId, roundId) {
|
|
|
4805
5034
|
);
|
|
4806
5035
|
}
|
|
4807
5036
|
function standaloneTaskPath(repoRoot, taskId) {
|
|
4808
|
-
return
|
|
5037
|
+
return join19(stateDir(repoRoot), "standalone_tasks", `${taskId}.json`);
|
|
4809
5038
|
}
|
|
4810
5039
|
function sessionLogPath(repoRoot) {
|
|
4811
|
-
return
|
|
5040
|
+
return join19(stateDir(repoRoot), "session", "current.json");
|
|
4812
5041
|
}
|
|
4813
5042
|
function todosPath(repoRoot) {
|
|
4814
|
-
return
|
|
5043
|
+
return join19(stateDir(repoRoot), "todos.json");
|
|
4815
5044
|
}
|
|
4816
5045
|
function worktreesPath(repoRoot) {
|
|
4817
|
-
return
|
|
5046
|
+
return join19(stateDir(repoRoot), "worktrees.json");
|
|
4818
5047
|
}
|
|
4819
5048
|
function pendingMarkerPath(repoRoot, entityId) {
|
|
4820
|
-
return
|
|
5049
|
+
return join19(stateDir(repoRoot), "_pending", `${entityId}.json`);
|
|
4821
5050
|
}
|
|
4822
5051
|
function serializeEntity(row) {
|
|
4823
5052
|
return JSON.stringify(row, null, 2) + "\n";
|
|
@@ -4828,7 +5057,7 @@ function hashEntity(row) {
|
|
|
4828
5057
|
async function readCursor(repoRoot) {
|
|
4829
5058
|
const p = cursorPath(repoRoot);
|
|
4830
5059
|
try {
|
|
4831
|
-
const raw = await
|
|
5060
|
+
const raw = await readFile16(p, "utf-8");
|
|
4832
5061
|
return JSON.parse(raw);
|
|
4833
5062
|
} catch (err) {
|
|
4834
5063
|
const code = err.code;
|
|
@@ -4845,7 +5074,7 @@ async function writeCursor(repoRoot, cursor) {
|
|
|
4845
5074
|
const p = cursorPath(repoRoot);
|
|
4846
5075
|
try {
|
|
4847
5076
|
await mkdir7(dirname8(p), { recursive: true });
|
|
4848
|
-
await
|
|
5077
|
+
await writeFile13(p, JSON.stringify(cursor, null, 2) + "\n", "utf-8");
|
|
4849
5078
|
} catch (err) {
|
|
4850
5079
|
process.stderr.write(
|
|
4851
5080
|
`state-store: writeCursor failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
@@ -4855,7 +5084,7 @@ async function writeCursor(repoRoot, cursor) {
|
|
|
4855
5084
|
}
|
|
4856
5085
|
async function readEntityFile(filePath) {
|
|
4857
5086
|
try {
|
|
4858
|
-
const raw = await
|
|
5087
|
+
const raw = await readFile16(filePath, "utf-8");
|
|
4859
5088
|
return JSON.parse(raw);
|
|
4860
5089
|
} catch (err) {
|
|
4861
5090
|
const code = err.code;
|
|
@@ -4873,7 +5102,7 @@ async function writeEntityFile(filePath, row) {
|
|
|
4873
5102
|
const hash = createHash4("sha256").update(serialized).digest("hex");
|
|
4874
5103
|
try {
|
|
4875
5104
|
await mkdir7(dirname8(filePath), { recursive: true });
|
|
4876
|
-
await
|
|
5105
|
+
await writeFile13(filePath, serialized, "utf-8");
|
|
4877
5106
|
} catch (err) {
|
|
4878
5107
|
process.stderr.write(
|
|
4879
5108
|
`state-store: writeEntityFile failed for ${filePath} (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
@@ -4920,7 +5149,7 @@ async function collectJsonFiles(dir, out) {
|
|
|
4920
5149
|
throw err;
|
|
4921
5150
|
}
|
|
4922
5151
|
for (const entry of entries) {
|
|
4923
|
-
const full =
|
|
5152
|
+
const full = join19(dir, entry);
|
|
4924
5153
|
try {
|
|
4925
5154
|
const s = await stat2(full);
|
|
4926
5155
|
if (s.isDirectory()) {
|
|
@@ -4938,7 +5167,7 @@ async function pruneEntityTree(repoRoot, knownIdsByTable) {
|
|
|
4938
5167
|
const taskIds = knownIdsByTable.tasks ?? /* @__PURE__ */ new Set();
|
|
4939
5168
|
const roundIds = knownIdsByTable.rounds ?? /* @__PURE__ */ new Set();
|
|
4940
5169
|
const base = stateDir(repoRoot);
|
|
4941
|
-
const checkpointsDir =
|
|
5170
|
+
const checkpointsDir = join19(base, "checkpoints");
|
|
4942
5171
|
const prunedCheckpointIds = /* @__PURE__ */ new Set();
|
|
4943
5172
|
const beforePrune = pruned.length;
|
|
4944
5173
|
await pruneJsonDir(checkpointsDir, checkpointIds, pruned);
|
|
@@ -4948,7 +5177,7 @@ async function pruneEntityTree(repoRoot, knownIdsByTable) {
|
|
|
4948
5177
|
}
|
|
4949
5178
|
for (const id of prunedCheckpointIds) {
|
|
4950
5179
|
try {
|
|
4951
|
-
await rm(
|
|
5180
|
+
await rm(join19(checkpointsDir, id), { recursive: true, force: true });
|
|
4952
5181
|
} catch (err) {
|
|
4953
5182
|
process.stderr.write(
|
|
4954
5183
|
`state-store: pruneEntityTree could not remove subtree for checkpoint ${id} (non-fatal): ${String(err)}
|
|
@@ -4956,7 +5185,7 @@ async function pruneEntityTree(repoRoot, knownIdsByTable) {
|
|
|
4956
5185
|
);
|
|
4957
5186
|
}
|
|
4958
5187
|
}
|
|
4959
|
-
const taskFiles = await listEntityFiles(
|
|
5188
|
+
const taskFiles = await listEntityFiles(join19(checkpointsDir));
|
|
4960
5189
|
for (const f of taskFiles) {
|
|
4961
5190
|
const chkMatch = f.match(/[/\\]checkpoints[/\\]([^/\\]+)[/\\]/);
|
|
4962
5191
|
if (chkMatch?.[1] && prunedCheckpointIds.has(chkMatch[1])) continue;
|
|
@@ -4996,7 +5225,7 @@ async function pruneJsonDir(dir, knownIds, pruned) {
|
|
|
4996
5225
|
if (!entry.endsWith(".json")) continue;
|
|
4997
5226
|
const id = entry.slice(0, -5);
|
|
4998
5227
|
if (!knownIds.has(id)) {
|
|
4999
|
-
const full =
|
|
5228
|
+
const full = join19(dir, entry);
|
|
5000
5229
|
await deleteEntityFile(full);
|
|
5001
5230
|
pruned.push(full);
|
|
5002
5231
|
}
|
|
@@ -5653,13 +5882,13 @@ function __disposeResources(env) {
|
|
|
5653
5882
|
}
|
|
5654
5883
|
return next();
|
|
5655
5884
|
}
|
|
5656
|
-
function __rewriteRelativeImportExtension(
|
|
5657
|
-
if (typeof
|
|
5658
|
-
return
|
|
5885
|
+
function __rewriteRelativeImportExtension(path22, preserveJsx) {
|
|
5886
|
+
if (typeof path22 === "string" && /^\.\.?\//.test(path22)) {
|
|
5887
|
+
return path22.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
5659
5888
|
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
5660
5889
|
});
|
|
5661
5890
|
}
|
|
5662
|
-
return
|
|
5891
|
+
return path22;
|
|
5663
5892
|
}
|
|
5664
5893
|
var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
|
|
5665
5894
|
var init_tslib_es6 = __esm({
|
|
@@ -14297,8 +14526,8 @@ var require_RealtimeChannel = __commonJS({
|
|
|
14297
14526
|
}
|
|
14298
14527
|
/** @internal */
|
|
14299
14528
|
_notThisChannelEvent(event, ref) {
|
|
14300
|
-
const { close, error, leave, join:
|
|
14301
|
-
const events = [close, error, leave,
|
|
14529
|
+
const { close, error, leave, join: join56 } = constants_1.CHANNEL_EVENTS;
|
|
14530
|
+
const events = [close, error, leave, join56];
|
|
14302
14531
|
return ref && events.includes(event) && ref !== this.joinPush.ref;
|
|
14303
14532
|
}
|
|
14304
14533
|
/** @internal */
|
|
@@ -15181,8 +15410,8 @@ var require_main2 = __commonJS({
|
|
|
15181
15410
|
});
|
|
15182
15411
|
|
|
15183
15412
|
// ../../node_modules/.pnpm/iceberg-js@0.8.1/node_modules/iceberg-js/dist/index.mjs
|
|
15184
|
-
function buildUrl2(baseUrl3,
|
|
15185
|
-
const url = new URL(
|
|
15413
|
+
function buildUrl2(baseUrl3, path22, query) {
|
|
15414
|
+
const url = new URL(path22, baseUrl3);
|
|
15186
15415
|
if (query) {
|
|
15187
15416
|
for (const [key, value] of Object.entries(query)) {
|
|
15188
15417
|
if (value !== void 0) {
|
|
@@ -15212,12 +15441,12 @@ function createFetchClient(options) {
|
|
|
15212
15441
|
return {
|
|
15213
15442
|
async request({
|
|
15214
15443
|
method,
|
|
15215
|
-
path:
|
|
15444
|
+
path: path22,
|
|
15216
15445
|
query,
|
|
15217
15446
|
body,
|
|
15218
15447
|
headers
|
|
15219
15448
|
}) {
|
|
15220
|
-
const url = buildUrl2(options.baseUrl,
|
|
15449
|
+
const url = buildUrl2(options.baseUrl, path22, query);
|
|
15221
15450
|
const authHeaders = await buildAuthHeaders(options.auth);
|
|
15222
15451
|
const res = await fetchFn(url, {
|
|
15223
15452
|
method,
|
|
@@ -16115,7 +16344,7 @@ var init_dist3 = __esm({
|
|
|
16115
16344
|
* @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
|
|
16116
16345
|
* @param fileBody The body of the file to be stored in the bucket.
|
|
16117
16346
|
*/
|
|
16118
|
-
async uploadOrUpdate(method,
|
|
16347
|
+
async uploadOrUpdate(method, path22, fileBody, fileOptions) {
|
|
16119
16348
|
var _this = this;
|
|
16120
16349
|
return _this.handleOperation(async () => {
|
|
16121
16350
|
let body;
|
|
@@ -16139,7 +16368,7 @@ var init_dist3 = __esm({
|
|
|
16139
16368
|
if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
|
|
16140
16369
|
}
|
|
16141
16370
|
if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
|
|
16142
|
-
const cleanPath = _this._removeEmptyFolders(
|
|
16371
|
+
const cleanPath = _this._removeEmptyFolders(path22);
|
|
16143
16372
|
const _path = _this._getFinalPath(cleanPath);
|
|
16144
16373
|
const data = await (method == "PUT" ? put : post)(_this.fetch, `${_this.url}/object/${_path}`, body, _objectSpread22({ headers }, (options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}));
|
|
16145
16374
|
return {
|
|
@@ -16201,8 +16430,8 @@ var init_dist3 = __esm({
|
|
|
16201
16430
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16202
16431
|
* - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.
|
|
16203
16432
|
*/
|
|
16204
|
-
async upload(
|
|
16205
|
-
return this.uploadOrUpdate("POST",
|
|
16433
|
+
async upload(path22, fileBody, fileOptions) {
|
|
16434
|
+
return this.uploadOrUpdate("POST", path22, fileBody, fileOptions);
|
|
16206
16435
|
}
|
|
16207
16436
|
/**
|
|
16208
16437
|
* Upload a file with a token generated from `createSignedUploadUrl`.
|
|
@@ -16242,9 +16471,9 @@ var init_dist3 = __esm({
|
|
|
16242
16471
|
* - `objects` table permissions: none
|
|
16243
16472
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16244
16473
|
*/
|
|
16245
|
-
async uploadToSignedUrl(
|
|
16474
|
+
async uploadToSignedUrl(path22, token, fileBody, fileOptions) {
|
|
16246
16475
|
var _this3 = this;
|
|
16247
|
-
const cleanPath = _this3._removeEmptyFolders(
|
|
16476
|
+
const cleanPath = _this3._removeEmptyFolders(path22);
|
|
16248
16477
|
const _path = _this3._getFinalPath(cleanPath);
|
|
16249
16478
|
const url = new URL(_this3.url + `/object/upload/sign/${_path}`);
|
|
16250
16479
|
url.searchParams.set("token", token);
|
|
@@ -16313,10 +16542,10 @@ var init_dist3 = __esm({
|
|
|
16313
16542
|
* - `objects` table permissions: `insert`
|
|
16314
16543
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16315
16544
|
*/
|
|
16316
|
-
async createSignedUploadUrl(
|
|
16545
|
+
async createSignedUploadUrl(path22, options) {
|
|
16317
16546
|
var _this4 = this;
|
|
16318
16547
|
return _this4.handleOperation(async () => {
|
|
16319
|
-
let _path = _this4._getFinalPath(
|
|
16548
|
+
let _path = _this4._getFinalPath(path22);
|
|
16320
16549
|
const headers = _objectSpread22({}, _this4.headers);
|
|
16321
16550
|
if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
|
|
16322
16551
|
const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
|
|
@@ -16325,7 +16554,7 @@ var init_dist3 = __esm({
|
|
|
16325
16554
|
if (!token) throw new StorageError("No token returned by API");
|
|
16326
16555
|
return {
|
|
16327
16556
|
signedUrl: url.toString(),
|
|
16328
|
-
path:
|
|
16557
|
+
path: path22,
|
|
16329
16558
|
token
|
|
16330
16559
|
};
|
|
16331
16560
|
});
|
|
@@ -16385,8 +16614,8 @@ var init_dist3 = __esm({
|
|
|
16385
16614
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16386
16615
|
* - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.
|
|
16387
16616
|
*/
|
|
16388
|
-
async update(
|
|
16389
|
-
return this.uploadOrUpdate("PUT",
|
|
16617
|
+
async update(path22, fileBody, fileOptions) {
|
|
16618
|
+
return this.uploadOrUpdate("PUT", path22, fileBody, fileOptions);
|
|
16390
16619
|
}
|
|
16391
16620
|
/**
|
|
16392
16621
|
* Moves an existing file to a new path in the same bucket.
|
|
@@ -16537,10 +16766,10 @@ var init_dist3 = __esm({
|
|
|
16537
16766
|
* - `objects` table permissions: `select`
|
|
16538
16767
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16539
16768
|
*/
|
|
16540
|
-
async createSignedUrl(
|
|
16769
|
+
async createSignedUrl(path22, expiresIn, options) {
|
|
16541
16770
|
var _this8 = this;
|
|
16542
16771
|
return _this8.handleOperation(async () => {
|
|
16543
|
-
let _path = _this8._getFinalPath(
|
|
16772
|
+
let _path = _this8._getFinalPath(path22);
|
|
16544
16773
|
const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
|
|
16545
16774
|
let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread22({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
|
|
16546
16775
|
const query = new URLSearchParams();
|
|
@@ -16676,13 +16905,13 @@ var init_dist3 = __esm({
|
|
|
16676
16905
|
* - `objects` table permissions: `select`
|
|
16677
16906
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16678
16907
|
*/
|
|
16679
|
-
download(
|
|
16908
|
+
download(path22, options, parameters) {
|
|
16680
16909
|
const renderPath = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0 ? "render/image/authenticated" : "object";
|
|
16681
16910
|
const query = new URLSearchParams();
|
|
16682
16911
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
16683
16912
|
if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
|
|
16684
16913
|
const queryString = query.toString();
|
|
16685
|
-
const _path = this._getFinalPath(
|
|
16914
|
+
const _path = this._getFinalPath(path22);
|
|
16686
16915
|
const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
|
|
16687
16916
|
headers: this.headers,
|
|
16688
16917
|
noResolveJson: true
|
|
@@ -16713,9 +16942,9 @@ var init_dist3 = __esm({
|
|
|
16713
16942
|
* }
|
|
16714
16943
|
* ```
|
|
16715
16944
|
*/
|
|
16716
|
-
async info(
|
|
16945
|
+
async info(path22) {
|
|
16717
16946
|
var _this10 = this;
|
|
16718
|
-
const _path = _this10._getFinalPath(
|
|
16947
|
+
const _path = _this10._getFinalPath(path22);
|
|
16719
16948
|
return _this10.handleOperation(async () => {
|
|
16720
16949
|
return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
|
|
16721
16950
|
});
|
|
@@ -16736,9 +16965,9 @@ var init_dist3 = __esm({
|
|
|
16736
16965
|
* .exists('folder/avatar1.png')
|
|
16737
16966
|
* ```
|
|
16738
16967
|
*/
|
|
16739
|
-
async exists(
|
|
16968
|
+
async exists(path22) {
|
|
16740
16969
|
var _this11 = this;
|
|
16741
|
-
const _path = _this11._getFinalPath(
|
|
16970
|
+
const _path = _this11._getFinalPath(path22);
|
|
16742
16971
|
try {
|
|
16743
16972
|
await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
|
|
16744
16973
|
return {
|
|
@@ -16817,8 +17046,8 @@ var init_dist3 = __esm({
|
|
|
16817
17046
|
* - `objects` table permissions: none
|
|
16818
17047
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16819
17048
|
*/
|
|
16820
|
-
getPublicUrl(
|
|
16821
|
-
const _path = this._getFinalPath(
|
|
17049
|
+
getPublicUrl(path22, options) {
|
|
17050
|
+
const _path = this._getFinalPath(path22);
|
|
16822
17051
|
const query = new URLSearchParams();
|
|
16823
17052
|
if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
|
|
16824
17053
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
@@ -16957,10 +17186,10 @@ var init_dist3 = __esm({
|
|
|
16957
17186
|
* - `objects` table permissions: `select`
|
|
16958
17187
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16959
17188
|
*/
|
|
16960
|
-
async list(
|
|
17189
|
+
async list(path22, options, parameters) {
|
|
16961
17190
|
var _this13 = this;
|
|
16962
17191
|
return _this13.handleOperation(async () => {
|
|
16963
|
-
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix:
|
|
17192
|
+
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path22 || "" });
|
|
16964
17193
|
return await post(_this13.fetch, `${_this13.url}/object/list/${_this13.bucketId}`, body, { headers: _this13.headers }, parameters);
|
|
16965
17194
|
});
|
|
16966
17195
|
}
|
|
@@ -17025,11 +17254,11 @@ var init_dist3 = __esm({
|
|
|
17025
17254
|
if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
|
|
17026
17255
|
return btoa(data);
|
|
17027
17256
|
}
|
|
17028
|
-
_getFinalPath(
|
|
17029
|
-
return `${this.bucketId}/${
|
|
17257
|
+
_getFinalPath(path22) {
|
|
17258
|
+
return `${this.bucketId}/${path22.replace(/^\/+/, "")}`;
|
|
17030
17259
|
}
|
|
17031
|
-
_removeEmptyFolders(
|
|
17032
|
-
return
|
|
17260
|
+
_removeEmptyFolders(path22) {
|
|
17261
|
+
return path22.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
|
|
17033
17262
|
}
|
|
17034
17263
|
/** Modifies the `query`, appending values the from `transform` */
|
|
17035
17264
|
applyTransformOptsToQuery(query, transform) {
|
|
@@ -27446,8 +27675,8 @@ __export(watch_exports, {
|
|
|
27446
27675
|
runWatchCommand: () => runWatchCommand
|
|
27447
27676
|
});
|
|
27448
27677
|
import { spawn as spawn2 } from "node:child_process";
|
|
27449
|
-
import { mkdir as mkdir8, readFile as
|
|
27450
|
-
import { join as
|
|
27678
|
+
import { mkdir as mkdir8, readFile as readFile17, unlink as unlink4, writeFile as writeFile14 } from "node:fs/promises";
|
|
27679
|
+
import { join as join20 } from "node:path";
|
|
27451
27680
|
async function resolveIdentity() {
|
|
27452
27681
|
const found = await findCodebyplanConfig(process.cwd());
|
|
27453
27682
|
const repoId = found?.contents.repo_id;
|
|
@@ -27467,18 +27696,18 @@ async function resolveIdentity() {
|
|
|
27467
27696
|
return { repoRoot, repoId, worktreeId };
|
|
27468
27697
|
}
|
|
27469
27698
|
function watchDir(repoRoot) {
|
|
27470
|
-
return
|
|
27699
|
+
return join20(repoRoot, ".codebyplan", "state", "_watch");
|
|
27471
27700
|
}
|
|
27472
27701
|
function pidFilePath(repoRoot, worktreeId) {
|
|
27473
|
-
return
|
|
27702
|
+
return join20(watchDir(repoRoot), `${worktreeId ?? "default"}.pid`);
|
|
27474
27703
|
}
|
|
27475
27704
|
function healthFilePath(repoRoot, worktreeId) {
|
|
27476
|
-
return
|
|
27705
|
+
return join20(watchDir(repoRoot), `${worktreeId ?? "default"}.health.json`);
|
|
27477
27706
|
}
|
|
27478
27707
|
async function handleStart(repoRoot, repoId, worktreeId, forwardArgs) {
|
|
27479
27708
|
const pidFile = pidFilePath(repoRoot, worktreeId);
|
|
27480
27709
|
try {
|
|
27481
|
-
const pidStr = await
|
|
27710
|
+
const pidStr = await readFile17(pidFile, "utf-8");
|
|
27482
27711
|
const pid = parseInt(pidStr.trim(), 10);
|
|
27483
27712
|
if (!isNaN(pid)) {
|
|
27484
27713
|
try {
|
|
@@ -27498,7 +27727,7 @@ async function handleStart(repoRoot, repoId, worktreeId, forwardArgs) {
|
|
|
27498
27727
|
}
|
|
27499
27728
|
const lockFile = `${pidFile}.lock`;
|
|
27500
27729
|
try {
|
|
27501
|
-
await
|
|
27730
|
+
await writeFile14(lockFile, String(process.pid), { flag: "wx" });
|
|
27502
27731
|
} catch {
|
|
27503
27732
|
process.stdout.write("watch: start already in progress\n");
|
|
27504
27733
|
process.exit(0);
|
|
@@ -27515,7 +27744,7 @@ async function handleStart(repoRoot, repoId, worktreeId, forwardArgs) {
|
|
|
27515
27744
|
child.unref();
|
|
27516
27745
|
if (child.pid !== void 0) {
|
|
27517
27746
|
try {
|
|
27518
|
-
await
|
|
27747
|
+
await writeFile14(pidFile, String(child.pid), "utf-8");
|
|
27519
27748
|
} catch {
|
|
27520
27749
|
}
|
|
27521
27750
|
process.stdout.write(`watch: daemon started (pid ${child.pid})
|
|
@@ -27535,7 +27764,7 @@ async function handleStop(repoRoot, worktreeId) {
|
|
|
27535
27764
|
const healthFile = healthFilePath(repoRoot, worktreeId);
|
|
27536
27765
|
let pid;
|
|
27537
27766
|
try {
|
|
27538
|
-
const pidStr = await
|
|
27767
|
+
const pidStr = await readFile17(pidFile, "utf-8");
|
|
27539
27768
|
pid = parseInt(pidStr.trim(), 10);
|
|
27540
27769
|
if (isNaN(pid)) throw new Error("invalid pid in pidfile");
|
|
27541
27770
|
} catch (err) {
|
|
@@ -27571,7 +27800,7 @@ async function handleStatus(repoRoot, worktreeId, subArgs) {
|
|
|
27571
27800
|
let pid = null;
|
|
27572
27801
|
let alive = false;
|
|
27573
27802
|
try {
|
|
27574
|
-
const pidStr = await
|
|
27803
|
+
const pidStr = await readFile17(pidFile, "utf-8");
|
|
27575
27804
|
const parsed = parseInt(pidStr.trim(), 10);
|
|
27576
27805
|
if (!isNaN(parsed)) {
|
|
27577
27806
|
pid = parsed;
|
|
@@ -27586,7 +27815,7 @@ async function handleStatus(repoRoot, worktreeId, subArgs) {
|
|
|
27586
27815
|
}
|
|
27587
27816
|
let health = null;
|
|
27588
27817
|
try {
|
|
27589
|
-
const raw = await
|
|
27818
|
+
const raw = await readFile17(healthFile, "utf-8");
|
|
27590
27819
|
health = JSON.parse(raw);
|
|
27591
27820
|
} catch {
|
|
27592
27821
|
}
|
|
@@ -27610,7 +27839,7 @@ async function handleRun(repoRoot, repoId, worktreeId) {
|
|
|
27610
27839
|
const healthFile = healthFilePath(repoRoot, worktreeId);
|
|
27611
27840
|
try {
|
|
27612
27841
|
await mkdir8(watchDir(repoRoot), { recursive: true });
|
|
27613
|
-
await
|
|
27842
|
+
await writeFile14(pidFile, String(process.pid), "utf-8");
|
|
27614
27843
|
} catch (err) {
|
|
27615
27844
|
process.stderr.write(
|
|
27616
27845
|
`watch: could not write pidfile: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -27659,7 +27888,7 @@ async function handleRun(repoRoot, repoId, worktreeId) {
|
|
|
27659
27888
|
worktree_id: worktreeId ?? null,
|
|
27660
27889
|
repo_id: repoId
|
|
27661
27890
|
};
|
|
27662
|
-
void
|
|
27891
|
+
void writeFile14(
|
|
27663
27892
|
healthFile,
|
|
27664
27893
|
JSON.stringify(data, null, 2) + "\n",
|
|
27665
27894
|
"utf-8"
|
|
@@ -27748,8 +27977,8 @@ var init_watch = __esm({
|
|
|
27748
27977
|
});
|
|
27749
27978
|
|
|
27750
27979
|
// src/lib/state-client.ts
|
|
27751
|
-
async function backendRequest(method,
|
|
27752
|
-
const url = `${getBackendBase()}${
|
|
27980
|
+
async function backendRequest(method, path22, body) {
|
|
27981
|
+
const url = `${getBackendBase()}${path22}`;
|
|
27753
27982
|
const auth = await getAuthHeaders();
|
|
27754
27983
|
const res = await fetch(url, {
|
|
27755
27984
|
method,
|
|
@@ -27761,7 +27990,7 @@ async function backendRequest(method, path21, body) {
|
|
|
27761
27990
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
27762
27991
|
});
|
|
27763
27992
|
if (!res.ok) {
|
|
27764
|
-
let message = `Backend ${method} ${
|
|
27993
|
+
let message = `Backend ${method} ${path22} failed with status ${res.status}`;
|
|
27765
27994
|
try {
|
|
27766
27995
|
const errBody = await res.json();
|
|
27767
27996
|
const msg = typeof errBody.message === "string" ? errBody.message : typeof errBody.error === "string" ? errBody.error : void 0;
|
|
@@ -27775,11 +28004,11 @@ async function backendRequest(method, path21, body) {
|
|
|
27775
28004
|
}
|
|
27776
28005
|
return res.json();
|
|
27777
28006
|
}
|
|
27778
|
-
async function apiBackendPost(
|
|
27779
|
-
return backendRequest("POST",
|
|
28007
|
+
async function apiBackendPost(path22, body) {
|
|
28008
|
+
return backendRequest("POST", path22, body);
|
|
27780
28009
|
}
|
|
27781
|
-
async function apiBackendPatch(
|
|
27782
|
-
return backendRequest("PATCH",
|
|
28010
|
+
async function apiBackendPatch(path22, body) {
|
|
28011
|
+
return backendRequest("PATCH", path22, body);
|
|
27783
28012
|
}
|
|
27784
28013
|
var REQUEST_TIMEOUT_MS2, BackendError;
|
|
27785
28014
|
var init_state_client = __esm({
|
|
@@ -28539,7 +28768,7 @@ __export(round_exports, {
|
|
|
28539
28768
|
setRetryDelayMs: () => setRetryDelayMs
|
|
28540
28769
|
});
|
|
28541
28770
|
import { access as access4 } from "node:fs/promises";
|
|
28542
|
-
import { join as
|
|
28771
|
+
import { join as join21 } from "node:path";
|
|
28543
28772
|
import { execSync as execSync3 } from "node:child_process";
|
|
28544
28773
|
function setRetryDelayMs(ms) {
|
|
28545
28774
|
RETRY_DELAY_MS = ms;
|
|
@@ -28919,7 +29148,7 @@ async function runRoundSyncApprovals(args) {
|
|
|
28919
29148
|
"sync-approvals: git status failed; proceeding with empty diff\n"
|
|
28920
29149
|
);
|
|
28921
29150
|
}
|
|
28922
|
-
const hookPath =
|
|
29151
|
+
const hookPath = join21(
|
|
28923
29152
|
repoRoot,
|
|
28924
29153
|
".claude",
|
|
28925
29154
|
"hooks",
|
|
@@ -29588,8 +29817,8 @@ var init_session = __esm({
|
|
|
29588
29817
|
});
|
|
29589
29818
|
|
|
29590
29819
|
// src/lib/migrate-branch-model.ts
|
|
29591
|
-
import { readFile as
|
|
29592
|
-
import { join as
|
|
29820
|
+
import { readFile as readFile18, writeFile as writeFile15 } from "node:fs/promises";
|
|
29821
|
+
import { join as join22 } from "node:path";
|
|
29593
29822
|
import { execSync as execSync4 } from "node:child_process";
|
|
29594
29823
|
function assertValidBranchName(branch) {
|
|
29595
29824
|
if (!/^[a-zA-Z0-9/_.-]+$/.test(branch)) {
|
|
@@ -29599,7 +29828,7 @@ function assertValidBranchName(branch) {
|
|
|
29599
29828
|
}
|
|
29600
29829
|
}
|
|
29601
29830
|
async function readJsonFile2(filePath) {
|
|
29602
|
-
const raw = await
|
|
29831
|
+
const raw = await readFile18(filePath, "utf-8");
|
|
29603
29832
|
const parsed = JSON.parse(raw);
|
|
29604
29833
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
29605
29834
|
throw new Error(`${filePath} does not contain a JSON object`);
|
|
@@ -29668,12 +29897,12 @@ async function runBranchMigration(opts) {
|
|
|
29668
29897
|
if (found) {
|
|
29669
29898
|
if (found.path.endsWith("/repo.json")) {
|
|
29670
29899
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
29671
|
-
configPath =
|
|
29900
|
+
configPath = join22(dir, "git.json");
|
|
29672
29901
|
} else {
|
|
29673
29902
|
configPath = found.path;
|
|
29674
29903
|
}
|
|
29675
29904
|
} else {
|
|
29676
|
-
configPath =
|
|
29905
|
+
configPath = join22(cwd, ".codebyplan", "git.json");
|
|
29677
29906
|
}
|
|
29678
29907
|
let fileRaw;
|
|
29679
29908
|
let fileParsed;
|
|
@@ -29747,7 +29976,7 @@ async function runBranchMigration(opts) {
|
|
|
29747
29976
|
const updatedParsed = { ...fileParsed, branch_config: after };
|
|
29748
29977
|
const newJson = JSON.stringify(updatedParsed, null, 2) + "\n";
|
|
29749
29978
|
if (newJson !== fileRaw) {
|
|
29750
|
-
await
|
|
29979
|
+
await writeFile15(configPath, newJson, "utf-8");
|
|
29751
29980
|
}
|
|
29752
29981
|
}
|
|
29753
29982
|
return {
|
|
@@ -29768,10 +29997,10 @@ var init_migrate_branch_model = __esm({
|
|
|
29768
29997
|
|
|
29769
29998
|
// src/lib/supabase.ts
|
|
29770
29999
|
import * as fs5 from "node:fs";
|
|
29771
|
-
import * as
|
|
29772
|
-
import { spawnSync as
|
|
30000
|
+
import * as path7 from "node:path";
|
|
30001
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
29773
30002
|
function defaultRun(cmd, args) {
|
|
29774
|
-
const result =
|
|
30003
|
+
const result = spawnSync6(cmd, args, {
|
|
29775
30004
|
encoding: "utf-8",
|
|
29776
30005
|
stdio: ["pipe", "pipe", "pipe"]
|
|
29777
30006
|
});
|
|
@@ -29848,7 +30077,7 @@ function extractStampToken(filename) {
|
|
|
29848
30077
|
}
|
|
29849
30078
|
function readShipmentConfig(cwd) {
|
|
29850
30079
|
const dir = cwd ?? process.cwd();
|
|
29851
|
-
const obj = readJsonFile3(
|
|
30080
|
+
const obj = readJsonFile3(path7.join(dir, ".codebyplan", "shipment.json"));
|
|
29852
30081
|
if (!obj) return { parentRef: null, previewBranches: [] };
|
|
29853
30082
|
const section = getSupabaseSection(obj);
|
|
29854
30083
|
if (!section) return { parentRef: null, previewBranches: [] };
|
|
@@ -29872,7 +30101,7 @@ function readShipmentConfig(cwd) {
|
|
|
29872
30101
|
}
|
|
29873
30102
|
function readGitConfig(cwd) {
|
|
29874
30103
|
const dir = cwd ?? process.cwd();
|
|
29875
|
-
const obj = readJsonFile3(
|
|
30104
|
+
const obj = readJsonFile3(path7.join(dir, ".codebyplan", "git.json"));
|
|
29876
30105
|
if (!obj) return { ...GIT_DEFAULTS };
|
|
29877
30106
|
const bc = obj["branch_config"];
|
|
29878
30107
|
if (typeof bc !== "object" || bc === null || Array.isArray(bc)) {
|
|
@@ -29893,7 +30122,7 @@ function readGitConfig(cwd) {
|
|
|
29893
30122
|
}
|
|
29894
30123
|
function readDbPaths(cwd) {
|
|
29895
30124
|
const dir = cwd ?? process.cwd();
|
|
29896
|
-
const obj = readJsonFile3(
|
|
30125
|
+
const obj = readJsonFile3(path7.join(dir, ".codebyplan", "shipment.json"));
|
|
29897
30126
|
if (!obj) return [...DEFAULT_DB_PATHS];
|
|
29898
30127
|
const section = getSupabaseSection(obj);
|
|
29899
30128
|
if (!section) return [...DEFAULT_DB_PATHS];
|
|
@@ -29933,7 +30162,7 @@ function generateMonotonicTimestamp(opts = {}) {
|
|
|
29933
30162
|
const cwd = opts.cwd ?? process.cwd();
|
|
29934
30163
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
29935
30164
|
const listDir = opts.listDir ?? defaultListDir;
|
|
29936
|
-
const migrationsDir =
|
|
30165
|
+
const migrationsDir = path7.join(cwd, "supabase", "migrations");
|
|
29937
30166
|
const files = listDir(migrationsDir);
|
|
29938
30167
|
const existingStamps = /* @__PURE__ */ new Set();
|
|
29939
30168
|
for (const file of files) {
|
|
@@ -30080,9 +30309,9 @@ var init_supabase = __esm({
|
|
|
30080
30309
|
});
|
|
30081
30310
|
|
|
30082
30311
|
// src/lib/branch-checkout.ts
|
|
30083
|
-
import { spawnSync as
|
|
30312
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
30084
30313
|
function defaultRun2(cmd, args, cwd) {
|
|
30085
|
-
const result =
|
|
30314
|
+
const result = spawnSync7(cmd, args, {
|
|
30086
30315
|
cwd,
|
|
30087
30316
|
encoding: "utf-8",
|
|
30088
30317
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30332,9 +30561,9 @@ var init_branch = __esm({
|
|
|
30332
30561
|
});
|
|
30333
30562
|
|
|
30334
30563
|
// src/lib/bump.ts
|
|
30335
|
-
import { readFile as
|
|
30336
|
-
import { join as
|
|
30337
|
-
import { spawnSync as
|
|
30564
|
+
import { readFile as readFile19, writeFile as writeFile16, access as access5, readdir as readdir4 } from "node:fs/promises";
|
|
30565
|
+
import { join as join24, relative as relative5, resolve as resolve3 } from "node:path";
|
|
30566
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
30338
30567
|
function parsePnpmWorkspaceGlobs(raw) {
|
|
30339
30568
|
const lines = raw.split("\n");
|
|
30340
30569
|
const globs = [];
|
|
@@ -30363,18 +30592,18 @@ async function expandGlob(cwd, glob) {
|
|
|
30363
30592
|
if (parts.length !== 2 || parts[1] !== "*") {
|
|
30364
30593
|
return [];
|
|
30365
30594
|
}
|
|
30366
|
-
const parentDir =
|
|
30595
|
+
const parentDir = join24(cwd, parts[0]);
|
|
30367
30596
|
let dirs;
|
|
30368
30597
|
try {
|
|
30369
30598
|
const entries = await readdir4(parentDir, { withFileTypes: true });
|
|
30370
|
-
dirs = entries.filter((e) => e.isDirectory()).map((e) =>
|
|
30599
|
+
dirs = entries.filter((e) => e.isDirectory()).map((e) => join24(parentDir, e.name));
|
|
30371
30600
|
} catch {
|
|
30372
30601
|
return [];
|
|
30373
30602
|
}
|
|
30374
30603
|
const results = [];
|
|
30375
30604
|
for (const dir of dirs) {
|
|
30376
30605
|
try {
|
|
30377
|
-
await access5(
|
|
30606
|
+
await access5(join24(dir, "package.json"));
|
|
30378
30607
|
results.push(dir);
|
|
30379
30608
|
} catch {
|
|
30380
30609
|
}
|
|
@@ -30385,7 +30614,7 @@ async function buildPackageMap(cwd) {
|
|
|
30385
30614
|
const map = /* @__PURE__ */ new Map();
|
|
30386
30615
|
let globs = [];
|
|
30387
30616
|
try {
|
|
30388
|
-
const raw = await
|
|
30617
|
+
const raw = await readFile19(join24(cwd, "pnpm-workspace.yaml"), "utf-8");
|
|
30389
30618
|
globs = parsePnpmWorkspaceGlobs(raw);
|
|
30390
30619
|
} catch {
|
|
30391
30620
|
}
|
|
@@ -30393,7 +30622,7 @@ async function buildPackageMap(cwd) {
|
|
|
30393
30622
|
const dirs = await expandGlob(cwd, glob);
|
|
30394
30623
|
for (const dir of dirs) {
|
|
30395
30624
|
try {
|
|
30396
|
-
const pkgRaw = await
|
|
30625
|
+
const pkgRaw = await readFile19(join24(dir, "package.json"), "utf-8");
|
|
30397
30626
|
const pkg = JSON.parse(pkgRaw);
|
|
30398
30627
|
const name = pkg.name ?? relative5(cwd, dir);
|
|
30399
30628
|
map.set(dir, { name, dir });
|
|
@@ -30471,7 +30700,7 @@ function compareSemver(a, b) {
|
|
|
30471
30700
|
return 0;
|
|
30472
30701
|
}
|
|
30473
30702
|
function gitShowFile(cwd, ref, relPath) {
|
|
30474
|
-
const result =
|
|
30703
|
+
const result = spawnSync8("git", ["show", `${ref}:${relPath}`], {
|
|
30475
30704
|
cwd,
|
|
30476
30705
|
encoding: "utf-8",
|
|
30477
30706
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30512,7 +30741,7 @@ function injectVersion(raw, nextVersion, filePath) {
|
|
|
30512
30741
|
async function prependChangelog(changelogPath, packageName, nextVersion, now, dryRun) {
|
|
30513
30742
|
let existing;
|
|
30514
30743
|
try {
|
|
30515
|
-
existing = await
|
|
30744
|
+
existing = await readFile19(changelogPath, "utf-8");
|
|
30516
30745
|
} catch {
|
|
30517
30746
|
return false;
|
|
30518
30747
|
}
|
|
@@ -30525,7 +30754,7 @@ async function prependChangelog(changelogPath, packageName, nextVersion, now, dr
|
|
|
30525
30754
|
`;
|
|
30526
30755
|
const updated = entry + existing;
|
|
30527
30756
|
if (!dryRun) {
|
|
30528
|
-
await
|
|
30757
|
+
await writeFile16(changelogPath, updated, "utf-8");
|
|
30529
30758
|
}
|
|
30530
30759
|
return true;
|
|
30531
30760
|
}
|
|
@@ -30536,7 +30765,7 @@ async function runBump(opts) {
|
|
|
30536
30765
|
const prereleaseId = opts?.prereleaseId;
|
|
30537
30766
|
const baseBranch = await readBaseBranch(cwd);
|
|
30538
30767
|
const baseRef = resolveBaseRef(cwd, baseBranch);
|
|
30539
|
-
const diffResult =
|
|
30768
|
+
const diffResult = spawnSync8(
|
|
30540
30769
|
"git",
|
|
30541
30770
|
["diff", "--name-only", `${baseRef}...HEAD`],
|
|
30542
30771
|
{
|
|
@@ -30552,7 +30781,7 @@ async function runBump(opts) {
|
|
|
30552
30781
|
const changedFiles = (diffResult.stdout ?? "").trim().split("\n").filter(Boolean).map((f) => resolve3(cwd, f));
|
|
30553
30782
|
const packageMap = await buildPackageMap(cwd);
|
|
30554
30783
|
const packageDirs = Array.from(packageMap.keys());
|
|
30555
|
-
const rootPkgPath =
|
|
30784
|
+
const rootPkgPath = join24(cwd, "package.json");
|
|
30556
30785
|
const changedPackageDirs = /* @__PURE__ */ new Set();
|
|
30557
30786
|
for (const absFile of changedFiles) {
|
|
30558
30787
|
const owner = findOwningPackage(absFile, packageDirs);
|
|
@@ -30563,19 +30792,19 @@ async function runBump(opts) {
|
|
|
30563
30792
|
const entries = [];
|
|
30564
30793
|
for (const pkgDir of changedPackageDirs) {
|
|
30565
30794
|
const pkgInfo = packageMap.get(pkgDir);
|
|
30566
|
-
const pkgJsonPath =
|
|
30795
|
+
const pkgJsonPath = join24(pkgDir, "package.json");
|
|
30567
30796
|
if (pkgJsonPath === rootPkgPath) continue;
|
|
30568
30797
|
const versionFileCandidates = [
|
|
30569
30798
|
{ abs: pkgJsonPath, rel: relative5(cwd, pkgJsonPath).replace(/\\/g, "/") }
|
|
30570
30799
|
];
|
|
30571
|
-
const tauriConfPath =
|
|
30800
|
+
const tauriConfPath = join24(pkgDir, "src-tauri", "tauri.conf.json");
|
|
30572
30801
|
const tauriRelPath = relative5(cwd, tauriConfPath).replace(/\\/g, "/");
|
|
30573
30802
|
try {
|
|
30574
30803
|
await access5(tauriConfPath);
|
|
30575
30804
|
versionFileCandidates.push({ abs: tauriConfPath, rel: tauriRelPath });
|
|
30576
30805
|
} catch {
|
|
30577
30806
|
}
|
|
30578
|
-
const appJsonPath =
|
|
30807
|
+
const appJsonPath = join24(pkgDir, "app.json");
|
|
30579
30808
|
const appJsonRelPath = relative5(cwd, appJsonPath).replace(/\\/g, "/");
|
|
30580
30809
|
try {
|
|
30581
30810
|
await access5(appJsonPath);
|
|
@@ -30584,7 +30813,7 @@ async function runBump(opts) {
|
|
|
30584
30813
|
}
|
|
30585
30814
|
let currentPkgJsonRaw;
|
|
30586
30815
|
try {
|
|
30587
|
-
currentPkgJsonRaw = await
|
|
30816
|
+
currentPkgJsonRaw = await readFile19(pkgJsonPath, "utf-8");
|
|
30588
30817
|
} catch (err) {
|
|
30589
30818
|
console.warn(
|
|
30590
30819
|
`runBump: could not read ${pkgJsonPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -30629,7 +30858,7 @@ async function runBump(opts) {
|
|
|
30629
30858
|
for (const { abs, rel } of versionFileCandidates) {
|
|
30630
30859
|
let raw;
|
|
30631
30860
|
try {
|
|
30632
|
-
raw = await
|
|
30861
|
+
raw = await readFile19(abs, "utf-8");
|
|
30633
30862
|
} catch {
|
|
30634
30863
|
continue;
|
|
30635
30864
|
}
|
|
@@ -30643,11 +30872,11 @@ async function runBump(opts) {
|
|
|
30643
30872
|
}
|
|
30644
30873
|
const updated = injectVersion(raw, nextVersion, abs);
|
|
30645
30874
|
if (!dryRun) {
|
|
30646
|
-
await
|
|
30875
|
+
await writeFile16(abs, updated, "utf-8");
|
|
30647
30876
|
}
|
|
30648
30877
|
updatedVersionFiles.push(rel);
|
|
30649
30878
|
}
|
|
30650
|
-
const changelogPath =
|
|
30879
|
+
const changelogPath = join24(pkgDir, "CHANGELOG.md");
|
|
30651
30880
|
const changelogUpdated = await prependChangelog(
|
|
30652
30881
|
changelogPath,
|
|
30653
30882
|
pkgInfo.name,
|
|
@@ -30757,7 +30986,7 @@ var init_bump2 = __esm({
|
|
|
30757
30986
|
});
|
|
30758
30987
|
|
|
30759
30988
|
// src/lib/ship.ts
|
|
30760
|
-
import { execSync as execSync5, spawnSync as
|
|
30989
|
+
import { execSync as execSync5, spawnSync as spawnSync9 } from "node:child_process";
|
|
30761
30990
|
import { relative as relative6 } from "node:path";
|
|
30762
30991
|
function assertValidBranchName2(branch, label) {
|
|
30763
30992
|
if (!/^[a-zA-Z0-9/_.-]+$/.test(branch)) {
|
|
@@ -30789,7 +31018,7 @@ async function pollChecks(feat, timeoutSeconds, cwd, _sleepMs = (ms) => new Prom
|
|
|
30789
31018
|
let totalGhErrors = 0;
|
|
30790
31019
|
let iteration = 0;
|
|
30791
31020
|
while (Date.now() < deadline) {
|
|
30792
|
-
const ghResult =
|
|
31021
|
+
const ghResult = spawnSync9(
|
|
30793
31022
|
"gh",
|
|
30794
31023
|
["pr", "checks", feat, "--json", "name,state,bucket"],
|
|
30795
31024
|
{
|
|
@@ -30940,7 +31169,7 @@ ${statusOut.trim()}`
|
|
|
30940
31169
|
...e.changelogUpdated ? [relative6(cwd, e.packageDir).replace(/\\/g, "/") + "/CHANGELOG.md"] : []
|
|
30941
31170
|
]);
|
|
30942
31171
|
if (toStage.length > 0) {
|
|
30943
|
-
const addResult =
|
|
31172
|
+
const addResult = spawnSync9("git", ["add", "--", ...toStage], {
|
|
30944
31173
|
cwd,
|
|
30945
31174
|
encoding: "utf-8",
|
|
30946
31175
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30950,13 +31179,13 @@ ${statusOut.trim()}`
|
|
|
30950
31179
|
`Failed to stage bump files: ${addResult.stderr?.trim() ?? addResult.error?.message}`
|
|
30951
31180
|
);
|
|
30952
31181
|
}
|
|
30953
|
-
const commitResult =
|
|
31182
|
+
const commitResult = spawnSync9(
|
|
30954
31183
|
"git",
|
|
30955
31184
|
["commit", "-m", "chore(release): bump versions"],
|
|
30956
31185
|
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
30957
31186
|
);
|
|
30958
31187
|
if (commitResult.status !== 0 || commitResult.error) {
|
|
30959
|
-
|
|
31188
|
+
spawnSync9(
|
|
30960
31189
|
"git",
|
|
30961
31190
|
["restore", "--staged", "--worktree", "--", ...toStage],
|
|
30962
31191
|
{
|
|
@@ -31001,7 +31230,7 @@ ${statusOut.trim()}`
|
|
|
31001
31230
|
} else {
|
|
31002
31231
|
createArgs.push("--body", defaultPrBody(feat, base));
|
|
31003
31232
|
}
|
|
31004
|
-
const createResult =
|
|
31233
|
+
const createResult = spawnSync9("gh", createArgs, {
|
|
31005
31234
|
cwd,
|
|
31006
31235
|
encoding: "utf-8",
|
|
31007
31236
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -31032,7 +31261,7 @@ ${statusOut.trim()}`
|
|
|
31032
31261
|
});
|
|
31033
31262
|
let mergeCommit = null;
|
|
31034
31263
|
try {
|
|
31035
|
-
const prViewResult =
|
|
31264
|
+
const prViewResult = spawnSync9(
|
|
31036
31265
|
"gh",
|
|
31037
31266
|
["pr", "view", feat, "--json", "state,mergeCommit"],
|
|
31038
31267
|
{
|
|
@@ -31190,14 +31419,14 @@ var init_ship2 = __esm({
|
|
|
31190
31419
|
|
|
31191
31420
|
// src/lib/scaffold-publish-workflow.ts
|
|
31192
31421
|
import * as fs6 from "node:fs";
|
|
31193
|
-
import * as
|
|
31422
|
+
import * as path8 from "node:path";
|
|
31194
31423
|
async function runScaffoldPublishWorkflow(opts) {
|
|
31195
31424
|
await Promise.resolve();
|
|
31196
31425
|
const dryRun = opts?.dryRun ?? false;
|
|
31197
31426
|
const force = opts?.force ?? false;
|
|
31198
|
-
const projectDir =
|
|
31427
|
+
const projectDir = path8.resolve(opts?.projectDir ?? process.cwd());
|
|
31199
31428
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
31200
|
-
const templatePath =
|
|
31429
|
+
const templatePath = path8.join(
|
|
31201
31430
|
templatesDir,
|
|
31202
31431
|
"github-workflows",
|
|
31203
31432
|
"publish.yml"
|
|
@@ -31208,7 +31437,7 @@ async function runScaffoldPublishWorkflow(opts) {
|
|
|
31208
31437
|
);
|
|
31209
31438
|
}
|
|
31210
31439
|
const templateContent = fs6.readFileSync(templatePath, "utf-8");
|
|
31211
|
-
const targetPath =
|
|
31440
|
+
const targetPath = path8.join(
|
|
31212
31441
|
projectDir,
|
|
31213
31442
|
".github",
|
|
31214
31443
|
"workflows",
|
|
@@ -31232,7 +31461,7 @@ async function runScaffoldPublishWorkflow(opts) {
|
|
|
31232
31461
|
);
|
|
31233
31462
|
}
|
|
31234
31463
|
}
|
|
31235
|
-
const targetDir =
|
|
31464
|
+
const targetDir = path8.dirname(targetPath);
|
|
31236
31465
|
fs6.mkdirSync(targetDir, { recursive: true });
|
|
31237
31466
|
fs6.writeFileSync(targetPath, templateContent, "utf-8");
|
|
31238
31467
|
return { status: "written", path: targetPath };
|
|
@@ -31329,7 +31558,7 @@ var init_atomic_write = __esm({
|
|
|
31329
31558
|
|
|
31330
31559
|
// src/lib/ci-init.ts
|
|
31331
31560
|
import * as fs8 from "node:fs";
|
|
31332
|
-
import * as
|
|
31561
|
+
import * as path9 from "node:path";
|
|
31333
31562
|
function tryReadJson(filePath) {
|
|
31334
31563
|
try {
|
|
31335
31564
|
return JSON.parse(fs8.readFileSync(filePath, "utf-8"));
|
|
@@ -31351,27 +31580,27 @@ function hasDevDep(pkg, name) {
|
|
|
31351
31580
|
function detectPlatforms(projectDir) {
|
|
31352
31581
|
const detected = /* @__PURE__ */ new Set();
|
|
31353
31582
|
const dirsToScan = [projectDir];
|
|
31354
|
-
const appsDir =
|
|
31583
|
+
const appsDir = path9.join(projectDir, "apps");
|
|
31355
31584
|
if (fs8.existsSync(appsDir)) {
|
|
31356
31585
|
try {
|
|
31357
31586
|
const appsEntries = fs8.readdirSync(appsDir, { withFileTypes: true });
|
|
31358
31587
|
for (const entry of appsEntries) {
|
|
31359
31588
|
if (entry.isDirectory()) {
|
|
31360
|
-
dirsToScan.push(
|
|
31589
|
+
dirsToScan.push(path9.join(appsDir, entry.name));
|
|
31361
31590
|
}
|
|
31362
31591
|
}
|
|
31363
31592
|
} catch {
|
|
31364
31593
|
}
|
|
31365
31594
|
}
|
|
31366
31595
|
for (const dir of dirsToScan) {
|
|
31367
|
-
const pkg = tryReadJson(
|
|
31368
|
-
if (fs8.existsSync(
|
|
31596
|
+
const pkg = tryReadJson(path9.join(dir, "package.json"));
|
|
31597
|
+
if (fs8.existsSync(path9.join(dir, "next.config.ts")) || fs8.existsSync(path9.join(dir, "next.config.js")) || fs8.existsSync(path9.join(dir, "next.config.mjs"))) {
|
|
31369
31598
|
detected.add("next_js");
|
|
31370
31599
|
}
|
|
31371
31600
|
if (hasDep(pkg, "@nestjs/core")) {
|
|
31372
31601
|
detected.add("nestjs");
|
|
31373
31602
|
}
|
|
31374
|
-
if (fs8.existsSync(
|
|
31603
|
+
if (fs8.existsSync(path9.join(dir, "tauri.conf.json")) || fs8.existsSync(path9.join(dir, "src-tauri"))) {
|
|
31375
31604
|
detected.add("tauri");
|
|
31376
31605
|
}
|
|
31377
31606
|
if (hasDevDep(pkg, "@types/vscode")) {
|
|
@@ -31382,7 +31611,7 @@ function detectPlatforms(projectDir) {
|
|
|
31382
31611
|
detected.add("expo");
|
|
31383
31612
|
}
|
|
31384
31613
|
}
|
|
31385
|
-
const packagesDir =
|
|
31614
|
+
const packagesDir = path9.join(projectDir, "packages");
|
|
31386
31615
|
if (fs8.existsSync(packagesDir)) {
|
|
31387
31616
|
try {
|
|
31388
31617
|
const pkgEntries = fs8.readdirSync(packagesDir, { withFileTypes: true });
|
|
@@ -31419,10 +31648,10 @@ function buildDefaultCiConfig(platforms) {
|
|
|
31419
31648
|
}
|
|
31420
31649
|
async function runCiInit(opts) {
|
|
31421
31650
|
await Promise.resolve();
|
|
31422
|
-
const projectDir =
|
|
31651
|
+
const projectDir = path9.resolve(opts?.projectDir ?? process.cwd());
|
|
31423
31652
|
const dryRun = opts?.dryRun ?? false;
|
|
31424
31653
|
const force = opts?.force ?? false;
|
|
31425
|
-
const ciPath =
|
|
31654
|
+
const ciPath = path9.join(projectDir, ".codebyplan", "ci.json");
|
|
31426
31655
|
const platforms = detectPlatforms(projectDir);
|
|
31427
31656
|
if (dryRun) {
|
|
31428
31657
|
return { status: "dry_run", path: ciPath, platforms };
|
|
@@ -31467,7 +31696,7 @@ async function runCiInit(opts) {
|
|
|
31467
31696
|
platforms: newPlatforms.length > 0 ? newPlatforms : platforms
|
|
31468
31697
|
};
|
|
31469
31698
|
}
|
|
31470
|
-
const codebyplanDir =
|
|
31699
|
+
const codebyplanDir = path9.join(projectDir, ".codebyplan");
|
|
31471
31700
|
fs8.mkdirSync(codebyplanDir, { recursive: true });
|
|
31472
31701
|
writeJsonAtomic(ciPath, newConfig);
|
|
31473
31702
|
return { status: "written", path: ciPath, platforms };
|
|
@@ -31676,7 +31905,7 @@ var init_ci_init = __esm({
|
|
|
31676
31905
|
|
|
31677
31906
|
// src/lib/scaffold-ci-workflow.ts
|
|
31678
31907
|
import * as fs9 from "node:fs";
|
|
31679
|
-
import * as
|
|
31908
|
+
import * as path10 from "node:path";
|
|
31680
31909
|
function substituteTokens(template, tokens) {
|
|
31681
31910
|
let result = template;
|
|
31682
31911
|
for (const [token, value] of Object.entries(tokens)) {
|
|
@@ -31686,7 +31915,7 @@ function substituteTokens(template, tokens) {
|
|
|
31686
31915
|
}
|
|
31687
31916
|
function detectPnpmVersionFromPackageJson(projectDir) {
|
|
31688
31917
|
try {
|
|
31689
|
-
const pkgPath =
|
|
31918
|
+
const pkgPath = path10.join(projectDir, "package.json");
|
|
31690
31919
|
const raw = fs9.readFileSync(pkgPath, "utf-8");
|
|
31691
31920
|
const pkg = JSON.parse(raw);
|
|
31692
31921
|
const pm = pkg.packageManager;
|
|
@@ -31703,7 +31932,7 @@ function detectPnpmVersionFromPackageJson(projectDir) {
|
|
|
31703
31932
|
}
|
|
31704
31933
|
function detectStrictEnforcedFromCiJson(projectDir) {
|
|
31705
31934
|
try {
|
|
31706
|
-
const ciJsonPath =
|
|
31935
|
+
const ciJsonPath = path10.join(projectDir, ".codebyplan", "ci.json");
|
|
31707
31936
|
const raw = fs9.readFileSync(ciJsonPath, "utf-8");
|
|
31708
31937
|
const parsed = JSON.parse(raw);
|
|
31709
31938
|
return parsed.workflow?.strict_check_enforced === true;
|
|
@@ -31715,12 +31944,12 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31715
31944
|
await Promise.resolve();
|
|
31716
31945
|
const dryRun = opts?.dryRun ?? false;
|
|
31717
31946
|
const force = opts?.force ?? false;
|
|
31718
|
-
const projectDir =
|
|
31947
|
+
const projectDir = path10.resolve(opts?.projectDir ?? process.cwd());
|
|
31719
31948
|
const pnpmVersion = opts?.pnpmVersion ?? detectPnpmVersionFromPackageJson(projectDir);
|
|
31720
31949
|
const nodeVersion = opts?.nodeVersion ?? "22";
|
|
31721
31950
|
const strictEnforced = opts?.strictEnforced ?? detectStrictEnforcedFromCiJson(projectDir);
|
|
31722
31951
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
31723
|
-
const templatePath =
|
|
31952
|
+
const templatePath = path10.join(templatesDir, "github-workflows", "ci.yml");
|
|
31724
31953
|
if (!fs9.existsSync(templatePath)) {
|
|
31725
31954
|
throw new Error(
|
|
31726
31955
|
`scaffold-ci-workflow: template not found at ${templatePath}`
|
|
@@ -31733,7 +31962,7 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31733
31962
|
STRICT_NAME_SUFFIX: strictEnforced ? "" : " (report-only)",
|
|
31734
31963
|
STRICT_CONTINUE_ON_ERROR_LINE: strictEnforced ? "" : "\n continue-on-error: true"
|
|
31735
31964
|
});
|
|
31736
|
-
const targetPath =
|
|
31965
|
+
const targetPath = path10.join(projectDir, ".github", "workflows", "ci.yml");
|
|
31737
31966
|
if (dryRun) {
|
|
31738
31967
|
return { status: "dry_run", path: targetPath };
|
|
31739
31968
|
}
|
|
@@ -31752,7 +31981,7 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31752
31981
|
);
|
|
31753
31982
|
}
|
|
31754
31983
|
}
|
|
31755
|
-
const targetDir =
|
|
31984
|
+
const targetDir = path10.dirname(targetPath);
|
|
31756
31985
|
fs9.mkdirSync(targetDir, { recursive: true });
|
|
31757
31986
|
const tmpPath = targetPath + ".tmp";
|
|
31758
31987
|
try {
|
|
@@ -31776,10 +32005,10 @@ var init_scaffold_ci_workflow = __esm({
|
|
|
31776
32005
|
|
|
31777
32006
|
// src/lib/gh-required-checks.ts
|
|
31778
32007
|
import * as fs10 from "node:fs";
|
|
31779
|
-
import * as
|
|
32008
|
+
import * as path11 from "node:path";
|
|
31780
32009
|
import { execSync as execSync6 } from "node:child_process";
|
|
31781
32010
|
function readCiJson(projectDir) {
|
|
31782
|
-
const ciPath =
|
|
32011
|
+
const ciPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31783
32012
|
if (!fs10.existsSync(ciPath)) {
|
|
31784
32013
|
return {
|
|
31785
32014
|
platforms: {},
|
|
@@ -31798,15 +32027,15 @@ function readCiJson(projectDir) {
|
|
|
31798
32027
|
}
|
|
31799
32028
|
}
|
|
31800
32029
|
function writeCiJsonAtomic(projectDir, config) {
|
|
31801
|
-
const ciPath =
|
|
32030
|
+
const ciPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31802
32031
|
writeJsonAtomic(ciPath, config);
|
|
31803
32032
|
}
|
|
31804
32033
|
function enforceRequiredCheck(opts) {
|
|
31805
|
-
const projectDir =
|
|
32034
|
+
const projectDir = path11.resolve(opts?.projectDir ?? process.cwd());
|
|
31806
32035
|
const branch = opts?.branch ?? "main";
|
|
31807
32036
|
const checkName = opts?.checkName ?? "Lint + typecheck + test + build";
|
|
31808
32037
|
const dryRun = opts?.dryRun ?? false;
|
|
31809
|
-
const ciPath =
|
|
32038
|
+
const ciPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31810
32039
|
const config = readCiJson(projectDir);
|
|
31811
32040
|
if (config.workflow?.required_check_enforced === true) {
|
|
31812
32041
|
return { status: "already_enforced", path: ciPath };
|
|
@@ -32213,9 +32442,9 @@ var init_ci = __esm({
|
|
|
32213
32442
|
|
|
32214
32443
|
// src/lib/cd-init.ts
|
|
32215
32444
|
import * as fs11 from "node:fs";
|
|
32216
|
-
import * as
|
|
32445
|
+
import * as path12 from "node:path";
|
|
32217
32446
|
function detectSurfaces(projectDir) {
|
|
32218
|
-
const shipmentPath =
|
|
32447
|
+
const shipmentPath = path12.join(projectDir, ".codebyplan", "shipment.json");
|
|
32219
32448
|
let shipment;
|
|
32220
32449
|
try {
|
|
32221
32450
|
shipment = JSON.parse(fs11.readFileSync(shipmentPath, "utf-8"));
|
|
@@ -32268,10 +32497,10 @@ function buildDefaultCdConfig(rawSurfaceKeys) {
|
|
|
32268
32497
|
}
|
|
32269
32498
|
async function runCdInit(opts) {
|
|
32270
32499
|
await Promise.resolve();
|
|
32271
|
-
const projectDir =
|
|
32500
|
+
const projectDir = path12.resolve(opts?.projectDir ?? process.cwd());
|
|
32272
32501
|
const dryRun = opts?.dryRun ?? false;
|
|
32273
32502
|
const force = opts?.force ?? false;
|
|
32274
|
-
const cdPath =
|
|
32503
|
+
const cdPath = path12.join(projectDir, ".codebyplan", "cd.json");
|
|
32275
32504
|
const rawSurfaceKeys = detectSurfaces(projectDir);
|
|
32276
32505
|
const seen = /* @__PURE__ */ new Set();
|
|
32277
32506
|
const surfaces = [];
|
|
@@ -32312,7 +32541,7 @@ async function runCdInit(opts) {
|
|
|
32312
32541
|
surfaces: newSurfaces
|
|
32313
32542
|
};
|
|
32314
32543
|
}
|
|
32315
|
-
const codebyplanDir =
|
|
32544
|
+
const codebyplanDir = path12.join(projectDir, ".codebyplan");
|
|
32316
32545
|
fs11.mkdirSync(codebyplanDir, { recursive: true });
|
|
32317
32546
|
writeJsonAtomic(cdPath, newConfig);
|
|
32318
32547
|
return { status: "written", path: cdPath, surfaces };
|
|
@@ -32402,14 +32631,14 @@ var init_cd_init = __esm({
|
|
|
32402
32631
|
|
|
32403
32632
|
// src/lib/scaffold-cd-workflow.ts
|
|
32404
32633
|
import * as fs12 from "node:fs";
|
|
32405
|
-
import * as
|
|
32634
|
+
import * as path13 from "node:path";
|
|
32406
32635
|
async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
32407
32636
|
await Promise.resolve();
|
|
32408
32637
|
const dryRun = opts.dryRun ?? false;
|
|
32409
32638
|
const force = opts.force ?? false;
|
|
32410
|
-
const projectDir =
|
|
32639
|
+
const projectDir = path13.resolve(opts.projectDir ?? process.cwd());
|
|
32411
32640
|
const templatesDir = opts.templatesDir ?? resolveTemplatesDir();
|
|
32412
|
-
const templatePath =
|
|
32641
|
+
const templatePath = path13.join(
|
|
32413
32642
|
templatesDir,
|
|
32414
32643
|
"github-workflows",
|
|
32415
32644
|
templateName
|
|
@@ -32420,7 +32649,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
32420
32649
|
);
|
|
32421
32650
|
}
|
|
32422
32651
|
const templateContent = fs12.readFileSync(templatePath, "utf-8");
|
|
32423
|
-
const targetPath =
|
|
32652
|
+
const targetPath = path13.join(projectDir, ".github", "workflows", targetName);
|
|
32424
32653
|
if (dryRun) {
|
|
32425
32654
|
return { status: "dry_run", path: targetPath };
|
|
32426
32655
|
}
|
|
@@ -32439,7 +32668,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
32439
32668
|
);
|
|
32440
32669
|
}
|
|
32441
32670
|
}
|
|
32442
|
-
const targetDir =
|
|
32671
|
+
const targetDir = path13.dirname(targetPath);
|
|
32443
32672
|
fs12.mkdirSync(targetDir, { recursive: true });
|
|
32444
32673
|
const tmpPath = targetPath + ".tmp";
|
|
32445
32674
|
try {
|
|
@@ -33115,7 +33344,7 @@ __export(version_status_exports, {
|
|
|
33115
33344
|
});
|
|
33116
33345
|
import { execFileSync, execSync as execSync7 } from "node:child_process";
|
|
33117
33346
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
33118
|
-
import { dirname as dirname12, join as
|
|
33347
|
+
import { dirname as dirname12, join as join31 } from "node:path";
|
|
33119
33348
|
function fetchLatestVersion() {
|
|
33120
33349
|
try {
|
|
33121
33350
|
return execFileSync("npm", ["view", "codebyplan", "version"], {
|
|
@@ -33139,9 +33368,9 @@ function detectPackageManager2(gitRoot) {
|
|
|
33139
33368
|
let dir = process.cwd();
|
|
33140
33369
|
const stopAt = gitRoot ?? null;
|
|
33141
33370
|
while (true) {
|
|
33142
|
-
if (existsSync10(
|
|
33143
|
-
if (existsSync10(
|
|
33144
|
-
if (existsSync10(
|
|
33371
|
+
if (existsSync10(join31(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
33372
|
+
if (existsSync10(join31(dir, "yarn.lock"))) return "yarn";
|
|
33373
|
+
if (existsSync10(join31(dir, "package-lock.json"))) return "npm";
|
|
33145
33374
|
if (stopAt !== null && dir === stopAt) break;
|
|
33146
33375
|
const parent = dirname12(dir);
|
|
33147
33376
|
if (parent === dir) break;
|
|
@@ -33161,7 +33390,7 @@ function buildInstallCommand2(pm) {
|
|
|
33161
33390
|
}
|
|
33162
33391
|
async function resolveGuard(gitRoot, currentBranch) {
|
|
33163
33392
|
if (gitRoot !== null) {
|
|
33164
|
-
const canonicalPkgPath =
|
|
33393
|
+
const canonicalPkgPath = join31(
|
|
33165
33394
|
gitRoot,
|
|
33166
33395
|
"packages",
|
|
33167
33396
|
"codebyplan-package",
|
|
@@ -33185,10 +33414,10 @@ async function resolveGuard(gitRoot, currentBranch) {
|
|
|
33185
33414
|
let gitJsonPath;
|
|
33186
33415
|
if (found.path.endsWith("/repo.json")) {
|
|
33187
33416
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
33188
|
-
gitJsonPath =
|
|
33417
|
+
gitJsonPath = join31(dir, "git.json");
|
|
33189
33418
|
} else {
|
|
33190
33419
|
const legacyDir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
33191
|
-
gitJsonPath =
|
|
33420
|
+
gitJsonPath = join31(legacyDir, ".codebyplan", "git.json");
|
|
33192
33421
|
}
|
|
33193
33422
|
const raw = readFileSync11(gitJsonPath, "utf-8");
|
|
33194
33423
|
const parsed = JSON.parse(raw);
|
|
@@ -33272,8 +33501,8 @@ var upload_e2e_images_exports = {};
|
|
|
33272
33501
|
__export(upload_e2e_images_exports, {
|
|
33273
33502
|
runUploadE2eImagesCommand: () => runUploadE2eImagesCommand
|
|
33274
33503
|
});
|
|
33275
|
-
import { readFile as
|
|
33276
|
-
import { join as
|
|
33504
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
33505
|
+
import { join as join32, basename, resolve as resolve10 } from "node:path";
|
|
33277
33506
|
import { execSync as execSync8 } from "node:child_process";
|
|
33278
33507
|
function baseUrl2() {
|
|
33279
33508
|
return (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
|
|
@@ -33307,8 +33536,8 @@ function parseArgs(args) {
|
|
|
33307
33536
|
}
|
|
33308
33537
|
async function readE2eConfig(projectPath) {
|
|
33309
33538
|
try {
|
|
33310
|
-
const raw = await
|
|
33311
|
-
|
|
33539
|
+
const raw = await readFile20(
|
|
33540
|
+
join32(projectPath, ".codebyplan", "e2e.json"),
|
|
33312
33541
|
"utf-8"
|
|
33313
33542
|
);
|
|
33314
33543
|
return JSON.parse(raw);
|
|
@@ -33349,7 +33578,7 @@ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, bas
|
|
|
33349
33578
|
continue;
|
|
33350
33579
|
const isNew = status === "A";
|
|
33351
33580
|
results.push({
|
|
33352
|
-
absolutePath:
|
|
33581
|
+
absolutePath: join32(projectPath, filePath),
|
|
33353
33582
|
filename: basename(filePath),
|
|
33354
33583
|
framework: frameworkName,
|
|
33355
33584
|
is_new: isNew
|
|
@@ -33446,7 +33675,7 @@ async function runUploadE2eImagesCommand(args) {
|
|
|
33446
33675
|
for (const png of allPngs) {
|
|
33447
33676
|
let bytes;
|
|
33448
33677
|
try {
|
|
33449
|
-
bytes = await
|
|
33678
|
+
bytes = await readFile20(png.absolutePath);
|
|
33450
33679
|
} catch {
|
|
33451
33680
|
process.stderr.write(
|
|
33452
33681
|
`upload-e2e-images: could not read file: ${png.absolutePath}
|
|
@@ -33523,10 +33752,10 @@ __export(arch_map_exports, {
|
|
|
33523
33752
|
runArchMapCommand: () => runArchMapCommand,
|
|
33524
33753
|
updateFrontmatterFields: () => updateFrontmatterFields
|
|
33525
33754
|
});
|
|
33526
|
-
import { readFile as
|
|
33755
|
+
import { readFile as readFile21, writeFile as writeFile17 } from "node:fs/promises";
|
|
33527
33756
|
import { existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
|
|
33528
|
-
import { join as
|
|
33529
|
-
import { spawnSync as
|
|
33757
|
+
import { join as join33 } from "node:path";
|
|
33758
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
33530
33759
|
function normalizeModulePath(modulePath) {
|
|
33531
33760
|
return modulePath.replace(/\/+$/, "");
|
|
33532
33761
|
}
|
|
@@ -33550,9 +33779,9 @@ async function resolveCodebyplanDir(startDir) {
|
|
|
33550
33779
|
}
|
|
33551
33780
|
}
|
|
33552
33781
|
async function readArchitectureConfig(codebyplanDir) {
|
|
33553
|
-
const filePath =
|
|
33782
|
+
const filePath = join33(codebyplanDir, "architecture.json");
|
|
33554
33783
|
try {
|
|
33555
|
-
const raw = await
|
|
33784
|
+
const raw = await readFile21(filePath, "utf-8");
|
|
33556
33785
|
const parsed = JSON.parse(raw);
|
|
33557
33786
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.modules)) {
|
|
33558
33787
|
return { version: 1, modules: [] };
|
|
@@ -33563,12 +33792,12 @@ async function readArchitectureConfig(codebyplanDir) {
|
|
|
33563
33792
|
}
|
|
33564
33793
|
}
|
|
33565
33794
|
async function writeArchitectureConfig(codebyplanDir, config) {
|
|
33566
|
-
const filePath =
|
|
33567
|
-
await
|
|
33795
|
+
const filePath = join33(codebyplanDir, "architecture.json");
|
|
33796
|
+
await writeFile17(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
33568
33797
|
}
|
|
33569
33798
|
function resolveGitSha(modulePath, cwd) {
|
|
33570
33799
|
try {
|
|
33571
|
-
const result =
|
|
33800
|
+
const result = spawnSync10(
|
|
33572
33801
|
"git",
|
|
33573
33802
|
["log", "--format=%H", "-1", "--", modulePath],
|
|
33574
33803
|
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -33582,10 +33811,10 @@ function resolveGitSha(modulePath, cwd) {
|
|
|
33582
33811
|
}
|
|
33583
33812
|
async function discoverModulePaths(projectRoot) {
|
|
33584
33813
|
const paths = [];
|
|
33585
|
-
const workspacePath =
|
|
33814
|
+
const workspacePath = join33(projectRoot, "pnpm-workspace.yaml");
|
|
33586
33815
|
let patterns = [];
|
|
33587
33816
|
try {
|
|
33588
|
-
const raw = await
|
|
33817
|
+
const raw = await readFile21(workspacePath, "utf-8");
|
|
33589
33818
|
const lines = raw.split("\n");
|
|
33590
33819
|
let inPackages = false;
|
|
33591
33820
|
for (const line of lines) {
|
|
@@ -33609,7 +33838,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33609
33838
|
for (const pattern of patterns) {
|
|
33610
33839
|
if (pattern.endsWith("/*")) {
|
|
33611
33840
|
const dir = pattern.slice(0, -2);
|
|
33612
|
-
const absDir =
|
|
33841
|
+
const absDir = join33(projectRoot, dir);
|
|
33613
33842
|
try {
|
|
33614
33843
|
if (existsSync11(absDir)) {
|
|
33615
33844
|
const entries = readdirSync4(absDir, { withFileTypes: true });
|
|
@@ -33622,7 +33851,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33622
33851
|
} catch {
|
|
33623
33852
|
}
|
|
33624
33853
|
} else if (!pattern.includes("*")) {
|
|
33625
|
-
const absPath =
|
|
33854
|
+
const absPath = join33(projectRoot, pattern);
|
|
33626
33855
|
if (existsSync11(absPath)) {
|
|
33627
33856
|
paths.push(pattern);
|
|
33628
33857
|
}
|
|
@@ -33630,7 +33859,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33630
33859
|
}
|
|
33631
33860
|
const crossCutting = ["supabase", ".github", "scripts"];
|
|
33632
33861
|
for (const dir of crossCutting) {
|
|
33633
|
-
const absPath =
|
|
33862
|
+
const absPath = join33(projectRoot, dir);
|
|
33634
33863
|
try {
|
|
33635
33864
|
if (existsSync11(absPath)) {
|
|
33636
33865
|
paths.push(dir);
|
|
@@ -33816,10 +34045,10 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
33816
34045
|
}
|
|
33817
34046
|
await writeArchitectureConfig(codebyplanDir, config);
|
|
33818
34047
|
const stampedEntry = existingIndex >= 0 ? config.modules[existingIndex] : config.modules[config.modules.length - 1];
|
|
33819
|
-
const mapAbsPath =
|
|
34048
|
+
const mapAbsPath = join33(repoRoot, stampedEntry.map_file);
|
|
33820
34049
|
let mapContent = null;
|
|
33821
34050
|
try {
|
|
33822
|
-
mapContent = await
|
|
34051
|
+
mapContent = await readFile21(mapAbsPath, "utf-8");
|
|
33823
34052
|
} catch {
|
|
33824
34053
|
console.warn(
|
|
33825
34054
|
" Warning: map file " + stampedEntry.map_file + " not found \u2014 stamped manifest only"
|
|
@@ -33841,7 +34070,7 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
33841
34070
|
);
|
|
33842
34071
|
} else {
|
|
33843
34072
|
try {
|
|
33844
|
-
await
|
|
34073
|
+
await writeFile17(mapAbsPath, updated, "utf-8");
|
|
33845
34074
|
} catch (writeErr) {
|
|
33846
34075
|
console.warn(
|
|
33847
34076
|
" Warning: could not write map file " + stampedEntry.map_file + " \u2014 " + (writeErr instanceof Error ? writeErr.message : String(writeErr)) + " \u2014 stamped manifest only"
|
|
@@ -34021,19 +34250,19 @@ var init_worktree_port_resolver = __esm({
|
|
|
34021
34250
|
});
|
|
34022
34251
|
|
|
34023
34252
|
// src/lib/migrate-local-config.ts
|
|
34024
|
-
import { mkdir as mkdir9, readFile as
|
|
34025
|
-
import { join as
|
|
34253
|
+
import { mkdir as mkdir9, readFile as readFile22, unlink as unlink5, writeFile as writeFile18 } from "node:fs/promises";
|
|
34254
|
+
import { join as join34 } from "node:path";
|
|
34026
34255
|
function legacySharedPath(projectPath) {
|
|
34027
|
-
return
|
|
34256
|
+
return join34(projectPath, ".codebyplan.json");
|
|
34028
34257
|
}
|
|
34029
34258
|
function legacyLocalPath(projectPath) {
|
|
34030
|
-
return
|
|
34259
|
+
return join34(projectPath, ".codebyplan.local.json");
|
|
34031
34260
|
}
|
|
34032
34261
|
function newDirPath(projectPath) {
|
|
34033
|
-
return
|
|
34262
|
+
return join34(projectPath, ".codebyplan");
|
|
34034
34263
|
}
|
|
34035
34264
|
function sentinelPath(projectPath) {
|
|
34036
|
-
return
|
|
34265
|
+
return join34(projectPath, ".codebyplan", "repo.json");
|
|
34037
34266
|
}
|
|
34038
34267
|
async function statSafe(p) {
|
|
34039
34268
|
const { stat: stat3 } = await import("node:fs/promises");
|
|
@@ -34072,7 +34301,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34072
34301
|
}
|
|
34073
34302
|
let legacyRaw;
|
|
34074
34303
|
try {
|
|
34075
|
-
legacyRaw = await
|
|
34304
|
+
legacyRaw = await readFile22(legacySharedPath(projectPath), "utf-8");
|
|
34076
34305
|
} catch {
|
|
34077
34306
|
return {
|
|
34078
34307
|
migrated: true,
|
|
@@ -34099,7 +34328,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34099
34328
|
let deviceId;
|
|
34100
34329
|
let deviceWrittenByHelper = false;
|
|
34101
34330
|
try {
|
|
34102
|
-
const localRaw = await
|
|
34331
|
+
const localRaw = await readFile22(legacyLocalPath(projectPath), "utf-8");
|
|
34103
34332
|
const localParsed = JSON.parse(localRaw);
|
|
34104
34333
|
if (typeof localParsed.device_id === "string") {
|
|
34105
34334
|
deviceId = localParsed.device_id;
|
|
@@ -34126,8 +34355,8 @@ async function runLocalMigration(projectPath) {
|
|
|
34126
34355
|
if ("repo_id" in cfg) repoJson.repo_id = cfg.repo_id;
|
|
34127
34356
|
if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
|
|
34128
34357
|
if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
|
|
34129
|
-
await
|
|
34130
|
-
|
|
34358
|
+
await writeFile18(
|
|
34359
|
+
join34(projectPath, ".codebyplan", "repo.json"),
|
|
34131
34360
|
JSON.stringify(repoJson, null, 2) + "\n",
|
|
34132
34361
|
"utf-8"
|
|
34133
34362
|
);
|
|
@@ -34139,8 +34368,8 @@ async function runLocalMigration(projectPath) {
|
|
|
34139
34368
|
serverJson.auto_push_enabled = cfg.auto_push_enabled;
|
|
34140
34369
|
if ("port_allocations" in cfg)
|
|
34141
34370
|
serverJson.port_allocations = cfg.port_allocations;
|
|
34142
|
-
await
|
|
34143
|
-
|
|
34371
|
+
await writeFile18(
|
|
34372
|
+
join34(projectPath, ".codebyplan", "server.json"),
|
|
34144
34373
|
JSON.stringify(serverJson, null, 2) + "\n",
|
|
34145
34374
|
"utf-8"
|
|
34146
34375
|
);
|
|
@@ -34148,44 +34377,44 @@ async function runLocalMigration(projectPath) {
|
|
|
34148
34377
|
const gitJson = {};
|
|
34149
34378
|
if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
|
|
34150
34379
|
if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
|
|
34151
|
-
await
|
|
34152
|
-
|
|
34380
|
+
await writeFile18(
|
|
34381
|
+
join34(projectPath, ".codebyplan", "git.json"),
|
|
34153
34382
|
JSON.stringify(gitJson, null, 2) + "\n",
|
|
34154
34383
|
"utf-8"
|
|
34155
34384
|
);
|
|
34156
34385
|
filesChanged.push(".codebyplan/git.json");
|
|
34157
34386
|
const shipmentJson = {};
|
|
34158
34387
|
if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
|
|
34159
|
-
await
|
|
34160
|
-
|
|
34388
|
+
await writeFile18(
|
|
34389
|
+
join34(projectPath, ".codebyplan", "shipment.json"),
|
|
34161
34390
|
JSON.stringify(shipmentJson, null, 2) + "\n",
|
|
34162
34391
|
"utf-8"
|
|
34163
34392
|
);
|
|
34164
34393
|
filesChanged.push(".codebyplan/shipment.json");
|
|
34165
34394
|
const vendorJson = {};
|
|
34166
|
-
await
|
|
34167
|
-
|
|
34395
|
+
await writeFile18(
|
|
34396
|
+
join34(projectPath, ".codebyplan", "vendor.json"),
|
|
34168
34397
|
JSON.stringify(vendorJson, null, 2) + "\n",
|
|
34169
34398
|
"utf-8"
|
|
34170
34399
|
);
|
|
34171
34400
|
filesChanged.push(".codebyplan/vendor.json");
|
|
34172
34401
|
const e2eJson = {};
|
|
34173
|
-
await
|
|
34174
|
-
|
|
34402
|
+
await writeFile18(
|
|
34403
|
+
join34(projectPath, ".codebyplan", "e2e.json"),
|
|
34175
34404
|
JSON.stringify(e2eJson, null, 2) + "\n",
|
|
34176
34405
|
"utf-8"
|
|
34177
34406
|
);
|
|
34178
34407
|
filesChanged.push(".codebyplan/e2e.json");
|
|
34179
34408
|
const eslintJson = {};
|
|
34180
|
-
await
|
|
34181
|
-
|
|
34409
|
+
await writeFile18(
|
|
34410
|
+
join34(projectPath, ".codebyplan", "eslint.json"),
|
|
34182
34411
|
JSON.stringify(eslintJson, null, 2) + "\n",
|
|
34183
34412
|
"utf-8"
|
|
34184
34413
|
);
|
|
34185
34414
|
filesChanged.push(".codebyplan/eslint.json");
|
|
34186
34415
|
if (!deviceWrittenByHelper) {
|
|
34187
|
-
await
|
|
34188
|
-
|
|
34416
|
+
await writeFile18(
|
|
34417
|
+
join34(projectPath, ".codebyplan", "device.local.json"),
|
|
34189
34418
|
JSON.stringify({ device_id: deviceId }, null, 2) + "\n",
|
|
34190
34419
|
"utf-8"
|
|
34191
34420
|
);
|
|
@@ -34197,9 +34426,9 @@ async function runLocalMigration(projectPath) {
|
|
|
34197
34426
|
"Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
|
|
34198
34427
|
);
|
|
34199
34428
|
}
|
|
34200
|
-
const gitignorePath =
|
|
34429
|
+
const gitignorePath = join34(projectPath, ".gitignore");
|
|
34201
34430
|
try {
|
|
34202
|
-
const gitignoreContent = await
|
|
34431
|
+
const gitignoreContent = await readFile22(gitignorePath, "utf-8");
|
|
34203
34432
|
const legacyLine = ".codebyplan.local.json";
|
|
34204
34433
|
const newLine = ".codebyplan/device.local.json";
|
|
34205
34434
|
const hasLegacy = gitignoreContent.split("\n").some((l) => l.trimEnd() === legacyLine);
|
|
@@ -34218,7 +34447,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34218
34447
|
updated = gitignoreContent;
|
|
34219
34448
|
}
|
|
34220
34449
|
if (updated !== gitignoreContent) {
|
|
34221
|
-
await
|
|
34450
|
+
await writeFile18(gitignorePath, updated, "utf-8");
|
|
34222
34451
|
filesChanged.push(".gitignore");
|
|
34223
34452
|
}
|
|
34224
34453
|
} catch {
|
|
@@ -34260,8 +34489,8 @@ __export(config_exports, {
|
|
|
34260
34489
|
runConfig: () => runConfig,
|
|
34261
34490
|
runConfigMigrate: () => runConfigMigrate
|
|
34262
34491
|
});
|
|
34263
|
-
import { mkdir as mkdir10, readFile as
|
|
34264
|
-
import { join as
|
|
34492
|
+
import { mkdir as mkdir10, readFile as readFile23, writeFile as writeFile19 } from "node:fs/promises";
|
|
34493
|
+
import { join as join35 } from "node:path";
|
|
34265
34494
|
async function runConfig() {
|
|
34266
34495
|
const flags = parseFlags(3);
|
|
34267
34496
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -34294,7 +34523,7 @@ async function runConfig() {
|
|
|
34294
34523
|
console.log("\n Config complete.\n");
|
|
34295
34524
|
}
|
|
34296
34525
|
async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
34297
|
-
const codebyplanDir =
|
|
34526
|
+
const codebyplanDir = join35(projectPath, ".codebyplan");
|
|
34298
34527
|
const {
|
|
34299
34528
|
resolvedWorktreeId,
|
|
34300
34529
|
portAllocations,
|
|
@@ -34387,16 +34616,16 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
34387
34616
|
];
|
|
34388
34617
|
let anyUpdated = false;
|
|
34389
34618
|
for (const { name, payload, createOnly } of files) {
|
|
34390
|
-
const filePath =
|
|
34619
|
+
const filePath = join35(codebyplanDir, name);
|
|
34391
34620
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
34392
34621
|
let currentJson = "";
|
|
34393
34622
|
try {
|
|
34394
|
-
currentJson = await
|
|
34623
|
+
currentJson = await readFile23(filePath, "utf-8");
|
|
34395
34624
|
} catch {
|
|
34396
34625
|
}
|
|
34397
34626
|
if (createOnly && currentJson !== "") continue;
|
|
34398
34627
|
if (currentJson === newJson) continue;
|
|
34399
|
-
await
|
|
34628
|
+
await writeFile19(filePath, newJson, "utf-8");
|
|
34400
34629
|
console.log(` Updated .codebyplan/${name}`);
|
|
34401
34630
|
anyUpdated = true;
|
|
34402
34631
|
}
|
|
@@ -34406,8 +34635,8 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
34406
34635
|
}
|
|
34407
34636
|
async function readRepoConfig(projectPath) {
|
|
34408
34637
|
try {
|
|
34409
|
-
const raw = await
|
|
34410
|
-
|
|
34638
|
+
const raw = await readFile23(
|
|
34639
|
+
join35(projectPath, ".codebyplan", "repo.json"),
|
|
34411
34640
|
"utf-8"
|
|
34412
34641
|
);
|
|
34413
34642
|
return JSON.parse(raw);
|
|
@@ -34417,8 +34646,8 @@ async function readRepoConfig(projectPath) {
|
|
|
34417
34646
|
}
|
|
34418
34647
|
async function readServerConfig(projectPath) {
|
|
34419
34648
|
try {
|
|
34420
|
-
const raw = await
|
|
34421
|
-
|
|
34649
|
+
const raw = await readFile23(
|
|
34650
|
+
join35(projectPath, ".codebyplan", "server.json"),
|
|
34422
34651
|
"utf-8"
|
|
34423
34652
|
);
|
|
34424
34653
|
return JSON.parse(raw);
|
|
@@ -34428,8 +34657,8 @@ async function readServerConfig(projectPath) {
|
|
|
34428
34657
|
}
|
|
34429
34658
|
async function readGitConfig2(projectPath) {
|
|
34430
34659
|
try {
|
|
34431
|
-
const raw = await
|
|
34432
|
-
|
|
34660
|
+
const raw = await readFile23(
|
|
34661
|
+
join35(projectPath, ".codebyplan", "git.json"),
|
|
34433
34662
|
"utf-8"
|
|
34434
34663
|
);
|
|
34435
34664
|
return JSON.parse(raw);
|
|
@@ -34439,8 +34668,8 @@ async function readGitConfig2(projectPath) {
|
|
|
34439
34668
|
}
|
|
34440
34669
|
async function readShipmentConfig2(projectPath) {
|
|
34441
34670
|
try {
|
|
34442
|
-
const raw = await
|
|
34443
|
-
|
|
34671
|
+
const raw = await readFile23(
|
|
34672
|
+
join35(projectPath, ".codebyplan", "shipment.json"),
|
|
34444
34673
|
"utf-8"
|
|
34445
34674
|
);
|
|
34446
34675
|
return JSON.parse(raw);
|
|
@@ -34450,8 +34679,8 @@ async function readShipmentConfig2(projectPath) {
|
|
|
34450
34679
|
}
|
|
34451
34680
|
async function readVendorConfig(projectPath) {
|
|
34452
34681
|
try {
|
|
34453
|
-
const raw = await
|
|
34454
|
-
|
|
34682
|
+
const raw = await readFile23(
|
|
34683
|
+
join35(projectPath, ".codebyplan", "vendor.json"),
|
|
34455
34684
|
"utf-8"
|
|
34456
34685
|
);
|
|
34457
34686
|
return JSON.parse(raw);
|
|
@@ -34461,8 +34690,8 @@ async function readVendorConfig(projectPath) {
|
|
|
34461
34690
|
}
|
|
34462
34691
|
async function readE2eConfig2(projectPath) {
|
|
34463
34692
|
try {
|
|
34464
|
-
const raw = await
|
|
34465
|
-
|
|
34693
|
+
const raw = await readFile23(
|
|
34694
|
+
join35(projectPath, ".codebyplan", "e2e.json"),
|
|
34466
34695
|
"utf-8"
|
|
34467
34696
|
);
|
|
34468
34697
|
return JSON.parse(raw);
|
|
@@ -34472,8 +34701,8 @@ async function readE2eConfig2(projectPath) {
|
|
|
34472
34701
|
}
|
|
34473
34702
|
async function readServerLocalConfig(projectPath) {
|
|
34474
34703
|
try {
|
|
34475
|
-
const raw = await
|
|
34476
|
-
|
|
34704
|
+
const raw = await readFile23(
|
|
34705
|
+
join35(projectPath, ".codebyplan", "server.local.json"),
|
|
34477
34706
|
"utf-8"
|
|
34478
34707
|
);
|
|
34479
34708
|
return JSON.parse(raw);
|
|
@@ -34545,8 +34774,8 @@ var init_config = __esm({
|
|
|
34545
34774
|
});
|
|
34546
34775
|
|
|
34547
34776
|
// src/lib/server-detect.ts
|
|
34548
|
-
import { readFile as
|
|
34549
|
-
import { join as
|
|
34777
|
+
import { readFile as readFile24, readdir as readdir5, access as access6 } from "node:fs/promises";
|
|
34778
|
+
import { join as join36 } from "node:path";
|
|
34550
34779
|
async function fileExists4(filePath) {
|
|
34551
34780
|
try {
|
|
34552
34781
|
await access6(filePath);
|
|
@@ -34557,8 +34786,8 @@ async function fileExists4(filePath) {
|
|
|
34557
34786
|
}
|
|
34558
34787
|
function detectPackageManager3(dir) {
|
|
34559
34788
|
return (async () => {
|
|
34560
|
-
if (await fileExists4(
|
|
34561
|
-
if (await fileExists4(
|
|
34789
|
+
if (await fileExists4(join36(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
34790
|
+
if (await fileExists4(join36(dir, "yarn.lock"))) return "yarn";
|
|
34562
34791
|
return "npm";
|
|
34563
34792
|
})();
|
|
34564
34793
|
}
|
|
@@ -34590,12 +34819,12 @@ function detectPortFromScripts(pkg) {
|
|
|
34590
34819
|
return null;
|
|
34591
34820
|
}
|
|
34592
34821
|
async function isMonorepo(dir) {
|
|
34593
|
-
return await fileExists4(
|
|
34822
|
+
return await fileExists4(join36(dir, "turbo.json")) || await fileExists4(join36(dir, "pnpm-workspace.yaml"));
|
|
34594
34823
|
}
|
|
34595
34824
|
async function detectServers(projectPath) {
|
|
34596
34825
|
let pkg;
|
|
34597
34826
|
try {
|
|
34598
|
-
const raw = await
|
|
34827
|
+
const raw = await readFile24(join36(projectPath, "package.json"), "utf-8");
|
|
34599
34828
|
pkg = JSON.parse(raw);
|
|
34600
34829
|
} catch {
|
|
34601
34830
|
return {
|
|
@@ -34611,15 +34840,15 @@ async function detectServers(projectPath) {
|
|
|
34611
34840
|
const mono = await isMonorepo(projectPath);
|
|
34612
34841
|
const servers = [];
|
|
34613
34842
|
if (mono) {
|
|
34614
|
-
const appsDir =
|
|
34843
|
+
const appsDir = join36(projectPath, "apps");
|
|
34615
34844
|
try {
|
|
34616
34845
|
const entries = await readdir5(appsDir, { withFileTypes: true });
|
|
34617
34846
|
const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
34618
34847
|
for (const entry of sorted) {
|
|
34619
34848
|
if (!entry.isDirectory()) continue;
|
|
34620
|
-
const appPkgPath =
|
|
34849
|
+
const appPkgPath = join36(appsDir, entry.name, "package.json");
|
|
34621
34850
|
try {
|
|
34622
|
-
const appRaw = await
|
|
34851
|
+
const appRaw = await readFile24(appPkgPath, "utf-8");
|
|
34623
34852
|
const appPkg = JSON.parse(appRaw);
|
|
34624
34853
|
const appName = entry.name;
|
|
34625
34854
|
const framework = detectFramework(appPkg);
|
|
@@ -34662,14 +34891,14 @@ var init_server_detect = __esm({
|
|
|
34662
34891
|
});
|
|
34663
34892
|
|
|
34664
34893
|
// src/lib/port-verify.ts
|
|
34665
|
-
import { readFile as
|
|
34894
|
+
import { readFile as readFile25 } from "node:fs/promises";
|
|
34666
34895
|
async function verifyPorts(projectPath, portAllocations) {
|
|
34667
34896
|
const mismatches = [];
|
|
34668
34897
|
const allocatedPorts = new Set(portAllocations.map((a) => a.port));
|
|
34669
34898
|
const packageJsonPaths = await findPackageJsonFiles(projectPath, projectPath);
|
|
34670
34899
|
for (const pkgPath of packageJsonPaths) {
|
|
34671
34900
|
try {
|
|
34672
|
-
const raw = await
|
|
34901
|
+
const raw = await readFile25(pkgPath, "utf-8");
|
|
34673
34902
|
const pkg = JSON.parse(raw);
|
|
34674
34903
|
const scriptPort = detectPortFromScripts(pkg);
|
|
34675
34904
|
if (scriptPort !== null && !allocatedPorts.has(scriptPort)) {
|
|
@@ -34732,7 +34961,7 @@ async function findUnallocatedApps(projectPath, portAllocations) {
|
|
|
34732
34961
|
}
|
|
34733
34962
|
let pkg;
|
|
34734
34963
|
try {
|
|
34735
|
-
const raw = await
|
|
34964
|
+
const raw = await readFile25(`${app.absPath}/package.json`, "utf-8");
|
|
34736
34965
|
pkg = JSON.parse(raw);
|
|
34737
34966
|
} catch {
|
|
34738
34967
|
continue;
|
|
@@ -34782,8 +35011,8 @@ __export(ports_exports, {
|
|
|
34782
35011
|
parseEnvFile: () => parseEnvFile,
|
|
34783
35012
|
runPorts: () => runPorts
|
|
34784
35013
|
});
|
|
34785
|
-
import { mkdir as mkdir11, readFile as
|
|
34786
|
-
import { join as
|
|
35014
|
+
import { mkdir as mkdir11, readFile as readFile26, writeFile as writeFile20 } from "node:fs/promises";
|
|
35015
|
+
import { join as join37 } from "node:path";
|
|
34787
35016
|
function printDetectionResult(result, projectPath) {
|
|
34788
35017
|
console.log(`
|
|
34789
35018
|
CodeByPlan Ports - List`);
|
|
@@ -34939,12 +35168,12 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
34939
35168
|
// and ServerLocalConfig.port_allocations is typed the same — honest end-to-end.
|
|
34940
35169
|
port_allocations: portAllocations
|
|
34941
35170
|
};
|
|
34942
|
-
const codebyplanDir =
|
|
34943
|
-
const filePath =
|
|
35171
|
+
const codebyplanDir = join37(projectPath, ".codebyplan");
|
|
35172
|
+
const filePath = join37(codebyplanDir, "server.local.json");
|
|
34944
35173
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
34945
35174
|
let currentJson = "";
|
|
34946
35175
|
try {
|
|
34947
|
-
currentJson = await
|
|
35176
|
+
currentJson = await readFile26(filePath, "utf-8");
|
|
34948
35177
|
} catch {
|
|
34949
35178
|
}
|
|
34950
35179
|
if (currentJson === newJson) {
|
|
@@ -34956,17 +35185,17 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
34956
35185
|
return;
|
|
34957
35186
|
}
|
|
34958
35187
|
await mkdir11(codebyplanDir, { recursive: true });
|
|
34959
|
-
await
|
|
35188
|
+
await writeFile20(filePath, newJson, "utf-8");
|
|
34960
35189
|
console.log(
|
|
34961
35190
|
` Updated .codebyplan/server.local.json (worktree ${resolvedWorktreeId ?? "\u2014"}, ${portAllocations.length} allocation${portAllocations.length === 1 ? "" : "s"}).`
|
|
34962
35191
|
);
|
|
34963
35192
|
}
|
|
34964
35193
|
async function provisionE2eEnv(projectPath, dryRun) {
|
|
34965
|
-
const relSource =
|
|
34966
|
-
const sourcePath =
|
|
35194
|
+
const relSource = join37("apps", "web", ".env.local");
|
|
35195
|
+
const sourcePath = join37(projectPath, relSource);
|
|
34967
35196
|
let sourceRaw;
|
|
34968
35197
|
try {
|
|
34969
|
-
sourceRaw = await
|
|
35198
|
+
sourceRaw = await readFile26(sourcePath, "utf-8");
|
|
34970
35199
|
} catch {
|
|
34971
35200
|
console.warn(
|
|
34972
35201
|
` Skipped .codebyplan/e2e.env \u2014 source ${relSource} not found.`
|
|
@@ -34995,12 +35224,12 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
34995
35224
|
);
|
|
34996
35225
|
return;
|
|
34997
35226
|
}
|
|
34998
|
-
const codebyplanDir =
|
|
34999
|
-
const filePath =
|
|
35227
|
+
const codebyplanDir = join37(projectPath, ".codebyplan");
|
|
35228
|
+
const filePath = join37(codebyplanDir, "e2e.env");
|
|
35000
35229
|
const newContent = lines.join("\n") + "\n";
|
|
35001
35230
|
let currentContent = "";
|
|
35002
35231
|
try {
|
|
35003
|
-
currentContent = await
|
|
35232
|
+
currentContent = await readFile26(filePath, "utf-8");
|
|
35004
35233
|
} catch {
|
|
35005
35234
|
}
|
|
35006
35235
|
if (currentContent === newContent) {
|
|
@@ -35012,7 +35241,7 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
35012
35241
|
return;
|
|
35013
35242
|
}
|
|
35014
35243
|
await mkdir11(codebyplanDir, { recursive: true });
|
|
35015
|
-
await
|
|
35244
|
+
await writeFile20(filePath, newContent, "utf-8");
|
|
35016
35245
|
console.log(
|
|
35017
35246
|
` Provisioned .codebyplan/e2e.env (${lines.length} var${lines.length === 1 ? "" : "s"}).`
|
|
35018
35247
|
);
|
|
@@ -35280,8 +35509,8 @@ __export(docs_exports, {
|
|
|
35280
35509
|
stripRangePrefix: () => stripRangePrefix
|
|
35281
35510
|
});
|
|
35282
35511
|
import { existsSync as existsSync13 } from "node:fs";
|
|
35283
|
-
import { mkdir as mkdir12, readFile as
|
|
35284
|
-
import { dirname as dirname13, isAbsolute, join as
|
|
35512
|
+
import { mkdir as mkdir12, readFile as readFile27, readdir as readdir6, rm as rm2, writeFile as writeFile21 } from "node:fs/promises";
|
|
35513
|
+
import { dirname as dirname13, isAbsolute as isAbsolute2, join as join38, relative as relative7, sep as sep2 } from "node:path";
|
|
35285
35514
|
function selectDependencies(deps) {
|
|
35286
35515
|
const byName = /* @__PURE__ */ new Map();
|
|
35287
35516
|
for (const dep of deps) {
|
|
@@ -35335,12 +35564,12 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
35335
35564
|
}
|
|
35336
35565
|
async function resolveExactVersion(projectPath, dep) {
|
|
35337
35566
|
const candidateDirs = [projectPath];
|
|
35338
|
-
const sourceDir =
|
|
35567
|
+
const sourceDir = join38(projectPath, dirname13(dep.sourcePath));
|
|
35339
35568
|
if (sourceDir !== projectPath) candidateDirs.push(sourceDir);
|
|
35340
35569
|
for (const base of candidateDirs) {
|
|
35341
35570
|
try {
|
|
35342
|
-
const raw = await
|
|
35343
|
-
|
|
35571
|
+
const raw = await readFile27(
|
|
35572
|
+
join38(base, "node_modules", dep.name, "package.json"),
|
|
35344
35573
|
"utf-8"
|
|
35345
35574
|
);
|
|
35346
35575
|
const pkg = JSON.parse(raw);
|
|
@@ -35354,8 +35583,8 @@ async function resolveExactVersion(projectPath, dep) {
|
|
|
35354
35583
|
}
|
|
35355
35584
|
async function readVendorDocsPath(projectPath) {
|
|
35356
35585
|
try {
|
|
35357
|
-
const raw = await
|
|
35358
|
-
|
|
35586
|
+
const raw = await readFile27(
|
|
35587
|
+
join38(projectPath, ".codebyplan", "vendor.json"),
|
|
35359
35588
|
"utf-8"
|
|
35360
35589
|
);
|
|
35361
35590
|
const parsed = JSON.parse(raw);
|
|
@@ -35368,7 +35597,7 @@ async function readVendorDocsPath(projectPath) {
|
|
|
35368
35597
|
}
|
|
35369
35598
|
async function resolveDocsDir(projectPath, flags) {
|
|
35370
35599
|
const configured = flags["dir"] ?? await readVendorDocsPath(projectPath) ?? DEFAULT_DOCS_DIR;
|
|
35371
|
-
const absDir =
|
|
35600
|
+
const absDir = isAbsolute2(configured) ? configured : join38(projectPath, configured);
|
|
35372
35601
|
const rel = relative7(projectPath, absDir);
|
|
35373
35602
|
const relDir = rel === "" || rel.startsWith("..") ? null : rel.split(sep2).join("/");
|
|
35374
35603
|
return { absDir, relDir };
|
|
@@ -35377,7 +35606,7 @@ async function readDocsLock(absDir) {
|
|
|
35377
35606
|
const empty = { generated_at: "", libraries: {} };
|
|
35378
35607
|
let raw;
|
|
35379
35608
|
try {
|
|
35380
|
-
raw = await
|
|
35609
|
+
raw = await readFile27(join38(absDir, LOCK_FILE), "utf-8");
|
|
35381
35610
|
} catch {
|
|
35382
35611
|
return empty;
|
|
35383
35612
|
}
|
|
@@ -35473,10 +35702,10 @@ function buildTopIndex(outcomes) {
|
|
|
35473
35702
|
}
|
|
35474
35703
|
async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
35475
35704
|
const entry = `/${relDir}/`;
|
|
35476
|
-
const gitignorePath =
|
|
35705
|
+
const gitignorePath = join38(projectPath, ".gitignore");
|
|
35477
35706
|
let existing = "";
|
|
35478
35707
|
try {
|
|
35479
|
-
existing = await
|
|
35708
|
+
existing = await readFile27(gitignorePath, "utf-8");
|
|
35480
35709
|
} catch {
|
|
35481
35710
|
}
|
|
35482
35711
|
const lines = existing.split(/\r?\n/).map((l) => l.trim());
|
|
@@ -35488,7 +35717,7 @@ async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
|
35488
35717
|
content += `${GITIGNORE_COMMENT}
|
|
35489
35718
|
${entry}
|
|
35490
35719
|
`;
|
|
35491
|
-
await
|
|
35720
|
+
await writeFile21(gitignorePath, content, "utf-8");
|
|
35492
35721
|
}
|
|
35493
35722
|
return "added";
|
|
35494
35723
|
}
|
|
@@ -35496,7 +35725,7 @@ async function markUncovered(dep, exactVersion, ctx) {
|
|
|
35496
35725
|
console.log(
|
|
35497
35726
|
` uncovered ${dep.name}@${exactVersion || "?"} \u2014 no docs in the library mirror`
|
|
35498
35727
|
);
|
|
35499
|
-
const libPath =
|
|
35728
|
+
const libPath = join38(ctx.absDir, libDirName(dep.name));
|
|
35500
35729
|
if (existsSync13(libPath)) {
|
|
35501
35730
|
if (ctx.dryRun) {
|
|
35502
35731
|
console.log(` would remove stale mirror dir ${libPath}`);
|
|
@@ -35549,14 +35778,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35549
35778
|
}
|
|
35550
35779
|
}
|
|
35551
35780
|
const lockEntry = ctx.lock.libraries[dep.name];
|
|
35552
|
-
const libPath =
|
|
35553
|
-
const versionPath =
|
|
35781
|
+
const libPath = join38(ctx.absDir, libDirName(dep.name));
|
|
35782
|
+
const versionPath = join38(libPath, manifest.resolved_version);
|
|
35554
35783
|
if (manifestMatchesLock(manifest, lockEntry)) {
|
|
35555
35784
|
console.log(` unchanged ${dep.name}@${manifest.resolved_version}`);
|
|
35556
|
-
if (!ctx.dryRun && !existsSync13(
|
|
35785
|
+
if (!ctx.dryRun && !existsSync13(join38(libPath, "INDEX.md"))) {
|
|
35557
35786
|
await mkdir12(libPath, { recursive: true });
|
|
35558
|
-
await
|
|
35559
|
-
|
|
35787
|
+
await writeFile21(
|
|
35788
|
+
join38(libPath, "INDEX.md"),
|
|
35560
35789
|
buildLibIndex(dep.name, manifest),
|
|
35561
35790
|
"utf-8"
|
|
35562
35791
|
);
|
|
@@ -35578,14 +35807,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35578
35807
|
);
|
|
35579
35808
|
continue;
|
|
35580
35809
|
}
|
|
35581
|
-
const target =
|
|
35810
|
+
const target = join38(versionPath, rel);
|
|
35582
35811
|
if (sameVersionLockFiles[file.path] === file.content_hash && existsSync13(target)) {
|
|
35583
35812
|
continue;
|
|
35584
35813
|
}
|
|
35585
35814
|
written++;
|
|
35586
35815
|
if (!ctx.dryRun) {
|
|
35587
35816
|
await mkdir12(dirname13(target), { recursive: true });
|
|
35588
|
-
await
|
|
35817
|
+
await writeFile21(target, file.content, "utf-8");
|
|
35589
35818
|
}
|
|
35590
35819
|
}
|
|
35591
35820
|
let removedFiles = 0;
|
|
@@ -35596,7 +35825,7 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35596
35825
|
const rel = sanitizeDocPath(lockedPath);
|
|
35597
35826
|
if (rel === null) continue;
|
|
35598
35827
|
removedFiles++;
|
|
35599
|
-
if (!ctx.dryRun) await rm2(
|
|
35828
|
+
if (!ctx.dryRun) await rm2(join38(versionPath, rel), { force: true });
|
|
35600
35829
|
}
|
|
35601
35830
|
}
|
|
35602
35831
|
let removedVersionDirs = 0;
|
|
@@ -35611,13 +35840,13 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35611
35840
|
}
|
|
35612
35841
|
removedVersionDirs++;
|
|
35613
35842
|
if (!ctx.dryRun) {
|
|
35614
|
-
await rm2(
|
|
35843
|
+
await rm2(join38(libPath, entry.name), { recursive: true, force: true });
|
|
35615
35844
|
}
|
|
35616
35845
|
}
|
|
35617
35846
|
if (!ctx.dryRun) {
|
|
35618
35847
|
await mkdir12(libPath, { recursive: true });
|
|
35619
|
-
await
|
|
35620
|
-
|
|
35848
|
+
await writeFile21(
|
|
35849
|
+
join38(libPath, "INDEX.md"),
|
|
35621
35850
|
buildLibIndex(dep.name, manifest),
|
|
35622
35851
|
"utf-8"
|
|
35623
35852
|
);
|
|
@@ -35671,7 +35900,7 @@ async function runDocsSync() {
|
|
|
35671
35900
|
);
|
|
35672
35901
|
if (!dryRun) {
|
|
35673
35902
|
await mkdir12(absDir, { recursive: true });
|
|
35674
|
-
await
|
|
35903
|
+
await writeFile21(join38(absDir, "INDEX.md"), buildTopIndex(outcomes), "utf-8");
|
|
35675
35904
|
const libraries = {};
|
|
35676
35905
|
for (const o of outcomes) {
|
|
35677
35906
|
if (o.kind === "synced" || o.kind === "unchanged") {
|
|
@@ -35696,8 +35925,8 @@ async function runDocsSync() {
|
|
|
35696
35925
|
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35697
35926
|
libraries: sortedLibraries
|
|
35698
35927
|
};
|
|
35699
|
-
await
|
|
35700
|
-
|
|
35928
|
+
await writeFile21(
|
|
35929
|
+
join38(absDir, LOCK_FILE),
|
|
35701
35930
|
JSON.stringify(newLock, null, 2) + "\n",
|
|
35702
35931
|
"utf-8"
|
|
35703
35932
|
);
|
|
@@ -35739,7 +35968,7 @@ async function countFilesRecursively(dirPath) {
|
|
|
35739
35968
|
let count = 0;
|
|
35740
35969
|
for (const entry of entries) {
|
|
35741
35970
|
if (entry.isDirectory()) {
|
|
35742
|
-
count += await countFilesRecursively(
|
|
35971
|
+
count += await countFilesRecursively(join38(dirPath, entry.name));
|
|
35743
35972
|
} else if (entry.isFile()) {
|
|
35744
35973
|
count++;
|
|
35745
35974
|
}
|
|
@@ -35756,7 +35985,7 @@ async function runDocsStatus() {
|
|
|
35756
35985
|
`);
|
|
35757
35986
|
let raw;
|
|
35758
35987
|
try {
|
|
35759
|
-
raw = await
|
|
35988
|
+
raw = await readFile27(join38(absDir, LOCK_FILE), "utf-8");
|
|
35760
35989
|
} catch {
|
|
35761
35990
|
console.log(
|
|
35762
35991
|
` No ${LOCK_FILE} found \u2014 run \`codebyplan docs sync\` first.
|
|
@@ -35785,7 +36014,7 @@ async function runDocsStatus() {
|
|
|
35785
36014
|
let outOfSync = 0;
|
|
35786
36015
|
for (const name of names) {
|
|
35787
36016
|
const entry = lock.libraries[name];
|
|
35788
|
-
const versionPath =
|
|
36017
|
+
const versionPath = join38(absDir, libDirName(name), entry.resolved_version);
|
|
35789
36018
|
const expected = Object.keys(entry.files).length;
|
|
35790
36019
|
if (!existsSync13(versionPath)) {
|
|
35791
36020
|
outOfSync++;
|
|
@@ -35873,7 +36102,7 @@ var init_docs = __esm({
|
|
|
35873
36102
|
|
|
35874
36103
|
// src/lib/check-baseline.ts
|
|
35875
36104
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
35876
|
-
import { join as
|
|
36105
|
+
import { join as join39 } from "node:path";
|
|
35877
36106
|
function emptyBaseline() {
|
|
35878
36107
|
return {
|
|
35879
36108
|
lint: { known_failing: [] },
|
|
@@ -35883,7 +36112,7 @@ function emptyBaseline() {
|
|
|
35883
36112
|
};
|
|
35884
36113
|
}
|
|
35885
36114
|
function loadBaseline(projectRoot) {
|
|
35886
|
-
const filePath =
|
|
36115
|
+
const filePath = join39(projectRoot, BASELINE_FILENAME);
|
|
35887
36116
|
try {
|
|
35888
36117
|
const raw = readFileSync12(filePath, "utf-8");
|
|
35889
36118
|
const parsed = JSON.parse(raw);
|
|
@@ -35907,7 +36136,7 @@ function loadBaseline(projectRoot) {
|
|
|
35907
36136
|
}
|
|
35908
36137
|
}
|
|
35909
36138
|
function saveBaseline(projectRoot, baseline) {
|
|
35910
|
-
const filePath =
|
|
36139
|
+
const filePath = join39(projectRoot, BASELINE_FILENAME);
|
|
35911
36140
|
writeFileSync7(filePath, JSON.stringify(baseline, null, 2) + "\n", "utf-8");
|
|
35912
36141
|
}
|
|
35913
36142
|
function diffBaseline(check, currentFailingPackages, baseline) {
|
|
@@ -35957,8 +36186,8 @@ var init_check_baseline = __esm({
|
|
|
35957
36186
|
|
|
35958
36187
|
// src/lib/check.ts
|
|
35959
36188
|
import { readFileSync as readFileSync13, existsSync as existsSync14 } from "node:fs";
|
|
35960
|
-
import { join as
|
|
35961
|
-
import { spawnSync as
|
|
36189
|
+
import { join as join40 } from "node:path";
|
|
36190
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
35962
36191
|
function hasSentinelValue(arrays) {
|
|
35963
36192
|
const SENTINELS = /* @__PURE__ */ new Set([
|
|
35964
36193
|
SUMMARY_UNREADABLE,
|
|
@@ -35973,7 +36202,7 @@ function resolveNewFailures(check, failingPackages, baseline, updateBaseline, no
|
|
|
35973
36202
|
return diffBaseline(check, failingPackages, baseline);
|
|
35974
36203
|
}
|
|
35975
36204
|
function defaultSpawnFn(command, opts) {
|
|
35976
|
-
const result =
|
|
36205
|
+
const result = spawnSync11(command, {
|
|
35977
36206
|
shell: true,
|
|
35978
36207
|
cwd: opts.cwd,
|
|
35979
36208
|
encoding: "utf-8",
|
|
@@ -36025,9 +36254,9 @@ function parseFailingPackagesFromSummary(summaryPath) {
|
|
|
36025
36254
|
return Array.from(failing).sort();
|
|
36026
36255
|
}
|
|
36027
36256
|
function resolveTurboBin(projectRoot) {
|
|
36028
|
-
const localBin =
|
|
36257
|
+
const localBin = join40(projectRoot, "node_modules", ".bin", "turbo");
|
|
36029
36258
|
if (existsSync14(localBin)) return localBin;
|
|
36030
|
-
const workspaceRootBin =
|
|
36259
|
+
const workspaceRootBin = join40(
|
|
36031
36260
|
projectRoot,
|
|
36032
36261
|
"..",
|
|
36033
36262
|
"..",
|
|
@@ -36524,7 +36753,7 @@ var init_check2 = __esm({
|
|
|
36524
36753
|
|
|
36525
36754
|
// src/lib/claude-plan.ts
|
|
36526
36755
|
import * as fs13 from "node:fs";
|
|
36527
|
-
import * as
|
|
36756
|
+
import * as path14 from "node:path";
|
|
36528
36757
|
function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
36529
36758
|
const packaged = walkTemplates(templatesDir);
|
|
36530
36759
|
const packagedBySrc = new Map(packaged.map((f) => [f.src, f]));
|
|
@@ -36538,8 +36767,8 @@ function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
|
36538
36767
|
};
|
|
36539
36768
|
for (const pkg of packaged) {
|
|
36540
36769
|
const inManifest = manifestBySrc.get(pkg.src);
|
|
36541
|
-
const absDest =
|
|
36542
|
-
const absSrc =
|
|
36770
|
+
const absDest = path14.join(projectDir, ".claude", pkg.dest);
|
|
36771
|
+
const absSrc = path14.join(templatesDir, pkg.src);
|
|
36543
36772
|
if (!inManifest) {
|
|
36544
36773
|
plan.newOptIn.push({
|
|
36545
36774
|
packaged: { src: pkg.src, dest: pkg.dest, hash: pkg.hash },
|
|
@@ -36588,7 +36817,7 @@ __export(status_exports, {
|
|
|
36588
36817
|
runStatus: () => runStatus2
|
|
36589
36818
|
});
|
|
36590
36819
|
import * as fs14 from "node:fs";
|
|
36591
|
-
import * as
|
|
36820
|
+
import * as path15 from "node:path";
|
|
36592
36821
|
import { execSync as execSync9 } from "node:child_process";
|
|
36593
36822
|
function makeFailSafe(checked_at) {
|
|
36594
36823
|
return {
|
|
@@ -36601,6 +36830,8 @@ function makeFailSafe(checked_at) {
|
|
|
36601
36830
|
new_in_package: [],
|
|
36602
36831
|
removed_from_package: [],
|
|
36603
36832
|
settings_drift: false,
|
|
36833
|
+
settings_missing: false,
|
|
36834
|
+
settings_ignored: false,
|
|
36604
36835
|
guarded: true,
|
|
36605
36836
|
guard_reason: "unknown",
|
|
36606
36837
|
in_sync: true,
|
|
@@ -36666,6 +36897,8 @@ async function runStatus2(argv) {
|
|
|
36666
36897
|
new_in_package: [],
|
|
36667
36898
|
removed_from_package: [],
|
|
36668
36899
|
settings_drift: false,
|
|
36900
|
+
settings_missing: false,
|
|
36901
|
+
settings_ignored: false,
|
|
36669
36902
|
guarded: true,
|
|
36670
36903
|
// guarded:true must always pair with a non-null reason. canonical_source
|
|
36671
36904
|
// keeps its reason; the bare no-manifest case (never-installed consumer)
|
|
@@ -36693,12 +36926,12 @@ async function runStatus2(argv) {
|
|
|
36693
36926
|
const latest = fetchLatestVersion();
|
|
36694
36927
|
const newer = latest !== null && compareSemver(latest, installed) > 0;
|
|
36695
36928
|
let settings_drift = false;
|
|
36696
|
-
const settingsPath =
|
|
36697
|
-
const baseSettingsPath =
|
|
36929
|
+
const settingsPath = path15.join(projectDir, ".claude", "settings.json");
|
|
36930
|
+
const baseSettingsPath = path15.join(
|
|
36698
36931
|
templatesDir,
|
|
36699
36932
|
"settings.project.base.json"
|
|
36700
36933
|
);
|
|
36701
|
-
const hooksJsonPath =
|
|
36934
|
+
const hooksJsonPath = path15.join(templatesDir, "hooks", "hooks.json");
|
|
36702
36935
|
if (fs14.existsSync(settingsPath)) {
|
|
36703
36936
|
try {
|
|
36704
36937
|
const settingsRaw = fs14.readFileSync(settingsPath, "utf8");
|
|
@@ -36722,6 +36955,8 @@ async function runStatus2(argv) {
|
|
|
36722
36955
|
settings_drift = false;
|
|
36723
36956
|
}
|
|
36724
36957
|
}
|
|
36958
|
+
const settings_missing = !fs14.existsSync(settingsPath);
|
|
36959
|
+
const settings_ignored = detectSettingsIgnored(projectDir).status === "ignored";
|
|
36725
36960
|
const in_sync = !version_skip && drifted_files.length === 0 && new_in_package.length === 0 && removed_from_package.length === 0 && !settings_drift;
|
|
36726
36961
|
let action = null;
|
|
36727
36962
|
if (guardReason !== "protected_branch") {
|
|
@@ -36737,6 +36972,8 @@ async function runStatus2(argv) {
|
|
|
36737
36972
|
new_in_package,
|
|
36738
36973
|
removed_from_package,
|
|
36739
36974
|
settings_drift,
|
|
36975
|
+
settings_missing,
|
|
36976
|
+
settings_ignored,
|
|
36740
36977
|
// Always false in the full-detection path: a protected_branch consumer
|
|
36741
36978
|
// (the only guarded case that reaches here) must still SEE the segment;
|
|
36742
36979
|
// only canonical_source / no-manifest (Branch A) report guarded:true.
|
|
@@ -36764,10 +37001,10 @@ function emitResult(result, writeCache, quiet, projectDir) {
|
|
|
36764
37001
|
const json = JSON.stringify(result, null, 2);
|
|
36765
37002
|
if (writeCache) {
|
|
36766
37003
|
try {
|
|
36767
|
-
const cacheDir =
|
|
37004
|
+
const cacheDir = path15.join(projectDir, ".codebyplan");
|
|
36768
37005
|
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
36769
37006
|
fs14.writeFileSync(
|
|
36770
|
-
|
|
37007
|
+
path15.join(cacheDir, "claude-status.local.json"),
|
|
36771
37008
|
json + "\n",
|
|
36772
37009
|
"utf8"
|
|
36773
37010
|
);
|
|
@@ -36789,6 +37026,7 @@ var init_status = __esm({
|
|
|
36789
37026
|
init_claude_plan();
|
|
36790
37027
|
init_settings_merge();
|
|
36791
37028
|
init_version_status();
|
|
37029
|
+
init_gitignore_detect();
|
|
36792
37030
|
}
|
|
36793
37031
|
});
|
|
36794
37032
|
|
|
@@ -36910,7 +37148,7 @@ __export(update_exports, {
|
|
|
36910
37148
|
});
|
|
36911
37149
|
import * as fs15 from "node:fs";
|
|
36912
37150
|
import * as os3 from "node:os";
|
|
36913
|
-
import * as
|
|
37151
|
+
import * as path16 from "node:path";
|
|
36914
37152
|
async function runUpdate(opts, deps = {}) {
|
|
36915
37153
|
await Promise.resolve();
|
|
36916
37154
|
const scope = opts.scope ?? "project";
|
|
@@ -36946,9 +37184,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36946
37184
|
finalManifestEntries.push(e);
|
|
36947
37185
|
}
|
|
36948
37186
|
for (const { packaged, absSrc } of plan.overwriteSafe) {
|
|
36949
|
-
const absDest =
|
|
37187
|
+
const absDest = path16.join(projectDir, ".claude", packaged.dest);
|
|
36950
37188
|
if (!opts.dryRun) {
|
|
36951
|
-
fs15.mkdirSync(
|
|
37189
|
+
fs15.mkdirSync(path16.dirname(absDest), { recursive: true });
|
|
36952
37190
|
fs15.copyFileSync(absSrc, absDest);
|
|
36953
37191
|
if (opts.verbose) console.log(`updated ${packaged.dest}`);
|
|
36954
37192
|
} else if (opts.verbose) {
|
|
@@ -36961,7 +37199,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36961
37199
|
absSrc,
|
|
36962
37200
|
onDiskContent
|
|
36963
37201
|
} of plan.overwriteHandEdited) {
|
|
36964
|
-
const absDest =
|
|
37202
|
+
const absDest = path16.join(projectDir, ".claude", packaged.dest);
|
|
36965
37203
|
const newContent = fs15.readFileSync(absSrc);
|
|
36966
37204
|
const showDiff = () => {
|
|
36967
37205
|
console.log(
|
|
@@ -36974,7 +37212,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36974
37212
|
const answer = await promptOverwrite(packaged.dest, opts, showDiff);
|
|
36975
37213
|
if (answer === "overwrite") {
|
|
36976
37214
|
if (!opts.dryRun) {
|
|
36977
|
-
fs15.mkdirSync(
|
|
37215
|
+
fs15.mkdirSync(path16.dirname(absDest), { recursive: true });
|
|
36978
37216
|
fs15.copyFileSync(absSrc, absDest);
|
|
36979
37217
|
}
|
|
36980
37218
|
finalManifestEntries.push(packaged);
|
|
@@ -36990,9 +37228,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36990
37228
|
for (const { packaged, absSrc } of plan.newOptIn) {
|
|
36991
37229
|
const answer = await promptOptIn(packaged.dest, opts);
|
|
36992
37230
|
if (answer === "opt-in") {
|
|
36993
|
-
const absDest =
|
|
37231
|
+
const absDest = path16.join(projectDir, ".claude", packaged.dest);
|
|
36994
37232
|
if (!opts.dryRun) {
|
|
36995
|
-
fs15.mkdirSync(
|
|
37233
|
+
fs15.mkdirSync(path16.dirname(absDest), { recursive: true });
|
|
36996
37234
|
fs15.copyFileSync(absSrc, absDest);
|
|
36997
37235
|
}
|
|
36998
37236
|
finalManifestEntries.push(packaged);
|
|
@@ -37004,25 +37242,25 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37004
37242
|
for (const e of plan.removedFromPackage) {
|
|
37005
37243
|
const answer = await promptRemove(e.dest, opts);
|
|
37006
37244
|
if (answer === "remove") {
|
|
37007
|
-
const absDest =
|
|
37245
|
+
const absDest = path16.join(projectDir, ".claude", e.dest);
|
|
37008
37246
|
if (!opts.dryRun && fs15.existsSync(absDest)) {
|
|
37009
37247
|
fs15.rmSync(absDest);
|
|
37010
|
-
const claudeDir =
|
|
37011
|
-
let cur =
|
|
37012
|
-
while (cur !== claudeDir && cur !==
|
|
37013
|
-
if (
|
|
37248
|
+
const claudeDir = path16.join(projectDir, ".claude");
|
|
37249
|
+
let cur = path16.dirname(absDest);
|
|
37250
|
+
while (cur !== claudeDir && cur !== path16.dirname(cur)) {
|
|
37251
|
+
if (path16.dirname(cur) === claudeDir) break;
|
|
37014
37252
|
try {
|
|
37015
37253
|
fs15.rmdirSync(cur);
|
|
37016
37254
|
if (opts.verbose)
|
|
37017
37255
|
console.log(
|
|
37018
|
-
`pruned empty dir ${
|
|
37256
|
+
`pruned empty dir ${path16.relative(claudeDir, cur)}`
|
|
37019
37257
|
);
|
|
37020
|
-
cur =
|
|
37258
|
+
cur = path16.dirname(cur);
|
|
37021
37259
|
} catch (err) {
|
|
37022
37260
|
const code = err.code;
|
|
37023
37261
|
if (code !== "ENOTEMPTY" && code !== "ENOENT") {
|
|
37024
37262
|
console.warn(
|
|
37025
|
-
`codebyplan claude: could not prune empty dir ${
|
|
37263
|
+
`codebyplan claude: could not prune empty dir ${path16.relative(claudeDir, cur)}: ${err.message}`
|
|
37026
37264
|
);
|
|
37027
37265
|
}
|
|
37028
37266
|
break;
|
|
@@ -37034,12 +37272,12 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37034
37272
|
if (opts.verbose) console.log(`kept (untracked) ${e.dest}`);
|
|
37035
37273
|
}
|
|
37036
37274
|
}
|
|
37037
|
-
const hooksJsonPath =
|
|
37038
|
-
const baseSettingsPath =
|
|
37275
|
+
const hooksJsonPath = path16.join(templatesDir, "hooks", "hooks.json");
|
|
37276
|
+
const baseSettingsPath = path16.join(
|
|
37039
37277
|
templatesDir,
|
|
37040
37278
|
"settings.project.base.json"
|
|
37041
37279
|
);
|
|
37042
|
-
const settingsPath =
|
|
37280
|
+
const settingsPath = path16.join(projectDir, ".claude", "settings.json");
|
|
37043
37281
|
const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
|
|
37044
37282
|
if (fs15.existsSync(baseSettingsPath)) {
|
|
37045
37283
|
const base = JSON.parse(
|
|
@@ -37060,21 +37298,29 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37060
37298
|
) : void 0
|
|
37061
37299
|
);
|
|
37062
37300
|
}
|
|
37301
|
+
await detectAndHealSettingsGitignore(
|
|
37302
|
+
projectDir,
|
|
37303
|
+
{ yes: opts.yes, dryRun: opts.dryRun },
|
|
37304
|
+
deps.detectHealDeps
|
|
37305
|
+
);
|
|
37063
37306
|
if (!opts.dryRun) {
|
|
37064
|
-
fs15.mkdirSync(
|
|
37307
|
+
fs15.mkdirSync(path16.dirname(settingsPath), { recursive: true });
|
|
37065
37308
|
fs15.writeFileSync(
|
|
37066
37309
|
settingsPath,
|
|
37067
37310
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
37068
37311
|
"utf8"
|
|
37069
37312
|
);
|
|
37070
37313
|
}
|
|
37314
|
+
if (!opts.dryRun) {
|
|
37315
|
+
warnIfSettingsUntracked(projectDir, deps.lsFilesDep);
|
|
37316
|
+
}
|
|
37071
37317
|
const gitignoreAction = await ensureManagedGitignoreBlock(
|
|
37072
37318
|
projectDir,
|
|
37073
37319
|
opts.dryRun
|
|
37074
37320
|
);
|
|
37075
37321
|
if (opts.verbose && gitignoreAction !== "unchanged") {
|
|
37076
37322
|
console.log(
|
|
37077
|
-
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${
|
|
37323
|
+
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${path16.relative(projectDir, path16.join(projectDir, ".gitignore"))}`
|
|
37078
37324
|
);
|
|
37079
37325
|
}
|
|
37080
37326
|
if (!opts.dryRun) {
|
|
@@ -37114,9 +37360,9 @@ function runUpdateUser(opts, deps) {
|
|
|
37114
37360
|
return;
|
|
37115
37361
|
}
|
|
37116
37362
|
try {
|
|
37117
|
-
const userDir = deps.userDir ??
|
|
37118
|
-
const settingsPath =
|
|
37119
|
-
const userBaseSettingsPath =
|
|
37363
|
+
const userDir = deps.userDir ?? path16.join(os3.homedir(), ".claude");
|
|
37364
|
+
const settingsPath = path16.join(userDir, "settings.json");
|
|
37365
|
+
const userBaseSettingsPath = path16.join(
|
|
37120
37366
|
templatesDir,
|
|
37121
37367
|
"settings.user.base.json"
|
|
37122
37368
|
);
|
|
@@ -37169,6 +37415,7 @@ var init_update = __esm({
|
|
|
37169
37415
|
"src/cli/claude/update.ts"() {
|
|
37170
37416
|
"use strict";
|
|
37171
37417
|
init_gitignore_block();
|
|
37418
|
+
init_gitignore_detect();
|
|
37172
37419
|
init_templates_dir();
|
|
37173
37420
|
init_manifest();
|
|
37174
37421
|
init_settings_merge();
|
|
@@ -37187,7 +37434,7 @@ __export(uninstall_exports, {
|
|
|
37187
37434
|
});
|
|
37188
37435
|
import * as fs16 from "node:fs";
|
|
37189
37436
|
import * as os4 from "node:os";
|
|
37190
|
-
import * as
|
|
37437
|
+
import * as path17 from "node:path";
|
|
37191
37438
|
async function runUninstall(opts, deps = {}) {
|
|
37192
37439
|
await Promise.resolve();
|
|
37193
37440
|
const scope = opts.scope ?? "project";
|
|
@@ -37216,7 +37463,7 @@ async function runUninstall(opts, deps = {}) {
|
|
|
37216
37463
|
let removed = 0;
|
|
37217
37464
|
let warnings = 0;
|
|
37218
37465
|
for (const entry of manifest.files) {
|
|
37219
|
-
const abs =
|
|
37466
|
+
const abs = path17.join(projectDir, ".claude", entry.dest);
|
|
37220
37467
|
if (!fs16.existsSync(abs)) {
|
|
37221
37468
|
console.warn(
|
|
37222
37469
|
`codebyplan claude uninstall: ${entry.dest} already absent (skipping).`
|
|
@@ -37240,12 +37487,12 @@ async function runUninstall(opts, deps = {}) {
|
|
|
37240
37487
|
if (!opts.dryRun) {
|
|
37241
37488
|
pruneEmptyManagedDirs(projectDir);
|
|
37242
37489
|
}
|
|
37243
|
-
const settingsPath =
|
|
37490
|
+
const settingsPath = path17.join(projectDir, ".claude", "settings.json");
|
|
37244
37491
|
if (fs16.existsSync(settingsPath)) {
|
|
37245
37492
|
const settings = JSON.parse(
|
|
37246
37493
|
fs16.readFileSync(settingsPath, "utf8")
|
|
37247
37494
|
);
|
|
37248
|
-
const baseSettingsPath = templatesDir ?
|
|
37495
|
+
const baseSettingsPath = templatesDir ? path17.join(templatesDir, "settings.project.base.json") : null;
|
|
37249
37496
|
if (baseSettingsPath && fs16.existsSync(baseSettingsPath)) {
|
|
37250
37497
|
const base = JSON.parse(
|
|
37251
37498
|
fs16.readFileSync(baseSettingsPath, "utf8")
|
|
@@ -37303,7 +37550,7 @@ function runUninstallUser(opts, deps) {
|
|
|
37303
37550
|
}
|
|
37304
37551
|
}
|
|
37305
37552
|
try {
|
|
37306
|
-
const userDir = deps.userDir ??
|
|
37553
|
+
const userDir = deps.userDir ?? path17.join(os4.homedir(), ".claude");
|
|
37307
37554
|
const existingManifest = readManifestForScope("user", userDir);
|
|
37308
37555
|
if (!existingManifest) {
|
|
37309
37556
|
console.error(
|
|
@@ -37312,12 +37559,12 @@ function runUninstallUser(opts, deps) {
|
|
|
37312
37559
|
process.exitCode = 1;
|
|
37313
37560
|
return;
|
|
37314
37561
|
}
|
|
37315
|
-
const settingsPath =
|
|
37562
|
+
const settingsPath = path17.join(userDir, "settings.json");
|
|
37316
37563
|
if (fs16.existsSync(settingsPath)) {
|
|
37317
37564
|
const settings = JSON.parse(
|
|
37318
37565
|
fs16.readFileSync(settingsPath, "utf8")
|
|
37319
37566
|
);
|
|
37320
|
-
const userBaseSettingsPath = templatesDir != null ?
|
|
37567
|
+
const userBaseSettingsPath = templatesDir != null ? path17.join(templatesDir, "settings.user.base.json") : null;
|
|
37321
37568
|
if (userBaseSettingsPath && fs16.existsSync(userBaseSettingsPath)) {
|
|
37322
37569
|
const userBase = JSON.parse(
|
|
37323
37570
|
fs16.readFileSync(userBaseSettingsPath, "utf8")
|
|
@@ -37358,7 +37605,7 @@ function runUninstallUser(opts, deps) {
|
|
|
37358
37605
|
function pruneEmptyManagedDirs(projectDir) {
|
|
37359
37606
|
const managedRoots = ["skills", "agents", "hooks", "rules"];
|
|
37360
37607
|
for (const root of managedRoots) {
|
|
37361
|
-
const abs =
|
|
37608
|
+
const abs = path17.join(projectDir, ".claude", root);
|
|
37362
37609
|
if (!fs16.existsSync(abs)) continue;
|
|
37363
37610
|
pruneLeafFirst(abs);
|
|
37364
37611
|
}
|
|
@@ -37369,7 +37616,7 @@ function pruneLeafFirst(dir) {
|
|
|
37369
37616
|
if (!stat3.isDirectory()) return;
|
|
37370
37617
|
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
37371
37618
|
if (entry.isDirectory()) {
|
|
37372
|
-
pruneLeafFirst(
|
|
37619
|
+
pruneLeafFirst(path17.join(dir, entry.name));
|
|
37373
37620
|
}
|
|
37374
37621
|
}
|
|
37375
37622
|
const remaining = fs16.readdirSync(dir);
|
|
@@ -37390,7 +37637,7 @@ var init_uninstall = __esm({
|
|
|
37390
37637
|
|
|
37391
37638
|
// src/lib/verify-parity.ts
|
|
37392
37639
|
import * as fs17 from "node:fs";
|
|
37393
|
-
import * as
|
|
37640
|
+
import * as path18 from "node:path";
|
|
37394
37641
|
function isValidScope(s) {
|
|
37395
37642
|
return s === "org-shared" || s === "project-shared" || REPO_ONLY_RE.test(s);
|
|
37396
37643
|
}
|
|
@@ -37407,25 +37654,25 @@ function checkSiblingParity(opts) {
|
|
|
37407
37654
|
expectedOneSided = DEFAULT_EXPECTED_ONE_SIDED,
|
|
37408
37655
|
ignoredSubtrees
|
|
37409
37656
|
} = opts;
|
|
37410
|
-
const defaultIgnored = [
|
|
37657
|
+
const defaultIgnored = [path18.join(claudeDir, "hooks", "__test-fixtures__")];
|
|
37411
37658
|
const ignored = ignoredSubtrees ?? defaultIgnored;
|
|
37412
37659
|
const violations = [];
|
|
37413
37660
|
const claudeSideRels = /* @__PURE__ */ new Set();
|
|
37414
37661
|
for (const scanDir of SCAN_DIRS) {
|
|
37415
|
-
const baseDir =
|
|
37662
|
+
const baseDir = path18.join(claudeDir, scanDir);
|
|
37416
37663
|
if (!fs17.existsSync(baseDir)) continue;
|
|
37417
37664
|
const entries = readdirRecursive(baseDir);
|
|
37418
37665
|
for (const entry of entries) {
|
|
37419
|
-
const absPath =
|
|
37666
|
+
const absPath = path18.join(baseDir, entry);
|
|
37420
37667
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37421
37668
|
if (ignored.some(
|
|
37422
|
-
(ig) => absPath.startsWith(ig +
|
|
37669
|
+
(ig) => absPath.startsWith(ig + path18.sep) || absPath === ig
|
|
37423
37670
|
)) {
|
|
37424
37671
|
continue;
|
|
37425
37672
|
}
|
|
37426
|
-
const relPath =
|
|
37673
|
+
const relPath = path18.join(scanDir, entry).split(path18.sep).join("/");
|
|
37427
37674
|
claudeSideRels.add(relPath);
|
|
37428
|
-
const templatePath =
|
|
37675
|
+
const templatePath = path18.join(templatesDir, relPath);
|
|
37429
37676
|
if (!fs17.existsSync(templatePath)) {
|
|
37430
37677
|
if (!expectedOneSided.has(relPath) && !isScaffoldFile(entry)) {
|
|
37431
37678
|
violations.push({ type: "missing-twin", path: relPath });
|
|
@@ -37440,14 +37687,14 @@ function checkSiblingParity(opts) {
|
|
|
37440
37687
|
}
|
|
37441
37688
|
}
|
|
37442
37689
|
for (const scanDir of SCAN_DIRS) {
|
|
37443
|
-
const tplBase =
|
|
37690
|
+
const tplBase = path18.join(templatesDir, scanDir);
|
|
37444
37691
|
if (!fs17.existsSync(tplBase)) continue;
|
|
37445
37692
|
const entries = readdirRecursive(tplBase);
|
|
37446
37693
|
for (const entry of entries) {
|
|
37447
|
-
const absPath =
|
|
37694
|
+
const absPath = path18.join(tplBase, entry);
|
|
37448
37695
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37449
37696
|
if (isScaffoldFile(entry)) continue;
|
|
37450
|
-
const relPath =
|
|
37697
|
+
const relPath = path18.join(scanDir, entry).split(path18.sep).join("/");
|
|
37451
37698
|
if (!claudeSideRels.has(relPath) && !expectedOneSided.has(relPath)) {
|
|
37452
37699
|
violations.push({ type: "extra-twin", path: relPath });
|
|
37453
37700
|
}
|
|
@@ -37483,18 +37730,18 @@ function checkScopeMarkers(opts) {
|
|
|
37483
37730
|
const twinDetectionActive = templatesDir != null && fs17.existsSync(templatesDir);
|
|
37484
37731
|
const violations = [];
|
|
37485
37732
|
for (const scanDir of scanDirs) {
|
|
37486
|
-
const baseDir =
|
|
37733
|
+
const baseDir = path18.join(claudeDir, scanDir);
|
|
37487
37734
|
if (!fs17.existsSync(baseDir)) continue;
|
|
37488
37735
|
const entries = readdirRecursive(baseDir);
|
|
37489
37736
|
for (const entry of entries) {
|
|
37490
|
-
const absPath =
|
|
37737
|
+
const absPath = path18.join(baseDir, entry);
|
|
37491
37738
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37492
37739
|
if (!isStructuralEntry(scanDir, entry)) continue;
|
|
37493
|
-
const ext =
|
|
37740
|
+
const ext = path18.extname(entry).toLowerCase();
|
|
37494
37741
|
const isMd = ext === ".md";
|
|
37495
37742
|
const isSh = ext === ".sh";
|
|
37496
37743
|
if (!isMd && !isSh) continue;
|
|
37497
|
-
const relPath =
|
|
37744
|
+
const relPath = path18.join(scanDir, entry).split(path18.sep).join("/");
|
|
37498
37745
|
if (allowlist.has(relPath)) continue;
|
|
37499
37746
|
let content;
|
|
37500
37747
|
try {
|
|
@@ -37508,7 +37755,7 @@ function checkScopeMarkers(opts) {
|
|
|
37508
37755
|
continue;
|
|
37509
37756
|
}
|
|
37510
37757
|
const scopeValue = isMd ? extractFrontmatterScope(content) : extractShScope(content);
|
|
37511
|
-
const managed = twinDetectionActive && fs17.existsSync(
|
|
37758
|
+
const managed = twinDetectionActive && fs17.existsSync(path18.join(templatesDir, relPath));
|
|
37512
37759
|
if (managed) {
|
|
37513
37760
|
if (scopeValue === null) {
|
|
37514
37761
|
} else if (scopeValue === "org-shared") {
|
|
@@ -37562,7 +37809,7 @@ function readdirRecursive(dir, rel = "", visited = /* @__PURE__ */ new Set()) {
|
|
|
37562
37809
|
visited.add(realDir);
|
|
37563
37810
|
const results = [];
|
|
37564
37811
|
for (const name of fs17.readdirSync(dir)) {
|
|
37565
|
-
const full =
|
|
37812
|
+
const full = path18.join(dir, name);
|
|
37566
37813
|
const relName = rel ? `${rel}/${name}` : name;
|
|
37567
37814
|
if (fs17.lstatSync(full).isDirectory()) {
|
|
37568
37815
|
results.push(...readdirRecursive(full, relName, visited));
|
|
@@ -37635,12 +37882,12 @@ __export(verify_parity_exports, {
|
|
|
37635
37882
|
verifyParity: () => verifyParity
|
|
37636
37883
|
});
|
|
37637
37884
|
import * as fs18 from "node:fs";
|
|
37638
|
-
import * as
|
|
37885
|
+
import * as path19 from "node:path";
|
|
37639
37886
|
function verifyParity(args, deps = {}) {
|
|
37640
37887
|
const warnOnly = args.includes("--warn-only");
|
|
37641
37888
|
const jsonMode = args.includes("--json");
|
|
37642
37889
|
const projectDir = deps.cwd ?? process.cwd();
|
|
37643
|
-
const claudeDir =
|
|
37890
|
+
const claudeDir = path19.join(projectDir, ".claude");
|
|
37644
37891
|
if (!fs18.existsSync(claudeDir)) {
|
|
37645
37892
|
const msg = "codebyplan claude verify-parity: .claude/ not found in cwd \u2014 run from the project root.\n";
|
|
37646
37893
|
process.stderr.write(msg);
|
|
@@ -38147,11 +38394,11 @@ var generate_exports = {};
|
|
|
38147
38394
|
__export(generate_exports, {
|
|
38148
38395
|
runGenerate: () => runGenerate
|
|
38149
38396
|
});
|
|
38150
|
-
import { readFile as
|
|
38151
|
-
import { join as
|
|
38397
|
+
import { readFile as readFile28, mkdir as mkdir13, writeFile as writeFile22 } from "node:fs/promises";
|
|
38398
|
+
import { join as join47, resolve as resolve11 } from "node:path";
|
|
38152
38399
|
async function readJsonFile4(filePath) {
|
|
38153
38400
|
try {
|
|
38154
|
-
const raw = await
|
|
38401
|
+
const raw = await readFile28(filePath, "utf-8");
|
|
38155
38402
|
return JSON.parse(raw);
|
|
38156
38403
|
} catch {
|
|
38157
38404
|
return null;
|
|
@@ -38159,7 +38406,7 @@ async function readJsonFile4(filePath) {
|
|
|
38159
38406
|
}
|
|
38160
38407
|
async function readPkgName(absPath) {
|
|
38161
38408
|
try {
|
|
38162
|
-
const raw = await
|
|
38409
|
+
const raw = await readFile28(join47(absPath, "package.json"), "utf-8");
|
|
38163
38410
|
const pkg = JSON.parse(raw);
|
|
38164
38411
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
38165
38412
|
} catch {
|
|
@@ -38173,7 +38420,7 @@ async function runGenerate(opts) {
|
|
|
38173
38420
|
const rootDir = resolve11(projectDir);
|
|
38174
38421
|
let packageManager;
|
|
38175
38422
|
try {
|
|
38176
|
-
const raw = await
|
|
38423
|
+
const raw = await readFile28(join47(rootDir, "package.json"), "utf-8");
|
|
38177
38424
|
const pkg = JSON.parse(raw);
|
|
38178
38425
|
if (typeof pkg.packageManager === "string") {
|
|
38179
38426
|
packageManager = pkg.packageManager;
|
|
@@ -38181,7 +38428,7 @@ async function runGenerate(opts) {
|
|
|
38181
38428
|
} catch {
|
|
38182
38429
|
}
|
|
38183
38430
|
const serverJson = await readJsonFile4(
|
|
38184
|
-
|
|
38431
|
+
join47(rootDir, ".codebyplan", "server.json")
|
|
38185
38432
|
);
|
|
38186
38433
|
const ports = [];
|
|
38187
38434
|
for (const alloc of serverJson?.port_allocations ?? []) {
|
|
@@ -38194,7 +38441,7 @@ async function runGenerate(opts) {
|
|
|
38194
38441
|
}
|
|
38195
38442
|
}
|
|
38196
38443
|
const gitJson = await readJsonFile4(
|
|
38197
|
-
|
|
38444
|
+
join47(rootDir, ".codebyplan", "git.json")
|
|
38198
38445
|
);
|
|
38199
38446
|
const branchModel = gitJson?.branch_config?.production ? {
|
|
38200
38447
|
production: gitJson.branch_config.production,
|
|
@@ -38203,7 +38450,7 @@ async function runGenerate(opts) {
|
|
|
38203
38450
|
)
|
|
38204
38451
|
} : void 0;
|
|
38205
38452
|
const shipmentJson = await readJsonFile4(
|
|
38206
|
-
|
|
38453
|
+
join47(rootDir, ".codebyplan", "shipment.json")
|
|
38207
38454
|
);
|
|
38208
38455
|
const shipmentSurfaces = [];
|
|
38209
38456
|
const rawSurfaces = shipmentJson?.shipment?.surfaces ?? shipmentJson?.surfaces ?? {};
|
|
@@ -38274,10 +38521,10 @@ async function runGenerate(opts) {
|
|
|
38274
38521
|
const structureMdContent = generateStructureMd(config);
|
|
38275
38522
|
const agentsContent = generateAgentsMd(structureMdContent);
|
|
38276
38523
|
if (check) {
|
|
38277
|
-
const agentsMdPath2 =
|
|
38524
|
+
const agentsMdPath2 = join47(rootDir, "AGENTS.md");
|
|
38278
38525
|
let existingAgents = null;
|
|
38279
38526
|
try {
|
|
38280
|
-
existingAgents = await
|
|
38527
|
+
existingAgents = await readFile28(agentsMdPath2, "utf-8");
|
|
38281
38528
|
} catch {
|
|
38282
38529
|
existingAgents = null;
|
|
38283
38530
|
}
|
|
@@ -38313,16 +38560,16 @@ async function runGenerate(opts) {
|
|
|
38313
38560
|
process.stdout.write(agentsContent);
|
|
38314
38561
|
return;
|
|
38315
38562
|
}
|
|
38316
|
-
const outputDir =
|
|
38563
|
+
const outputDir = join47(rootDir, ".claude", "generated");
|
|
38317
38564
|
await mkdir13(outputDir, { recursive: true });
|
|
38318
|
-
const outputPath =
|
|
38319
|
-
await
|
|
38565
|
+
const outputPath = join47(outputDir, "structure.md");
|
|
38566
|
+
await writeFile22(outputPath, structureMdContent, "utf-8");
|
|
38320
38567
|
process.stdout.write(`Wrote: .claude/generated/structure.md
|
|
38321
38568
|
`);
|
|
38322
|
-
const agentsMdPath =
|
|
38569
|
+
const agentsMdPath = join47(rootDir, "AGENTS.md");
|
|
38323
38570
|
let existingAgentsContent = null;
|
|
38324
38571
|
try {
|
|
38325
|
-
existingAgentsContent = await
|
|
38572
|
+
existingAgentsContent = await readFile28(agentsMdPath, "utf-8");
|
|
38326
38573
|
} catch {
|
|
38327
38574
|
existingAgentsContent = null;
|
|
38328
38575
|
}
|
|
@@ -38330,7 +38577,7 @@ async function runGenerate(opts) {
|
|
|
38330
38577
|
process.stdout.write(`Up to date: AGENTS.md
|
|
38331
38578
|
`);
|
|
38332
38579
|
} else {
|
|
38333
|
-
await
|
|
38580
|
+
await writeFile22(agentsMdPath, agentsContent, "utf-8");
|
|
38334
38581
|
process.stdout.write(`Wrote: AGENTS.md
|
|
38335
38582
|
`);
|
|
38336
38583
|
}
|
|
@@ -38350,11 +38597,11 @@ __export(readme_exports, {
|
|
|
38350
38597
|
runReadme: () => runReadme,
|
|
38351
38598
|
runReadmeCommand: () => runReadmeCommand
|
|
38352
38599
|
});
|
|
38353
|
-
import { readFile as
|
|
38354
|
-
import { join as
|
|
38600
|
+
import { readFile as readFile29, writeFile as writeFile23 } from "node:fs/promises";
|
|
38601
|
+
import { join as join48, resolve as resolve12, relative as relative9 } from "node:path";
|
|
38355
38602
|
async function readJsonFile5(filePath) {
|
|
38356
38603
|
try {
|
|
38357
|
-
const raw = await
|
|
38604
|
+
const raw = await readFile29(filePath, "utf-8");
|
|
38358
38605
|
return JSON.parse(raw);
|
|
38359
38606
|
} catch {
|
|
38360
38607
|
return null;
|
|
@@ -38423,7 +38670,7 @@ async function discoverUnits(rootDir, rootPkgJson) {
|
|
|
38423
38670
|
const discovered = await discoverMonorepoApps(rootDir);
|
|
38424
38671
|
for (const app of discovered) {
|
|
38425
38672
|
const pkgJson = await readJsonFile5(
|
|
38426
|
-
|
|
38673
|
+
join48(app.absPath, "package.json")
|
|
38427
38674
|
);
|
|
38428
38675
|
pkgJsonByPath.set(app.absPath, pkgJson);
|
|
38429
38676
|
allPackages.push({
|
|
@@ -38449,7 +38696,7 @@ async function runReadme(opts) {
|
|
|
38449
38696
|
const init = opts.init ?? opts["init"] ?? false;
|
|
38450
38697
|
const rootDir = resolve12(projectDir);
|
|
38451
38698
|
const rootPkgJson = await readJsonFile5(
|
|
38452
|
-
|
|
38699
|
+
join48(rootDir, "package.json")
|
|
38453
38700
|
);
|
|
38454
38701
|
const { units, allPackages, pkgJsonByPath } = await discoverUnits(
|
|
38455
38702
|
rootDir,
|
|
@@ -38458,11 +38705,11 @@ async function runReadme(opts) {
|
|
|
38458
38705
|
const driftUnits = [];
|
|
38459
38706
|
const missingUnits = [];
|
|
38460
38707
|
for (const unit of units) {
|
|
38461
|
-
const readmePath =
|
|
38462
|
-
const relPath = unit.isRoot ? "README.md" :
|
|
38708
|
+
const readmePath = join48(unit.absPath, "README.md");
|
|
38709
|
+
const relPath = unit.isRoot ? "README.md" : join48(relative9(rootDir, unit.absPath), "README.md");
|
|
38463
38710
|
let existingContent = null;
|
|
38464
38711
|
try {
|
|
38465
|
-
existingContent = await
|
|
38712
|
+
existingContent = await readFile29(readmePath, "utf-8");
|
|
38466
38713
|
} catch {
|
|
38467
38714
|
existingContent = null;
|
|
38468
38715
|
}
|
|
@@ -38497,7 +38744,7 @@ ${newContent}
|
|
|
38497
38744
|
`
|
|
38498
38745
|
);
|
|
38499
38746
|
} else {
|
|
38500
|
-
await
|
|
38747
|
+
await writeFile23(readmePath, newContent, "utf-8");
|
|
38501
38748
|
process.stdout.write(`Wrote (scaffold): ${relPath}
|
|
38502
38749
|
`);
|
|
38503
38750
|
}
|
|
@@ -38535,7 +38782,7 @@ ${newContent}
|
|
|
38535
38782
|
`
|
|
38536
38783
|
);
|
|
38537
38784
|
} else {
|
|
38538
|
-
await
|
|
38785
|
+
await writeFile23(readmePath, newContent, "utf-8");
|
|
38539
38786
|
process.stdout.write(`Wrote (refresh): ${relPath}
|
|
38540
38787
|
`);
|
|
38541
38788
|
}
|
|
@@ -38554,7 +38801,7 @@ ${newContent}
|
|
|
38554
38801
|
`
|
|
38555
38802
|
);
|
|
38556
38803
|
} else {
|
|
38557
|
-
await
|
|
38804
|
+
await writeFile23(readmePath, newContent, "utf-8");
|
|
38558
38805
|
process.stdout.write(`Wrote (init): ${relPath}
|
|
38559
38806
|
`);
|
|
38560
38807
|
}
|
|
@@ -38642,15 +38889,15 @@ __export(migrate_memory_exports, {
|
|
|
38642
38889
|
runMigrateMemory: () => runMigrateMemory
|
|
38643
38890
|
});
|
|
38644
38891
|
import {
|
|
38645
|
-
readFile as
|
|
38646
|
-
writeFile as
|
|
38892
|
+
readFile as readFile30,
|
|
38893
|
+
writeFile as writeFile24,
|
|
38647
38894
|
mkdir as mkdir14,
|
|
38648
38895
|
unlink as unlink6,
|
|
38649
38896
|
rmdir,
|
|
38650
38897
|
readdir as readdir7
|
|
38651
38898
|
} from "node:fs/promises";
|
|
38652
38899
|
import { existsSync as existsSync21 } from "node:fs";
|
|
38653
|
-
import { join as
|
|
38900
|
+
import { join as join49, resolve as resolve13, dirname as dirname15, sep as sep4 } from "node:path";
|
|
38654
38901
|
import { homedir as homedir8 } from "node:os";
|
|
38655
38902
|
function encodeProjectPath(absPath) {
|
|
38656
38903
|
return resolve13(absPath).replace(/[/\\]/g, "-");
|
|
@@ -38661,7 +38908,7 @@ function resolveAutoMemoryDir(opts) {
|
|
|
38661
38908
|
}
|
|
38662
38909
|
const projectDir = opts.projectDir ?? process.cwd();
|
|
38663
38910
|
const encoded = encodeProjectPath(projectDir);
|
|
38664
|
-
return
|
|
38911
|
+
return join49(homedir8(), ".claude", "projects", encoded, "memory");
|
|
38665
38912
|
}
|
|
38666
38913
|
function parseFrontmatter(content) {
|
|
38667
38914
|
content = content.replace(/\r\n/g, "\n");
|
|
@@ -38727,10 +38974,10 @@ async function inventoryFiles(dir) {
|
|
|
38727
38974
|
}
|
|
38728
38975
|
const results = [];
|
|
38729
38976
|
for (const filename of filenames) {
|
|
38730
|
-
const sourcePath =
|
|
38977
|
+
const sourcePath = join49(dir, filename);
|
|
38731
38978
|
let raw;
|
|
38732
38979
|
try {
|
|
38733
|
-
raw = await
|
|
38980
|
+
raw = await readFile30(sourcePath, "utf-8");
|
|
38734
38981
|
} catch (err) {
|
|
38735
38982
|
const msg = err instanceof Error ? err.message : String(err);
|
|
38736
38983
|
results.push({
|
|
@@ -38816,8 +39063,8 @@ async function applyPlan(plan, opts) {
|
|
|
38816
39063
|
if (entry.suggested_action !== "keep") continue;
|
|
38817
39064
|
if (!entry.suggested_target?.startsWith("nested:")) continue;
|
|
38818
39065
|
const relPath = entry.suggested_target.slice("nested:".length);
|
|
38819
|
-
const targetDir = resolve13(
|
|
38820
|
-
const targetFile =
|
|
39066
|
+
const targetDir = resolve13(join49(projectDir, relPath));
|
|
39067
|
+
const targetFile = join49(targetDir, "CLAUDE.md");
|
|
38821
39068
|
if (!targetDir.startsWith(resolve13(projectDir) + sep4)) {
|
|
38822
39069
|
process.stderr.write(
|
|
38823
39070
|
`migrate-memory: skipping unsafe suggested_target "${entry.suggested_target}" \u2014 resolves outside projectDir
|
|
@@ -38849,11 +39096,11 @@ ${anchor}
|
|
|
38849
39096
|
await mkdir14(targetDir, { recursive: true });
|
|
38850
39097
|
let existing = "";
|
|
38851
39098
|
try {
|
|
38852
|
-
existing = await
|
|
39099
|
+
existing = await readFile30(targetFile, "utf-8");
|
|
38853
39100
|
} catch {
|
|
38854
39101
|
}
|
|
38855
39102
|
if (!existing.includes(anchor)) {
|
|
38856
|
-
await
|
|
39103
|
+
await writeFile24(targetFile, existing + appendContent, "utf-8");
|
|
38857
39104
|
}
|
|
38858
39105
|
if (resolve13(entry.source_path).startsWith(resolve13(plan.auto_memory_dir) + sep4)) {
|
|
38859
39106
|
try {
|
|
@@ -38867,7 +39114,7 @@ ${anchor}
|
|
|
38867
39114
|
);
|
|
38868
39115
|
}
|
|
38869
39116
|
}
|
|
38870
|
-
const rootClaudeMd =
|
|
39117
|
+
const rootClaudeMd = join49(projectDir, ".claude", "CLAUDE.md");
|
|
38871
39118
|
if (dryRun) {
|
|
38872
39119
|
process.stdout.write(
|
|
38873
39120
|
`[dry-run] Would ensure ${rootClaudeMd} contains: ${IMPORT_LINE}
|
|
@@ -38876,12 +39123,12 @@ ${anchor}
|
|
|
38876
39123
|
} else {
|
|
38877
39124
|
let claudeMdContent = "";
|
|
38878
39125
|
try {
|
|
38879
|
-
claudeMdContent = await
|
|
39126
|
+
claudeMdContent = await readFile30(rootClaudeMd, "utf-8");
|
|
38880
39127
|
} catch {
|
|
38881
39128
|
await mkdir14(dirname15(rootClaudeMd), { recursive: true });
|
|
38882
39129
|
}
|
|
38883
39130
|
if (!claudeMdContent.includes(IMPORT_LINE)) {
|
|
38884
|
-
await
|
|
39131
|
+
await writeFile24(
|
|
38885
39132
|
rootClaudeMd,
|
|
38886
39133
|
claudeMdContent + `
|
|
38887
39134
|
${IMPORT_LINE}
|
|
@@ -38911,8 +39158,8 @@ ${IMPORT_LINE}
|
|
|
38911
39158
|
} catch {
|
|
38912
39159
|
}
|
|
38913
39160
|
}
|
|
38914
|
-
const memoryMd =
|
|
38915
|
-
const safeRmdirBase =
|
|
39161
|
+
const memoryMd = join49(plan.auto_memory_dir, "MEMORY.md");
|
|
39162
|
+
const safeRmdirBase = join49(homedir8(), ".claude", "projects");
|
|
38916
39163
|
if (dryRun) {
|
|
38917
39164
|
process.stdout.write(`[dry-run] Would delete MEMORY.md: ${memoryMd}
|
|
38918
39165
|
`);
|
|
@@ -38965,7 +39212,7 @@ async function runMigrateMemory(opts) {
|
|
|
38965
39212
|
if (applyFile) {
|
|
38966
39213
|
let planJson;
|
|
38967
39214
|
try {
|
|
38968
|
-
planJson = await
|
|
39215
|
+
planJson = await readFile30(resolve13(applyFile), "utf-8");
|
|
38969
39216
|
} catch (err) {
|
|
38970
39217
|
const msg = err instanceof Error ? err.message : String(err);
|
|
38971
39218
|
process.stderr.write(
|
|
@@ -39036,7 +39283,7 @@ var init_migrate_memory = __esm({
|
|
|
39036
39283
|
|
|
39037
39284
|
// src/lib/claude-mode-audit.ts
|
|
39038
39285
|
import { readdirSync as readdirSync7, readFileSync as readFileSync19, existsSync as existsSync22 } from "node:fs";
|
|
39039
|
-
import { join as
|
|
39286
|
+
import { join as join50, basename as basename2 } from "node:path";
|
|
39040
39287
|
function parseFrontmatter2(content) {
|
|
39041
39288
|
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
39042
39289
|
if (!match) return {};
|
|
@@ -39113,19 +39360,19 @@ function auditSkill(filePath) {
|
|
|
39113
39360
|
}
|
|
39114
39361
|
function auditMode(templatesDir) {
|
|
39115
39362
|
const entries = [];
|
|
39116
|
-
const agentsDir =
|
|
39363
|
+
const agentsDir = join50(templatesDir, "agents");
|
|
39117
39364
|
if (existsSync22(agentsDir)) {
|
|
39118
39365
|
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md")).sort();
|
|
39119
39366
|
for (const f of agentFiles) {
|
|
39120
|
-
entries.push(auditAgent(
|
|
39367
|
+
entries.push(auditAgent(join50(agentsDir, f)));
|
|
39121
39368
|
}
|
|
39122
39369
|
}
|
|
39123
|
-
const skillsDir =
|
|
39370
|
+
const skillsDir = join50(templatesDir, "skills");
|
|
39124
39371
|
if (existsSync22(skillsDir)) {
|
|
39125
39372
|
const skillDirs = readdirSync7(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
39126
39373
|
for (const dir of skillDirs) {
|
|
39127
|
-
if (existsSync22(
|
|
39128
|
-
const skillMd =
|
|
39374
|
+
if (existsSync22(join50(skillsDir, dir, "PROVENANCE.md"))) continue;
|
|
39375
|
+
const skillMd = join50(skillsDir, dir, "SKILL.md");
|
|
39129
39376
|
if (existsSync22(skillMd)) {
|
|
39130
39377
|
entries.push(auditSkill(skillMd));
|
|
39131
39378
|
}
|
|
@@ -39230,9 +39477,9 @@ var resolve_preview_exports = {};
|
|
|
39230
39477
|
__export(resolve_preview_exports, {
|
|
39231
39478
|
resolvePreview: () => resolvePreview
|
|
39232
39479
|
});
|
|
39233
|
-
import { spawnSync as
|
|
39480
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
39234
39481
|
function defaultGetCurrentBranch(cwd) {
|
|
39235
|
-
const result =
|
|
39482
|
+
const result = spawnSync12("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
39236
39483
|
cwd,
|
|
39237
39484
|
encoding: "utf-8",
|
|
39238
39485
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39384,7 +39631,7 @@ __export(new_migration_exports, {
|
|
|
39384
39631
|
newMigration: () => newMigration
|
|
39385
39632
|
});
|
|
39386
39633
|
import * as fs19 from "node:fs";
|
|
39387
|
-
import * as
|
|
39634
|
+
import * as path20 from "node:path";
|
|
39388
39635
|
function slugify(name) {
|
|
39389
39636
|
return name.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_");
|
|
39390
39637
|
}
|
|
@@ -39405,9 +39652,9 @@ function newMigration(args, deps = {}) {
|
|
|
39405
39652
|
}
|
|
39406
39653
|
const slug = slugify(rawName);
|
|
39407
39654
|
const stamp = genTimestamp({ cwd });
|
|
39408
|
-
const migrationsDir =
|
|
39655
|
+
const migrationsDir = path20.join(cwd, "supabase", "migrations");
|
|
39409
39656
|
const filename = `${stamp}_${slug}.sql`;
|
|
39410
|
-
const filePath =
|
|
39657
|
+
const filePath = path20.join(migrationsDir, filename);
|
|
39411
39658
|
mkdirSync11(migrationsDir, { recursive: true });
|
|
39412
39659
|
writeFileSync12(filePath, "");
|
|
39413
39660
|
process.stdout.write(JSON.stringify({ path: filePath }) + "\n");
|
|
@@ -39425,9 +39672,9 @@ var preview_check_exports = {};
|
|
|
39425
39672
|
__export(preview_check_exports, {
|
|
39426
39673
|
previewCheck: () => previewCheck
|
|
39427
39674
|
});
|
|
39428
|
-
import { spawnSync as
|
|
39675
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
39429
39676
|
function defaultRun3(cmd, args) {
|
|
39430
|
-
const result =
|
|
39677
|
+
const result = spawnSync13(cmd, args, {
|
|
39431
39678
|
encoding: "utf-8",
|
|
39432
39679
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39433
39680
|
});
|
|
@@ -39482,10 +39729,10 @@ var init_preview_check = __esm({
|
|
|
39482
39729
|
});
|
|
39483
39730
|
|
|
39484
39731
|
// src/lib/session.ts
|
|
39485
|
-
import { spawnSync as
|
|
39486
|
-
import * as
|
|
39732
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
39733
|
+
import * as path21 from "node:path";
|
|
39487
39734
|
function defaultRun4(cmd, args, cwd) {
|
|
39488
|
-
const result =
|
|
39735
|
+
const result = spawnSync14(cmd, args, {
|
|
39489
39736
|
cwd,
|
|
39490
39737
|
encoding: "utf-8",
|
|
39491
39738
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39513,7 +39760,7 @@ function homeFf(opts = {}) {
|
|
|
39513
39760
|
reason: "git rev-parse --show-toplevel failed"
|
|
39514
39761
|
};
|
|
39515
39762
|
}
|
|
39516
|
-
const folder =
|
|
39763
|
+
const folder = path21.basename(repoRoot);
|
|
39517
39764
|
let current;
|
|
39518
39765
|
try {
|
|
39519
39766
|
current = run("git", ["rev-parse", "--abbrev-ref", "HEAD"], cwd).trim();
|
|
@@ -39546,7 +39793,7 @@ function homeFf(opts = {}) {
|
|
|
39546
39793
|
}
|
|
39547
39794
|
function spawnVersionStatus(cwd) {
|
|
39548
39795
|
try {
|
|
39549
|
-
const result =
|
|
39796
|
+
const result = spawnSync14("npx", ["codebyplan", "version-status"], {
|
|
39550
39797
|
cwd,
|
|
39551
39798
|
encoding: "utf-8",
|
|
39552
39799
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39580,7 +39827,7 @@ function defaultRunInstall(installCommand, cwd) {
|
|
|
39580
39827
|
const cmd = parts[0];
|
|
39581
39828
|
const args = parts.slice(1);
|
|
39582
39829
|
if (!cmd) throw new Error("empty installCommand");
|
|
39583
|
-
const result =
|
|
39830
|
+
const result = spawnSync14(cmd, args, {
|
|
39584
39831
|
cwd,
|
|
39585
39832
|
encoding: "utf-8",
|
|
39586
39833
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39594,7 +39841,7 @@ function defaultRunInstall(installCommand, cwd) {
|
|
|
39594
39841
|
}
|
|
39595
39842
|
}
|
|
39596
39843
|
function defaultRunClaudeUpdate(cwd) {
|
|
39597
|
-
const result =
|
|
39844
|
+
const result = spawnSync14("npx", ["codebyplan", "claude", "update", "--yes"], {
|
|
39598
39845
|
cwd,
|
|
39599
39846
|
encoding: "utf-8",
|
|
39600
39847
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39608,7 +39855,7 @@ function defaultRunClaudeUpdate(cwd) {
|
|
|
39608
39855
|
}
|
|
39609
39856
|
}
|
|
39610
39857
|
function defaultRunGitStatus(cwd) {
|
|
39611
|
-
const result =
|
|
39858
|
+
const result = spawnSync14(
|
|
39612
39859
|
"git",
|
|
39613
39860
|
["status", "--porcelain", "--", ".claude/", ".codebyplan/"],
|
|
39614
39861
|
{
|
|
@@ -39861,9 +40108,9 @@ var commit_exports = {};
|
|
|
39861
40108
|
__export(commit_exports, {
|
|
39862
40109
|
runCommitCommand: () => runCommitCommand
|
|
39863
40110
|
});
|
|
39864
|
-
import { spawnSync as
|
|
40111
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
39865
40112
|
function defaultRun5(cmd, args) {
|
|
39866
|
-
const result =
|
|
40113
|
+
const result = spawnSync15(cmd, args, {
|
|
39867
40114
|
encoding: "utf-8",
|
|
39868
40115
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39869
40116
|
});
|
|
@@ -39911,7 +40158,7 @@ var init_commit = __esm({
|
|
|
39911
40158
|
});
|
|
39912
40159
|
|
|
39913
40160
|
// src/lib/migration-collisions.ts
|
|
39914
|
-
import { spawnSync as
|
|
40161
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
39915
40162
|
function extractPrefix(filename) {
|
|
39916
40163
|
const base = filename.endsWith(".sql") ? filename.slice(0, -4) : filename;
|
|
39917
40164
|
const underscoreIdx = base.indexOf("_");
|
|
@@ -39923,7 +40170,7 @@ function extractPrefix(filename) {
|
|
|
39923
40170
|
}
|
|
39924
40171
|
function makeDefaultRun(cwd) {
|
|
39925
40172
|
return (cmd, args) => {
|
|
39926
|
-
const result =
|
|
40173
|
+
const result = spawnSync16(cmd, args, {
|
|
39927
40174
|
cwd,
|
|
39928
40175
|
encoding: "utf-8",
|
|
39929
40176
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40080,13 +40327,13 @@ function validateWaves(waves) {
|
|
|
40080
40327
|
pathOwners.set(file, owners);
|
|
40081
40328
|
}
|
|
40082
40329
|
}
|
|
40083
|
-
for (const [
|
|
40330
|
+
for (const [path22, owners] of pathOwners) {
|
|
40084
40331
|
if (owners.length > 1) {
|
|
40085
40332
|
violations.push({
|
|
40086
40333
|
invariant: "I",
|
|
40087
40334
|
code: "DUPLICATE_FILE",
|
|
40088
|
-
message: `File "${
|
|
40089
|
-
detail: { path:
|
|
40335
|
+
message: `File "${path22}" appears in multiple waves: ${owners.join(", ")}.`,
|
|
40336
|
+
detail: { path: path22, waves: owners }
|
|
40090
40337
|
});
|
|
40091
40338
|
}
|
|
40092
40339
|
}
|
|
@@ -40180,7 +40427,7 @@ var validate_waves_exports = {};
|
|
|
40180
40427
|
__export(validate_waves_exports, {
|
|
40181
40428
|
runValidateWavesCommand: () => runValidateWavesCommand
|
|
40182
40429
|
});
|
|
40183
|
-
import { readFile as
|
|
40430
|
+
import { readFile as readFile31 } from "node:fs/promises";
|
|
40184
40431
|
async function readStdin() {
|
|
40185
40432
|
return new Promise((resolve16, reject) => {
|
|
40186
40433
|
const chunks = [];
|
|
@@ -40199,7 +40446,7 @@ async function runValidateWavesCommand(args) {
|
|
|
40199
40446
|
let raw;
|
|
40200
40447
|
if (filePath) {
|
|
40201
40448
|
try {
|
|
40202
|
-
raw = await
|
|
40449
|
+
raw = await readFile31(filePath, "utf-8");
|
|
40203
40450
|
} catch (err) {
|
|
40204
40451
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40205
40452
|
process.stderr.write(
|
|
@@ -40279,12 +40526,12 @@ var init_validate_waves2 = __esm({
|
|
|
40279
40526
|
});
|
|
40280
40527
|
|
|
40281
40528
|
// src/cli/worktree/path.ts
|
|
40282
|
-
import { dirname as dirname16, basename as basename4, join as
|
|
40529
|
+
import { dirname as dirname16, basename as basename4, join as join52 } from "node:path";
|
|
40283
40530
|
function computeWorktreePath(cwd, checkpointNumber) {
|
|
40284
40531
|
const parent = dirname16(cwd);
|
|
40285
40532
|
const base = basename4(cwd);
|
|
40286
40533
|
const nnn = String(checkpointNumber).padStart(3, "0");
|
|
40287
|
-
return
|
|
40534
|
+
return join52(parent, `${base}-CHK-${nnn}`);
|
|
40288
40535
|
}
|
|
40289
40536
|
var init_path = __esm({
|
|
40290
40537
|
"src/cli/worktree/path.ts"() {
|
|
@@ -40293,9 +40540,9 @@ var init_path = __esm({
|
|
|
40293
40540
|
});
|
|
40294
40541
|
|
|
40295
40542
|
// src/cli/worktree/add.ts
|
|
40296
|
-
import { join as
|
|
40297
|
-
import { mkdir as mkdir15, readFile as
|
|
40298
|
-
import { spawnSync as
|
|
40543
|
+
import { join as join53, basename as basename5 } from "node:path";
|
|
40544
|
+
import { mkdir as mkdir15, readFile as readFile32, writeFile as writeFile25 } from "node:fs/promises";
|
|
40545
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
40299
40546
|
async function defaultGetRepoId(cwd) {
|
|
40300
40547
|
const found = await findCodebyplanConfig(cwd);
|
|
40301
40548
|
return found?.contents.repo_id ?? null;
|
|
@@ -40324,7 +40571,7 @@ async function defaultLookupBranch(repoId, checkpointNumber) {
|
|
|
40324
40571
|
return { found: true, branch_name: chk.branch_name };
|
|
40325
40572
|
}
|
|
40326
40573
|
function defaultGitRun(args, cwd) {
|
|
40327
|
-
const result =
|
|
40574
|
+
const result = spawnSync17("git", args, {
|
|
40328
40575
|
cwd,
|
|
40329
40576
|
encoding: "utf-8",
|
|
40330
40577
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40336,34 +40583,56 @@ function defaultGitRun(args, cwd) {
|
|
|
40336
40583
|
error: result.error
|
|
40337
40584
|
};
|
|
40338
40585
|
}
|
|
40586
|
+
async function copyClaudeSettings(srcCwd, destPath, deps = {}) {
|
|
40587
|
+
const readFileFn = deps.readFileFn ?? ((p) => readFile32(p, "utf-8"));
|
|
40588
|
+
const writeFileFn = deps.writeFileFn ?? ((p, content) => writeFile25(p, content, "utf-8"));
|
|
40589
|
+
const existsFn = deps.existsFn ?? ((p) => import("node:fs/promises").then(
|
|
40590
|
+
(fsp) => fsp.access(p).then(() => true).catch(() => false)
|
|
40591
|
+
));
|
|
40592
|
+
const mkdirFn = deps.mkdirFn ?? ((p, opts) => mkdir15(p, opts));
|
|
40593
|
+
await mkdirFn(join53(destPath, ".claude"), { recursive: true });
|
|
40594
|
+
const claudeStubs = ["settings.json", "settings.local.json"];
|
|
40595
|
+
for (const stub of claudeStubs) {
|
|
40596
|
+
const srcFile = join53(srcCwd, ".claude", stub);
|
|
40597
|
+
const destFile = join53(destPath, ".claude", stub);
|
|
40598
|
+
try {
|
|
40599
|
+
const destExists = await existsFn(destFile);
|
|
40600
|
+
if (destExists) continue;
|
|
40601
|
+
const content = await readFileFn(srcFile);
|
|
40602
|
+
await writeFileFn(destFile, content);
|
|
40603
|
+
} catch {
|
|
40604
|
+
}
|
|
40605
|
+
}
|
|
40606
|
+
}
|
|
40339
40607
|
async function defaultCopyConfigStubs(srcCwd, destPath) {
|
|
40340
|
-
await mkdir15(
|
|
40608
|
+
await mkdir15(join53(destPath, ".codebyplan"), { recursive: true });
|
|
40341
40609
|
const topLevelStubs = [".mcp.json", ".env.local"];
|
|
40342
40610
|
for (const stub of topLevelStubs) {
|
|
40343
40611
|
try {
|
|
40344
|
-
const content = await
|
|
40345
|
-
await
|
|
40612
|
+
const content = await readFile32(join53(srcCwd, stub), "utf-8");
|
|
40613
|
+
await writeFile25(join53(destPath, stub), content, "utf-8");
|
|
40346
40614
|
} catch {
|
|
40347
40615
|
}
|
|
40348
40616
|
}
|
|
40349
40617
|
try {
|
|
40350
|
-
const content = await
|
|
40351
|
-
|
|
40618
|
+
const content = await readFile32(
|
|
40619
|
+
join53(srcCwd, ".codebyplan", "repo.json"),
|
|
40352
40620
|
"utf-8"
|
|
40353
40621
|
);
|
|
40354
|
-
await
|
|
40355
|
-
|
|
40622
|
+
await writeFile25(
|
|
40623
|
+
join53(destPath, ".codebyplan", "repo.json"),
|
|
40356
40624
|
content,
|
|
40357
40625
|
"utf-8"
|
|
40358
40626
|
);
|
|
40359
40627
|
} catch {
|
|
40360
40628
|
}
|
|
40629
|
+
await copyClaudeSettings(srcCwd, destPath);
|
|
40361
40630
|
}
|
|
40362
|
-
async function defaultRegisterWorktree(repoId, name,
|
|
40631
|
+
async function defaultRegisterWorktree(repoId, name, path22) {
|
|
40363
40632
|
const res = await apiPost("/worktrees", {
|
|
40364
40633
|
repo_id: repoId,
|
|
40365
40634
|
name,
|
|
40366
|
-
path:
|
|
40635
|
+
path: path22,
|
|
40367
40636
|
status: "active"
|
|
40368
40637
|
});
|
|
40369
40638
|
return { worktree_id: res.data.id };
|
|
@@ -40461,10 +40730,12 @@ async function runWorktreeAdd(args, deps = {}) {
|
|
|
40461
40730
|
);
|
|
40462
40731
|
return 1;
|
|
40463
40732
|
}
|
|
40733
|
+
let copyStubsWarn;
|
|
40464
40734
|
try {
|
|
40465
40735
|
await copyConfigStubs(cwd, worktreePath);
|
|
40466
40736
|
} catch (err) {
|
|
40467
40737
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40738
|
+
copyStubsWarn = `Failed to copy config stubs: ${msg}`;
|
|
40468
40739
|
process.stderr.write(`Warning: failed to copy config stubs: ${msg}
|
|
40469
40740
|
`);
|
|
40470
40741
|
}
|
|
@@ -40478,7 +40749,8 @@ async function runWorktreeAdd(args, deps = {}) {
|
|
|
40478
40749
|
status: "added",
|
|
40479
40750
|
worktree_path: worktreePath,
|
|
40480
40751
|
branch_name: branchName,
|
|
40481
|
-
worktree_id
|
|
40752
|
+
worktree_id,
|
|
40753
|
+
...copyStubsWarn ? { warn: copyStubsWarn } : {}
|
|
40482
40754
|
};
|
|
40483
40755
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40484
40756
|
return 0;
|
|
@@ -40513,7 +40785,7 @@ var init_add = __esm({
|
|
|
40513
40785
|
});
|
|
40514
40786
|
|
|
40515
40787
|
// src/cli/worktree/create.ts
|
|
40516
|
-
import { join as
|
|
40788
|
+
import { join as join54 } from "node:path";
|
|
40517
40789
|
async function defaultGetRepoIdentity(cwd) {
|
|
40518
40790
|
const found = await findCodebyplanConfig(cwd);
|
|
40519
40791
|
const contents = found?.contents ?? null;
|
|
@@ -40525,11 +40797,11 @@ async function defaultGetRepoIdentity(cwd) {
|
|
|
40525
40797
|
project_id: typeof contents?.["project_id"] === "string" ? contents["project_id"] : void 0
|
|
40526
40798
|
};
|
|
40527
40799
|
}
|
|
40528
|
-
async function defaultRegisterWorktree2(repoId, name,
|
|
40800
|
+
async function defaultRegisterWorktree2(repoId, name, path22) {
|
|
40529
40801
|
const res = await apiPost("/worktrees", {
|
|
40530
40802
|
repo_id: repoId,
|
|
40531
40803
|
name,
|
|
40532
|
-
path:
|
|
40804
|
+
path: path22,
|
|
40533
40805
|
status: "active"
|
|
40534
40806
|
});
|
|
40535
40807
|
return { worktree_id: res.data.id };
|
|
@@ -40558,6 +40830,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40558
40830
|
const getRepoIdentity = deps.getRepoIdentity ?? defaultGetRepoIdentity;
|
|
40559
40831
|
const getDeviceId = deps.getDeviceId ?? getOrCreateDeviceId;
|
|
40560
40832
|
const registerWorktree = deps.registerWorktree ?? defaultRegisterWorktree2;
|
|
40833
|
+
const copyClaudeSettingsFn = deps.copyClaudeSettingsFn ?? ((srcCwd, destPath) => copyClaudeSettings(srcCwd, destPath));
|
|
40561
40834
|
const identity = await getRepoIdentity(cwd);
|
|
40562
40835
|
const repoId = identity?.repo_id ?? null;
|
|
40563
40836
|
if (!identity || !repoId) {
|
|
@@ -40568,7 +40841,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40568
40841
|
);
|
|
40569
40842
|
return 1;
|
|
40570
40843
|
}
|
|
40571
|
-
const worktreePath = explicitPath ??
|
|
40844
|
+
const worktreePath = explicitPath ?? join54(cwd, "..", name);
|
|
40572
40845
|
const deviceId = await getDeviceId(cwd);
|
|
40573
40846
|
let filesWritten = false;
|
|
40574
40847
|
try {
|
|
@@ -40593,12 +40866,19 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40593
40866
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40594
40867
|
return 0;
|
|
40595
40868
|
}
|
|
40869
|
+
let copyWarn;
|
|
40870
|
+
try {
|
|
40871
|
+
await copyClaudeSettingsFn(cwd, worktreePath);
|
|
40872
|
+
} catch (err) {
|
|
40873
|
+
copyWarn = err instanceof Error ? err.message : String(err);
|
|
40874
|
+
}
|
|
40596
40875
|
try {
|
|
40597
40876
|
const { worktree_id } = await registerWorktree(repoId, name, worktreePath);
|
|
40598
40877
|
const result = {
|
|
40599
40878
|
worktree_files_written: true,
|
|
40600
40879
|
mcp_registered: true,
|
|
40601
|
-
worktree_id
|
|
40880
|
+
worktree_id,
|
|
40881
|
+
...copyWarn ? { warn: `Settings copy failed (non-fatal): ${copyWarn}` } : {}
|
|
40602
40882
|
};
|
|
40603
40883
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40604
40884
|
return 0;
|
|
@@ -40620,12 +40900,13 @@ var init_create = __esm({
|
|
|
40620
40900
|
init_local_config();
|
|
40621
40901
|
init_api();
|
|
40622
40902
|
init_worktree();
|
|
40903
|
+
init_add();
|
|
40623
40904
|
}
|
|
40624
40905
|
});
|
|
40625
40906
|
|
|
40626
40907
|
// src/cli/worktree/remove.ts
|
|
40627
40908
|
import { basename as basename6 } from "node:path";
|
|
40628
|
-
import { spawnSync as
|
|
40909
|
+
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
40629
40910
|
async function defaultGetRepoId2(cwd) {
|
|
40630
40911
|
const found = await findCodebyplanConfig(cwd);
|
|
40631
40912
|
return found?.contents.repo_id ?? null;
|
|
@@ -40647,7 +40928,7 @@ async function defaultDeregisterWorktree(worktreeId) {
|
|
|
40647
40928
|
await mcpCall("delete_worktree", { worktree_id: worktreeId });
|
|
40648
40929
|
}
|
|
40649
40930
|
function defaultGitRun2(args, cwd) {
|
|
40650
|
-
const result =
|
|
40931
|
+
const result = spawnSync18("git", args, {
|
|
40651
40932
|
cwd,
|
|
40652
40933
|
encoding: "utf-8",
|
|
40653
40934
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40660,7 +40941,7 @@ function defaultGitRun2(args, cwd) {
|
|
|
40660
40941
|
};
|
|
40661
40942
|
}
|
|
40662
40943
|
function defaultGetWorktreeBranchName(worktreePath) {
|
|
40663
|
-
const result =
|
|
40944
|
+
const result = spawnSync18("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
40664
40945
|
cwd: worktreePath,
|
|
40665
40946
|
encoding: "utf-8",
|
|
40666
40947
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -41071,7 +41352,7 @@ var init_e2e = __esm({
|
|
|
41071
41352
|
});
|
|
41072
41353
|
|
|
41073
41354
|
// src/cli/e2e/verify-round.ts
|
|
41074
|
-
import { readFile as
|
|
41355
|
+
import { readFile as readFile33 } from "node:fs/promises";
|
|
41075
41356
|
import { resolve as resolve14 } from "node:path";
|
|
41076
41357
|
async function defaultFetchRounds(taskId) {
|
|
41077
41358
|
return mcpCall("get_rounds", { task_id: taskId });
|
|
@@ -41079,7 +41360,7 @@ async function defaultFetchRounds(taskId) {
|
|
|
41079
41360
|
async function defaultReadE2eConfig(cwd) {
|
|
41080
41361
|
try {
|
|
41081
41362
|
const p = resolve14(cwd, ".codebyplan", "e2e.json");
|
|
41082
|
-
const raw = await
|
|
41363
|
+
const raw = await readFile33(p, "utf-8");
|
|
41083
41364
|
return JSON.parse(raw);
|
|
41084
41365
|
} catch {
|
|
41085
41366
|
return null;
|
|
@@ -41204,6 +41485,8 @@ var doctor_exports = {};
|
|
|
41204
41485
|
__export(doctor_exports, {
|
|
41205
41486
|
runDoctor: () => runDoctor
|
|
41206
41487
|
});
|
|
41488
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
41489
|
+
import { join as join55 } from "node:path";
|
|
41207
41490
|
import { execSync as execSync10 } from "node:child_process";
|
|
41208
41491
|
async function checkAuth() {
|
|
41209
41492
|
try {
|
|
@@ -41310,6 +41593,75 @@ async function checkWorktree() {
|
|
|
41310
41593
|
};
|
|
41311
41594
|
}
|
|
41312
41595
|
}
|
|
41596
|
+
function checkSettings() {
|
|
41597
|
+
try {
|
|
41598
|
+
let projectDir;
|
|
41599
|
+
try {
|
|
41600
|
+
projectDir = execSync10("git rev-parse --show-toplevel", {
|
|
41601
|
+
encoding: "utf-8"
|
|
41602
|
+
}).trim();
|
|
41603
|
+
} catch {
|
|
41604
|
+
projectDir = process.cwd();
|
|
41605
|
+
}
|
|
41606
|
+
if (readManifest(projectDir) === null) {
|
|
41607
|
+
return {
|
|
41608
|
+
name: "settings",
|
|
41609
|
+
status: "skip",
|
|
41610
|
+
detail: "codebyplan not installed (no .cbp.manifest.json)"
|
|
41611
|
+
};
|
|
41612
|
+
}
|
|
41613
|
+
if (!existsSync23(join55(projectDir, ".claude", "settings.json"))) {
|
|
41614
|
+
return {
|
|
41615
|
+
name: "settings",
|
|
41616
|
+
status: "warn",
|
|
41617
|
+
detail: ".claude/settings.json missing \u2014 run `codebyplan claude update` to recreate, then git add + commit"
|
|
41618
|
+
};
|
|
41619
|
+
}
|
|
41620
|
+
const ignoreResult = detectSettingsIgnored(projectDir);
|
|
41621
|
+
if (ignoreResult.status === "non-git") {
|
|
41622
|
+
return {
|
|
41623
|
+
name: "settings",
|
|
41624
|
+
status: "skip",
|
|
41625
|
+
detail: "not in a git repo"
|
|
41626
|
+
};
|
|
41627
|
+
}
|
|
41628
|
+
if (ignoreResult.status === "ignored") {
|
|
41629
|
+
const { sourceFile, lineNum, pattern } = ignoreResult.info;
|
|
41630
|
+
return {
|
|
41631
|
+
name: "settings",
|
|
41632
|
+
status: "warn",
|
|
41633
|
+
detail: `.claude/settings.json is gitignored by "${pattern}" (${sourceFile}:${lineNum}) \u2014 remove the rule or run \`codebyplan claude update\` to auto-heal specific rules, then git add + commit`
|
|
41634
|
+
};
|
|
41635
|
+
}
|
|
41636
|
+
const trackedStatus = checkSettingsUntracked(projectDir);
|
|
41637
|
+
if (trackedStatus === "untracked") {
|
|
41638
|
+
return {
|
|
41639
|
+
name: "settings",
|
|
41640
|
+
status: "warn",
|
|
41641
|
+
detail: ".claude/settings.json is untracked \u2014 run `git add .claude/settings.json` and commit it"
|
|
41642
|
+
};
|
|
41643
|
+
}
|
|
41644
|
+
if (trackedStatus === "non-git") {
|
|
41645
|
+
return {
|
|
41646
|
+
name: "settings",
|
|
41647
|
+
status: "skip",
|
|
41648
|
+
detail: "not in a git repo"
|
|
41649
|
+
};
|
|
41650
|
+
}
|
|
41651
|
+
return {
|
|
41652
|
+
name: "settings",
|
|
41653
|
+
status: "ok",
|
|
41654
|
+
detail: ".claude/settings.json present and tracked"
|
|
41655
|
+
};
|
|
41656
|
+
} catch (err) {
|
|
41657
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
41658
|
+
return {
|
|
41659
|
+
name: "settings",
|
|
41660
|
+
status: "warn",
|
|
41661
|
+
detail: `settings check failed: ${msg}`
|
|
41662
|
+
};
|
|
41663
|
+
}
|
|
41664
|
+
}
|
|
41313
41665
|
function overallStatus(checks) {
|
|
41314
41666
|
if (checks.some((c) => c.status === "fail")) return "fail";
|
|
41315
41667
|
if (checks.some((c) => c.status === "warn")) return "warn";
|
|
@@ -41334,7 +41686,7 @@ function printHuman(result) {
|
|
|
41334
41686
|
}
|
|
41335
41687
|
function printHelp6() {
|
|
41336
41688
|
process.stdout.write(
|
|
41337
|
-
"\n codebyplan doctor [--json]\n\n Run diagnostics: auth, version, worktree.\n Always exits 0 \u2014 safe for scripted use.\n\n Flags:\n --json Emit structured JSON instead of the human table\n\n"
|
|
41689
|
+
"\n codebyplan doctor [--json]\n\n Run diagnostics: auth, version, worktree, settings.\n Always exits 0 \u2014 safe for scripted use.\n\n Flags:\n --json Emit structured JSON instead of the human table\n\n"
|
|
41338
41690
|
);
|
|
41339
41691
|
}
|
|
41340
41692
|
async function runDoctor(args) {
|
|
@@ -41348,7 +41700,8 @@ async function runDoctor(args) {
|
|
|
41348
41700
|
const checks = await Promise.all([
|
|
41349
41701
|
checkAuth(),
|
|
41350
41702
|
checkVersion(),
|
|
41351
|
-
checkWorktree()
|
|
41703
|
+
checkWorktree(),
|
|
41704
|
+
Promise.resolve(checkSettings())
|
|
41352
41705
|
]);
|
|
41353
41706
|
const result = {
|
|
41354
41707
|
checks,
|
|
@@ -41372,6 +41725,8 @@ var init_doctor = __esm({
|
|
|
41372
41725
|
init_flags();
|
|
41373
41726
|
init_local_config();
|
|
41374
41727
|
init_resolve_worktree();
|
|
41728
|
+
init_manifest();
|
|
41729
|
+
init_gitignore_detect();
|
|
41375
41730
|
}
|
|
41376
41731
|
});
|
|
41377
41732
|
|