codebyplan 1.13.52 → 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 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.52";
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 path16 = localConfigPath(projectPath);
117
- const dirPath = dirname(path16);
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(path16, JSON.stringify(content, null, 2) + "\n", "utf-8");
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(path16) {
656
- return readFile6(path16, "utf-8").then(() => true).catch(() => false);
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: (path16, opts) => mkdir3(path16, opts).then(() => void 0),
778
- writeFile: (path16, data, encoding) => writeFile4(path16, data, encoding),
779
- readFile: (path16, encoding) => readFile6(path16, encoding),
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 path16 = fallbackFile(filename);
848
- await mkdir4(dirname2(path16), { recursive: true });
849
- await writeFile5(path16, JSON.stringify(data, null, 2) + "\n", "utf-8");
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(path16, 384);
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(path16, params) {
1145
- const url = new URL(`${baseUrl()}/api${path16}`);
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((resolve11) => setTimeout(resolve11, ms));
1162
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
1163
1163
  }
1164
- async function request(method, path16, options) {
1165
- const url = buildUrl(path16, options?.params);
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} ${path16} failed with status ${res.status}`;
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(path16, params) {
1220
- return request("GET", path16, { params });
1219
+ async function apiGet(path21, params) {
1220
+ return request("GET", path21, { params });
1221
1221
  }
1222
- async function apiPost(path16, body) {
1223
- return request("POST", path16, { body });
1222
+ async function apiPost(path21, body) {
1223
+ return request("POST", path21, { body });
1224
1224
  }
1225
- async function apiPut(path16, body) {
1226
- return request("PUT", path16, { body });
1225
+ async function apiPut(path21, body) {
1226
+ return request("PUT", path21, { body });
1227
1227
  }
1228
- async function apiPatch(path16, body) {
1229
- return request("PATCH", path16, { body });
1228
+ async function apiPatch(path21, body) {
1229
+ return request("PATCH", path21, { body });
1230
1230
  }
1231
- async function apiDelete(path16, params) {
1232
- await request("DELETE", path16, { params });
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((resolve11) => setTimeout(resolve11, ms));
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(path16) {
3414
+ async function readConfig(path21) {
3415
3415
  try {
3416
- const raw = await readFile11(path16, "utf-8");
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(path16) {
3847
+ async function readConfig2(path21) {
3848
3848
  try {
3849
- const raw = await readFile12(path16, "utf-8");
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(path16, config, newUrl) {
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(path16, JSON.stringify(config, null, 2) + "\n", "utf-8");
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 path16 of configPaths()) {
3880
- const config = await readConfig2(path16);
3879
+ for (const path21 of configPaths()) {
3880
+ const config = await readConfig2(path21);
3881
3881
  if (!config) continue;
3882
- const changed = await rewriteConfig(path16, config, newUrl);
3882
+ const changed = await rewriteConfig(path21, config, newUrl);
3883
3883
  if (changed) {
3884
- console.log(` Updated ${path16}`);
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: execSync10 } = await import("node:child_process");
4561
+ const { execSync: execSync11 } = await import("node:child_process");
4562
4562
  try {
4563
- execSync10(installCmd, { cwd: projectPath, stdio: "inherit" });
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(resolve11) {
5330
- resolve11(value);
5329
+ return value instanceof P ? value : new P(function(resolve16) {
5330
+ resolve16(value);
5331
5331
  });
5332
5332
  }
5333
- return new (P || (P = Promise))(function(resolve11, reject) {
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 ? resolve11(result.value) : adopt(result.value).then(fulfilled, rejected);
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(resolve11, reject) {
5541
- v = o[n](v), settle(resolve11, reject, v.done, v.value);
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(resolve11, reject, d, v) {
5545
+ function settle(resolve16, reject, d, v) {
5546
5546
  Promise.resolve(v).then(function(v2) {
5547
- resolve11({ value: v2, done: d });
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(path16, preserveJsx) {
5640
- if (typeof path16 === "string" && /^\.\.?\//.test(path16)) {
5641
- return path16.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
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 path16;
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((resolve11) => {
6120
+ return new Promise((resolve16) => {
6121
6121
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
6122
- resolve11();
6122
+ resolve16();
6123
6123
  return;
6124
6124
  }
6125
6125
  const id = setTimeout(() => {
6126
6126
  signal === null || signal === void 0 || signal.removeEventListener("abort", onAbort);
6127
- resolve11();
6127
+ resolve16();
6128
6128
  }, ms);
6129
6129
  function onAbort() {
6130
6130
  clearTimeout(id);
6131
- resolve11();
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((resolve11) => {
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
- resolve11("ok");
14172
+ resolve16("ok");
14173
14173
  }
14174
- push.receive("ok", () => resolve11("ok"));
14175
- push.receive("error", () => resolve11("error"));
14176
- push.receive("timeout", () => resolve11("timed out"));
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((resolve11) => {
14202
- this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve11("ok")).receive("timeout", () => resolve11("timed out")).receive("error", () => resolve11("error"));
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: join48 } = constants_1.CHANNEL_EVENTS;
14284
- const events = [close, error, leave, join48];
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((resolve11) => {
14407
- setTimeout(() => resolve11("timeout"), timeout);
14406
+ return new Promise((resolve16) => {
14407
+ setTimeout(() => resolve16("timeout"), timeout);
14408
14408
  this.socket.disconnect(() => {
14409
14409
  callback();
14410
- resolve11("ok");
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, path16, query) {
15168
- const url = new URL(path16, baseUrl3);
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: path16,
15198
+ path: path21,
15199
15199
  query,
15200
15200
  body,
15201
15201
  headers
15202
15202
  }) {
15203
- const url = buildUrl2(options.baseUrl, path16, query);
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((resolve11, reject) => {
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) => resolve11(data)).catch((error) => handleError(error, reject, options, namespace));
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, path16, fileBody, fileOptions) {
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(path16);
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(path16, fileBody, fileOptions) {
16188
- return this.uploadOrUpdate("POST", path16, fileBody, fileOptions);
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(path16, token, fileBody, fileOptions) {
16228
+ async uploadToSignedUrl(path21, token, fileBody, fileOptions) {
16229
16229
  var _this3 = this;
16230
- const cleanPath = _this3._removeEmptyFolders(path16);
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(path16, options) {
16299
+ async createSignedUploadUrl(path21, options) {
16300
16300
  var _this4 = this;
16301
16301
  return _this4.handleOperation(async () => {
16302
- let _path = _this4._getFinalPath(path16);
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: path16,
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(path16, fileBody, fileOptions) {
16372
- return this.uploadOrUpdate("PUT", path16, fileBody, fileOptions);
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(path16, expiresIn, options) {
16523
+ async createSignedUrl(path21, expiresIn, options) {
16524
16524
  var _this8 = this;
16525
16525
  return _this8.handleOperation(async () => {
16526
- let _path = _this8._getFinalPath(path16);
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(path16, options, parameters) {
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(path16);
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(path16) {
16699
+ async info(path21) {
16700
16700
  var _this10 = this;
16701
- const _path = _this10._getFinalPath(path16);
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(path16) {
16722
+ async exists(path21) {
16723
16723
  var _this11 = this;
16724
- const _path = _this11._getFinalPath(path16);
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(path16, options) {
16804
- const _path = this._getFinalPath(path16);
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(path16, options, parameters) {
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: path16 || "" });
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(path16) {
17012
- return `${this.bucketId}/${path16.replace(/^\/+/, "")}`;
17011
+ _getFinalPath(path21) {
17012
+ return `${this.bucketId}/${path21.replace(/^\/+/, "")}`;
17013
17013
  }
17014
- _removeEmptyFolders(path16) {
17015
- return path16.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
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(resolve11) {
26394
- resolve11(value);
26393
+ return value instanceof P ? value : new P(function(resolve16) {
26394
+ resolve16(value);
26395
26395
  });
26396
26396
  }
26397
- return new (P || (P = Promise))(function(resolve11, reject) {
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 ? resolve11(result.value) : adopt(result.value).then(fulfilled, rejected);
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((resolve11) => {
27149
- this.stopResolve = resolve11;
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((resolve11) => setTimeout(resolve11, ms));
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, path16, body) {
27735
- const url = `${getBackendBase()}${path16}`;
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} ${path16} failed with status ${res.status}`;
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(path16, body) {
27762
- return backendRequest("POST", path16, body);
27761
+ async function apiBackendPost(path21, body) {
27762
+ return backendRequest("POST", path21, body);
27763
27763
  }
27764
- async function apiBackendPatch(path16, body) {
27765
- return backendRequest("PATCH", path16, body);
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((resolve11) => setTimeout(resolve11, ms));
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((resolve11) => setTimeout(resolve11, ms)));
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 execSync6 } from "node:child_process";
31437
- import { existsSync as existsSync5, readFileSync as readFileSync6 } from "node:fs";
31438
- import { dirname as dirname10, join as join25 } from "node:path";
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 execSync6("git rev-parse --show-toplevel", {
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 (existsSync5(join25(dir, "pnpm-lock.yaml"))) return "pnpm";
31463
- if (existsSync5(join25(dir, "yarn.lock"))) return "yarn";
31464
- if (existsSync5(join25(dir, "package-lock.json"))) return "npm";
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 = dirname10(dir);
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 = join25(
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 (existsSync5(canonicalPkgPath)) {
31492
- const raw = readFileSync6(canonicalPkgPath, "utf-8");
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 = join25(dir, "git.json");
32823
+ gitJsonPath = join30(dir, "git.json");
31509
32824
  } else {
31510
32825
  const legacyDir = found.path.slice(0, found.path.lastIndexOf("/"));
31511
- gitJsonPath = join25(legacyDir, ".codebyplan", "git.json");
32826
+ gitJsonPath = join30(legacyDir, ".codebyplan", "git.json");
31512
32827
  }
31513
- const raw = readFileSync6(gitJsonPath, "utf-8");
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 join26, basename, resolve as resolve5 } from "node:path";
31597
- import { execSync as execSync7 } from "node:child_process";
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
- join26(projectPath, ".codebyplan", "e2e.json"),
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 = execSync7(
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: join26(projectPath, filePath),
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 = resolve5(process.cwd());
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 existsSync6, readdirSync as readdirSync3 } from "node:fs";
31848
- import { join as join27 } from "node:path";
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 = join27(codebyplanDir, "architecture.json");
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 = join27(codebyplanDir, "architecture.json");
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 = join27(projectRoot, "pnpm-workspace.yaml");
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 = join27(projectRoot, dir);
33247
+ const absDir = join32(projectRoot, dir);
31933
33248
  try {
31934
- if (existsSync6(absDir)) {
31935
- const entries = readdirSync3(absDir, { withFileTypes: true });
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 = join27(projectRoot, pattern);
31946
- if (existsSync6(absPath)) {
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 = join27(projectRoot, dir);
33268
+ const absPath = join32(projectRoot, dir);
31954
33269
  try {
31955
- if (existsSync6(absPath)) {
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 = join27(repoRoot, stampedEntry.map_file);
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 join28 } from "node:path";
33660
+ import { join as join33 } from "node:path";
32346
33661
  function legacySharedPath(projectPath) {
32347
- return join28(projectPath, ".codebyplan.json");
33662
+ return join33(projectPath, ".codebyplan.json");
32348
33663
  }
32349
33664
  function legacyLocalPath(projectPath) {
32350
- return join28(projectPath, ".codebyplan.local.json");
33665
+ return join33(projectPath, ".codebyplan.local.json");
32351
33666
  }
32352
33667
  function newDirPath(projectPath) {
32353
- return join28(projectPath, ".codebyplan");
33668
+ return join33(projectPath, ".codebyplan");
32354
33669
  }
32355
33670
  function sentinelPath(projectPath) {
32356
- return join28(projectPath, ".codebyplan", "repo.json");
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
- join28(projectPath, ".codebyplan", "repo.json"),
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
- join28(projectPath, ".codebyplan", "server.json"),
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
- join28(projectPath, ".codebyplan", "git.json"),
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
- join28(projectPath, ".codebyplan", "shipment.json"),
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
- join28(projectPath, ".codebyplan", "vendor.json"),
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
- join28(projectPath, ".codebyplan", "e2e.json"),
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
- join28(projectPath, ".codebyplan", "eslint.json"),
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
- join28(projectPath, ".codebyplan", "device.local.json"),
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 = join28(projectPath, ".gitignore");
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 join29 } from "node:path";
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 = join29(projectPath, ".codebyplan");
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 = join29(codebyplanDir, name);
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
- join29(projectPath, ".codebyplan", "repo.json"),
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
- join29(projectPath, ".codebyplan", "server.json"),
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
- join29(projectPath, ".codebyplan", "git.json"),
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
- join29(projectPath, ".codebyplan", "shipment.json"),
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
- join29(projectPath, ".codebyplan", "vendor.json"),
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
- join29(projectPath, ".codebyplan", "e2e.json"),
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
- join29(projectPath, ".codebyplan", "server.local.json"),
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 join30 } from "node:path";
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(join30(dir, "pnpm-lock.yaml"))) return "pnpm";
32881
- if (await fileExists4(join30(dir, "yarn.lock"))) return "yarn";
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 hasDep = (name) => name in deps || name in devDeps;
32889
- if (hasDep("next")) return "nextjs";
32890
- if (hasDep("@tauri-apps/api") || hasDep("@tauri-apps/cli")) return "tauri";
32891
- if (hasDep("expo")) return "expo";
32892
- if (hasDep("vite")) return "vite";
32893
- if (hasDep("express")) return "express";
32894
- if (hasDep("@nestjs/core")) return "nestjs";
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(join30(dir, "turbo.json")) || await fileExists4(join30(dir, "pnpm-workspace.yaml"));
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(join30(projectPath, "package.json"), "utf-8");
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 = join30(projectPath, "apps");
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 = join30(appsDir, entry.name, "package.json");
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 join31 } from "node:path";
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 = join31(projectPath, ".codebyplan");
33263
- const filePath = join31(codebyplanDir, "server.local.json");
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 = join31("apps", "web", ".env.local");
33286
- const sourcePath = join31(projectPath, relSource);
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 = join31(projectPath, ".codebyplan");
33319
- const filePath = join31(codebyplanDir, "e2e.env");
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 existsSync7 } from "node:fs";
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 ? existsSync7(wt.path) : false
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 readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
33595
- import { join as join32 } from "node:path";
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 = join32(projectRoot, BASELINE_FILENAME);
34920
+ const filePath = join37(projectRoot, BASELINE_FILENAME);
33606
34921
  try {
33607
- const raw = readFileSync7(filePath, "utf-8");
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 = join32(projectRoot, BASELINE_FILENAME);
33630
- writeFileSync4(filePath, JSON.stringify(baseline, null, 2) + "\n", "utf-8");
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 readFileSync8, existsSync as existsSync8 } from "node:fs";
33679
- import { join as join33 } from "node:path";
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 = readFileSync8(summaryPath, "utf-8");
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 = join33(projectRoot, "node_modules", ".bin", "turbo");
33743
- if (existsSync8(localBin)) return localBin;
33744
- const workspaceRootBin = join33(
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 (existsSync8(workspaceRootBin)) return workspaceRootBin;
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 fs7 from "node:fs";
34181
- import * as path8 from "node:path";
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 = path8.join(projectDir, ".claude", pkg.dest);
34196
- const absSrc = path8.join(templatesDir, pkg.src);
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 = fs7.existsSync(absDest);
34205
- const onDiskContent = onDiskExists ? fs7.readFileSync(absDest) : Buffer.alloc(0);
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 fs8 from "node:fs";
34245
- import * as path9 from "node:path";
34246
- import { execSync as execSync8 } from "node:child_process";
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 execSync8("git rev-parse --show-toplevel", {
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 = path9.join(projectDir, ".claude", "settings.json");
34351
- const baseSettingsPath = path9.join(
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 = path9.join(templatesDir, "hooks", "hooks.json");
34356
- if (fs8.existsSync(settingsPath)) {
35670
+ const hooksJsonPath = path14.join(templatesDir, "hooks", "hooks.json");
35671
+ if (fs14.existsSync(settingsPath)) {
34357
35672
  try {
34358
- const settingsRaw = fs8.readFileSync(settingsPath, "utf8");
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 (fs8.existsSync(baseSettingsPath)) {
35676
+ if (fs14.existsSync(baseSettingsPath)) {
34362
35677
  const base = JSON.parse(
34363
- fs8.readFileSync(baseSettingsPath, "utf8")
35678
+ fs14.readFileSync(baseSettingsPath, "utf8")
34364
35679
  );
34365
35680
  mergeBaseSettingsIntoSettings(cloned, base);
34366
35681
  }
34367
- if (fs8.existsSync(hooksJsonPath)) {
35682
+ if (fs14.existsSync(hooksJsonPath)) {
34368
35683
  const hooksJson = JSON.parse(
34369
- fs8.readFileSync(hooksJsonPath, "utf8")
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 = path9.join(projectDir, ".codebyplan");
34422
- fs8.mkdirSync(cacheDir, { recursive: true });
34423
- fs8.writeFileSync(
34424
- path9.join(cacheDir, "claude-status.local.json"),
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((resolve11) => {
35782
+ const answer = await new Promise((resolve16) => {
34468
35783
  rl.question(`${q.message}
34469
35784
  ${choices}
34470
35785
  > `, (input) => {
34471
- resolve11(input.trim().toLowerCase());
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 fs9 from "node:fs";
35880
+ import * as fs15 from "node:fs";
34566
35881
  import * as os3 from "node:os";
34567
- import * as path10 from "node:path";
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 = path10.join(projectDir, ".claude", packaged.dest);
35918
+ const absDest = path15.join(projectDir, ".claude", packaged.dest);
34604
35919
  if (!opts.dryRun) {
34605
- fs9.mkdirSync(path10.dirname(absDest), { recursive: true });
34606
- fs9.copyFileSync(absSrc, absDest);
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 = path10.join(projectDir, ".claude", packaged.dest);
34619
- const newContent = fs9.readFileSync(absSrc);
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
- fs9.mkdirSync(path10.dirname(absDest), { recursive: true });
34632
- fs9.copyFileSync(absSrc, absDest);
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 = path10.join(projectDir, ".claude", packaged.dest);
35962
+ const absDest = path15.join(projectDir, ".claude", packaged.dest);
34648
35963
  if (!opts.dryRun) {
34649
- fs9.mkdirSync(path10.dirname(absDest), { recursive: true });
34650
- fs9.copyFileSync(absSrc, absDest);
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 = path10.join(projectDir, ".claude", e.dest);
34662
- if (!opts.dryRun && fs9.existsSync(absDest)) {
34663
- fs9.rmSync(absDest);
34664
- const claudeDir = path10.join(projectDir, ".claude");
34665
- let cur = path10.dirname(absDest);
34666
- while (cur !== claudeDir && cur !== path10.dirname(cur)) {
34667
- if (path10.dirname(cur) === claudeDir) break;
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
- fs9.rmdirSync(cur);
35984
+ fs15.rmdirSync(cur);
34670
35985
  if (opts.verbose)
34671
35986
  console.log(
34672
- `pruned empty dir ${path10.relative(claudeDir, cur)}`
35987
+ `pruned empty dir ${path15.relative(claudeDir, cur)}`
34673
35988
  );
34674
- cur = path10.dirname(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 ${path10.relative(claudeDir, cur)}: ${err.message}`
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 = path10.join(templatesDir, "hooks", "hooks.json");
34692
- const baseSettingsPath = path10.join(
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 = path10.join(projectDir, ".claude", "settings.json");
34697
- const existingSettings = fs9.existsSync(settingsPath) ? JSON.parse(fs9.readFileSync(settingsPath, "utf8")) : {};
34698
- if (fs9.existsSync(baseSettingsPath)) {
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
- fs9.readFileSync(baseSettingsPath, "utf8")
36015
+ fs15.readFileSync(baseSettingsPath, "utf8")
34701
36016
  );
34702
36017
  mergeBaseSettingsIntoSettings(existingSettings, base);
34703
36018
  }
34704
- if (fs9.existsSync(hooksJsonPath)) {
36019
+ if (fs15.existsSync(hooksJsonPath)) {
34705
36020
  const hooksJson = JSON.parse(
34706
- fs9.readFileSync(hooksJsonPath, "utf8")
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
- fs9.mkdirSync(path10.dirname(settingsPath), { recursive: true });
34719
- fs9.writeFileSync(
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 ${path10.relative(projectDir, path10.join(projectDir, ".gitignore"))}`
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 ?? path10.join(os3.homedir(), ".claude");
34772
- const settingsPath = path10.join(userDir, "settings.json");
34773
- const userBaseSettingsPath = path10.join(
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 (!fs9.existsSync(userBaseSettingsPath)) {
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
- fs9.readFileSync(userBaseSettingsPath, "utf8")
36108
+ fs15.readFileSync(userBaseSettingsPath, "utf8")
34794
36109
  );
34795
- const existingSettings = fs9.existsSync(settingsPath) ? JSON.parse(fs9.readFileSync(settingsPath, "utf8")) : {};
36110
+ const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
34796
36111
  mergeBaseSettingsIntoSettings(existingSettings, userBase);
34797
36112
  if (!opts.dryRun) {
34798
- fs9.mkdirSync(userDir, { recursive: true });
34799
- fs9.writeFileSync(
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 fs10 from "node:fs";
36157
+ import * as fs16 from "node:fs";
34843
36158
  import * as os4 from "node:os";
34844
- import * as path11 from "node:path";
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 = path11.join(projectDir, ".claude", entry.dest);
34874
- if (!fs10.existsSync(abs)) {
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(fs10.readFileSync(abs));
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
- fs10.rmSync(abs);
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 = path11.join(projectDir, ".claude", "settings.json");
34898
- if (fs10.existsSync(settingsPath)) {
36212
+ const settingsPath = path16.join(projectDir, ".claude", "settings.json");
36213
+ if (fs16.existsSync(settingsPath)) {
34899
36214
  const settings = JSON.parse(
34900
- fs10.readFileSync(settingsPath, "utf8")
36215
+ fs16.readFileSync(settingsPath, "utf8")
34901
36216
  );
34902
- const baseSettingsPath = templatesDir ? path11.join(templatesDir, "settings.project.base.json") : null;
34903
- if (baseSettingsPath && fs10.existsSync(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
- fs10.readFileSync(baseSettingsPath, "utf8")
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
- fs10.rmSync(settingsPath);
36228
+ fs16.rmSync(settingsPath);
34914
36229
  } else {
34915
- fs10.writeFileSync(
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 (fs10.existsSync(m)) fs10.rmSync(m);
36249
+ if (fs16.existsSync(m)) fs16.rmSync(m);
34935
36250
  const mid = midManifestPath(projectDir);
34936
- if (fs10.existsSync(mid)) fs10.rmSync(mid);
36251
+ if (fs16.existsSync(mid)) fs16.rmSync(mid);
34937
36252
  const legacy = oldManifestPath(projectDir);
34938
- if (fs10.existsSync(legacy)) fs10.rmSync(legacy);
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 ?? path11.join(os4.homedir(), ".claude");
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 = path11.join(userDir, "settings.json");
34970
- if (fs10.existsSync(settingsPath)) {
36284
+ const settingsPath = path16.join(userDir, "settings.json");
36285
+ if (fs16.existsSync(settingsPath)) {
34971
36286
  const settings = JSON.parse(
34972
- fs10.readFileSync(settingsPath, "utf8")
36287
+ fs16.readFileSync(settingsPath, "utf8")
34973
36288
  );
34974
- const userBaseSettingsPath = templatesDir != null ? path11.join(templatesDir, "settings.user.base.json") : null;
34975
- if (userBaseSettingsPath && fs10.existsSync(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
- fs10.readFileSync(userBaseSettingsPath, "utf8")
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
- fs10.rmSync(settingsPath);
36299
+ fs16.rmSync(settingsPath);
34985
36300
  } else {
34986
- fs10.writeFileSync(
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 (fs10.existsSync(m)) fs10.rmSync(m);
36311
+ if (fs16.existsSync(m)) fs16.rmSync(m);
34997
36312
  const midUser = userMidManifestPath(userDir);
34998
- if (fs10.existsSync(midUser)) fs10.rmSync(midUser);
36313
+ if (fs16.existsSync(midUser)) fs16.rmSync(midUser);
34999
36314
  const oldUser = userOldManifestPath(userDir);
35000
- if (fs10.existsSync(oldUser)) fs10.rmSync(oldUser);
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 = path11.join(projectDir, ".claude", root);
35016
- if (!fs10.existsSync(abs)) continue;
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 (!fs10.existsSync(dir)) return;
35022
- const stat3 = fs10.statSync(dir);
36336
+ if (!fs16.existsSync(dir)) return;
36337
+ const stat3 = fs16.statSync(dir);
35023
36338
  if (!stat3.isDirectory()) return;
35024
- for (const entry of fs10.readdirSync(dir, { withFileTypes: true })) {
36339
+ for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
35025
36340
  if (entry.isDirectory()) {
35026
- pruneLeafFirst(path11.join(dir, entry.name));
36341
+ pruneLeafFirst(path16.join(dir, entry.name));
35027
36342
  }
35028
36343
  }
35029
- const remaining = fs10.readdirSync(dir);
36344
+ const remaining = fs16.readdirSync(dir);
35030
36345
  if (remaining.length === 0) {
35031
- fs10.rmdirSync(dir);
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 fs11 from "node:fs";
35047
- import * as path12 from "node:path";
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 = [path12.join(claudeDir, "hooks", "__test-fixtures__")];
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 = path12.join(claudeDir, scanDir);
35070
- if (!fs11.existsSync(baseDir)) continue;
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 = path12.join(baseDir, entry);
35074
- if (!fs11.lstatSync(absPath).isFile()) continue;
36388
+ const absPath = path17.join(baseDir, entry);
36389
+ if (!fs17.lstatSync(absPath).isFile()) continue;
35075
36390
  if (ignored.some(
35076
- (ig) => absPath.startsWith(ig + path12.sep) || absPath === ig
36391
+ (ig) => absPath.startsWith(ig + path17.sep) || absPath === ig
35077
36392
  )) {
35078
36393
  continue;
35079
36394
  }
35080
- const relPath = path12.join(scanDir, entry).split(path12.sep).join("/");
36395
+ const relPath = path17.join(scanDir, entry).split(path17.sep).join("/");
35081
36396
  claudeSideRels.add(relPath);
35082
- const templatePath = path12.join(templatesDir, relPath);
35083
- if (!fs11.existsSync(templatePath)) {
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 = fs11.readFileSync(absPath);
35090
- const tplBuf = fs11.readFileSync(templatePath);
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 = path12.join(templatesDir, scanDir);
35098
- if (!fs11.existsSync(tplBase)) continue;
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 = path12.join(tplBase, entry);
35102
- if (!fs11.lstatSync(absPath).isFile()) continue;
36416
+ const absPath = path17.join(tplBase, entry);
36417
+ if (!fs17.lstatSync(absPath).isFile()) continue;
35103
36418
  if (isScaffoldFile(entry)) continue;
35104
- const relPath = path12.join(scanDir, entry).split(path12.sep).join("/");
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 && fs11.existsSync(templatesDir);
36452
+ const twinDetectionActive = templatesDir != null && fs17.existsSync(templatesDir);
35138
36453
  const violations = [];
35139
36454
  for (const scanDir of scanDirs) {
35140
- const baseDir = path12.join(claudeDir, scanDir);
35141
- if (!fs11.existsSync(baseDir)) continue;
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 = path12.join(baseDir, entry);
35145
- if (!fs11.lstatSync(absPath).isFile()) continue;
36459
+ const absPath = path17.join(baseDir, entry);
36460
+ if (!fs17.lstatSync(absPath).isFile()) continue;
35146
36461
  if (!isStructuralEntry(scanDir, entry)) continue;
35147
- const ext = path12.extname(entry).toLowerCase();
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 = path12.join(scanDir, entry).split(path12.sep).join("/");
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 = fs11.readFileSync(absPath, "utf8");
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 && fs11.existsSync(path12.join(templatesDir, relPath));
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 && fs11.existsSync(templatesDir)) {
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 = fs11.realpathSync(dir);
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 fs11.readdirSync(dir)) {
35219
- const full = path12.join(dir, name);
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 (fs11.lstatSync(full).isDirectory()) {
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 fs12 from "node:fs";
35292
- import * as path13 from "node:path";
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 = path13.join(projectDir, ".claude");
35298
- if (!fs12.existsSync(claudeDir)) {
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 join40, resolve as resolve6 } from "node:path";
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(join40(absPath, "package.json"), "utf-8");
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 = resolve6(projectDir);
37142
+ const rootDir = resolve11(projectDir);
35828
37143
  let packageManager;
35829
37144
  try {
35830
- const raw = await readFile26(join40(rootDir, "package.json"), "utf-8");
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
- join40(rootDir, ".codebyplan", "server.json")
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
- join40(rootDir, ".codebyplan", "git.json")
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
- join40(rootDir, ".codebyplan", "shipment.json")
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 = join40(rootDir, "AGENTS.md");
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 = join40(rootDir, ".claude", "generated");
37285
+ const outputDir = join45(rootDir, ".claude", "generated");
35971
37286
  await mkdir12(outputDir, { recursive: true });
35972
- const outputPath = join40(outputDir, "structure.md");
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 = join40(rootDir, "AGENTS.md");
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 join41, resolve as resolve7, relative as relative8 } from "node:path";
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
- join41(app.absPath, "package.json")
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 = resolve7(projectDir);
37419
+ const rootDir = resolve12(projectDir);
36105
37420
  const rootPkgJson = await readJsonFile5(
36106
- join41(rootDir, "package.json")
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 = join41(unit.absPath, "README.md");
36116
- const relPath = unit.isRoot ? "README.md" : join41(relative8(rootDir, unit.absPath), "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 existsSync15 } from "node:fs";
36307
- import { join as join42, resolve as resolve8, dirname as dirname12, sep as sep3 } from "node:path";
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 resolve8(absPath).replace(/[/\\]/g, "-");
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 join42(homedir8(), ".claude", "projects", encoded, "memory");
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 = join42(dir, filename);
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 = resolve8(opts.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 = resolve8(join42(projectDir, relPath));
36474
- const targetFile = join42(targetDir, "CLAUDE.md");
36475
- if (!targetDir.startsWith(resolve8(projectDir) + sep3)) {
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 (resolve8(entry.source_path).startsWith(
36494
- resolve8(plan.auto_memory_dir) + sep3
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 (resolve8(entry.source_path).startsWith(resolve8(plan.auto_memory_dir) + sep3)) {
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 = join42(projectDir, ".claude", "CLAUDE.md");
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(dirname12(rootClaudeMd), { recursive: true });
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 (!resolve8(entry.source_path).startsWith(
36550
- resolve8(plan.auto_memory_dir) + sep3
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 = join42(plan.auto_memory_dir, "MEMORY.md");
36569
- const safeRmdirBase = join42(homedir8(), ".claude", "projects");
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 (resolve8(plan.auto_memory_dir).startsWith(safeRmdirBase + sep3)) {
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 (!resolve8(plan.auto_memory_dir).startsWith(safeRmdirBase + sep3)) {
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(resolve8(applyFile), "utf-8");
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 (!existsSync15(autoMemoryDir)) {
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 readdirSync6, readFileSync as readFileSync14, existsSync as existsSync16 } from "node:fs";
36693
- import { join as join43, basename as basename2 } from "node:path";
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 = readFileSync14(filePath, "utf-8");
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 = readFileSync14(filePath, "utf-8");
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 = join43(templatesDir, "agents");
36771
- if (existsSync16(agentsDir)) {
36772
- const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md")).sort();
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(join43(agentsDir, f)));
38089
+ entries.push(auditAgent(join48(agentsDir, f)));
36775
38090
  }
36776
38091
  }
36777
- const skillsDir = join43(templatesDir, "skills");
36778
- if (existsSync16(skillsDir)) {
36779
- const skillDirs = readdirSync6(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
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 (existsSync16(join43(skillsDir, dir, "PROVENANCE.md"))) continue;
36782
- const skillMd = join43(skillsDir, dir, "SKILL.md");
36783
- if (existsSync16(skillMd)) {
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 printHelp3() {
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
- printHelp3();
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 fs13 from "node:fs";
37041
- import * as path14 from "node:path";
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 mkdirSync7 = deps.mkdirSyncFn ?? ((dir, opts) => fs13.mkdirSync(dir, opts));
37049
- const writeFileSync9 = deps.writeFileSyncFn ?? ((filePath2, content) => fs13.writeFileSync(filePath2, content));
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 = path14.join(cwd, "supabase", "migrations");
38377
+ const migrationsDir = path19.join(cwd, "supabase", "migrations");
37063
38378
  const filename = `${stamp}_${slug}.sql`;
37064
- const filePath = path14.join(migrationsDir, filename);
37065
- mkdirSync7(migrationsDir, { recursive: true });
37066
- writeFileSync9(filePath, "");
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((resolve11) => setTimeout(resolve11, ms)));
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 path15 from "node:path";
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 = path15.basename(repoRoot);
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 [path16, owners] of pathOwners) {
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 "${path16}" appears in multiple waves: ${owners.join(", ")}.`,
37743
- detail: { path: path16, waves: owners }
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((resolve11, reject) => {
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
- () => resolve11(Buffer.concat(chunks).toString("utf-8"))
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 dirname13, basename as basename4, join as join45 } from "node:path";
39251
+ import { dirname as dirname15, basename as basename4, join as join50 } from "node:path";
37937
39252
  function computeWorktreePath(cwd, checkpointNumber) {
37938
- const parent = dirname13(cwd);
39253
+ const parent = dirname15(cwd);
37939
39254
  const base = basename4(cwd);
37940
39255
  const nnn = String(checkpointNumber).padStart(3, "0");
37941
- return join45(parent, `${base}-CHK-${nnn}`);
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 join46, basename as basename5 } from "node:path";
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(join46(destPath, ".codebyplan"), { recursive: true });
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(join46(srcCwd, stub), "utf-8");
37999
- await writeFile23(join46(destPath, stub), content, "utf-8");
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
- join46(srcCwd, ".codebyplan", "repo.json"),
39320
+ join51(srcCwd, ".codebyplan", "repo.json"),
38006
39321
  "utf-8"
38007
39322
  );
38008
39323
  await writeFile23(
38009
- join46(destPath, ".codebyplan", "repo.json"),
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, path16) {
39331
+ async function defaultRegisterWorktree(repoId, name, path21) {
38017
39332
  const res = await apiPost("/worktrees", {
38018
39333
  repo_id: repoId,
38019
39334
  name,
38020
- path: path16,
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((resolve11) => setTimeout(resolve11, ms)));
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 join47 } from "node:path";
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, path16) {
39497
+ async function defaultRegisterWorktree2(repoId, name, path21) {
38183
39498
  const res = await apiPost("/worktrees", {
38184
39499
  repo_id: repoId,
38185
39500
  name,
38186
- path: path16,
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 ?? join47(cwd, "..", name);
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 resolve9 } from "node:path";
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 = resolve9(cwd, ".codebyplan", "e2e.json");
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 execSync9 } from "node:child_process";
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 = execSync9("git rev-parse --show-toplevel", {
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 printHelp4() {
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
- printHelp4();
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 readFileSync15 } from "node:fs";
39017
- import { resolve as resolve10 } from "node:path";
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 = resolve10(process.cwd(), ".env.local");
39022
- const content = readFileSync15(envPath, "utf-8");
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