codebyplan 1.13.55 → 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 +992 -586
- package/package.json +1 -1
- package/templates/agents/cbp-e2e-maestro.md +97 -8
- package/templates/agents/cbp-e2e-playwright.md +118 -15
- package/templates/agents/cbp-verify-reviewer.md +8 -0
- package/templates/context/testing/e2e.md +43 -2
- package/templates/github-workflows/ci.yml +19 -14
- 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/templates/rules/e2e-mandatory.md +21 -0
- package/templates/rules/two-tier-ci.md +14 -6
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;
|
|
@@ -31701,15 +31930,26 @@ function detectPnpmVersionFromPackageJson(projectDir) {
|
|
|
31701
31930
|
return "10";
|
|
31702
31931
|
}
|
|
31703
31932
|
}
|
|
31933
|
+
function detectStrictEnforcedFromCiJson(projectDir) {
|
|
31934
|
+
try {
|
|
31935
|
+
const ciJsonPath = path10.join(projectDir, ".codebyplan", "ci.json");
|
|
31936
|
+
const raw = fs9.readFileSync(ciJsonPath, "utf-8");
|
|
31937
|
+
const parsed = JSON.parse(raw);
|
|
31938
|
+
return parsed.workflow?.strict_check_enforced === true;
|
|
31939
|
+
} catch {
|
|
31940
|
+
return false;
|
|
31941
|
+
}
|
|
31942
|
+
}
|
|
31704
31943
|
async function runScaffoldCiWorkflow(opts) {
|
|
31705
31944
|
await Promise.resolve();
|
|
31706
31945
|
const dryRun = opts?.dryRun ?? false;
|
|
31707
31946
|
const force = opts?.force ?? false;
|
|
31708
|
-
const projectDir =
|
|
31947
|
+
const projectDir = path10.resolve(opts?.projectDir ?? process.cwd());
|
|
31709
31948
|
const pnpmVersion = opts?.pnpmVersion ?? detectPnpmVersionFromPackageJson(projectDir);
|
|
31710
31949
|
const nodeVersion = opts?.nodeVersion ?? "22";
|
|
31950
|
+
const strictEnforced = opts?.strictEnforced ?? detectStrictEnforcedFromCiJson(projectDir);
|
|
31711
31951
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
31712
|
-
const templatePath =
|
|
31952
|
+
const templatePath = path10.join(templatesDir, "github-workflows", "ci.yml");
|
|
31713
31953
|
if (!fs9.existsSync(templatePath)) {
|
|
31714
31954
|
throw new Error(
|
|
31715
31955
|
`scaffold-ci-workflow: template not found at ${templatePath}`
|
|
@@ -31718,9 +31958,11 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31718
31958
|
const rawTemplate = fs9.readFileSync(templatePath, "utf-8");
|
|
31719
31959
|
const renderedContent = substituteTokens(rawTemplate, {
|
|
31720
31960
|
PNPM_VERSION: pnpmVersion,
|
|
31721
|
-
NODE_VERSION: nodeVersion
|
|
31961
|
+
NODE_VERSION: nodeVersion,
|
|
31962
|
+
STRICT_NAME_SUFFIX: strictEnforced ? "" : " (report-only)",
|
|
31963
|
+
STRICT_CONTINUE_ON_ERROR_LINE: strictEnforced ? "" : "\n continue-on-error: true"
|
|
31722
31964
|
});
|
|
31723
|
-
const targetPath =
|
|
31965
|
+
const targetPath = path10.join(projectDir, ".github", "workflows", "ci.yml");
|
|
31724
31966
|
if (dryRun) {
|
|
31725
31967
|
return { status: "dry_run", path: targetPath };
|
|
31726
31968
|
}
|
|
@@ -31739,7 +31981,7 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31739
31981
|
);
|
|
31740
31982
|
}
|
|
31741
31983
|
}
|
|
31742
|
-
const targetDir =
|
|
31984
|
+
const targetDir = path10.dirname(targetPath);
|
|
31743
31985
|
fs9.mkdirSync(targetDir, { recursive: true });
|
|
31744
31986
|
const tmpPath = targetPath + ".tmp";
|
|
31745
31987
|
try {
|
|
@@ -31763,10 +32005,10 @@ var init_scaffold_ci_workflow = __esm({
|
|
|
31763
32005
|
|
|
31764
32006
|
// src/lib/gh-required-checks.ts
|
|
31765
32007
|
import * as fs10 from "node:fs";
|
|
31766
|
-
import * as
|
|
32008
|
+
import * as path11 from "node:path";
|
|
31767
32009
|
import { execSync as execSync6 } from "node:child_process";
|
|
31768
32010
|
function readCiJson(projectDir) {
|
|
31769
|
-
const ciPath =
|
|
32011
|
+
const ciPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31770
32012
|
if (!fs10.existsSync(ciPath)) {
|
|
31771
32013
|
return {
|
|
31772
32014
|
platforms: {},
|
|
@@ -31785,15 +32027,15 @@ function readCiJson(projectDir) {
|
|
|
31785
32027
|
}
|
|
31786
32028
|
}
|
|
31787
32029
|
function writeCiJsonAtomic(projectDir, config) {
|
|
31788
|
-
const ciPath =
|
|
32030
|
+
const ciPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31789
32031
|
writeJsonAtomic(ciPath, config);
|
|
31790
32032
|
}
|
|
31791
32033
|
function enforceRequiredCheck(opts) {
|
|
31792
|
-
const projectDir =
|
|
32034
|
+
const projectDir = path11.resolve(opts?.projectDir ?? process.cwd());
|
|
31793
32035
|
const branch = opts?.branch ?? "main";
|
|
31794
32036
|
const checkName = opts?.checkName ?? "Lint + typecheck + test + build";
|
|
31795
32037
|
const dryRun = opts?.dryRun ?? false;
|
|
31796
|
-
const ciPath =
|
|
32038
|
+
const ciPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31797
32039
|
const config = readCiJson(projectDir);
|
|
31798
32040
|
if (config.workflow?.required_check_enforced === true) {
|
|
31799
32041
|
return { status: "already_enforced", path: ciPath };
|
|
@@ -31963,7 +32205,7 @@ function parseFlagsFromArgs2(args) {
|
|
|
31963
32205
|
}
|
|
31964
32206
|
function printHelp3() {
|
|
31965
32207
|
process.stdout.write(
|
|
31966
|
-
'\n codebyplan ci\n\n CI configuration management \u2014 detect platforms, scaffold workflow, enforce required check.\n\n Subcommands:\n init Detect platforms and write/update .codebyplan/ci.json\n scaffold-workflow Write .github/workflows/ci.yml from the bundled template\n enforce-check Enforce the required CI status check on a GitHub branch\n resolve <category> Resolve the shell command for a CI check category (unit_test|typecheck|build|lint|e2e|audit)\n\n Flags (all subcommands):\n --dry-run Preview the operation without writing any files\n --force Overwrite existing content that differs\n --project-dir <p> Target project root (default: current directory)\n --json Emit structured JSON to stdout\n\n Flags (scaffold-workflow only):\n --pnpm-version <v> pnpm version for {{PNPM_VERSION}} token (default: auto-detected from package.json packageManager, falls back to "10")\n --node-version <v> Node.js version for {{NODE_VERSION}} token (default: "22")\n\n Flags (enforce-check only):\n --branch <b> Branch to enforce (default: "main")\n --check-name <n> Status check name (default: "Lint + typecheck + test + build")\n\n Flags (resolve only):\n --platform <slug> Platform slug to resolve against (e.g. next_js, nestjs, package)\n --json Emit the full CiResolveResult as JSON\n\n'
|
|
32208
|
+
'\n codebyplan ci\n\n CI configuration management \u2014 detect platforms, scaffold workflow, enforce required check.\n\n Subcommands:\n init Detect platforms and write/update .codebyplan/ci.json\n scaffold-workflow Write .github/workflows/ci.yml from the bundled template\n enforce-check Enforce the required CI status check on a GitHub branch\n resolve <category> Resolve the shell command for a CI check category (unit_test|typecheck|build|lint|e2e|audit)\n\n Flags (all subcommands):\n --dry-run Preview the operation without writing any files\n --force Overwrite existing content that differs\n --project-dir <p> Target project root (default: current directory)\n --json Emit structured JSON to stdout\n\n Flags (scaffold-workflow only):\n --pnpm-version <v> pnpm version for {{PNPM_VERSION}} token (default: auto-detected from package.json packageManager, falls back to "10")\n --node-version <v> Node.js version for {{NODE_VERSION}} token (default: "22")\n --strict-enforced Emit ci-strict as an enforced gate (continue-on-error:false, no\n report-only suffix). Default: read .codebyplan/ci.json\n workflow.strict_check_enforced (falls back to report-only)\n\n Flags (enforce-check only):\n --branch <b> Branch to enforce (default: "main")\n --check-name <n> Status check name (default: "Lint + typecheck + test + build")\n\n Flags (resolve only):\n --platform <slug> Platform slug to resolve against (e.g. next_js, nestjs, package)\n --json Emit the full CiResolveResult as JSON\n\n'
|
|
31967
32209
|
);
|
|
31968
32210
|
}
|
|
31969
32211
|
function printInitResult(result) {
|
|
@@ -32062,6 +32304,7 @@ async function runCiCommand(args) {
|
|
|
32062
32304
|
if (subcommand === "scaffold-workflow") {
|
|
32063
32305
|
const pnpmVersion = flags["pnpm-version"];
|
|
32064
32306
|
const nodeVersion = flags["node-version"];
|
|
32307
|
+
const strictEnforced = flags["strict-enforced"] ? true : void 0;
|
|
32065
32308
|
let result;
|
|
32066
32309
|
try {
|
|
32067
32310
|
result = await runScaffoldCiWorkflow({
|
|
@@ -32069,7 +32312,8 @@ async function runCiCommand(args) {
|
|
|
32069
32312
|
force,
|
|
32070
32313
|
projectDir,
|
|
32071
32314
|
pnpmVersion,
|
|
32072
|
-
nodeVersion
|
|
32315
|
+
nodeVersion,
|
|
32316
|
+
strictEnforced
|
|
32073
32317
|
});
|
|
32074
32318
|
} catch (err) {
|
|
32075
32319
|
process.stderr.write(
|
|
@@ -32198,9 +32442,9 @@ var init_ci = __esm({
|
|
|
32198
32442
|
|
|
32199
32443
|
// src/lib/cd-init.ts
|
|
32200
32444
|
import * as fs11 from "node:fs";
|
|
32201
|
-
import * as
|
|
32445
|
+
import * as path12 from "node:path";
|
|
32202
32446
|
function detectSurfaces(projectDir) {
|
|
32203
|
-
const shipmentPath =
|
|
32447
|
+
const shipmentPath = path12.join(projectDir, ".codebyplan", "shipment.json");
|
|
32204
32448
|
let shipment;
|
|
32205
32449
|
try {
|
|
32206
32450
|
shipment = JSON.parse(fs11.readFileSync(shipmentPath, "utf-8"));
|
|
@@ -32253,10 +32497,10 @@ function buildDefaultCdConfig(rawSurfaceKeys) {
|
|
|
32253
32497
|
}
|
|
32254
32498
|
async function runCdInit(opts) {
|
|
32255
32499
|
await Promise.resolve();
|
|
32256
|
-
const projectDir =
|
|
32500
|
+
const projectDir = path12.resolve(opts?.projectDir ?? process.cwd());
|
|
32257
32501
|
const dryRun = opts?.dryRun ?? false;
|
|
32258
32502
|
const force = opts?.force ?? false;
|
|
32259
|
-
const cdPath =
|
|
32503
|
+
const cdPath = path12.join(projectDir, ".codebyplan", "cd.json");
|
|
32260
32504
|
const rawSurfaceKeys = detectSurfaces(projectDir);
|
|
32261
32505
|
const seen = /* @__PURE__ */ new Set();
|
|
32262
32506
|
const surfaces = [];
|
|
@@ -32297,7 +32541,7 @@ async function runCdInit(opts) {
|
|
|
32297
32541
|
surfaces: newSurfaces
|
|
32298
32542
|
};
|
|
32299
32543
|
}
|
|
32300
|
-
const codebyplanDir =
|
|
32544
|
+
const codebyplanDir = path12.join(projectDir, ".codebyplan");
|
|
32301
32545
|
fs11.mkdirSync(codebyplanDir, { recursive: true });
|
|
32302
32546
|
writeJsonAtomic(cdPath, newConfig);
|
|
32303
32547
|
return { status: "written", path: cdPath, surfaces };
|
|
@@ -32387,14 +32631,14 @@ var init_cd_init = __esm({
|
|
|
32387
32631
|
|
|
32388
32632
|
// src/lib/scaffold-cd-workflow.ts
|
|
32389
32633
|
import * as fs12 from "node:fs";
|
|
32390
|
-
import * as
|
|
32634
|
+
import * as path13 from "node:path";
|
|
32391
32635
|
async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
32392
32636
|
await Promise.resolve();
|
|
32393
32637
|
const dryRun = opts.dryRun ?? false;
|
|
32394
32638
|
const force = opts.force ?? false;
|
|
32395
|
-
const projectDir =
|
|
32639
|
+
const projectDir = path13.resolve(opts.projectDir ?? process.cwd());
|
|
32396
32640
|
const templatesDir = opts.templatesDir ?? resolveTemplatesDir();
|
|
32397
|
-
const templatePath =
|
|
32641
|
+
const templatePath = path13.join(
|
|
32398
32642
|
templatesDir,
|
|
32399
32643
|
"github-workflows",
|
|
32400
32644
|
templateName
|
|
@@ -32405,7 +32649,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
32405
32649
|
);
|
|
32406
32650
|
}
|
|
32407
32651
|
const templateContent = fs12.readFileSync(templatePath, "utf-8");
|
|
32408
|
-
const targetPath =
|
|
32652
|
+
const targetPath = path13.join(projectDir, ".github", "workflows", targetName);
|
|
32409
32653
|
if (dryRun) {
|
|
32410
32654
|
return { status: "dry_run", path: targetPath };
|
|
32411
32655
|
}
|
|
@@ -32424,7 +32668,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
32424
32668
|
);
|
|
32425
32669
|
}
|
|
32426
32670
|
}
|
|
32427
|
-
const targetDir =
|
|
32671
|
+
const targetDir = path13.dirname(targetPath);
|
|
32428
32672
|
fs12.mkdirSync(targetDir, { recursive: true });
|
|
32429
32673
|
const tmpPath = targetPath + ".tmp";
|
|
32430
32674
|
try {
|
|
@@ -33100,7 +33344,7 @@ __export(version_status_exports, {
|
|
|
33100
33344
|
});
|
|
33101
33345
|
import { execFileSync, execSync as execSync7 } from "node:child_process";
|
|
33102
33346
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
33103
|
-
import { dirname as dirname12, join as
|
|
33347
|
+
import { dirname as dirname12, join as join31 } from "node:path";
|
|
33104
33348
|
function fetchLatestVersion() {
|
|
33105
33349
|
try {
|
|
33106
33350
|
return execFileSync("npm", ["view", "codebyplan", "version"], {
|
|
@@ -33124,9 +33368,9 @@ function detectPackageManager2(gitRoot) {
|
|
|
33124
33368
|
let dir = process.cwd();
|
|
33125
33369
|
const stopAt = gitRoot ?? null;
|
|
33126
33370
|
while (true) {
|
|
33127
|
-
if (existsSync10(
|
|
33128
|
-
if (existsSync10(
|
|
33129
|
-
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";
|
|
33130
33374
|
if (stopAt !== null && dir === stopAt) break;
|
|
33131
33375
|
const parent = dirname12(dir);
|
|
33132
33376
|
if (parent === dir) break;
|
|
@@ -33146,7 +33390,7 @@ function buildInstallCommand2(pm) {
|
|
|
33146
33390
|
}
|
|
33147
33391
|
async function resolveGuard(gitRoot, currentBranch) {
|
|
33148
33392
|
if (gitRoot !== null) {
|
|
33149
|
-
const canonicalPkgPath =
|
|
33393
|
+
const canonicalPkgPath = join31(
|
|
33150
33394
|
gitRoot,
|
|
33151
33395
|
"packages",
|
|
33152
33396
|
"codebyplan-package",
|
|
@@ -33170,10 +33414,10 @@ async function resolveGuard(gitRoot, currentBranch) {
|
|
|
33170
33414
|
let gitJsonPath;
|
|
33171
33415
|
if (found.path.endsWith("/repo.json")) {
|
|
33172
33416
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
33173
|
-
gitJsonPath =
|
|
33417
|
+
gitJsonPath = join31(dir, "git.json");
|
|
33174
33418
|
} else {
|
|
33175
33419
|
const legacyDir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
33176
|
-
gitJsonPath =
|
|
33420
|
+
gitJsonPath = join31(legacyDir, ".codebyplan", "git.json");
|
|
33177
33421
|
}
|
|
33178
33422
|
const raw = readFileSync11(gitJsonPath, "utf-8");
|
|
33179
33423
|
const parsed = JSON.parse(raw);
|
|
@@ -33257,8 +33501,8 @@ var upload_e2e_images_exports = {};
|
|
|
33257
33501
|
__export(upload_e2e_images_exports, {
|
|
33258
33502
|
runUploadE2eImagesCommand: () => runUploadE2eImagesCommand
|
|
33259
33503
|
});
|
|
33260
|
-
import { readFile as
|
|
33261
|
-
import { join as
|
|
33504
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
33505
|
+
import { join as join32, basename, resolve as resolve10 } from "node:path";
|
|
33262
33506
|
import { execSync as execSync8 } from "node:child_process";
|
|
33263
33507
|
function baseUrl2() {
|
|
33264
33508
|
return (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
|
|
@@ -33292,8 +33536,8 @@ function parseArgs(args) {
|
|
|
33292
33536
|
}
|
|
33293
33537
|
async function readE2eConfig(projectPath) {
|
|
33294
33538
|
try {
|
|
33295
|
-
const raw = await
|
|
33296
|
-
|
|
33539
|
+
const raw = await readFile20(
|
|
33540
|
+
join32(projectPath, ".codebyplan", "e2e.json"),
|
|
33297
33541
|
"utf-8"
|
|
33298
33542
|
);
|
|
33299
33543
|
return JSON.parse(raw);
|
|
@@ -33334,7 +33578,7 @@ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, bas
|
|
|
33334
33578
|
continue;
|
|
33335
33579
|
const isNew = status === "A";
|
|
33336
33580
|
results.push({
|
|
33337
|
-
absolutePath:
|
|
33581
|
+
absolutePath: join32(projectPath, filePath),
|
|
33338
33582
|
filename: basename(filePath),
|
|
33339
33583
|
framework: frameworkName,
|
|
33340
33584
|
is_new: isNew
|
|
@@ -33431,7 +33675,7 @@ async function runUploadE2eImagesCommand(args) {
|
|
|
33431
33675
|
for (const png of allPngs) {
|
|
33432
33676
|
let bytes;
|
|
33433
33677
|
try {
|
|
33434
|
-
bytes = await
|
|
33678
|
+
bytes = await readFile20(png.absolutePath);
|
|
33435
33679
|
} catch {
|
|
33436
33680
|
process.stderr.write(
|
|
33437
33681
|
`upload-e2e-images: could not read file: ${png.absolutePath}
|
|
@@ -33508,10 +33752,10 @@ __export(arch_map_exports, {
|
|
|
33508
33752
|
runArchMapCommand: () => runArchMapCommand,
|
|
33509
33753
|
updateFrontmatterFields: () => updateFrontmatterFields
|
|
33510
33754
|
});
|
|
33511
|
-
import { readFile as
|
|
33755
|
+
import { readFile as readFile21, writeFile as writeFile17 } from "node:fs/promises";
|
|
33512
33756
|
import { existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
|
|
33513
|
-
import { join as
|
|
33514
|
-
import { spawnSync as
|
|
33757
|
+
import { join as join33 } from "node:path";
|
|
33758
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
33515
33759
|
function normalizeModulePath(modulePath) {
|
|
33516
33760
|
return modulePath.replace(/\/+$/, "");
|
|
33517
33761
|
}
|
|
@@ -33535,9 +33779,9 @@ async function resolveCodebyplanDir(startDir) {
|
|
|
33535
33779
|
}
|
|
33536
33780
|
}
|
|
33537
33781
|
async function readArchitectureConfig(codebyplanDir) {
|
|
33538
|
-
const filePath =
|
|
33782
|
+
const filePath = join33(codebyplanDir, "architecture.json");
|
|
33539
33783
|
try {
|
|
33540
|
-
const raw = await
|
|
33784
|
+
const raw = await readFile21(filePath, "utf-8");
|
|
33541
33785
|
const parsed = JSON.parse(raw);
|
|
33542
33786
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.modules)) {
|
|
33543
33787
|
return { version: 1, modules: [] };
|
|
@@ -33548,12 +33792,12 @@ async function readArchitectureConfig(codebyplanDir) {
|
|
|
33548
33792
|
}
|
|
33549
33793
|
}
|
|
33550
33794
|
async function writeArchitectureConfig(codebyplanDir, config) {
|
|
33551
|
-
const filePath =
|
|
33552
|
-
await
|
|
33795
|
+
const filePath = join33(codebyplanDir, "architecture.json");
|
|
33796
|
+
await writeFile17(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
33553
33797
|
}
|
|
33554
33798
|
function resolveGitSha(modulePath, cwd) {
|
|
33555
33799
|
try {
|
|
33556
|
-
const result =
|
|
33800
|
+
const result = spawnSync10(
|
|
33557
33801
|
"git",
|
|
33558
33802
|
["log", "--format=%H", "-1", "--", modulePath],
|
|
33559
33803
|
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -33567,10 +33811,10 @@ function resolveGitSha(modulePath, cwd) {
|
|
|
33567
33811
|
}
|
|
33568
33812
|
async function discoverModulePaths(projectRoot) {
|
|
33569
33813
|
const paths = [];
|
|
33570
|
-
const workspacePath =
|
|
33814
|
+
const workspacePath = join33(projectRoot, "pnpm-workspace.yaml");
|
|
33571
33815
|
let patterns = [];
|
|
33572
33816
|
try {
|
|
33573
|
-
const raw = await
|
|
33817
|
+
const raw = await readFile21(workspacePath, "utf-8");
|
|
33574
33818
|
const lines = raw.split("\n");
|
|
33575
33819
|
let inPackages = false;
|
|
33576
33820
|
for (const line of lines) {
|
|
@@ -33594,7 +33838,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33594
33838
|
for (const pattern of patterns) {
|
|
33595
33839
|
if (pattern.endsWith("/*")) {
|
|
33596
33840
|
const dir = pattern.slice(0, -2);
|
|
33597
|
-
const absDir =
|
|
33841
|
+
const absDir = join33(projectRoot, dir);
|
|
33598
33842
|
try {
|
|
33599
33843
|
if (existsSync11(absDir)) {
|
|
33600
33844
|
const entries = readdirSync4(absDir, { withFileTypes: true });
|
|
@@ -33607,7 +33851,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33607
33851
|
} catch {
|
|
33608
33852
|
}
|
|
33609
33853
|
} else if (!pattern.includes("*")) {
|
|
33610
|
-
const absPath =
|
|
33854
|
+
const absPath = join33(projectRoot, pattern);
|
|
33611
33855
|
if (existsSync11(absPath)) {
|
|
33612
33856
|
paths.push(pattern);
|
|
33613
33857
|
}
|
|
@@ -33615,7 +33859,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33615
33859
|
}
|
|
33616
33860
|
const crossCutting = ["supabase", ".github", "scripts"];
|
|
33617
33861
|
for (const dir of crossCutting) {
|
|
33618
|
-
const absPath =
|
|
33862
|
+
const absPath = join33(projectRoot, dir);
|
|
33619
33863
|
try {
|
|
33620
33864
|
if (existsSync11(absPath)) {
|
|
33621
33865
|
paths.push(dir);
|
|
@@ -33801,10 +34045,10 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
33801
34045
|
}
|
|
33802
34046
|
await writeArchitectureConfig(codebyplanDir, config);
|
|
33803
34047
|
const stampedEntry = existingIndex >= 0 ? config.modules[existingIndex] : config.modules[config.modules.length - 1];
|
|
33804
|
-
const mapAbsPath =
|
|
34048
|
+
const mapAbsPath = join33(repoRoot, stampedEntry.map_file);
|
|
33805
34049
|
let mapContent = null;
|
|
33806
34050
|
try {
|
|
33807
|
-
mapContent = await
|
|
34051
|
+
mapContent = await readFile21(mapAbsPath, "utf-8");
|
|
33808
34052
|
} catch {
|
|
33809
34053
|
console.warn(
|
|
33810
34054
|
" Warning: map file " + stampedEntry.map_file + " not found \u2014 stamped manifest only"
|
|
@@ -33826,7 +34070,7 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
33826
34070
|
);
|
|
33827
34071
|
} else {
|
|
33828
34072
|
try {
|
|
33829
|
-
await
|
|
34073
|
+
await writeFile17(mapAbsPath, updated, "utf-8");
|
|
33830
34074
|
} catch (writeErr) {
|
|
33831
34075
|
console.warn(
|
|
33832
34076
|
" Warning: could not write map file " + stampedEntry.map_file + " \u2014 " + (writeErr instanceof Error ? writeErr.message : String(writeErr)) + " \u2014 stamped manifest only"
|
|
@@ -34006,19 +34250,19 @@ var init_worktree_port_resolver = __esm({
|
|
|
34006
34250
|
});
|
|
34007
34251
|
|
|
34008
34252
|
// src/lib/migrate-local-config.ts
|
|
34009
|
-
import { mkdir as mkdir9, readFile as
|
|
34010
|
-
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";
|
|
34011
34255
|
function legacySharedPath(projectPath) {
|
|
34012
|
-
return
|
|
34256
|
+
return join34(projectPath, ".codebyplan.json");
|
|
34013
34257
|
}
|
|
34014
34258
|
function legacyLocalPath(projectPath) {
|
|
34015
|
-
return
|
|
34259
|
+
return join34(projectPath, ".codebyplan.local.json");
|
|
34016
34260
|
}
|
|
34017
34261
|
function newDirPath(projectPath) {
|
|
34018
|
-
return
|
|
34262
|
+
return join34(projectPath, ".codebyplan");
|
|
34019
34263
|
}
|
|
34020
34264
|
function sentinelPath(projectPath) {
|
|
34021
|
-
return
|
|
34265
|
+
return join34(projectPath, ".codebyplan", "repo.json");
|
|
34022
34266
|
}
|
|
34023
34267
|
async function statSafe(p) {
|
|
34024
34268
|
const { stat: stat3 } = await import("node:fs/promises");
|
|
@@ -34057,7 +34301,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34057
34301
|
}
|
|
34058
34302
|
let legacyRaw;
|
|
34059
34303
|
try {
|
|
34060
|
-
legacyRaw = await
|
|
34304
|
+
legacyRaw = await readFile22(legacySharedPath(projectPath), "utf-8");
|
|
34061
34305
|
} catch {
|
|
34062
34306
|
return {
|
|
34063
34307
|
migrated: true,
|
|
@@ -34084,7 +34328,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34084
34328
|
let deviceId;
|
|
34085
34329
|
let deviceWrittenByHelper = false;
|
|
34086
34330
|
try {
|
|
34087
|
-
const localRaw = await
|
|
34331
|
+
const localRaw = await readFile22(legacyLocalPath(projectPath), "utf-8");
|
|
34088
34332
|
const localParsed = JSON.parse(localRaw);
|
|
34089
34333
|
if (typeof localParsed.device_id === "string") {
|
|
34090
34334
|
deviceId = localParsed.device_id;
|
|
@@ -34111,8 +34355,8 @@ async function runLocalMigration(projectPath) {
|
|
|
34111
34355
|
if ("repo_id" in cfg) repoJson.repo_id = cfg.repo_id;
|
|
34112
34356
|
if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
|
|
34113
34357
|
if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
|
|
34114
|
-
await
|
|
34115
|
-
|
|
34358
|
+
await writeFile18(
|
|
34359
|
+
join34(projectPath, ".codebyplan", "repo.json"),
|
|
34116
34360
|
JSON.stringify(repoJson, null, 2) + "\n",
|
|
34117
34361
|
"utf-8"
|
|
34118
34362
|
);
|
|
@@ -34124,8 +34368,8 @@ async function runLocalMigration(projectPath) {
|
|
|
34124
34368
|
serverJson.auto_push_enabled = cfg.auto_push_enabled;
|
|
34125
34369
|
if ("port_allocations" in cfg)
|
|
34126
34370
|
serverJson.port_allocations = cfg.port_allocations;
|
|
34127
|
-
await
|
|
34128
|
-
|
|
34371
|
+
await writeFile18(
|
|
34372
|
+
join34(projectPath, ".codebyplan", "server.json"),
|
|
34129
34373
|
JSON.stringify(serverJson, null, 2) + "\n",
|
|
34130
34374
|
"utf-8"
|
|
34131
34375
|
);
|
|
@@ -34133,44 +34377,44 @@ async function runLocalMigration(projectPath) {
|
|
|
34133
34377
|
const gitJson = {};
|
|
34134
34378
|
if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
|
|
34135
34379
|
if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
|
|
34136
|
-
await
|
|
34137
|
-
|
|
34380
|
+
await writeFile18(
|
|
34381
|
+
join34(projectPath, ".codebyplan", "git.json"),
|
|
34138
34382
|
JSON.stringify(gitJson, null, 2) + "\n",
|
|
34139
34383
|
"utf-8"
|
|
34140
34384
|
);
|
|
34141
34385
|
filesChanged.push(".codebyplan/git.json");
|
|
34142
34386
|
const shipmentJson = {};
|
|
34143
34387
|
if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
|
|
34144
|
-
await
|
|
34145
|
-
|
|
34388
|
+
await writeFile18(
|
|
34389
|
+
join34(projectPath, ".codebyplan", "shipment.json"),
|
|
34146
34390
|
JSON.stringify(shipmentJson, null, 2) + "\n",
|
|
34147
34391
|
"utf-8"
|
|
34148
34392
|
);
|
|
34149
34393
|
filesChanged.push(".codebyplan/shipment.json");
|
|
34150
34394
|
const vendorJson = {};
|
|
34151
|
-
await
|
|
34152
|
-
|
|
34395
|
+
await writeFile18(
|
|
34396
|
+
join34(projectPath, ".codebyplan", "vendor.json"),
|
|
34153
34397
|
JSON.stringify(vendorJson, null, 2) + "\n",
|
|
34154
34398
|
"utf-8"
|
|
34155
34399
|
);
|
|
34156
34400
|
filesChanged.push(".codebyplan/vendor.json");
|
|
34157
34401
|
const e2eJson = {};
|
|
34158
|
-
await
|
|
34159
|
-
|
|
34402
|
+
await writeFile18(
|
|
34403
|
+
join34(projectPath, ".codebyplan", "e2e.json"),
|
|
34160
34404
|
JSON.stringify(e2eJson, null, 2) + "\n",
|
|
34161
34405
|
"utf-8"
|
|
34162
34406
|
);
|
|
34163
34407
|
filesChanged.push(".codebyplan/e2e.json");
|
|
34164
34408
|
const eslintJson = {};
|
|
34165
|
-
await
|
|
34166
|
-
|
|
34409
|
+
await writeFile18(
|
|
34410
|
+
join34(projectPath, ".codebyplan", "eslint.json"),
|
|
34167
34411
|
JSON.stringify(eslintJson, null, 2) + "\n",
|
|
34168
34412
|
"utf-8"
|
|
34169
34413
|
);
|
|
34170
34414
|
filesChanged.push(".codebyplan/eslint.json");
|
|
34171
34415
|
if (!deviceWrittenByHelper) {
|
|
34172
|
-
await
|
|
34173
|
-
|
|
34416
|
+
await writeFile18(
|
|
34417
|
+
join34(projectPath, ".codebyplan", "device.local.json"),
|
|
34174
34418
|
JSON.stringify({ device_id: deviceId }, null, 2) + "\n",
|
|
34175
34419
|
"utf-8"
|
|
34176
34420
|
);
|
|
@@ -34182,9 +34426,9 @@ async function runLocalMigration(projectPath) {
|
|
|
34182
34426
|
"Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
|
|
34183
34427
|
);
|
|
34184
34428
|
}
|
|
34185
|
-
const gitignorePath =
|
|
34429
|
+
const gitignorePath = join34(projectPath, ".gitignore");
|
|
34186
34430
|
try {
|
|
34187
|
-
const gitignoreContent = await
|
|
34431
|
+
const gitignoreContent = await readFile22(gitignorePath, "utf-8");
|
|
34188
34432
|
const legacyLine = ".codebyplan.local.json";
|
|
34189
34433
|
const newLine = ".codebyplan/device.local.json";
|
|
34190
34434
|
const hasLegacy = gitignoreContent.split("\n").some((l) => l.trimEnd() === legacyLine);
|
|
@@ -34203,7 +34447,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34203
34447
|
updated = gitignoreContent;
|
|
34204
34448
|
}
|
|
34205
34449
|
if (updated !== gitignoreContent) {
|
|
34206
|
-
await
|
|
34450
|
+
await writeFile18(gitignorePath, updated, "utf-8");
|
|
34207
34451
|
filesChanged.push(".gitignore");
|
|
34208
34452
|
}
|
|
34209
34453
|
} catch {
|
|
@@ -34245,8 +34489,8 @@ __export(config_exports, {
|
|
|
34245
34489
|
runConfig: () => runConfig,
|
|
34246
34490
|
runConfigMigrate: () => runConfigMigrate
|
|
34247
34491
|
});
|
|
34248
|
-
import { mkdir as mkdir10, readFile as
|
|
34249
|
-
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";
|
|
34250
34494
|
async function runConfig() {
|
|
34251
34495
|
const flags = parseFlags(3);
|
|
34252
34496
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -34279,7 +34523,7 @@ async function runConfig() {
|
|
|
34279
34523
|
console.log("\n Config complete.\n");
|
|
34280
34524
|
}
|
|
34281
34525
|
async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
34282
|
-
const codebyplanDir =
|
|
34526
|
+
const codebyplanDir = join35(projectPath, ".codebyplan");
|
|
34283
34527
|
const {
|
|
34284
34528
|
resolvedWorktreeId,
|
|
34285
34529
|
portAllocations,
|
|
@@ -34372,16 +34616,16 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
34372
34616
|
];
|
|
34373
34617
|
let anyUpdated = false;
|
|
34374
34618
|
for (const { name, payload, createOnly } of files) {
|
|
34375
|
-
const filePath =
|
|
34619
|
+
const filePath = join35(codebyplanDir, name);
|
|
34376
34620
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
34377
34621
|
let currentJson = "";
|
|
34378
34622
|
try {
|
|
34379
|
-
currentJson = await
|
|
34623
|
+
currentJson = await readFile23(filePath, "utf-8");
|
|
34380
34624
|
} catch {
|
|
34381
34625
|
}
|
|
34382
34626
|
if (createOnly && currentJson !== "") continue;
|
|
34383
34627
|
if (currentJson === newJson) continue;
|
|
34384
|
-
await
|
|
34628
|
+
await writeFile19(filePath, newJson, "utf-8");
|
|
34385
34629
|
console.log(` Updated .codebyplan/${name}`);
|
|
34386
34630
|
anyUpdated = true;
|
|
34387
34631
|
}
|
|
@@ -34391,8 +34635,8 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
34391
34635
|
}
|
|
34392
34636
|
async function readRepoConfig(projectPath) {
|
|
34393
34637
|
try {
|
|
34394
|
-
const raw = await
|
|
34395
|
-
|
|
34638
|
+
const raw = await readFile23(
|
|
34639
|
+
join35(projectPath, ".codebyplan", "repo.json"),
|
|
34396
34640
|
"utf-8"
|
|
34397
34641
|
);
|
|
34398
34642
|
return JSON.parse(raw);
|
|
@@ -34402,8 +34646,8 @@ async function readRepoConfig(projectPath) {
|
|
|
34402
34646
|
}
|
|
34403
34647
|
async function readServerConfig(projectPath) {
|
|
34404
34648
|
try {
|
|
34405
|
-
const raw = await
|
|
34406
|
-
|
|
34649
|
+
const raw = await readFile23(
|
|
34650
|
+
join35(projectPath, ".codebyplan", "server.json"),
|
|
34407
34651
|
"utf-8"
|
|
34408
34652
|
);
|
|
34409
34653
|
return JSON.parse(raw);
|
|
@@ -34413,8 +34657,8 @@ async function readServerConfig(projectPath) {
|
|
|
34413
34657
|
}
|
|
34414
34658
|
async function readGitConfig2(projectPath) {
|
|
34415
34659
|
try {
|
|
34416
|
-
const raw = await
|
|
34417
|
-
|
|
34660
|
+
const raw = await readFile23(
|
|
34661
|
+
join35(projectPath, ".codebyplan", "git.json"),
|
|
34418
34662
|
"utf-8"
|
|
34419
34663
|
);
|
|
34420
34664
|
return JSON.parse(raw);
|
|
@@ -34424,8 +34668,8 @@ async function readGitConfig2(projectPath) {
|
|
|
34424
34668
|
}
|
|
34425
34669
|
async function readShipmentConfig2(projectPath) {
|
|
34426
34670
|
try {
|
|
34427
|
-
const raw = await
|
|
34428
|
-
|
|
34671
|
+
const raw = await readFile23(
|
|
34672
|
+
join35(projectPath, ".codebyplan", "shipment.json"),
|
|
34429
34673
|
"utf-8"
|
|
34430
34674
|
);
|
|
34431
34675
|
return JSON.parse(raw);
|
|
@@ -34435,8 +34679,8 @@ async function readShipmentConfig2(projectPath) {
|
|
|
34435
34679
|
}
|
|
34436
34680
|
async function readVendorConfig(projectPath) {
|
|
34437
34681
|
try {
|
|
34438
|
-
const raw = await
|
|
34439
|
-
|
|
34682
|
+
const raw = await readFile23(
|
|
34683
|
+
join35(projectPath, ".codebyplan", "vendor.json"),
|
|
34440
34684
|
"utf-8"
|
|
34441
34685
|
);
|
|
34442
34686
|
return JSON.parse(raw);
|
|
@@ -34446,8 +34690,8 @@ async function readVendorConfig(projectPath) {
|
|
|
34446
34690
|
}
|
|
34447
34691
|
async function readE2eConfig2(projectPath) {
|
|
34448
34692
|
try {
|
|
34449
|
-
const raw = await
|
|
34450
|
-
|
|
34693
|
+
const raw = await readFile23(
|
|
34694
|
+
join35(projectPath, ".codebyplan", "e2e.json"),
|
|
34451
34695
|
"utf-8"
|
|
34452
34696
|
);
|
|
34453
34697
|
return JSON.parse(raw);
|
|
@@ -34457,8 +34701,8 @@ async function readE2eConfig2(projectPath) {
|
|
|
34457
34701
|
}
|
|
34458
34702
|
async function readServerLocalConfig(projectPath) {
|
|
34459
34703
|
try {
|
|
34460
|
-
const raw = await
|
|
34461
|
-
|
|
34704
|
+
const raw = await readFile23(
|
|
34705
|
+
join35(projectPath, ".codebyplan", "server.local.json"),
|
|
34462
34706
|
"utf-8"
|
|
34463
34707
|
);
|
|
34464
34708
|
return JSON.parse(raw);
|
|
@@ -34530,8 +34774,8 @@ var init_config = __esm({
|
|
|
34530
34774
|
});
|
|
34531
34775
|
|
|
34532
34776
|
// src/lib/server-detect.ts
|
|
34533
|
-
import { readFile as
|
|
34534
|
-
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";
|
|
34535
34779
|
async function fileExists4(filePath) {
|
|
34536
34780
|
try {
|
|
34537
34781
|
await access6(filePath);
|
|
@@ -34542,8 +34786,8 @@ async function fileExists4(filePath) {
|
|
|
34542
34786
|
}
|
|
34543
34787
|
function detectPackageManager3(dir) {
|
|
34544
34788
|
return (async () => {
|
|
34545
|
-
if (await fileExists4(
|
|
34546
|
-
if (await fileExists4(
|
|
34789
|
+
if (await fileExists4(join36(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
34790
|
+
if (await fileExists4(join36(dir, "yarn.lock"))) return "yarn";
|
|
34547
34791
|
return "npm";
|
|
34548
34792
|
})();
|
|
34549
34793
|
}
|
|
@@ -34575,12 +34819,12 @@ function detectPortFromScripts(pkg) {
|
|
|
34575
34819
|
return null;
|
|
34576
34820
|
}
|
|
34577
34821
|
async function isMonorepo(dir) {
|
|
34578
|
-
return await fileExists4(
|
|
34822
|
+
return await fileExists4(join36(dir, "turbo.json")) || await fileExists4(join36(dir, "pnpm-workspace.yaml"));
|
|
34579
34823
|
}
|
|
34580
34824
|
async function detectServers(projectPath) {
|
|
34581
34825
|
let pkg;
|
|
34582
34826
|
try {
|
|
34583
|
-
const raw = await
|
|
34827
|
+
const raw = await readFile24(join36(projectPath, "package.json"), "utf-8");
|
|
34584
34828
|
pkg = JSON.parse(raw);
|
|
34585
34829
|
} catch {
|
|
34586
34830
|
return {
|
|
@@ -34596,15 +34840,15 @@ async function detectServers(projectPath) {
|
|
|
34596
34840
|
const mono = await isMonorepo(projectPath);
|
|
34597
34841
|
const servers = [];
|
|
34598
34842
|
if (mono) {
|
|
34599
|
-
const appsDir =
|
|
34843
|
+
const appsDir = join36(projectPath, "apps");
|
|
34600
34844
|
try {
|
|
34601
34845
|
const entries = await readdir5(appsDir, { withFileTypes: true });
|
|
34602
34846
|
const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
34603
34847
|
for (const entry of sorted) {
|
|
34604
34848
|
if (!entry.isDirectory()) continue;
|
|
34605
|
-
const appPkgPath =
|
|
34849
|
+
const appPkgPath = join36(appsDir, entry.name, "package.json");
|
|
34606
34850
|
try {
|
|
34607
|
-
const appRaw = await
|
|
34851
|
+
const appRaw = await readFile24(appPkgPath, "utf-8");
|
|
34608
34852
|
const appPkg = JSON.parse(appRaw);
|
|
34609
34853
|
const appName = entry.name;
|
|
34610
34854
|
const framework = detectFramework(appPkg);
|
|
@@ -34647,14 +34891,14 @@ var init_server_detect = __esm({
|
|
|
34647
34891
|
});
|
|
34648
34892
|
|
|
34649
34893
|
// src/lib/port-verify.ts
|
|
34650
|
-
import { readFile as
|
|
34894
|
+
import { readFile as readFile25 } from "node:fs/promises";
|
|
34651
34895
|
async function verifyPorts(projectPath, portAllocations) {
|
|
34652
34896
|
const mismatches = [];
|
|
34653
34897
|
const allocatedPorts = new Set(portAllocations.map((a) => a.port));
|
|
34654
34898
|
const packageJsonPaths = await findPackageJsonFiles(projectPath, projectPath);
|
|
34655
34899
|
for (const pkgPath of packageJsonPaths) {
|
|
34656
34900
|
try {
|
|
34657
|
-
const raw = await
|
|
34901
|
+
const raw = await readFile25(pkgPath, "utf-8");
|
|
34658
34902
|
const pkg = JSON.parse(raw);
|
|
34659
34903
|
const scriptPort = detectPortFromScripts(pkg);
|
|
34660
34904
|
if (scriptPort !== null && !allocatedPorts.has(scriptPort)) {
|
|
@@ -34717,7 +34961,7 @@ async function findUnallocatedApps(projectPath, portAllocations) {
|
|
|
34717
34961
|
}
|
|
34718
34962
|
let pkg;
|
|
34719
34963
|
try {
|
|
34720
|
-
const raw = await
|
|
34964
|
+
const raw = await readFile25(`${app.absPath}/package.json`, "utf-8");
|
|
34721
34965
|
pkg = JSON.parse(raw);
|
|
34722
34966
|
} catch {
|
|
34723
34967
|
continue;
|
|
@@ -34767,8 +35011,8 @@ __export(ports_exports, {
|
|
|
34767
35011
|
parseEnvFile: () => parseEnvFile,
|
|
34768
35012
|
runPorts: () => runPorts
|
|
34769
35013
|
});
|
|
34770
|
-
import { mkdir as mkdir11, readFile as
|
|
34771
|
-
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";
|
|
34772
35016
|
function printDetectionResult(result, projectPath) {
|
|
34773
35017
|
console.log(`
|
|
34774
35018
|
CodeByPlan Ports - List`);
|
|
@@ -34924,12 +35168,12 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
34924
35168
|
// and ServerLocalConfig.port_allocations is typed the same — honest end-to-end.
|
|
34925
35169
|
port_allocations: portAllocations
|
|
34926
35170
|
};
|
|
34927
|
-
const codebyplanDir =
|
|
34928
|
-
const filePath =
|
|
35171
|
+
const codebyplanDir = join37(projectPath, ".codebyplan");
|
|
35172
|
+
const filePath = join37(codebyplanDir, "server.local.json");
|
|
34929
35173
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
34930
35174
|
let currentJson = "";
|
|
34931
35175
|
try {
|
|
34932
|
-
currentJson = await
|
|
35176
|
+
currentJson = await readFile26(filePath, "utf-8");
|
|
34933
35177
|
} catch {
|
|
34934
35178
|
}
|
|
34935
35179
|
if (currentJson === newJson) {
|
|
@@ -34941,17 +35185,17 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
34941
35185
|
return;
|
|
34942
35186
|
}
|
|
34943
35187
|
await mkdir11(codebyplanDir, { recursive: true });
|
|
34944
|
-
await
|
|
35188
|
+
await writeFile20(filePath, newJson, "utf-8");
|
|
34945
35189
|
console.log(
|
|
34946
35190
|
` Updated .codebyplan/server.local.json (worktree ${resolvedWorktreeId ?? "\u2014"}, ${portAllocations.length} allocation${portAllocations.length === 1 ? "" : "s"}).`
|
|
34947
35191
|
);
|
|
34948
35192
|
}
|
|
34949
35193
|
async function provisionE2eEnv(projectPath, dryRun) {
|
|
34950
|
-
const relSource =
|
|
34951
|
-
const sourcePath =
|
|
35194
|
+
const relSource = join37("apps", "web", ".env.local");
|
|
35195
|
+
const sourcePath = join37(projectPath, relSource);
|
|
34952
35196
|
let sourceRaw;
|
|
34953
35197
|
try {
|
|
34954
|
-
sourceRaw = await
|
|
35198
|
+
sourceRaw = await readFile26(sourcePath, "utf-8");
|
|
34955
35199
|
} catch {
|
|
34956
35200
|
console.warn(
|
|
34957
35201
|
` Skipped .codebyplan/e2e.env \u2014 source ${relSource} not found.`
|
|
@@ -34980,12 +35224,12 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
34980
35224
|
);
|
|
34981
35225
|
return;
|
|
34982
35226
|
}
|
|
34983
|
-
const codebyplanDir =
|
|
34984
|
-
const filePath =
|
|
35227
|
+
const codebyplanDir = join37(projectPath, ".codebyplan");
|
|
35228
|
+
const filePath = join37(codebyplanDir, "e2e.env");
|
|
34985
35229
|
const newContent = lines.join("\n") + "\n";
|
|
34986
35230
|
let currentContent = "";
|
|
34987
35231
|
try {
|
|
34988
|
-
currentContent = await
|
|
35232
|
+
currentContent = await readFile26(filePath, "utf-8");
|
|
34989
35233
|
} catch {
|
|
34990
35234
|
}
|
|
34991
35235
|
if (currentContent === newContent) {
|
|
@@ -34997,7 +35241,7 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
34997
35241
|
return;
|
|
34998
35242
|
}
|
|
34999
35243
|
await mkdir11(codebyplanDir, { recursive: true });
|
|
35000
|
-
await
|
|
35244
|
+
await writeFile20(filePath, newContent, "utf-8");
|
|
35001
35245
|
console.log(
|
|
35002
35246
|
` Provisioned .codebyplan/e2e.env (${lines.length} var${lines.length === 1 ? "" : "s"}).`
|
|
35003
35247
|
);
|
|
@@ -35265,8 +35509,8 @@ __export(docs_exports, {
|
|
|
35265
35509
|
stripRangePrefix: () => stripRangePrefix
|
|
35266
35510
|
});
|
|
35267
35511
|
import { existsSync as existsSync13 } from "node:fs";
|
|
35268
|
-
import { mkdir as mkdir12, readFile as
|
|
35269
|
-
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";
|
|
35270
35514
|
function selectDependencies(deps) {
|
|
35271
35515
|
const byName = /* @__PURE__ */ new Map();
|
|
35272
35516
|
for (const dep of deps) {
|
|
@@ -35320,12 +35564,12 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
35320
35564
|
}
|
|
35321
35565
|
async function resolveExactVersion(projectPath, dep) {
|
|
35322
35566
|
const candidateDirs = [projectPath];
|
|
35323
|
-
const sourceDir =
|
|
35567
|
+
const sourceDir = join38(projectPath, dirname13(dep.sourcePath));
|
|
35324
35568
|
if (sourceDir !== projectPath) candidateDirs.push(sourceDir);
|
|
35325
35569
|
for (const base of candidateDirs) {
|
|
35326
35570
|
try {
|
|
35327
|
-
const raw = await
|
|
35328
|
-
|
|
35571
|
+
const raw = await readFile27(
|
|
35572
|
+
join38(base, "node_modules", dep.name, "package.json"),
|
|
35329
35573
|
"utf-8"
|
|
35330
35574
|
);
|
|
35331
35575
|
const pkg = JSON.parse(raw);
|
|
@@ -35339,8 +35583,8 @@ async function resolveExactVersion(projectPath, dep) {
|
|
|
35339
35583
|
}
|
|
35340
35584
|
async function readVendorDocsPath(projectPath) {
|
|
35341
35585
|
try {
|
|
35342
|
-
const raw = await
|
|
35343
|
-
|
|
35586
|
+
const raw = await readFile27(
|
|
35587
|
+
join38(projectPath, ".codebyplan", "vendor.json"),
|
|
35344
35588
|
"utf-8"
|
|
35345
35589
|
);
|
|
35346
35590
|
const parsed = JSON.parse(raw);
|
|
@@ -35353,7 +35597,7 @@ async function readVendorDocsPath(projectPath) {
|
|
|
35353
35597
|
}
|
|
35354
35598
|
async function resolveDocsDir(projectPath, flags) {
|
|
35355
35599
|
const configured = flags["dir"] ?? await readVendorDocsPath(projectPath) ?? DEFAULT_DOCS_DIR;
|
|
35356
|
-
const absDir =
|
|
35600
|
+
const absDir = isAbsolute2(configured) ? configured : join38(projectPath, configured);
|
|
35357
35601
|
const rel = relative7(projectPath, absDir);
|
|
35358
35602
|
const relDir = rel === "" || rel.startsWith("..") ? null : rel.split(sep2).join("/");
|
|
35359
35603
|
return { absDir, relDir };
|
|
@@ -35362,7 +35606,7 @@ async function readDocsLock(absDir) {
|
|
|
35362
35606
|
const empty = { generated_at: "", libraries: {} };
|
|
35363
35607
|
let raw;
|
|
35364
35608
|
try {
|
|
35365
|
-
raw = await
|
|
35609
|
+
raw = await readFile27(join38(absDir, LOCK_FILE), "utf-8");
|
|
35366
35610
|
} catch {
|
|
35367
35611
|
return empty;
|
|
35368
35612
|
}
|
|
@@ -35458,10 +35702,10 @@ function buildTopIndex(outcomes) {
|
|
|
35458
35702
|
}
|
|
35459
35703
|
async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
35460
35704
|
const entry = `/${relDir}/`;
|
|
35461
|
-
const gitignorePath =
|
|
35705
|
+
const gitignorePath = join38(projectPath, ".gitignore");
|
|
35462
35706
|
let existing = "";
|
|
35463
35707
|
try {
|
|
35464
|
-
existing = await
|
|
35708
|
+
existing = await readFile27(gitignorePath, "utf-8");
|
|
35465
35709
|
} catch {
|
|
35466
35710
|
}
|
|
35467
35711
|
const lines = existing.split(/\r?\n/).map((l) => l.trim());
|
|
@@ -35473,7 +35717,7 @@ async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
|
35473
35717
|
content += `${GITIGNORE_COMMENT}
|
|
35474
35718
|
${entry}
|
|
35475
35719
|
`;
|
|
35476
|
-
await
|
|
35720
|
+
await writeFile21(gitignorePath, content, "utf-8");
|
|
35477
35721
|
}
|
|
35478
35722
|
return "added";
|
|
35479
35723
|
}
|
|
@@ -35481,7 +35725,7 @@ async function markUncovered(dep, exactVersion, ctx) {
|
|
|
35481
35725
|
console.log(
|
|
35482
35726
|
` uncovered ${dep.name}@${exactVersion || "?"} \u2014 no docs in the library mirror`
|
|
35483
35727
|
);
|
|
35484
|
-
const libPath =
|
|
35728
|
+
const libPath = join38(ctx.absDir, libDirName(dep.name));
|
|
35485
35729
|
if (existsSync13(libPath)) {
|
|
35486
35730
|
if (ctx.dryRun) {
|
|
35487
35731
|
console.log(` would remove stale mirror dir ${libPath}`);
|
|
@@ -35534,14 +35778,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35534
35778
|
}
|
|
35535
35779
|
}
|
|
35536
35780
|
const lockEntry = ctx.lock.libraries[dep.name];
|
|
35537
|
-
const libPath =
|
|
35538
|
-
const versionPath =
|
|
35781
|
+
const libPath = join38(ctx.absDir, libDirName(dep.name));
|
|
35782
|
+
const versionPath = join38(libPath, manifest.resolved_version);
|
|
35539
35783
|
if (manifestMatchesLock(manifest, lockEntry)) {
|
|
35540
35784
|
console.log(` unchanged ${dep.name}@${manifest.resolved_version}`);
|
|
35541
|
-
if (!ctx.dryRun && !existsSync13(
|
|
35785
|
+
if (!ctx.dryRun && !existsSync13(join38(libPath, "INDEX.md"))) {
|
|
35542
35786
|
await mkdir12(libPath, { recursive: true });
|
|
35543
|
-
await
|
|
35544
|
-
|
|
35787
|
+
await writeFile21(
|
|
35788
|
+
join38(libPath, "INDEX.md"),
|
|
35545
35789
|
buildLibIndex(dep.name, manifest),
|
|
35546
35790
|
"utf-8"
|
|
35547
35791
|
);
|
|
@@ -35563,14 +35807,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35563
35807
|
);
|
|
35564
35808
|
continue;
|
|
35565
35809
|
}
|
|
35566
|
-
const target =
|
|
35810
|
+
const target = join38(versionPath, rel);
|
|
35567
35811
|
if (sameVersionLockFiles[file.path] === file.content_hash && existsSync13(target)) {
|
|
35568
35812
|
continue;
|
|
35569
35813
|
}
|
|
35570
35814
|
written++;
|
|
35571
35815
|
if (!ctx.dryRun) {
|
|
35572
35816
|
await mkdir12(dirname13(target), { recursive: true });
|
|
35573
|
-
await
|
|
35817
|
+
await writeFile21(target, file.content, "utf-8");
|
|
35574
35818
|
}
|
|
35575
35819
|
}
|
|
35576
35820
|
let removedFiles = 0;
|
|
@@ -35581,7 +35825,7 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35581
35825
|
const rel = sanitizeDocPath(lockedPath);
|
|
35582
35826
|
if (rel === null) continue;
|
|
35583
35827
|
removedFiles++;
|
|
35584
|
-
if (!ctx.dryRun) await rm2(
|
|
35828
|
+
if (!ctx.dryRun) await rm2(join38(versionPath, rel), { force: true });
|
|
35585
35829
|
}
|
|
35586
35830
|
}
|
|
35587
35831
|
let removedVersionDirs = 0;
|
|
@@ -35596,13 +35840,13 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35596
35840
|
}
|
|
35597
35841
|
removedVersionDirs++;
|
|
35598
35842
|
if (!ctx.dryRun) {
|
|
35599
|
-
await rm2(
|
|
35843
|
+
await rm2(join38(libPath, entry.name), { recursive: true, force: true });
|
|
35600
35844
|
}
|
|
35601
35845
|
}
|
|
35602
35846
|
if (!ctx.dryRun) {
|
|
35603
35847
|
await mkdir12(libPath, { recursive: true });
|
|
35604
|
-
await
|
|
35605
|
-
|
|
35848
|
+
await writeFile21(
|
|
35849
|
+
join38(libPath, "INDEX.md"),
|
|
35606
35850
|
buildLibIndex(dep.name, manifest),
|
|
35607
35851
|
"utf-8"
|
|
35608
35852
|
);
|
|
@@ -35656,7 +35900,7 @@ async function runDocsSync() {
|
|
|
35656
35900
|
);
|
|
35657
35901
|
if (!dryRun) {
|
|
35658
35902
|
await mkdir12(absDir, { recursive: true });
|
|
35659
|
-
await
|
|
35903
|
+
await writeFile21(join38(absDir, "INDEX.md"), buildTopIndex(outcomes), "utf-8");
|
|
35660
35904
|
const libraries = {};
|
|
35661
35905
|
for (const o of outcomes) {
|
|
35662
35906
|
if (o.kind === "synced" || o.kind === "unchanged") {
|
|
@@ -35681,8 +35925,8 @@ async function runDocsSync() {
|
|
|
35681
35925
|
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35682
35926
|
libraries: sortedLibraries
|
|
35683
35927
|
};
|
|
35684
|
-
await
|
|
35685
|
-
|
|
35928
|
+
await writeFile21(
|
|
35929
|
+
join38(absDir, LOCK_FILE),
|
|
35686
35930
|
JSON.stringify(newLock, null, 2) + "\n",
|
|
35687
35931
|
"utf-8"
|
|
35688
35932
|
);
|
|
@@ -35724,7 +35968,7 @@ async function countFilesRecursively(dirPath) {
|
|
|
35724
35968
|
let count = 0;
|
|
35725
35969
|
for (const entry of entries) {
|
|
35726
35970
|
if (entry.isDirectory()) {
|
|
35727
|
-
count += await countFilesRecursively(
|
|
35971
|
+
count += await countFilesRecursively(join38(dirPath, entry.name));
|
|
35728
35972
|
} else if (entry.isFile()) {
|
|
35729
35973
|
count++;
|
|
35730
35974
|
}
|
|
@@ -35741,7 +35985,7 @@ async function runDocsStatus() {
|
|
|
35741
35985
|
`);
|
|
35742
35986
|
let raw;
|
|
35743
35987
|
try {
|
|
35744
|
-
raw = await
|
|
35988
|
+
raw = await readFile27(join38(absDir, LOCK_FILE), "utf-8");
|
|
35745
35989
|
} catch {
|
|
35746
35990
|
console.log(
|
|
35747
35991
|
` No ${LOCK_FILE} found \u2014 run \`codebyplan docs sync\` first.
|
|
@@ -35770,7 +36014,7 @@ async function runDocsStatus() {
|
|
|
35770
36014
|
let outOfSync = 0;
|
|
35771
36015
|
for (const name of names) {
|
|
35772
36016
|
const entry = lock.libraries[name];
|
|
35773
|
-
const versionPath =
|
|
36017
|
+
const versionPath = join38(absDir, libDirName(name), entry.resolved_version);
|
|
35774
36018
|
const expected = Object.keys(entry.files).length;
|
|
35775
36019
|
if (!existsSync13(versionPath)) {
|
|
35776
36020
|
outOfSync++;
|
|
@@ -35858,7 +36102,7 @@ var init_docs = __esm({
|
|
|
35858
36102
|
|
|
35859
36103
|
// src/lib/check-baseline.ts
|
|
35860
36104
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
35861
|
-
import { join as
|
|
36105
|
+
import { join as join39 } from "node:path";
|
|
35862
36106
|
function emptyBaseline() {
|
|
35863
36107
|
return {
|
|
35864
36108
|
lint: { known_failing: [] },
|
|
@@ -35868,7 +36112,7 @@ function emptyBaseline() {
|
|
|
35868
36112
|
};
|
|
35869
36113
|
}
|
|
35870
36114
|
function loadBaseline(projectRoot) {
|
|
35871
|
-
const filePath =
|
|
36115
|
+
const filePath = join39(projectRoot, BASELINE_FILENAME);
|
|
35872
36116
|
try {
|
|
35873
36117
|
const raw = readFileSync12(filePath, "utf-8");
|
|
35874
36118
|
const parsed = JSON.parse(raw);
|
|
@@ -35892,7 +36136,7 @@ function loadBaseline(projectRoot) {
|
|
|
35892
36136
|
}
|
|
35893
36137
|
}
|
|
35894
36138
|
function saveBaseline(projectRoot, baseline) {
|
|
35895
|
-
const filePath =
|
|
36139
|
+
const filePath = join39(projectRoot, BASELINE_FILENAME);
|
|
35896
36140
|
writeFileSync7(filePath, JSON.stringify(baseline, null, 2) + "\n", "utf-8");
|
|
35897
36141
|
}
|
|
35898
36142
|
function diffBaseline(check, currentFailingPackages, baseline) {
|
|
@@ -35942,8 +36186,8 @@ var init_check_baseline = __esm({
|
|
|
35942
36186
|
|
|
35943
36187
|
// src/lib/check.ts
|
|
35944
36188
|
import { readFileSync as readFileSync13, existsSync as existsSync14 } from "node:fs";
|
|
35945
|
-
import { join as
|
|
35946
|
-
import { spawnSync as
|
|
36189
|
+
import { join as join40 } from "node:path";
|
|
36190
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
35947
36191
|
function hasSentinelValue(arrays) {
|
|
35948
36192
|
const SENTINELS = /* @__PURE__ */ new Set([
|
|
35949
36193
|
SUMMARY_UNREADABLE,
|
|
@@ -35958,7 +36202,7 @@ function resolveNewFailures(check, failingPackages, baseline, updateBaseline, no
|
|
|
35958
36202
|
return diffBaseline(check, failingPackages, baseline);
|
|
35959
36203
|
}
|
|
35960
36204
|
function defaultSpawnFn(command, opts) {
|
|
35961
|
-
const result =
|
|
36205
|
+
const result = spawnSync11(command, {
|
|
35962
36206
|
shell: true,
|
|
35963
36207
|
cwd: opts.cwd,
|
|
35964
36208
|
encoding: "utf-8",
|
|
@@ -36010,9 +36254,9 @@ function parseFailingPackagesFromSummary(summaryPath) {
|
|
|
36010
36254
|
return Array.from(failing).sort();
|
|
36011
36255
|
}
|
|
36012
36256
|
function resolveTurboBin(projectRoot) {
|
|
36013
|
-
const localBin =
|
|
36257
|
+
const localBin = join40(projectRoot, "node_modules", ".bin", "turbo");
|
|
36014
36258
|
if (existsSync14(localBin)) return localBin;
|
|
36015
|
-
const workspaceRootBin =
|
|
36259
|
+
const workspaceRootBin = join40(
|
|
36016
36260
|
projectRoot,
|
|
36017
36261
|
"..",
|
|
36018
36262
|
"..",
|
|
@@ -36023,9 +36267,10 @@ function resolveTurboBin(projectRoot) {
|
|
|
36023
36267
|
if (existsSync14(workspaceRootBin)) return workspaceRootBin;
|
|
36024
36268
|
return TURBO_NOT_FOUND_SENTINEL;
|
|
36025
36269
|
}
|
|
36026
|
-
function runTurboWithSummary(task, projectRoot, spawnFn) {
|
|
36270
|
+
function runTurboWithSummary(task, projectRoot, spawnFn, concurrency) {
|
|
36027
36271
|
const turboBin = resolveTurboBin(projectRoot);
|
|
36028
|
-
const
|
|
36272
|
+
const concurrencyFlag = concurrency !== void 0 ? ` --concurrency=${concurrency}` : "";
|
|
36273
|
+
const command = `${turboBin} run ${task}${concurrencyFlag} --summarize`;
|
|
36029
36274
|
let spawnResult;
|
|
36030
36275
|
try {
|
|
36031
36276
|
spawnResult = spawnFn(command, { cwd: projectRoot });
|
|
@@ -36059,6 +36304,7 @@ function runCheck(opts) {
|
|
|
36059
36304
|
spawnFn = defaultSpawnFn,
|
|
36060
36305
|
updateBaseline: updateBaselineOpt = false,
|
|
36061
36306
|
noBaseline = false,
|
|
36307
|
+
concurrency,
|
|
36062
36308
|
loadBaselineFn = loadBaseline,
|
|
36063
36309
|
saveBaselineFn = saveBaseline
|
|
36064
36310
|
} = opts;
|
|
@@ -36107,7 +36353,7 @@ function runCheck(opts) {
|
|
|
36107
36353
|
spawnResult,
|
|
36108
36354
|
failingPackages,
|
|
36109
36355
|
command: lintCommand
|
|
36110
|
-
} = runTurboWithSummary("lint", projectRoot, spawnFn);
|
|
36356
|
+
} = runTurboWithSummary("lint", projectRoot, spawnFn, concurrency);
|
|
36111
36357
|
currentFailing.lint = failingPackages;
|
|
36112
36358
|
const newFailures = resolveNewFailures(
|
|
36113
36359
|
"lint",
|
|
@@ -36132,7 +36378,7 @@ function runCheck(opts) {
|
|
|
36132
36378
|
spawnResult,
|
|
36133
36379
|
failingPackages,
|
|
36134
36380
|
command: typecheckCommand
|
|
36135
|
-
} = runTurboWithSummary("typecheck", projectRoot, spawnFn);
|
|
36381
|
+
} = runTurboWithSummary("typecheck", projectRoot, spawnFn, concurrency);
|
|
36136
36382
|
currentFailing.typecheck = failingPackages;
|
|
36137
36383
|
const newFailures = resolveNewFailures(
|
|
36138
36384
|
"typecheck",
|
|
@@ -36157,7 +36403,7 @@ function runCheck(opts) {
|
|
|
36157
36403
|
spawnResult,
|
|
36158
36404
|
failingPackages,
|
|
36159
36405
|
command: testsCommand
|
|
36160
|
-
} = runTurboWithSummary("test", projectRoot, spawnFn);
|
|
36406
|
+
} = runTurboWithSummary("test", projectRoot, spawnFn, concurrency);
|
|
36161
36407
|
currentFailing.tests = failingPackages;
|
|
36162
36408
|
const newFailures = resolveNewFailures(
|
|
36163
36409
|
"tests",
|
|
@@ -36358,9 +36604,24 @@ function parseCheckArgs(args) {
|
|
|
36358
36604
|
let files;
|
|
36359
36605
|
let updateBaseline = false;
|
|
36360
36606
|
let noBaseline = false;
|
|
36607
|
+
let concurrency;
|
|
36361
36608
|
for (let i = 0; i < args.length; i++) {
|
|
36362
36609
|
const arg = args[i];
|
|
36363
|
-
if (arg === "--
|
|
36610
|
+
if (arg === "--concurrency") {
|
|
36611
|
+
const val = args[i + 1];
|
|
36612
|
+
const parsed = val !== void 0 ? Number(val) : NaN;
|
|
36613
|
+
if (Number.isInteger(parsed) && parsed > 0) {
|
|
36614
|
+
concurrency = parsed;
|
|
36615
|
+
i++;
|
|
36616
|
+
} else {
|
|
36617
|
+
process.stderr.write(
|
|
36618
|
+
`check: --concurrency value must be a positive integer (got: '${val ?? ""}').
|
|
36619
|
+
`
|
|
36620
|
+
);
|
|
36621
|
+
process.exitCode = 1;
|
|
36622
|
+
return null;
|
|
36623
|
+
}
|
|
36624
|
+
} else if (arg === "--scope") {
|
|
36364
36625
|
const val = args[i + 1];
|
|
36365
36626
|
if (val === "round" || val === "task" || val === "merged") {
|
|
36366
36627
|
scope = val;
|
|
@@ -36392,7 +36653,7 @@ function parseCheckArgs(args) {
|
|
|
36392
36653
|
}
|
|
36393
36654
|
}
|
|
36394
36655
|
}
|
|
36395
|
-
return { scope, json, files, updateBaseline, noBaseline };
|
|
36656
|
+
return { scope, json, files, updateBaseline, noBaseline, concurrency };
|
|
36396
36657
|
}
|
|
36397
36658
|
function emitTable(result) {
|
|
36398
36659
|
const strict = result.no_baseline === true;
|
|
@@ -36465,13 +36726,14 @@ function runCheckCommand(args) {
|
|
|
36465
36726
|
if (parsed === null) {
|
|
36466
36727
|
return;
|
|
36467
36728
|
}
|
|
36468
|
-
const { scope, json, files, updateBaseline, noBaseline } = parsed;
|
|
36729
|
+
const { scope, json, files, updateBaseline, noBaseline, concurrency } = parsed;
|
|
36469
36730
|
const result = runCheck({
|
|
36470
36731
|
scope,
|
|
36471
36732
|
changedFiles: files,
|
|
36472
36733
|
// NO-OP in whole-repo mode; notice emitted by runCheck
|
|
36473
36734
|
updateBaseline,
|
|
36474
|
-
noBaseline
|
|
36735
|
+
noBaseline,
|
|
36736
|
+
concurrency
|
|
36475
36737
|
});
|
|
36476
36738
|
if (json) {
|
|
36477
36739
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
@@ -36491,7 +36753,7 @@ var init_check2 = __esm({
|
|
|
36491
36753
|
|
|
36492
36754
|
// src/lib/claude-plan.ts
|
|
36493
36755
|
import * as fs13 from "node:fs";
|
|
36494
|
-
import * as
|
|
36756
|
+
import * as path14 from "node:path";
|
|
36495
36757
|
function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
36496
36758
|
const packaged = walkTemplates(templatesDir);
|
|
36497
36759
|
const packagedBySrc = new Map(packaged.map((f) => [f.src, f]));
|
|
@@ -36505,8 +36767,8 @@ function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
|
36505
36767
|
};
|
|
36506
36768
|
for (const pkg of packaged) {
|
|
36507
36769
|
const inManifest = manifestBySrc.get(pkg.src);
|
|
36508
|
-
const absDest =
|
|
36509
|
-
const absSrc =
|
|
36770
|
+
const absDest = path14.join(projectDir, ".claude", pkg.dest);
|
|
36771
|
+
const absSrc = path14.join(templatesDir, pkg.src);
|
|
36510
36772
|
if (!inManifest) {
|
|
36511
36773
|
plan.newOptIn.push({
|
|
36512
36774
|
packaged: { src: pkg.src, dest: pkg.dest, hash: pkg.hash },
|
|
@@ -36555,7 +36817,7 @@ __export(status_exports, {
|
|
|
36555
36817
|
runStatus: () => runStatus2
|
|
36556
36818
|
});
|
|
36557
36819
|
import * as fs14 from "node:fs";
|
|
36558
|
-
import * as
|
|
36820
|
+
import * as path15 from "node:path";
|
|
36559
36821
|
import { execSync as execSync9 } from "node:child_process";
|
|
36560
36822
|
function makeFailSafe(checked_at) {
|
|
36561
36823
|
return {
|
|
@@ -36568,6 +36830,8 @@ function makeFailSafe(checked_at) {
|
|
|
36568
36830
|
new_in_package: [],
|
|
36569
36831
|
removed_from_package: [],
|
|
36570
36832
|
settings_drift: false,
|
|
36833
|
+
settings_missing: false,
|
|
36834
|
+
settings_ignored: false,
|
|
36571
36835
|
guarded: true,
|
|
36572
36836
|
guard_reason: "unknown",
|
|
36573
36837
|
in_sync: true,
|
|
@@ -36633,6 +36897,8 @@ async function runStatus2(argv) {
|
|
|
36633
36897
|
new_in_package: [],
|
|
36634
36898
|
removed_from_package: [],
|
|
36635
36899
|
settings_drift: false,
|
|
36900
|
+
settings_missing: false,
|
|
36901
|
+
settings_ignored: false,
|
|
36636
36902
|
guarded: true,
|
|
36637
36903
|
// guarded:true must always pair with a non-null reason. canonical_source
|
|
36638
36904
|
// keeps its reason; the bare no-manifest case (never-installed consumer)
|
|
@@ -36660,12 +36926,12 @@ async function runStatus2(argv) {
|
|
|
36660
36926
|
const latest = fetchLatestVersion();
|
|
36661
36927
|
const newer = latest !== null && compareSemver(latest, installed) > 0;
|
|
36662
36928
|
let settings_drift = false;
|
|
36663
|
-
const settingsPath =
|
|
36664
|
-
const baseSettingsPath =
|
|
36929
|
+
const settingsPath = path15.join(projectDir, ".claude", "settings.json");
|
|
36930
|
+
const baseSettingsPath = path15.join(
|
|
36665
36931
|
templatesDir,
|
|
36666
36932
|
"settings.project.base.json"
|
|
36667
36933
|
);
|
|
36668
|
-
const hooksJsonPath =
|
|
36934
|
+
const hooksJsonPath = path15.join(templatesDir, "hooks", "hooks.json");
|
|
36669
36935
|
if (fs14.existsSync(settingsPath)) {
|
|
36670
36936
|
try {
|
|
36671
36937
|
const settingsRaw = fs14.readFileSync(settingsPath, "utf8");
|
|
@@ -36689,6 +36955,8 @@ async function runStatus2(argv) {
|
|
|
36689
36955
|
settings_drift = false;
|
|
36690
36956
|
}
|
|
36691
36957
|
}
|
|
36958
|
+
const settings_missing = !fs14.existsSync(settingsPath);
|
|
36959
|
+
const settings_ignored = detectSettingsIgnored(projectDir).status === "ignored";
|
|
36692
36960
|
const in_sync = !version_skip && drifted_files.length === 0 && new_in_package.length === 0 && removed_from_package.length === 0 && !settings_drift;
|
|
36693
36961
|
let action = null;
|
|
36694
36962
|
if (guardReason !== "protected_branch") {
|
|
@@ -36704,6 +36972,8 @@ async function runStatus2(argv) {
|
|
|
36704
36972
|
new_in_package,
|
|
36705
36973
|
removed_from_package,
|
|
36706
36974
|
settings_drift,
|
|
36975
|
+
settings_missing,
|
|
36976
|
+
settings_ignored,
|
|
36707
36977
|
// Always false in the full-detection path: a protected_branch consumer
|
|
36708
36978
|
// (the only guarded case that reaches here) must still SEE the segment;
|
|
36709
36979
|
// only canonical_source / no-manifest (Branch A) report guarded:true.
|
|
@@ -36731,10 +37001,10 @@ function emitResult(result, writeCache, quiet, projectDir) {
|
|
|
36731
37001
|
const json = JSON.stringify(result, null, 2);
|
|
36732
37002
|
if (writeCache) {
|
|
36733
37003
|
try {
|
|
36734
|
-
const cacheDir =
|
|
37004
|
+
const cacheDir = path15.join(projectDir, ".codebyplan");
|
|
36735
37005
|
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
36736
37006
|
fs14.writeFileSync(
|
|
36737
|
-
|
|
37007
|
+
path15.join(cacheDir, "claude-status.local.json"),
|
|
36738
37008
|
json + "\n",
|
|
36739
37009
|
"utf8"
|
|
36740
37010
|
);
|
|
@@ -36756,6 +37026,7 @@ var init_status = __esm({
|
|
|
36756
37026
|
init_claude_plan();
|
|
36757
37027
|
init_settings_merge();
|
|
36758
37028
|
init_version_status();
|
|
37029
|
+
init_gitignore_detect();
|
|
36759
37030
|
}
|
|
36760
37031
|
});
|
|
36761
37032
|
|
|
@@ -36877,7 +37148,7 @@ __export(update_exports, {
|
|
|
36877
37148
|
});
|
|
36878
37149
|
import * as fs15 from "node:fs";
|
|
36879
37150
|
import * as os3 from "node:os";
|
|
36880
|
-
import * as
|
|
37151
|
+
import * as path16 from "node:path";
|
|
36881
37152
|
async function runUpdate(opts, deps = {}) {
|
|
36882
37153
|
await Promise.resolve();
|
|
36883
37154
|
const scope = opts.scope ?? "project";
|
|
@@ -36913,9 +37184,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36913
37184
|
finalManifestEntries.push(e);
|
|
36914
37185
|
}
|
|
36915
37186
|
for (const { packaged, absSrc } of plan.overwriteSafe) {
|
|
36916
|
-
const absDest =
|
|
37187
|
+
const absDest = path16.join(projectDir, ".claude", packaged.dest);
|
|
36917
37188
|
if (!opts.dryRun) {
|
|
36918
|
-
fs15.mkdirSync(
|
|
37189
|
+
fs15.mkdirSync(path16.dirname(absDest), { recursive: true });
|
|
36919
37190
|
fs15.copyFileSync(absSrc, absDest);
|
|
36920
37191
|
if (opts.verbose) console.log(`updated ${packaged.dest}`);
|
|
36921
37192
|
} else if (opts.verbose) {
|
|
@@ -36928,7 +37199,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36928
37199
|
absSrc,
|
|
36929
37200
|
onDiskContent
|
|
36930
37201
|
} of plan.overwriteHandEdited) {
|
|
36931
|
-
const absDest =
|
|
37202
|
+
const absDest = path16.join(projectDir, ".claude", packaged.dest);
|
|
36932
37203
|
const newContent = fs15.readFileSync(absSrc);
|
|
36933
37204
|
const showDiff = () => {
|
|
36934
37205
|
console.log(
|
|
@@ -36941,7 +37212,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36941
37212
|
const answer = await promptOverwrite(packaged.dest, opts, showDiff);
|
|
36942
37213
|
if (answer === "overwrite") {
|
|
36943
37214
|
if (!opts.dryRun) {
|
|
36944
|
-
fs15.mkdirSync(
|
|
37215
|
+
fs15.mkdirSync(path16.dirname(absDest), { recursive: true });
|
|
36945
37216
|
fs15.copyFileSync(absSrc, absDest);
|
|
36946
37217
|
}
|
|
36947
37218
|
finalManifestEntries.push(packaged);
|
|
@@ -36957,9 +37228,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36957
37228
|
for (const { packaged, absSrc } of plan.newOptIn) {
|
|
36958
37229
|
const answer = await promptOptIn(packaged.dest, opts);
|
|
36959
37230
|
if (answer === "opt-in") {
|
|
36960
|
-
const absDest =
|
|
37231
|
+
const absDest = path16.join(projectDir, ".claude", packaged.dest);
|
|
36961
37232
|
if (!opts.dryRun) {
|
|
36962
|
-
fs15.mkdirSync(
|
|
37233
|
+
fs15.mkdirSync(path16.dirname(absDest), { recursive: true });
|
|
36963
37234
|
fs15.copyFileSync(absSrc, absDest);
|
|
36964
37235
|
}
|
|
36965
37236
|
finalManifestEntries.push(packaged);
|
|
@@ -36971,25 +37242,25 @@ async function runUpdate(opts, deps = {}) {
|
|
|
36971
37242
|
for (const e of plan.removedFromPackage) {
|
|
36972
37243
|
const answer = await promptRemove(e.dest, opts);
|
|
36973
37244
|
if (answer === "remove") {
|
|
36974
|
-
const absDest =
|
|
37245
|
+
const absDest = path16.join(projectDir, ".claude", e.dest);
|
|
36975
37246
|
if (!opts.dryRun && fs15.existsSync(absDest)) {
|
|
36976
37247
|
fs15.rmSync(absDest);
|
|
36977
|
-
const claudeDir =
|
|
36978
|
-
let cur =
|
|
36979
|
-
while (cur !== claudeDir && cur !==
|
|
36980
|
-
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;
|
|
36981
37252
|
try {
|
|
36982
37253
|
fs15.rmdirSync(cur);
|
|
36983
37254
|
if (opts.verbose)
|
|
36984
37255
|
console.log(
|
|
36985
|
-
`pruned empty dir ${
|
|
37256
|
+
`pruned empty dir ${path16.relative(claudeDir, cur)}`
|
|
36986
37257
|
);
|
|
36987
|
-
cur =
|
|
37258
|
+
cur = path16.dirname(cur);
|
|
36988
37259
|
} catch (err) {
|
|
36989
37260
|
const code = err.code;
|
|
36990
37261
|
if (code !== "ENOTEMPTY" && code !== "ENOENT") {
|
|
36991
37262
|
console.warn(
|
|
36992
|
-
`codebyplan claude: could not prune empty dir ${
|
|
37263
|
+
`codebyplan claude: could not prune empty dir ${path16.relative(claudeDir, cur)}: ${err.message}`
|
|
36993
37264
|
);
|
|
36994
37265
|
}
|
|
36995
37266
|
break;
|
|
@@ -37001,12 +37272,12 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37001
37272
|
if (opts.verbose) console.log(`kept (untracked) ${e.dest}`);
|
|
37002
37273
|
}
|
|
37003
37274
|
}
|
|
37004
|
-
const hooksJsonPath =
|
|
37005
|
-
const baseSettingsPath =
|
|
37275
|
+
const hooksJsonPath = path16.join(templatesDir, "hooks", "hooks.json");
|
|
37276
|
+
const baseSettingsPath = path16.join(
|
|
37006
37277
|
templatesDir,
|
|
37007
37278
|
"settings.project.base.json"
|
|
37008
37279
|
);
|
|
37009
|
-
const settingsPath =
|
|
37280
|
+
const settingsPath = path16.join(projectDir, ".claude", "settings.json");
|
|
37010
37281
|
const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
|
|
37011
37282
|
if (fs15.existsSync(baseSettingsPath)) {
|
|
37012
37283
|
const base = JSON.parse(
|
|
@@ -37027,21 +37298,29 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37027
37298
|
) : void 0
|
|
37028
37299
|
);
|
|
37029
37300
|
}
|
|
37301
|
+
await detectAndHealSettingsGitignore(
|
|
37302
|
+
projectDir,
|
|
37303
|
+
{ yes: opts.yes, dryRun: opts.dryRun },
|
|
37304
|
+
deps.detectHealDeps
|
|
37305
|
+
);
|
|
37030
37306
|
if (!opts.dryRun) {
|
|
37031
|
-
fs15.mkdirSync(
|
|
37307
|
+
fs15.mkdirSync(path16.dirname(settingsPath), { recursive: true });
|
|
37032
37308
|
fs15.writeFileSync(
|
|
37033
37309
|
settingsPath,
|
|
37034
37310
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
37035
37311
|
"utf8"
|
|
37036
37312
|
);
|
|
37037
37313
|
}
|
|
37314
|
+
if (!opts.dryRun) {
|
|
37315
|
+
warnIfSettingsUntracked(projectDir, deps.lsFilesDep);
|
|
37316
|
+
}
|
|
37038
37317
|
const gitignoreAction = await ensureManagedGitignoreBlock(
|
|
37039
37318
|
projectDir,
|
|
37040
37319
|
opts.dryRun
|
|
37041
37320
|
);
|
|
37042
37321
|
if (opts.verbose && gitignoreAction !== "unchanged") {
|
|
37043
37322
|
console.log(
|
|
37044
|
-
`${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"))}`
|
|
37045
37324
|
);
|
|
37046
37325
|
}
|
|
37047
37326
|
if (!opts.dryRun) {
|
|
@@ -37081,9 +37360,9 @@ function runUpdateUser(opts, deps) {
|
|
|
37081
37360
|
return;
|
|
37082
37361
|
}
|
|
37083
37362
|
try {
|
|
37084
|
-
const userDir = deps.userDir ??
|
|
37085
|
-
const settingsPath =
|
|
37086
|
-
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(
|
|
37087
37366
|
templatesDir,
|
|
37088
37367
|
"settings.user.base.json"
|
|
37089
37368
|
);
|
|
@@ -37136,6 +37415,7 @@ var init_update = __esm({
|
|
|
37136
37415
|
"src/cli/claude/update.ts"() {
|
|
37137
37416
|
"use strict";
|
|
37138
37417
|
init_gitignore_block();
|
|
37418
|
+
init_gitignore_detect();
|
|
37139
37419
|
init_templates_dir();
|
|
37140
37420
|
init_manifest();
|
|
37141
37421
|
init_settings_merge();
|
|
@@ -37154,7 +37434,7 @@ __export(uninstall_exports, {
|
|
|
37154
37434
|
});
|
|
37155
37435
|
import * as fs16 from "node:fs";
|
|
37156
37436
|
import * as os4 from "node:os";
|
|
37157
|
-
import * as
|
|
37437
|
+
import * as path17 from "node:path";
|
|
37158
37438
|
async function runUninstall(opts, deps = {}) {
|
|
37159
37439
|
await Promise.resolve();
|
|
37160
37440
|
const scope = opts.scope ?? "project";
|
|
@@ -37183,7 +37463,7 @@ async function runUninstall(opts, deps = {}) {
|
|
|
37183
37463
|
let removed = 0;
|
|
37184
37464
|
let warnings = 0;
|
|
37185
37465
|
for (const entry of manifest.files) {
|
|
37186
|
-
const abs =
|
|
37466
|
+
const abs = path17.join(projectDir, ".claude", entry.dest);
|
|
37187
37467
|
if (!fs16.existsSync(abs)) {
|
|
37188
37468
|
console.warn(
|
|
37189
37469
|
`codebyplan claude uninstall: ${entry.dest} already absent (skipping).`
|
|
@@ -37207,12 +37487,12 @@ async function runUninstall(opts, deps = {}) {
|
|
|
37207
37487
|
if (!opts.dryRun) {
|
|
37208
37488
|
pruneEmptyManagedDirs(projectDir);
|
|
37209
37489
|
}
|
|
37210
|
-
const settingsPath =
|
|
37490
|
+
const settingsPath = path17.join(projectDir, ".claude", "settings.json");
|
|
37211
37491
|
if (fs16.existsSync(settingsPath)) {
|
|
37212
37492
|
const settings = JSON.parse(
|
|
37213
37493
|
fs16.readFileSync(settingsPath, "utf8")
|
|
37214
37494
|
);
|
|
37215
|
-
const baseSettingsPath = templatesDir ?
|
|
37495
|
+
const baseSettingsPath = templatesDir ? path17.join(templatesDir, "settings.project.base.json") : null;
|
|
37216
37496
|
if (baseSettingsPath && fs16.existsSync(baseSettingsPath)) {
|
|
37217
37497
|
const base = JSON.parse(
|
|
37218
37498
|
fs16.readFileSync(baseSettingsPath, "utf8")
|
|
@@ -37270,7 +37550,7 @@ function runUninstallUser(opts, deps) {
|
|
|
37270
37550
|
}
|
|
37271
37551
|
}
|
|
37272
37552
|
try {
|
|
37273
|
-
const userDir = deps.userDir ??
|
|
37553
|
+
const userDir = deps.userDir ?? path17.join(os4.homedir(), ".claude");
|
|
37274
37554
|
const existingManifest = readManifestForScope("user", userDir);
|
|
37275
37555
|
if (!existingManifest) {
|
|
37276
37556
|
console.error(
|
|
@@ -37279,12 +37559,12 @@ function runUninstallUser(opts, deps) {
|
|
|
37279
37559
|
process.exitCode = 1;
|
|
37280
37560
|
return;
|
|
37281
37561
|
}
|
|
37282
|
-
const settingsPath =
|
|
37562
|
+
const settingsPath = path17.join(userDir, "settings.json");
|
|
37283
37563
|
if (fs16.existsSync(settingsPath)) {
|
|
37284
37564
|
const settings = JSON.parse(
|
|
37285
37565
|
fs16.readFileSync(settingsPath, "utf8")
|
|
37286
37566
|
);
|
|
37287
|
-
const userBaseSettingsPath = templatesDir != null ?
|
|
37567
|
+
const userBaseSettingsPath = templatesDir != null ? path17.join(templatesDir, "settings.user.base.json") : null;
|
|
37288
37568
|
if (userBaseSettingsPath && fs16.existsSync(userBaseSettingsPath)) {
|
|
37289
37569
|
const userBase = JSON.parse(
|
|
37290
37570
|
fs16.readFileSync(userBaseSettingsPath, "utf8")
|
|
@@ -37325,7 +37605,7 @@ function runUninstallUser(opts, deps) {
|
|
|
37325
37605
|
function pruneEmptyManagedDirs(projectDir) {
|
|
37326
37606
|
const managedRoots = ["skills", "agents", "hooks", "rules"];
|
|
37327
37607
|
for (const root of managedRoots) {
|
|
37328
|
-
const abs =
|
|
37608
|
+
const abs = path17.join(projectDir, ".claude", root);
|
|
37329
37609
|
if (!fs16.existsSync(abs)) continue;
|
|
37330
37610
|
pruneLeafFirst(abs);
|
|
37331
37611
|
}
|
|
@@ -37336,7 +37616,7 @@ function pruneLeafFirst(dir) {
|
|
|
37336
37616
|
if (!stat3.isDirectory()) return;
|
|
37337
37617
|
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
37338
37618
|
if (entry.isDirectory()) {
|
|
37339
|
-
pruneLeafFirst(
|
|
37619
|
+
pruneLeafFirst(path17.join(dir, entry.name));
|
|
37340
37620
|
}
|
|
37341
37621
|
}
|
|
37342
37622
|
const remaining = fs16.readdirSync(dir);
|
|
@@ -37357,7 +37637,7 @@ var init_uninstall = __esm({
|
|
|
37357
37637
|
|
|
37358
37638
|
// src/lib/verify-parity.ts
|
|
37359
37639
|
import * as fs17 from "node:fs";
|
|
37360
|
-
import * as
|
|
37640
|
+
import * as path18 from "node:path";
|
|
37361
37641
|
function isValidScope(s) {
|
|
37362
37642
|
return s === "org-shared" || s === "project-shared" || REPO_ONLY_RE.test(s);
|
|
37363
37643
|
}
|
|
@@ -37374,25 +37654,25 @@ function checkSiblingParity(opts) {
|
|
|
37374
37654
|
expectedOneSided = DEFAULT_EXPECTED_ONE_SIDED,
|
|
37375
37655
|
ignoredSubtrees
|
|
37376
37656
|
} = opts;
|
|
37377
|
-
const defaultIgnored = [
|
|
37657
|
+
const defaultIgnored = [path18.join(claudeDir, "hooks", "__test-fixtures__")];
|
|
37378
37658
|
const ignored = ignoredSubtrees ?? defaultIgnored;
|
|
37379
37659
|
const violations = [];
|
|
37380
37660
|
const claudeSideRels = /* @__PURE__ */ new Set();
|
|
37381
37661
|
for (const scanDir of SCAN_DIRS) {
|
|
37382
|
-
const baseDir =
|
|
37662
|
+
const baseDir = path18.join(claudeDir, scanDir);
|
|
37383
37663
|
if (!fs17.existsSync(baseDir)) continue;
|
|
37384
37664
|
const entries = readdirRecursive(baseDir);
|
|
37385
37665
|
for (const entry of entries) {
|
|
37386
|
-
const absPath =
|
|
37666
|
+
const absPath = path18.join(baseDir, entry);
|
|
37387
37667
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37388
37668
|
if (ignored.some(
|
|
37389
|
-
(ig) => absPath.startsWith(ig +
|
|
37669
|
+
(ig) => absPath.startsWith(ig + path18.sep) || absPath === ig
|
|
37390
37670
|
)) {
|
|
37391
37671
|
continue;
|
|
37392
37672
|
}
|
|
37393
|
-
const relPath =
|
|
37673
|
+
const relPath = path18.join(scanDir, entry).split(path18.sep).join("/");
|
|
37394
37674
|
claudeSideRels.add(relPath);
|
|
37395
|
-
const templatePath =
|
|
37675
|
+
const templatePath = path18.join(templatesDir, relPath);
|
|
37396
37676
|
if (!fs17.existsSync(templatePath)) {
|
|
37397
37677
|
if (!expectedOneSided.has(relPath) && !isScaffoldFile(entry)) {
|
|
37398
37678
|
violations.push({ type: "missing-twin", path: relPath });
|
|
@@ -37407,14 +37687,14 @@ function checkSiblingParity(opts) {
|
|
|
37407
37687
|
}
|
|
37408
37688
|
}
|
|
37409
37689
|
for (const scanDir of SCAN_DIRS) {
|
|
37410
|
-
const tplBase =
|
|
37690
|
+
const tplBase = path18.join(templatesDir, scanDir);
|
|
37411
37691
|
if (!fs17.existsSync(tplBase)) continue;
|
|
37412
37692
|
const entries = readdirRecursive(tplBase);
|
|
37413
37693
|
for (const entry of entries) {
|
|
37414
|
-
const absPath =
|
|
37694
|
+
const absPath = path18.join(tplBase, entry);
|
|
37415
37695
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37416
37696
|
if (isScaffoldFile(entry)) continue;
|
|
37417
|
-
const relPath =
|
|
37697
|
+
const relPath = path18.join(scanDir, entry).split(path18.sep).join("/");
|
|
37418
37698
|
if (!claudeSideRels.has(relPath) && !expectedOneSided.has(relPath)) {
|
|
37419
37699
|
violations.push({ type: "extra-twin", path: relPath });
|
|
37420
37700
|
}
|
|
@@ -37450,18 +37730,18 @@ function checkScopeMarkers(opts) {
|
|
|
37450
37730
|
const twinDetectionActive = templatesDir != null && fs17.existsSync(templatesDir);
|
|
37451
37731
|
const violations = [];
|
|
37452
37732
|
for (const scanDir of scanDirs) {
|
|
37453
|
-
const baseDir =
|
|
37733
|
+
const baseDir = path18.join(claudeDir, scanDir);
|
|
37454
37734
|
if (!fs17.existsSync(baseDir)) continue;
|
|
37455
37735
|
const entries = readdirRecursive(baseDir);
|
|
37456
37736
|
for (const entry of entries) {
|
|
37457
|
-
const absPath =
|
|
37737
|
+
const absPath = path18.join(baseDir, entry);
|
|
37458
37738
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37459
37739
|
if (!isStructuralEntry(scanDir, entry)) continue;
|
|
37460
|
-
const ext =
|
|
37740
|
+
const ext = path18.extname(entry).toLowerCase();
|
|
37461
37741
|
const isMd = ext === ".md";
|
|
37462
37742
|
const isSh = ext === ".sh";
|
|
37463
37743
|
if (!isMd && !isSh) continue;
|
|
37464
|
-
const relPath =
|
|
37744
|
+
const relPath = path18.join(scanDir, entry).split(path18.sep).join("/");
|
|
37465
37745
|
if (allowlist.has(relPath)) continue;
|
|
37466
37746
|
let content;
|
|
37467
37747
|
try {
|
|
@@ -37475,7 +37755,7 @@ function checkScopeMarkers(opts) {
|
|
|
37475
37755
|
continue;
|
|
37476
37756
|
}
|
|
37477
37757
|
const scopeValue = isMd ? extractFrontmatterScope(content) : extractShScope(content);
|
|
37478
|
-
const managed = twinDetectionActive && fs17.existsSync(
|
|
37758
|
+
const managed = twinDetectionActive && fs17.existsSync(path18.join(templatesDir, relPath));
|
|
37479
37759
|
if (managed) {
|
|
37480
37760
|
if (scopeValue === null) {
|
|
37481
37761
|
} else if (scopeValue === "org-shared") {
|
|
@@ -37529,7 +37809,7 @@ function readdirRecursive(dir, rel = "", visited = /* @__PURE__ */ new Set()) {
|
|
|
37529
37809
|
visited.add(realDir);
|
|
37530
37810
|
const results = [];
|
|
37531
37811
|
for (const name of fs17.readdirSync(dir)) {
|
|
37532
|
-
const full =
|
|
37812
|
+
const full = path18.join(dir, name);
|
|
37533
37813
|
const relName = rel ? `${rel}/${name}` : name;
|
|
37534
37814
|
if (fs17.lstatSync(full).isDirectory()) {
|
|
37535
37815
|
results.push(...readdirRecursive(full, relName, visited));
|
|
@@ -37602,12 +37882,12 @@ __export(verify_parity_exports, {
|
|
|
37602
37882
|
verifyParity: () => verifyParity
|
|
37603
37883
|
});
|
|
37604
37884
|
import * as fs18 from "node:fs";
|
|
37605
|
-
import * as
|
|
37885
|
+
import * as path19 from "node:path";
|
|
37606
37886
|
function verifyParity(args, deps = {}) {
|
|
37607
37887
|
const warnOnly = args.includes("--warn-only");
|
|
37608
37888
|
const jsonMode = args.includes("--json");
|
|
37609
37889
|
const projectDir = deps.cwd ?? process.cwd();
|
|
37610
|
-
const claudeDir =
|
|
37890
|
+
const claudeDir = path19.join(projectDir, ".claude");
|
|
37611
37891
|
if (!fs18.existsSync(claudeDir)) {
|
|
37612
37892
|
const msg = "codebyplan claude verify-parity: .claude/ not found in cwd \u2014 run from the project root.\n";
|
|
37613
37893
|
process.stderr.write(msg);
|
|
@@ -38114,11 +38394,11 @@ var generate_exports = {};
|
|
|
38114
38394
|
__export(generate_exports, {
|
|
38115
38395
|
runGenerate: () => runGenerate
|
|
38116
38396
|
});
|
|
38117
|
-
import { readFile as
|
|
38118
|
-
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";
|
|
38119
38399
|
async function readJsonFile4(filePath) {
|
|
38120
38400
|
try {
|
|
38121
|
-
const raw = await
|
|
38401
|
+
const raw = await readFile28(filePath, "utf-8");
|
|
38122
38402
|
return JSON.parse(raw);
|
|
38123
38403
|
} catch {
|
|
38124
38404
|
return null;
|
|
@@ -38126,7 +38406,7 @@ async function readJsonFile4(filePath) {
|
|
|
38126
38406
|
}
|
|
38127
38407
|
async function readPkgName(absPath) {
|
|
38128
38408
|
try {
|
|
38129
|
-
const raw = await
|
|
38409
|
+
const raw = await readFile28(join47(absPath, "package.json"), "utf-8");
|
|
38130
38410
|
const pkg = JSON.parse(raw);
|
|
38131
38411
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
38132
38412
|
} catch {
|
|
@@ -38140,7 +38420,7 @@ async function runGenerate(opts) {
|
|
|
38140
38420
|
const rootDir = resolve11(projectDir);
|
|
38141
38421
|
let packageManager;
|
|
38142
38422
|
try {
|
|
38143
|
-
const raw = await
|
|
38423
|
+
const raw = await readFile28(join47(rootDir, "package.json"), "utf-8");
|
|
38144
38424
|
const pkg = JSON.parse(raw);
|
|
38145
38425
|
if (typeof pkg.packageManager === "string") {
|
|
38146
38426
|
packageManager = pkg.packageManager;
|
|
@@ -38148,7 +38428,7 @@ async function runGenerate(opts) {
|
|
|
38148
38428
|
} catch {
|
|
38149
38429
|
}
|
|
38150
38430
|
const serverJson = await readJsonFile4(
|
|
38151
|
-
|
|
38431
|
+
join47(rootDir, ".codebyplan", "server.json")
|
|
38152
38432
|
);
|
|
38153
38433
|
const ports = [];
|
|
38154
38434
|
for (const alloc of serverJson?.port_allocations ?? []) {
|
|
@@ -38161,7 +38441,7 @@ async function runGenerate(opts) {
|
|
|
38161
38441
|
}
|
|
38162
38442
|
}
|
|
38163
38443
|
const gitJson = await readJsonFile4(
|
|
38164
|
-
|
|
38444
|
+
join47(rootDir, ".codebyplan", "git.json")
|
|
38165
38445
|
);
|
|
38166
38446
|
const branchModel = gitJson?.branch_config?.production ? {
|
|
38167
38447
|
production: gitJson.branch_config.production,
|
|
@@ -38170,7 +38450,7 @@ async function runGenerate(opts) {
|
|
|
38170
38450
|
)
|
|
38171
38451
|
} : void 0;
|
|
38172
38452
|
const shipmentJson = await readJsonFile4(
|
|
38173
|
-
|
|
38453
|
+
join47(rootDir, ".codebyplan", "shipment.json")
|
|
38174
38454
|
);
|
|
38175
38455
|
const shipmentSurfaces = [];
|
|
38176
38456
|
const rawSurfaces = shipmentJson?.shipment?.surfaces ?? shipmentJson?.surfaces ?? {};
|
|
@@ -38241,10 +38521,10 @@ async function runGenerate(opts) {
|
|
|
38241
38521
|
const structureMdContent = generateStructureMd(config);
|
|
38242
38522
|
const agentsContent = generateAgentsMd(structureMdContent);
|
|
38243
38523
|
if (check) {
|
|
38244
|
-
const agentsMdPath2 =
|
|
38524
|
+
const agentsMdPath2 = join47(rootDir, "AGENTS.md");
|
|
38245
38525
|
let existingAgents = null;
|
|
38246
38526
|
try {
|
|
38247
|
-
existingAgents = await
|
|
38527
|
+
existingAgents = await readFile28(agentsMdPath2, "utf-8");
|
|
38248
38528
|
} catch {
|
|
38249
38529
|
existingAgents = null;
|
|
38250
38530
|
}
|
|
@@ -38280,16 +38560,16 @@ async function runGenerate(opts) {
|
|
|
38280
38560
|
process.stdout.write(agentsContent);
|
|
38281
38561
|
return;
|
|
38282
38562
|
}
|
|
38283
|
-
const outputDir =
|
|
38563
|
+
const outputDir = join47(rootDir, ".claude", "generated");
|
|
38284
38564
|
await mkdir13(outputDir, { recursive: true });
|
|
38285
|
-
const outputPath =
|
|
38286
|
-
await
|
|
38565
|
+
const outputPath = join47(outputDir, "structure.md");
|
|
38566
|
+
await writeFile22(outputPath, structureMdContent, "utf-8");
|
|
38287
38567
|
process.stdout.write(`Wrote: .claude/generated/structure.md
|
|
38288
38568
|
`);
|
|
38289
|
-
const agentsMdPath =
|
|
38569
|
+
const agentsMdPath = join47(rootDir, "AGENTS.md");
|
|
38290
38570
|
let existingAgentsContent = null;
|
|
38291
38571
|
try {
|
|
38292
|
-
existingAgentsContent = await
|
|
38572
|
+
existingAgentsContent = await readFile28(agentsMdPath, "utf-8");
|
|
38293
38573
|
} catch {
|
|
38294
38574
|
existingAgentsContent = null;
|
|
38295
38575
|
}
|
|
@@ -38297,7 +38577,7 @@ async function runGenerate(opts) {
|
|
|
38297
38577
|
process.stdout.write(`Up to date: AGENTS.md
|
|
38298
38578
|
`);
|
|
38299
38579
|
} else {
|
|
38300
|
-
await
|
|
38580
|
+
await writeFile22(agentsMdPath, agentsContent, "utf-8");
|
|
38301
38581
|
process.stdout.write(`Wrote: AGENTS.md
|
|
38302
38582
|
`);
|
|
38303
38583
|
}
|
|
@@ -38317,11 +38597,11 @@ __export(readme_exports, {
|
|
|
38317
38597
|
runReadme: () => runReadme,
|
|
38318
38598
|
runReadmeCommand: () => runReadmeCommand
|
|
38319
38599
|
});
|
|
38320
|
-
import { readFile as
|
|
38321
|
-
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";
|
|
38322
38602
|
async function readJsonFile5(filePath) {
|
|
38323
38603
|
try {
|
|
38324
|
-
const raw = await
|
|
38604
|
+
const raw = await readFile29(filePath, "utf-8");
|
|
38325
38605
|
return JSON.parse(raw);
|
|
38326
38606
|
} catch {
|
|
38327
38607
|
return null;
|
|
@@ -38390,7 +38670,7 @@ async function discoverUnits(rootDir, rootPkgJson) {
|
|
|
38390
38670
|
const discovered = await discoverMonorepoApps(rootDir);
|
|
38391
38671
|
for (const app of discovered) {
|
|
38392
38672
|
const pkgJson = await readJsonFile5(
|
|
38393
|
-
|
|
38673
|
+
join48(app.absPath, "package.json")
|
|
38394
38674
|
);
|
|
38395
38675
|
pkgJsonByPath.set(app.absPath, pkgJson);
|
|
38396
38676
|
allPackages.push({
|
|
@@ -38416,7 +38696,7 @@ async function runReadme(opts) {
|
|
|
38416
38696
|
const init = opts.init ?? opts["init"] ?? false;
|
|
38417
38697
|
const rootDir = resolve12(projectDir);
|
|
38418
38698
|
const rootPkgJson = await readJsonFile5(
|
|
38419
|
-
|
|
38699
|
+
join48(rootDir, "package.json")
|
|
38420
38700
|
);
|
|
38421
38701
|
const { units, allPackages, pkgJsonByPath } = await discoverUnits(
|
|
38422
38702
|
rootDir,
|
|
@@ -38425,11 +38705,11 @@ async function runReadme(opts) {
|
|
|
38425
38705
|
const driftUnits = [];
|
|
38426
38706
|
const missingUnits = [];
|
|
38427
38707
|
for (const unit of units) {
|
|
38428
|
-
const readmePath =
|
|
38429
|
-
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");
|
|
38430
38710
|
let existingContent = null;
|
|
38431
38711
|
try {
|
|
38432
|
-
existingContent = await
|
|
38712
|
+
existingContent = await readFile29(readmePath, "utf-8");
|
|
38433
38713
|
} catch {
|
|
38434
38714
|
existingContent = null;
|
|
38435
38715
|
}
|
|
@@ -38464,7 +38744,7 @@ ${newContent}
|
|
|
38464
38744
|
`
|
|
38465
38745
|
);
|
|
38466
38746
|
} else {
|
|
38467
|
-
await
|
|
38747
|
+
await writeFile23(readmePath, newContent, "utf-8");
|
|
38468
38748
|
process.stdout.write(`Wrote (scaffold): ${relPath}
|
|
38469
38749
|
`);
|
|
38470
38750
|
}
|
|
@@ -38502,7 +38782,7 @@ ${newContent}
|
|
|
38502
38782
|
`
|
|
38503
38783
|
);
|
|
38504
38784
|
} else {
|
|
38505
|
-
await
|
|
38785
|
+
await writeFile23(readmePath, newContent, "utf-8");
|
|
38506
38786
|
process.stdout.write(`Wrote (refresh): ${relPath}
|
|
38507
38787
|
`);
|
|
38508
38788
|
}
|
|
@@ -38521,7 +38801,7 @@ ${newContent}
|
|
|
38521
38801
|
`
|
|
38522
38802
|
);
|
|
38523
38803
|
} else {
|
|
38524
|
-
await
|
|
38804
|
+
await writeFile23(readmePath, newContent, "utf-8");
|
|
38525
38805
|
process.stdout.write(`Wrote (init): ${relPath}
|
|
38526
38806
|
`);
|
|
38527
38807
|
}
|
|
@@ -38609,15 +38889,15 @@ __export(migrate_memory_exports, {
|
|
|
38609
38889
|
runMigrateMemory: () => runMigrateMemory
|
|
38610
38890
|
});
|
|
38611
38891
|
import {
|
|
38612
|
-
readFile as
|
|
38613
|
-
writeFile as
|
|
38892
|
+
readFile as readFile30,
|
|
38893
|
+
writeFile as writeFile24,
|
|
38614
38894
|
mkdir as mkdir14,
|
|
38615
38895
|
unlink as unlink6,
|
|
38616
38896
|
rmdir,
|
|
38617
38897
|
readdir as readdir7
|
|
38618
38898
|
} from "node:fs/promises";
|
|
38619
38899
|
import { existsSync as existsSync21 } from "node:fs";
|
|
38620
|
-
import { join as
|
|
38900
|
+
import { join as join49, resolve as resolve13, dirname as dirname15, sep as sep4 } from "node:path";
|
|
38621
38901
|
import { homedir as homedir8 } from "node:os";
|
|
38622
38902
|
function encodeProjectPath(absPath) {
|
|
38623
38903
|
return resolve13(absPath).replace(/[/\\]/g, "-");
|
|
@@ -38628,7 +38908,7 @@ function resolveAutoMemoryDir(opts) {
|
|
|
38628
38908
|
}
|
|
38629
38909
|
const projectDir = opts.projectDir ?? process.cwd();
|
|
38630
38910
|
const encoded = encodeProjectPath(projectDir);
|
|
38631
|
-
return
|
|
38911
|
+
return join49(homedir8(), ".claude", "projects", encoded, "memory");
|
|
38632
38912
|
}
|
|
38633
38913
|
function parseFrontmatter(content) {
|
|
38634
38914
|
content = content.replace(/\r\n/g, "\n");
|
|
@@ -38694,10 +38974,10 @@ async function inventoryFiles(dir) {
|
|
|
38694
38974
|
}
|
|
38695
38975
|
const results = [];
|
|
38696
38976
|
for (const filename of filenames) {
|
|
38697
|
-
const sourcePath =
|
|
38977
|
+
const sourcePath = join49(dir, filename);
|
|
38698
38978
|
let raw;
|
|
38699
38979
|
try {
|
|
38700
|
-
raw = await
|
|
38980
|
+
raw = await readFile30(sourcePath, "utf-8");
|
|
38701
38981
|
} catch (err) {
|
|
38702
38982
|
const msg = err instanceof Error ? err.message : String(err);
|
|
38703
38983
|
results.push({
|
|
@@ -38783,8 +39063,8 @@ async function applyPlan(plan, opts) {
|
|
|
38783
39063
|
if (entry.suggested_action !== "keep") continue;
|
|
38784
39064
|
if (!entry.suggested_target?.startsWith("nested:")) continue;
|
|
38785
39065
|
const relPath = entry.suggested_target.slice("nested:".length);
|
|
38786
|
-
const targetDir = resolve13(
|
|
38787
|
-
const targetFile =
|
|
39066
|
+
const targetDir = resolve13(join49(projectDir, relPath));
|
|
39067
|
+
const targetFile = join49(targetDir, "CLAUDE.md");
|
|
38788
39068
|
if (!targetDir.startsWith(resolve13(projectDir) + sep4)) {
|
|
38789
39069
|
process.stderr.write(
|
|
38790
39070
|
`migrate-memory: skipping unsafe suggested_target "${entry.suggested_target}" \u2014 resolves outside projectDir
|
|
@@ -38816,11 +39096,11 @@ ${anchor}
|
|
|
38816
39096
|
await mkdir14(targetDir, { recursive: true });
|
|
38817
39097
|
let existing = "";
|
|
38818
39098
|
try {
|
|
38819
|
-
existing = await
|
|
39099
|
+
existing = await readFile30(targetFile, "utf-8");
|
|
38820
39100
|
} catch {
|
|
38821
39101
|
}
|
|
38822
39102
|
if (!existing.includes(anchor)) {
|
|
38823
|
-
await
|
|
39103
|
+
await writeFile24(targetFile, existing + appendContent, "utf-8");
|
|
38824
39104
|
}
|
|
38825
39105
|
if (resolve13(entry.source_path).startsWith(resolve13(plan.auto_memory_dir) + sep4)) {
|
|
38826
39106
|
try {
|
|
@@ -38834,7 +39114,7 @@ ${anchor}
|
|
|
38834
39114
|
);
|
|
38835
39115
|
}
|
|
38836
39116
|
}
|
|
38837
|
-
const rootClaudeMd =
|
|
39117
|
+
const rootClaudeMd = join49(projectDir, ".claude", "CLAUDE.md");
|
|
38838
39118
|
if (dryRun) {
|
|
38839
39119
|
process.stdout.write(
|
|
38840
39120
|
`[dry-run] Would ensure ${rootClaudeMd} contains: ${IMPORT_LINE}
|
|
@@ -38843,12 +39123,12 @@ ${anchor}
|
|
|
38843
39123
|
} else {
|
|
38844
39124
|
let claudeMdContent = "";
|
|
38845
39125
|
try {
|
|
38846
|
-
claudeMdContent = await
|
|
39126
|
+
claudeMdContent = await readFile30(rootClaudeMd, "utf-8");
|
|
38847
39127
|
} catch {
|
|
38848
39128
|
await mkdir14(dirname15(rootClaudeMd), { recursive: true });
|
|
38849
39129
|
}
|
|
38850
39130
|
if (!claudeMdContent.includes(IMPORT_LINE)) {
|
|
38851
|
-
await
|
|
39131
|
+
await writeFile24(
|
|
38852
39132
|
rootClaudeMd,
|
|
38853
39133
|
claudeMdContent + `
|
|
38854
39134
|
${IMPORT_LINE}
|
|
@@ -38878,8 +39158,8 @@ ${IMPORT_LINE}
|
|
|
38878
39158
|
} catch {
|
|
38879
39159
|
}
|
|
38880
39160
|
}
|
|
38881
|
-
const memoryMd =
|
|
38882
|
-
const safeRmdirBase =
|
|
39161
|
+
const memoryMd = join49(plan.auto_memory_dir, "MEMORY.md");
|
|
39162
|
+
const safeRmdirBase = join49(homedir8(), ".claude", "projects");
|
|
38883
39163
|
if (dryRun) {
|
|
38884
39164
|
process.stdout.write(`[dry-run] Would delete MEMORY.md: ${memoryMd}
|
|
38885
39165
|
`);
|
|
@@ -38932,7 +39212,7 @@ async function runMigrateMemory(opts) {
|
|
|
38932
39212
|
if (applyFile) {
|
|
38933
39213
|
let planJson;
|
|
38934
39214
|
try {
|
|
38935
|
-
planJson = await
|
|
39215
|
+
planJson = await readFile30(resolve13(applyFile), "utf-8");
|
|
38936
39216
|
} catch (err) {
|
|
38937
39217
|
const msg = err instanceof Error ? err.message : String(err);
|
|
38938
39218
|
process.stderr.write(
|
|
@@ -39003,7 +39283,7 @@ var init_migrate_memory = __esm({
|
|
|
39003
39283
|
|
|
39004
39284
|
// src/lib/claude-mode-audit.ts
|
|
39005
39285
|
import { readdirSync as readdirSync7, readFileSync as readFileSync19, existsSync as existsSync22 } from "node:fs";
|
|
39006
|
-
import { join as
|
|
39286
|
+
import { join as join50, basename as basename2 } from "node:path";
|
|
39007
39287
|
function parseFrontmatter2(content) {
|
|
39008
39288
|
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
39009
39289
|
if (!match) return {};
|
|
@@ -39080,19 +39360,19 @@ function auditSkill(filePath) {
|
|
|
39080
39360
|
}
|
|
39081
39361
|
function auditMode(templatesDir) {
|
|
39082
39362
|
const entries = [];
|
|
39083
|
-
const agentsDir =
|
|
39363
|
+
const agentsDir = join50(templatesDir, "agents");
|
|
39084
39364
|
if (existsSync22(agentsDir)) {
|
|
39085
39365
|
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md")).sort();
|
|
39086
39366
|
for (const f of agentFiles) {
|
|
39087
|
-
entries.push(auditAgent(
|
|
39367
|
+
entries.push(auditAgent(join50(agentsDir, f)));
|
|
39088
39368
|
}
|
|
39089
39369
|
}
|
|
39090
|
-
const skillsDir =
|
|
39370
|
+
const skillsDir = join50(templatesDir, "skills");
|
|
39091
39371
|
if (existsSync22(skillsDir)) {
|
|
39092
39372
|
const skillDirs = readdirSync7(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
39093
39373
|
for (const dir of skillDirs) {
|
|
39094
|
-
if (existsSync22(
|
|
39095
|
-
const skillMd =
|
|
39374
|
+
if (existsSync22(join50(skillsDir, dir, "PROVENANCE.md"))) continue;
|
|
39375
|
+
const skillMd = join50(skillsDir, dir, "SKILL.md");
|
|
39096
39376
|
if (existsSync22(skillMd)) {
|
|
39097
39377
|
entries.push(auditSkill(skillMd));
|
|
39098
39378
|
}
|
|
@@ -39197,9 +39477,9 @@ var resolve_preview_exports = {};
|
|
|
39197
39477
|
__export(resolve_preview_exports, {
|
|
39198
39478
|
resolvePreview: () => resolvePreview
|
|
39199
39479
|
});
|
|
39200
|
-
import { spawnSync as
|
|
39480
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
39201
39481
|
function defaultGetCurrentBranch(cwd) {
|
|
39202
|
-
const result =
|
|
39482
|
+
const result = spawnSync12("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
39203
39483
|
cwd,
|
|
39204
39484
|
encoding: "utf-8",
|
|
39205
39485
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39351,7 +39631,7 @@ __export(new_migration_exports, {
|
|
|
39351
39631
|
newMigration: () => newMigration
|
|
39352
39632
|
});
|
|
39353
39633
|
import * as fs19 from "node:fs";
|
|
39354
|
-
import * as
|
|
39634
|
+
import * as path20 from "node:path";
|
|
39355
39635
|
function slugify(name) {
|
|
39356
39636
|
return name.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_");
|
|
39357
39637
|
}
|
|
@@ -39372,9 +39652,9 @@ function newMigration(args, deps = {}) {
|
|
|
39372
39652
|
}
|
|
39373
39653
|
const slug = slugify(rawName);
|
|
39374
39654
|
const stamp = genTimestamp({ cwd });
|
|
39375
|
-
const migrationsDir =
|
|
39655
|
+
const migrationsDir = path20.join(cwd, "supabase", "migrations");
|
|
39376
39656
|
const filename = `${stamp}_${slug}.sql`;
|
|
39377
|
-
const filePath =
|
|
39657
|
+
const filePath = path20.join(migrationsDir, filename);
|
|
39378
39658
|
mkdirSync11(migrationsDir, { recursive: true });
|
|
39379
39659
|
writeFileSync12(filePath, "");
|
|
39380
39660
|
process.stdout.write(JSON.stringify({ path: filePath }) + "\n");
|
|
@@ -39392,9 +39672,9 @@ var preview_check_exports = {};
|
|
|
39392
39672
|
__export(preview_check_exports, {
|
|
39393
39673
|
previewCheck: () => previewCheck
|
|
39394
39674
|
});
|
|
39395
|
-
import { spawnSync as
|
|
39675
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
39396
39676
|
function defaultRun3(cmd, args) {
|
|
39397
|
-
const result =
|
|
39677
|
+
const result = spawnSync13(cmd, args, {
|
|
39398
39678
|
encoding: "utf-8",
|
|
39399
39679
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39400
39680
|
});
|
|
@@ -39449,10 +39729,10 @@ var init_preview_check = __esm({
|
|
|
39449
39729
|
});
|
|
39450
39730
|
|
|
39451
39731
|
// src/lib/session.ts
|
|
39452
|
-
import { spawnSync as
|
|
39453
|
-
import * as
|
|
39732
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
39733
|
+
import * as path21 from "node:path";
|
|
39454
39734
|
function defaultRun4(cmd, args, cwd) {
|
|
39455
|
-
const result =
|
|
39735
|
+
const result = spawnSync14(cmd, args, {
|
|
39456
39736
|
cwd,
|
|
39457
39737
|
encoding: "utf-8",
|
|
39458
39738
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39480,7 +39760,7 @@ function homeFf(opts = {}) {
|
|
|
39480
39760
|
reason: "git rev-parse --show-toplevel failed"
|
|
39481
39761
|
};
|
|
39482
39762
|
}
|
|
39483
|
-
const folder =
|
|
39763
|
+
const folder = path21.basename(repoRoot);
|
|
39484
39764
|
let current;
|
|
39485
39765
|
try {
|
|
39486
39766
|
current = run("git", ["rev-parse", "--abbrev-ref", "HEAD"], cwd).trim();
|
|
@@ -39513,7 +39793,7 @@ function homeFf(opts = {}) {
|
|
|
39513
39793
|
}
|
|
39514
39794
|
function spawnVersionStatus(cwd) {
|
|
39515
39795
|
try {
|
|
39516
|
-
const result =
|
|
39796
|
+
const result = spawnSync14("npx", ["codebyplan", "version-status"], {
|
|
39517
39797
|
cwd,
|
|
39518
39798
|
encoding: "utf-8",
|
|
39519
39799
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39547,7 +39827,7 @@ function defaultRunInstall(installCommand, cwd) {
|
|
|
39547
39827
|
const cmd = parts[0];
|
|
39548
39828
|
const args = parts.slice(1);
|
|
39549
39829
|
if (!cmd) throw new Error("empty installCommand");
|
|
39550
|
-
const result =
|
|
39830
|
+
const result = spawnSync14(cmd, args, {
|
|
39551
39831
|
cwd,
|
|
39552
39832
|
encoding: "utf-8",
|
|
39553
39833
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39561,7 +39841,7 @@ function defaultRunInstall(installCommand, cwd) {
|
|
|
39561
39841
|
}
|
|
39562
39842
|
}
|
|
39563
39843
|
function defaultRunClaudeUpdate(cwd) {
|
|
39564
|
-
const result =
|
|
39844
|
+
const result = spawnSync14("npx", ["codebyplan", "claude", "update", "--yes"], {
|
|
39565
39845
|
cwd,
|
|
39566
39846
|
encoding: "utf-8",
|
|
39567
39847
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39575,7 +39855,7 @@ function defaultRunClaudeUpdate(cwd) {
|
|
|
39575
39855
|
}
|
|
39576
39856
|
}
|
|
39577
39857
|
function defaultRunGitStatus(cwd) {
|
|
39578
|
-
const result =
|
|
39858
|
+
const result = spawnSync14(
|
|
39579
39859
|
"git",
|
|
39580
39860
|
["status", "--porcelain", "--", ".claude/", ".codebyplan/"],
|
|
39581
39861
|
{
|
|
@@ -39828,9 +40108,9 @@ var commit_exports = {};
|
|
|
39828
40108
|
__export(commit_exports, {
|
|
39829
40109
|
runCommitCommand: () => runCommitCommand
|
|
39830
40110
|
});
|
|
39831
|
-
import { spawnSync as
|
|
40111
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
39832
40112
|
function defaultRun5(cmd, args) {
|
|
39833
|
-
const result =
|
|
40113
|
+
const result = spawnSync15(cmd, args, {
|
|
39834
40114
|
encoding: "utf-8",
|
|
39835
40115
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39836
40116
|
});
|
|
@@ -39878,7 +40158,7 @@ var init_commit = __esm({
|
|
|
39878
40158
|
});
|
|
39879
40159
|
|
|
39880
40160
|
// src/lib/migration-collisions.ts
|
|
39881
|
-
import { spawnSync as
|
|
40161
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
39882
40162
|
function extractPrefix(filename) {
|
|
39883
40163
|
const base = filename.endsWith(".sql") ? filename.slice(0, -4) : filename;
|
|
39884
40164
|
const underscoreIdx = base.indexOf("_");
|
|
@@ -39890,7 +40170,7 @@ function extractPrefix(filename) {
|
|
|
39890
40170
|
}
|
|
39891
40171
|
function makeDefaultRun(cwd) {
|
|
39892
40172
|
return (cmd, args) => {
|
|
39893
|
-
const result =
|
|
40173
|
+
const result = spawnSync16(cmd, args, {
|
|
39894
40174
|
cwd,
|
|
39895
40175
|
encoding: "utf-8",
|
|
39896
40176
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40047,13 +40327,13 @@ function validateWaves(waves) {
|
|
|
40047
40327
|
pathOwners.set(file, owners);
|
|
40048
40328
|
}
|
|
40049
40329
|
}
|
|
40050
|
-
for (const [
|
|
40330
|
+
for (const [path22, owners] of pathOwners) {
|
|
40051
40331
|
if (owners.length > 1) {
|
|
40052
40332
|
violations.push({
|
|
40053
40333
|
invariant: "I",
|
|
40054
40334
|
code: "DUPLICATE_FILE",
|
|
40055
|
-
message: `File "${
|
|
40056
|
-
detail: { path:
|
|
40335
|
+
message: `File "${path22}" appears in multiple waves: ${owners.join(", ")}.`,
|
|
40336
|
+
detail: { path: path22, waves: owners }
|
|
40057
40337
|
});
|
|
40058
40338
|
}
|
|
40059
40339
|
}
|
|
@@ -40147,7 +40427,7 @@ var validate_waves_exports = {};
|
|
|
40147
40427
|
__export(validate_waves_exports, {
|
|
40148
40428
|
runValidateWavesCommand: () => runValidateWavesCommand
|
|
40149
40429
|
});
|
|
40150
|
-
import { readFile as
|
|
40430
|
+
import { readFile as readFile31 } from "node:fs/promises";
|
|
40151
40431
|
async function readStdin() {
|
|
40152
40432
|
return new Promise((resolve16, reject) => {
|
|
40153
40433
|
const chunks = [];
|
|
@@ -40166,7 +40446,7 @@ async function runValidateWavesCommand(args) {
|
|
|
40166
40446
|
let raw;
|
|
40167
40447
|
if (filePath) {
|
|
40168
40448
|
try {
|
|
40169
|
-
raw = await
|
|
40449
|
+
raw = await readFile31(filePath, "utf-8");
|
|
40170
40450
|
} catch (err) {
|
|
40171
40451
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40172
40452
|
process.stderr.write(
|
|
@@ -40246,12 +40526,12 @@ var init_validate_waves2 = __esm({
|
|
|
40246
40526
|
});
|
|
40247
40527
|
|
|
40248
40528
|
// src/cli/worktree/path.ts
|
|
40249
|
-
import { dirname as dirname16, basename as basename4, join as
|
|
40529
|
+
import { dirname as dirname16, basename as basename4, join as join52 } from "node:path";
|
|
40250
40530
|
function computeWorktreePath(cwd, checkpointNumber) {
|
|
40251
40531
|
const parent = dirname16(cwd);
|
|
40252
40532
|
const base = basename4(cwd);
|
|
40253
40533
|
const nnn = String(checkpointNumber).padStart(3, "0");
|
|
40254
|
-
return
|
|
40534
|
+
return join52(parent, `${base}-CHK-${nnn}`);
|
|
40255
40535
|
}
|
|
40256
40536
|
var init_path = __esm({
|
|
40257
40537
|
"src/cli/worktree/path.ts"() {
|
|
@@ -40260,9 +40540,9 @@ var init_path = __esm({
|
|
|
40260
40540
|
});
|
|
40261
40541
|
|
|
40262
40542
|
// src/cli/worktree/add.ts
|
|
40263
|
-
import { join as
|
|
40264
|
-
import { mkdir as mkdir15, readFile as
|
|
40265
|
-
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";
|
|
40266
40546
|
async function defaultGetRepoId(cwd) {
|
|
40267
40547
|
const found = await findCodebyplanConfig(cwd);
|
|
40268
40548
|
return found?.contents.repo_id ?? null;
|
|
@@ -40291,7 +40571,7 @@ async function defaultLookupBranch(repoId, checkpointNumber) {
|
|
|
40291
40571
|
return { found: true, branch_name: chk.branch_name };
|
|
40292
40572
|
}
|
|
40293
40573
|
function defaultGitRun(args, cwd) {
|
|
40294
|
-
const result =
|
|
40574
|
+
const result = spawnSync17("git", args, {
|
|
40295
40575
|
cwd,
|
|
40296
40576
|
encoding: "utf-8",
|
|
40297
40577
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40303,34 +40583,56 @@ function defaultGitRun(args, cwd) {
|
|
|
40303
40583
|
error: result.error
|
|
40304
40584
|
};
|
|
40305
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
|
+
}
|
|
40306
40607
|
async function defaultCopyConfigStubs(srcCwd, destPath) {
|
|
40307
|
-
await mkdir15(
|
|
40608
|
+
await mkdir15(join53(destPath, ".codebyplan"), { recursive: true });
|
|
40308
40609
|
const topLevelStubs = [".mcp.json", ".env.local"];
|
|
40309
40610
|
for (const stub of topLevelStubs) {
|
|
40310
40611
|
try {
|
|
40311
|
-
const content = await
|
|
40312
|
-
await
|
|
40612
|
+
const content = await readFile32(join53(srcCwd, stub), "utf-8");
|
|
40613
|
+
await writeFile25(join53(destPath, stub), content, "utf-8");
|
|
40313
40614
|
} catch {
|
|
40314
40615
|
}
|
|
40315
40616
|
}
|
|
40316
40617
|
try {
|
|
40317
|
-
const content = await
|
|
40318
|
-
|
|
40618
|
+
const content = await readFile32(
|
|
40619
|
+
join53(srcCwd, ".codebyplan", "repo.json"),
|
|
40319
40620
|
"utf-8"
|
|
40320
40621
|
);
|
|
40321
|
-
await
|
|
40322
|
-
|
|
40622
|
+
await writeFile25(
|
|
40623
|
+
join53(destPath, ".codebyplan", "repo.json"),
|
|
40323
40624
|
content,
|
|
40324
40625
|
"utf-8"
|
|
40325
40626
|
);
|
|
40326
40627
|
} catch {
|
|
40327
40628
|
}
|
|
40629
|
+
await copyClaudeSettings(srcCwd, destPath);
|
|
40328
40630
|
}
|
|
40329
|
-
async function defaultRegisterWorktree(repoId, name,
|
|
40631
|
+
async function defaultRegisterWorktree(repoId, name, path22) {
|
|
40330
40632
|
const res = await apiPost("/worktrees", {
|
|
40331
40633
|
repo_id: repoId,
|
|
40332
40634
|
name,
|
|
40333
|
-
path:
|
|
40635
|
+
path: path22,
|
|
40334
40636
|
status: "active"
|
|
40335
40637
|
});
|
|
40336
40638
|
return { worktree_id: res.data.id };
|
|
@@ -40428,10 +40730,12 @@ async function runWorktreeAdd(args, deps = {}) {
|
|
|
40428
40730
|
);
|
|
40429
40731
|
return 1;
|
|
40430
40732
|
}
|
|
40733
|
+
let copyStubsWarn;
|
|
40431
40734
|
try {
|
|
40432
40735
|
await copyConfigStubs(cwd, worktreePath);
|
|
40433
40736
|
} catch (err) {
|
|
40434
40737
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40738
|
+
copyStubsWarn = `Failed to copy config stubs: ${msg}`;
|
|
40435
40739
|
process.stderr.write(`Warning: failed to copy config stubs: ${msg}
|
|
40436
40740
|
`);
|
|
40437
40741
|
}
|
|
@@ -40445,7 +40749,8 @@ async function runWorktreeAdd(args, deps = {}) {
|
|
|
40445
40749
|
status: "added",
|
|
40446
40750
|
worktree_path: worktreePath,
|
|
40447
40751
|
branch_name: branchName,
|
|
40448
|
-
worktree_id
|
|
40752
|
+
worktree_id,
|
|
40753
|
+
...copyStubsWarn ? { warn: copyStubsWarn } : {}
|
|
40449
40754
|
};
|
|
40450
40755
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40451
40756
|
return 0;
|
|
@@ -40480,7 +40785,7 @@ var init_add = __esm({
|
|
|
40480
40785
|
});
|
|
40481
40786
|
|
|
40482
40787
|
// src/cli/worktree/create.ts
|
|
40483
|
-
import { join as
|
|
40788
|
+
import { join as join54 } from "node:path";
|
|
40484
40789
|
async function defaultGetRepoIdentity(cwd) {
|
|
40485
40790
|
const found = await findCodebyplanConfig(cwd);
|
|
40486
40791
|
const contents = found?.contents ?? null;
|
|
@@ -40492,11 +40797,11 @@ async function defaultGetRepoIdentity(cwd) {
|
|
|
40492
40797
|
project_id: typeof contents?.["project_id"] === "string" ? contents["project_id"] : void 0
|
|
40493
40798
|
};
|
|
40494
40799
|
}
|
|
40495
|
-
async function defaultRegisterWorktree2(repoId, name,
|
|
40800
|
+
async function defaultRegisterWorktree2(repoId, name, path22) {
|
|
40496
40801
|
const res = await apiPost("/worktrees", {
|
|
40497
40802
|
repo_id: repoId,
|
|
40498
40803
|
name,
|
|
40499
|
-
path:
|
|
40804
|
+
path: path22,
|
|
40500
40805
|
status: "active"
|
|
40501
40806
|
});
|
|
40502
40807
|
return { worktree_id: res.data.id };
|
|
@@ -40525,6 +40830,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40525
40830
|
const getRepoIdentity = deps.getRepoIdentity ?? defaultGetRepoIdentity;
|
|
40526
40831
|
const getDeviceId = deps.getDeviceId ?? getOrCreateDeviceId;
|
|
40527
40832
|
const registerWorktree = deps.registerWorktree ?? defaultRegisterWorktree2;
|
|
40833
|
+
const copyClaudeSettingsFn = deps.copyClaudeSettingsFn ?? ((srcCwd, destPath) => copyClaudeSettings(srcCwd, destPath));
|
|
40528
40834
|
const identity = await getRepoIdentity(cwd);
|
|
40529
40835
|
const repoId = identity?.repo_id ?? null;
|
|
40530
40836
|
if (!identity || !repoId) {
|
|
@@ -40535,7 +40841,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40535
40841
|
);
|
|
40536
40842
|
return 1;
|
|
40537
40843
|
}
|
|
40538
|
-
const worktreePath = explicitPath ??
|
|
40844
|
+
const worktreePath = explicitPath ?? join54(cwd, "..", name);
|
|
40539
40845
|
const deviceId = await getDeviceId(cwd);
|
|
40540
40846
|
let filesWritten = false;
|
|
40541
40847
|
try {
|
|
@@ -40560,12 +40866,19 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40560
40866
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40561
40867
|
return 0;
|
|
40562
40868
|
}
|
|
40869
|
+
let copyWarn;
|
|
40870
|
+
try {
|
|
40871
|
+
await copyClaudeSettingsFn(cwd, worktreePath);
|
|
40872
|
+
} catch (err) {
|
|
40873
|
+
copyWarn = err instanceof Error ? err.message : String(err);
|
|
40874
|
+
}
|
|
40563
40875
|
try {
|
|
40564
40876
|
const { worktree_id } = await registerWorktree(repoId, name, worktreePath);
|
|
40565
40877
|
const result = {
|
|
40566
40878
|
worktree_files_written: true,
|
|
40567
40879
|
mcp_registered: true,
|
|
40568
|
-
worktree_id
|
|
40880
|
+
worktree_id,
|
|
40881
|
+
...copyWarn ? { warn: `Settings copy failed (non-fatal): ${copyWarn}` } : {}
|
|
40569
40882
|
};
|
|
40570
40883
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40571
40884
|
return 0;
|
|
@@ -40587,12 +40900,13 @@ var init_create = __esm({
|
|
|
40587
40900
|
init_local_config();
|
|
40588
40901
|
init_api();
|
|
40589
40902
|
init_worktree();
|
|
40903
|
+
init_add();
|
|
40590
40904
|
}
|
|
40591
40905
|
});
|
|
40592
40906
|
|
|
40593
40907
|
// src/cli/worktree/remove.ts
|
|
40594
40908
|
import { basename as basename6 } from "node:path";
|
|
40595
|
-
import { spawnSync as
|
|
40909
|
+
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
40596
40910
|
async function defaultGetRepoId2(cwd) {
|
|
40597
40911
|
const found = await findCodebyplanConfig(cwd);
|
|
40598
40912
|
return found?.contents.repo_id ?? null;
|
|
@@ -40614,7 +40928,7 @@ async function defaultDeregisterWorktree(worktreeId) {
|
|
|
40614
40928
|
await mcpCall("delete_worktree", { worktree_id: worktreeId });
|
|
40615
40929
|
}
|
|
40616
40930
|
function defaultGitRun2(args, cwd) {
|
|
40617
|
-
const result =
|
|
40931
|
+
const result = spawnSync18("git", args, {
|
|
40618
40932
|
cwd,
|
|
40619
40933
|
encoding: "utf-8",
|
|
40620
40934
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40627,7 +40941,7 @@ function defaultGitRun2(args, cwd) {
|
|
|
40627
40941
|
};
|
|
40628
40942
|
}
|
|
40629
40943
|
function defaultGetWorktreeBranchName(worktreePath) {
|
|
40630
|
-
const result =
|
|
40944
|
+
const result = spawnSync18("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
40631
40945
|
cwd: worktreePath,
|
|
40632
40946
|
encoding: "utf-8",
|
|
40633
40947
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -41006,6 +41320,24 @@ function verifyRound(input) {
|
|
|
41006
41320
|
}
|
|
41007
41321
|
}
|
|
41008
41322
|
}
|
|
41323
|
+
if (output.status === "completed") {
|
|
41324
|
+
const consoleErrors = output.console_errors;
|
|
41325
|
+
if (Array.isArray(consoleErrors) && consoleErrors.length > 0) {
|
|
41326
|
+
failed_checks.push({
|
|
41327
|
+
check: "console_errors_reported",
|
|
41328
|
+
framework,
|
|
41329
|
+
detail: `Framework "${framework}" completed but reported ${consoleErrors.length} console/page error(s) \u2014 a completed run must be console-clean per rules/e2e-mandatory.md.`
|
|
41330
|
+
});
|
|
41331
|
+
}
|
|
41332
|
+
const violations = output.a11y?.violations;
|
|
41333
|
+
if (Array.isArray(violations) && violations.length > 0) {
|
|
41334
|
+
failed_checks.push({
|
|
41335
|
+
check: "a11y_violations_reported",
|
|
41336
|
+
framework,
|
|
41337
|
+
detail: `Framework "${framework}" completed but reported ${violations.length} accessibility violation(s) \u2014 fix in-scope or classify as category 'a11y' failures per rules/e2e-mandatory.md.`
|
|
41338
|
+
});
|
|
41339
|
+
}
|
|
41340
|
+
}
|
|
41009
41341
|
}
|
|
41010
41342
|
return {
|
|
41011
41343
|
pass: failed_checks.length === 0,
|
|
@@ -41020,7 +41352,7 @@ var init_e2e = __esm({
|
|
|
41020
41352
|
});
|
|
41021
41353
|
|
|
41022
41354
|
// src/cli/e2e/verify-round.ts
|
|
41023
|
-
import { readFile as
|
|
41355
|
+
import { readFile as readFile33 } from "node:fs/promises";
|
|
41024
41356
|
import { resolve as resolve14 } from "node:path";
|
|
41025
41357
|
async function defaultFetchRounds(taskId) {
|
|
41026
41358
|
return mcpCall("get_rounds", { task_id: taskId });
|
|
@@ -41028,7 +41360,7 @@ async function defaultFetchRounds(taskId) {
|
|
|
41028
41360
|
async function defaultReadE2eConfig(cwd) {
|
|
41029
41361
|
try {
|
|
41030
41362
|
const p = resolve14(cwd, ".codebyplan", "e2e.json");
|
|
41031
|
-
const raw = await
|
|
41363
|
+
const raw = await readFile33(p, "utf-8");
|
|
41032
41364
|
return JSON.parse(raw);
|
|
41033
41365
|
} catch {
|
|
41034
41366
|
return null;
|
|
@@ -41153,6 +41485,8 @@ var doctor_exports = {};
|
|
|
41153
41485
|
__export(doctor_exports, {
|
|
41154
41486
|
runDoctor: () => runDoctor
|
|
41155
41487
|
});
|
|
41488
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
41489
|
+
import { join as join55 } from "node:path";
|
|
41156
41490
|
import { execSync as execSync10 } from "node:child_process";
|
|
41157
41491
|
async function checkAuth() {
|
|
41158
41492
|
try {
|
|
@@ -41259,6 +41593,75 @@ async function checkWorktree() {
|
|
|
41259
41593
|
};
|
|
41260
41594
|
}
|
|
41261
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
|
+
}
|
|
41262
41665
|
function overallStatus(checks) {
|
|
41263
41666
|
if (checks.some((c) => c.status === "fail")) return "fail";
|
|
41264
41667
|
if (checks.some((c) => c.status === "warn")) return "warn";
|
|
@@ -41283,7 +41686,7 @@ function printHuman(result) {
|
|
|
41283
41686
|
}
|
|
41284
41687
|
function printHelp6() {
|
|
41285
41688
|
process.stdout.write(
|
|
41286
|
-
"\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"
|
|
41287
41690
|
);
|
|
41288
41691
|
}
|
|
41289
41692
|
async function runDoctor(args) {
|
|
@@ -41297,7 +41700,8 @@ async function runDoctor(args) {
|
|
|
41297
41700
|
const checks = await Promise.all([
|
|
41298
41701
|
checkAuth(),
|
|
41299
41702
|
checkVersion(),
|
|
41300
|
-
checkWorktree()
|
|
41703
|
+
checkWorktree(),
|
|
41704
|
+
Promise.resolve(checkSettings())
|
|
41301
41705
|
]);
|
|
41302
41706
|
const result = {
|
|
41303
41707
|
checks,
|
|
@@ -41321,6 +41725,8 @@ var init_doctor = __esm({
|
|
|
41321
41725
|
init_flags();
|
|
41322
41726
|
init_local_config();
|
|
41323
41727
|
init_resolve_worktree();
|
|
41728
|
+
init_manifest();
|
|
41729
|
+
init_gitignore_detect();
|
|
41324
41730
|
}
|
|
41325
41731
|
});
|
|
41326
41732
|
|