codebyplan 1.13.51 → 1.13.53
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 +1776 -449
- package/package.json +1 -1
- package/templates/agents/cbp-security-agent.md +9 -1
- package/templates/agents/cbp-testing-qa-agent.md +23 -9
- package/templates/github-workflows/ci.yml +63 -0
- package/templates/github-workflows/publish.yml +8 -27
- package/templates/github-workflows/release-desktop.yml +215 -0
- package/templates/settings.project.base.json +7 -1
- package/templates/skills/cbp-build-cc-skill/SKILL.md +1 -0
- package/templates/skills/cbp-build-cc-skill/reference/fork-eligibility.md +78 -0
- package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +4 -0
- package/templates/skills/cbp-checkpoint-check/SKILL.md +9 -1
- package/templates/skills/cbp-checkpoint-end/SKILL.md +5 -1
- package/templates/skills/cbp-round-check/SKILL.md +2 -0
- package/templates/skills/cbp-setup-cd/SKILL.md +291 -0
- package/templates/skills/cbp-setup-cd/reference/github-actions-cd.md +231 -0
- package/templates/skills/cbp-setup-ci/SKILL.md +175 -0
- package/templates/skills/cbp-setup-ci/reference/github-actions.md +100 -0
- package/templates/skills/cbp-ship/SKILL.md +21 -0
- package/templates/skills/cbp-standalone-task-testing/SKILL.md +11 -2
- package/templates/skills/cbp-task-testing/SKILL.md +2 -0
package/dist/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ var VERSION, PACKAGE_NAME;
|
|
|
39
39
|
var init_version = __esm({
|
|
40
40
|
"src/lib/version.ts"() {
|
|
41
41
|
"use strict";
|
|
42
|
-
VERSION = "1.13.
|
|
42
|
+
VERSION = "1.13.53";
|
|
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 path21 = localConfigPath(projectPath);
|
|
117
|
+
const dirPath = dirname(path21);
|
|
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(path21, 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(path21) {
|
|
656
|
+
return readFile6(path21, "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: (path21, opts) => mkdir3(path21, opts).then(() => void 0),
|
|
778
|
+
writeFile: (path21, data, encoding) => writeFile4(path21, data, encoding),
|
|
779
|
+
readFile: (path21, encoding) => readFile6(path21, 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 path21 = fallbackFile(filename);
|
|
848
|
+
await mkdir4(dirname2(path21), { recursive: true });
|
|
849
|
+
await writeFile5(path21, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
850
850
|
if (platform() !== "win32") {
|
|
851
851
|
try {
|
|
852
|
-
await chmod(
|
|
852
|
+
await chmod(path21, 384);
|
|
853
853
|
} catch {
|
|
854
854
|
}
|
|
855
855
|
}
|
|
@@ -1141,8 +1141,8 @@ async function validateConnectivity() {
|
|
|
1141
1141
|
);
|
|
1142
1142
|
}
|
|
1143
1143
|
}
|
|
1144
|
-
function buildUrl(
|
|
1145
|
-
const url = new URL(`${baseUrl()}/api${
|
|
1144
|
+
function buildUrl(path21, params) {
|
|
1145
|
+
const url = new URL(`${baseUrl()}/api${path21}`);
|
|
1146
1146
|
if (params) {
|
|
1147
1147
|
for (const [key, value] of Object.entries(params)) {
|
|
1148
1148
|
if (value !== void 0) {
|
|
@@ -1159,10 +1159,10 @@ function isRetryable(err) {
|
|
|
1159
1159
|
return false;
|
|
1160
1160
|
}
|
|
1161
1161
|
function delay(ms) {
|
|
1162
|
-
return new Promise((
|
|
1162
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
1163
1163
|
}
|
|
1164
|
-
async function request(method,
|
|
1165
|
-
const url = buildUrl(
|
|
1164
|
+
async function request(method, path21, options) {
|
|
1165
|
+
const url = buildUrl(path21, options?.params);
|
|
1166
1166
|
const auth = await getAuthHeaders();
|
|
1167
1167
|
let lastError;
|
|
1168
1168
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
@@ -1182,7 +1182,7 @@ async function request(method, path16, options) {
|
|
|
1182
1182
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
1183
1183
|
});
|
|
1184
1184
|
if (!res.ok) {
|
|
1185
|
-
let message = `API ${method} ${
|
|
1185
|
+
let message = `API ${method} ${path21} failed with status ${res.status}`;
|
|
1186
1186
|
let code;
|
|
1187
1187
|
try {
|
|
1188
1188
|
const body = await res.json();
|
|
@@ -1216,20 +1216,20 @@ async function request(method, path16, options) {
|
|
|
1216
1216
|
}
|
|
1217
1217
|
throw lastError;
|
|
1218
1218
|
}
|
|
1219
|
-
async function apiGet(
|
|
1220
|
-
return request("GET",
|
|
1219
|
+
async function apiGet(path21, params) {
|
|
1220
|
+
return request("GET", path21, { params });
|
|
1221
1221
|
}
|
|
1222
|
-
async function apiPost(
|
|
1223
|
-
return request("POST",
|
|
1222
|
+
async function apiPost(path21, body) {
|
|
1223
|
+
return request("POST", path21, { body });
|
|
1224
1224
|
}
|
|
1225
|
-
async function apiPut(
|
|
1226
|
-
return request("PUT",
|
|
1225
|
+
async function apiPut(path21, body) {
|
|
1226
|
+
return request("PUT", path21, { body });
|
|
1227
1227
|
}
|
|
1228
|
-
async function apiPatch(
|
|
1229
|
-
return request("PATCH",
|
|
1228
|
+
async function apiPatch(path21, body) {
|
|
1229
|
+
return request("PATCH", path21, { body });
|
|
1230
1230
|
}
|
|
1231
|
-
async function apiDelete(
|
|
1232
|
-
await request("DELETE",
|
|
1231
|
+
async function apiDelete(path21, params) {
|
|
1232
|
+
await request("DELETE", path21, { params });
|
|
1233
1233
|
}
|
|
1234
1234
|
async function callMcpTool(toolName, params) {
|
|
1235
1235
|
const url = mcpEndpoint();
|
|
@@ -1523,7 +1523,7 @@ var init_device_flow = __esm({
|
|
|
1523
1523
|
this.name = "OAuthInvalidClientError";
|
|
1524
1524
|
}
|
|
1525
1525
|
};
|
|
1526
|
-
defaultSleep = (ms) => new Promise((
|
|
1526
|
+
defaultSleep = (ms) => new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
1527
1527
|
}
|
|
1528
1528
|
});
|
|
1529
1529
|
|
|
@@ -3411,9 +3411,9 @@ import { createInterface } from "node:readline/promises";
|
|
|
3411
3411
|
function getConfigPath(scope) {
|
|
3412
3412
|
return scope === "user" ? join14(homedir4(), ".claude.json") : join14(process.cwd(), ".mcp.json");
|
|
3413
3413
|
}
|
|
3414
|
-
async function readConfig(
|
|
3414
|
+
async function readConfig(path21) {
|
|
3415
3415
|
try {
|
|
3416
|
-
const raw = await readFile11(
|
|
3416
|
+
const raw = await readFile11(path21, "utf-8");
|
|
3417
3417
|
const parsed = JSON.parse(raw);
|
|
3418
3418
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3419
3419
|
return parsed;
|
|
@@ -3844,9 +3844,9 @@ import { join as join15 } from "node:path";
|
|
|
3844
3844
|
function configPaths() {
|
|
3845
3845
|
return [join15(homedir5(), ".claude.json"), join15(process.cwd(), ".mcp.json")];
|
|
3846
3846
|
}
|
|
3847
|
-
async function readConfig2(
|
|
3847
|
+
async function readConfig2(path21) {
|
|
3848
3848
|
try {
|
|
3849
|
-
const raw = await readFile12(
|
|
3849
|
+
const raw = await readFile12(path21, "utf-8");
|
|
3850
3850
|
const parsed = JSON.parse(raw);
|
|
3851
3851
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3852
3852
|
return parsed;
|
|
@@ -3860,7 +3860,7 @@ function entryHasLegacyApiKey(entry) {
|
|
|
3860
3860
|
if (!entry || !entry.headers) return false;
|
|
3861
3861
|
return "x-api-key" in entry.headers;
|
|
3862
3862
|
}
|
|
3863
|
-
async function rewriteConfig(
|
|
3863
|
+
async function rewriteConfig(path21, config, newUrl) {
|
|
3864
3864
|
const servers = config.mcpServers;
|
|
3865
3865
|
if (!servers) return false;
|
|
3866
3866
|
const entry = servers.codebyplan;
|
|
@@ -3868,7 +3868,7 @@ async function rewriteConfig(path16, config, newUrl) {
|
|
|
3868
3868
|
if (!entryHasLegacyApiKey(entry) && entry.url === newUrl && entry.type === "http")
|
|
3869
3869
|
return false;
|
|
3870
3870
|
servers.codebyplan = { type: "http", url: newUrl };
|
|
3871
|
-
await writeFile9(
|
|
3871
|
+
await writeFile9(path21, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3872
3872
|
return true;
|
|
3873
3873
|
}
|
|
3874
3874
|
async function runUpgradeAuth() {
|
|
@@ -3876,12 +3876,12 @@ async function runUpgradeAuth() {
|
|
|
3876
3876
|
await runLogin();
|
|
3877
3877
|
const newUrl = mcpEndpoint();
|
|
3878
3878
|
let migrated = 0;
|
|
3879
|
-
for (const
|
|
3880
|
-
const config = await readConfig2(
|
|
3879
|
+
for (const path21 of configPaths()) {
|
|
3880
|
+
const config = await readConfig2(path21);
|
|
3881
3881
|
if (!config) continue;
|
|
3882
|
-
const changed = await rewriteConfig(
|
|
3882
|
+
const changed = await rewriteConfig(path21, config, newUrl);
|
|
3883
3883
|
if (changed) {
|
|
3884
|
-
console.log(` Updated ${
|
|
3884
|
+
console.log(` Updated ${path21}`);
|
|
3885
3885
|
migrated++;
|
|
3886
3886
|
}
|
|
3887
3887
|
}
|
|
@@ -4558,9 +4558,9 @@ async function eslintInit(repoId, projectPath) {
|
|
|
4558
4558
|
Install ${missingPkgs.length} missing packages? [Y/n] `
|
|
4559
4559
|
);
|
|
4560
4560
|
if (confirmed) {
|
|
4561
|
-
const { execSync:
|
|
4561
|
+
const { execSync: execSync11 } = await import("node:child_process");
|
|
4562
4562
|
try {
|
|
4563
|
-
|
|
4563
|
+
execSync11(installCmd, { cwd: projectPath, stdio: "inherit" });
|
|
4564
4564
|
console.log(" Packages installed.\n");
|
|
4565
4565
|
} catch (err) {
|
|
4566
4566
|
console.error(
|
|
@@ -5326,11 +5326,11 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
5326
5326
|
}
|
|
5327
5327
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
5328
5328
|
function adopt(value) {
|
|
5329
|
-
return value instanceof P ? value : new P(function(
|
|
5330
|
-
|
|
5329
|
+
return value instanceof P ? value : new P(function(resolve16) {
|
|
5330
|
+
resolve16(value);
|
|
5331
5331
|
});
|
|
5332
5332
|
}
|
|
5333
|
-
return new (P || (P = Promise))(function(
|
|
5333
|
+
return new (P || (P = Promise))(function(resolve16, reject) {
|
|
5334
5334
|
function fulfilled(value) {
|
|
5335
5335
|
try {
|
|
5336
5336
|
step(generator.next(value));
|
|
@@ -5346,7 +5346,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
5346
5346
|
}
|
|
5347
5347
|
}
|
|
5348
5348
|
function step(result) {
|
|
5349
|
-
result.done ?
|
|
5349
|
+
result.done ? resolve16(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
5350
5350
|
}
|
|
5351
5351
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
5352
5352
|
});
|
|
@@ -5537,14 +5537,14 @@ function __asyncValues(o) {
|
|
|
5537
5537
|
}, i);
|
|
5538
5538
|
function verb(n) {
|
|
5539
5539
|
i[n] = o[n] && function(v) {
|
|
5540
|
-
return new Promise(function(
|
|
5541
|
-
v = o[n](v), settle(
|
|
5540
|
+
return new Promise(function(resolve16, reject) {
|
|
5541
|
+
v = o[n](v), settle(resolve16, reject, v.done, v.value);
|
|
5542
5542
|
});
|
|
5543
5543
|
};
|
|
5544
5544
|
}
|
|
5545
|
-
function settle(
|
|
5545
|
+
function settle(resolve16, reject, d, v) {
|
|
5546
5546
|
Promise.resolve(v).then(function(v2) {
|
|
5547
|
-
|
|
5547
|
+
resolve16({ value: v2, done: d });
|
|
5548
5548
|
}, reject);
|
|
5549
5549
|
}
|
|
5550
5550
|
}
|
|
@@ -5636,13 +5636,13 @@ function __disposeResources(env) {
|
|
|
5636
5636
|
}
|
|
5637
5637
|
return next();
|
|
5638
5638
|
}
|
|
5639
|
-
function __rewriteRelativeImportExtension(
|
|
5640
|
-
if (typeof
|
|
5641
|
-
return
|
|
5639
|
+
function __rewriteRelativeImportExtension(path21, preserveJsx) {
|
|
5640
|
+
if (typeof path21 === "string" && /^\.\.?\//.test(path21)) {
|
|
5641
|
+
return path21.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
5642
5642
|
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
5643
5643
|
});
|
|
5644
5644
|
}
|
|
5645
|
-
return
|
|
5645
|
+
return path21;
|
|
5646
5646
|
}
|
|
5647
5647
|
var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
|
|
5648
5648
|
var init_tslib_es6 = __esm({
|
|
@@ -6117,18 +6117,18 @@ var require_main = __commonJS({
|
|
|
6117
6117
|
|
|
6118
6118
|
// ../../node_modules/.pnpm/@supabase+postgrest-js@2.106.0/node_modules/@supabase/postgrest-js/dist/index.mjs
|
|
6119
6119
|
function sleep(ms, signal) {
|
|
6120
|
-
return new Promise((
|
|
6120
|
+
return new Promise((resolve16) => {
|
|
6121
6121
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
6122
|
-
|
|
6122
|
+
resolve16();
|
|
6123
6123
|
return;
|
|
6124
6124
|
}
|
|
6125
6125
|
const id = setTimeout(() => {
|
|
6126
6126
|
signal === null || signal === void 0 || signal.removeEventListener("abort", onAbort);
|
|
6127
|
-
|
|
6127
|
+
resolve16();
|
|
6128
6128
|
}, ms);
|
|
6129
6129
|
function onAbort() {
|
|
6130
6130
|
clearTimeout(id);
|
|
6131
|
-
|
|
6131
|
+
resolve16();
|
|
6132
6132
|
}
|
|
6133
6133
|
signal === null || signal === void 0 || signal.addEventListener("abort", onAbort);
|
|
6134
6134
|
});
|
|
@@ -14165,15 +14165,15 @@ var require_RealtimeChannel = __commonJS({
|
|
|
14165
14165
|
}
|
|
14166
14166
|
}
|
|
14167
14167
|
} else {
|
|
14168
|
-
return new Promise((
|
|
14168
|
+
return new Promise((resolve16) => {
|
|
14169
14169
|
var _a2, _b2, _c;
|
|
14170
14170
|
const push = this.channelAdapter.push(args.type, args, opts.timeout || this.timeout);
|
|
14171
14171
|
if (args.type === "broadcast" && !((_c = (_b2 = (_a2 = this.params) === null || _a2 === void 0 ? void 0 : _a2.config) === null || _b2 === void 0 ? void 0 : _b2.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
|
|
14172
|
-
|
|
14172
|
+
resolve16("ok");
|
|
14173
14173
|
}
|
|
14174
|
-
push.receive("ok", () =>
|
|
14175
|
-
push.receive("error", () =>
|
|
14176
|
-
push.receive("timeout", () =>
|
|
14174
|
+
push.receive("ok", () => resolve16("ok"));
|
|
14175
|
+
push.receive("error", () => resolve16("error"));
|
|
14176
|
+
push.receive("timeout", () => resolve16("timed out"));
|
|
14177
14177
|
});
|
|
14178
14178
|
}
|
|
14179
14179
|
}
|
|
@@ -14198,8 +14198,8 @@ var require_RealtimeChannel = __commonJS({
|
|
|
14198
14198
|
* @category Realtime
|
|
14199
14199
|
*/
|
|
14200
14200
|
async unsubscribe(timeout = this.timeout) {
|
|
14201
|
-
return new Promise((
|
|
14202
|
-
this.channelAdapter.unsubscribe(timeout).receive("ok", () =>
|
|
14201
|
+
return new Promise((resolve16) => {
|
|
14202
|
+
this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve16("ok")).receive("timeout", () => resolve16("timed out")).receive("error", () => resolve16("error"));
|
|
14203
14203
|
});
|
|
14204
14204
|
}
|
|
14205
14205
|
/**
|
|
@@ -14280,8 +14280,8 @@ var require_RealtimeChannel = __commonJS({
|
|
|
14280
14280
|
}
|
|
14281
14281
|
/** @internal */
|
|
14282
14282
|
_notThisChannelEvent(event, ref) {
|
|
14283
|
-
const { close, error, leave, join:
|
|
14284
|
-
const events = [close, error, leave,
|
|
14283
|
+
const { close, error, leave, join: join53 } = constants_1.CHANNEL_EVENTS;
|
|
14284
|
+
const events = [close, error, leave, join53];
|
|
14285
14285
|
return ref && events.includes(event) && ref !== this.joinPush.ref;
|
|
14286
14286
|
}
|
|
14287
14287
|
/** @internal */
|
|
@@ -14403,11 +14403,11 @@ var require_socketAdapter = __commonJS({
|
|
|
14403
14403
|
this.socket.connect();
|
|
14404
14404
|
}
|
|
14405
14405
|
disconnect(callback, code, reason, timeout = 1e4) {
|
|
14406
|
-
return new Promise((
|
|
14407
|
-
setTimeout(() =>
|
|
14406
|
+
return new Promise((resolve16) => {
|
|
14407
|
+
setTimeout(() => resolve16("timeout"), timeout);
|
|
14408
14408
|
this.socket.disconnect(() => {
|
|
14409
14409
|
callback();
|
|
14410
|
-
|
|
14410
|
+
resolve16("ok");
|
|
14411
14411
|
}, code, reason);
|
|
14412
14412
|
});
|
|
14413
14413
|
}
|
|
@@ -15164,8 +15164,8 @@ var require_main2 = __commonJS({
|
|
|
15164
15164
|
});
|
|
15165
15165
|
|
|
15166
15166
|
// ../../node_modules/.pnpm/iceberg-js@0.8.1/node_modules/iceberg-js/dist/index.mjs
|
|
15167
|
-
function buildUrl2(baseUrl3,
|
|
15168
|
-
const url = new URL(
|
|
15167
|
+
function buildUrl2(baseUrl3, path21, query) {
|
|
15168
|
+
const url = new URL(path21, baseUrl3);
|
|
15169
15169
|
if (query) {
|
|
15170
15170
|
for (const [key, value] of Object.entries(query)) {
|
|
15171
15171
|
if (value !== void 0) {
|
|
@@ -15195,12 +15195,12 @@ function createFetchClient(options) {
|
|
|
15195
15195
|
return {
|
|
15196
15196
|
async request({
|
|
15197
15197
|
method,
|
|
15198
|
-
path:
|
|
15198
|
+
path: path21,
|
|
15199
15199
|
query,
|
|
15200
15200
|
body,
|
|
15201
15201
|
headers
|
|
15202
15202
|
}) {
|
|
15203
|
-
const url = buildUrl2(options.baseUrl,
|
|
15203
|
+
const url = buildUrl2(options.baseUrl, path21, query);
|
|
15204
15204
|
const authHeaders = await buildAuthHeaders(options.auth);
|
|
15205
15205
|
const res = await fetchFn(url, {
|
|
15206
15206
|
method,
|
|
@@ -15769,7 +15769,7 @@ function normalizeHeaders(headers) {
|
|
|
15769
15769
|
return result;
|
|
15770
15770
|
}
|
|
15771
15771
|
async function _handleRequest(fetcher, method, url, options, parameters, body, namespace) {
|
|
15772
|
-
return new Promise((
|
|
15772
|
+
return new Promise((resolve16, reject) => {
|
|
15773
15773
|
fetcher(url, _getRequestParams(method, options, parameters, body)).then((result) => {
|
|
15774
15774
|
if (!result.ok) throw result;
|
|
15775
15775
|
if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result;
|
|
@@ -15779,7 +15779,7 @@ async function _handleRequest(fetcher, method, url, options, parameters, body, n
|
|
|
15779
15779
|
if (!contentType || !contentType.includes("application/json")) return {};
|
|
15780
15780
|
}
|
|
15781
15781
|
return result.json();
|
|
15782
|
-
}).then((data) =>
|
|
15782
|
+
}).then((data) => resolve16(data)).catch((error) => handleError(error, reject, options, namespace));
|
|
15783
15783
|
});
|
|
15784
15784
|
}
|
|
15785
15785
|
function createFetchApi(namespace = "storage") {
|
|
@@ -16098,7 +16098,7 @@ var init_dist3 = __esm({
|
|
|
16098
16098
|
* @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
|
|
16099
16099
|
* @param fileBody The body of the file to be stored in the bucket.
|
|
16100
16100
|
*/
|
|
16101
|
-
async uploadOrUpdate(method,
|
|
16101
|
+
async uploadOrUpdate(method, path21, fileBody, fileOptions) {
|
|
16102
16102
|
var _this = this;
|
|
16103
16103
|
return _this.handleOperation(async () => {
|
|
16104
16104
|
let body;
|
|
@@ -16122,7 +16122,7 @@ var init_dist3 = __esm({
|
|
|
16122
16122
|
if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
|
|
16123
16123
|
}
|
|
16124
16124
|
if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
|
|
16125
|
-
const cleanPath = _this._removeEmptyFolders(
|
|
16125
|
+
const cleanPath = _this._removeEmptyFolders(path21);
|
|
16126
16126
|
const _path = _this._getFinalPath(cleanPath);
|
|
16127
16127
|
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 } : {}));
|
|
16128
16128
|
return {
|
|
@@ -16184,8 +16184,8 @@ var init_dist3 = __esm({
|
|
|
16184
16184
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16185
16185
|
* - 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.
|
|
16186
16186
|
*/
|
|
16187
|
-
async upload(
|
|
16188
|
-
return this.uploadOrUpdate("POST",
|
|
16187
|
+
async upload(path21, fileBody, fileOptions) {
|
|
16188
|
+
return this.uploadOrUpdate("POST", path21, fileBody, fileOptions);
|
|
16189
16189
|
}
|
|
16190
16190
|
/**
|
|
16191
16191
|
* Upload a file with a token generated from `createSignedUploadUrl`.
|
|
@@ -16225,9 +16225,9 @@ var init_dist3 = __esm({
|
|
|
16225
16225
|
* - `objects` table permissions: none
|
|
16226
16226
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16227
16227
|
*/
|
|
16228
|
-
async uploadToSignedUrl(
|
|
16228
|
+
async uploadToSignedUrl(path21, token, fileBody, fileOptions) {
|
|
16229
16229
|
var _this3 = this;
|
|
16230
|
-
const cleanPath = _this3._removeEmptyFolders(
|
|
16230
|
+
const cleanPath = _this3._removeEmptyFolders(path21);
|
|
16231
16231
|
const _path = _this3._getFinalPath(cleanPath);
|
|
16232
16232
|
const url = new URL(_this3.url + `/object/upload/sign/${_path}`);
|
|
16233
16233
|
url.searchParams.set("token", token);
|
|
@@ -16296,10 +16296,10 @@ var init_dist3 = __esm({
|
|
|
16296
16296
|
* - `objects` table permissions: `insert`
|
|
16297
16297
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16298
16298
|
*/
|
|
16299
|
-
async createSignedUploadUrl(
|
|
16299
|
+
async createSignedUploadUrl(path21, options) {
|
|
16300
16300
|
var _this4 = this;
|
|
16301
16301
|
return _this4.handleOperation(async () => {
|
|
16302
|
-
let _path = _this4._getFinalPath(
|
|
16302
|
+
let _path = _this4._getFinalPath(path21);
|
|
16303
16303
|
const headers = _objectSpread22({}, _this4.headers);
|
|
16304
16304
|
if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
|
|
16305
16305
|
const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
|
|
@@ -16308,7 +16308,7 @@ var init_dist3 = __esm({
|
|
|
16308
16308
|
if (!token) throw new StorageError("No token returned by API");
|
|
16309
16309
|
return {
|
|
16310
16310
|
signedUrl: url.toString(),
|
|
16311
|
-
path:
|
|
16311
|
+
path: path21,
|
|
16312
16312
|
token
|
|
16313
16313
|
};
|
|
16314
16314
|
});
|
|
@@ -16368,8 +16368,8 @@ var init_dist3 = __esm({
|
|
|
16368
16368
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16369
16369
|
* - 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.
|
|
16370
16370
|
*/
|
|
16371
|
-
async update(
|
|
16372
|
-
return this.uploadOrUpdate("PUT",
|
|
16371
|
+
async update(path21, fileBody, fileOptions) {
|
|
16372
|
+
return this.uploadOrUpdate("PUT", path21, fileBody, fileOptions);
|
|
16373
16373
|
}
|
|
16374
16374
|
/**
|
|
16375
16375
|
* Moves an existing file to a new path in the same bucket.
|
|
@@ -16520,10 +16520,10 @@ var init_dist3 = __esm({
|
|
|
16520
16520
|
* - `objects` table permissions: `select`
|
|
16521
16521
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16522
16522
|
*/
|
|
16523
|
-
async createSignedUrl(
|
|
16523
|
+
async createSignedUrl(path21, expiresIn, options) {
|
|
16524
16524
|
var _this8 = this;
|
|
16525
16525
|
return _this8.handleOperation(async () => {
|
|
16526
|
-
let _path = _this8._getFinalPath(
|
|
16526
|
+
let _path = _this8._getFinalPath(path21);
|
|
16527
16527
|
const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
|
|
16528
16528
|
let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread22({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
|
|
16529
16529
|
const query = new URLSearchParams();
|
|
@@ -16659,13 +16659,13 @@ var init_dist3 = __esm({
|
|
|
16659
16659
|
* - `objects` table permissions: `select`
|
|
16660
16660
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16661
16661
|
*/
|
|
16662
|
-
download(
|
|
16662
|
+
download(path21, options, parameters) {
|
|
16663
16663
|
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";
|
|
16664
16664
|
const query = new URLSearchParams();
|
|
16665
16665
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
16666
16666
|
if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
|
|
16667
16667
|
const queryString = query.toString();
|
|
16668
|
-
const _path = this._getFinalPath(
|
|
16668
|
+
const _path = this._getFinalPath(path21);
|
|
16669
16669
|
const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
|
|
16670
16670
|
headers: this.headers,
|
|
16671
16671
|
noResolveJson: true
|
|
@@ -16696,9 +16696,9 @@ var init_dist3 = __esm({
|
|
|
16696
16696
|
* }
|
|
16697
16697
|
* ```
|
|
16698
16698
|
*/
|
|
16699
|
-
async info(
|
|
16699
|
+
async info(path21) {
|
|
16700
16700
|
var _this10 = this;
|
|
16701
|
-
const _path = _this10._getFinalPath(
|
|
16701
|
+
const _path = _this10._getFinalPath(path21);
|
|
16702
16702
|
return _this10.handleOperation(async () => {
|
|
16703
16703
|
return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
|
|
16704
16704
|
});
|
|
@@ -16719,9 +16719,9 @@ var init_dist3 = __esm({
|
|
|
16719
16719
|
* .exists('folder/avatar1.png')
|
|
16720
16720
|
* ```
|
|
16721
16721
|
*/
|
|
16722
|
-
async exists(
|
|
16722
|
+
async exists(path21) {
|
|
16723
16723
|
var _this11 = this;
|
|
16724
|
-
const _path = _this11._getFinalPath(
|
|
16724
|
+
const _path = _this11._getFinalPath(path21);
|
|
16725
16725
|
try {
|
|
16726
16726
|
await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
|
|
16727
16727
|
return {
|
|
@@ -16800,8 +16800,8 @@ var init_dist3 = __esm({
|
|
|
16800
16800
|
* - `objects` table permissions: none
|
|
16801
16801
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16802
16802
|
*/
|
|
16803
|
-
getPublicUrl(
|
|
16804
|
-
const _path = this._getFinalPath(
|
|
16803
|
+
getPublicUrl(path21, options) {
|
|
16804
|
+
const _path = this._getFinalPath(path21);
|
|
16805
16805
|
const query = new URLSearchParams();
|
|
16806
16806
|
if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
|
|
16807
16807
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
@@ -16940,10 +16940,10 @@ var init_dist3 = __esm({
|
|
|
16940
16940
|
* - `objects` table permissions: `select`
|
|
16941
16941
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16942
16942
|
*/
|
|
16943
|
-
async list(
|
|
16943
|
+
async list(path21, options, parameters) {
|
|
16944
16944
|
var _this13 = this;
|
|
16945
16945
|
return _this13.handleOperation(async () => {
|
|
16946
|
-
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix:
|
|
16946
|
+
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path21 || "" });
|
|
16947
16947
|
return await post(_this13.fetch, `${_this13.url}/object/list/${_this13.bucketId}`, body, { headers: _this13.headers }, parameters);
|
|
16948
16948
|
});
|
|
16949
16949
|
}
|
|
@@ -17008,11 +17008,11 @@ var init_dist3 = __esm({
|
|
|
17008
17008
|
if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
|
|
17009
17009
|
return btoa(data);
|
|
17010
17010
|
}
|
|
17011
|
-
_getFinalPath(
|
|
17012
|
-
return `${this.bucketId}/${
|
|
17011
|
+
_getFinalPath(path21) {
|
|
17012
|
+
return `${this.bucketId}/${path21.replace(/^\/+/, "")}`;
|
|
17013
17013
|
}
|
|
17014
|
-
_removeEmptyFolders(
|
|
17015
|
-
return
|
|
17014
|
+
_removeEmptyFolders(path21) {
|
|
17015
|
+
return path21.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
|
|
17016
17016
|
}
|
|
17017
17017
|
/** Modifies the `query`, appending values the from `transform` */
|
|
17018
17018
|
applyTransformOptsToQuery(query, transform) {
|
|
@@ -26390,11 +26390,11 @@ __export(dist_exports, {
|
|
|
26390
26390
|
});
|
|
26391
26391
|
function __awaiter2(thisArg, _arguments, P, generator) {
|
|
26392
26392
|
function adopt(value) {
|
|
26393
|
-
return value instanceof P ? value : new P(function(
|
|
26394
|
-
|
|
26393
|
+
return value instanceof P ? value : new P(function(resolve16) {
|
|
26394
|
+
resolve16(value);
|
|
26395
26395
|
});
|
|
26396
26396
|
}
|
|
26397
|
-
return new (P || (P = Promise))(function(
|
|
26397
|
+
return new (P || (P = Promise))(function(resolve16, reject) {
|
|
26398
26398
|
function fulfilled(value) {
|
|
26399
26399
|
try {
|
|
26400
26400
|
step(generator.next(value));
|
|
@@ -26410,7 +26410,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
|
|
|
26410
26410
|
}
|
|
26411
26411
|
}
|
|
26412
26412
|
function step(result) {
|
|
26413
|
-
result.done ?
|
|
26413
|
+
result.done ? resolve16(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
26414
26414
|
}
|
|
26415
26415
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
26416
26416
|
});
|
|
@@ -27145,8 +27145,8 @@ var init_watch_daemon = __esm({
|
|
|
27145
27145
|
);
|
|
27146
27146
|
}
|
|
27147
27147
|
this.startSafetyPoll(repoRoot, repoId, worktreeId);
|
|
27148
|
-
await new Promise((
|
|
27149
|
-
this.stopResolve =
|
|
27148
|
+
await new Promise((resolve16) => {
|
|
27149
|
+
this.stopResolve = resolve16;
|
|
27150
27150
|
});
|
|
27151
27151
|
}
|
|
27152
27152
|
/**
|
|
@@ -27417,7 +27417,7 @@ var init_watch_daemon = __esm({
|
|
|
27417
27417
|
}
|
|
27418
27418
|
/** Sleep for `ms` milliseconds — uses setTimeout so fake timers work in tests. */
|
|
27419
27419
|
sleep(ms) {
|
|
27420
|
-
return new Promise((
|
|
27420
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
27421
27421
|
}
|
|
27422
27422
|
};
|
|
27423
27423
|
}
|
|
@@ -27731,8 +27731,8 @@ var init_watch = __esm({
|
|
|
27731
27731
|
});
|
|
27732
27732
|
|
|
27733
27733
|
// src/lib/state-client.ts
|
|
27734
|
-
async function backendRequest(method,
|
|
27735
|
-
const url = `${getBackendBase()}${
|
|
27734
|
+
async function backendRequest(method, path21, body) {
|
|
27735
|
+
const url = `${getBackendBase()}${path21}`;
|
|
27736
27736
|
const auth = await getAuthHeaders();
|
|
27737
27737
|
const res = await fetch(url, {
|
|
27738
27738
|
method,
|
|
@@ -27744,7 +27744,7 @@ async function backendRequest(method, path16, body) {
|
|
|
27744
27744
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
27745
27745
|
});
|
|
27746
27746
|
if (!res.ok) {
|
|
27747
|
-
let message = `Backend ${method} ${
|
|
27747
|
+
let message = `Backend ${method} ${path21} failed with status ${res.status}`;
|
|
27748
27748
|
try {
|
|
27749
27749
|
const errBody = await res.json();
|
|
27750
27750
|
const msg = typeof errBody.message === "string" ? errBody.message : typeof errBody.error === "string" ? errBody.error : void 0;
|
|
@@ -27758,11 +27758,11 @@ async function backendRequest(method, path16, body) {
|
|
|
27758
27758
|
}
|
|
27759
27759
|
return res.json();
|
|
27760
27760
|
}
|
|
27761
|
-
async function apiBackendPost(
|
|
27762
|
-
return backendRequest("POST",
|
|
27761
|
+
async function apiBackendPost(path21, body) {
|
|
27762
|
+
return backendRequest("POST", path21, body);
|
|
27763
27763
|
}
|
|
27764
|
-
async function apiBackendPatch(
|
|
27765
|
-
return backendRequest("PATCH",
|
|
27764
|
+
async function apiBackendPatch(path21, body) {
|
|
27765
|
+
return backendRequest("PATCH", path21, body);
|
|
27766
27766
|
}
|
|
27767
27767
|
var REQUEST_TIMEOUT_MS2, BackendError;
|
|
27768
27768
|
var init_state_client = __esm({
|
|
@@ -28766,7 +28766,7 @@ function setRetryDelayMs(ms) {
|
|
|
28766
28766
|
RETRY_DELAY_MS = ms;
|
|
28767
28767
|
}
|
|
28768
28768
|
function sleep2(ms) {
|
|
28769
|
-
return new Promise((
|
|
28769
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
28770
28770
|
}
|
|
28771
28771
|
function isTransientMcpError(err) {
|
|
28772
28772
|
if (!(err instanceof McpError)) return false;
|
|
@@ -29610,7 +29610,7 @@ function generateMonotonicTimestamp(opts = {}) {
|
|
|
29610
29610
|
}
|
|
29611
29611
|
async function pollGhPreviewCheck(opts = {}) {
|
|
29612
29612
|
const run = opts.run ?? defaultRun;
|
|
29613
|
-
const sleep3 = opts.sleep ?? ((ms) => new Promise((
|
|
29613
|
+
const sleep3 = opts.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
29614
29614
|
const maxPolls = opts.maxPolls ?? 20;
|
|
29615
29615
|
const intervalMs = opts.intervalMs ?? 15e3;
|
|
29616
29616
|
if (!opts.prNumber) {
|
|
@@ -30956,6 +30956,1321 @@ var init_scaffold_publish_workflow2 = __esm({
|
|
|
30956
30956
|
}
|
|
30957
30957
|
});
|
|
30958
30958
|
|
|
30959
|
+
// src/lib/atomic-write.ts
|
|
30960
|
+
import * as fs7 from "node:fs";
|
|
30961
|
+
function writeJsonAtomic(filePath, value) {
|
|
30962
|
+
const tmpPath = filePath + ".tmp";
|
|
30963
|
+
try {
|
|
30964
|
+
fs7.writeFileSync(tmpPath, JSON.stringify(value, null, 2) + "\n", "utf-8");
|
|
30965
|
+
fs7.renameSync(tmpPath, filePath);
|
|
30966
|
+
} catch (err) {
|
|
30967
|
+
try {
|
|
30968
|
+
fs7.unlinkSync(tmpPath);
|
|
30969
|
+
} catch {
|
|
30970
|
+
}
|
|
30971
|
+
throw err;
|
|
30972
|
+
}
|
|
30973
|
+
}
|
|
30974
|
+
var init_atomic_write = __esm({
|
|
30975
|
+
"src/lib/atomic-write.ts"() {
|
|
30976
|
+
"use strict";
|
|
30977
|
+
}
|
|
30978
|
+
});
|
|
30979
|
+
|
|
30980
|
+
// src/lib/ci-init.ts
|
|
30981
|
+
import * as fs8 from "node:fs";
|
|
30982
|
+
import * as path8 from "node:path";
|
|
30983
|
+
function tryReadJson(filePath) {
|
|
30984
|
+
try {
|
|
30985
|
+
return JSON.parse(fs8.readFileSync(filePath, "utf-8"));
|
|
30986
|
+
} catch {
|
|
30987
|
+
return null;
|
|
30988
|
+
}
|
|
30989
|
+
}
|
|
30990
|
+
function hasDep(pkg, name) {
|
|
30991
|
+
if (!pkg) return false;
|
|
30992
|
+
const deps = pkg["dependencies"];
|
|
30993
|
+
const devDeps = pkg["devDependencies"];
|
|
30994
|
+
return Boolean(deps?.[name] ?? devDeps?.[name]);
|
|
30995
|
+
}
|
|
30996
|
+
function hasDevDep(pkg, name) {
|
|
30997
|
+
if (!pkg) return false;
|
|
30998
|
+
const devDeps = pkg["devDependencies"];
|
|
30999
|
+
return Boolean(devDeps?.[name]);
|
|
31000
|
+
}
|
|
31001
|
+
function detectPlatforms(projectDir) {
|
|
31002
|
+
const detected = /* @__PURE__ */ new Set();
|
|
31003
|
+
const dirsToScan = [projectDir];
|
|
31004
|
+
const appsDir = path8.join(projectDir, "apps");
|
|
31005
|
+
if (fs8.existsSync(appsDir)) {
|
|
31006
|
+
try {
|
|
31007
|
+
const appsEntries = fs8.readdirSync(appsDir, { withFileTypes: true });
|
|
31008
|
+
for (const entry of appsEntries) {
|
|
31009
|
+
if (entry.isDirectory()) {
|
|
31010
|
+
dirsToScan.push(path8.join(appsDir, entry.name));
|
|
31011
|
+
}
|
|
31012
|
+
}
|
|
31013
|
+
} catch {
|
|
31014
|
+
}
|
|
31015
|
+
}
|
|
31016
|
+
for (const dir of dirsToScan) {
|
|
31017
|
+
const pkg = tryReadJson(path8.join(dir, "package.json"));
|
|
31018
|
+
if (fs8.existsSync(path8.join(dir, "next.config.ts")) || fs8.existsSync(path8.join(dir, "next.config.js")) || fs8.existsSync(path8.join(dir, "next.config.mjs"))) {
|
|
31019
|
+
detected.add("next_js");
|
|
31020
|
+
}
|
|
31021
|
+
if (hasDep(pkg, "@nestjs/core")) {
|
|
31022
|
+
detected.add("nestjs");
|
|
31023
|
+
}
|
|
31024
|
+
if (fs8.existsSync(path8.join(dir, "tauri.conf.json")) || fs8.existsSync(path8.join(dir, "src-tauri"))) {
|
|
31025
|
+
detected.add("tauri");
|
|
31026
|
+
}
|
|
31027
|
+
if (hasDevDep(pkg, "@types/vscode")) {
|
|
31028
|
+
detected.add("vscode");
|
|
31029
|
+
}
|
|
31030
|
+
const deps = pkg?.["dependencies"];
|
|
31031
|
+
if (deps?.["expo"]) {
|
|
31032
|
+
detected.add("expo");
|
|
31033
|
+
}
|
|
31034
|
+
}
|
|
31035
|
+
const packagesDir = path8.join(projectDir, "packages");
|
|
31036
|
+
if (fs8.existsSync(packagesDir)) {
|
|
31037
|
+
try {
|
|
31038
|
+
const pkgEntries = fs8.readdirSync(packagesDir, { withFileTypes: true });
|
|
31039
|
+
if (pkgEntries.some((e) => e.isDirectory())) {
|
|
31040
|
+
detected.add("package");
|
|
31041
|
+
}
|
|
31042
|
+
} catch {
|
|
31043
|
+
}
|
|
31044
|
+
}
|
|
31045
|
+
if (detected.size === 0) {
|
|
31046
|
+
detected.add("package");
|
|
31047
|
+
}
|
|
31048
|
+
return Array.from(detected);
|
|
31049
|
+
}
|
|
31050
|
+
function buildDefaultCiConfig(platforms) {
|
|
31051
|
+
const config = {
|
|
31052
|
+
platforms: {},
|
|
31053
|
+
delegation: {
|
|
31054
|
+
lint: ".codebyplan/eslint.json",
|
|
31055
|
+
e2e: ".codebyplan/e2e.json",
|
|
31056
|
+
detection: ".claude/docs/architecture/testing-matrix.md"
|
|
31057
|
+
},
|
|
31058
|
+
workflow: {
|
|
31059
|
+
required_check_enforced: false
|
|
31060
|
+
}
|
|
31061
|
+
};
|
|
31062
|
+
for (const platform2 of platforms) {
|
|
31063
|
+
const checks = PLATFORM_COMMAND_MAP[platform2] ?? PLATFORM_COMMAND_MAP["package"];
|
|
31064
|
+
if (checks) {
|
|
31065
|
+
config.platforms[platform2] = { ...checks };
|
|
31066
|
+
}
|
|
31067
|
+
}
|
|
31068
|
+
return config;
|
|
31069
|
+
}
|
|
31070
|
+
async function runCiInit(opts) {
|
|
31071
|
+
await Promise.resolve();
|
|
31072
|
+
const projectDir = path8.resolve(opts?.projectDir ?? process.cwd());
|
|
31073
|
+
const dryRun = opts?.dryRun ?? false;
|
|
31074
|
+
const force = opts?.force ?? false;
|
|
31075
|
+
const ciPath = path8.join(projectDir, ".codebyplan", "ci.json");
|
|
31076
|
+
const platforms = detectPlatforms(projectDir);
|
|
31077
|
+
if (dryRun) {
|
|
31078
|
+
return { status: "dry_run", path: ciPath, platforms };
|
|
31079
|
+
}
|
|
31080
|
+
let existing = null;
|
|
31081
|
+
if (fs8.existsSync(ciPath)) {
|
|
31082
|
+
try {
|
|
31083
|
+
existing = JSON.parse(fs8.readFileSync(ciPath, "utf-8"));
|
|
31084
|
+
} catch {
|
|
31085
|
+
}
|
|
31086
|
+
}
|
|
31087
|
+
const newConfig = buildDefaultCiConfig(platforms);
|
|
31088
|
+
if (existing !== null && !force) {
|
|
31089
|
+
if (!existing.platforms) existing.platforms = {};
|
|
31090
|
+
const newPlatforms = platforms.filter((p) => !(p in existing.platforms));
|
|
31091
|
+
for (const p of newPlatforms) {
|
|
31092
|
+
const checks = newConfig.platforms[p];
|
|
31093
|
+
if (checks) {
|
|
31094
|
+
existing.platforms[p] = checks;
|
|
31095
|
+
}
|
|
31096
|
+
}
|
|
31097
|
+
let categoriesAdded = false;
|
|
31098
|
+
for (const p of platforms) {
|
|
31099
|
+
if (newPlatforms.includes(p)) continue;
|
|
31100
|
+
const existingChecks = existing.platforms[p];
|
|
31101
|
+
const defaultChecks = newConfig.platforms[p];
|
|
31102
|
+
if (!existingChecks || !defaultChecks) continue;
|
|
31103
|
+
for (const [cat, check] of Object.entries(defaultChecks)) {
|
|
31104
|
+
if (!(cat in existingChecks)) {
|
|
31105
|
+
existingChecks[cat] = check;
|
|
31106
|
+
categoriesAdded = true;
|
|
31107
|
+
}
|
|
31108
|
+
}
|
|
31109
|
+
}
|
|
31110
|
+
if (newPlatforms.length === 0 && !categoriesAdded) {
|
|
31111
|
+
return { status: "skipped", path: ciPath, platforms };
|
|
31112
|
+
}
|
|
31113
|
+
writeJsonAtomic(ciPath, existing);
|
|
31114
|
+
return {
|
|
31115
|
+
status: "written",
|
|
31116
|
+
path: ciPath,
|
|
31117
|
+
platforms: newPlatforms.length > 0 ? newPlatforms : platforms
|
|
31118
|
+
};
|
|
31119
|
+
}
|
|
31120
|
+
const codebyplanDir = path8.join(projectDir, ".codebyplan");
|
|
31121
|
+
fs8.mkdirSync(codebyplanDir, { recursive: true });
|
|
31122
|
+
writeJsonAtomic(ciPath, newConfig);
|
|
31123
|
+
return { status: "written", path: ciPath, platforms };
|
|
31124
|
+
}
|
|
31125
|
+
var PLATFORM_COMMAND_MAP;
|
|
31126
|
+
var init_ci_init = __esm({
|
|
31127
|
+
"src/lib/ci-init.ts"() {
|
|
31128
|
+
"use strict";
|
|
31129
|
+
init_atomic_write();
|
|
31130
|
+
PLATFORM_COMMAND_MAP = {
|
|
31131
|
+
next_js: {
|
|
31132
|
+
unit_test: {
|
|
31133
|
+
command: "pnpm turbo test",
|
|
31134
|
+
scope: "per_app_changed",
|
|
31135
|
+
hard_fail: true
|
|
31136
|
+
},
|
|
31137
|
+
typecheck: {
|
|
31138
|
+
command: "pnpm turbo typecheck",
|
|
31139
|
+
scope: "per_app_changed",
|
|
31140
|
+
hard_fail: true
|
|
31141
|
+
},
|
|
31142
|
+
build: {
|
|
31143
|
+
command: "pnpm turbo build",
|
|
31144
|
+
scope: "per_app_changed",
|
|
31145
|
+
hard_fail: true
|
|
31146
|
+
},
|
|
31147
|
+
lint: {
|
|
31148
|
+
scope: "per_app_changed",
|
|
31149
|
+
hard_fail: true,
|
|
31150
|
+
delegates_to: ".codebyplan/eslint.json"
|
|
31151
|
+
},
|
|
31152
|
+
e2e: {
|
|
31153
|
+
scope: "per_app_changed",
|
|
31154
|
+
hard_fail: false,
|
|
31155
|
+
delegates_to: ".codebyplan/e2e.json"
|
|
31156
|
+
},
|
|
31157
|
+
audit: {
|
|
31158
|
+
command: "pnpm audit --json",
|
|
31159
|
+
scope: "full_repo",
|
|
31160
|
+
hard_fail: true
|
|
31161
|
+
}
|
|
31162
|
+
},
|
|
31163
|
+
nestjs: {
|
|
31164
|
+
unit_test: {
|
|
31165
|
+
command: "pnpm turbo test",
|
|
31166
|
+
scope: "per_app_changed",
|
|
31167
|
+
hard_fail: true
|
|
31168
|
+
},
|
|
31169
|
+
typecheck: {
|
|
31170
|
+
command: "pnpm turbo typecheck",
|
|
31171
|
+
scope: "per_app_changed",
|
|
31172
|
+
hard_fail: true
|
|
31173
|
+
},
|
|
31174
|
+
build: {
|
|
31175
|
+
command: "pnpm turbo build",
|
|
31176
|
+
scope: "per_app_changed",
|
|
31177
|
+
hard_fail: true
|
|
31178
|
+
},
|
|
31179
|
+
lint: {
|
|
31180
|
+
scope: "per_app_changed",
|
|
31181
|
+
hard_fail: true,
|
|
31182
|
+
delegates_to: ".codebyplan/eslint.json"
|
|
31183
|
+
},
|
|
31184
|
+
e2e: {
|
|
31185
|
+
scope: "per_app_changed",
|
|
31186
|
+
hard_fail: false,
|
|
31187
|
+
delegates_to: ".codebyplan/e2e.json"
|
|
31188
|
+
},
|
|
31189
|
+
audit: {
|
|
31190
|
+
command: "pnpm audit --json",
|
|
31191
|
+
scope: "full_repo",
|
|
31192
|
+
hard_fail: true
|
|
31193
|
+
}
|
|
31194
|
+
},
|
|
31195
|
+
tauri: {
|
|
31196
|
+
unit_test: {
|
|
31197
|
+
command: "pnpm turbo test",
|
|
31198
|
+
scope: "per_app_changed",
|
|
31199
|
+
hard_fail: true
|
|
31200
|
+
},
|
|
31201
|
+
typecheck: {
|
|
31202
|
+
command: "pnpm turbo typecheck",
|
|
31203
|
+
scope: "per_app_changed",
|
|
31204
|
+
hard_fail: true
|
|
31205
|
+
},
|
|
31206
|
+
build: {
|
|
31207
|
+
command: "pnpm turbo build",
|
|
31208
|
+
scope: "per_app_changed",
|
|
31209
|
+
hard_fail: true
|
|
31210
|
+
},
|
|
31211
|
+
lint: {
|
|
31212
|
+
scope: "per_app_changed",
|
|
31213
|
+
hard_fail: true,
|
|
31214
|
+
delegates_to: ".codebyplan/eslint.json"
|
|
31215
|
+
},
|
|
31216
|
+
e2e: {
|
|
31217
|
+
scope: "per_app_changed",
|
|
31218
|
+
hard_fail: false,
|
|
31219
|
+
delegates_to: ".codebyplan/e2e.json"
|
|
31220
|
+
},
|
|
31221
|
+
audit: {
|
|
31222
|
+
command: "pnpm audit --json",
|
|
31223
|
+
scope: "full_repo",
|
|
31224
|
+
hard_fail: true
|
|
31225
|
+
}
|
|
31226
|
+
},
|
|
31227
|
+
vscode: {
|
|
31228
|
+
unit_test: {
|
|
31229
|
+
command: "pnpm turbo test",
|
|
31230
|
+
scope: "per_app_changed",
|
|
31231
|
+
hard_fail: true
|
|
31232
|
+
},
|
|
31233
|
+
typecheck: {
|
|
31234
|
+
command: "pnpm turbo typecheck",
|
|
31235
|
+
scope: "per_app_changed",
|
|
31236
|
+
hard_fail: true
|
|
31237
|
+
},
|
|
31238
|
+
build: {
|
|
31239
|
+
command: "pnpm turbo build",
|
|
31240
|
+
scope: "per_app_changed",
|
|
31241
|
+
hard_fail: true
|
|
31242
|
+
},
|
|
31243
|
+
lint: {
|
|
31244
|
+
scope: "per_app_changed",
|
|
31245
|
+
hard_fail: true,
|
|
31246
|
+
delegates_to: ".codebyplan/eslint.json"
|
|
31247
|
+
},
|
|
31248
|
+
e2e: {
|
|
31249
|
+
scope: "per_app_changed",
|
|
31250
|
+
hard_fail: false,
|
|
31251
|
+
delegates_to: ".codebyplan/e2e.json"
|
|
31252
|
+
},
|
|
31253
|
+
audit: {
|
|
31254
|
+
command: "pnpm audit --json",
|
|
31255
|
+
scope: "full_repo",
|
|
31256
|
+
hard_fail: true
|
|
31257
|
+
}
|
|
31258
|
+
},
|
|
31259
|
+
expo: {
|
|
31260
|
+
unit_test: {
|
|
31261
|
+
command: "pnpm turbo test",
|
|
31262
|
+
scope: "per_app_changed",
|
|
31263
|
+
hard_fail: true
|
|
31264
|
+
},
|
|
31265
|
+
typecheck: {
|
|
31266
|
+
command: "pnpm turbo typecheck",
|
|
31267
|
+
scope: "per_app_changed",
|
|
31268
|
+
hard_fail: true
|
|
31269
|
+
},
|
|
31270
|
+
build: {
|
|
31271
|
+
command: "pnpm turbo build",
|
|
31272
|
+
scope: "per_app_changed",
|
|
31273
|
+
hard_fail: true
|
|
31274
|
+
},
|
|
31275
|
+
lint: {
|
|
31276
|
+
scope: "per_app_changed",
|
|
31277
|
+
hard_fail: true,
|
|
31278
|
+
delegates_to: ".codebyplan/eslint.json"
|
|
31279
|
+
},
|
|
31280
|
+
e2e: {
|
|
31281
|
+
scope: "per_app_changed",
|
|
31282
|
+
hard_fail: false,
|
|
31283
|
+
delegates_to: ".codebyplan/e2e.json"
|
|
31284
|
+
},
|
|
31285
|
+
audit: {
|
|
31286
|
+
command: "pnpm audit --json",
|
|
31287
|
+
scope: "full_repo",
|
|
31288
|
+
hard_fail: true
|
|
31289
|
+
}
|
|
31290
|
+
},
|
|
31291
|
+
package: {
|
|
31292
|
+
unit_test: {
|
|
31293
|
+
command: "pnpm turbo test",
|
|
31294
|
+
scope: "per_app_changed",
|
|
31295
|
+
hard_fail: true
|
|
31296
|
+
},
|
|
31297
|
+
typecheck: {
|
|
31298
|
+
command: "pnpm turbo typecheck",
|
|
31299
|
+
scope: "per_app_changed",
|
|
31300
|
+
hard_fail: true
|
|
31301
|
+
},
|
|
31302
|
+
build: {
|
|
31303
|
+
command: "pnpm turbo build",
|
|
31304
|
+
scope: "per_app_changed",
|
|
31305
|
+
hard_fail: true
|
|
31306
|
+
},
|
|
31307
|
+
lint: {
|
|
31308
|
+
scope: "per_app_changed",
|
|
31309
|
+
hard_fail: true,
|
|
31310
|
+
delegates_to: ".codebyplan/eslint.json"
|
|
31311
|
+
},
|
|
31312
|
+
e2e: {
|
|
31313
|
+
scope: "per_app_changed",
|
|
31314
|
+
hard_fail: false,
|
|
31315
|
+
delegates_to: ".codebyplan/e2e.json"
|
|
31316
|
+
},
|
|
31317
|
+
audit: {
|
|
31318
|
+
command: "pnpm audit --json",
|
|
31319
|
+
scope: "full_repo",
|
|
31320
|
+
hard_fail: true
|
|
31321
|
+
}
|
|
31322
|
+
}
|
|
31323
|
+
};
|
|
31324
|
+
}
|
|
31325
|
+
});
|
|
31326
|
+
|
|
31327
|
+
// src/lib/scaffold-ci-workflow.ts
|
|
31328
|
+
import * as fs9 from "node:fs";
|
|
31329
|
+
import * as path9 from "node:path";
|
|
31330
|
+
function substituteTokens(template, tokens) {
|
|
31331
|
+
let result = template;
|
|
31332
|
+
for (const [token, value] of Object.entries(tokens)) {
|
|
31333
|
+
result = result.split(`{{${token}}}`).join(value);
|
|
31334
|
+
}
|
|
31335
|
+
return result;
|
|
31336
|
+
}
|
|
31337
|
+
function detectPnpmVersionFromPackageJson(projectDir) {
|
|
31338
|
+
try {
|
|
31339
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
31340
|
+
const raw = fs9.readFileSync(pkgPath, "utf-8");
|
|
31341
|
+
const pkg = JSON.parse(raw);
|
|
31342
|
+
const pm = pkg.packageManager;
|
|
31343
|
+
if (typeof pm === "string" && pm.startsWith("pnpm@")) {
|
|
31344
|
+
const version3 = pm.slice("pnpm@".length).split("+")[0];
|
|
31345
|
+
if (version3 && /^\d/.test(version3)) {
|
|
31346
|
+
return version3;
|
|
31347
|
+
}
|
|
31348
|
+
}
|
|
31349
|
+
return "10";
|
|
31350
|
+
} catch {
|
|
31351
|
+
return "10";
|
|
31352
|
+
}
|
|
31353
|
+
}
|
|
31354
|
+
async function runScaffoldCiWorkflow(opts) {
|
|
31355
|
+
await Promise.resolve();
|
|
31356
|
+
const dryRun = opts?.dryRun ?? false;
|
|
31357
|
+
const force = opts?.force ?? false;
|
|
31358
|
+
const projectDir = path9.resolve(opts?.projectDir ?? process.cwd());
|
|
31359
|
+
const pnpmVersion = opts?.pnpmVersion ?? detectPnpmVersionFromPackageJson(projectDir);
|
|
31360
|
+
const nodeVersion = opts?.nodeVersion ?? "22";
|
|
31361
|
+
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
31362
|
+
const templatePath = path9.join(templatesDir, "github-workflows", "ci.yml");
|
|
31363
|
+
if (!fs9.existsSync(templatePath)) {
|
|
31364
|
+
throw new Error(
|
|
31365
|
+
`scaffold-ci-workflow: template not found at ${templatePath}`
|
|
31366
|
+
);
|
|
31367
|
+
}
|
|
31368
|
+
const rawTemplate = fs9.readFileSync(templatePath, "utf-8");
|
|
31369
|
+
const renderedContent = substituteTokens(rawTemplate, {
|
|
31370
|
+
PNPM_VERSION: pnpmVersion,
|
|
31371
|
+
NODE_VERSION: nodeVersion
|
|
31372
|
+
});
|
|
31373
|
+
const targetPath = path9.join(projectDir, ".github", "workflows", "ci.yml");
|
|
31374
|
+
if (dryRun) {
|
|
31375
|
+
return { status: "dry_run", path: targetPath };
|
|
31376
|
+
}
|
|
31377
|
+
if (fs9.existsSync(targetPath)) {
|
|
31378
|
+
const existingContent = fs9.readFileSync(targetPath, "utf-8");
|
|
31379
|
+
if (existingContent === renderedContent) {
|
|
31380
|
+
return {
|
|
31381
|
+
status: "skipped",
|
|
31382
|
+
path: targetPath,
|
|
31383
|
+
reason: "already up to date"
|
|
31384
|
+
};
|
|
31385
|
+
}
|
|
31386
|
+
if (!force) {
|
|
31387
|
+
throw new Error(
|
|
31388
|
+
`scaffold-ci-workflow: ${targetPath} already exists and differs from the template. Pass --force to overwrite.`
|
|
31389
|
+
);
|
|
31390
|
+
}
|
|
31391
|
+
}
|
|
31392
|
+
const targetDir = path9.dirname(targetPath);
|
|
31393
|
+
fs9.mkdirSync(targetDir, { recursive: true });
|
|
31394
|
+
const tmpPath = targetPath + ".tmp";
|
|
31395
|
+
try {
|
|
31396
|
+
fs9.writeFileSync(tmpPath, renderedContent, "utf-8");
|
|
31397
|
+
fs9.renameSync(tmpPath, targetPath);
|
|
31398
|
+
} catch (err) {
|
|
31399
|
+
try {
|
|
31400
|
+
fs9.unlinkSync(tmpPath);
|
|
31401
|
+
} catch {
|
|
31402
|
+
}
|
|
31403
|
+
throw err;
|
|
31404
|
+
}
|
|
31405
|
+
return { status: "written", path: targetPath };
|
|
31406
|
+
}
|
|
31407
|
+
var init_scaffold_ci_workflow = __esm({
|
|
31408
|
+
"src/lib/scaffold-ci-workflow.ts"() {
|
|
31409
|
+
"use strict";
|
|
31410
|
+
init_install();
|
|
31411
|
+
}
|
|
31412
|
+
});
|
|
31413
|
+
|
|
31414
|
+
// src/lib/gh-required-checks.ts
|
|
31415
|
+
import * as fs10 from "node:fs";
|
|
31416
|
+
import * as path10 from "node:path";
|
|
31417
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
31418
|
+
function readCiJson(projectDir) {
|
|
31419
|
+
const ciPath = path10.join(projectDir, ".codebyplan", "ci.json");
|
|
31420
|
+
if (!fs10.existsSync(ciPath)) {
|
|
31421
|
+
return {
|
|
31422
|
+
platforms: {},
|
|
31423
|
+
delegation: {},
|
|
31424
|
+
workflow: { required_check_enforced: false }
|
|
31425
|
+
};
|
|
31426
|
+
}
|
|
31427
|
+
try {
|
|
31428
|
+
return JSON.parse(fs10.readFileSync(ciPath, "utf-8"));
|
|
31429
|
+
} catch {
|
|
31430
|
+
return {
|
|
31431
|
+
platforms: {},
|
|
31432
|
+
delegation: {},
|
|
31433
|
+
workflow: { required_check_enforced: false }
|
|
31434
|
+
};
|
|
31435
|
+
}
|
|
31436
|
+
}
|
|
31437
|
+
function writeCiJsonAtomic(projectDir, config) {
|
|
31438
|
+
const ciPath = path10.join(projectDir, ".codebyplan", "ci.json");
|
|
31439
|
+
writeJsonAtomic(ciPath, config);
|
|
31440
|
+
}
|
|
31441
|
+
function enforceRequiredCheck(opts) {
|
|
31442
|
+
const projectDir = path10.resolve(opts?.projectDir ?? process.cwd());
|
|
31443
|
+
const branch = opts?.branch ?? "main";
|
|
31444
|
+
const checkName = opts?.checkName ?? "Lint + typecheck + test + build";
|
|
31445
|
+
const dryRun = opts?.dryRun ?? false;
|
|
31446
|
+
const ciPath = path10.join(projectDir, ".codebyplan", "ci.json");
|
|
31447
|
+
const config = readCiJson(projectDir);
|
|
31448
|
+
if (config.workflow?.required_check_enforced === true) {
|
|
31449
|
+
return { status: "already_enforced", path: ciPath };
|
|
31450
|
+
}
|
|
31451
|
+
if (dryRun) {
|
|
31452
|
+
process.stdout.write(
|
|
31453
|
+
`
|
|
31454
|
+
[dry-run] Would add required status check "${checkName}" to branch "${branch}" protection and set workflow.required_check_enforced=true in ci.json.
|
|
31455
|
+
No GitHub API call or file write performed.
|
|
31456
|
+
|
|
31457
|
+
`
|
|
31458
|
+
);
|
|
31459
|
+
return { status: "dry_run", path: ciPath };
|
|
31460
|
+
}
|
|
31461
|
+
const manualInstructions = [
|
|
31462
|
+
"",
|
|
31463
|
+
` Manual GitHub branch protection setup for branch "${branch}":`,
|
|
31464
|
+
" 1. Go to: Settings \u2192 Branches \u2192 Branch protection rules",
|
|
31465
|
+
` 2. Add or edit a rule for "${branch}"`,
|
|
31466
|
+
' 3. Enable "Require status checks to pass before merging"',
|
|
31467
|
+
` 4. Search for and add the required check: "${checkName}"`,
|
|
31468
|
+
" 5. Save changes.",
|
|
31469
|
+
""
|
|
31470
|
+
].join("\n");
|
|
31471
|
+
try {
|
|
31472
|
+
let protectionExists = true;
|
|
31473
|
+
try {
|
|
31474
|
+
execSync6(`gh api repos/{owner}/{repo}/branches/${branch}/protection`, {
|
|
31475
|
+
encoding: "utf-8",
|
|
31476
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
31477
|
+
});
|
|
31478
|
+
} catch {
|
|
31479
|
+
protectionExists = false;
|
|
31480
|
+
}
|
|
31481
|
+
if (protectionExists) {
|
|
31482
|
+
execSync6(
|
|
31483
|
+
`gh api --method POST repos/{owner}/{repo}/branches/${branch}/protection/required_status_checks/contexts --input -`,
|
|
31484
|
+
{
|
|
31485
|
+
encoding: "utf-8",
|
|
31486
|
+
input: JSON.stringify([checkName]),
|
|
31487
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
31488
|
+
}
|
|
31489
|
+
);
|
|
31490
|
+
} else {
|
|
31491
|
+
const putBody = {
|
|
31492
|
+
required_status_checks: { strict: true, contexts: [checkName] },
|
|
31493
|
+
enforce_admins: false,
|
|
31494
|
+
required_pull_request_reviews: null,
|
|
31495
|
+
restrictions: null
|
|
31496
|
+
};
|
|
31497
|
+
execSync6(
|
|
31498
|
+
`gh api --method PUT repos/{owner}/{repo}/branches/${branch}/protection --input -`,
|
|
31499
|
+
{
|
|
31500
|
+
encoding: "utf-8",
|
|
31501
|
+
input: JSON.stringify(putBody),
|
|
31502
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
31503
|
+
}
|
|
31504
|
+
);
|
|
31505
|
+
}
|
|
31506
|
+
config.workflow = {
|
|
31507
|
+
...config.workflow,
|
|
31508
|
+
required_check_enforced: true,
|
|
31509
|
+
required_check_enforced_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
31510
|
+
};
|
|
31511
|
+
writeCiJsonAtomic(projectDir, config);
|
|
31512
|
+
return { status: "enforced", path: ciPath };
|
|
31513
|
+
} catch {
|
|
31514
|
+
console.error(
|
|
31515
|
+
"enforce-check: gh api command failed. Set up branch protection manually."
|
|
31516
|
+
);
|
|
31517
|
+
process.stdout.write(manualInstructions);
|
|
31518
|
+
return {
|
|
31519
|
+
status: "manual_required",
|
|
31520
|
+
path: ciPath,
|
|
31521
|
+
instructions: manualInstructions
|
|
31522
|
+
};
|
|
31523
|
+
}
|
|
31524
|
+
}
|
|
31525
|
+
var init_gh_required_checks = __esm({
|
|
31526
|
+
"src/lib/gh-required-checks.ts"() {
|
|
31527
|
+
"use strict";
|
|
31528
|
+
init_atomic_write();
|
|
31529
|
+
}
|
|
31530
|
+
});
|
|
31531
|
+
|
|
31532
|
+
// src/lib/ci-resolve.ts
|
|
31533
|
+
function toResult(category, platform2, check, fromFallback) {
|
|
31534
|
+
if (check.delegates_to !== void 0) {
|
|
31535
|
+
return {
|
|
31536
|
+
status: "delegates",
|
|
31537
|
+
category,
|
|
31538
|
+
platform: platform2,
|
|
31539
|
+
delegates_to: check.delegates_to,
|
|
31540
|
+
scope: check.scope,
|
|
31541
|
+
hard_fail: check.hard_fail,
|
|
31542
|
+
fallback_used: fromFallback
|
|
31543
|
+
};
|
|
31544
|
+
}
|
|
31545
|
+
if (check.command !== void 0) {
|
|
31546
|
+
return {
|
|
31547
|
+
status: fromFallback ? "fallback" : "resolved",
|
|
31548
|
+
category,
|
|
31549
|
+
platform: platform2,
|
|
31550
|
+
command: check.command,
|
|
31551
|
+
scope: check.scope,
|
|
31552
|
+
hard_fail: check.hard_fail,
|
|
31553
|
+
fallback_used: fromFallback
|
|
31554
|
+
};
|
|
31555
|
+
}
|
|
31556
|
+
return null;
|
|
31557
|
+
}
|
|
31558
|
+
function resolveCiCommand(opts) {
|
|
31559
|
+
const { category } = opts;
|
|
31560
|
+
const projectDir = opts.projectDir ?? process.cwd();
|
|
31561
|
+
const config = readCiJson(projectDir);
|
|
31562
|
+
const ciPlatforms = config.platforms ?? {};
|
|
31563
|
+
const ciKeys = Object.keys(ciPlatforms);
|
|
31564
|
+
const slug = opts.platform ?? ciKeys[0] ?? "package";
|
|
31565
|
+
const ciCheck = ciPlatforms[slug]?.[category];
|
|
31566
|
+
if (ciCheck !== void 0) {
|
|
31567
|
+
const result = toResult(category, slug, ciCheck, false);
|
|
31568
|
+
if (result !== null) return result;
|
|
31569
|
+
}
|
|
31570
|
+
const mapSlug = slug in PLATFORM_COMMAND_MAP ? slug : "package";
|
|
31571
|
+
const mapCheck = PLATFORM_COMMAND_MAP[mapSlug]?.[category];
|
|
31572
|
+
if (mapCheck !== void 0) {
|
|
31573
|
+
const result = toResult(category, mapSlug, mapCheck, true);
|
|
31574
|
+
if (result !== null) return result;
|
|
31575
|
+
}
|
|
31576
|
+
return {
|
|
31577
|
+
status: "not_found",
|
|
31578
|
+
category,
|
|
31579
|
+
platform: slug,
|
|
31580
|
+
fallback_used: ciCheck === void 0
|
|
31581
|
+
};
|
|
31582
|
+
}
|
|
31583
|
+
var init_ci_resolve = __esm({
|
|
31584
|
+
"src/lib/ci-resolve.ts"() {
|
|
31585
|
+
"use strict";
|
|
31586
|
+
init_gh_required_checks();
|
|
31587
|
+
init_ci_init();
|
|
31588
|
+
}
|
|
31589
|
+
});
|
|
31590
|
+
|
|
31591
|
+
// src/cli/ci.ts
|
|
31592
|
+
var ci_exports = {};
|
|
31593
|
+
__export(ci_exports, {
|
|
31594
|
+
runCiCommand: () => runCiCommand
|
|
31595
|
+
});
|
|
31596
|
+
function parseFlagsFromArgs2(args) {
|
|
31597
|
+
const flags = {};
|
|
31598
|
+
const booleans = /* @__PURE__ */ new Set();
|
|
31599
|
+
for (let i = 0; i < args.length; i++) {
|
|
31600
|
+
const arg = args[i];
|
|
31601
|
+
if (arg.startsWith("--")) {
|
|
31602
|
+
const key = arg.slice(2);
|
|
31603
|
+
const next = args[i + 1];
|
|
31604
|
+
if (next !== void 0 && !next.startsWith("--")) {
|
|
31605
|
+
flags[key] = next;
|
|
31606
|
+
i++;
|
|
31607
|
+
} else {
|
|
31608
|
+
booleans.add(key);
|
|
31609
|
+
}
|
|
31610
|
+
}
|
|
31611
|
+
}
|
|
31612
|
+
return { flags, booleans };
|
|
31613
|
+
}
|
|
31614
|
+
function printHelp3() {
|
|
31615
|
+
process.stdout.write(
|
|
31616
|
+
'\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'
|
|
31617
|
+
);
|
|
31618
|
+
}
|
|
31619
|
+
function printInitResult(result) {
|
|
31620
|
+
switch (result.status) {
|
|
31621
|
+
case "written":
|
|
31622
|
+
process.stdout.write(
|
|
31623
|
+
`Written: ${result.path} (platforms: ${result.platforms.join(", ")})
|
|
31624
|
+
`
|
|
31625
|
+
);
|
|
31626
|
+
break;
|
|
31627
|
+
case "skipped":
|
|
31628
|
+
process.stdout.write(
|
|
31629
|
+
`Skipped: ${result.path} (platforms already configured: ${result.platforms.join(", ")})
|
|
31630
|
+
`
|
|
31631
|
+
);
|
|
31632
|
+
break;
|
|
31633
|
+
case "dry_run":
|
|
31634
|
+
process.stdout.write(
|
|
31635
|
+
`[dry-run] Would write: ${result.path} (detected platforms: ${result.platforms.join(", ")})
|
|
31636
|
+
`
|
|
31637
|
+
);
|
|
31638
|
+
break;
|
|
31639
|
+
}
|
|
31640
|
+
}
|
|
31641
|
+
function printScaffoldResult(result) {
|
|
31642
|
+
switch (result.status) {
|
|
31643
|
+
case "written":
|
|
31644
|
+
process.stdout.write(`Written: ${result.path}
|
|
31645
|
+
`);
|
|
31646
|
+
break;
|
|
31647
|
+
case "skipped":
|
|
31648
|
+
process.stdout.write(`Skipped: ${result.path} (${result.reason})
|
|
31649
|
+
`);
|
|
31650
|
+
break;
|
|
31651
|
+
case "dry_run":
|
|
31652
|
+
process.stdout.write(`[dry-run] Would write: ${result.path}
|
|
31653
|
+
`);
|
|
31654
|
+
break;
|
|
31655
|
+
}
|
|
31656
|
+
}
|
|
31657
|
+
function printEnforceResult(result) {
|
|
31658
|
+
switch (result.status) {
|
|
31659
|
+
case "enforced":
|
|
31660
|
+
process.stdout.write(
|
|
31661
|
+
`Enforced required check. Branch protection updated: ${result.path}
|
|
31662
|
+
`
|
|
31663
|
+
);
|
|
31664
|
+
break;
|
|
31665
|
+
case "already_enforced":
|
|
31666
|
+
process.stdout.write(
|
|
31667
|
+
`Skipped: required check already enforced (${result.path})
|
|
31668
|
+
`
|
|
31669
|
+
);
|
|
31670
|
+
break;
|
|
31671
|
+
case "manual_required":
|
|
31672
|
+
process.stdout.write(
|
|
31673
|
+
`Manual setup required \u2014 see instructions above. (${result.path})
|
|
31674
|
+
`
|
|
31675
|
+
);
|
|
31676
|
+
break;
|
|
31677
|
+
case "dry_run":
|
|
31678
|
+
break;
|
|
31679
|
+
}
|
|
31680
|
+
}
|
|
31681
|
+
async function runCiCommand(args) {
|
|
31682
|
+
const subcommand = args[0];
|
|
31683
|
+
if (subcommand === "help" || subcommand === "--help" || subcommand === "-h" || subcommand === void 0) {
|
|
31684
|
+
printHelp3();
|
|
31685
|
+
process.exit(0);
|
|
31686
|
+
}
|
|
31687
|
+
const rest = args.slice(1);
|
|
31688
|
+
const { flags, booleans } = parseFlagsFromArgs2(rest);
|
|
31689
|
+
const dryRun = booleans.has("dry-run");
|
|
31690
|
+
const force = booleans.has("force");
|
|
31691
|
+
const jsonOutput = booleans.has("json");
|
|
31692
|
+
const projectDir = flags["project-dir"];
|
|
31693
|
+
if (subcommand === "init") {
|
|
31694
|
+
let result;
|
|
31695
|
+
try {
|
|
31696
|
+
result = await runCiInit({ dryRun, force, projectDir });
|
|
31697
|
+
} catch (err) {
|
|
31698
|
+
process.stderr.write(
|
|
31699
|
+
`ci init: ${err instanceof Error ? err.message : String(err)}
|
|
31700
|
+
`
|
|
31701
|
+
);
|
|
31702
|
+
process.exitCode = 1;
|
|
31703
|
+
return;
|
|
31704
|
+
}
|
|
31705
|
+
if (jsonOutput) {
|
|
31706
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
31707
|
+
return;
|
|
31708
|
+
}
|
|
31709
|
+
printInitResult(result);
|
|
31710
|
+
return;
|
|
31711
|
+
}
|
|
31712
|
+
if (subcommand === "scaffold-workflow") {
|
|
31713
|
+
const pnpmVersion = flags["pnpm-version"];
|
|
31714
|
+
const nodeVersion = flags["node-version"];
|
|
31715
|
+
let result;
|
|
31716
|
+
try {
|
|
31717
|
+
result = await runScaffoldCiWorkflow({
|
|
31718
|
+
dryRun,
|
|
31719
|
+
force,
|
|
31720
|
+
projectDir,
|
|
31721
|
+
pnpmVersion,
|
|
31722
|
+
nodeVersion
|
|
31723
|
+
});
|
|
31724
|
+
} catch (err) {
|
|
31725
|
+
process.stderr.write(
|
|
31726
|
+
`ci scaffold-workflow: ${err instanceof Error ? err.message : String(err)}
|
|
31727
|
+
`
|
|
31728
|
+
);
|
|
31729
|
+
process.exitCode = 1;
|
|
31730
|
+
return;
|
|
31731
|
+
}
|
|
31732
|
+
if (jsonOutput) {
|
|
31733
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
31734
|
+
return;
|
|
31735
|
+
}
|
|
31736
|
+
printScaffoldResult(result);
|
|
31737
|
+
return;
|
|
31738
|
+
}
|
|
31739
|
+
if (subcommand === "enforce-check") {
|
|
31740
|
+
const branch = flags["branch"];
|
|
31741
|
+
const checkName = flags["check-name"];
|
|
31742
|
+
let result;
|
|
31743
|
+
try {
|
|
31744
|
+
result = enforceRequiredCheck({ projectDir, branch, checkName, dryRun });
|
|
31745
|
+
} catch (err) {
|
|
31746
|
+
process.stderr.write(
|
|
31747
|
+
`ci enforce-check: ${err instanceof Error ? err.message : String(err)}
|
|
31748
|
+
`
|
|
31749
|
+
);
|
|
31750
|
+
process.exitCode = 1;
|
|
31751
|
+
return;
|
|
31752
|
+
}
|
|
31753
|
+
if (jsonOutput) {
|
|
31754
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
31755
|
+
return;
|
|
31756
|
+
}
|
|
31757
|
+
printEnforceResult(result);
|
|
31758
|
+
return;
|
|
31759
|
+
}
|
|
31760
|
+
if (subcommand === "resolve") {
|
|
31761
|
+
const validCategories = [
|
|
31762
|
+
"unit_test",
|
|
31763
|
+
"typecheck",
|
|
31764
|
+
"build",
|
|
31765
|
+
"lint",
|
|
31766
|
+
"e2e",
|
|
31767
|
+
"audit"
|
|
31768
|
+
];
|
|
31769
|
+
const categoryArg = rest[0];
|
|
31770
|
+
if (categoryArg === void 0 || categoryArg.startsWith("--") || !validCategories.includes(categoryArg)) {
|
|
31771
|
+
process.stderr.write(
|
|
31772
|
+
"ci resolve: category required (one of: unit_test, typecheck, build, lint, e2e, audit)\n"
|
|
31773
|
+
);
|
|
31774
|
+
process.exitCode = 1;
|
|
31775
|
+
return;
|
|
31776
|
+
}
|
|
31777
|
+
const category = categoryArg;
|
|
31778
|
+
const resolveRest = rest.slice(1);
|
|
31779
|
+
const { flags: resolveFlags, booleans: resolveBooleans } = parseFlagsFromArgs2(resolveRest);
|
|
31780
|
+
const platform2 = resolveFlags["platform"];
|
|
31781
|
+
const resolveProjectDir = resolveFlags["project-dir"] ?? projectDir;
|
|
31782
|
+
const resolveJsonOutput = resolveBooleans.has("json") || jsonOutput;
|
|
31783
|
+
let result;
|
|
31784
|
+
try {
|
|
31785
|
+
result = resolveCiCommand({
|
|
31786
|
+
category,
|
|
31787
|
+
platform: platform2,
|
|
31788
|
+
projectDir: resolveProjectDir
|
|
31789
|
+
});
|
|
31790
|
+
} catch (err) {
|
|
31791
|
+
process.stderr.write(
|
|
31792
|
+
`ci resolve: ${err instanceof Error ? err.message : String(err)}
|
|
31793
|
+
`
|
|
31794
|
+
);
|
|
31795
|
+
process.exitCode = 1;
|
|
31796
|
+
return;
|
|
31797
|
+
}
|
|
31798
|
+
if (resolveJsonOutput) {
|
|
31799
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
31800
|
+
return;
|
|
31801
|
+
}
|
|
31802
|
+
switch (result.status) {
|
|
31803
|
+
case "resolved":
|
|
31804
|
+
process.stdout.write(`${result.command}
|
|
31805
|
+
`);
|
|
31806
|
+
break;
|
|
31807
|
+
case "fallback":
|
|
31808
|
+
process.stderr.write(
|
|
31809
|
+
`ci resolve: no ci.json entry for ${result.platform}/${category}, using default
|
|
31810
|
+
`
|
|
31811
|
+
);
|
|
31812
|
+
process.stdout.write(`${result.command}
|
|
31813
|
+
`);
|
|
31814
|
+
break;
|
|
31815
|
+
case "delegates":
|
|
31816
|
+
process.stderr.write(
|
|
31817
|
+
`ci resolve: '${category}' delegates to ${result.delegates_to} \u2014 config path, not a runnable command
|
|
31818
|
+
`
|
|
31819
|
+
);
|
|
31820
|
+
process.stdout.write(`${result.delegates_to}
|
|
31821
|
+
`);
|
|
31822
|
+
break;
|
|
31823
|
+
case "not_found":
|
|
31824
|
+
process.stderr.write(
|
|
31825
|
+
`ci resolve: category '${category}' not found for platform '${result.platform}'
|
|
31826
|
+
`
|
|
31827
|
+
);
|
|
31828
|
+
process.exitCode = 1;
|
|
31829
|
+
break;
|
|
31830
|
+
}
|
|
31831
|
+
return;
|
|
31832
|
+
}
|
|
31833
|
+
process.stderr.write(
|
|
31834
|
+
`ci: unknown subcommand '${subcommand}'. Run 'codebyplan ci help' for usage.
|
|
31835
|
+
`
|
|
31836
|
+
);
|
|
31837
|
+
process.exitCode = 1;
|
|
31838
|
+
}
|
|
31839
|
+
var init_ci = __esm({
|
|
31840
|
+
"src/cli/ci.ts"() {
|
|
31841
|
+
"use strict";
|
|
31842
|
+
init_ci_init();
|
|
31843
|
+
init_scaffold_ci_workflow();
|
|
31844
|
+
init_gh_required_checks();
|
|
31845
|
+
init_ci_resolve();
|
|
31846
|
+
}
|
|
31847
|
+
});
|
|
31848
|
+
|
|
31849
|
+
// src/lib/cd-init.ts
|
|
31850
|
+
import * as fs11 from "node:fs";
|
|
31851
|
+
import * as path11 from "node:path";
|
|
31852
|
+
function detectSurfaces(projectDir) {
|
|
31853
|
+
const shipmentPath = path11.join(projectDir, ".codebyplan", "shipment.json");
|
|
31854
|
+
let shipment;
|
|
31855
|
+
try {
|
|
31856
|
+
shipment = JSON.parse(fs11.readFileSync(shipmentPath, "utf-8"));
|
|
31857
|
+
} catch {
|
|
31858
|
+
return [];
|
|
31859
|
+
}
|
|
31860
|
+
const outer = shipment["shipment"];
|
|
31861
|
+
const surfacesBlock = outer?.["surfaces"] ?? shipment["surfaces"];
|
|
31862
|
+
if (!surfacesBlock || typeof surfacesBlock !== "object") {
|
|
31863
|
+
return [];
|
|
31864
|
+
}
|
|
31865
|
+
return Object.keys(surfacesBlock);
|
|
31866
|
+
}
|
|
31867
|
+
function normaliseSurfaceKey(key) {
|
|
31868
|
+
const known = [
|
|
31869
|
+
"vercel",
|
|
31870
|
+
"eas",
|
|
31871
|
+
"npm",
|
|
31872
|
+
"tauri",
|
|
31873
|
+
"railway",
|
|
31874
|
+
"supabase",
|
|
31875
|
+
"vscode"
|
|
31876
|
+
];
|
|
31877
|
+
if (known.includes(key)) {
|
|
31878
|
+
return key;
|
|
31879
|
+
}
|
|
31880
|
+
for (const id of known) {
|
|
31881
|
+
if (key.startsWith(id + "-") || key.startsWith(id + "_")) {
|
|
31882
|
+
return id;
|
|
31883
|
+
}
|
|
31884
|
+
}
|
|
31885
|
+
return key;
|
|
31886
|
+
}
|
|
31887
|
+
function buildDefaultCdConfig(rawSurfaceKeys) {
|
|
31888
|
+
const config = {
|
|
31889
|
+
surfaces: {},
|
|
31890
|
+
workflow: {
|
|
31891
|
+
workflows_scaffolded: false
|
|
31892
|
+
}
|
|
31893
|
+
};
|
|
31894
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31895
|
+
for (const rawKey of rawSurfaceKeys) {
|
|
31896
|
+
const normalised = normaliseSurfaceKey(rawKey);
|
|
31897
|
+
if (seen.has(normalised)) continue;
|
|
31898
|
+
seen.add(normalised);
|
|
31899
|
+
const defaults = SURFACE_DEFAULTS[normalised] ?? DEFAULT_SURFACE;
|
|
31900
|
+
config.surfaces[normalised] = { ...defaults };
|
|
31901
|
+
}
|
|
31902
|
+
return config;
|
|
31903
|
+
}
|
|
31904
|
+
async function runCdInit(opts) {
|
|
31905
|
+
await Promise.resolve();
|
|
31906
|
+
const projectDir = path11.resolve(opts?.projectDir ?? process.cwd());
|
|
31907
|
+
const dryRun = opts?.dryRun ?? false;
|
|
31908
|
+
const force = opts?.force ?? false;
|
|
31909
|
+
const cdPath = path11.join(projectDir, ".codebyplan", "cd.json");
|
|
31910
|
+
const rawSurfaceKeys = detectSurfaces(projectDir);
|
|
31911
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31912
|
+
const surfaces = [];
|
|
31913
|
+
for (const rawKey of rawSurfaceKeys) {
|
|
31914
|
+
const normalised = normaliseSurfaceKey(rawKey);
|
|
31915
|
+
if (!seen.has(normalised)) {
|
|
31916
|
+
seen.add(normalised);
|
|
31917
|
+
surfaces.push(normalised);
|
|
31918
|
+
}
|
|
31919
|
+
}
|
|
31920
|
+
if (dryRun) {
|
|
31921
|
+
return { status: "dry_run", path: cdPath, surfaces };
|
|
31922
|
+
}
|
|
31923
|
+
let existing = null;
|
|
31924
|
+
if (fs11.existsSync(cdPath)) {
|
|
31925
|
+
try {
|
|
31926
|
+
existing = JSON.parse(fs11.readFileSync(cdPath, "utf-8"));
|
|
31927
|
+
} catch {
|
|
31928
|
+
}
|
|
31929
|
+
}
|
|
31930
|
+
const newConfig = buildDefaultCdConfig(rawSurfaceKeys);
|
|
31931
|
+
if (existing !== null && !force) {
|
|
31932
|
+
if (!existing.surfaces) existing.surfaces = {};
|
|
31933
|
+
const newSurfaces = surfaces.filter((s) => !(s in existing.surfaces));
|
|
31934
|
+
for (const s of newSurfaces) {
|
|
31935
|
+
const surfaceConfig = newConfig.surfaces[s];
|
|
31936
|
+
if (surfaceConfig) {
|
|
31937
|
+
existing.surfaces[s] = surfaceConfig;
|
|
31938
|
+
}
|
|
31939
|
+
}
|
|
31940
|
+
if (newSurfaces.length === 0) {
|
|
31941
|
+
return { status: "skipped", path: cdPath, surfaces };
|
|
31942
|
+
}
|
|
31943
|
+
writeJsonAtomic(cdPath, existing);
|
|
31944
|
+
return {
|
|
31945
|
+
status: "written",
|
|
31946
|
+
path: cdPath,
|
|
31947
|
+
surfaces: newSurfaces
|
|
31948
|
+
};
|
|
31949
|
+
}
|
|
31950
|
+
const codebyplanDir = path11.join(projectDir, ".codebyplan");
|
|
31951
|
+
fs11.mkdirSync(codebyplanDir, { recursive: true });
|
|
31952
|
+
writeJsonAtomic(cdPath, newConfig);
|
|
31953
|
+
return { status: "written", path: cdPath, surfaces };
|
|
31954
|
+
}
|
|
31955
|
+
var SURFACE_DEFAULTS, DEFAULT_SURFACE;
|
|
31956
|
+
var init_cd_init = __esm({
|
|
31957
|
+
"src/lib/cd-init.ts"() {
|
|
31958
|
+
"use strict";
|
|
31959
|
+
init_atomic_write();
|
|
31960
|
+
SURFACE_DEFAULTS = {
|
|
31961
|
+
npm: {
|
|
31962
|
+
trigger: "push-to-main",
|
|
31963
|
+
path_filter: "packages/**",
|
|
31964
|
+
approval_required: false,
|
|
31965
|
+
oidc_auth: true,
|
|
31966
|
+
version_gate: true,
|
|
31967
|
+
credentials: { env_var_names: [] }
|
|
31968
|
+
},
|
|
31969
|
+
tauri: {
|
|
31970
|
+
trigger: "push-to-main",
|
|
31971
|
+
path_filter: "apps/desktop/**",
|
|
31972
|
+
approval_required: false,
|
|
31973
|
+
oidc_auth: false,
|
|
31974
|
+
version_gate: true,
|
|
31975
|
+
credentials: {
|
|
31976
|
+
env_var_names: [
|
|
31977
|
+
"TAURI_SIGNING_PRIVATE_KEY",
|
|
31978
|
+
"TAURI_SIGNING_PRIVATE_KEY_PASSWORD",
|
|
31979
|
+
"APPLE_CERTIFICATE",
|
|
31980
|
+
"APPLE_CERTIFICATE_PASSWORD",
|
|
31981
|
+
"APPLE_SIGNING_IDENTITY",
|
|
31982
|
+
"APPLE_API_ISSUER",
|
|
31983
|
+
"APPLE_API_KEY",
|
|
31984
|
+
"APPLE_API_KEY_CONTENT",
|
|
31985
|
+
"WINDOWS_CERTIFICATE",
|
|
31986
|
+
"WINDOWS_CERTIFICATE_PASSWORD"
|
|
31987
|
+
]
|
|
31988
|
+
}
|
|
31989
|
+
},
|
|
31990
|
+
vercel: {
|
|
31991
|
+
trigger: "push-to-main",
|
|
31992
|
+
approval_required: false,
|
|
31993
|
+
oidc_auth: false,
|
|
31994
|
+
version_gate: false,
|
|
31995
|
+
credentials: { env_var_names: ["VERCEL_TOKEN"] }
|
|
31996
|
+
},
|
|
31997
|
+
eas: {
|
|
31998
|
+
trigger: "push-to-main",
|
|
31999
|
+
approval_required: false,
|
|
32000
|
+
oidc_auth: false,
|
|
32001
|
+
version_gate: true,
|
|
32002
|
+
credentials: { env_var_names: ["EXPO_TOKEN"] }
|
|
32003
|
+
},
|
|
32004
|
+
railway: {
|
|
32005
|
+
trigger: "push-to-main",
|
|
32006
|
+
approval_required: false,
|
|
32007
|
+
oidc_auth: false,
|
|
32008
|
+
version_gate: false,
|
|
32009
|
+
credentials: { env_var_names: ["RAILWAY_TOKEN"] }
|
|
32010
|
+
},
|
|
32011
|
+
supabase: {
|
|
32012
|
+
trigger: "push-to-main",
|
|
32013
|
+
approval_required: false,
|
|
32014
|
+
oidc_auth: false,
|
|
32015
|
+
version_gate: false,
|
|
32016
|
+
credentials: {
|
|
32017
|
+
env_var_names: ["SUPABASE_ACCESS_TOKEN", "SUPABASE_PROJECT_REF"]
|
|
32018
|
+
}
|
|
32019
|
+
},
|
|
32020
|
+
vscode: {
|
|
32021
|
+
trigger: "push-to-main",
|
|
32022
|
+
approval_required: false,
|
|
32023
|
+
oidc_auth: false,
|
|
32024
|
+
version_gate: true,
|
|
32025
|
+
credentials: { env_var_names: ["VSCE_PAT"] }
|
|
32026
|
+
}
|
|
32027
|
+
};
|
|
32028
|
+
DEFAULT_SURFACE = {
|
|
32029
|
+
trigger: "push-to-main",
|
|
32030
|
+
approval_required: false,
|
|
32031
|
+
oidc_auth: false,
|
|
32032
|
+
version_gate: false,
|
|
32033
|
+
credentials: { env_var_names: [] }
|
|
32034
|
+
};
|
|
32035
|
+
}
|
|
32036
|
+
});
|
|
32037
|
+
|
|
32038
|
+
// src/lib/scaffold-cd-workflow.ts
|
|
32039
|
+
import * as fs12 from "node:fs";
|
|
32040
|
+
import * as path12 from "node:path";
|
|
32041
|
+
async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
32042
|
+
await Promise.resolve();
|
|
32043
|
+
const dryRun = opts.dryRun ?? false;
|
|
32044
|
+
const force = opts.force ?? false;
|
|
32045
|
+
const projectDir = path12.resolve(opts.projectDir ?? process.cwd());
|
|
32046
|
+
const templatesDir = opts.templatesDir ?? resolveTemplatesDir();
|
|
32047
|
+
const templatePath = path12.join(
|
|
32048
|
+
templatesDir,
|
|
32049
|
+
"github-workflows",
|
|
32050
|
+
templateName
|
|
32051
|
+
);
|
|
32052
|
+
if (!fs12.existsSync(templatePath)) {
|
|
32053
|
+
throw new Error(
|
|
32054
|
+
`scaffold-cd-workflow: template not found at ${templatePath}`
|
|
32055
|
+
);
|
|
32056
|
+
}
|
|
32057
|
+
const templateContent = fs12.readFileSync(templatePath, "utf-8");
|
|
32058
|
+
const targetPath = path12.join(projectDir, ".github", "workflows", targetName);
|
|
32059
|
+
if (dryRun) {
|
|
32060
|
+
return { status: "dry_run", path: targetPath };
|
|
32061
|
+
}
|
|
32062
|
+
if (fs12.existsSync(targetPath)) {
|
|
32063
|
+
const existingContent = fs12.readFileSync(targetPath, "utf-8");
|
|
32064
|
+
if (existingContent === templateContent) {
|
|
32065
|
+
return {
|
|
32066
|
+
status: "skipped",
|
|
32067
|
+
path: targetPath,
|
|
32068
|
+
reason: "already up to date"
|
|
32069
|
+
};
|
|
32070
|
+
}
|
|
32071
|
+
if (!force) {
|
|
32072
|
+
throw new Error(
|
|
32073
|
+
`scaffold-cd-workflow: ${targetPath} already exists and differs from the template. Pass --force to overwrite.`
|
|
32074
|
+
);
|
|
32075
|
+
}
|
|
32076
|
+
}
|
|
32077
|
+
const targetDir = path12.dirname(targetPath);
|
|
32078
|
+
fs12.mkdirSync(targetDir, { recursive: true });
|
|
32079
|
+
const tmpPath = targetPath + ".tmp";
|
|
32080
|
+
try {
|
|
32081
|
+
fs12.writeFileSync(tmpPath, templateContent, "utf-8");
|
|
32082
|
+
fs12.renameSync(tmpPath, targetPath);
|
|
32083
|
+
} catch (err) {
|
|
32084
|
+
try {
|
|
32085
|
+
fs12.unlinkSync(tmpPath);
|
|
32086
|
+
} catch {
|
|
32087
|
+
}
|
|
32088
|
+
throw err;
|
|
32089
|
+
}
|
|
32090
|
+
return { status: "written", path: targetPath };
|
|
32091
|
+
}
|
|
32092
|
+
async function runScaffoldCdWorkflow(opts) {
|
|
32093
|
+
const workflows = opts?.workflows ?? ["publish", "release-desktop"];
|
|
32094
|
+
const results = [];
|
|
32095
|
+
const workflowMap = {
|
|
32096
|
+
publish: { template: "publish.yml", target: "publish.yml" },
|
|
32097
|
+
"release-desktop": {
|
|
32098
|
+
template: "release-desktop.yml",
|
|
32099
|
+
target: "release-desktop.yml"
|
|
32100
|
+
}
|
|
32101
|
+
};
|
|
32102
|
+
for (const wf of workflows) {
|
|
32103
|
+
const entry = workflowMap[wf];
|
|
32104
|
+
if (!entry) {
|
|
32105
|
+
throw new Error(
|
|
32106
|
+
`scaffold-cd-workflow: unknown workflow '${wf}'. Valid options: publish, release-desktop.`
|
|
32107
|
+
);
|
|
32108
|
+
}
|
|
32109
|
+
const result = await scaffoldOneWorkflow(
|
|
32110
|
+
entry.template,
|
|
32111
|
+
entry.target,
|
|
32112
|
+
opts ?? {}
|
|
32113
|
+
);
|
|
32114
|
+
results.push({ ...result, workflow: wf });
|
|
32115
|
+
}
|
|
32116
|
+
return { results };
|
|
32117
|
+
}
|
|
32118
|
+
var init_scaffold_cd_workflow = __esm({
|
|
32119
|
+
"src/lib/scaffold-cd-workflow.ts"() {
|
|
32120
|
+
"use strict";
|
|
32121
|
+
init_templates_dir();
|
|
32122
|
+
}
|
|
32123
|
+
});
|
|
32124
|
+
|
|
32125
|
+
// src/cli/cd.ts
|
|
32126
|
+
var cd_exports = {};
|
|
32127
|
+
__export(cd_exports, {
|
|
32128
|
+
runCdCommand: () => runCdCommand
|
|
32129
|
+
});
|
|
32130
|
+
function parseFlagsFromArgs3(args) {
|
|
32131
|
+
const flags = {};
|
|
32132
|
+
const booleans = /* @__PURE__ */ new Set();
|
|
32133
|
+
const multi = {};
|
|
32134
|
+
for (let i = 0; i < args.length; i++) {
|
|
32135
|
+
const arg = args[i];
|
|
32136
|
+
if (arg.startsWith("--")) {
|
|
32137
|
+
const key = arg.slice(2);
|
|
32138
|
+
const next = args[i + 1];
|
|
32139
|
+
if (next !== void 0 && !next.startsWith("--")) {
|
|
32140
|
+
if (multi[key]) {
|
|
32141
|
+
multi[key].push(next);
|
|
32142
|
+
} else {
|
|
32143
|
+
multi[key] = [next];
|
|
32144
|
+
flags[key] = next;
|
|
32145
|
+
}
|
|
32146
|
+
i++;
|
|
32147
|
+
} else {
|
|
32148
|
+
booleans.add(key);
|
|
32149
|
+
}
|
|
32150
|
+
}
|
|
32151
|
+
}
|
|
32152
|
+
return { flags, booleans, multi };
|
|
32153
|
+
}
|
|
32154
|
+
function printHelp4() {
|
|
32155
|
+
process.stdout.write(
|
|
32156
|
+
"\n codebyplan cd\n\n CD configuration management \u2014 detect surfaces, scaffold workflow files.\n\n Subcommands:\n init Detect surfaces from .codebyplan/shipment.json and write/update .codebyplan/cd.json\n scaffold-workflow Write .github/workflows/publish.yml + release-desktop.yml from bundled templates\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 --workflow <name> Workflow to scaffold: publish | release-desktop\n May be specified multiple times. Defaults to both.\n\n"
|
|
32157
|
+
);
|
|
32158
|
+
}
|
|
32159
|
+
function printInitResult2(result) {
|
|
32160
|
+
switch (result.status) {
|
|
32161
|
+
case "written":
|
|
32162
|
+
process.stdout.write(
|
|
32163
|
+
`Written: ${result.path} (surfaces: ${result.surfaces.join(", ") || "(none)"})
|
|
32164
|
+
`
|
|
32165
|
+
);
|
|
32166
|
+
break;
|
|
32167
|
+
case "skipped":
|
|
32168
|
+
process.stdout.write(
|
|
32169
|
+
`Skipped: ${result.path} (surfaces already configured: ${result.surfaces.join(", ") || "(none)"})
|
|
32170
|
+
`
|
|
32171
|
+
);
|
|
32172
|
+
break;
|
|
32173
|
+
case "dry_run":
|
|
32174
|
+
process.stdout.write(
|
|
32175
|
+
`[dry-run] Would write: ${result.path} (detected surfaces: ${result.surfaces.join(", ") || "(none)"})
|
|
32176
|
+
`
|
|
32177
|
+
);
|
|
32178
|
+
break;
|
|
32179
|
+
}
|
|
32180
|
+
}
|
|
32181
|
+
function printScaffoldResult2(result) {
|
|
32182
|
+
for (const r of result.results) {
|
|
32183
|
+
switch (r.status) {
|
|
32184
|
+
case "written":
|
|
32185
|
+
process.stdout.write(`Written: ${r.path} (${r.workflow})
|
|
32186
|
+
`);
|
|
32187
|
+
break;
|
|
32188
|
+
case "skipped":
|
|
32189
|
+
process.stdout.write(
|
|
32190
|
+
`Skipped: ${r.path} (${r.workflow} \u2014 ${"reason" in r ? r.reason : "already up to date"})
|
|
32191
|
+
`
|
|
32192
|
+
);
|
|
32193
|
+
break;
|
|
32194
|
+
case "dry_run":
|
|
32195
|
+
process.stdout.write(
|
|
32196
|
+
`[dry-run] Would write: ${r.path} (${r.workflow})
|
|
32197
|
+
`
|
|
32198
|
+
);
|
|
32199
|
+
break;
|
|
32200
|
+
}
|
|
32201
|
+
}
|
|
32202
|
+
}
|
|
32203
|
+
async function runCdCommand(args) {
|
|
32204
|
+
const subcommand = args[0];
|
|
32205
|
+
if (subcommand === "help" || subcommand === "--help" || subcommand === "-h" || subcommand === void 0) {
|
|
32206
|
+
printHelp4();
|
|
32207
|
+
process.exit(0);
|
|
32208
|
+
}
|
|
32209
|
+
const rest = args.slice(1);
|
|
32210
|
+
const { flags, booleans, multi } = parseFlagsFromArgs3(rest);
|
|
32211
|
+
const dryRun = booleans.has("dry-run");
|
|
32212
|
+
const force = booleans.has("force");
|
|
32213
|
+
const jsonOutput = booleans.has("json");
|
|
32214
|
+
const projectDir = flags["project-dir"];
|
|
32215
|
+
if (subcommand === "init") {
|
|
32216
|
+
let result;
|
|
32217
|
+
try {
|
|
32218
|
+
result = await runCdInit({ dryRun, force, projectDir });
|
|
32219
|
+
} catch (err) {
|
|
32220
|
+
process.stderr.write(
|
|
32221
|
+
`cd init: ${err instanceof Error ? err.message : String(err)}
|
|
32222
|
+
`
|
|
32223
|
+
);
|
|
32224
|
+
process.exitCode = 1;
|
|
32225
|
+
return;
|
|
32226
|
+
}
|
|
32227
|
+
if (jsonOutput) {
|
|
32228
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
32229
|
+
return;
|
|
32230
|
+
}
|
|
32231
|
+
printInitResult2(result);
|
|
32232
|
+
return;
|
|
32233
|
+
}
|
|
32234
|
+
if (subcommand === "scaffold-workflow") {
|
|
32235
|
+
const workflowArgs = multi["workflow"] ?? [];
|
|
32236
|
+
const workflows = workflowArgs.length > 0 ? workflowArgs : void 0;
|
|
32237
|
+
let result;
|
|
32238
|
+
try {
|
|
32239
|
+
result = await runScaffoldCdWorkflow({
|
|
32240
|
+
dryRun,
|
|
32241
|
+
force,
|
|
32242
|
+
projectDir,
|
|
32243
|
+
workflows
|
|
32244
|
+
});
|
|
32245
|
+
} catch (err) {
|
|
32246
|
+
process.stderr.write(
|
|
32247
|
+
`cd scaffold-workflow: ${err instanceof Error ? err.message : String(err)}
|
|
32248
|
+
`
|
|
32249
|
+
);
|
|
32250
|
+
process.exitCode = 1;
|
|
32251
|
+
return;
|
|
32252
|
+
}
|
|
32253
|
+
if (jsonOutput) {
|
|
32254
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
32255
|
+
return;
|
|
32256
|
+
}
|
|
32257
|
+
printScaffoldResult2(result);
|
|
32258
|
+
return;
|
|
32259
|
+
}
|
|
32260
|
+
process.stderr.write(
|
|
32261
|
+
`cd: unknown subcommand '${subcommand}'. Run 'codebyplan cd help' for usage.
|
|
32262
|
+
`
|
|
32263
|
+
);
|
|
32264
|
+
process.exitCode = 1;
|
|
32265
|
+
}
|
|
32266
|
+
var init_cd = __esm({
|
|
32267
|
+
"src/cli/cd.ts"() {
|
|
32268
|
+
"use strict";
|
|
32269
|
+
init_cd_init();
|
|
32270
|
+
init_scaffold_cd_workflow();
|
|
32271
|
+
}
|
|
32272
|
+
});
|
|
32273
|
+
|
|
30959
32274
|
// src/cli/process-exit-signal.ts
|
|
30960
32275
|
var ProcessExitSignal;
|
|
30961
32276
|
var init_process_exit_signal = __esm({
|
|
@@ -31433,9 +32748,9 @@ __export(version_status_exports, {
|
|
|
31433
32748
|
resolveGuard: () => resolveGuard,
|
|
31434
32749
|
runVersionStatus: () => runVersionStatus
|
|
31435
32750
|
});
|
|
31436
|
-
import { execFileSync, execSync as
|
|
31437
|
-
import { existsSync as
|
|
31438
|
-
import { dirname as
|
|
32751
|
+
import { execFileSync, execSync as execSync7 } from "node:child_process";
|
|
32752
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
32753
|
+
import { dirname as dirname12, join as join30 } from "node:path";
|
|
31439
32754
|
function fetchLatestVersion() {
|
|
31440
32755
|
try {
|
|
31441
32756
|
return execFileSync("npm", ["view", "codebyplan", "version"], {
|
|
@@ -31448,7 +32763,7 @@ function fetchLatestVersion() {
|
|
|
31448
32763
|
}
|
|
31449
32764
|
function resolveGitRoot() {
|
|
31450
32765
|
try {
|
|
31451
|
-
return
|
|
32766
|
+
return execSync7("git rev-parse --show-toplevel", {
|
|
31452
32767
|
encoding: "utf-8"
|
|
31453
32768
|
}).trim();
|
|
31454
32769
|
} catch {
|
|
@@ -31459,11 +32774,11 @@ function detectPackageManager2(gitRoot) {
|
|
|
31459
32774
|
let dir = process.cwd();
|
|
31460
32775
|
const stopAt = gitRoot ?? null;
|
|
31461
32776
|
while (true) {
|
|
31462
|
-
if (
|
|
31463
|
-
if (
|
|
31464
|
-
if (
|
|
32777
|
+
if (existsSync10(join30(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
32778
|
+
if (existsSync10(join30(dir, "yarn.lock"))) return "yarn";
|
|
32779
|
+
if (existsSync10(join30(dir, "package-lock.json"))) return "npm";
|
|
31465
32780
|
if (stopAt !== null && dir === stopAt) break;
|
|
31466
|
-
const parent =
|
|
32781
|
+
const parent = dirname12(dir);
|
|
31467
32782
|
if (parent === dir) break;
|
|
31468
32783
|
dir = parent;
|
|
31469
32784
|
}
|
|
@@ -31481,15 +32796,15 @@ function buildInstallCommand2(pm) {
|
|
|
31481
32796
|
}
|
|
31482
32797
|
async function resolveGuard(gitRoot, currentBranch) {
|
|
31483
32798
|
if (gitRoot !== null) {
|
|
31484
|
-
const canonicalPkgPath =
|
|
32799
|
+
const canonicalPkgPath = join30(
|
|
31485
32800
|
gitRoot,
|
|
31486
32801
|
"packages",
|
|
31487
32802
|
"codebyplan-package",
|
|
31488
32803
|
"package.json"
|
|
31489
32804
|
);
|
|
31490
32805
|
try {
|
|
31491
|
-
if (
|
|
31492
|
-
const raw =
|
|
32806
|
+
if (existsSync10(canonicalPkgPath)) {
|
|
32807
|
+
const raw = readFileSync11(canonicalPkgPath, "utf-8");
|
|
31493
32808
|
const parsed = JSON.parse(raw);
|
|
31494
32809
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && parsed["name"] === "codebyplan") {
|
|
31495
32810
|
return { guarded: true, guardReason: "canonical_source" };
|
|
@@ -31505,12 +32820,12 @@ async function resolveGuard(gitRoot, currentBranch) {
|
|
|
31505
32820
|
let gitJsonPath;
|
|
31506
32821
|
if (found.path.endsWith("/repo.json")) {
|
|
31507
32822
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
31508
|
-
gitJsonPath =
|
|
32823
|
+
gitJsonPath = join30(dir, "git.json");
|
|
31509
32824
|
} else {
|
|
31510
32825
|
const legacyDir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
31511
|
-
gitJsonPath =
|
|
32826
|
+
gitJsonPath = join30(legacyDir, ".codebyplan", "git.json");
|
|
31512
32827
|
}
|
|
31513
|
-
const raw =
|
|
32828
|
+
const raw = readFileSync11(gitJsonPath, "utf-8");
|
|
31514
32829
|
const parsed = JSON.parse(raw);
|
|
31515
32830
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
31516
32831
|
const bc = parsed["branch_config"];
|
|
@@ -31593,8 +32908,8 @@ __export(upload_e2e_images_exports, {
|
|
|
31593
32908
|
runUploadE2eImagesCommand: () => runUploadE2eImagesCommand
|
|
31594
32909
|
});
|
|
31595
32910
|
import { readFile as readFile19 } from "node:fs/promises";
|
|
31596
|
-
import { join as
|
|
31597
|
-
import { execSync as
|
|
32911
|
+
import { join as join31, basename, resolve as resolve10 } from "node:path";
|
|
32912
|
+
import { execSync as execSync8 } from "node:child_process";
|
|
31598
32913
|
function baseUrl2() {
|
|
31599
32914
|
return (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
|
|
31600
32915
|
}
|
|
@@ -31628,7 +32943,7 @@ function parseArgs(args) {
|
|
|
31628
32943
|
async function readE2eConfig(projectPath) {
|
|
31629
32944
|
try {
|
|
31630
32945
|
const raw = await readFile19(
|
|
31631
|
-
|
|
32946
|
+
join31(projectPath, ".codebyplan", "e2e.json"),
|
|
31632
32947
|
"utf-8"
|
|
31633
32948
|
);
|
|
31634
32949
|
return JSON.parse(raw);
|
|
@@ -31643,7 +32958,7 @@ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, bas
|
|
|
31643
32958
|
}
|
|
31644
32959
|
let stdout7;
|
|
31645
32960
|
try {
|
|
31646
|
-
stdout7 =
|
|
32961
|
+
stdout7 = execSync8(
|
|
31647
32962
|
`git diff --name-status --diff-filter=AM "${baseBranch}...HEAD" -- "${pathspec}"`,
|
|
31648
32963
|
{ cwd: projectPath, encoding: "utf-8" }
|
|
31649
32964
|
);
|
|
@@ -31669,7 +32984,7 @@ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, bas
|
|
|
31669
32984
|
continue;
|
|
31670
32985
|
const isNew = status === "A";
|
|
31671
32986
|
results.push({
|
|
31672
|
-
absolutePath:
|
|
32987
|
+
absolutePath: join31(projectPath, filePath),
|
|
31673
32988
|
filename: basename(filePath),
|
|
31674
32989
|
framework: frameworkName,
|
|
31675
32990
|
is_new: isNew
|
|
@@ -31708,7 +33023,7 @@ async function runUploadE2eImagesCommand(args) {
|
|
|
31708
33023
|
process.exit(1);
|
|
31709
33024
|
}
|
|
31710
33025
|
const checkpointId = parsed.checkpointId;
|
|
31711
|
-
const projectPath =
|
|
33026
|
+
const projectPath = resolve10(process.cwd());
|
|
31712
33027
|
let repoId = parsed.repoId;
|
|
31713
33028
|
if (!repoId) {
|
|
31714
33029
|
const found = await findCodebyplanConfig(projectPath);
|
|
@@ -31844,8 +33159,8 @@ __export(arch_map_exports, {
|
|
|
31844
33159
|
updateFrontmatterFields: () => updateFrontmatterFields
|
|
31845
33160
|
});
|
|
31846
33161
|
import { readFile as readFile20, writeFile as writeFile16 } from "node:fs/promises";
|
|
31847
|
-
import { existsSync as
|
|
31848
|
-
import { join as
|
|
33162
|
+
import { existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
|
|
33163
|
+
import { join as join32 } from "node:path";
|
|
31849
33164
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
31850
33165
|
function normalizeModulePath(modulePath) {
|
|
31851
33166
|
return modulePath.replace(/\/+$/, "");
|
|
@@ -31870,7 +33185,7 @@ async function resolveCodebyplanDir(startDir) {
|
|
|
31870
33185
|
}
|
|
31871
33186
|
}
|
|
31872
33187
|
async function readArchitectureConfig(codebyplanDir) {
|
|
31873
|
-
const filePath =
|
|
33188
|
+
const filePath = join32(codebyplanDir, "architecture.json");
|
|
31874
33189
|
try {
|
|
31875
33190
|
const raw = await readFile20(filePath, "utf-8");
|
|
31876
33191
|
const parsed = JSON.parse(raw);
|
|
@@ -31883,7 +33198,7 @@ async function readArchitectureConfig(codebyplanDir) {
|
|
|
31883
33198
|
}
|
|
31884
33199
|
}
|
|
31885
33200
|
async function writeArchitectureConfig(codebyplanDir, config) {
|
|
31886
|
-
const filePath =
|
|
33201
|
+
const filePath = join32(codebyplanDir, "architecture.json");
|
|
31887
33202
|
await writeFile16(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
31888
33203
|
}
|
|
31889
33204
|
function resolveGitSha(modulePath, cwd) {
|
|
@@ -31902,7 +33217,7 @@ function resolveGitSha(modulePath, cwd) {
|
|
|
31902
33217
|
}
|
|
31903
33218
|
async function discoverModulePaths(projectRoot) {
|
|
31904
33219
|
const paths = [];
|
|
31905
|
-
const workspacePath =
|
|
33220
|
+
const workspacePath = join32(projectRoot, "pnpm-workspace.yaml");
|
|
31906
33221
|
let patterns = [];
|
|
31907
33222
|
try {
|
|
31908
33223
|
const raw = await readFile20(workspacePath, "utf-8");
|
|
@@ -31929,10 +33244,10 @@ async function discoverModulePaths(projectRoot) {
|
|
|
31929
33244
|
for (const pattern of patterns) {
|
|
31930
33245
|
if (pattern.endsWith("/*")) {
|
|
31931
33246
|
const dir = pattern.slice(0, -2);
|
|
31932
|
-
const absDir =
|
|
33247
|
+
const absDir = join32(projectRoot, dir);
|
|
31933
33248
|
try {
|
|
31934
|
-
if (
|
|
31935
|
-
const entries =
|
|
33249
|
+
if (existsSync11(absDir)) {
|
|
33250
|
+
const entries = readdirSync4(absDir, { withFileTypes: true });
|
|
31936
33251
|
for (const entry of entries) {
|
|
31937
33252
|
if (entry.isDirectory()) {
|
|
31938
33253
|
paths.push(`${dir}/${entry.name}`);
|
|
@@ -31942,17 +33257,17 @@ async function discoverModulePaths(projectRoot) {
|
|
|
31942
33257
|
} catch {
|
|
31943
33258
|
}
|
|
31944
33259
|
} else if (!pattern.includes("*")) {
|
|
31945
|
-
const absPath =
|
|
31946
|
-
if (
|
|
33260
|
+
const absPath = join32(projectRoot, pattern);
|
|
33261
|
+
if (existsSync11(absPath)) {
|
|
31947
33262
|
paths.push(pattern);
|
|
31948
33263
|
}
|
|
31949
33264
|
}
|
|
31950
33265
|
}
|
|
31951
33266
|
const crossCutting = ["supabase", ".github", "scripts"];
|
|
31952
33267
|
for (const dir of crossCutting) {
|
|
31953
|
-
const absPath =
|
|
33268
|
+
const absPath = join32(projectRoot, dir);
|
|
31954
33269
|
try {
|
|
31955
|
-
if (
|
|
33270
|
+
if (existsSync11(absPath)) {
|
|
31956
33271
|
paths.push(dir);
|
|
31957
33272
|
}
|
|
31958
33273
|
} catch {
|
|
@@ -32136,7 +33451,7 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
32136
33451
|
}
|
|
32137
33452
|
await writeArchitectureConfig(codebyplanDir, config);
|
|
32138
33453
|
const stampedEntry = existingIndex >= 0 ? config.modules[existingIndex] : config.modules[config.modules.length - 1];
|
|
32139
|
-
const mapAbsPath =
|
|
33454
|
+
const mapAbsPath = join32(repoRoot, stampedEntry.map_file);
|
|
32140
33455
|
let mapContent = null;
|
|
32141
33456
|
try {
|
|
32142
33457
|
mapContent = await readFile20(mapAbsPath, "utf-8");
|
|
@@ -32342,18 +33657,18 @@ var init_worktree_port_resolver = __esm({
|
|
|
32342
33657
|
|
|
32343
33658
|
// src/lib/migrate-local-config.ts
|
|
32344
33659
|
import { mkdir as mkdir9, readFile as readFile21, unlink as unlink5, writeFile as writeFile17 } from "node:fs/promises";
|
|
32345
|
-
import { join as
|
|
33660
|
+
import { join as join33 } from "node:path";
|
|
32346
33661
|
function legacySharedPath(projectPath) {
|
|
32347
|
-
return
|
|
33662
|
+
return join33(projectPath, ".codebyplan.json");
|
|
32348
33663
|
}
|
|
32349
33664
|
function legacyLocalPath(projectPath) {
|
|
32350
|
-
return
|
|
33665
|
+
return join33(projectPath, ".codebyplan.local.json");
|
|
32351
33666
|
}
|
|
32352
33667
|
function newDirPath(projectPath) {
|
|
32353
|
-
return
|
|
33668
|
+
return join33(projectPath, ".codebyplan");
|
|
32354
33669
|
}
|
|
32355
33670
|
function sentinelPath(projectPath) {
|
|
32356
|
-
return
|
|
33671
|
+
return join33(projectPath, ".codebyplan", "repo.json");
|
|
32357
33672
|
}
|
|
32358
33673
|
async function statSafe(p) {
|
|
32359
33674
|
const { stat: stat3 } = await import("node:fs/promises");
|
|
@@ -32447,7 +33762,7 @@ async function runLocalMigration(projectPath) {
|
|
|
32447
33762
|
if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
|
|
32448
33763
|
if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
|
|
32449
33764
|
await writeFile17(
|
|
32450
|
-
|
|
33765
|
+
join33(projectPath, ".codebyplan", "repo.json"),
|
|
32451
33766
|
JSON.stringify(repoJson, null, 2) + "\n",
|
|
32452
33767
|
"utf-8"
|
|
32453
33768
|
);
|
|
@@ -32460,7 +33775,7 @@ async function runLocalMigration(projectPath) {
|
|
|
32460
33775
|
if ("port_allocations" in cfg)
|
|
32461
33776
|
serverJson.port_allocations = cfg.port_allocations;
|
|
32462
33777
|
await writeFile17(
|
|
32463
|
-
|
|
33778
|
+
join33(projectPath, ".codebyplan", "server.json"),
|
|
32464
33779
|
JSON.stringify(serverJson, null, 2) + "\n",
|
|
32465
33780
|
"utf-8"
|
|
32466
33781
|
);
|
|
@@ -32469,7 +33784,7 @@ async function runLocalMigration(projectPath) {
|
|
|
32469
33784
|
if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
|
|
32470
33785
|
if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
|
|
32471
33786
|
await writeFile17(
|
|
32472
|
-
|
|
33787
|
+
join33(projectPath, ".codebyplan", "git.json"),
|
|
32473
33788
|
JSON.stringify(gitJson, null, 2) + "\n",
|
|
32474
33789
|
"utf-8"
|
|
32475
33790
|
);
|
|
@@ -32477,35 +33792,35 @@ async function runLocalMigration(projectPath) {
|
|
|
32477
33792
|
const shipmentJson = {};
|
|
32478
33793
|
if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
|
|
32479
33794
|
await writeFile17(
|
|
32480
|
-
|
|
33795
|
+
join33(projectPath, ".codebyplan", "shipment.json"),
|
|
32481
33796
|
JSON.stringify(shipmentJson, null, 2) + "\n",
|
|
32482
33797
|
"utf-8"
|
|
32483
33798
|
);
|
|
32484
33799
|
filesChanged.push(".codebyplan/shipment.json");
|
|
32485
33800
|
const vendorJson = {};
|
|
32486
33801
|
await writeFile17(
|
|
32487
|
-
|
|
33802
|
+
join33(projectPath, ".codebyplan", "vendor.json"),
|
|
32488
33803
|
JSON.stringify(vendorJson, null, 2) + "\n",
|
|
32489
33804
|
"utf-8"
|
|
32490
33805
|
);
|
|
32491
33806
|
filesChanged.push(".codebyplan/vendor.json");
|
|
32492
33807
|
const e2eJson = {};
|
|
32493
33808
|
await writeFile17(
|
|
32494
|
-
|
|
33809
|
+
join33(projectPath, ".codebyplan", "e2e.json"),
|
|
32495
33810
|
JSON.stringify(e2eJson, null, 2) + "\n",
|
|
32496
33811
|
"utf-8"
|
|
32497
33812
|
);
|
|
32498
33813
|
filesChanged.push(".codebyplan/e2e.json");
|
|
32499
33814
|
const eslintJson = {};
|
|
32500
33815
|
await writeFile17(
|
|
32501
|
-
|
|
33816
|
+
join33(projectPath, ".codebyplan", "eslint.json"),
|
|
32502
33817
|
JSON.stringify(eslintJson, null, 2) + "\n",
|
|
32503
33818
|
"utf-8"
|
|
32504
33819
|
);
|
|
32505
33820
|
filesChanged.push(".codebyplan/eslint.json");
|
|
32506
33821
|
if (!deviceWrittenByHelper) {
|
|
32507
33822
|
await writeFile17(
|
|
32508
|
-
|
|
33823
|
+
join33(projectPath, ".codebyplan", "device.local.json"),
|
|
32509
33824
|
JSON.stringify({ device_id: deviceId }, null, 2) + "\n",
|
|
32510
33825
|
"utf-8"
|
|
32511
33826
|
);
|
|
@@ -32517,7 +33832,7 @@ async function runLocalMigration(projectPath) {
|
|
|
32517
33832
|
"Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
|
|
32518
33833
|
);
|
|
32519
33834
|
}
|
|
32520
|
-
const gitignorePath =
|
|
33835
|
+
const gitignorePath = join33(projectPath, ".gitignore");
|
|
32521
33836
|
try {
|
|
32522
33837
|
const gitignoreContent = await readFile21(gitignorePath, "utf-8");
|
|
32523
33838
|
const legacyLine = ".codebyplan.local.json";
|
|
@@ -32581,7 +33896,7 @@ __export(config_exports, {
|
|
|
32581
33896
|
runConfigMigrate: () => runConfigMigrate
|
|
32582
33897
|
});
|
|
32583
33898
|
import { mkdir as mkdir10, readFile as readFile22, writeFile as writeFile18 } from "node:fs/promises";
|
|
32584
|
-
import { join as
|
|
33899
|
+
import { join as join34 } from "node:path";
|
|
32585
33900
|
async function runConfig() {
|
|
32586
33901
|
const flags = parseFlags(3);
|
|
32587
33902
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -32614,7 +33929,7 @@ async function runConfig() {
|
|
|
32614
33929
|
console.log("\n Config complete.\n");
|
|
32615
33930
|
}
|
|
32616
33931
|
async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
32617
|
-
const codebyplanDir =
|
|
33932
|
+
const codebyplanDir = join34(projectPath, ".codebyplan");
|
|
32618
33933
|
const {
|
|
32619
33934
|
resolvedWorktreeId,
|
|
32620
33935
|
portAllocations,
|
|
@@ -32707,7 +34022,7 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
32707
34022
|
];
|
|
32708
34023
|
let anyUpdated = false;
|
|
32709
34024
|
for (const { name, payload, createOnly } of files) {
|
|
32710
|
-
const filePath =
|
|
34025
|
+
const filePath = join34(codebyplanDir, name);
|
|
32711
34026
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
32712
34027
|
let currentJson = "";
|
|
32713
34028
|
try {
|
|
@@ -32727,7 +34042,7 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
32727
34042
|
async function readRepoConfig(projectPath) {
|
|
32728
34043
|
try {
|
|
32729
34044
|
const raw = await readFile22(
|
|
32730
|
-
|
|
34045
|
+
join34(projectPath, ".codebyplan", "repo.json"),
|
|
32731
34046
|
"utf-8"
|
|
32732
34047
|
);
|
|
32733
34048
|
return JSON.parse(raw);
|
|
@@ -32738,7 +34053,7 @@ async function readRepoConfig(projectPath) {
|
|
|
32738
34053
|
async function readServerConfig(projectPath) {
|
|
32739
34054
|
try {
|
|
32740
34055
|
const raw = await readFile22(
|
|
32741
|
-
|
|
34056
|
+
join34(projectPath, ".codebyplan", "server.json"),
|
|
32742
34057
|
"utf-8"
|
|
32743
34058
|
);
|
|
32744
34059
|
return JSON.parse(raw);
|
|
@@ -32749,7 +34064,7 @@ async function readServerConfig(projectPath) {
|
|
|
32749
34064
|
async function readGitConfig2(projectPath) {
|
|
32750
34065
|
try {
|
|
32751
34066
|
const raw = await readFile22(
|
|
32752
|
-
|
|
34067
|
+
join34(projectPath, ".codebyplan", "git.json"),
|
|
32753
34068
|
"utf-8"
|
|
32754
34069
|
);
|
|
32755
34070
|
return JSON.parse(raw);
|
|
@@ -32760,7 +34075,7 @@ async function readGitConfig2(projectPath) {
|
|
|
32760
34075
|
async function readShipmentConfig2(projectPath) {
|
|
32761
34076
|
try {
|
|
32762
34077
|
const raw = await readFile22(
|
|
32763
|
-
|
|
34078
|
+
join34(projectPath, ".codebyplan", "shipment.json"),
|
|
32764
34079
|
"utf-8"
|
|
32765
34080
|
);
|
|
32766
34081
|
return JSON.parse(raw);
|
|
@@ -32771,7 +34086,7 @@ async function readShipmentConfig2(projectPath) {
|
|
|
32771
34086
|
async function readVendorConfig(projectPath) {
|
|
32772
34087
|
try {
|
|
32773
34088
|
const raw = await readFile22(
|
|
32774
|
-
|
|
34089
|
+
join34(projectPath, ".codebyplan", "vendor.json"),
|
|
32775
34090
|
"utf-8"
|
|
32776
34091
|
);
|
|
32777
34092
|
return JSON.parse(raw);
|
|
@@ -32782,7 +34097,7 @@ async function readVendorConfig(projectPath) {
|
|
|
32782
34097
|
async function readE2eConfig2(projectPath) {
|
|
32783
34098
|
try {
|
|
32784
34099
|
const raw = await readFile22(
|
|
32785
|
-
|
|
34100
|
+
join34(projectPath, ".codebyplan", "e2e.json"),
|
|
32786
34101
|
"utf-8"
|
|
32787
34102
|
);
|
|
32788
34103
|
return JSON.parse(raw);
|
|
@@ -32793,7 +34108,7 @@ async function readE2eConfig2(projectPath) {
|
|
|
32793
34108
|
async function readServerLocalConfig(projectPath) {
|
|
32794
34109
|
try {
|
|
32795
34110
|
const raw = await readFile22(
|
|
32796
|
-
|
|
34111
|
+
join34(projectPath, ".codebyplan", "server.local.json"),
|
|
32797
34112
|
"utf-8"
|
|
32798
34113
|
);
|
|
32799
34114
|
return JSON.parse(raw);
|
|
@@ -32866,7 +34181,7 @@ var init_config = __esm({
|
|
|
32866
34181
|
|
|
32867
34182
|
// src/lib/server-detect.ts
|
|
32868
34183
|
import { readFile as readFile23, readdir as readdir5, access as access6 } from "node:fs/promises";
|
|
32869
|
-
import { join as
|
|
34184
|
+
import { join as join35 } from "node:path";
|
|
32870
34185
|
async function fileExists4(filePath) {
|
|
32871
34186
|
try {
|
|
32872
34187
|
await access6(filePath);
|
|
@@ -32877,21 +34192,21 @@ async function fileExists4(filePath) {
|
|
|
32877
34192
|
}
|
|
32878
34193
|
function detectPackageManager3(dir) {
|
|
32879
34194
|
return (async () => {
|
|
32880
|
-
if (await fileExists4(
|
|
32881
|
-
if (await fileExists4(
|
|
34195
|
+
if (await fileExists4(join35(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
34196
|
+
if (await fileExists4(join35(dir, "yarn.lock"))) return "yarn";
|
|
32882
34197
|
return "npm";
|
|
32883
34198
|
})();
|
|
32884
34199
|
}
|
|
32885
34200
|
function detectFramework(pkg) {
|
|
32886
34201
|
const deps = pkg.dependencies ?? {};
|
|
32887
34202
|
const devDeps = pkg.devDependencies ?? {};
|
|
32888
|
-
const
|
|
32889
|
-
if (
|
|
32890
|
-
if (
|
|
32891
|
-
if (
|
|
32892
|
-
if (
|
|
32893
|
-
if (
|
|
32894
|
-
if (
|
|
34203
|
+
const hasDep2 = (name) => name in deps || name in devDeps;
|
|
34204
|
+
if (hasDep2("next")) return "nextjs";
|
|
34205
|
+
if (hasDep2("@tauri-apps/api") || hasDep2("@tauri-apps/cli")) return "tauri";
|
|
34206
|
+
if (hasDep2("expo")) return "expo";
|
|
34207
|
+
if (hasDep2("vite")) return "vite";
|
|
34208
|
+
if (hasDep2("express")) return "express";
|
|
34209
|
+
if (hasDep2("@nestjs/core")) return "nestjs";
|
|
32895
34210
|
return "custom";
|
|
32896
34211
|
}
|
|
32897
34212
|
function detectPortFromScripts(pkg) {
|
|
@@ -32910,12 +34225,12 @@ function detectPortFromScripts(pkg) {
|
|
|
32910
34225
|
return null;
|
|
32911
34226
|
}
|
|
32912
34227
|
async function isMonorepo(dir) {
|
|
32913
|
-
return await fileExists4(
|
|
34228
|
+
return await fileExists4(join35(dir, "turbo.json")) || await fileExists4(join35(dir, "pnpm-workspace.yaml"));
|
|
32914
34229
|
}
|
|
32915
34230
|
async function detectServers(projectPath) {
|
|
32916
34231
|
let pkg;
|
|
32917
34232
|
try {
|
|
32918
|
-
const raw = await readFile23(
|
|
34233
|
+
const raw = await readFile23(join35(projectPath, "package.json"), "utf-8");
|
|
32919
34234
|
pkg = JSON.parse(raw);
|
|
32920
34235
|
} catch {
|
|
32921
34236
|
return {
|
|
@@ -32931,13 +34246,13 @@ async function detectServers(projectPath) {
|
|
|
32931
34246
|
const mono = await isMonorepo(projectPath);
|
|
32932
34247
|
const servers = [];
|
|
32933
34248
|
if (mono) {
|
|
32934
|
-
const appsDir =
|
|
34249
|
+
const appsDir = join35(projectPath, "apps");
|
|
32935
34250
|
try {
|
|
32936
34251
|
const entries = await readdir5(appsDir, { withFileTypes: true });
|
|
32937
34252
|
const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
32938
34253
|
for (const entry of sorted) {
|
|
32939
34254
|
if (!entry.isDirectory()) continue;
|
|
32940
|
-
const appPkgPath =
|
|
34255
|
+
const appPkgPath = join35(appsDir, entry.name, "package.json");
|
|
32941
34256
|
try {
|
|
32942
34257
|
const appRaw = await readFile23(appPkgPath, "utf-8");
|
|
32943
34258
|
const appPkg = JSON.parse(appRaw);
|
|
@@ -33103,7 +34418,7 @@ __export(ports_exports, {
|
|
|
33103
34418
|
runPorts: () => runPorts
|
|
33104
34419
|
});
|
|
33105
34420
|
import { mkdir as mkdir11, readFile as readFile25, writeFile as writeFile19 } from "node:fs/promises";
|
|
33106
|
-
import { join as
|
|
34421
|
+
import { join as join36 } from "node:path";
|
|
33107
34422
|
function printDetectionResult(result, projectPath) {
|
|
33108
34423
|
console.log(`
|
|
33109
34424
|
CodeByPlan Ports - List`);
|
|
@@ -33259,8 +34574,8 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
33259
34574
|
// and ServerLocalConfig.port_allocations is typed the same — honest end-to-end.
|
|
33260
34575
|
port_allocations: portAllocations
|
|
33261
34576
|
};
|
|
33262
|
-
const codebyplanDir =
|
|
33263
|
-
const filePath =
|
|
34577
|
+
const codebyplanDir = join36(projectPath, ".codebyplan");
|
|
34578
|
+
const filePath = join36(codebyplanDir, "server.local.json");
|
|
33264
34579
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
33265
34580
|
let currentJson = "";
|
|
33266
34581
|
try {
|
|
@@ -33282,8 +34597,8 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
33282
34597
|
);
|
|
33283
34598
|
}
|
|
33284
34599
|
async function provisionE2eEnv(projectPath, dryRun) {
|
|
33285
|
-
const relSource =
|
|
33286
|
-
const sourcePath =
|
|
34600
|
+
const relSource = join36("apps", "web", ".env.local");
|
|
34601
|
+
const sourcePath = join36(projectPath, relSource);
|
|
33287
34602
|
let sourceRaw;
|
|
33288
34603
|
try {
|
|
33289
34604
|
sourceRaw = await readFile25(sourcePath, "utf-8");
|
|
@@ -33315,8 +34630,8 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
33315
34630
|
);
|
|
33316
34631
|
return;
|
|
33317
34632
|
}
|
|
33318
|
-
const codebyplanDir =
|
|
33319
|
-
const filePath =
|
|
34633
|
+
const codebyplanDir = join36(projectPath, ".codebyplan");
|
|
34634
|
+
const filePath = join36(codebyplanDir, "e2e.env");
|
|
33320
34635
|
const newContent = lines.join("\n") + "\n";
|
|
33321
34636
|
let currentContent = "";
|
|
33322
34637
|
try {
|
|
@@ -33383,7 +34698,7 @@ __export(tech_stack_exports, {
|
|
|
33383
34698
|
runFullTechStack: () => runFullTechStack,
|
|
33384
34699
|
runTechStack: () => runTechStack
|
|
33385
34700
|
});
|
|
33386
|
-
import { existsSync as
|
|
34701
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
33387
34702
|
async function runTechStack() {
|
|
33388
34703
|
const flags = parseFlags(3);
|
|
33389
34704
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -33552,7 +34867,7 @@ async function runFullTechStack(dryRun) {
|
|
|
33552
34867
|
continue;
|
|
33553
34868
|
}
|
|
33554
34869
|
const localWorktrees = worktrees.filter(
|
|
33555
|
-
(wt) => wt.path ?
|
|
34870
|
+
(wt) => wt.path ? existsSync12(wt.path) : false
|
|
33556
34871
|
);
|
|
33557
34872
|
if (localWorktrees.length === 0) {
|
|
33558
34873
|
console.log(` skipping ${repo.name} \u2014 no local worktree on this device`);
|
|
@@ -33591,8 +34906,8 @@ var init_tech_stack = __esm({
|
|
|
33591
34906
|
});
|
|
33592
34907
|
|
|
33593
34908
|
// src/lib/check-baseline.ts
|
|
33594
|
-
import { readFileSync as
|
|
33595
|
-
import { join as
|
|
34909
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
34910
|
+
import { join as join37 } from "node:path";
|
|
33596
34911
|
function emptyBaseline() {
|
|
33597
34912
|
return {
|
|
33598
34913
|
lint: { known_failing: [] },
|
|
@@ -33602,9 +34917,9 @@ function emptyBaseline() {
|
|
|
33602
34917
|
};
|
|
33603
34918
|
}
|
|
33604
34919
|
function loadBaseline(projectRoot) {
|
|
33605
|
-
const filePath =
|
|
34920
|
+
const filePath = join37(projectRoot, BASELINE_FILENAME);
|
|
33606
34921
|
try {
|
|
33607
|
-
const raw =
|
|
34922
|
+
const raw = readFileSync12(filePath, "utf-8");
|
|
33608
34923
|
const parsed = JSON.parse(raw);
|
|
33609
34924
|
const defaults = emptyBaseline();
|
|
33610
34925
|
return {
|
|
@@ -33626,8 +34941,8 @@ function loadBaseline(projectRoot) {
|
|
|
33626
34941
|
}
|
|
33627
34942
|
}
|
|
33628
34943
|
function saveBaseline(projectRoot, baseline) {
|
|
33629
|
-
const filePath =
|
|
33630
|
-
|
|
34944
|
+
const filePath = join37(projectRoot, BASELINE_FILENAME);
|
|
34945
|
+
writeFileSync7(filePath, JSON.stringify(baseline, null, 2) + "\n", "utf-8");
|
|
33631
34946
|
}
|
|
33632
34947
|
function diffBaseline(check, currentFailingPackages, baseline) {
|
|
33633
34948
|
const knownFailing = new Set(baseline[check].known_failing);
|
|
@@ -33675,8 +34990,8 @@ var init_check_baseline = __esm({
|
|
|
33675
34990
|
});
|
|
33676
34991
|
|
|
33677
34992
|
// src/lib/check.ts
|
|
33678
|
-
import { readFileSync as
|
|
33679
|
-
import { join as
|
|
34993
|
+
import { readFileSync as readFileSync13, existsSync as existsSync13 } from "node:fs";
|
|
34994
|
+
import { join as join38 } from "node:path";
|
|
33680
34995
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
33681
34996
|
function hasSentinelValue(arrays) {
|
|
33682
34997
|
const SENTINELS = /* @__PURE__ */ new Set([
|
|
@@ -33707,7 +35022,7 @@ function parseSummaryPath(output) {
|
|
|
33707
35022
|
function parseFailingPackagesFromSummary(summaryPath) {
|
|
33708
35023
|
let raw;
|
|
33709
35024
|
try {
|
|
33710
|
-
raw =
|
|
35025
|
+
raw = readFileSync13(summaryPath, "utf-8");
|
|
33711
35026
|
} catch {
|
|
33712
35027
|
return [SUMMARY_UNREADABLE];
|
|
33713
35028
|
}
|
|
@@ -33739,9 +35054,9 @@ function parseFailingPackagesFromSummary(summaryPath) {
|
|
|
33739
35054
|
return Array.from(failing).sort();
|
|
33740
35055
|
}
|
|
33741
35056
|
function resolveTurboBin(projectRoot) {
|
|
33742
|
-
const localBin =
|
|
33743
|
-
if (
|
|
33744
|
-
const workspaceRootBin =
|
|
35057
|
+
const localBin = join38(projectRoot, "node_modules", ".bin", "turbo");
|
|
35058
|
+
if (existsSync13(localBin)) return localBin;
|
|
35059
|
+
const workspaceRootBin = join38(
|
|
33745
35060
|
projectRoot,
|
|
33746
35061
|
"..",
|
|
33747
35062
|
"..",
|
|
@@ -33749,7 +35064,7 @@ function resolveTurboBin(projectRoot) {
|
|
|
33749
35064
|
".bin",
|
|
33750
35065
|
"turbo"
|
|
33751
35066
|
);
|
|
33752
|
-
if (
|
|
35067
|
+
if (existsSync13(workspaceRootBin)) return workspaceRootBin;
|
|
33753
35068
|
return TURBO_NOT_FOUND_SENTINEL;
|
|
33754
35069
|
}
|
|
33755
35070
|
function runTurboWithSummary(task, projectRoot, spawnFn) {
|
|
@@ -34177,8 +35492,8 @@ var init_check2 = __esm({
|
|
|
34177
35492
|
});
|
|
34178
35493
|
|
|
34179
35494
|
// src/lib/claude-plan.ts
|
|
34180
|
-
import * as
|
|
34181
|
-
import * as
|
|
35495
|
+
import * as fs13 from "node:fs";
|
|
35496
|
+
import * as path13 from "node:path";
|
|
34182
35497
|
function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
34183
35498
|
const packaged = walkTemplates(templatesDir);
|
|
34184
35499
|
const packagedBySrc = new Map(packaged.map((f) => [f.src, f]));
|
|
@@ -34192,8 +35507,8 @@ function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
|
34192
35507
|
};
|
|
34193
35508
|
for (const pkg of packaged) {
|
|
34194
35509
|
const inManifest = manifestBySrc.get(pkg.src);
|
|
34195
|
-
const absDest =
|
|
34196
|
-
const absSrc =
|
|
35510
|
+
const absDest = path13.join(projectDir, ".claude", pkg.dest);
|
|
35511
|
+
const absSrc = path13.join(templatesDir, pkg.src);
|
|
34197
35512
|
if (!inManifest) {
|
|
34198
35513
|
plan.newOptIn.push({
|
|
34199
35514
|
packaged: { src: pkg.src, dest: pkg.dest, hash: pkg.hash },
|
|
@@ -34201,8 +35516,8 @@ function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
|
34201
35516
|
});
|
|
34202
35517
|
continue;
|
|
34203
35518
|
}
|
|
34204
|
-
const onDiskExists =
|
|
34205
|
-
const onDiskContent = onDiskExists ?
|
|
35519
|
+
const onDiskExists = fs13.existsSync(absDest);
|
|
35520
|
+
const onDiskContent = onDiskExists ? fs13.readFileSync(absDest) : Buffer.alloc(0);
|
|
34206
35521
|
const onDiskHash = onDiskExists ? sha256(onDiskContent) : null;
|
|
34207
35522
|
if (pkg.hash === inManifest.hash && onDiskHash === inManifest.hash) {
|
|
34208
35523
|
plan.unchanged.push(inManifest);
|
|
@@ -34241,9 +35556,9 @@ var status_exports = {};
|
|
|
34241
35556
|
__export(status_exports, {
|
|
34242
35557
|
runStatus: () => runStatus2
|
|
34243
35558
|
});
|
|
34244
|
-
import * as
|
|
34245
|
-
import * as
|
|
34246
|
-
import { execSync as
|
|
35559
|
+
import * as fs14 from "node:fs";
|
|
35560
|
+
import * as path14 from "node:path";
|
|
35561
|
+
import { execSync as execSync9 } from "node:child_process";
|
|
34247
35562
|
function makeFailSafe(checked_at) {
|
|
34248
35563
|
return {
|
|
34249
35564
|
installed: VERSION,
|
|
@@ -34264,7 +35579,7 @@ function makeFailSafe(checked_at) {
|
|
|
34264
35579
|
}
|
|
34265
35580
|
function resolveGitRoot2() {
|
|
34266
35581
|
try {
|
|
34267
|
-
return
|
|
35582
|
+
return execSync9("git rev-parse --show-toplevel", {
|
|
34268
35583
|
encoding: "utf-8"
|
|
34269
35584
|
}).trim();
|
|
34270
35585
|
} catch {
|
|
@@ -34347,26 +35662,26 @@ async function runStatus2(argv) {
|
|
|
34347
35662
|
const latest = fetchLatestVersion();
|
|
34348
35663
|
const newer = latest !== null && compareSemver(latest, installed) > 0;
|
|
34349
35664
|
let settings_drift = false;
|
|
34350
|
-
const settingsPath =
|
|
34351
|
-
const baseSettingsPath =
|
|
35665
|
+
const settingsPath = path14.join(projectDir, ".claude", "settings.json");
|
|
35666
|
+
const baseSettingsPath = path14.join(
|
|
34352
35667
|
templatesDir,
|
|
34353
35668
|
"settings.project.base.json"
|
|
34354
35669
|
);
|
|
34355
|
-
const hooksJsonPath =
|
|
34356
|
-
if (
|
|
35670
|
+
const hooksJsonPath = path14.join(templatesDir, "hooks", "hooks.json");
|
|
35671
|
+
if (fs14.existsSync(settingsPath)) {
|
|
34357
35672
|
try {
|
|
34358
|
-
const settingsRaw =
|
|
35673
|
+
const settingsRaw = fs14.readFileSync(settingsPath, "utf8");
|
|
34359
35674
|
const before = JSON.stringify(JSON.parse(settingsRaw));
|
|
34360
35675
|
const cloned = JSON.parse(settingsRaw);
|
|
34361
|
-
if (
|
|
35676
|
+
if (fs14.existsSync(baseSettingsPath)) {
|
|
34362
35677
|
const base = JSON.parse(
|
|
34363
|
-
|
|
35678
|
+
fs14.readFileSync(baseSettingsPath, "utf8")
|
|
34364
35679
|
);
|
|
34365
35680
|
mergeBaseSettingsIntoSettings(cloned, base);
|
|
34366
35681
|
}
|
|
34367
|
-
if (
|
|
35682
|
+
if (fs14.existsSync(hooksJsonPath)) {
|
|
34368
35683
|
const hooksJson = JSON.parse(
|
|
34369
|
-
|
|
35684
|
+
fs14.readFileSync(hooksJsonPath, "utf8")
|
|
34370
35685
|
);
|
|
34371
35686
|
mergeHooksIntoSettings(cloned, hooksJson);
|
|
34372
35687
|
}
|
|
@@ -34418,10 +35733,10 @@ function emitResult(result, writeCache, quiet, projectDir) {
|
|
|
34418
35733
|
const json = JSON.stringify(result, null, 2);
|
|
34419
35734
|
if (writeCache) {
|
|
34420
35735
|
try {
|
|
34421
|
-
const cacheDir =
|
|
34422
|
-
|
|
34423
|
-
|
|
34424
|
-
|
|
35736
|
+
const cacheDir = path14.join(projectDir, ".codebyplan");
|
|
35737
|
+
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
35738
|
+
fs14.writeFileSync(
|
|
35739
|
+
path14.join(cacheDir, "claude-status.local.json"),
|
|
34425
35740
|
json + "\n",
|
|
34426
35741
|
"utf8"
|
|
34427
35742
|
);
|
|
@@ -34464,11 +35779,11 @@ async function ask(q, opts) {
|
|
|
34464
35779
|
try {
|
|
34465
35780
|
while (true) {
|
|
34466
35781
|
const choices = q.choices.map((c) => `[${c.key}] ${c.label}`).join(" ");
|
|
34467
|
-
const answer = await new Promise((
|
|
35782
|
+
const answer = await new Promise((resolve16) => {
|
|
34468
35783
|
rl.question(`${q.message}
|
|
34469
35784
|
${choices}
|
|
34470
35785
|
> `, (input) => {
|
|
34471
|
-
|
|
35786
|
+
resolve16(input.trim().toLowerCase());
|
|
34472
35787
|
});
|
|
34473
35788
|
});
|
|
34474
35789
|
const match = q.choices.find(
|
|
@@ -34562,9 +35877,9 @@ var update_exports = {};
|
|
|
34562
35877
|
__export(update_exports, {
|
|
34563
35878
|
runUpdate: () => runUpdate
|
|
34564
35879
|
});
|
|
34565
|
-
import * as
|
|
35880
|
+
import * as fs15 from "node:fs";
|
|
34566
35881
|
import * as os3 from "node:os";
|
|
34567
|
-
import * as
|
|
35882
|
+
import * as path15 from "node:path";
|
|
34568
35883
|
async function runUpdate(opts, deps = {}) {
|
|
34569
35884
|
await Promise.resolve();
|
|
34570
35885
|
const scope = opts.scope ?? "project";
|
|
@@ -34600,10 +35915,10 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34600
35915
|
finalManifestEntries.push(e);
|
|
34601
35916
|
}
|
|
34602
35917
|
for (const { packaged, absSrc } of plan.overwriteSafe) {
|
|
34603
|
-
const absDest =
|
|
35918
|
+
const absDest = path15.join(projectDir, ".claude", packaged.dest);
|
|
34604
35919
|
if (!opts.dryRun) {
|
|
34605
|
-
|
|
34606
|
-
|
|
35920
|
+
fs15.mkdirSync(path15.dirname(absDest), { recursive: true });
|
|
35921
|
+
fs15.copyFileSync(absSrc, absDest);
|
|
34607
35922
|
if (opts.verbose) console.log(`updated ${packaged.dest}`);
|
|
34608
35923
|
} else if (opts.verbose) {
|
|
34609
35924
|
console.log(`[dry-run] would update ${packaged.dest}`);
|
|
@@ -34615,8 +35930,8 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34615
35930
|
absSrc,
|
|
34616
35931
|
onDiskContent
|
|
34617
35932
|
} of plan.overwriteHandEdited) {
|
|
34618
|
-
const absDest =
|
|
34619
|
-
const newContent =
|
|
35933
|
+
const absDest = path15.join(projectDir, ".claude", packaged.dest);
|
|
35934
|
+
const newContent = fs15.readFileSync(absSrc);
|
|
34620
35935
|
const showDiff = () => {
|
|
34621
35936
|
console.log(
|
|
34622
35937
|
renderDiff(
|
|
@@ -34628,8 +35943,8 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34628
35943
|
const answer = await promptOverwrite(packaged.dest, opts, showDiff);
|
|
34629
35944
|
if (answer === "overwrite") {
|
|
34630
35945
|
if (!opts.dryRun) {
|
|
34631
|
-
|
|
34632
|
-
|
|
35946
|
+
fs15.mkdirSync(path15.dirname(absDest), { recursive: true });
|
|
35947
|
+
fs15.copyFileSync(absSrc, absDest);
|
|
34633
35948
|
}
|
|
34634
35949
|
finalManifestEntries.push(packaged);
|
|
34635
35950
|
} else {
|
|
@@ -34644,10 +35959,10 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34644
35959
|
for (const { packaged, absSrc } of plan.newOptIn) {
|
|
34645
35960
|
const answer = await promptOptIn(packaged.dest, opts);
|
|
34646
35961
|
if (answer === "opt-in") {
|
|
34647
|
-
const absDest =
|
|
35962
|
+
const absDest = path15.join(projectDir, ".claude", packaged.dest);
|
|
34648
35963
|
if (!opts.dryRun) {
|
|
34649
|
-
|
|
34650
|
-
|
|
35964
|
+
fs15.mkdirSync(path15.dirname(absDest), { recursive: true });
|
|
35965
|
+
fs15.copyFileSync(absSrc, absDest);
|
|
34651
35966
|
}
|
|
34652
35967
|
finalManifestEntries.push(packaged);
|
|
34653
35968
|
if (opts.verbose) console.log(`installed new file ${packaged.dest}`);
|
|
@@ -34658,25 +35973,25 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34658
35973
|
for (const e of plan.removedFromPackage) {
|
|
34659
35974
|
const answer = await promptRemove(e.dest, opts);
|
|
34660
35975
|
if (answer === "remove") {
|
|
34661
|
-
const absDest =
|
|
34662
|
-
if (!opts.dryRun &&
|
|
34663
|
-
|
|
34664
|
-
const claudeDir =
|
|
34665
|
-
let cur =
|
|
34666
|
-
while (cur !== claudeDir && cur !==
|
|
34667
|
-
if (
|
|
35976
|
+
const absDest = path15.join(projectDir, ".claude", e.dest);
|
|
35977
|
+
if (!opts.dryRun && fs15.existsSync(absDest)) {
|
|
35978
|
+
fs15.rmSync(absDest);
|
|
35979
|
+
const claudeDir = path15.join(projectDir, ".claude");
|
|
35980
|
+
let cur = path15.dirname(absDest);
|
|
35981
|
+
while (cur !== claudeDir && cur !== path15.dirname(cur)) {
|
|
35982
|
+
if (path15.dirname(cur) === claudeDir) break;
|
|
34668
35983
|
try {
|
|
34669
|
-
|
|
35984
|
+
fs15.rmdirSync(cur);
|
|
34670
35985
|
if (opts.verbose)
|
|
34671
35986
|
console.log(
|
|
34672
|
-
`pruned empty dir ${
|
|
35987
|
+
`pruned empty dir ${path15.relative(claudeDir, cur)}`
|
|
34673
35988
|
);
|
|
34674
|
-
cur =
|
|
35989
|
+
cur = path15.dirname(cur);
|
|
34675
35990
|
} catch (err) {
|
|
34676
35991
|
const code = err.code;
|
|
34677
35992
|
if (code !== "ENOTEMPTY" && code !== "ENOENT") {
|
|
34678
35993
|
console.warn(
|
|
34679
|
-
`codebyplan claude: could not prune empty dir ${
|
|
35994
|
+
`codebyplan claude: could not prune empty dir ${path15.relative(claudeDir, cur)}: ${err.message}`
|
|
34680
35995
|
);
|
|
34681
35996
|
}
|
|
34682
35997
|
break;
|
|
@@ -34688,22 +36003,22 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34688
36003
|
if (opts.verbose) console.log(`kept (untracked) ${e.dest}`);
|
|
34689
36004
|
}
|
|
34690
36005
|
}
|
|
34691
|
-
const hooksJsonPath =
|
|
34692
|
-
const baseSettingsPath =
|
|
36006
|
+
const hooksJsonPath = path15.join(templatesDir, "hooks", "hooks.json");
|
|
36007
|
+
const baseSettingsPath = path15.join(
|
|
34693
36008
|
templatesDir,
|
|
34694
36009
|
"settings.project.base.json"
|
|
34695
36010
|
);
|
|
34696
|
-
const settingsPath =
|
|
34697
|
-
const existingSettings =
|
|
34698
|
-
if (
|
|
36011
|
+
const settingsPath = path15.join(projectDir, ".claude", "settings.json");
|
|
36012
|
+
const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
|
|
36013
|
+
if (fs15.existsSync(baseSettingsPath)) {
|
|
34699
36014
|
const base = JSON.parse(
|
|
34700
|
-
|
|
36015
|
+
fs15.readFileSync(baseSettingsPath, "utf8")
|
|
34701
36016
|
);
|
|
34702
36017
|
mergeBaseSettingsIntoSettings(existingSettings, base);
|
|
34703
36018
|
}
|
|
34704
|
-
if (
|
|
36019
|
+
if (fs15.existsSync(hooksJsonPath)) {
|
|
34705
36020
|
const hooksJson = JSON.parse(
|
|
34706
|
-
|
|
36021
|
+
fs15.readFileSync(hooksJsonPath, "utf8")
|
|
34707
36022
|
);
|
|
34708
36023
|
mergeHooksIntoSettings(existingSettings, hooksJson);
|
|
34709
36024
|
pruneMissingManagedHooks(
|
|
@@ -34715,8 +36030,8 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34715
36030
|
);
|
|
34716
36031
|
}
|
|
34717
36032
|
if (!opts.dryRun) {
|
|
34718
|
-
|
|
34719
|
-
|
|
36033
|
+
fs15.mkdirSync(path15.dirname(settingsPath), { recursive: true });
|
|
36034
|
+
fs15.writeFileSync(
|
|
34720
36035
|
settingsPath,
|
|
34721
36036
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
34722
36037
|
"utf8"
|
|
@@ -34728,7 +36043,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
34728
36043
|
);
|
|
34729
36044
|
if (opts.verbose && gitignoreAction !== "unchanged") {
|
|
34730
36045
|
console.log(
|
|
34731
|
-
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${
|
|
36046
|
+
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${path15.relative(projectDir, path15.join(projectDir, ".gitignore"))}`
|
|
34732
36047
|
);
|
|
34733
36048
|
}
|
|
34734
36049
|
if (!opts.dryRun) {
|
|
@@ -34768,9 +36083,9 @@ function runUpdateUser(opts, deps) {
|
|
|
34768
36083
|
return;
|
|
34769
36084
|
}
|
|
34770
36085
|
try {
|
|
34771
|
-
const userDir = deps.userDir ??
|
|
34772
|
-
const settingsPath =
|
|
34773
|
-
const userBaseSettingsPath =
|
|
36086
|
+
const userDir = deps.userDir ?? path15.join(os3.homedir(), ".claude");
|
|
36087
|
+
const settingsPath = path15.join(userDir, "settings.json");
|
|
36088
|
+
const userBaseSettingsPath = path15.join(
|
|
34774
36089
|
templatesDir,
|
|
34775
36090
|
"settings.user.base.json"
|
|
34776
36091
|
);
|
|
@@ -34782,7 +36097,7 @@ function runUpdateUser(opts, deps) {
|
|
|
34782
36097
|
process.exitCode = 1;
|
|
34783
36098
|
return;
|
|
34784
36099
|
}
|
|
34785
|
-
if (!
|
|
36100
|
+
if (!fs15.existsSync(userBaseSettingsPath)) {
|
|
34786
36101
|
console.error(
|
|
34787
36102
|
"codebyplan claude update: settings.user.base.json not found in templates."
|
|
34788
36103
|
);
|
|
@@ -34790,13 +36105,13 @@ function runUpdateUser(opts, deps) {
|
|
|
34790
36105
|
return;
|
|
34791
36106
|
}
|
|
34792
36107
|
const userBase = JSON.parse(
|
|
34793
|
-
|
|
36108
|
+
fs15.readFileSync(userBaseSettingsPath, "utf8")
|
|
34794
36109
|
);
|
|
34795
|
-
const existingSettings =
|
|
36110
|
+
const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
|
|
34796
36111
|
mergeBaseSettingsIntoSettings(existingSettings, userBase);
|
|
34797
36112
|
if (!opts.dryRun) {
|
|
34798
|
-
|
|
34799
|
-
|
|
36113
|
+
fs15.mkdirSync(userDir, { recursive: true });
|
|
36114
|
+
fs15.writeFileSync(
|
|
34800
36115
|
settingsPath,
|
|
34801
36116
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
34802
36117
|
"utf8"
|
|
@@ -34839,9 +36154,9 @@ var uninstall_exports = {};
|
|
|
34839
36154
|
__export(uninstall_exports, {
|
|
34840
36155
|
runUninstall: () => runUninstall
|
|
34841
36156
|
});
|
|
34842
|
-
import * as
|
|
36157
|
+
import * as fs16 from "node:fs";
|
|
34843
36158
|
import * as os4 from "node:os";
|
|
34844
|
-
import * as
|
|
36159
|
+
import * as path16 from "node:path";
|
|
34845
36160
|
async function runUninstall(opts, deps = {}) {
|
|
34846
36161
|
await Promise.resolve();
|
|
34847
36162
|
const scope = opts.scope ?? "project";
|
|
@@ -34870,15 +36185,15 @@ async function runUninstall(opts, deps = {}) {
|
|
|
34870
36185
|
let removed = 0;
|
|
34871
36186
|
let warnings = 0;
|
|
34872
36187
|
for (const entry of manifest.files) {
|
|
34873
|
-
const abs =
|
|
34874
|
-
if (!
|
|
36188
|
+
const abs = path16.join(projectDir, ".claude", entry.dest);
|
|
36189
|
+
if (!fs16.existsSync(abs)) {
|
|
34875
36190
|
console.warn(
|
|
34876
36191
|
`codebyplan claude uninstall: ${entry.dest} already absent (skipping).`
|
|
34877
36192
|
);
|
|
34878
36193
|
warnings += 1;
|
|
34879
36194
|
continue;
|
|
34880
36195
|
}
|
|
34881
|
-
const onDiskHash = sha256(
|
|
36196
|
+
const onDiskHash = sha256(fs16.readFileSync(abs));
|
|
34882
36197
|
if (onDiskHash !== entry.hash) {
|
|
34883
36198
|
console.warn(
|
|
34884
36199
|
`codebyplan claude uninstall: ${entry.dest} has been modified locally; removing anyway.`
|
|
@@ -34886,7 +36201,7 @@ async function runUninstall(opts, deps = {}) {
|
|
|
34886
36201
|
warnings += 1;
|
|
34887
36202
|
}
|
|
34888
36203
|
if (!opts.dryRun) {
|
|
34889
|
-
|
|
36204
|
+
fs16.rmSync(abs);
|
|
34890
36205
|
}
|
|
34891
36206
|
removed += 1;
|
|
34892
36207
|
if (opts.verbose) console.log(`removed ${entry.dest}`);
|
|
@@ -34894,15 +36209,15 @@ async function runUninstall(opts, deps = {}) {
|
|
|
34894
36209
|
if (!opts.dryRun) {
|
|
34895
36210
|
pruneEmptyManagedDirs(projectDir);
|
|
34896
36211
|
}
|
|
34897
|
-
const settingsPath =
|
|
34898
|
-
if (
|
|
36212
|
+
const settingsPath = path16.join(projectDir, ".claude", "settings.json");
|
|
36213
|
+
if (fs16.existsSync(settingsPath)) {
|
|
34899
36214
|
const settings = JSON.parse(
|
|
34900
|
-
|
|
36215
|
+
fs16.readFileSync(settingsPath, "utf8")
|
|
34901
36216
|
);
|
|
34902
|
-
const baseSettingsPath = templatesDir ?
|
|
34903
|
-
if (baseSettingsPath &&
|
|
36217
|
+
const baseSettingsPath = templatesDir ? path16.join(templatesDir, "settings.project.base.json") : null;
|
|
36218
|
+
if (baseSettingsPath && fs16.existsSync(baseSettingsPath)) {
|
|
34904
36219
|
const base = JSON.parse(
|
|
34905
|
-
|
|
36220
|
+
fs16.readFileSync(baseSettingsPath, "utf8")
|
|
34906
36221
|
);
|
|
34907
36222
|
stripBaseSettingsFromSettings(settings, base);
|
|
34908
36223
|
}
|
|
@@ -34910,9 +36225,9 @@ async function runUninstall(opts, deps = {}) {
|
|
|
34910
36225
|
if (!opts.dryRun) {
|
|
34911
36226
|
const isEmpty = Object.keys(settings).length === 0;
|
|
34912
36227
|
if (isEmpty) {
|
|
34913
|
-
|
|
36228
|
+
fs16.rmSync(settingsPath);
|
|
34914
36229
|
} else {
|
|
34915
|
-
|
|
36230
|
+
fs16.writeFileSync(
|
|
34916
36231
|
settingsPath,
|
|
34917
36232
|
JSON.stringify(settings, null, 2) + "\n",
|
|
34918
36233
|
"utf8"
|
|
@@ -34931,11 +36246,11 @@ async function runUninstall(opts, deps = {}) {
|
|
|
34931
36246
|
}
|
|
34932
36247
|
if (!opts.dryRun) {
|
|
34933
36248
|
const m = manifestPath(projectDir);
|
|
34934
|
-
if (
|
|
36249
|
+
if (fs16.existsSync(m)) fs16.rmSync(m);
|
|
34935
36250
|
const mid = midManifestPath(projectDir);
|
|
34936
|
-
if (
|
|
36251
|
+
if (fs16.existsSync(mid)) fs16.rmSync(mid);
|
|
34937
36252
|
const legacy = oldManifestPath(projectDir);
|
|
34938
|
-
if (
|
|
36253
|
+
if (fs16.existsSync(legacy)) fs16.rmSync(legacy);
|
|
34939
36254
|
}
|
|
34940
36255
|
console.log(
|
|
34941
36256
|
`codebyplan claude uninstall${opts.dryRun ? " (dry-run)" : ""}: removed ${removed} files${warnings > 0 ? ` (${warnings} warnings)` : ""}.`
|
|
@@ -34957,7 +36272,7 @@ function runUninstallUser(opts, deps) {
|
|
|
34957
36272
|
}
|
|
34958
36273
|
}
|
|
34959
36274
|
try {
|
|
34960
|
-
const userDir = deps.userDir ??
|
|
36275
|
+
const userDir = deps.userDir ?? path16.join(os4.homedir(), ".claude");
|
|
34961
36276
|
const existingManifest = readManifestForScope("user", userDir);
|
|
34962
36277
|
if (!existingManifest) {
|
|
34963
36278
|
console.error(
|
|
@@ -34966,24 +36281,24 @@ function runUninstallUser(opts, deps) {
|
|
|
34966
36281
|
process.exitCode = 1;
|
|
34967
36282
|
return;
|
|
34968
36283
|
}
|
|
34969
|
-
const settingsPath =
|
|
34970
|
-
if (
|
|
36284
|
+
const settingsPath = path16.join(userDir, "settings.json");
|
|
36285
|
+
if (fs16.existsSync(settingsPath)) {
|
|
34971
36286
|
const settings = JSON.parse(
|
|
34972
|
-
|
|
36287
|
+
fs16.readFileSync(settingsPath, "utf8")
|
|
34973
36288
|
);
|
|
34974
|
-
const userBaseSettingsPath = templatesDir != null ?
|
|
34975
|
-
if (userBaseSettingsPath &&
|
|
36289
|
+
const userBaseSettingsPath = templatesDir != null ? path16.join(templatesDir, "settings.user.base.json") : null;
|
|
36290
|
+
if (userBaseSettingsPath && fs16.existsSync(userBaseSettingsPath)) {
|
|
34976
36291
|
const userBase = JSON.parse(
|
|
34977
|
-
|
|
36292
|
+
fs16.readFileSync(userBaseSettingsPath, "utf8")
|
|
34978
36293
|
);
|
|
34979
36294
|
stripBaseSettingsFromSettings(settings, userBase);
|
|
34980
36295
|
}
|
|
34981
36296
|
if (!opts.dryRun) {
|
|
34982
36297
|
const isEmpty = Object.keys(settings).length === 0;
|
|
34983
36298
|
if (isEmpty) {
|
|
34984
|
-
|
|
36299
|
+
fs16.rmSync(settingsPath);
|
|
34985
36300
|
} else {
|
|
34986
|
-
|
|
36301
|
+
fs16.writeFileSync(
|
|
34987
36302
|
settingsPath,
|
|
34988
36303
|
JSON.stringify(settings, null, 2) + "\n",
|
|
34989
36304
|
"utf8"
|
|
@@ -34993,11 +36308,11 @@ function runUninstallUser(opts, deps) {
|
|
|
34993
36308
|
}
|
|
34994
36309
|
if (!opts.dryRun) {
|
|
34995
36310
|
const m = userManifestPath(userDir);
|
|
34996
|
-
if (
|
|
36311
|
+
if (fs16.existsSync(m)) fs16.rmSync(m);
|
|
34997
36312
|
const midUser = userMidManifestPath(userDir);
|
|
34998
|
-
if (
|
|
36313
|
+
if (fs16.existsSync(midUser)) fs16.rmSync(midUser);
|
|
34999
36314
|
const oldUser = userOldManifestPath(userDir);
|
|
35000
|
-
if (
|
|
36315
|
+
if (fs16.existsSync(oldUser)) fs16.rmSync(oldUser);
|
|
35001
36316
|
}
|
|
35002
36317
|
console.log(
|
|
35003
36318
|
`codebyplan claude uninstall --scope user${opts.dryRun ? " (dry-run)" : ""}: user base settings stripped.`
|
|
@@ -35012,23 +36327,23 @@ function runUninstallUser(opts, deps) {
|
|
|
35012
36327
|
function pruneEmptyManagedDirs(projectDir) {
|
|
35013
36328
|
const managedRoots = ["skills", "agents", "hooks", "rules"];
|
|
35014
36329
|
for (const root of managedRoots) {
|
|
35015
|
-
const abs =
|
|
35016
|
-
if (!
|
|
36330
|
+
const abs = path16.join(projectDir, ".claude", root);
|
|
36331
|
+
if (!fs16.existsSync(abs)) continue;
|
|
35017
36332
|
pruneLeafFirst(abs);
|
|
35018
36333
|
}
|
|
35019
36334
|
}
|
|
35020
36335
|
function pruneLeafFirst(dir) {
|
|
35021
|
-
if (!
|
|
35022
|
-
const stat3 =
|
|
36336
|
+
if (!fs16.existsSync(dir)) return;
|
|
36337
|
+
const stat3 = fs16.statSync(dir);
|
|
35023
36338
|
if (!stat3.isDirectory()) return;
|
|
35024
|
-
for (const entry of
|
|
36339
|
+
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
35025
36340
|
if (entry.isDirectory()) {
|
|
35026
|
-
pruneLeafFirst(
|
|
36341
|
+
pruneLeafFirst(path16.join(dir, entry.name));
|
|
35027
36342
|
}
|
|
35028
36343
|
}
|
|
35029
|
-
const remaining =
|
|
36344
|
+
const remaining = fs16.readdirSync(dir);
|
|
35030
36345
|
if (remaining.length === 0) {
|
|
35031
|
-
|
|
36346
|
+
fs16.rmdirSync(dir);
|
|
35032
36347
|
}
|
|
35033
36348
|
}
|
|
35034
36349
|
var init_uninstall = __esm({
|
|
@@ -35043,8 +36358,8 @@ var init_uninstall = __esm({
|
|
|
35043
36358
|
});
|
|
35044
36359
|
|
|
35045
36360
|
// src/lib/verify-parity.ts
|
|
35046
|
-
import * as
|
|
35047
|
-
import * as
|
|
36361
|
+
import * as fs17 from "node:fs";
|
|
36362
|
+
import * as path17 from "node:path";
|
|
35048
36363
|
function isValidScope(s) {
|
|
35049
36364
|
return s === "org-shared" || s === "project-shared" || REPO_ONLY_RE.test(s);
|
|
35050
36365
|
}
|
|
@@ -35061,47 +36376,47 @@ function checkSiblingParity(opts) {
|
|
|
35061
36376
|
expectedOneSided = DEFAULT_EXPECTED_ONE_SIDED,
|
|
35062
36377
|
ignoredSubtrees
|
|
35063
36378
|
} = opts;
|
|
35064
|
-
const defaultIgnored = [
|
|
36379
|
+
const defaultIgnored = [path17.join(claudeDir, "hooks", "__test-fixtures__")];
|
|
35065
36380
|
const ignored = ignoredSubtrees ?? defaultIgnored;
|
|
35066
36381
|
const violations = [];
|
|
35067
36382
|
const claudeSideRels = /* @__PURE__ */ new Set();
|
|
35068
36383
|
for (const scanDir of SCAN_DIRS) {
|
|
35069
|
-
const baseDir =
|
|
35070
|
-
if (!
|
|
36384
|
+
const baseDir = path17.join(claudeDir, scanDir);
|
|
36385
|
+
if (!fs17.existsSync(baseDir)) continue;
|
|
35071
36386
|
const entries = readdirRecursive(baseDir);
|
|
35072
36387
|
for (const entry of entries) {
|
|
35073
|
-
const absPath =
|
|
35074
|
-
if (!
|
|
36388
|
+
const absPath = path17.join(baseDir, entry);
|
|
36389
|
+
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
35075
36390
|
if (ignored.some(
|
|
35076
|
-
(ig) => absPath.startsWith(ig +
|
|
36391
|
+
(ig) => absPath.startsWith(ig + path17.sep) || absPath === ig
|
|
35077
36392
|
)) {
|
|
35078
36393
|
continue;
|
|
35079
36394
|
}
|
|
35080
|
-
const relPath =
|
|
36395
|
+
const relPath = path17.join(scanDir, entry).split(path17.sep).join("/");
|
|
35081
36396
|
claudeSideRels.add(relPath);
|
|
35082
|
-
const templatePath =
|
|
35083
|
-
if (!
|
|
36397
|
+
const templatePath = path17.join(templatesDir, relPath);
|
|
36398
|
+
if (!fs17.existsSync(templatePath)) {
|
|
35084
36399
|
if (!expectedOneSided.has(relPath) && !isScaffoldFile(entry)) {
|
|
35085
36400
|
violations.push({ type: "missing-twin", path: relPath });
|
|
35086
36401
|
}
|
|
35087
36402
|
continue;
|
|
35088
36403
|
}
|
|
35089
|
-
const srcBuf =
|
|
35090
|
-
const tplBuf =
|
|
36404
|
+
const srcBuf = fs17.readFileSync(absPath);
|
|
36405
|
+
const tplBuf = fs17.readFileSync(templatePath);
|
|
35091
36406
|
if (Buffer.compare(srcBuf, tplBuf) !== 0) {
|
|
35092
36407
|
violations.push({ type: "divergent", path: relPath });
|
|
35093
36408
|
}
|
|
35094
36409
|
}
|
|
35095
36410
|
}
|
|
35096
36411
|
for (const scanDir of SCAN_DIRS) {
|
|
35097
|
-
const tplBase =
|
|
35098
|
-
if (!
|
|
36412
|
+
const tplBase = path17.join(templatesDir, scanDir);
|
|
36413
|
+
if (!fs17.existsSync(tplBase)) continue;
|
|
35099
36414
|
const entries = readdirRecursive(tplBase);
|
|
35100
36415
|
for (const entry of entries) {
|
|
35101
|
-
const absPath =
|
|
35102
|
-
if (!
|
|
36416
|
+
const absPath = path17.join(tplBase, entry);
|
|
36417
|
+
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
35103
36418
|
if (isScaffoldFile(entry)) continue;
|
|
35104
|
-
const relPath =
|
|
36419
|
+
const relPath = path17.join(scanDir, entry).split(path17.sep).join("/");
|
|
35105
36420
|
if (!claudeSideRels.has(relPath) && !expectedOneSided.has(relPath)) {
|
|
35106
36421
|
violations.push({ type: "extra-twin", path: relPath });
|
|
35107
36422
|
}
|
|
@@ -35134,25 +36449,25 @@ function checkScopeMarkers(opts) {
|
|
|
35134
36449
|
allowlist = /* @__PURE__ */ new Set(),
|
|
35135
36450
|
templatesDir
|
|
35136
36451
|
} = opts;
|
|
35137
|
-
const twinDetectionActive = templatesDir != null &&
|
|
36452
|
+
const twinDetectionActive = templatesDir != null && fs17.existsSync(templatesDir);
|
|
35138
36453
|
const violations = [];
|
|
35139
36454
|
for (const scanDir of scanDirs) {
|
|
35140
|
-
const baseDir =
|
|
35141
|
-
if (!
|
|
36455
|
+
const baseDir = path17.join(claudeDir, scanDir);
|
|
36456
|
+
if (!fs17.existsSync(baseDir)) continue;
|
|
35142
36457
|
const entries = readdirRecursive(baseDir);
|
|
35143
36458
|
for (const entry of entries) {
|
|
35144
|
-
const absPath =
|
|
35145
|
-
if (!
|
|
36459
|
+
const absPath = path17.join(baseDir, entry);
|
|
36460
|
+
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
35146
36461
|
if (!isStructuralEntry(scanDir, entry)) continue;
|
|
35147
|
-
const ext =
|
|
36462
|
+
const ext = path17.extname(entry).toLowerCase();
|
|
35148
36463
|
const isMd = ext === ".md";
|
|
35149
36464
|
const isSh = ext === ".sh";
|
|
35150
36465
|
if (!isMd && !isSh) continue;
|
|
35151
|
-
const relPath =
|
|
36466
|
+
const relPath = path17.join(scanDir, entry).split(path17.sep).join("/");
|
|
35152
36467
|
if (allowlist.has(relPath)) continue;
|
|
35153
36468
|
let content;
|
|
35154
36469
|
try {
|
|
35155
|
-
content =
|
|
36470
|
+
content = fs17.readFileSync(absPath, "utf8");
|
|
35156
36471
|
} catch (err) {
|
|
35157
36472
|
violations.push({
|
|
35158
36473
|
type: "missing-scope",
|
|
@@ -35162,7 +36477,7 @@ function checkScopeMarkers(opts) {
|
|
|
35162
36477
|
continue;
|
|
35163
36478
|
}
|
|
35164
36479
|
const scopeValue = isMd ? extractFrontmatterScope(content) : extractShScope(content);
|
|
35165
|
-
const managed = twinDetectionActive &&
|
|
36480
|
+
const managed = twinDetectionActive && fs17.existsSync(path17.join(templatesDir, relPath));
|
|
35166
36481
|
if (managed) {
|
|
35167
36482
|
if (scopeValue === null) {
|
|
35168
36483
|
} else if (scopeValue === "org-shared") {
|
|
@@ -35198,7 +36513,7 @@ function runVerifyParity(opts) {
|
|
|
35198
36513
|
const allScopeItems = [];
|
|
35199
36514
|
const parityItems = [];
|
|
35200
36515
|
allScopeItems.push(...checkScopeMarkers({ claudeDir, templatesDir }));
|
|
35201
|
-
if (templatesDir != null &&
|
|
36516
|
+
if (templatesDir != null && fs17.existsSync(templatesDir)) {
|
|
35202
36517
|
parityItems.push(
|
|
35203
36518
|
...checkSiblingParity({ claudeDir, templatesDir, expectedOneSided })
|
|
35204
36519
|
);
|
|
@@ -35211,14 +36526,14 @@ function runVerifyParity(opts) {
|
|
|
35211
36526
|
return { violations, warnings };
|
|
35212
36527
|
}
|
|
35213
36528
|
function readdirRecursive(dir, rel = "", visited = /* @__PURE__ */ new Set()) {
|
|
35214
|
-
const realDir =
|
|
36529
|
+
const realDir = fs17.realpathSync(dir);
|
|
35215
36530
|
if (visited.has(realDir)) return [];
|
|
35216
36531
|
visited.add(realDir);
|
|
35217
36532
|
const results = [];
|
|
35218
|
-
for (const name of
|
|
35219
|
-
const full =
|
|
36533
|
+
for (const name of fs17.readdirSync(dir)) {
|
|
36534
|
+
const full = path17.join(dir, name);
|
|
35220
36535
|
const relName = rel ? `${rel}/${name}` : name;
|
|
35221
|
-
if (
|
|
36536
|
+
if (fs17.lstatSync(full).isDirectory()) {
|
|
35222
36537
|
results.push(...readdirRecursive(full, relName, visited));
|
|
35223
36538
|
} else {
|
|
35224
36539
|
results.push(relName);
|
|
@@ -35288,14 +36603,14 @@ var verify_parity_exports = {};
|
|
|
35288
36603
|
__export(verify_parity_exports, {
|
|
35289
36604
|
verifyParity: () => verifyParity
|
|
35290
36605
|
});
|
|
35291
|
-
import * as
|
|
35292
|
-
import * as
|
|
36606
|
+
import * as fs18 from "node:fs";
|
|
36607
|
+
import * as path18 from "node:path";
|
|
35293
36608
|
function verifyParity(args, deps = {}) {
|
|
35294
36609
|
const warnOnly = args.includes("--warn-only");
|
|
35295
36610
|
const jsonMode = args.includes("--json");
|
|
35296
36611
|
const projectDir = deps.cwd ?? process.cwd();
|
|
35297
|
-
const claudeDir =
|
|
35298
|
-
if (!
|
|
36612
|
+
const claudeDir = path18.join(projectDir, ".claude");
|
|
36613
|
+
if (!fs18.existsSync(claudeDir)) {
|
|
35299
36614
|
const msg = "codebyplan claude verify-parity: .claude/ not found in cwd \u2014 run from the project root.\n";
|
|
35300
36615
|
process.stderr.write(msg);
|
|
35301
36616
|
return 2;
|
|
@@ -35802,7 +37117,7 @@ __export(generate_exports, {
|
|
|
35802
37117
|
runGenerate: () => runGenerate
|
|
35803
37118
|
});
|
|
35804
37119
|
import { readFile as readFile26, mkdir as mkdir12, writeFile as writeFile20 } from "node:fs/promises";
|
|
35805
|
-
import { join as
|
|
37120
|
+
import { join as join45, resolve as resolve11 } from "node:path";
|
|
35806
37121
|
async function readJsonFile4(filePath) {
|
|
35807
37122
|
try {
|
|
35808
37123
|
const raw = await readFile26(filePath, "utf-8");
|
|
@@ -35813,7 +37128,7 @@ async function readJsonFile4(filePath) {
|
|
|
35813
37128
|
}
|
|
35814
37129
|
async function readPkgName(absPath) {
|
|
35815
37130
|
try {
|
|
35816
|
-
const raw = await readFile26(
|
|
37131
|
+
const raw = await readFile26(join45(absPath, "package.json"), "utf-8");
|
|
35817
37132
|
const pkg = JSON.parse(raw);
|
|
35818
37133
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
35819
37134
|
} catch {
|
|
@@ -35824,10 +37139,10 @@ async function runGenerate(opts) {
|
|
|
35824
37139
|
const projectDir = opts.projectDir ?? opts["project-dir"] ?? process.cwd();
|
|
35825
37140
|
const dryRun = opts.dryRun ?? opts["dryRun"] ?? false;
|
|
35826
37141
|
const check = opts.check ?? opts["check"] ?? false;
|
|
35827
|
-
const rootDir =
|
|
37142
|
+
const rootDir = resolve11(projectDir);
|
|
35828
37143
|
let packageManager;
|
|
35829
37144
|
try {
|
|
35830
|
-
const raw = await readFile26(
|
|
37145
|
+
const raw = await readFile26(join45(rootDir, "package.json"), "utf-8");
|
|
35831
37146
|
const pkg = JSON.parse(raw);
|
|
35832
37147
|
if (typeof pkg.packageManager === "string") {
|
|
35833
37148
|
packageManager = pkg.packageManager;
|
|
@@ -35835,7 +37150,7 @@ async function runGenerate(opts) {
|
|
|
35835
37150
|
} catch {
|
|
35836
37151
|
}
|
|
35837
37152
|
const serverJson = await readJsonFile4(
|
|
35838
|
-
|
|
37153
|
+
join45(rootDir, ".codebyplan", "server.json")
|
|
35839
37154
|
);
|
|
35840
37155
|
const ports = [];
|
|
35841
37156
|
for (const alloc of serverJson?.port_allocations ?? []) {
|
|
@@ -35848,7 +37163,7 @@ async function runGenerate(opts) {
|
|
|
35848
37163
|
}
|
|
35849
37164
|
}
|
|
35850
37165
|
const gitJson = await readJsonFile4(
|
|
35851
|
-
|
|
37166
|
+
join45(rootDir, ".codebyplan", "git.json")
|
|
35852
37167
|
);
|
|
35853
37168
|
const branchModel = gitJson?.branch_config?.production ? {
|
|
35854
37169
|
production: gitJson.branch_config.production,
|
|
@@ -35857,7 +37172,7 @@ async function runGenerate(opts) {
|
|
|
35857
37172
|
)
|
|
35858
37173
|
} : void 0;
|
|
35859
37174
|
const shipmentJson = await readJsonFile4(
|
|
35860
|
-
|
|
37175
|
+
join45(rootDir, ".codebyplan", "shipment.json")
|
|
35861
37176
|
);
|
|
35862
37177
|
const shipmentSurfaces = [];
|
|
35863
37178
|
const rawSurfaces = shipmentJson?.shipment?.surfaces ?? shipmentJson?.surfaces ?? {};
|
|
@@ -35928,7 +37243,7 @@ async function runGenerate(opts) {
|
|
|
35928
37243
|
const structureMdContent = generateStructureMd(config);
|
|
35929
37244
|
const agentsContent = generateAgentsMd(structureMdContent);
|
|
35930
37245
|
if (check) {
|
|
35931
|
-
const agentsMdPath2 =
|
|
37246
|
+
const agentsMdPath2 = join45(rootDir, "AGENTS.md");
|
|
35932
37247
|
let existingAgents = null;
|
|
35933
37248
|
try {
|
|
35934
37249
|
existingAgents = await readFile26(agentsMdPath2, "utf-8");
|
|
@@ -35967,13 +37282,13 @@ async function runGenerate(opts) {
|
|
|
35967
37282
|
process.stdout.write(agentsContent);
|
|
35968
37283
|
return;
|
|
35969
37284
|
}
|
|
35970
|
-
const outputDir =
|
|
37285
|
+
const outputDir = join45(rootDir, ".claude", "generated");
|
|
35971
37286
|
await mkdir12(outputDir, { recursive: true });
|
|
35972
|
-
const outputPath =
|
|
37287
|
+
const outputPath = join45(outputDir, "structure.md");
|
|
35973
37288
|
await writeFile20(outputPath, structureMdContent, "utf-8");
|
|
35974
37289
|
process.stdout.write(`Wrote: .claude/generated/structure.md
|
|
35975
37290
|
`);
|
|
35976
|
-
const agentsMdPath =
|
|
37291
|
+
const agentsMdPath = join45(rootDir, "AGENTS.md");
|
|
35977
37292
|
let existingAgentsContent = null;
|
|
35978
37293
|
try {
|
|
35979
37294
|
existingAgentsContent = await readFile26(agentsMdPath, "utf-8");
|
|
@@ -36005,7 +37320,7 @@ __export(readme_exports, {
|
|
|
36005
37320
|
runReadmeCommand: () => runReadmeCommand
|
|
36006
37321
|
});
|
|
36007
37322
|
import { readFile as readFile27, writeFile as writeFile21 } from "node:fs/promises";
|
|
36008
|
-
import { join as
|
|
37323
|
+
import { join as join46, resolve as resolve12, relative as relative8 } from "node:path";
|
|
36009
37324
|
async function readJsonFile5(filePath) {
|
|
36010
37325
|
try {
|
|
36011
37326
|
const raw = await readFile27(filePath, "utf-8");
|
|
@@ -36077,7 +37392,7 @@ async function discoverUnits(rootDir, rootPkgJson) {
|
|
|
36077
37392
|
const discovered = await discoverMonorepoApps(rootDir);
|
|
36078
37393
|
for (const app of discovered) {
|
|
36079
37394
|
const pkgJson = await readJsonFile5(
|
|
36080
|
-
|
|
37395
|
+
join46(app.absPath, "package.json")
|
|
36081
37396
|
);
|
|
36082
37397
|
pkgJsonByPath.set(app.absPath, pkgJson);
|
|
36083
37398
|
allPackages.push({
|
|
@@ -36101,9 +37416,9 @@ async function runReadme(opts) {
|
|
|
36101
37416
|
const dryRun = opts.dryRun ?? opts["dryRun"] ?? false;
|
|
36102
37417
|
const check = opts.check ?? opts["check"] ?? false;
|
|
36103
37418
|
const init = opts.init ?? opts["init"] ?? false;
|
|
36104
|
-
const rootDir =
|
|
37419
|
+
const rootDir = resolve12(projectDir);
|
|
36105
37420
|
const rootPkgJson = await readJsonFile5(
|
|
36106
|
-
|
|
37421
|
+
join46(rootDir, "package.json")
|
|
36107
37422
|
);
|
|
36108
37423
|
const { units, allPackages, pkgJsonByPath } = await discoverUnits(
|
|
36109
37424
|
rootDir,
|
|
@@ -36112,8 +37427,8 @@ async function runReadme(opts) {
|
|
|
36112
37427
|
const driftUnits = [];
|
|
36113
37428
|
const missingUnits = [];
|
|
36114
37429
|
for (const unit of units) {
|
|
36115
|
-
const readmePath =
|
|
36116
|
-
const relPath = unit.isRoot ? "README.md" :
|
|
37430
|
+
const readmePath = join46(unit.absPath, "README.md");
|
|
37431
|
+
const relPath = unit.isRoot ? "README.md" : join46(relative8(rootDir, unit.absPath), "README.md");
|
|
36117
37432
|
let existingContent = null;
|
|
36118
37433
|
try {
|
|
36119
37434
|
existingContent = await readFile27(readmePath, "utf-8");
|
|
@@ -36303,11 +37618,11 @@ import {
|
|
|
36303
37618
|
rmdir,
|
|
36304
37619
|
readdir as readdir6
|
|
36305
37620
|
} from "node:fs/promises";
|
|
36306
|
-
import { existsSync as
|
|
36307
|
-
import { join as
|
|
37621
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
37622
|
+
import { join as join47, resolve as resolve13, dirname as dirname14, sep as sep3 } from "node:path";
|
|
36308
37623
|
import { homedir as homedir8 } from "node:os";
|
|
36309
37624
|
function encodeProjectPath(absPath) {
|
|
36310
|
-
return
|
|
37625
|
+
return resolve13(absPath).replace(/[/\\]/g, "-");
|
|
36311
37626
|
}
|
|
36312
37627
|
function resolveAutoMemoryDir(opts) {
|
|
36313
37628
|
if (opts.autoMemoryDir) {
|
|
@@ -36315,7 +37630,7 @@ function resolveAutoMemoryDir(opts) {
|
|
|
36315
37630
|
}
|
|
36316
37631
|
const projectDir = opts.projectDir ?? process.cwd();
|
|
36317
37632
|
const encoded = encodeProjectPath(projectDir);
|
|
36318
|
-
return
|
|
37633
|
+
return join47(homedir8(), ".claude", "projects", encoded, "memory");
|
|
36319
37634
|
}
|
|
36320
37635
|
function parseFrontmatter(content) {
|
|
36321
37636
|
content = content.replace(/\r\n/g, "\n");
|
|
@@ -36381,7 +37696,7 @@ async function inventoryFiles(dir) {
|
|
|
36381
37696
|
}
|
|
36382
37697
|
const results = [];
|
|
36383
37698
|
for (const filename of filenames) {
|
|
36384
|
-
const sourcePath =
|
|
37699
|
+
const sourcePath = join47(dir, filename);
|
|
36385
37700
|
let raw;
|
|
36386
37701
|
try {
|
|
36387
37702
|
raw = await readFile28(sourcePath, "utf-8");
|
|
@@ -36464,15 +37779,15 @@ function buildPlan(entries, opts) {
|
|
|
36464
37779
|
return plan;
|
|
36465
37780
|
}
|
|
36466
37781
|
async function applyPlan(plan, opts) {
|
|
36467
|
-
const projectDir =
|
|
37782
|
+
const projectDir = resolve13(opts.projectDir);
|
|
36468
37783
|
const dryRun = opts.dryRun ?? false;
|
|
36469
37784
|
for (const entry of plan.entries) {
|
|
36470
37785
|
if (entry.suggested_action !== "keep") continue;
|
|
36471
37786
|
if (!entry.suggested_target?.startsWith("nested:")) continue;
|
|
36472
37787
|
const relPath = entry.suggested_target.slice("nested:".length);
|
|
36473
|
-
const targetDir =
|
|
36474
|
-
const targetFile =
|
|
36475
|
-
if (!targetDir.startsWith(
|
|
37788
|
+
const targetDir = resolve13(join47(projectDir, relPath));
|
|
37789
|
+
const targetFile = join47(targetDir, "CLAUDE.md");
|
|
37790
|
+
if (!targetDir.startsWith(resolve13(projectDir) + sep3)) {
|
|
36476
37791
|
process.stderr.write(
|
|
36477
37792
|
`migrate-memory: skipping unsafe suggested_target "${entry.suggested_target}" \u2014 resolves outside projectDir
|
|
36478
37793
|
`
|
|
@@ -36490,8 +37805,8 @@ ${anchor}
|
|
|
36490
37805
|
if (dryRun) {
|
|
36491
37806
|
process.stdout.write(`[dry-run] Would create/append: ${targetFile}
|
|
36492
37807
|
`);
|
|
36493
|
-
if (
|
|
36494
|
-
|
|
37808
|
+
if (resolve13(entry.source_path).startsWith(
|
|
37809
|
+
resolve13(plan.auto_memory_dir) + sep3
|
|
36495
37810
|
)) {
|
|
36496
37811
|
process.stdout.write(
|
|
36497
37812
|
`[dry-run] Would delete migrated keep source: ${entry.source_path}
|
|
@@ -36509,7 +37824,7 @@ ${anchor}
|
|
|
36509
37824
|
if (!existing.includes(anchor)) {
|
|
36510
37825
|
await writeFile22(targetFile, existing + appendContent, "utf-8");
|
|
36511
37826
|
}
|
|
36512
|
-
if (
|
|
37827
|
+
if (resolve13(entry.source_path).startsWith(resolve13(plan.auto_memory_dir) + sep3)) {
|
|
36513
37828
|
try {
|
|
36514
37829
|
await unlink6(entry.source_path);
|
|
36515
37830
|
} catch {
|
|
@@ -36521,7 +37836,7 @@ ${anchor}
|
|
|
36521
37836
|
);
|
|
36522
37837
|
}
|
|
36523
37838
|
}
|
|
36524
|
-
const rootClaudeMd =
|
|
37839
|
+
const rootClaudeMd = join47(projectDir, ".claude", "CLAUDE.md");
|
|
36525
37840
|
if (dryRun) {
|
|
36526
37841
|
process.stdout.write(
|
|
36527
37842
|
`[dry-run] Would ensure ${rootClaudeMd} contains: ${IMPORT_LINE}
|
|
@@ -36532,7 +37847,7 @@ ${anchor}
|
|
|
36532
37847
|
try {
|
|
36533
37848
|
claudeMdContent = await readFile28(rootClaudeMd, "utf-8");
|
|
36534
37849
|
} catch {
|
|
36535
|
-
await mkdir13(
|
|
37850
|
+
await mkdir13(dirname14(rootClaudeMd), { recursive: true });
|
|
36536
37851
|
}
|
|
36537
37852
|
if (!claudeMdContent.includes(IMPORT_LINE)) {
|
|
36538
37853
|
await writeFile22(
|
|
@@ -36546,8 +37861,8 @@ ${IMPORT_LINE}
|
|
|
36546
37861
|
}
|
|
36547
37862
|
for (const entry of plan.entries) {
|
|
36548
37863
|
if (entry.suggested_action !== "drop") continue;
|
|
36549
|
-
if (!
|
|
36550
|
-
|
|
37864
|
+
if (!resolve13(entry.source_path).startsWith(
|
|
37865
|
+
resolve13(plan.auto_memory_dir) + sep3
|
|
36551
37866
|
)) {
|
|
36552
37867
|
process.stderr.write(
|
|
36553
37868
|
`migrate-memory: skipping delete of "${entry.source_path}" \u2014 resolves outside auto_memory_dir
|
|
@@ -36565,13 +37880,13 @@ ${IMPORT_LINE}
|
|
|
36565
37880
|
} catch {
|
|
36566
37881
|
}
|
|
36567
37882
|
}
|
|
36568
|
-
const memoryMd =
|
|
36569
|
-
const safeRmdirBase =
|
|
37883
|
+
const memoryMd = join47(plan.auto_memory_dir, "MEMORY.md");
|
|
37884
|
+
const safeRmdirBase = join47(homedir8(), ".claude", "projects");
|
|
36570
37885
|
if (dryRun) {
|
|
36571
37886
|
process.stdout.write(`[dry-run] Would delete MEMORY.md: ${memoryMd}
|
|
36572
37887
|
`);
|
|
36573
37888
|
} else {
|
|
36574
|
-
if (
|
|
37889
|
+
if (resolve13(plan.auto_memory_dir).startsWith(safeRmdirBase + sep3)) {
|
|
36575
37890
|
try {
|
|
36576
37891
|
await unlink6(memoryMd);
|
|
36577
37892
|
} catch {
|
|
@@ -36589,7 +37904,7 @@ ${IMPORT_LINE}
|
|
|
36589
37904
|
`
|
|
36590
37905
|
);
|
|
36591
37906
|
} else {
|
|
36592
|
-
if (!
|
|
37907
|
+
if (!resolve13(plan.auto_memory_dir).startsWith(safeRmdirBase + sep3)) {
|
|
36593
37908
|
process.stderr.write(
|
|
36594
37909
|
`migrate-memory: skipping rmdir of "${plan.auto_memory_dir}" \u2014 not under ~/.claude/projects
|
|
36595
37910
|
`
|
|
@@ -36619,7 +37934,7 @@ async function runMigrateMemory(opts) {
|
|
|
36619
37934
|
if (applyFile) {
|
|
36620
37935
|
let planJson;
|
|
36621
37936
|
try {
|
|
36622
|
-
planJson = await readFile28(
|
|
37937
|
+
planJson = await readFile28(resolve13(applyFile), "utf-8");
|
|
36623
37938
|
} catch (err) {
|
|
36624
37939
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36625
37940
|
process.stderr.write(
|
|
@@ -36647,7 +37962,7 @@ async function runMigrateMemory(opts) {
|
|
|
36647
37962
|
);
|
|
36648
37963
|
return;
|
|
36649
37964
|
}
|
|
36650
|
-
if (!
|
|
37965
|
+
if (!existsSync20(autoMemoryDir)) {
|
|
36651
37966
|
process.stdout.write(
|
|
36652
37967
|
JSON.stringify(
|
|
36653
37968
|
{
|
|
@@ -36689,8 +38004,8 @@ var init_migrate_memory = __esm({
|
|
|
36689
38004
|
});
|
|
36690
38005
|
|
|
36691
38006
|
// src/lib/claude-mode-audit.ts
|
|
36692
|
-
import { readdirSync as
|
|
36693
|
-
import { join as
|
|
38007
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync19, existsSync as existsSync21 } from "node:fs";
|
|
38008
|
+
import { join as join48, basename as basename2 } from "node:path";
|
|
36694
38009
|
function parseFrontmatter2(content) {
|
|
36695
38010
|
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
36696
38011
|
if (!match) return {};
|
|
@@ -36708,7 +38023,7 @@ function parseFrontmatter2(content) {
|
|
|
36708
38023
|
return result;
|
|
36709
38024
|
}
|
|
36710
38025
|
function auditAgent(filePath) {
|
|
36711
|
-
const content =
|
|
38026
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
36712
38027
|
const fm = parseFrontmatter2(content);
|
|
36713
38028
|
const agentName = fm.name ?? basename2(filePath, ".md");
|
|
36714
38029
|
const expected = AGENT_EXCEPTIONS[agentName] ?? AGENT_DEFAULT;
|
|
@@ -36740,7 +38055,7 @@ function auditAgent(filePath) {
|
|
|
36740
38055
|
};
|
|
36741
38056
|
}
|
|
36742
38057
|
function auditSkill(filePath) {
|
|
36743
|
-
const content =
|
|
38058
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
36744
38059
|
const fm = parseFrontmatter2(content);
|
|
36745
38060
|
const model = fm.model ?? null;
|
|
36746
38061
|
const effort = fm.effort ?? null;
|
|
@@ -36767,20 +38082,20 @@ function auditSkill(filePath) {
|
|
|
36767
38082
|
}
|
|
36768
38083
|
function auditMode(templatesDir) {
|
|
36769
38084
|
const entries = [];
|
|
36770
|
-
const agentsDir =
|
|
36771
|
-
if (
|
|
36772
|
-
const agentFiles =
|
|
38085
|
+
const agentsDir = join48(templatesDir, "agents");
|
|
38086
|
+
if (existsSync21(agentsDir)) {
|
|
38087
|
+
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md")).sort();
|
|
36773
38088
|
for (const f of agentFiles) {
|
|
36774
|
-
entries.push(auditAgent(
|
|
38089
|
+
entries.push(auditAgent(join48(agentsDir, f)));
|
|
36775
38090
|
}
|
|
36776
38091
|
}
|
|
36777
|
-
const skillsDir =
|
|
36778
|
-
if (
|
|
36779
|
-
const skillDirs =
|
|
38092
|
+
const skillsDir = join48(templatesDir, "skills");
|
|
38093
|
+
if (existsSync21(skillsDir)) {
|
|
38094
|
+
const skillDirs = readdirSync7(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
36780
38095
|
for (const dir of skillDirs) {
|
|
36781
|
-
if (
|
|
36782
|
-
const skillMd =
|
|
36783
|
-
if (
|
|
38096
|
+
if (existsSync21(join48(skillsDir, dir, "PROVENANCE.md"))) continue;
|
|
38097
|
+
const skillMd = join48(skillsDir, dir, "SKILL.md");
|
|
38098
|
+
if (existsSync21(skillMd)) {
|
|
36784
38099
|
entries.push(auditSkill(skillMd));
|
|
36785
38100
|
}
|
|
36786
38101
|
}
|
|
@@ -36807,7 +38122,7 @@ var audit_mode_exports = {};
|
|
|
36807
38122
|
__export(audit_mode_exports, {
|
|
36808
38123
|
runAuditMode: () => runAuditMode
|
|
36809
38124
|
});
|
|
36810
|
-
function
|
|
38125
|
+
function printHelp5() {
|
|
36811
38126
|
process.stdout.write(
|
|
36812
38127
|
"\n codebyplan claude audit-mode\n\n Audit model/effort frontmatter convention across authoring templates.\n\n Scans templates/agents/*.md and templates/skills/*/SKILL.md.\n Exits 0 when all files comply; exits 1 on any gap.\n\n Flags:\n --json Emit entries array as JSON\n\n"
|
|
36813
38128
|
);
|
|
@@ -36846,7 +38161,7 @@ ${total} audited, ${ok} ok, ${gaps} gap${gaps !== 1 ? "s" : ""}
|
|
|
36846
38161
|
async function runAuditMode(args) {
|
|
36847
38162
|
const first = args[0];
|
|
36848
38163
|
if (first === "--help" || first === "-h" || first === "help") {
|
|
36849
|
-
|
|
38164
|
+
printHelp5();
|
|
36850
38165
|
process.exit(0);
|
|
36851
38166
|
}
|
|
36852
38167
|
const { booleans } = parseFlagsFromArgs(args);
|
|
@@ -37037,16 +38352,16 @@ var new_migration_exports = {};
|
|
|
37037
38352
|
__export(new_migration_exports, {
|
|
37038
38353
|
newMigration: () => newMigration
|
|
37039
38354
|
});
|
|
37040
|
-
import * as
|
|
37041
|
-
import * as
|
|
38355
|
+
import * as fs19 from "node:fs";
|
|
38356
|
+
import * as path19 from "node:path";
|
|
37042
38357
|
function slugify(name) {
|
|
37043
38358
|
return name.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_");
|
|
37044
38359
|
}
|
|
37045
38360
|
function newMigration(args, deps = {}) {
|
|
37046
38361
|
const cwd = deps.cwd ?? process.cwd();
|
|
37047
38362
|
const genTimestamp = deps.generateTimestamp ?? generateMonotonicTimestamp;
|
|
37048
|
-
const
|
|
37049
|
-
const
|
|
38363
|
+
const mkdirSync11 = deps.mkdirSyncFn ?? ((dir, opts) => fs19.mkdirSync(dir, opts));
|
|
38364
|
+
const writeFileSync12 = deps.writeFileSyncFn ?? ((filePath2, content) => fs19.writeFileSync(filePath2, content));
|
|
37050
38365
|
const rawName = args[0];
|
|
37051
38366
|
if (!rawName) {
|
|
37052
38367
|
process.stderr.write(
|
|
@@ -37059,11 +38374,11 @@ function newMigration(args, deps = {}) {
|
|
|
37059
38374
|
}
|
|
37060
38375
|
const slug = slugify(rawName);
|
|
37061
38376
|
const stamp = genTimestamp({ cwd });
|
|
37062
|
-
const migrationsDir =
|
|
38377
|
+
const migrationsDir = path19.join(cwd, "supabase", "migrations");
|
|
37063
38378
|
const filename = `${stamp}_${slug}.sql`;
|
|
37064
|
-
const filePath =
|
|
37065
|
-
|
|
37066
|
-
|
|
38379
|
+
const filePath = path19.join(migrationsDir, filename);
|
|
38380
|
+
mkdirSync11(migrationsDir, { recursive: true });
|
|
38381
|
+
writeFileSync12(filePath, "");
|
|
37067
38382
|
process.stdout.write(JSON.stringify({ path: filePath }) + "\n");
|
|
37068
38383
|
return 0;
|
|
37069
38384
|
}
|
|
@@ -37107,7 +38422,7 @@ function defaultGetPrNumber(cwd, run) {
|
|
|
37107
38422
|
async function previewCheck(args, deps = {}) {
|
|
37108
38423
|
const cwd = deps.cwd ?? process.cwd();
|
|
37109
38424
|
const run = deps.run ?? defaultRun3;
|
|
37110
|
-
const sleep3 = deps.sleep ?? ((ms) => new Promise((
|
|
38425
|
+
const sleep3 = deps.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
37111
38426
|
const getPrNumber = deps.getPrNumber ?? defaultGetPrNumber;
|
|
37112
38427
|
const poll = deps.pollCheck ?? pollGhPreviewCheck;
|
|
37113
38428
|
let mode = "pre_merge";
|
|
@@ -37137,7 +38452,7 @@ var init_preview_check = __esm({
|
|
|
37137
38452
|
|
|
37138
38453
|
// src/lib/session.ts
|
|
37139
38454
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
37140
|
-
import * as
|
|
38455
|
+
import * as path20 from "node:path";
|
|
37141
38456
|
function defaultRun4(cmd, args, cwd) {
|
|
37142
38457
|
const result = spawnSync13(cmd, args, {
|
|
37143
38458
|
cwd,
|
|
@@ -37167,7 +38482,7 @@ function homeFf(opts = {}) {
|
|
|
37167
38482
|
reason: "git rev-parse --show-toplevel failed"
|
|
37168
38483
|
};
|
|
37169
38484
|
}
|
|
37170
|
-
const folder =
|
|
38485
|
+
const folder = path20.basename(repoRoot);
|
|
37171
38486
|
let current;
|
|
37172
38487
|
try {
|
|
37173
38488
|
current = run("git", ["rev-parse", "--abbrev-ref", "HEAD"], cwd).trim();
|
|
@@ -37734,13 +39049,13 @@ function validateWaves(waves) {
|
|
|
37734
39049
|
pathOwners.set(file, owners);
|
|
37735
39050
|
}
|
|
37736
39051
|
}
|
|
37737
|
-
for (const [
|
|
39052
|
+
for (const [path21, owners] of pathOwners) {
|
|
37738
39053
|
if (owners.length > 1) {
|
|
37739
39054
|
violations.push({
|
|
37740
39055
|
invariant: "I",
|
|
37741
39056
|
code: "DUPLICATE_FILE",
|
|
37742
|
-
message: `File "${
|
|
37743
|
-
detail: { path:
|
|
39057
|
+
message: `File "${path21}" appears in multiple waves: ${owners.join(", ")}.`,
|
|
39058
|
+
detail: { path: path21, waves: owners }
|
|
37744
39059
|
});
|
|
37745
39060
|
}
|
|
37746
39061
|
}
|
|
@@ -37836,12 +39151,12 @@ __export(validate_waves_exports, {
|
|
|
37836
39151
|
});
|
|
37837
39152
|
import { readFile as readFile29 } from "node:fs/promises";
|
|
37838
39153
|
async function readStdin() {
|
|
37839
|
-
return new Promise((
|
|
39154
|
+
return new Promise((resolve16, reject) => {
|
|
37840
39155
|
const chunks = [];
|
|
37841
39156
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
37842
39157
|
process.stdin.on(
|
|
37843
39158
|
"end",
|
|
37844
|
-
() =>
|
|
39159
|
+
() => resolve16(Buffer.concat(chunks).toString("utf-8"))
|
|
37845
39160
|
);
|
|
37846
39161
|
process.stdin.on("error", reject);
|
|
37847
39162
|
});
|
|
@@ -37933,12 +39248,12 @@ var init_validate_waves2 = __esm({
|
|
|
37933
39248
|
});
|
|
37934
39249
|
|
|
37935
39250
|
// src/cli/worktree/path.ts
|
|
37936
|
-
import { dirname as
|
|
39251
|
+
import { dirname as dirname15, basename as basename4, join as join50 } from "node:path";
|
|
37937
39252
|
function computeWorktreePath(cwd, checkpointNumber) {
|
|
37938
|
-
const parent =
|
|
39253
|
+
const parent = dirname15(cwd);
|
|
37939
39254
|
const base = basename4(cwd);
|
|
37940
39255
|
const nnn = String(checkpointNumber).padStart(3, "0");
|
|
37941
|
-
return
|
|
39256
|
+
return join50(parent, `${base}-CHK-${nnn}`);
|
|
37942
39257
|
}
|
|
37943
39258
|
var init_path = __esm({
|
|
37944
39259
|
"src/cli/worktree/path.ts"() {
|
|
@@ -37947,7 +39262,7 @@ var init_path = __esm({
|
|
|
37947
39262
|
});
|
|
37948
39263
|
|
|
37949
39264
|
// src/cli/worktree/add.ts
|
|
37950
|
-
import { join as
|
|
39265
|
+
import { join as join51, basename as basename5 } from "node:path";
|
|
37951
39266
|
import { mkdir as mkdir14, readFile as readFile30, writeFile as writeFile23 } from "node:fs/promises";
|
|
37952
39267
|
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
37953
39268
|
async function defaultGetRepoId(cwd) {
|
|
@@ -37991,33 +39306,33 @@ function defaultGitRun(args, cwd) {
|
|
|
37991
39306
|
};
|
|
37992
39307
|
}
|
|
37993
39308
|
async function defaultCopyConfigStubs(srcCwd, destPath) {
|
|
37994
|
-
await mkdir14(
|
|
39309
|
+
await mkdir14(join51(destPath, ".codebyplan"), { recursive: true });
|
|
37995
39310
|
const topLevelStubs = [".mcp.json", ".env.local"];
|
|
37996
39311
|
for (const stub of topLevelStubs) {
|
|
37997
39312
|
try {
|
|
37998
|
-
const content = await readFile30(
|
|
37999
|
-
await writeFile23(
|
|
39313
|
+
const content = await readFile30(join51(srcCwd, stub), "utf-8");
|
|
39314
|
+
await writeFile23(join51(destPath, stub), content, "utf-8");
|
|
38000
39315
|
} catch {
|
|
38001
39316
|
}
|
|
38002
39317
|
}
|
|
38003
39318
|
try {
|
|
38004
39319
|
const content = await readFile30(
|
|
38005
|
-
|
|
39320
|
+
join51(srcCwd, ".codebyplan", "repo.json"),
|
|
38006
39321
|
"utf-8"
|
|
38007
39322
|
);
|
|
38008
39323
|
await writeFile23(
|
|
38009
|
-
|
|
39324
|
+
join51(destPath, ".codebyplan", "repo.json"),
|
|
38010
39325
|
content,
|
|
38011
39326
|
"utf-8"
|
|
38012
39327
|
);
|
|
38013
39328
|
} catch {
|
|
38014
39329
|
}
|
|
38015
39330
|
}
|
|
38016
|
-
async function defaultRegisterWorktree(repoId, name,
|
|
39331
|
+
async function defaultRegisterWorktree(repoId, name, path21) {
|
|
38017
39332
|
const res = await apiPost("/worktrees", {
|
|
38018
39333
|
repo_id: repoId,
|
|
38019
39334
|
name,
|
|
38020
|
-
path:
|
|
39335
|
+
path: path21,
|
|
38021
39336
|
status: "active"
|
|
38022
39337
|
});
|
|
38023
39338
|
return { worktree_id: res.data.id };
|
|
@@ -38051,7 +39366,7 @@ async function runWorktreeAdd(args, deps = {}) {
|
|
|
38051
39366
|
const getRepoId = deps.getRepoId ?? defaultGetRepoId;
|
|
38052
39367
|
const lookupBranch = deps.lookupBranch ?? defaultLookupBranch;
|
|
38053
39368
|
const gitRun = deps.gitRun ?? defaultGitRun;
|
|
38054
|
-
const sleep3 = deps.sleep ?? ((ms) => new Promise((
|
|
39369
|
+
const sleep3 = deps.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
38055
39370
|
const copyConfigStubs = deps.copyConfigStubs ?? defaultCopyConfigStubs;
|
|
38056
39371
|
const registerWorktree = deps.registerWorktree ?? defaultRegisterWorktree;
|
|
38057
39372
|
try {
|
|
@@ -38167,7 +39482,7 @@ var init_add = __esm({
|
|
|
38167
39482
|
});
|
|
38168
39483
|
|
|
38169
39484
|
// src/cli/worktree/create.ts
|
|
38170
|
-
import { join as
|
|
39485
|
+
import { join as join52 } from "node:path";
|
|
38171
39486
|
async function defaultGetRepoIdentity(cwd) {
|
|
38172
39487
|
const found = await findCodebyplanConfig(cwd);
|
|
38173
39488
|
const contents = found?.contents ?? null;
|
|
@@ -38179,11 +39494,11 @@ async function defaultGetRepoIdentity(cwd) {
|
|
|
38179
39494
|
project_id: typeof contents?.["project_id"] === "string" ? contents["project_id"] : void 0
|
|
38180
39495
|
};
|
|
38181
39496
|
}
|
|
38182
|
-
async function defaultRegisterWorktree2(repoId, name,
|
|
39497
|
+
async function defaultRegisterWorktree2(repoId, name, path21) {
|
|
38183
39498
|
const res = await apiPost("/worktrees", {
|
|
38184
39499
|
repo_id: repoId,
|
|
38185
39500
|
name,
|
|
38186
|
-
path:
|
|
39501
|
+
path: path21,
|
|
38187
39502
|
status: "active"
|
|
38188
39503
|
});
|
|
38189
39504
|
return { worktree_id: res.data.id };
|
|
@@ -38222,7 +39537,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
38222
39537
|
);
|
|
38223
39538
|
return 1;
|
|
38224
39539
|
}
|
|
38225
|
-
const worktreePath = explicitPath ??
|
|
39540
|
+
const worktreePath = explicitPath ?? join52(cwd, "..", name);
|
|
38226
39541
|
const deviceId = await getDeviceId(cwd);
|
|
38227
39542
|
let filesWritten = false;
|
|
38228
39543
|
try {
|
|
@@ -38708,13 +40023,13 @@ var init_e2e = __esm({
|
|
|
38708
40023
|
|
|
38709
40024
|
// src/cli/e2e/verify-round.ts
|
|
38710
40025
|
import { readFile as readFile31 } from "node:fs/promises";
|
|
38711
|
-
import { resolve as
|
|
40026
|
+
import { resolve as resolve14 } from "node:path";
|
|
38712
40027
|
async function defaultFetchRounds(taskId) {
|
|
38713
40028
|
return mcpCall("get_rounds", { task_id: taskId });
|
|
38714
40029
|
}
|
|
38715
40030
|
async function defaultReadE2eConfig(cwd) {
|
|
38716
40031
|
try {
|
|
38717
|
-
const p =
|
|
40032
|
+
const p = resolve14(cwd, ".codebyplan", "e2e.json");
|
|
38718
40033
|
const raw = await readFile31(p, "utf-8");
|
|
38719
40034
|
return JSON.parse(raw);
|
|
38720
40035
|
} catch {
|
|
@@ -38840,7 +40155,7 @@ var doctor_exports = {};
|
|
|
38840
40155
|
__export(doctor_exports, {
|
|
38841
40156
|
runDoctor: () => runDoctor
|
|
38842
40157
|
});
|
|
38843
|
-
import { execSync as
|
|
40158
|
+
import { execSync as execSync10 } from "node:child_process";
|
|
38844
40159
|
async function checkAuth() {
|
|
38845
40160
|
try {
|
|
38846
40161
|
await validateAuth();
|
|
@@ -38861,7 +40176,7 @@ async function checkVersion() {
|
|
|
38861
40176
|
const installed = VERSION;
|
|
38862
40177
|
let gitRoot = null;
|
|
38863
40178
|
try {
|
|
38864
|
-
gitRoot =
|
|
40179
|
+
gitRoot = execSync10("git rev-parse --show-toplevel", {
|
|
38865
40180
|
encoding: "utf-8"
|
|
38866
40181
|
}).trim();
|
|
38867
40182
|
} catch {
|
|
@@ -38968,7 +40283,7 @@ function printHuman(result) {
|
|
|
38968
40283
|
|
|
38969
40284
|
`);
|
|
38970
40285
|
}
|
|
38971
|
-
function
|
|
40286
|
+
function printHelp6() {
|
|
38972
40287
|
process.stdout.write(
|
|
38973
40288
|
"\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"
|
|
38974
40289
|
);
|
|
@@ -38976,7 +40291,7 @@ function printHelp4() {
|
|
|
38976
40291
|
async function runDoctor(args) {
|
|
38977
40292
|
const first = args[0];
|
|
38978
40293
|
if (first === "--help" || first === "-h" || first === "help") {
|
|
38979
|
-
|
|
40294
|
+
printHelp6();
|
|
38980
40295
|
process.exit(0);
|
|
38981
40296
|
}
|
|
38982
40297
|
const { booleans } = parseFlagsFromArgs(args);
|
|
@@ -39013,13 +40328,13 @@ var init_doctor = __esm({
|
|
|
39013
40328
|
|
|
39014
40329
|
// src/index.ts
|
|
39015
40330
|
init_version();
|
|
39016
|
-
import { readFileSync as
|
|
39017
|
-
import { resolve as
|
|
40331
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
40332
|
+
import { resolve as resolve15 } from "node:path";
|
|
39018
40333
|
void (async () => {
|
|
39019
40334
|
if (!process.env.CODEBYPLAN_API_KEY) {
|
|
39020
40335
|
try {
|
|
39021
|
-
const envPath =
|
|
39022
|
-
const content =
|
|
40336
|
+
const envPath = resolve15(process.cwd(), ".env.local");
|
|
40337
|
+
const content = readFileSync20(envPath, "utf-8");
|
|
39023
40338
|
for (const line of content.split("\n")) {
|
|
39024
40339
|
const trimmed = line.trim();
|
|
39025
40340
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -39156,6 +40471,16 @@ void (async () => {
|
|
|
39156
40471
|
await runScaffoldPublishWorkflowCommand2(process.argv.slice(3));
|
|
39157
40472
|
process.exit(process.exitCode ?? 0);
|
|
39158
40473
|
}
|
|
40474
|
+
if (arg === "ci") {
|
|
40475
|
+
const { runCiCommand: runCiCommand2 } = await Promise.resolve().then(() => (init_ci(), ci_exports));
|
|
40476
|
+
await runCiCommand2(process.argv.slice(3));
|
|
40477
|
+
process.exit(process.exitCode ?? 0);
|
|
40478
|
+
}
|
|
40479
|
+
if (arg === "cd") {
|
|
40480
|
+
const { runCdCommand: runCdCommand2 } = await Promise.resolve().then(() => (init_cd(), cd_exports));
|
|
40481
|
+
await runCdCommand2(process.argv.slice(3));
|
|
40482
|
+
process.exit(process.exitCode ?? 0);
|
|
40483
|
+
}
|
|
39159
40484
|
if (arg === "resolve-worktree") {
|
|
39160
40485
|
const { runResolveWorktree: runResolveWorktree2 } = await Promise.resolve().then(() => (init_resolve_worktree2(), resolve_worktree_exports));
|
|
39161
40486
|
await runResolveWorktree2();
|
|
@@ -39474,6 +40799,8 @@ void (async () => {
|
|
|
39474
40799
|
codebyplan tech-stack Detect and sync tech stack dependencies
|
|
39475
40800
|
(--full-tech-stack: sync every local worktree on this device)
|
|
39476
40801
|
codebyplan eslint ESLint config management (init)
|
|
40802
|
+
codebyplan ci CI configuration management (init / scaffold-workflow / enforce-check)
|
|
40803
|
+
codebyplan cd CD configuration management (init / scaffold-workflow)
|
|
39477
40804
|
codebyplan check Run unified check matrix (lint, tsc, tests, audit)
|
|
39478
40805
|
(--scope <round|task|merged>, --files <csv>, --json)
|
|
39479
40806
|
codebyplan lsp Detect tech stack and enable LSP plugins in Claude Code
|