codebyplan 1.13.64 → 1.13.65
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 +923 -443
- package/package.json +1 -1
- package/templates/github-workflows/ci.yml +5 -0
- package/templates/hooks/cbp-session-id-stamp.sh +67 -0
- package/templates/hooks/cbp-test-hooks.sh +105 -0
- package/templates/rules/handoff-file-convention.md +65 -0
- package/templates/settings.project.base.json +17 -1
- package/templates/skills/cbp-checkpoint-complete/SKILL.md +32 -0
- package/templates/skills/cbp-clear-continue/SKILL.md +23 -1
- package/templates/skills/cbp-clear-prep/SKILL.md +22 -1
- package/templates/skills/cbp-finalize/SKILL.md +36 -0
- package/templates/skills/cbp-session-end/SKILL.md +23 -25
- package/templates/skills/cbp-session-start/SKILL.md +24 -2
- package/templates/skills/cbp-standalone-task-complete/SKILL.md +32 -0
package/dist/cli.js
CHANGED
|
@@ -48,7 +48,7 @@ var VERSION, PACKAGE_NAME;
|
|
|
48
48
|
var init_version = __esm({
|
|
49
49
|
"src/lib/version.ts"() {
|
|
50
50
|
"use strict";
|
|
51
|
-
VERSION = "1.13.
|
|
51
|
+
VERSION = "1.13.65";
|
|
52
52
|
PACKAGE_NAME = "codebyplan";
|
|
53
53
|
}
|
|
54
54
|
});
|
|
@@ -303,6 +303,7 @@ var init_gitignore_block = __esm({
|
|
|
303
303
|
".codebyplan/state/",
|
|
304
304
|
".codebyplan/clear/",
|
|
305
305
|
".codebyplan/todo/",
|
|
306
|
+
"!.codebyplan/handoff/",
|
|
306
307
|
".codebyplan/claude-status.local.json",
|
|
307
308
|
".codebyplan.local.json"
|
|
308
309
|
];
|
|
@@ -314,8 +315,8 @@ var init_gitignore_block = __esm({
|
|
|
314
315
|
// src/lib/worktree.ts
|
|
315
316
|
import { mkdir as mkdir2, writeFile as writeFile3, readFile as readFile3 } from "node:fs/promises";
|
|
316
317
|
import { join as join3 } from "node:path";
|
|
317
|
-
function defaultExists(
|
|
318
|
-
return readFile3(
|
|
318
|
+
function defaultExists(path25) {
|
|
319
|
+
return readFile3(path25, "utf-8").then(() => true).catch(() => false);
|
|
319
320
|
}
|
|
320
321
|
async function writeRepoJson(codebyplanDir, selectedRepo, deps) {
|
|
321
322
|
const repoJson = {
|
|
@@ -432,9 +433,9 @@ var init_worktree = __esm({
|
|
|
432
433
|
init_statusline_config();
|
|
433
434
|
init_gitignore_block();
|
|
434
435
|
defaultFsDeps = {
|
|
435
|
-
mkdir: (
|
|
436
|
-
writeFile: (
|
|
437
|
-
readFile: (
|
|
436
|
+
mkdir: (path25, opts) => mkdir2(path25, opts).then(() => void 0),
|
|
437
|
+
writeFile: (path25, data, encoding) => writeFile3(path25, data, encoding),
|
|
438
|
+
readFile: (path25, encoding) => readFile3(path25, encoding),
|
|
438
439
|
exists: defaultExists
|
|
439
440
|
};
|
|
440
441
|
}
|
|
@@ -502,12 +503,12 @@ async function readFallback(filename) {
|
|
|
502
503
|
}
|
|
503
504
|
}
|
|
504
505
|
async function writeFallback(filename, data) {
|
|
505
|
-
const
|
|
506
|
-
await mkdir3(dirname(
|
|
507
|
-
await writeFile4(
|
|
506
|
+
const path25 = fallbackFile(filename);
|
|
507
|
+
await mkdir3(dirname(path25), { recursive: true });
|
|
508
|
+
await writeFile4(path25, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
508
509
|
if (platform() !== "win32") {
|
|
509
510
|
try {
|
|
510
|
-
await chmod(
|
|
511
|
+
await chmod(path25, 384);
|
|
511
512
|
} catch {
|
|
512
513
|
}
|
|
513
514
|
}
|
|
@@ -3140,9 +3141,9 @@ import { createInterface } from "node:readline/promises";
|
|
|
3140
3141
|
function getConfigPath(scope) {
|
|
3141
3142
|
return scope === "user" ? join12(homedir4(), ".claude.json") : join12(process.cwd(), ".mcp.json");
|
|
3142
3143
|
}
|
|
3143
|
-
async function readConfig(
|
|
3144
|
+
async function readConfig(path25) {
|
|
3144
3145
|
try {
|
|
3145
|
-
const raw = await readFile9(
|
|
3146
|
+
const raw = await readFile9(path25, "utf-8");
|
|
3146
3147
|
const parsed = JSON.parse(raw);
|
|
3147
3148
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3148
3149
|
return parsed;
|
|
@@ -3551,9 +3552,9 @@ import { join as join13 } from "node:path";
|
|
|
3551
3552
|
function configPaths() {
|
|
3552
3553
|
return [join13(homedir5(), ".claude.json"), join13(process.cwd(), ".mcp.json")];
|
|
3553
3554
|
}
|
|
3554
|
-
async function readConfig2(
|
|
3555
|
+
async function readConfig2(path25) {
|
|
3555
3556
|
try {
|
|
3556
|
-
const raw = await readFile10(
|
|
3557
|
+
const raw = await readFile10(path25, "utf-8");
|
|
3557
3558
|
const parsed = JSON.parse(raw);
|
|
3558
3559
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3559
3560
|
return parsed;
|
|
@@ -3567,7 +3568,7 @@ function entryHasLegacyApiKey(entry) {
|
|
|
3567
3568
|
if (!entry || !entry.headers) return false;
|
|
3568
3569
|
return "x-api-key" in entry.headers;
|
|
3569
3570
|
}
|
|
3570
|
-
async function rewriteConfig(
|
|
3571
|
+
async function rewriteConfig(path25, config, newUrl) {
|
|
3571
3572
|
const servers = config.mcpServers;
|
|
3572
3573
|
if (!servers) return false;
|
|
3573
3574
|
const entry = servers.codebyplan;
|
|
@@ -3575,7 +3576,7 @@ async function rewriteConfig(path23, config, newUrl) {
|
|
|
3575
3576
|
if (!entryHasLegacyApiKey(entry) && entry.url === newUrl && entry.type === "http")
|
|
3576
3577
|
return false;
|
|
3577
3578
|
servers.codebyplan = { type: "http", url: newUrl };
|
|
3578
|
-
await writeFile8(
|
|
3579
|
+
await writeFile8(path25, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3579
3580
|
return true;
|
|
3580
3581
|
}
|
|
3581
3582
|
async function runUpgradeAuth() {
|
|
@@ -3583,12 +3584,12 @@ async function runUpgradeAuth() {
|
|
|
3583
3584
|
await runLogin();
|
|
3584
3585
|
const newUrl = mcpEndpoint();
|
|
3585
3586
|
let migrated = 0;
|
|
3586
|
-
for (const
|
|
3587
|
-
const config = await readConfig2(
|
|
3587
|
+
for (const path25 of configPaths()) {
|
|
3588
|
+
const config = await readConfig2(path25);
|
|
3588
3589
|
if (!config) continue;
|
|
3589
|
-
const changed = await rewriteConfig(
|
|
3590
|
+
const changed = await rewriteConfig(path25, config, newUrl);
|
|
3590
3591
|
if (changed) {
|
|
3591
|
-
console.log(` Updated ${
|
|
3592
|
+
console.log(` Updated ${path25}`);
|
|
3592
3593
|
migrated++;
|
|
3593
3594
|
}
|
|
3594
3595
|
}
|
|
@@ -3731,8 +3732,8 @@ async function validateConnectivity() {
|
|
|
3731
3732
|
);
|
|
3732
3733
|
}
|
|
3733
3734
|
}
|
|
3734
|
-
function buildUrl(
|
|
3735
|
-
const url = new URL(`${baseUrl()}/api${
|
|
3735
|
+
function buildUrl(path25, params) {
|
|
3736
|
+
const url = new URL(`${baseUrl()}/api${path25}`);
|
|
3736
3737
|
if (params) {
|
|
3737
3738
|
for (const [key, value] of Object.entries(params)) {
|
|
3738
3739
|
if (value !== void 0) {
|
|
@@ -3751,8 +3752,8 @@ function isRetryable(err) {
|
|
|
3751
3752
|
function delay(ms) {
|
|
3752
3753
|
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
3753
3754
|
}
|
|
3754
|
-
async function request(method,
|
|
3755
|
-
const url = buildUrl(
|
|
3755
|
+
async function request(method, path25, options) {
|
|
3756
|
+
const url = buildUrl(path25, options?.params);
|
|
3756
3757
|
const auth = await getAuthHeaders();
|
|
3757
3758
|
let lastError;
|
|
3758
3759
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
@@ -3772,7 +3773,7 @@ async function request(method, path23, options) {
|
|
|
3772
3773
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
3773
3774
|
});
|
|
3774
3775
|
if (!res.ok) {
|
|
3775
|
-
let message = `API ${method} ${
|
|
3776
|
+
let message = `API ${method} ${path25} failed with status ${res.status}`;
|
|
3776
3777
|
let code;
|
|
3777
3778
|
try {
|
|
3778
3779
|
const body = await res.json();
|
|
@@ -3806,20 +3807,20 @@ async function request(method, path23, options) {
|
|
|
3806
3807
|
}
|
|
3807
3808
|
throw lastError;
|
|
3808
3809
|
}
|
|
3809
|
-
async function apiGet(
|
|
3810
|
-
return request("GET",
|
|
3810
|
+
async function apiGet(path25, params) {
|
|
3811
|
+
return request("GET", path25, { params });
|
|
3811
3812
|
}
|
|
3812
|
-
async function apiPost(
|
|
3813
|
-
return request("POST",
|
|
3813
|
+
async function apiPost(path25, body) {
|
|
3814
|
+
return request("POST", path25, { body });
|
|
3814
3815
|
}
|
|
3815
|
-
async function apiPut(
|
|
3816
|
-
return request("PUT",
|
|
3816
|
+
async function apiPut(path25, body) {
|
|
3817
|
+
return request("PUT", path25, { body });
|
|
3817
3818
|
}
|
|
3818
|
-
async function apiPatch(
|
|
3819
|
-
return request("PATCH",
|
|
3819
|
+
async function apiPatch(path25, body) {
|
|
3820
|
+
return request("PATCH", path25, { body });
|
|
3820
3821
|
}
|
|
3821
|
-
async function apiDelete(
|
|
3822
|
-
await request("DELETE",
|
|
3822
|
+
async function apiDelete(path25, params) {
|
|
3823
|
+
await request("DELETE", path25, { params });
|
|
3823
3824
|
}
|
|
3824
3825
|
async function callMcpTool(toolName, params) {
|
|
3825
3826
|
const url = mcpEndpoint();
|
|
@@ -5680,13 +5681,13 @@ function __disposeResources(env) {
|
|
|
5680
5681
|
}
|
|
5681
5682
|
return next();
|
|
5682
5683
|
}
|
|
5683
|
-
function __rewriteRelativeImportExtension(
|
|
5684
|
-
if (typeof
|
|
5685
|
-
return
|
|
5684
|
+
function __rewriteRelativeImportExtension(path25, preserveJsx) {
|
|
5685
|
+
if (typeof path25 === "string" && /^\.\.?\//.test(path25)) {
|
|
5686
|
+
return path25.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
5686
5687
|
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
5687
5688
|
});
|
|
5688
5689
|
}
|
|
5689
|
-
return
|
|
5690
|
+
return path25;
|
|
5690
5691
|
}
|
|
5691
5692
|
var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
|
|
5692
5693
|
var init_tslib_es6 = __esm({
|
|
@@ -14324,8 +14325,8 @@ var require_RealtimeChannel = __commonJS({
|
|
|
14324
14325
|
}
|
|
14325
14326
|
/** @internal */
|
|
14326
14327
|
_notThisChannelEvent(event, ref) {
|
|
14327
|
-
const { close, error, leave, join:
|
|
14328
|
-
const events = [close, error, leave,
|
|
14328
|
+
const { close, error, leave, join: join60 } = constants_1.CHANNEL_EVENTS;
|
|
14329
|
+
const events = [close, error, leave, join60];
|
|
14329
14330
|
return ref && events.includes(event) && ref !== this.joinPush.ref;
|
|
14330
14331
|
}
|
|
14331
14332
|
/** @internal */
|
|
@@ -15208,8 +15209,8 @@ var require_main2 = __commonJS({
|
|
|
15208
15209
|
});
|
|
15209
15210
|
|
|
15210
15211
|
// ../../node_modules/.pnpm/iceberg-js@0.8.1/node_modules/iceberg-js/dist/index.mjs
|
|
15211
|
-
function buildUrl2(baseUrl3,
|
|
15212
|
-
const url = new URL(
|
|
15212
|
+
function buildUrl2(baseUrl3, path25, query) {
|
|
15213
|
+
const url = new URL(path25, baseUrl3);
|
|
15213
15214
|
if (query) {
|
|
15214
15215
|
for (const [key, value] of Object.entries(query)) {
|
|
15215
15216
|
if (value !== void 0) {
|
|
@@ -15239,12 +15240,12 @@ function createFetchClient(options) {
|
|
|
15239
15240
|
return {
|
|
15240
15241
|
async request({
|
|
15241
15242
|
method,
|
|
15242
|
-
path:
|
|
15243
|
+
path: path25,
|
|
15243
15244
|
query,
|
|
15244
15245
|
body,
|
|
15245
15246
|
headers
|
|
15246
15247
|
}) {
|
|
15247
|
-
const url = buildUrl2(options.baseUrl,
|
|
15248
|
+
const url = buildUrl2(options.baseUrl, path25, query);
|
|
15248
15249
|
const authHeaders = await buildAuthHeaders(options.auth);
|
|
15249
15250
|
const res = await fetchFn(url, {
|
|
15250
15251
|
method,
|
|
@@ -16142,7 +16143,7 @@ var init_dist3 = __esm({
|
|
|
16142
16143
|
* @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
|
|
16143
16144
|
* @param fileBody The body of the file to be stored in the bucket.
|
|
16144
16145
|
*/
|
|
16145
|
-
async uploadOrUpdate(method,
|
|
16146
|
+
async uploadOrUpdate(method, path25, fileBody, fileOptions) {
|
|
16146
16147
|
var _this = this;
|
|
16147
16148
|
return _this.handleOperation(async () => {
|
|
16148
16149
|
let body;
|
|
@@ -16166,7 +16167,7 @@ var init_dist3 = __esm({
|
|
|
16166
16167
|
if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
|
|
16167
16168
|
}
|
|
16168
16169
|
if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
|
|
16169
|
-
const cleanPath = _this._removeEmptyFolders(
|
|
16170
|
+
const cleanPath = _this._removeEmptyFolders(path25);
|
|
16170
16171
|
const _path = _this._getFinalPath(cleanPath);
|
|
16171
16172
|
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 } : {}));
|
|
16172
16173
|
return {
|
|
@@ -16228,8 +16229,8 @@ var init_dist3 = __esm({
|
|
|
16228
16229
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16229
16230
|
* - 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.
|
|
16230
16231
|
*/
|
|
16231
|
-
async upload(
|
|
16232
|
-
return this.uploadOrUpdate("POST",
|
|
16232
|
+
async upload(path25, fileBody, fileOptions) {
|
|
16233
|
+
return this.uploadOrUpdate("POST", path25, fileBody, fileOptions);
|
|
16233
16234
|
}
|
|
16234
16235
|
/**
|
|
16235
16236
|
* Upload a file with a token generated from `createSignedUploadUrl`.
|
|
@@ -16269,9 +16270,9 @@ var init_dist3 = __esm({
|
|
|
16269
16270
|
* - `objects` table permissions: none
|
|
16270
16271
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16271
16272
|
*/
|
|
16272
|
-
async uploadToSignedUrl(
|
|
16273
|
+
async uploadToSignedUrl(path25, token, fileBody, fileOptions) {
|
|
16273
16274
|
var _this3 = this;
|
|
16274
|
-
const cleanPath = _this3._removeEmptyFolders(
|
|
16275
|
+
const cleanPath = _this3._removeEmptyFolders(path25);
|
|
16275
16276
|
const _path = _this3._getFinalPath(cleanPath);
|
|
16276
16277
|
const url = new URL(_this3.url + `/object/upload/sign/${_path}`);
|
|
16277
16278
|
url.searchParams.set("token", token);
|
|
@@ -16340,10 +16341,10 @@ var init_dist3 = __esm({
|
|
|
16340
16341
|
* - `objects` table permissions: `insert`
|
|
16341
16342
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16342
16343
|
*/
|
|
16343
|
-
async createSignedUploadUrl(
|
|
16344
|
+
async createSignedUploadUrl(path25, options) {
|
|
16344
16345
|
var _this4 = this;
|
|
16345
16346
|
return _this4.handleOperation(async () => {
|
|
16346
|
-
let _path = _this4._getFinalPath(
|
|
16347
|
+
let _path = _this4._getFinalPath(path25);
|
|
16347
16348
|
const headers = _objectSpread22({}, _this4.headers);
|
|
16348
16349
|
if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
|
|
16349
16350
|
const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
|
|
@@ -16352,7 +16353,7 @@ var init_dist3 = __esm({
|
|
|
16352
16353
|
if (!token) throw new StorageError("No token returned by API");
|
|
16353
16354
|
return {
|
|
16354
16355
|
signedUrl: url.toString(),
|
|
16355
|
-
path:
|
|
16356
|
+
path: path25,
|
|
16356
16357
|
token
|
|
16357
16358
|
};
|
|
16358
16359
|
});
|
|
@@ -16412,8 +16413,8 @@ var init_dist3 = __esm({
|
|
|
16412
16413
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16413
16414
|
* - 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.
|
|
16414
16415
|
*/
|
|
16415
|
-
async update(
|
|
16416
|
-
return this.uploadOrUpdate("PUT",
|
|
16416
|
+
async update(path25, fileBody, fileOptions) {
|
|
16417
|
+
return this.uploadOrUpdate("PUT", path25, fileBody, fileOptions);
|
|
16417
16418
|
}
|
|
16418
16419
|
/**
|
|
16419
16420
|
* Moves an existing file to a new path in the same bucket.
|
|
@@ -16564,10 +16565,10 @@ var init_dist3 = __esm({
|
|
|
16564
16565
|
* - `objects` table permissions: `select`
|
|
16565
16566
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16566
16567
|
*/
|
|
16567
|
-
async createSignedUrl(
|
|
16568
|
+
async createSignedUrl(path25, expiresIn, options) {
|
|
16568
16569
|
var _this8 = this;
|
|
16569
16570
|
return _this8.handleOperation(async () => {
|
|
16570
|
-
let _path = _this8._getFinalPath(
|
|
16571
|
+
let _path = _this8._getFinalPath(path25);
|
|
16571
16572
|
const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
|
|
16572
16573
|
let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread22({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
|
|
16573
16574
|
const query = new URLSearchParams();
|
|
@@ -16703,13 +16704,13 @@ var init_dist3 = __esm({
|
|
|
16703
16704
|
* - `objects` table permissions: `select`
|
|
16704
16705
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16705
16706
|
*/
|
|
16706
|
-
download(
|
|
16707
|
+
download(path25, options, parameters) {
|
|
16707
16708
|
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";
|
|
16708
16709
|
const query = new URLSearchParams();
|
|
16709
16710
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
16710
16711
|
if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
|
|
16711
16712
|
const queryString = query.toString();
|
|
16712
|
-
const _path = this._getFinalPath(
|
|
16713
|
+
const _path = this._getFinalPath(path25);
|
|
16713
16714
|
const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
|
|
16714
16715
|
headers: this.headers,
|
|
16715
16716
|
noResolveJson: true
|
|
@@ -16740,9 +16741,9 @@ var init_dist3 = __esm({
|
|
|
16740
16741
|
* }
|
|
16741
16742
|
* ```
|
|
16742
16743
|
*/
|
|
16743
|
-
async info(
|
|
16744
|
+
async info(path25) {
|
|
16744
16745
|
var _this10 = this;
|
|
16745
|
-
const _path = _this10._getFinalPath(
|
|
16746
|
+
const _path = _this10._getFinalPath(path25);
|
|
16746
16747
|
return _this10.handleOperation(async () => {
|
|
16747
16748
|
return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
|
|
16748
16749
|
});
|
|
@@ -16763,9 +16764,9 @@ var init_dist3 = __esm({
|
|
|
16763
16764
|
* .exists('folder/avatar1.png')
|
|
16764
16765
|
* ```
|
|
16765
16766
|
*/
|
|
16766
|
-
async exists(
|
|
16767
|
+
async exists(path25) {
|
|
16767
16768
|
var _this11 = this;
|
|
16768
|
-
const _path = _this11._getFinalPath(
|
|
16769
|
+
const _path = _this11._getFinalPath(path25);
|
|
16769
16770
|
try {
|
|
16770
16771
|
await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
|
|
16771
16772
|
return {
|
|
@@ -16844,8 +16845,8 @@ var init_dist3 = __esm({
|
|
|
16844
16845
|
* - `objects` table permissions: none
|
|
16845
16846
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16846
16847
|
*/
|
|
16847
|
-
getPublicUrl(
|
|
16848
|
-
const _path = this._getFinalPath(
|
|
16848
|
+
getPublicUrl(path25, options) {
|
|
16849
|
+
const _path = this._getFinalPath(path25);
|
|
16849
16850
|
const query = new URLSearchParams();
|
|
16850
16851
|
if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
|
|
16851
16852
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
@@ -16984,10 +16985,10 @@ var init_dist3 = __esm({
|
|
|
16984
16985
|
* - `objects` table permissions: `select`
|
|
16985
16986
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
16986
16987
|
*/
|
|
16987
|
-
async list(
|
|
16988
|
+
async list(path25, options, parameters) {
|
|
16988
16989
|
var _this13 = this;
|
|
16989
16990
|
return _this13.handleOperation(async () => {
|
|
16990
|
-
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix:
|
|
16991
|
+
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path25 || "" });
|
|
16991
16992
|
return await post(_this13.fetch, `${_this13.url}/object/list/${_this13.bucketId}`, body, { headers: _this13.headers }, parameters);
|
|
16992
16993
|
});
|
|
16993
16994
|
}
|
|
@@ -17052,11 +17053,11 @@ var init_dist3 = __esm({
|
|
|
17052
17053
|
if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
|
|
17053
17054
|
return btoa(data);
|
|
17054
17055
|
}
|
|
17055
|
-
_getFinalPath(
|
|
17056
|
-
return `${this.bucketId}/${
|
|
17056
|
+
_getFinalPath(path25) {
|
|
17057
|
+
return `${this.bucketId}/${path25.replace(/^\/+/, "")}`;
|
|
17057
17058
|
}
|
|
17058
|
-
_removeEmptyFolders(
|
|
17059
|
-
return
|
|
17059
|
+
_removeEmptyFolders(path25) {
|
|
17060
|
+
return path25.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
|
|
17060
17061
|
}
|
|
17061
17062
|
/** Modifies the `query`, appending values the from `transform` */
|
|
17062
17063
|
applyTransformOptsToQuery(query, transform) {
|
|
@@ -27774,8 +27775,8 @@ var init_watch = __esm({
|
|
|
27774
27775
|
function isConflict(err) {
|
|
27775
27776
|
return err instanceof BackendError && err.status === 409;
|
|
27776
27777
|
}
|
|
27777
|
-
async function backendRequest(method,
|
|
27778
|
-
const url = `${getBackendBase()}${
|
|
27778
|
+
async function backendRequest(method, path25, body) {
|
|
27779
|
+
const url = `${getBackendBase()}${path25}`;
|
|
27779
27780
|
const auth = await getAuthHeaders();
|
|
27780
27781
|
const res = await fetch(url, {
|
|
27781
27782
|
method,
|
|
@@ -27787,7 +27788,7 @@ async function backendRequest(method, path23, body) {
|
|
|
27787
27788
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
27788
27789
|
});
|
|
27789
27790
|
if (!res.ok) {
|
|
27790
|
-
let message = `Backend ${method} ${
|
|
27791
|
+
let message = `Backend ${method} ${path25} failed with status ${res.status}`;
|
|
27791
27792
|
try {
|
|
27792
27793
|
const errBody = await res.json();
|
|
27793
27794
|
const msg = typeof errBody.message === "string" ? errBody.message : typeof errBody.error === "string" ? errBody.error : void 0;
|
|
@@ -27801,11 +27802,11 @@ async function backendRequest(method, path23, body) {
|
|
|
27801
27802
|
}
|
|
27802
27803
|
return res.json();
|
|
27803
27804
|
}
|
|
27804
|
-
async function apiBackendPost(
|
|
27805
|
-
return backendRequest("POST",
|
|
27805
|
+
async function apiBackendPost(path25, body) {
|
|
27806
|
+
return backendRequest("POST", path25, body);
|
|
27806
27807
|
}
|
|
27807
|
-
async function apiBackendPatch(
|
|
27808
|
-
return backendRequest("PATCH",
|
|
27808
|
+
async function apiBackendPatch(path25, body) {
|
|
27809
|
+
return backendRequest("PATCH", path25, body);
|
|
27809
27810
|
}
|
|
27810
27811
|
var REQUEST_TIMEOUT_MS2, BackendError;
|
|
27811
27812
|
var init_state_client = __esm({
|
|
@@ -28081,8 +28082,8 @@ ${taskRows}
|
|
|
28081
28082
|
for (const task of data.tasks) {
|
|
28082
28083
|
if (Array.isArray(task.files_changed)) {
|
|
28083
28084
|
for (const f of task.files_changed) {
|
|
28084
|
-
const
|
|
28085
|
-
if (
|
|
28085
|
+
const path25 = typeof f === "string" ? f : f?.path;
|
|
28086
|
+
if (path25) allFiles.add(path25);
|
|
28086
28087
|
}
|
|
28087
28088
|
}
|
|
28088
28089
|
}
|
|
@@ -30690,7 +30691,7 @@ __export(start_exports, {
|
|
|
30690
30691
|
runSessionStartCli: () => runSessionStartCli
|
|
30691
30692
|
});
|
|
30692
30693
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
30693
|
-
import { dirname as dirname7 } from "node:path";
|
|
30694
|
+
import { dirname as dirname7, join as join24 } from "node:path";
|
|
30694
30695
|
async function updateCursorHashLocal(repoRoot, entityId, row) {
|
|
30695
30696
|
const cursor = await readCursor(repoRoot);
|
|
30696
30697
|
if (!cursor) return;
|
|
@@ -30738,7 +30739,7 @@ async function defaultUpdateStateActivate(repoId, repoRoot) {
|
|
|
30738
30739
|
);
|
|
30739
30740
|
}
|
|
30740
30741
|
}
|
|
30741
|
-
function buildCreateLogBody(repoId, now = /* @__PURE__ */ new Date()) {
|
|
30742
|
+
function buildCreateLogBody(repoId, now = /* @__PURE__ */ new Date(), claudeSessionId) {
|
|
30742
30743
|
const session_date = now.toISOString().slice(0, 10);
|
|
30743
30744
|
const jan1 = Date.UTC(now.getUTCFullYear(), 0, 1);
|
|
30744
30745
|
const day_number = Math.floor((now.getTime() - jan1) / 864e5) + 1;
|
|
@@ -30747,11 +30748,28 @@ function buildCreateLogBody(repoId, now = /* @__PURE__ */ new Date()) {
|
|
|
30747
30748
|
session_date,
|
|
30748
30749
|
day_number,
|
|
30749
30750
|
started_at: now.toISOString(),
|
|
30750
|
-
|
|
30751
|
+
...claudeSessionId != null ? { claude_session_id: claudeSessionId } : {}
|
|
30751
30752
|
};
|
|
30752
30753
|
}
|
|
30753
30754
|
async function defaultCreateLog(repoId, repoRoot) {
|
|
30754
|
-
|
|
30755
|
+
let claudeSessionId = null;
|
|
30756
|
+
try {
|
|
30757
|
+
const sessionIdFile = join24(
|
|
30758
|
+
repoRoot,
|
|
30759
|
+
".codebyplan",
|
|
30760
|
+
"state",
|
|
30761
|
+
"session",
|
|
30762
|
+
"session-id.json"
|
|
30763
|
+
);
|
|
30764
|
+
const raw = await readEntityFile(
|
|
30765
|
+
sessionIdFile
|
|
30766
|
+
);
|
|
30767
|
+
if (raw?.claude_session_id && typeof raw.claude_session_id === "string") {
|
|
30768
|
+
claudeSessionId = raw.claude_session_id;
|
|
30769
|
+
}
|
|
30770
|
+
} catch {
|
|
30771
|
+
}
|
|
30772
|
+
const body = buildCreateLogBody(repoId, /* @__PURE__ */ new Date(), claudeSessionId);
|
|
30755
30773
|
try {
|
|
30756
30774
|
const created = await apiBackendPost(new URL(backendSessionLogsEndpoint()).pathname, body);
|
|
30757
30775
|
const sessionLog = created.session_log ?? created;
|
|
@@ -31356,9 +31374,464 @@ var init_session2 = __esm({
|
|
|
31356
31374
|
}
|
|
31357
31375
|
});
|
|
31358
31376
|
|
|
31377
|
+
// src/lib/handoff-file.ts
|
|
31378
|
+
import * as path9 from "node:path";
|
|
31379
|
+
function handoffPath(projectDir, level, opts = {}) {
|
|
31380
|
+
const base = path9.join(projectDir, ".codebyplan", "handoff");
|
|
31381
|
+
switch (level) {
|
|
31382
|
+
case "repo":
|
|
31383
|
+
return path9.join(base, "repo.md");
|
|
31384
|
+
case "checkpoint": {
|
|
31385
|
+
if (opts.checkpoint == null) {
|
|
31386
|
+
throw new Error(
|
|
31387
|
+
'handoffPath: opts.checkpoint is required for level "checkpoint"'
|
|
31388
|
+
);
|
|
31389
|
+
}
|
|
31390
|
+
const n = String(opts.checkpoint).padStart(3, "0");
|
|
31391
|
+
return path9.join(base, "checkpoint", `${n}.md`);
|
|
31392
|
+
}
|
|
31393
|
+
case "task": {
|
|
31394
|
+
if (opts.checkpoint == null) {
|
|
31395
|
+
throw new Error(
|
|
31396
|
+
'handoffPath: opts.checkpoint is required for level "task"'
|
|
31397
|
+
);
|
|
31398
|
+
}
|
|
31399
|
+
if (opts.task == null) {
|
|
31400
|
+
throw new Error('handoffPath: opts.task is required for level "task"');
|
|
31401
|
+
}
|
|
31402
|
+
const n = String(opts.checkpoint).padStart(3, "0");
|
|
31403
|
+
return path9.join(base, "task", `${n}-${opts.task}.md`);
|
|
31404
|
+
}
|
|
31405
|
+
case "standalone": {
|
|
31406
|
+
if (opts.number == null) {
|
|
31407
|
+
throw new Error(
|
|
31408
|
+
'handoffPath: opts.number is required for level "standalone"'
|
|
31409
|
+
);
|
|
31410
|
+
}
|
|
31411
|
+
return path9.join(base, "standalone", `${opts.number}.md`);
|
|
31412
|
+
}
|
|
31413
|
+
}
|
|
31414
|
+
}
|
|
31415
|
+
function isHandoffEmpty(content) {
|
|
31416
|
+
if (content == null) return true;
|
|
31417
|
+
return content.trim() === "";
|
|
31418
|
+
}
|
|
31419
|
+
function readHandoffSection(fileContent, sectionLabel) {
|
|
31420
|
+
const heading = `## ${sectionLabel}`;
|
|
31421
|
+
const lines = fileContent.split("\n");
|
|
31422
|
+
const startIdx = lines.findIndex((l) => l.trim() === heading);
|
|
31423
|
+
if (startIdx === -1) return null;
|
|
31424
|
+
const bodyLines = [];
|
|
31425
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
31426
|
+
const line = lines[i];
|
|
31427
|
+
if (line.startsWith("## ")) break;
|
|
31428
|
+
bodyLines.push(line);
|
|
31429
|
+
}
|
|
31430
|
+
let start = 0;
|
|
31431
|
+
while (start < bodyLines.length && (bodyLines[start] ?? "").trim() === "") {
|
|
31432
|
+
start++;
|
|
31433
|
+
}
|
|
31434
|
+
let end = bodyLines.length - 1;
|
|
31435
|
+
while (end >= start && (bodyLines[end] ?? "").trim() === "") {
|
|
31436
|
+
end--;
|
|
31437
|
+
}
|
|
31438
|
+
const body = bodyLines.slice(start, end + 1).join("\n");
|
|
31439
|
+
return body.trim() === "" ? null : body;
|
|
31440
|
+
}
|
|
31441
|
+
function replaceHandoffSection(fileContent, sectionLabel, body) {
|
|
31442
|
+
if (isHandoffEmpty(body)) {
|
|
31443
|
+
return removeHandoffSection(fileContent, sectionLabel);
|
|
31444
|
+
}
|
|
31445
|
+
const heading = `## ${sectionLabel}`;
|
|
31446
|
+
const lines = fileContent.split("\n");
|
|
31447
|
+
const startIdx = lines.findIndex((l) => l.trim() === heading);
|
|
31448
|
+
const newSection = [heading, "", body.trim(), ""].join("\n");
|
|
31449
|
+
if (startIdx === -1) {
|
|
31450
|
+
const trimmed = fileContent.trimEnd();
|
|
31451
|
+
const separator = trimmed.length > 0 ? "\n\n" : "";
|
|
31452
|
+
return trimmed + separator + newSection;
|
|
31453
|
+
}
|
|
31454
|
+
let endIdx = lines.length;
|
|
31455
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
31456
|
+
if ((lines[i] ?? "").startsWith("## ")) {
|
|
31457
|
+
endIdx = i;
|
|
31458
|
+
break;
|
|
31459
|
+
}
|
|
31460
|
+
}
|
|
31461
|
+
const before = lines.slice(0, startIdx).join("\n");
|
|
31462
|
+
const after = lines.slice(endIdx).join("\n");
|
|
31463
|
+
const parts = [];
|
|
31464
|
+
if (before.trimEnd().length > 0) parts.push(before.trimEnd());
|
|
31465
|
+
parts.push(newSection.trimEnd());
|
|
31466
|
+
if (after.trimStart().length > 0) parts.push(after.trimStart());
|
|
31467
|
+
return parts.join("\n\n") + "\n";
|
|
31468
|
+
}
|
|
31469
|
+
function removeHandoffSection(fileContent, sectionLabel) {
|
|
31470
|
+
const heading = `## ${sectionLabel}`;
|
|
31471
|
+
const lines = fileContent.split("\n");
|
|
31472
|
+
const startIdx = lines.findIndex((l) => l.trim() === heading);
|
|
31473
|
+
if (startIdx === -1) return fileContent;
|
|
31474
|
+
let endIdx = lines.length;
|
|
31475
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
31476
|
+
if ((lines[i] ?? "").startsWith("## ")) {
|
|
31477
|
+
endIdx = i;
|
|
31478
|
+
break;
|
|
31479
|
+
}
|
|
31480
|
+
}
|
|
31481
|
+
const before = lines.slice(0, startIdx);
|
|
31482
|
+
const after = lines.slice(endIdx);
|
|
31483
|
+
while (before.length > 0 && (before[before.length - 1] ?? "").trim() === "") {
|
|
31484
|
+
before.pop();
|
|
31485
|
+
}
|
|
31486
|
+
while (after.length > 0 && (after[0] ?? "").trim() === "") {
|
|
31487
|
+
after.shift();
|
|
31488
|
+
}
|
|
31489
|
+
if (before.length === 0 && after.length === 0) return "";
|
|
31490
|
+
const parts = [];
|
|
31491
|
+
if (before.length > 0) parts.push(before.join("\n"));
|
|
31492
|
+
if (after.length > 0) parts.push(after.join("\n"));
|
|
31493
|
+
return parts.join("\n\n") + (fileContent.endsWith("\n") ? "\n" : "");
|
|
31494
|
+
}
|
|
31495
|
+
var HANDOFF_LEVELS;
|
|
31496
|
+
var init_handoff_file = __esm({
|
|
31497
|
+
"src/lib/handoff-file.ts"() {
|
|
31498
|
+
"use strict";
|
|
31499
|
+
HANDOFF_LEVELS = [
|
|
31500
|
+
"repo",
|
|
31501
|
+
"checkpoint",
|
|
31502
|
+
"task",
|
|
31503
|
+
"standalone"
|
|
31504
|
+
];
|
|
31505
|
+
}
|
|
31506
|
+
});
|
|
31507
|
+
|
|
31508
|
+
// src/cli/handoff.ts
|
|
31509
|
+
var handoff_exports = {};
|
|
31510
|
+
__export(handoff_exports, {
|
|
31511
|
+
runHandoffCommand: () => runHandoffCommand
|
|
31512
|
+
});
|
|
31513
|
+
import { readFile as readFile15, writeFile as writeFile12, mkdir as mkdir7, unlink as unlink5, readdir as readdir4 } from "node:fs/promises";
|
|
31514
|
+
import * as path10 from "node:path";
|
|
31515
|
+
async function resolveWorktreeLabel(repoRoot) {
|
|
31516
|
+
let branch = "";
|
|
31517
|
+
try {
|
|
31518
|
+
branch = getCurrentBranch(repoRoot);
|
|
31519
|
+
} catch {
|
|
31520
|
+
}
|
|
31521
|
+
if (branch) {
|
|
31522
|
+
try {
|
|
31523
|
+
const worktreesPath = path10.join(
|
|
31524
|
+
repoRoot,
|
|
31525
|
+
".codebyplan",
|
|
31526
|
+
"state",
|
|
31527
|
+
"worktrees.json"
|
|
31528
|
+
);
|
|
31529
|
+
const raw = await readFile15(worktreesPath, "utf-8");
|
|
31530
|
+
const parsed = JSON.parse(raw);
|
|
31531
|
+
const entries = Array.isArray(parsed) ? parsed : parsed.data ?? [];
|
|
31532
|
+
const match = entries.find((e) => e.branch === branch);
|
|
31533
|
+
if (match?.name) return match.name;
|
|
31534
|
+
} catch {
|
|
31535
|
+
}
|
|
31536
|
+
return branch.replace(/\//g, "-");
|
|
31537
|
+
}
|
|
31538
|
+
return "default";
|
|
31539
|
+
}
|
|
31540
|
+
async function readHandoffFile(filePath) {
|
|
31541
|
+
try {
|
|
31542
|
+
return await readFile15(filePath, "utf-8");
|
|
31543
|
+
} catch {
|
|
31544
|
+
return null;
|
|
31545
|
+
}
|
|
31546
|
+
}
|
|
31547
|
+
async function writeHandoffFile(filePath, content) {
|
|
31548
|
+
await mkdir7(path10.dirname(filePath), { recursive: true });
|
|
31549
|
+
await writeFile12(filePath, content, "utf-8");
|
|
31550
|
+
}
|
|
31551
|
+
async function deleteHandoffFile(filePath) {
|
|
31552
|
+
try {
|
|
31553
|
+
await unlink5(filePath);
|
|
31554
|
+
} catch {
|
|
31555
|
+
}
|
|
31556
|
+
}
|
|
31557
|
+
function parseLevel(flags) {
|
|
31558
|
+
const raw = flags["level"];
|
|
31559
|
+
if (!raw) {
|
|
31560
|
+
process.stderr.write("handoff: --level <level> is required\n");
|
|
31561
|
+
process.exit(1);
|
|
31562
|
+
}
|
|
31563
|
+
if (!HANDOFF_LEVELS.includes(raw)) {
|
|
31564
|
+
process.stderr.write(
|
|
31565
|
+
`handoff: unknown level "${raw}". Valid levels: ${HANDOFF_LEVELS.join(", ")}
|
|
31566
|
+
`
|
|
31567
|
+
);
|
|
31568
|
+
process.exit(1);
|
|
31569
|
+
}
|
|
31570
|
+
return raw;
|
|
31571
|
+
}
|
|
31572
|
+
function parsePathOpts(flags) {
|
|
31573
|
+
const opts = {};
|
|
31574
|
+
if (flags["number"] !== void 0) opts.number = Number(flags["number"]);
|
|
31575
|
+
if (flags["task"] !== void 0) opts.task = Number(flags["task"]);
|
|
31576
|
+
if (flags["checkpoint"] !== void 0)
|
|
31577
|
+
opts.checkpoint = Number(flags["checkpoint"]);
|
|
31578
|
+
if (opts.checkpoint == null && flags["number"] !== void 0) {
|
|
31579
|
+
opts.checkpoint = Number(flags["number"]);
|
|
31580
|
+
}
|
|
31581
|
+
return opts;
|
|
31582
|
+
}
|
|
31583
|
+
async function resolveRepoRoot5() {
|
|
31584
|
+
const found = await findCodebyplanConfig(process.cwd());
|
|
31585
|
+
if (!found) {
|
|
31586
|
+
process.stderr.write(
|
|
31587
|
+
"handoff: no .codebyplan/repo.json found. Run `codebyplan setup`.\n"
|
|
31588
|
+
);
|
|
31589
|
+
process.exit(1);
|
|
31590
|
+
}
|
|
31591
|
+
return deriveRepoRoot(found.path);
|
|
31592
|
+
}
|
|
31593
|
+
async function runHandoffRead(args) {
|
|
31594
|
+
const { flags } = parseFlagsFromArgs(args);
|
|
31595
|
+
const level = parseLevel(flags);
|
|
31596
|
+
const repoRoot = await resolveRepoRoot5();
|
|
31597
|
+
let filePath;
|
|
31598
|
+
try {
|
|
31599
|
+
filePath = handoffPath(repoRoot, level, parsePathOpts(flags));
|
|
31600
|
+
} catch (err) {
|
|
31601
|
+
process.stderr.write(
|
|
31602
|
+
`handoff read: ${err instanceof Error ? err.message : String(err)}
|
|
31603
|
+
`
|
|
31604
|
+
);
|
|
31605
|
+
process.exit(1);
|
|
31606
|
+
}
|
|
31607
|
+
const content = await readHandoffFile(filePath);
|
|
31608
|
+
if (content === null || isHandoffEmpty(content)) {
|
|
31609
|
+
process.exit(0);
|
|
31610
|
+
}
|
|
31611
|
+
if (level === "repo") {
|
|
31612
|
+
const label = await resolveWorktreeLabel(repoRoot);
|
|
31613
|
+
const section = readHandoffSection(content, label);
|
|
31614
|
+
if (section !== null) {
|
|
31615
|
+
process.stdout.write(section + "\n");
|
|
31616
|
+
}
|
|
31617
|
+
} else {
|
|
31618
|
+
process.stdout.write(content);
|
|
31619
|
+
}
|
|
31620
|
+
process.exit(0);
|
|
31621
|
+
}
|
|
31622
|
+
async function runHandoffWrite(args) {
|
|
31623
|
+
const { flags } = parseFlagsFromArgs(args);
|
|
31624
|
+
const level = parseLevel(flags);
|
|
31625
|
+
const newContent = flags["content"];
|
|
31626
|
+
if (newContent === void 0) {
|
|
31627
|
+
process.stderr.write("handoff write: --content <text> is required\n");
|
|
31628
|
+
process.exit(1);
|
|
31629
|
+
}
|
|
31630
|
+
const repoRoot = await resolveRepoRoot5();
|
|
31631
|
+
let filePath;
|
|
31632
|
+
try {
|
|
31633
|
+
filePath = handoffPath(repoRoot, level, parsePathOpts(flags));
|
|
31634
|
+
} catch (err) {
|
|
31635
|
+
process.stderr.write(
|
|
31636
|
+
`handoff write: ${err instanceof Error ? err.message : String(err)}
|
|
31637
|
+
`
|
|
31638
|
+
);
|
|
31639
|
+
process.exit(1);
|
|
31640
|
+
}
|
|
31641
|
+
if (level === "repo") {
|
|
31642
|
+
const label = await resolveWorktreeLabel(repoRoot);
|
|
31643
|
+
const existing = await readHandoffFile(filePath) ?? "";
|
|
31644
|
+
const updated = replaceHandoffSection(existing, label, newContent);
|
|
31645
|
+
if (isHandoffEmpty(updated)) {
|
|
31646
|
+
await deleteHandoffFile(filePath);
|
|
31647
|
+
} else {
|
|
31648
|
+
await writeHandoffFile(filePath, updated);
|
|
31649
|
+
}
|
|
31650
|
+
} else {
|
|
31651
|
+
if (isHandoffEmpty(newContent)) {
|
|
31652
|
+
await deleteHandoffFile(filePath);
|
|
31653
|
+
} else {
|
|
31654
|
+
await writeHandoffFile(filePath, newContent);
|
|
31655
|
+
}
|
|
31656
|
+
}
|
|
31657
|
+
process.exit(0);
|
|
31658
|
+
}
|
|
31659
|
+
async function runHandoffAppend(args) {
|
|
31660
|
+
const { flags } = parseFlagsFromArgs(args);
|
|
31661
|
+
const level = parseLevel(flags);
|
|
31662
|
+
const appendContent = flags["content"];
|
|
31663
|
+
if (appendContent === void 0) {
|
|
31664
|
+
process.stderr.write("handoff append: --content <text> is required\n");
|
|
31665
|
+
process.exit(1);
|
|
31666
|
+
}
|
|
31667
|
+
const repoRoot = await resolveRepoRoot5();
|
|
31668
|
+
let filePath;
|
|
31669
|
+
try {
|
|
31670
|
+
filePath = handoffPath(repoRoot, level, parsePathOpts(flags));
|
|
31671
|
+
} catch (err) {
|
|
31672
|
+
process.stderr.write(
|
|
31673
|
+
`handoff append: ${err instanceof Error ? err.message : String(err)}
|
|
31674
|
+
`
|
|
31675
|
+
);
|
|
31676
|
+
process.exit(1);
|
|
31677
|
+
}
|
|
31678
|
+
const existing = await readHandoffFile(filePath) ?? "";
|
|
31679
|
+
if (level === "repo") {
|
|
31680
|
+
const label = await resolveWorktreeLabel(repoRoot);
|
|
31681
|
+
const currentSection = readHandoffSection(existing, label) ?? "";
|
|
31682
|
+
const combined = isHandoffEmpty(currentSection) ? appendContent : currentSection + "\n" + appendContent;
|
|
31683
|
+
const updated = replaceHandoffSection(existing, label, combined);
|
|
31684
|
+
if (isHandoffEmpty(updated)) {
|
|
31685
|
+
await deleteHandoffFile(filePath);
|
|
31686
|
+
} else {
|
|
31687
|
+
await writeHandoffFile(filePath, updated);
|
|
31688
|
+
}
|
|
31689
|
+
} else {
|
|
31690
|
+
const combined = isHandoffEmpty(existing) ? appendContent : existing.trimEnd() + "\n" + appendContent;
|
|
31691
|
+
if (isHandoffEmpty(combined)) {
|
|
31692
|
+
await deleteHandoffFile(filePath);
|
|
31693
|
+
} else {
|
|
31694
|
+
await writeHandoffFile(filePath, combined);
|
|
31695
|
+
}
|
|
31696
|
+
}
|
|
31697
|
+
process.exit(0);
|
|
31698
|
+
}
|
|
31699
|
+
async function runHandoffClear(args) {
|
|
31700
|
+
const { flags } = parseFlagsFromArgs(args);
|
|
31701
|
+
const level = parseLevel(flags);
|
|
31702
|
+
const repoRoot = await resolveRepoRoot5();
|
|
31703
|
+
let filePath;
|
|
31704
|
+
try {
|
|
31705
|
+
filePath = handoffPath(repoRoot, level, parsePathOpts(flags));
|
|
31706
|
+
} catch (err) {
|
|
31707
|
+
process.stderr.write(
|
|
31708
|
+
`handoff clear: ${err instanceof Error ? err.message : String(err)}
|
|
31709
|
+
`
|
|
31710
|
+
);
|
|
31711
|
+
process.exit(1);
|
|
31712
|
+
}
|
|
31713
|
+
if (level === "repo") {
|
|
31714
|
+
const label = await resolveWorktreeLabel(repoRoot);
|
|
31715
|
+
const existing = await readHandoffFile(filePath) ?? "";
|
|
31716
|
+
const updated = removeHandoffSection(existing, label);
|
|
31717
|
+
if (isHandoffEmpty(updated)) {
|
|
31718
|
+
await deleteHandoffFile(filePath);
|
|
31719
|
+
} else {
|
|
31720
|
+
await writeHandoffFile(filePath, updated);
|
|
31721
|
+
}
|
|
31722
|
+
} else {
|
|
31723
|
+
await deleteHandoffFile(filePath);
|
|
31724
|
+
}
|
|
31725
|
+
process.exit(0);
|
|
31726
|
+
}
|
|
31727
|
+
async function scanHandoffDir(baseDir, level, subDir) {
|
|
31728
|
+
const dir = path10.join(baseDir, subDir);
|
|
31729
|
+
const entries = [];
|
|
31730
|
+
let files;
|
|
31731
|
+
try {
|
|
31732
|
+
files = await readdir4(dir);
|
|
31733
|
+
} catch {
|
|
31734
|
+
return entries;
|
|
31735
|
+
}
|
|
31736
|
+
for (const file of files.filter((f) => f.endsWith(".md"))) {
|
|
31737
|
+
const filePath = path10.join(dir, file);
|
|
31738
|
+
const content = await readHandoffFile(filePath);
|
|
31739
|
+
if (!isHandoffEmpty(content)) {
|
|
31740
|
+
entries.push({
|
|
31741
|
+
level,
|
|
31742
|
+
identifier: path10.basename(file, ".md"),
|
|
31743
|
+
path: filePath
|
|
31744
|
+
});
|
|
31745
|
+
}
|
|
31746
|
+
}
|
|
31747
|
+
return entries;
|
|
31748
|
+
}
|
|
31749
|
+
async function runHandoffStatus(args) {
|
|
31750
|
+
const { booleans } = parseFlagsFromArgs(args);
|
|
31751
|
+
const jsonMode = booleans.has("json");
|
|
31752
|
+
const repoRoot = await resolveRepoRoot5();
|
|
31753
|
+
const baseDir = path10.join(repoRoot, ".codebyplan", "handoff");
|
|
31754
|
+
const nonEmpty = [];
|
|
31755
|
+
const repoFile = path10.join(baseDir, "repo.md");
|
|
31756
|
+
const repoContent = await readHandoffFile(repoFile);
|
|
31757
|
+
if (!isHandoffEmpty(repoContent)) {
|
|
31758
|
+
nonEmpty.push({ level: "repo", identifier: "repo", path: repoFile });
|
|
31759
|
+
}
|
|
31760
|
+
nonEmpty.push(...await scanHandoffDir(baseDir, "checkpoint", "checkpoint"));
|
|
31761
|
+
nonEmpty.push(...await scanHandoffDir(baseDir, "task", "task"));
|
|
31762
|
+
nonEmpty.push(...await scanHandoffDir(baseDir, "standalone", "standalone"));
|
|
31763
|
+
const output = { nonEmpty, empty: [] };
|
|
31764
|
+
if (jsonMode) {
|
|
31765
|
+
process.stdout.write(JSON.stringify(output, null, 2) + "\n");
|
|
31766
|
+
} else {
|
|
31767
|
+
if (nonEmpty.length === 0) {
|
|
31768
|
+
process.stdout.write("No handoff content found.\n");
|
|
31769
|
+
} else {
|
|
31770
|
+
process.stdout.write("Handoffs with content:\n");
|
|
31771
|
+
for (const entry of nonEmpty) {
|
|
31772
|
+
process.stdout.write(
|
|
31773
|
+
` [${entry.level}] ${entry.identifier} ${entry.path}
|
|
31774
|
+
`
|
|
31775
|
+
);
|
|
31776
|
+
}
|
|
31777
|
+
}
|
|
31778
|
+
}
|
|
31779
|
+
process.exit(0);
|
|
31780
|
+
}
|
|
31781
|
+
async function runHandoffCommand(args) {
|
|
31782
|
+
const subcommand = args[0];
|
|
31783
|
+
if (subcommand === "read") {
|
|
31784
|
+
await runHandoffRead(args.slice(1));
|
|
31785
|
+
return;
|
|
31786
|
+
}
|
|
31787
|
+
if (subcommand === "write") {
|
|
31788
|
+
await runHandoffWrite(args.slice(1));
|
|
31789
|
+
return;
|
|
31790
|
+
}
|
|
31791
|
+
if (subcommand === "append") {
|
|
31792
|
+
await runHandoffAppend(args.slice(1));
|
|
31793
|
+
return;
|
|
31794
|
+
}
|
|
31795
|
+
if (subcommand === "clear") {
|
|
31796
|
+
await runHandoffClear(args.slice(1));
|
|
31797
|
+
return;
|
|
31798
|
+
}
|
|
31799
|
+
if (subcommand === "status") {
|
|
31800
|
+
await runHandoffStatus(args.slice(1));
|
|
31801
|
+
return;
|
|
31802
|
+
}
|
|
31803
|
+
if (subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
31804
|
+
printHandoffHelp();
|
|
31805
|
+
process.exit(0);
|
|
31806
|
+
}
|
|
31807
|
+
if (subcommand) {
|
|
31808
|
+
process.stderr.write(
|
|
31809
|
+
`Unknown handoff subcommand: ${subcommand}
|
|
31810
|
+
Run 'codebyplan handoff help' for usage.
|
|
31811
|
+
`
|
|
31812
|
+
);
|
|
31813
|
+
} else {
|
|
31814
|
+
printHandoffHelp();
|
|
31815
|
+
}
|
|
31816
|
+
process.exit(1);
|
|
31817
|
+
}
|
|
31818
|
+
function printHandoffHelp() {
|
|
31819
|
+
process.stdout.write(
|
|
31820
|
+
"\n codebyplan handoff <subcommand>\n\n Manage per-level handoff notes in .codebyplan/handoff/\n\n Levels:\n repo Per-worktree section in .codebyplan/handoff/repo.md\n checkpoint .codebyplan/handoff/checkpoint/<NNN>.md\n task .codebyplan/handoff/task/<NNN>-<T>.md\n standalone .codebyplan/handoff/standalone/<N>.md\n\n Subcommands:\n read --level <l> [--number N] [--task T]\n Print current handoff content (empty output if absent)\n write --level <l> [--number N] [--task T] --content <text>\n Replace handoff content; deletes file when content is empty\n append --level <l> [--number N] [--task T] --content <text>\n Append to existing handoff (creates if absent)\n clear --level <l> [--number N] [--task T]\n Delete handoff file (idempotent; repo level removes section)\n status [--json]\n List all levels with non-empty handoff content\n\n Level flags:\n --number N Standalone task number (level=standalone)\n or checkpoint number (level=checkpoint)\n --checkpoint N Checkpoint number (level=checkpoint or task)\n --task T Task number within checkpoint (level=task)\n\n"
|
|
31821
|
+
);
|
|
31822
|
+
}
|
|
31823
|
+
var init_handoff = __esm({
|
|
31824
|
+
"src/cli/handoff.ts"() {
|
|
31825
|
+
"use strict";
|
|
31826
|
+
init_flags();
|
|
31827
|
+
init_git_utils();
|
|
31828
|
+
init_handoff_file();
|
|
31829
|
+
}
|
|
31830
|
+
});
|
|
31831
|
+
|
|
31359
31832
|
// src/lib/migrate-branch-model.ts
|
|
31360
|
-
import { readFile as
|
|
31361
|
-
import { join as
|
|
31833
|
+
import { readFile as readFile16, writeFile as writeFile13 } from "node:fs/promises";
|
|
31834
|
+
import { join as join27 } from "node:path";
|
|
31362
31835
|
import { execSync as execSync3 } from "node:child_process";
|
|
31363
31836
|
function assertValidBranchName(branch) {
|
|
31364
31837
|
if (!/^[a-zA-Z0-9/_.-]+$/.test(branch)) {
|
|
@@ -31368,7 +31841,7 @@ function assertValidBranchName(branch) {
|
|
|
31368
31841
|
}
|
|
31369
31842
|
}
|
|
31370
31843
|
async function readJsonFile3(filePath) {
|
|
31371
|
-
const raw = await
|
|
31844
|
+
const raw = await readFile16(filePath, "utf-8");
|
|
31372
31845
|
const parsed = JSON.parse(raw);
|
|
31373
31846
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
31374
31847
|
throw new Error(`${filePath} does not contain a JSON object`);
|
|
@@ -31437,12 +31910,12 @@ async function runBranchMigration(opts) {
|
|
|
31437
31910
|
if (found) {
|
|
31438
31911
|
if (found.path.endsWith("/repo.json")) {
|
|
31439
31912
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
31440
|
-
configPath =
|
|
31913
|
+
configPath = join27(dir, "git.json");
|
|
31441
31914
|
} else {
|
|
31442
31915
|
configPath = found.path;
|
|
31443
31916
|
}
|
|
31444
31917
|
} else {
|
|
31445
|
-
configPath =
|
|
31918
|
+
configPath = join27(cwd, ".codebyplan", "git.json");
|
|
31446
31919
|
}
|
|
31447
31920
|
let fileRaw;
|
|
31448
31921
|
let fileParsed;
|
|
@@ -31516,7 +31989,7 @@ async function runBranchMigration(opts) {
|
|
|
31516
31989
|
const updatedParsed = { ...fileParsed, branch_config: after };
|
|
31517
31990
|
const newJson = JSON.stringify(updatedParsed, null, 2) + "\n";
|
|
31518
31991
|
if (newJson !== fileRaw) {
|
|
31519
|
-
await
|
|
31992
|
+
await writeFile13(configPath, newJson, "utf-8");
|
|
31520
31993
|
}
|
|
31521
31994
|
}
|
|
31522
31995
|
return {
|
|
@@ -31788,8 +32261,8 @@ var init_branch = __esm({
|
|
|
31788
32261
|
});
|
|
31789
32262
|
|
|
31790
32263
|
// src/lib/bump.ts
|
|
31791
|
-
import { readFile as
|
|
31792
|
-
import { join as
|
|
32264
|
+
import { readFile as readFile17, writeFile as writeFile14, access as access5, readdir as readdir5 } from "node:fs/promises";
|
|
32265
|
+
import { join as join28, relative as relative5, resolve as resolve3 } from "node:path";
|
|
31793
32266
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
31794
32267
|
function parsePnpmWorkspaceGlobs(raw) {
|
|
31795
32268
|
const lines = raw.split("\n");
|
|
@@ -31819,18 +32292,18 @@ async function expandGlob(cwd, glob) {
|
|
|
31819
32292
|
if (parts.length !== 2 || parts[1] !== "*") {
|
|
31820
32293
|
return [];
|
|
31821
32294
|
}
|
|
31822
|
-
const parentDir =
|
|
32295
|
+
const parentDir = join28(cwd, parts[0]);
|
|
31823
32296
|
let dirs;
|
|
31824
32297
|
try {
|
|
31825
|
-
const entries = await
|
|
31826
|
-
dirs = entries.filter((e) => e.isDirectory()).map((e) =>
|
|
32298
|
+
const entries = await readdir5(parentDir, { withFileTypes: true });
|
|
32299
|
+
dirs = entries.filter((e) => e.isDirectory()).map((e) => join28(parentDir, e.name));
|
|
31827
32300
|
} catch {
|
|
31828
32301
|
return [];
|
|
31829
32302
|
}
|
|
31830
32303
|
const results = [];
|
|
31831
32304
|
for (const dir of dirs) {
|
|
31832
32305
|
try {
|
|
31833
|
-
await access5(
|
|
32306
|
+
await access5(join28(dir, "package.json"));
|
|
31834
32307
|
results.push(dir);
|
|
31835
32308
|
} catch {
|
|
31836
32309
|
}
|
|
@@ -31841,7 +32314,7 @@ async function buildPackageMap(cwd) {
|
|
|
31841
32314
|
const map = /* @__PURE__ */ new Map();
|
|
31842
32315
|
let globs = [];
|
|
31843
32316
|
try {
|
|
31844
|
-
const raw = await
|
|
32317
|
+
const raw = await readFile17(join28(cwd, "pnpm-workspace.yaml"), "utf-8");
|
|
31845
32318
|
globs = parsePnpmWorkspaceGlobs(raw);
|
|
31846
32319
|
} catch {
|
|
31847
32320
|
}
|
|
@@ -31849,7 +32322,7 @@ async function buildPackageMap(cwd) {
|
|
|
31849
32322
|
const dirs = await expandGlob(cwd, glob);
|
|
31850
32323
|
for (const dir of dirs) {
|
|
31851
32324
|
try {
|
|
31852
|
-
const pkgRaw = await
|
|
32325
|
+
const pkgRaw = await readFile17(join28(dir, "package.json"), "utf-8");
|
|
31853
32326
|
const pkg = JSON.parse(pkgRaw);
|
|
31854
32327
|
const name = pkg.name ?? relative5(cwd, dir);
|
|
31855
32328
|
map.set(dir, { name, dir });
|
|
@@ -31968,7 +32441,7 @@ function injectVersion(raw, nextVersion, filePath) {
|
|
|
31968
32441
|
async function prependChangelog(changelogPath, packageName, nextVersion, now, dryRun) {
|
|
31969
32442
|
let existing;
|
|
31970
32443
|
try {
|
|
31971
|
-
existing = await
|
|
32444
|
+
existing = await readFile17(changelogPath, "utf-8");
|
|
31972
32445
|
} catch {
|
|
31973
32446
|
return false;
|
|
31974
32447
|
}
|
|
@@ -31981,7 +32454,7 @@ async function prependChangelog(changelogPath, packageName, nextVersion, now, dr
|
|
|
31981
32454
|
`;
|
|
31982
32455
|
const updated = entry + existing;
|
|
31983
32456
|
if (!dryRun) {
|
|
31984
|
-
await
|
|
32457
|
+
await writeFile14(changelogPath, updated, "utf-8");
|
|
31985
32458
|
}
|
|
31986
32459
|
return true;
|
|
31987
32460
|
}
|
|
@@ -32008,7 +32481,7 @@ async function runBump(opts) {
|
|
|
32008
32481
|
const changedFiles = (diffResult.stdout ?? "").trim().split("\n").filter(Boolean).map((f) => resolve3(cwd, f));
|
|
32009
32482
|
const packageMap = await buildPackageMap(cwd);
|
|
32010
32483
|
const packageDirs = Array.from(packageMap.keys());
|
|
32011
|
-
const rootPkgPath =
|
|
32484
|
+
const rootPkgPath = join28(cwd, "package.json");
|
|
32012
32485
|
const changedPackageDirs = /* @__PURE__ */ new Set();
|
|
32013
32486
|
for (const absFile of changedFiles) {
|
|
32014
32487
|
const owner = findOwningPackage(absFile, packageDirs);
|
|
@@ -32019,19 +32492,19 @@ async function runBump(opts) {
|
|
|
32019
32492
|
const entries = [];
|
|
32020
32493
|
for (const pkgDir of changedPackageDirs) {
|
|
32021
32494
|
const pkgInfo = packageMap.get(pkgDir);
|
|
32022
|
-
const pkgJsonPath =
|
|
32495
|
+
const pkgJsonPath = join28(pkgDir, "package.json");
|
|
32023
32496
|
if (pkgJsonPath === rootPkgPath) continue;
|
|
32024
32497
|
const versionFileCandidates = [
|
|
32025
32498
|
{ abs: pkgJsonPath, rel: relative5(cwd, pkgJsonPath).replace(/\\/g, "/") }
|
|
32026
32499
|
];
|
|
32027
|
-
const tauriConfPath =
|
|
32500
|
+
const tauriConfPath = join28(pkgDir, "src-tauri", "tauri.conf.json");
|
|
32028
32501
|
const tauriRelPath = relative5(cwd, tauriConfPath).replace(/\\/g, "/");
|
|
32029
32502
|
try {
|
|
32030
32503
|
await access5(tauriConfPath);
|
|
32031
32504
|
versionFileCandidates.push({ abs: tauriConfPath, rel: tauriRelPath });
|
|
32032
32505
|
} catch {
|
|
32033
32506
|
}
|
|
32034
|
-
const appJsonPath =
|
|
32507
|
+
const appJsonPath = join28(pkgDir, "app.json");
|
|
32035
32508
|
const appJsonRelPath = relative5(cwd, appJsonPath).replace(/\\/g, "/");
|
|
32036
32509
|
try {
|
|
32037
32510
|
await access5(appJsonPath);
|
|
@@ -32040,7 +32513,7 @@ async function runBump(opts) {
|
|
|
32040
32513
|
}
|
|
32041
32514
|
let currentPkgJsonRaw;
|
|
32042
32515
|
try {
|
|
32043
|
-
currentPkgJsonRaw = await
|
|
32516
|
+
currentPkgJsonRaw = await readFile17(pkgJsonPath, "utf-8");
|
|
32044
32517
|
} catch (err) {
|
|
32045
32518
|
console.warn(
|
|
32046
32519
|
`runBump: could not read ${pkgJsonPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -32085,7 +32558,7 @@ async function runBump(opts) {
|
|
|
32085
32558
|
for (const { abs, rel } of versionFileCandidates) {
|
|
32086
32559
|
let raw;
|
|
32087
32560
|
try {
|
|
32088
|
-
raw = await
|
|
32561
|
+
raw = await readFile17(abs, "utf-8");
|
|
32089
32562
|
} catch {
|
|
32090
32563
|
continue;
|
|
32091
32564
|
}
|
|
@@ -32099,11 +32572,11 @@ async function runBump(opts) {
|
|
|
32099
32572
|
}
|
|
32100
32573
|
const updated = injectVersion(raw, nextVersion, abs);
|
|
32101
32574
|
if (!dryRun) {
|
|
32102
|
-
await
|
|
32575
|
+
await writeFile14(abs, updated, "utf-8");
|
|
32103
32576
|
}
|
|
32104
32577
|
updatedVersionFiles.push(rel);
|
|
32105
32578
|
}
|
|
32106
|
-
const changelogPath =
|
|
32579
|
+
const changelogPath = join28(pkgDir, "CHANGELOG.md");
|
|
32107
32580
|
const changelogUpdated = await prependChangelog(
|
|
32108
32581
|
changelogPath,
|
|
32109
32582
|
pkgInfo.name,
|
|
@@ -32646,14 +33119,14 @@ var init_ship2 = __esm({
|
|
|
32646
33119
|
|
|
32647
33120
|
// src/lib/scaffold-publish-workflow.ts
|
|
32648
33121
|
import * as fs6 from "node:fs";
|
|
32649
|
-
import * as
|
|
33122
|
+
import * as path11 from "node:path";
|
|
32650
33123
|
async function runScaffoldPublishWorkflow(opts) {
|
|
32651
33124
|
await Promise.resolve();
|
|
32652
33125
|
const dryRun = opts?.dryRun ?? false;
|
|
32653
33126
|
const force = opts?.force ?? false;
|
|
32654
|
-
const projectDir =
|
|
33127
|
+
const projectDir = path11.resolve(opts?.projectDir ?? process.cwd());
|
|
32655
33128
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
32656
|
-
const templatePath =
|
|
33129
|
+
const templatePath = path11.join(
|
|
32657
33130
|
templatesDir,
|
|
32658
33131
|
"github-workflows",
|
|
32659
33132
|
"publish.yml"
|
|
@@ -32664,7 +33137,7 @@ async function runScaffoldPublishWorkflow(opts) {
|
|
|
32664
33137
|
);
|
|
32665
33138
|
}
|
|
32666
33139
|
const templateContent = fs6.readFileSync(templatePath, "utf-8");
|
|
32667
|
-
const targetPath =
|
|
33140
|
+
const targetPath = path11.join(
|
|
32668
33141
|
projectDir,
|
|
32669
33142
|
".github",
|
|
32670
33143
|
"workflows",
|
|
@@ -32688,7 +33161,7 @@ async function runScaffoldPublishWorkflow(opts) {
|
|
|
32688
33161
|
);
|
|
32689
33162
|
}
|
|
32690
33163
|
}
|
|
32691
|
-
const targetDir =
|
|
33164
|
+
const targetDir = path11.dirname(targetPath);
|
|
32692
33165
|
fs6.mkdirSync(targetDir, { recursive: true });
|
|
32693
33166
|
fs6.writeFileSync(targetPath, templateContent, "utf-8");
|
|
32694
33167
|
return { status: "written", path: targetPath };
|
|
@@ -32785,7 +33258,7 @@ var init_atomic_write = __esm({
|
|
|
32785
33258
|
|
|
32786
33259
|
// src/lib/repo-reader.ts
|
|
32787
33260
|
import * as fsPromises from "node:fs/promises";
|
|
32788
|
-
import * as
|
|
33261
|
+
import * as path12 from "node:path";
|
|
32789
33262
|
var LocalFsReader;
|
|
32790
33263
|
var init_repo_reader = __esm({
|
|
32791
33264
|
"src/lib/repo-reader.ts"() {
|
|
@@ -32796,7 +33269,7 @@ var init_repo_reader = __esm({
|
|
|
32796
33269
|
}
|
|
32797
33270
|
rootDir;
|
|
32798
33271
|
resolve(p) {
|
|
32799
|
-
return
|
|
33272
|
+
return path12.isAbsolute(p) ? p : path12.resolve(this.rootDir, p);
|
|
32800
33273
|
}
|
|
32801
33274
|
async list(dir) {
|
|
32802
33275
|
const abs = this.resolve(dir);
|
|
@@ -32832,7 +33305,7 @@ var init_repo_reader = __esm({
|
|
|
32832
33305
|
|
|
32833
33306
|
// src/lib/ci-init.ts
|
|
32834
33307
|
import * as fs8 from "node:fs";
|
|
32835
|
-
import * as
|
|
33308
|
+
import * as path13 from "node:path";
|
|
32836
33309
|
async function tryReadJson(reader, filePath) {
|
|
32837
33310
|
try {
|
|
32838
33311
|
const raw = await reader.read(filePath);
|
|
@@ -32910,10 +33383,10 @@ function buildDefaultCiConfig(platforms) {
|
|
|
32910
33383
|
return config;
|
|
32911
33384
|
}
|
|
32912
33385
|
async function runCiInit(opts) {
|
|
32913
|
-
const projectDir =
|
|
33386
|
+
const projectDir = path13.resolve(opts?.projectDir ?? process.cwd());
|
|
32914
33387
|
const dryRun = opts?.dryRun ?? false;
|
|
32915
33388
|
const force = opts?.force ?? false;
|
|
32916
|
-
const ciPath =
|
|
33389
|
+
const ciPath = path13.join(projectDir, ".codebyplan", "ci.json");
|
|
32917
33390
|
const reader = opts?.reader ?? new LocalFsReader(projectDir);
|
|
32918
33391
|
const platforms = await detectPlatforms(reader);
|
|
32919
33392
|
if (dryRun) {
|
|
@@ -32959,7 +33432,7 @@ async function runCiInit(opts) {
|
|
|
32959
33432
|
platforms: newPlatforms.length > 0 ? newPlatforms : platforms
|
|
32960
33433
|
};
|
|
32961
33434
|
}
|
|
32962
|
-
const codebyplanDir =
|
|
33435
|
+
const codebyplanDir = path13.join(projectDir, ".codebyplan");
|
|
32963
33436
|
fs8.mkdirSync(codebyplanDir, { recursive: true });
|
|
32964
33437
|
writeJsonAtomic(ciPath, newConfig);
|
|
32965
33438
|
return { status: "written", path: ciPath, platforms };
|
|
@@ -33169,7 +33642,7 @@ var init_ci_init = __esm({
|
|
|
33169
33642
|
|
|
33170
33643
|
// src/lib/scaffold-ci-workflow.ts
|
|
33171
33644
|
import * as fs9 from "node:fs";
|
|
33172
|
-
import * as
|
|
33645
|
+
import * as path14 from "node:path";
|
|
33173
33646
|
function substituteTokens(template, tokens) {
|
|
33174
33647
|
let result = template;
|
|
33175
33648
|
for (const [token, value] of Object.entries(tokens)) {
|
|
@@ -33203,13 +33676,13 @@ async function detectStrictEnforcedFromCiJson(reader) {
|
|
|
33203
33676
|
}
|
|
33204
33677
|
}
|
|
33205
33678
|
async function renderCiWorkflowContent(opts) {
|
|
33206
|
-
const projectDir =
|
|
33679
|
+
const projectDir = path14.resolve(opts?.projectDir ?? process.cwd());
|
|
33207
33680
|
const reader = opts?.reader ?? new LocalFsReader(projectDir);
|
|
33208
33681
|
const pnpmVersion = opts?.pnpmVersion ?? await detectPnpmVersionFromPackageJson(reader);
|
|
33209
33682
|
const nodeVersion = opts?.nodeVersion ?? "22";
|
|
33210
33683
|
const strictEnforced = opts?.strictEnforced ?? await detectStrictEnforcedFromCiJson(reader);
|
|
33211
33684
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
33212
|
-
const templatePath =
|
|
33685
|
+
const templatePath = path14.join(templatesDir, "github-workflows", "ci.yml");
|
|
33213
33686
|
if (!fs9.existsSync(templatePath)) {
|
|
33214
33687
|
throw new Error(
|
|
33215
33688
|
`scaffold-ci-workflow: template not found at ${templatePath}`
|
|
@@ -33226,9 +33699,9 @@ async function renderCiWorkflowContent(opts) {
|
|
|
33226
33699
|
async function runScaffoldCiWorkflow(opts) {
|
|
33227
33700
|
const dryRun = opts?.dryRun ?? false;
|
|
33228
33701
|
const force = opts?.force ?? false;
|
|
33229
|
-
const projectDir =
|
|
33702
|
+
const projectDir = path14.resolve(opts?.projectDir ?? process.cwd());
|
|
33230
33703
|
const renderedContent = await renderCiWorkflowContent(opts);
|
|
33231
|
-
const targetPath =
|
|
33704
|
+
const targetPath = path14.join(projectDir, ".github", "workflows", "ci.yml");
|
|
33232
33705
|
if (dryRun) {
|
|
33233
33706
|
return { status: "dry_run", path: targetPath };
|
|
33234
33707
|
}
|
|
@@ -33247,7 +33720,7 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
33247
33720
|
);
|
|
33248
33721
|
}
|
|
33249
33722
|
}
|
|
33250
|
-
const targetDir =
|
|
33723
|
+
const targetDir = path14.dirname(targetPath);
|
|
33251
33724
|
fs9.mkdirSync(targetDir, { recursive: true });
|
|
33252
33725
|
const tmpPath = targetPath + ".tmp";
|
|
33253
33726
|
try {
|
|
@@ -33272,10 +33745,10 @@ var init_scaffold_ci_workflow = __esm({
|
|
|
33272
33745
|
|
|
33273
33746
|
// src/lib/gh-required-checks.ts
|
|
33274
33747
|
import * as fs10 from "node:fs";
|
|
33275
|
-
import * as
|
|
33748
|
+
import * as path15 from "node:path";
|
|
33276
33749
|
import { execSync as execSync5 } from "node:child_process";
|
|
33277
33750
|
function readCiJson(projectDir) {
|
|
33278
|
-
const ciPath =
|
|
33751
|
+
const ciPath = path15.join(projectDir, ".codebyplan", "ci.json");
|
|
33279
33752
|
if (!fs10.existsSync(ciPath)) {
|
|
33280
33753
|
return {
|
|
33281
33754
|
platforms: {},
|
|
@@ -33294,15 +33767,15 @@ function readCiJson(projectDir) {
|
|
|
33294
33767
|
}
|
|
33295
33768
|
}
|
|
33296
33769
|
function writeCiJsonAtomic(projectDir, config) {
|
|
33297
|
-
const ciPath =
|
|
33770
|
+
const ciPath = path15.join(projectDir, ".codebyplan", "ci.json");
|
|
33298
33771
|
writeJsonAtomic(ciPath, config);
|
|
33299
33772
|
}
|
|
33300
33773
|
function enforceRequiredCheck(opts) {
|
|
33301
|
-
const projectDir =
|
|
33774
|
+
const projectDir = path15.resolve(opts?.projectDir ?? process.cwd());
|
|
33302
33775
|
const branch = opts?.branch ?? "main";
|
|
33303
33776
|
const checkName = opts?.checkName ?? "Lint + typecheck + test + build";
|
|
33304
33777
|
const dryRun = opts?.dryRun ?? false;
|
|
33305
|
-
const ciPath =
|
|
33778
|
+
const ciPath = path15.join(projectDir, ".codebyplan", "ci.json");
|
|
33306
33779
|
const config = readCiJson(projectDir);
|
|
33307
33780
|
if (config.workflow?.required_check_enforced === true) {
|
|
33308
33781
|
return { status: "already_enforced", path: ciPath };
|
|
@@ -33709,9 +34182,9 @@ var init_ci = __esm({
|
|
|
33709
34182
|
|
|
33710
34183
|
// src/lib/cd-init.ts
|
|
33711
34184
|
import * as fs11 from "node:fs";
|
|
33712
|
-
import * as
|
|
34185
|
+
import * as path16 from "node:path";
|
|
33713
34186
|
function detectSurfaces(projectDir) {
|
|
33714
|
-
const shipmentPath =
|
|
34187
|
+
const shipmentPath = path16.join(projectDir, ".codebyplan", "shipment.json");
|
|
33715
34188
|
let shipment;
|
|
33716
34189
|
try {
|
|
33717
34190
|
shipment = JSON.parse(fs11.readFileSync(shipmentPath, "utf-8"));
|
|
@@ -33764,10 +34237,10 @@ function buildDefaultCdConfig(rawSurfaceKeys) {
|
|
|
33764
34237
|
}
|
|
33765
34238
|
async function runCdInit(opts) {
|
|
33766
34239
|
await Promise.resolve();
|
|
33767
|
-
const projectDir =
|
|
34240
|
+
const projectDir = path16.resolve(opts?.projectDir ?? process.cwd());
|
|
33768
34241
|
const dryRun = opts?.dryRun ?? false;
|
|
33769
34242
|
const force = opts?.force ?? false;
|
|
33770
|
-
const cdPath =
|
|
34243
|
+
const cdPath = path16.join(projectDir, ".codebyplan", "cd.json");
|
|
33771
34244
|
const rawSurfaceKeys = detectSurfaces(projectDir);
|
|
33772
34245
|
const seen = /* @__PURE__ */ new Set();
|
|
33773
34246
|
const surfaces = [];
|
|
@@ -33808,7 +34281,7 @@ async function runCdInit(opts) {
|
|
|
33808
34281
|
surfaces: newSurfaces
|
|
33809
34282
|
};
|
|
33810
34283
|
}
|
|
33811
|
-
const codebyplanDir =
|
|
34284
|
+
const codebyplanDir = path16.join(projectDir, ".codebyplan");
|
|
33812
34285
|
fs11.mkdirSync(codebyplanDir, { recursive: true });
|
|
33813
34286
|
writeJsonAtomic(cdPath, newConfig);
|
|
33814
34287
|
return { status: "written", path: cdPath, surfaces };
|
|
@@ -33898,14 +34371,14 @@ var init_cd_init = __esm({
|
|
|
33898
34371
|
|
|
33899
34372
|
// src/lib/scaffold-cd-workflow.ts
|
|
33900
34373
|
import * as fs12 from "node:fs";
|
|
33901
|
-
import * as
|
|
34374
|
+
import * as path17 from "node:path";
|
|
33902
34375
|
async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
33903
34376
|
await Promise.resolve();
|
|
33904
34377
|
const dryRun = opts.dryRun ?? false;
|
|
33905
34378
|
const force = opts.force ?? false;
|
|
33906
|
-
const projectDir =
|
|
34379
|
+
const projectDir = path17.resolve(opts.projectDir ?? process.cwd());
|
|
33907
34380
|
const templatesDir = opts.templatesDir ?? resolveTemplatesDir();
|
|
33908
|
-
const templatePath =
|
|
34381
|
+
const templatePath = path17.join(
|
|
33909
34382
|
templatesDir,
|
|
33910
34383
|
"github-workflows",
|
|
33911
34384
|
templateName
|
|
@@ -33916,7 +34389,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
33916
34389
|
);
|
|
33917
34390
|
}
|
|
33918
34391
|
const templateContent = fs12.readFileSync(templatePath, "utf-8");
|
|
33919
|
-
const targetPath =
|
|
34392
|
+
const targetPath = path17.join(projectDir, ".github", "workflows", targetName);
|
|
33920
34393
|
if (dryRun) {
|
|
33921
34394
|
return { status: "dry_run", path: targetPath };
|
|
33922
34395
|
}
|
|
@@ -33935,7 +34408,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
33935
34408
|
);
|
|
33936
34409
|
}
|
|
33937
34410
|
}
|
|
33938
|
-
const targetDir =
|
|
34411
|
+
const targetDir = path17.dirname(targetPath);
|
|
33939
34412
|
fs12.mkdirSync(targetDir, { recursive: true });
|
|
33940
34413
|
const tmpPath = targetPath + ".tmp";
|
|
33941
34414
|
try {
|
|
@@ -34461,7 +34934,7 @@ __export(version_status_exports, {
|
|
|
34461
34934
|
});
|
|
34462
34935
|
import { execFileSync, execSync as execSync6 } from "node:child_process";
|
|
34463
34936
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
34464
|
-
import { dirname as
|
|
34937
|
+
import { dirname as dirname12, join as join35 } from "node:path";
|
|
34465
34938
|
function fetchLatestVersion() {
|
|
34466
34939
|
try {
|
|
34467
34940
|
return execFileSync("npm", ["view", "codebyplan", "version"], {
|
|
@@ -34485,11 +34958,11 @@ function detectPackageManager2(gitRoot) {
|
|
|
34485
34958
|
let dir = process.cwd();
|
|
34486
34959
|
const stopAt = gitRoot ?? null;
|
|
34487
34960
|
while (true) {
|
|
34488
|
-
if (existsSync10(
|
|
34489
|
-
if (existsSync10(
|
|
34490
|
-
if (existsSync10(
|
|
34961
|
+
if (existsSync10(join35(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
34962
|
+
if (existsSync10(join35(dir, "yarn.lock"))) return "yarn";
|
|
34963
|
+
if (existsSync10(join35(dir, "package-lock.json"))) return "npm";
|
|
34491
34964
|
if (stopAt !== null && dir === stopAt) break;
|
|
34492
|
-
const parent =
|
|
34965
|
+
const parent = dirname12(dir);
|
|
34493
34966
|
if (parent === dir) break;
|
|
34494
34967
|
dir = parent;
|
|
34495
34968
|
}
|
|
@@ -34507,7 +34980,7 @@ function buildInstallCommand2(pm) {
|
|
|
34507
34980
|
}
|
|
34508
34981
|
async function resolveGuard(gitRoot, currentBranch) {
|
|
34509
34982
|
if (gitRoot !== null) {
|
|
34510
|
-
const canonicalPkgPath =
|
|
34983
|
+
const canonicalPkgPath = join35(
|
|
34511
34984
|
gitRoot,
|
|
34512
34985
|
"packages",
|
|
34513
34986
|
"codebyplan-package",
|
|
@@ -34531,10 +35004,10 @@ async function resolveGuard(gitRoot, currentBranch) {
|
|
|
34531
35004
|
let gitJsonPath;
|
|
34532
35005
|
if (found.path.endsWith("/repo.json")) {
|
|
34533
35006
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
34534
|
-
gitJsonPath =
|
|
35007
|
+
gitJsonPath = join35(dir, "git.json");
|
|
34535
35008
|
} else {
|
|
34536
35009
|
const legacyDir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
34537
|
-
gitJsonPath =
|
|
35010
|
+
gitJsonPath = join35(legacyDir, ".codebyplan", "git.json");
|
|
34538
35011
|
}
|
|
34539
35012
|
const raw = readFileSync11(gitJsonPath, "utf-8");
|
|
34540
35013
|
const parsed = JSON.parse(raw);
|
|
@@ -34618,8 +35091,8 @@ var upload_e2e_images_exports = {};
|
|
|
34618
35091
|
__export(upload_e2e_images_exports, {
|
|
34619
35092
|
runUploadE2eImagesCommand: () => runUploadE2eImagesCommand
|
|
34620
35093
|
});
|
|
34621
|
-
import { readFile as
|
|
34622
|
-
import { join as
|
|
35094
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
35095
|
+
import { join as join36, basename as basename3, resolve as resolve11 } from "node:path";
|
|
34623
35096
|
import { execSync as execSync7 } from "node:child_process";
|
|
34624
35097
|
function baseUrl2() {
|
|
34625
35098
|
return (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
|
|
@@ -34653,8 +35126,8 @@ function parseArgs(args) {
|
|
|
34653
35126
|
}
|
|
34654
35127
|
async function readE2eConfig(projectPath) {
|
|
34655
35128
|
try {
|
|
34656
|
-
const raw = await
|
|
34657
|
-
|
|
35129
|
+
const raw = await readFile19(
|
|
35130
|
+
join36(projectPath, ".codebyplan", "e2e.json"),
|
|
34658
35131
|
"utf-8"
|
|
34659
35132
|
);
|
|
34660
35133
|
return JSON.parse(raw);
|
|
@@ -34695,8 +35168,8 @@ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, bas
|
|
|
34695
35168
|
continue;
|
|
34696
35169
|
const isNew = status === "A";
|
|
34697
35170
|
results.push({
|
|
34698
|
-
absolutePath:
|
|
34699
|
-
filename:
|
|
35171
|
+
absolutePath: join36(projectPath, filePath),
|
|
35172
|
+
filename: basename3(filePath),
|
|
34700
35173
|
framework: frameworkName,
|
|
34701
35174
|
is_new: isNew
|
|
34702
35175
|
});
|
|
@@ -34711,11 +35184,11 @@ function deriveTestName(absolutePath) {
|
|
|
34711
35184
|
return seg.replace(".spec.ts-snapshots", "");
|
|
34712
35185
|
}
|
|
34713
35186
|
}
|
|
34714
|
-
return
|
|
35187
|
+
return basename3(absolutePath, ".png");
|
|
34715
35188
|
}
|
|
34716
35189
|
function buildManifestItem(png) {
|
|
34717
35190
|
const testName = deriveTestName(png.absolutePath);
|
|
34718
|
-
const pageOrScreen =
|
|
35191
|
+
const pageOrScreen = basename3(png.absolutePath, ".png");
|
|
34719
35192
|
return {
|
|
34720
35193
|
filename: png.filename,
|
|
34721
35194
|
test_name: testName,
|
|
@@ -34792,7 +35265,7 @@ async function runUploadE2eImagesCommand(args) {
|
|
|
34792
35265
|
for (const png of allPngs) {
|
|
34793
35266
|
let bytes;
|
|
34794
35267
|
try {
|
|
34795
|
-
bytes = await
|
|
35268
|
+
bytes = await readFile19(png.absolutePath);
|
|
34796
35269
|
} catch {
|
|
34797
35270
|
process.stderr.write(
|
|
34798
35271
|
`upload-e2e-images: could not read file: ${png.absolutePath}
|
|
@@ -34869,9 +35342,9 @@ __export(arch_map_exports, {
|
|
|
34869
35342
|
runArchMapCommand: () => runArchMapCommand,
|
|
34870
35343
|
updateFrontmatterFields: () => updateFrontmatterFields
|
|
34871
35344
|
});
|
|
34872
|
-
import { readFile as
|
|
35345
|
+
import { readFile as readFile20, writeFile as writeFile15 } from "node:fs/promises";
|
|
34873
35346
|
import { existsSync as existsSync11, readdirSync as readdirSync3 } from "node:fs";
|
|
34874
|
-
import { join as
|
|
35347
|
+
import { join as join37 } from "node:path";
|
|
34875
35348
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
34876
35349
|
function normalizeModulePath(modulePath) {
|
|
34877
35350
|
return modulePath.replace(/\/+$/, "");
|
|
@@ -34896,9 +35369,9 @@ async function resolveCodebyplanDir(startDir) {
|
|
|
34896
35369
|
}
|
|
34897
35370
|
}
|
|
34898
35371
|
async function readArchitectureConfig(codebyplanDir) {
|
|
34899
|
-
const filePath =
|
|
35372
|
+
const filePath = join37(codebyplanDir, "architecture.json");
|
|
34900
35373
|
try {
|
|
34901
|
-
const raw = await
|
|
35374
|
+
const raw = await readFile20(filePath, "utf-8");
|
|
34902
35375
|
const parsed = JSON.parse(raw);
|
|
34903
35376
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.modules)) {
|
|
34904
35377
|
return { version: 1, modules: [] };
|
|
@@ -34909,8 +35382,8 @@ async function readArchitectureConfig(codebyplanDir) {
|
|
|
34909
35382
|
}
|
|
34910
35383
|
}
|
|
34911
35384
|
async function writeArchitectureConfig(codebyplanDir, config) {
|
|
34912
|
-
const filePath =
|
|
34913
|
-
await
|
|
35385
|
+
const filePath = join37(codebyplanDir, "architecture.json");
|
|
35386
|
+
await writeFile15(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
34914
35387
|
}
|
|
34915
35388
|
function resolveGitSha(modulePath, cwd) {
|
|
34916
35389
|
try {
|
|
@@ -34928,10 +35401,10 @@ function resolveGitSha(modulePath, cwd) {
|
|
|
34928
35401
|
}
|
|
34929
35402
|
async function discoverModulePaths(projectRoot) {
|
|
34930
35403
|
const paths = [];
|
|
34931
|
-
const workspacePath =
|
|
35404
|
+
const workspacePath = join37(projectRoot, "pnpm-workspace.yaml");
|
|
34932
35405
|
let patterns = [];
|
|
34933
35406
|
try {
|
|
34934
|
-
const raw = await
|
|
35407
|
+
const raw = await readFile20(workspacePath, "utf-8");
|
|
34935
35408
|
const lines = raw.split("\n");
|
|
34936
35409
|
let inPackages = false;
|
|
34937
35410
|
for (const line of lines) {
|
|
@@ -34955,7 +35428,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
34955
35428
|
for (const pattern of patterns) {
|
|
34956
35429
|
if (pattern.endsWith("/*")) {
|
|
34957
35430
|
const dir = pattern.slice(0, -2);
|
|
34958
|
-
const absDir =
|
|
35431
|
+
const absDir = join37(projectRoot, dir);
|
|
34959
35432
|
try {
|
|
34960
35433
|
if (existsSync11(absDir)) {
|
|
34961
35434
|
const entries = readdirSync3(absDir, { withFileTypes: true });
|
|
@@ -34968,7 +35441,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
34968
35441
|
} catch {
|
|
34969
35442
|
}
|
|
34970
35443
|
} else if (!pattern.includes("*")) {
|
|
34971
|
-
const absPath =
|
|
35444
|
+
const absPath = join37(projectRoot, pattern);
|
|
34972
35445
|
if (existsSync11(absPath)) {
|
|
34973
35446
|
paths.push(pattern);
|
|
34974
35447
|
}
|
|
@@ -34976,7 +35449,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
34976
35449
|
}
|
|
34977
35450
|
const crossCutting = ["supabase", ".github", "scripts"];
|
|
34978
35451
|
for (const dir of crossCutting) {
|
|
34979
|
-
const absPath =
|
|
35452
|
+
const absPath = join37(projectRoot, dir);
|
|
34980
35453
|
try {
|
|
34981
35454
|
if (existsSync11(absPath)) {
|
|
34982
35455
|
paths.push(dir);
|
|
@@ -35162,10 +35635,10 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
35162
35635
|
}
|
|
35163
35636
|
await writeArchitectureConfig(codebyplanDir, config);
|
|
35164
35637
|
const stampedEntry = existingIndex >= 0 ? config.modules[existingIndex] : config.modules[config.modules.length - 1];
|
|
35165
|
-
const mapAbsPath =
|
|
35638
|
+
const mapAbsPath = join37(repoRoot, stampedEntry.map_file);
|
|
35166
35639
|
let mapContent = null;
|
|
35167
35640
|
try {
|
|
35168
|
-
mapContent = await
|
|
35641
|
+
mapContent = await readFile20(mapAbsPath, "utf-8");
|
|
35169
35642
|
} catch {
|
|
35170
35643
|
console.warn(
|
|
35171
35644
|
" Warning: map file " + stampedEntry.map_file + " not found \u2014 stamped manifest only"
|
|
@@ -35187,7 +35660,7 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
35187
35660
|
);
|
|
35188
35661
|
} else {
|
|
35189
35662
|
try {
|
|
35190
|
-
await
|
|
35663
|
+
await writeFile15(mapAbsPath, updated, "utf-8");
|
|
35191
35664
|
} catch (writeErr) {
|
|
35192
35665
|
console.warn(
|
|
35193
35666
|
" Warning: could not write map file " + stampedEntry.map_file + " \u2014 " + (writeErr instanceof Error ? writeErr.message : String(writeErr)) + " \u2014 stamped manifest only"
|
|
@@ -35340,19 +35813,19 @@ var init_branch_port_resolver = __esm({
|
|
|
35340
35813
|
});
|
|
35341
35814
|
|
|
35342
35815
|
// src/lib/migrate-local-config.ts
|
|
35343
|
-
import { mkdir as
|
|
35344
|
-
import { join as
|
|
35816
|
+
import { mkdir as mkdir8, readFile as readFile21, unlink as unlink6, writeFile as writeFile16 } from "node:fs/promises";
|
|
35817
|
+
import { join as join38 } from "node:path";
|
|
35345
35818
|
function legacySharedPath(projectPath) {
|
|
35346
|
-
return
|
|
35819
|
+
return join38(projectPath, ".codebyplan.json");
|
|
35347
35820
|
}
|
|
35348
35821
|
function legacyLocalPath(projectPath) {
|
|
35349
|
-
return
|
|
35822
|
+
return join38(projectPath, ".codebyplan.local.json");
|
|
35350
35823
|
}
|
|
35351
35824
|
function newDirPath(projectPath) {
|
|
35352
|
-
return
|
|
35825
|
+
return join38(projectPath, ".codebyplan");
|
|
35353
35826
|
}
|
|
35354
35827
|
function sentinelPath(projectPath) {
|
|
35355
|
-
return
|
|
35828
|
+
return join38(projectPath, ".codebyplan", "repo.json");
|
|
35356
35829
|
}
|
|
35357
35830
|
async function statSafe(p) {
|
|
35358
35831
|
const { stat: stat2 } = await import("node:fs/promises");
|
|
@@ -35391,7 +35864,7 @@ async function runLocalMigration(projectPath) {
|
|
|
35391
35864
|
}
|
|
35392
35865
|
let legacyRaw;
|
|
35393
35866
|
try {
|
|
35394
|
-
legacyRaw = await
|
|
35867
|
+
legacyRaw = await readFile21(legacySharedPath(projectPath), "utf-8");
|
|
35395
35868
|
} catch {
|
|
35396
35869
|
return {
|
|
35397
35870
|
migrated: true,
|
|
@@ -35416,7 +35889,7 @@ async function runLocalMigration(projectPath) {
|
|
|
35416
35889
|
}
|
|
35417
35890
|
const cfg = parsed;
|
|
35418
35891
|
try {
|
|
35419
|
-
await
|
|
35892
|
+
await mkdir8(newDirPath(projectPath), { recursive: true });
|
|
35420
35893
|
} catch (err) {
|
|
35421
35894
|
const code = err.code;
|
|
35422
35895
|
if (code === "ENOTDIR" || code === "EEXIST") {
|
|
@@ -35431,8 +35904,8 @@ async function runLocalMigration(projectPath) {
|
|
|
35431
35904
|
if ("repo_id" in cfg) repoJson.repo_id = cfg.repo_id;
|
|
35432
35905
|
if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
|
|
35433
35906
|
if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
|
|
35434
|
-
await
|
|
35435
|
-
|
|
35907
|
+
await writeFile16(
|
|
35908
|
+
join38(projectPath, ".codebyplan", "repo.json"),
|
|
35436
35909
|
JSON.stringify(repoJson, null, 2) + "\n",
|
|
35437
35910
|
"utf-8"
|
|
35438
35911
|
);
|
|
@@ -35444,8 +35917,8 @@ async function runLocalMigration(projectPath) {
|
|
|
35444
35917
|
serverJson.auto_push_enabled = cfg.auto_push_enabled;
|
|
35445
35918
|
if ("port_allocations" in cfg)
|
|
35446
35919
|
serverJson.port_allocations = cfg.port_allocations;
|
|
35447
|
-
await
|
|
35448
|
-
|
|
35920
|
+
await writeFile16(
|
|
35921
|
+
join38(projectPath, ".codebyplan", "server.json"),
|
|
35449
35922
|
JSON.stringify(serverJson, null, 2) + "\n",
|
|
35450
35923
|
"utf-8"
|
|
35451
35924
|
);
|
|
@@ -35453,37 +35926,37 @@ async function runLocalMigration(projectPath) {
|
|
|
35453
35926
|
const gitJson = {};
|
|
35454
35927
|
if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
|
|
35455
35928
|
if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
|
|
35456
|
-
await
|
|
35457
|
-
|
|
35929
|
+
await writeFile16(
|
|
35930
|
+
join38(projectPath, ".codebyplan", "git.json"),
|
|
35458
35931
|
JSON.stringify(gitJson, null, 2) + "\n",
|
|
35459
35932
|
"utf-8"
|
|
35460
35933
|
);
|
|
35461
35934
|
filesChanged.push(".codebyplan/git.json");
|
|
35462
35935
|
const shipmentJson = {};
|
|
35463
35936
|
if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
|
|
35464
|
-
await
|
|
35465
|
-
|
|
35937
|
+
await writeFile16(
|
|
35938
|
+
join38(projectPath, ".codebyplan", "shipment.json"),
|
|
35466
35939
|
JSON.stringify(shipmentJson, null, 2) + "\n",
|
|
35467
35940
|
"utf-8"
|
|
35468
35941
|
);
|
|
35469
35942
|
filesChanged.push(".codebyplan/shipment.json");
|
|
35470
35943
|
const vendorJson = {};
|
|
35471
|
-
await
|
|
35472
|
-
|
|
35944
|
+
await writeFile16(
|
|
35945
|
+
join38(projectPath, ".codebyplan", "vendor.json"),
|
|
35473
35946
|
JSON.stringify(vendorJson, null, 2) + "\n",
|
|
35474
35947
|
"utf-8"
|
|
35475
35948
|
);
|
|
35476
35949
|
filesChanged.push(".codebyplan/vendor.json");
|
|
35477
35950
|
const e2eJson = {};
|
|
35478
|
-
await
|
|
35479
|
-
|
|
35951
|
+
await writeFile16(
|
|
35952
|
+
join38(projectPath, ".codebyplan", "e2e.json"),
|
|
35480
35953
|
JSON.stringify(e2eJson, null, 2) + "\n",
|
|
35481
35954
|
"utf-8"
|
|
35482
35955
|
);
|
|
35483
35956
|
filesChanged.push(".codebyplan/e2e.json");
|
|
35484
35957
|
const eslintJson = {};
|
|
35485
|
-
await
|
|
35486
|
-
|
|
35958
|
+
await writeFile16(
|
|
35959
|
+
join38(projectPath, ".codebyplan", "eslint.json"),
|
|
35487
35960
|
JSON.stringify(eslintJson, null, 2) + "\n",
|
|
35488
35961
|
"utf-8"
|
|
35489
35962
|
);
|
|
@@ -35494,9 +35967,9 @@ async function runLocalMigration(projectPath) {
|
|
|
35494
35967
|
"Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
|
|
35495
35968
|
);
|
|
35496
35969
|
}
|
|
35497
|
-
const gitignorePath =
|
|
35970
|
+
const gitignorePath = join38(projectPath, ".gitignore");
|
|
35498
35971
|
try {
|
|
35499
|
-
const gitignoreContent = await
|
|
35972
|
+
const gitignoreContent = await readFile21(gitignorePath, "utf-8");
|
|
35500
35973
|
const legacyLine = ".codebyplan.local.json";
|
|
35501
35974
|
const newLine = ".codebyplan/device.local.json";
|
|
35502
35975
|
const hasLegacy = gitignoreContent.split("\n").some((l) => l.trimEnd() === legacyLine);
|
|
@@ -35515,18 +35988,18 @@ async function runLocalMigration(projectPath) {
|
|
|
35515
35988
|
updated = gitignoreContent;
|
|
35516
35989
|
}
|
|
35517
35990
|
if (updated !== gitignoreContent) {
|
|
35518
|
-
await
|
|
35991
|
+
await writeFile16(gitignorePath, updated, "utf-8");
|
|
35519
35992
|
filesChanged.push(".gitignore");
|
|
35520
35993
|
}
|
|
35521
35994
|
} catch {
|
|
35522
35995
|
}
|
|
35523
35996
|
try {
|
|
35524
|
-
await
|
|
35997
|
+
await unlink6(legacySharedPath(projectPath));
|
|
35525
35998
|
filesChanged.push(".codebyplan.json (deleted)");
|
|
35526
35999
|
} catch {
|
|
35527
36000
|
}
|
|
35528
36001
|
try {
|
|
35529
|
-
await
|
|
36002
|
+
await unlink6(legacyLocalPath(projectPath));
|
|
35530
36003
|
filesChanged.push(".codebyplan.local.json (deleted)");
|
|
35531
36004
|
} catch {
|
|
35532
36005
|
}
|
|
@@ -35556,8 +36029,8 @@ __export(config_exports, {
|
|
|
35556
36029
|
runConfig: () => runConfig,
|
|
35557
36030
|
runConfigMigrate: () => runConfigMigrate
|
|
35558
36031
|
});
|
|
35559
|
-
import { mkdir as
|
|
35560
|
-
import { join as
|
|
36032
|
+
import { mkdir as mkdir9, readFile as readFile22, writeFile as writeFile17 } from "node:fs/promises";
|
|
36033
|
+
import { join as join39 } from "node:path";
|
|
35561
36034
|
async function runConfig() {
|
|
35562
36035
|
const flags = parseFlags(3);
|
|
35563
36036
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -35590,7 +36063,7 @@ async function runConfig() {
|
|
|
35590
36063
|
console.log("\n Config complete.\n");
|
|
35591
36064
|
}
|
|
35592
36065
|
async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
35593
|
-
const codebyplanDir =
|
|
36066
|
+
const codebyplanDir = join39(projectPath, ".codebyplan");
|
|
35594
36067
|
const {
|
|
35595
36068
|
currentBranch,
|
|
35596
36069
|
portAllocations,
|
|
@@ -35666,7 +36139,7 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
35666
36139
|
console.log(" Config would be updated (dry-run).");
|
|
35667
36140
|
return;
|
|
35668
36141
|
}
|
|
35669
|
-
await
|
|
36142
|
+
await mkdir9(codebyplanDir, { recursive: true });
|
|
35670
36143
|
const files = [
|
|
35671
36144
|
{ name: "repo.json", payload: repoPayload },
|
|
35672
36145
|
{ name: "server.json", payload: serverPayload },
|
|
@@ -35683,16 +36156,16 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
35683
36156
|
];
|
|
35684
36157
|
let anyUpdated = false;
|
|
35685
36158
|
for (const { name, payload, createOnly } of files) {
|
|
35686
|
-
const filePath =
|
|
36159
|
+
const filePath = join39(codebyplanDir, name);
|
|
35687
36160
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
35688
36161
|
let currentJson = "";
|
|
35689
36162
|
try {
|
|
35690
|
-
currentJson = await
|
|
36163
|
+
currentJson = await readFile22(filePath, "utf-8");
|
|
35691
36164
|
} catch {
|
|
35692
36165
|
}
|
|
35693
36166
|
if (createOnly && currentJson !== "") continue;
|
|
35694
36167
|
if (currentJson === newJson) continue;
|
|
35695
|
-
await
|
|
36168
|
+
await writeFile17(filePath, newJson, "utf-8");
|
|
35696
36169
|
console.log(` Updated .codebyplan/${name}`);
|
|
35697
36170
|
anyUpdated = true;
|
|
35698
36171
|
}
|
|
@@ -35702,8 +36175,8 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
35702
36175
|
}
|
|
35703
36176
|
async function readRepoConfig(projectPath) {
|
|
35704
36177
|
try {
|
|
35705
|
-
const raw = await
|
|
35706
|
-
|
|
36178
|
+
const raw = await readFile22(
|
|
36179
|
+
join39(projectPath, ".codebyplan", "repo.json"),
|
|
35707
36180
|
"utf-8"
|
|
35708
36181
|
);
|
|
35709
36182
|
return JSON.parse(raw);
|
|
@@ -35713,8 +36186,8 @@ async function readRepoConfig(projectPath) {
|
|
|
35713
36186
|
}
|
|
35714
36187
|
async function readServerConfig(projectPath) {
|
|
35715
36188
|
try {
|
|
35716
|
-
const raw = await
|
|
35717
|
-
|
|
36189
|
+
const raw = await readFile22(
|
|
36190
|
+
join39(projectPath, ".codebyplan", "server.json"),
|
|
35718
36191
|
"utf-8"
|
|
35719
36192
|
);
|
|
35720
36193
|
return JSON.parse(raw);
|
|
@@ -35724,8 +36197,8 @@ async function readServerConfig(projectPath) {
|
|
|
35724
36197
|
}
|
|
35725
36198
|
async function readGitConfig2(projectPath) {
|
|
35726
36199
|
try {
|
|
35727
|
-
const raw = await
|
|
35728
|
-
|
|
36200
|
+
const raw = await readFile22(
|
|
36201
|
+
join39(projectPath, ".codebyplan", "git.json"),
|
|
35729
36202
|
"utf-8"
|
|
35730
36203
|
);
|
|
35731
36204
|
return JSON.parse(raw);
|
|
@@ -35735,8 +36208,8 @@ async function readGitConfig2(projectPath) {
|
|
|
35735
36208
|
}
|
|
35736
36209
|
async function readShipmentConfig2(projectPath) {
|
|
35737
36210
|
try {
|
|
35738
|
-
const raw = await
|
|
35739
|
-
|
|
36211
|
+
const raw = await readFile22(
|
|
36212
|
+
join39(projectPath, ".codebyplan", "shipment.json"),
|
|
35740
36213
|
"utf-8"
|
|
35741
36214
|
);
|
|
35742
36215
|
return JSON.parse(raw);
|
|
@@ -35746,8 +36219,8 @@ async function readShipmentConfig2(projectPath) {
|
|
|
35746
36219
|
}
|
|
35747
36220
|
async function readVendorConfig(projectPath) {
|
|
35748
36221
|
try {
|
|
35749
|
-
const raw = await
|
|
35750
|
-
|
|
36222
|
+
const raw = await readFile22(
|
|
36223
|
+
join39(projectPath, ".codebyplan", "vendor.json"),
|
|
35751
36224
|
"utf-8"
|
|
35752
36225
|
);
|
|
35753
36226
|
return JSON.parse(raw);
|
|
@@ -35757,8 +36230,8 @@ async function readVendorConfig(projectPath) {
|
|
|
35757
36230
|
}
|
|
35758
36231
|
async function readE2eConfig2(projectPath) {
|
|
35759
36232
|
try {
|
|
35760
|
-
const raw = await
|
|
35761
|
-
|
|
36233
|
+
const raw = await readFile22(
|
|
36234
|
+
join39(projectPath, ".codebyplan", "e2e.json"),
|
|
35762
36235
|
"utf-8"
|
|
35763
36236
|
);
|
|
35764
36237
|
return JSON.parse(raw);
|
|
@@ -35768,8 +36241,8 @@ async function readE2eConfig2(projectPath) {
|
|
|
35768
36241
|
}
|
|
35769
36242
|
async function readServerLocalConfig(projectPath) {
|
|
35770
36243
|
try {
|
|
35771
|
-
const raw = await
|
|
35772
|
-
|
|
36244
|
+
const raw = await readFile22(
|
|
36245
|
+
join39(projectPath, ".codebyplan", "server.local.json"),
|
|
35773
36246
|
"utf-8"
|
|
35774
36247
|
);
|
|
35775
36248
|
return JSON.parse(raw);
|
|
@@ -35841,8 +36314,8 @@ var init_config = __esm({
|
|
|
35841
36314
|
});
|
|
35842
36315
|
|
|
35843
36316
|
// src/lib/server-detect.ts
|
|
35844
|
-
import { readFile as
|
|
35845
|
-
import { join as
|
|
36317
|
+
import { readFile as readFile23, readdir as readdir7, access as access7 } from "node:fs/promises";
|
|
36318
|
+
import { join as join40 } from "node:path";
|
|
35846
36319
|
async function fileExists4(filePath) {
|
|
35847
36320
|
try {
|
|
35848
36321
|
await access7(filePath);
|
|
@@ -35853,8 +36326,8 @@ async function fileExists4(filePath) {
|
|
|
35853
36326
|
}
|
|
35854
36327
|
function detectPackageManager3(dir) {
|
|
35855
36328
|
return (async () => {
|
|
35856
|
-
if (await fileExists4(
|
|
35857
|
-
if (await fileExists4(
|
|
36329
|
+
if (await fileExists4(join40(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
36330
|
+
if (await fileExists4(join40(dir, "yarn.lock"))) return "yarn";
|
|
35858
36331
|
return "npm";
|
|
35859
36332
|
})();
|
|
35860
36333
|
}
|
|
@@ -35886,12 +36359,12 @@ function detectPortFromScripts(pkg) {
|
|
|
35886
36359
|
return null;
|
|
35887
36360
|
}
|
|
35888
36361
|
async function isMonorepo(dir) {
|
|
35889
|
-
return await fileExists4(
|
|
36362
|
+
return await fileExists4(join40(dir, "turbo.json")) || await fileExists4(join40(dir, "pnpm-workspace.yaml"));
|
|
35890
36363
|
}
|
|
35891
36364
|
async function detectServers(projectPath) {
|
|
35892
36365
|
let pkg;
|
|
35893
36366
|
try {
|
|
35894
|
-
const raw = await
|
|
36367
|
+
const raw = await readFile23(join40(projectPath, "package.json"), "utf-8");
|
|
35895
36368
|
pkg = JSON.parse(raw);
|
|
35896
36369
|
} catch {
|
|
35897
36370
|
return {
|
|
@@ -35907,15 +36380,15 @@ async function detectServers(projectPath) {
|
|
|
35907
36380
|
const mono = await isMonorepo(projectPath);
|
|
35908
36381
|
const servers = [];
|
|
35909
36382
|
if (mono) {
|
|
35910
|
-
const appsDir =
|
|
36383
|
+
const appsDir = join40(projectPath, "apps");
|
|
35911
36384
|
try {
|
|
35912
|
-
const entries = await
|
|
36385
|
+
const entries = await readdir7(appsDir, { withFileTypes: true });
|
|
35913
36386
|
const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
35914
36387
|
for (const entry of sorted) {
|
|
35915
36388
|
if (!entry.isDirectory()) continue;
|
|
35916
|
-
const appPkgPath =
|
|
36389
|
+
const appPkgPath = join40(appsDir, entry.name, "package.json");
|
|
35917
36390
|
try {
|
|
35918
|
-
const appRaw = await
|
|
36391
|
+
const appRaw = await readFile23(appPkgPath, "utf-8");
|
|
35919
36392
|
const appPkg = JSON.parse(appRaw);
|
|
35920
36393
|
const appName = entry.name;
|
|
35921
36394
|
const framework = detectFramework(appPkg);
|
|
@@ -35958,14 +36431,14 @@ var init_server_detect = __esm({
|
|
|
35958
36431
|
});
|
|
35959
36432
|
|
|
35960
36433
|
// src/lib/port-verify.ts
|
|
35961
|
-
import { readFile as
|
|
36434
|
+
import { readFile as readFile24 } from "node:fs/promises";
|
|
35962
36435
|
async function verifyPorts(projectPath, portAllocations) {
|
|
35963
36436
|
const mismatches = [];
|
|
35964
36437
|
const allocatedPorts = new Set(portAllocations.map((a) => a.port));
|
|
35965
36438
|
const packageJsonPaths = await findPackageJsonFiles(projectPath, projectPath);
|
|
35966
36439
|
for (const pkgPath of packageJsonPaths) {
|
|
35967
36440
|
try {
|
|
35968
|
-
const raw = await
|
|
36441
|
+
const raw = await readFile24(pkgPath, "utf-8");
|
|
35969
36442
|
const pkg = JSON.parse(raw);
|
|
35970
36443
|
const scriptPort = detectPortFromScripts(pkg);
|
|
35971
36444
|
if (scriptPort !== null && !allocatedPorts.has(scriptPort)) {
|
|
@@ -36028,7 +36501,7 @@ async function findUnallocatedApps(projectPath, portAllocations) {
|
|
|
36028
36501
|
}
|
|
36029
36502
|
let pkg;
|
|
36030
36503
|
try {
|
|
36031
|
-
const raw = await
|
|
36504
|
+
const raw = await readFile24(`${app.absPath}/package.json`, "utf-8");
|
|
36032
36505
|
pkg = JSON.parse(raw);
|
|
36033
36506
|
} catch {
|
|
36034
36507
|
continue;
|
|
@@ -36078,8 +36551,8 @@ __export(ports_exports, {
|
|
|
36078
36551
|
parseEnvFile: () => parseEnvFile,
|
|
36079
36552
|
runPorts: () => runPorts
|
|
36080
36553
|
});
|
|
36081
|
-
import { mkdir as
|
|
36082
|
-
import { join as
|
|
36554
|
+
import { mkdir as mkdir10, readFile as readFile25, writeFile as writeFile18 } from "node:fs/promises";
|
|
36555
|
+
import { join as join41 } from "node:path";
|
|
36083
36556
|
function printDetectionResult(result, projectPath) {
|
|
36084
36557
|
console.log(`
|
|
36085
36558
|
CodeByPlan Ports - List`);
|
|
@@ -36236,12 +36709,12 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
36236
36709
|
// which matches ServerLocalConfig.port_allocations — honest end-to-end.
|
|
36237
36710
|
port_allocations: portAllocations
|
|
36238
36711
|
};
|
|
36239
|
-
const codebyplanDir =
|
|
36240
|
-
const filePath =
|
|
36712
|
+
const codebyplanDir = join41(projectPath, ".codebyplan");
|
|
36713
|
+
const filePath = join41(codebyplanDir, "server.local.json");
|
|
36241
36714
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
36242
36715
|
let currentJson = "";
|
|
36243
36716
|
try {
|
|
36244
|
-
currentJson = await
|
|
36717
|
+
currentJson = await readFile25(filePath, "utf-8");
|
|
36245
36718
|
} catch {
|
|
36246
36719
|
}
|
|
36247
36720
|
if (currentJson === newJson) {
|
|
@@ -36252,18 +36725,18 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
36252
36725
|
console.log(" Would update .codebyplan/server.local.json (dry-run).");
|
|
36253
36726
|
return;
|
|
36254
36727
|
}
|
|
36255
|
-
await
|
|
36256
|
-
await
|
|
36728
|
+
await mkdir10(codebyplanDir, { recursive: true });
|
|
36729
|
+
await writeFile18(filePath, newJson, "utf-8");
|
|
36257
36730
|
console.log(
|
|
36258
36731
|
` Updated .codebyplan/server.local.json (branch '${currentBranch}', ${portAllocations.length} allocation${portAllocations.length === 1 ? "" : "s"}).`
|
|
36259
36732
|
);
|
|
36260
36733
|
}
|
|
36261
36734
|
async function provisionE2eEnv(projectPath, dryRun) {
|
|
36262
|
-
const relSource =
|
|
36263
|
-
const sourcePath =
|
|
36735
|
+
const relSource = join41("apps", "web", ".env.local");
|
|
36736
|
+
const sourcePath = join41(projectPath, relSource);
|
|
36264
36737
|
let sourceRaw;
|
|
36265
36738
|
try {
|
|
36266
|
-
sourceRaw = await
|
|
36739
|
+
sourceRaw = await readFile25(sourcePath, "utf-8");
|
|
36267
36740
|
} catch {
|
|
36268
36741
|
console.warn(
|
|
36269
36742
|
` Skipped .codebyplan/e2e.env \u2014 source ${relSource} not found.`
|
|
@@ -36292,12 +36765,12 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
36292
36765
|
);
|
|
36293
36766
|
return;
|
|
36294
36767
|
}
|
|
36295
|
-
const codebyplanDir =
|
|
36296
|
-
const filePath =
|
|
36768
|
+
const codebyplanDir = join41(projectPath, ".codebyplan");
|
|
36769
|
+
const filePath = join41(codebyplanDir, "e2e.env");
|
|
36297
36770
|
const newContent = lines.join("\n") + "\n";
|
|
36298
36771
|
let currentContent = "";
|
|
36299
36772
|
try {
|
|
36300
|
-
currentContent = await
|
|
36773
|
+
currentContent = await readFile25(filePath, "utf-8");
|
|
36301
36774
|
} catch {
|
|
36302
36775
|
}
|
|
36303
36776
|
if (currentContent === newContent) {
|
|
@@ -36308,8 +36781,8 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
36308
36781
|
console.log(" Would provision .codebyplan/e2e.env (dry-run).");
|
|
36309
36782
|
return;
|
|
36310
36783
|
}
|
|
36311
|
-
await
|
|
36312
|
-
await
|
|
36784
|
+
await mkdir10(codebyplanDir, { recursive: true });
|
|
36785
|
+
await writeFile18(filePath, newContent, "utf-8");
|
|
36313
36786
|
console.log(
|
|
36314
36787
|
` Provisioned .codebyplan/e2e.env (${lines.length} var${lines.length === 1 ? "" : "s"}).`
|
|
36315
36788
|
);
|
|
@@ -36517,8 +36990,8 @@ __export(docs_exports, {
|
|
|
36517
36990
|
stripRangePrefix: () => stripRangePrefix
|
|
36518
36991
|
});
|
|
36519
36992
|
import { existsSync as existsSync12 } from "node:fs";
|
|
36520
|
-
import { mkdir as
|
|
36521
|
-
import { dirname as
|
|
36993
|
+
import { mkdir as mkdir11, readFile as readFile26, readdir as readdir8, rm as rm2, writeFile as writeFile19 } from "node:fs/promises";
|
|
36994
|
+
import { dirname as dirname13, isAbsolute as isAbsolute3, join as join42, relative as relative7, sep as sep2 } from "node:path";
|
|
36522
36995
|
function selectDependencies(deps) {
|
|
36523
36996
|
const byName = /* @__PURE__ */ new Map();
|
|
36524
36997
|
for (const dep of deps) {
|
|
@@ -36572,12 +37045,12 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
36572
37045
|
}
|
|
36573
37046
|
async function resolveExactVersion(projectPath, dep) {
|
|
36574
37047
|
const candidateDirs = [projectPath];
|
|
36575
|
-
const sourceDir =
|
|
37048
|
+
const sourceDir = join42(projectPath, dirname13(dep.sourcePath));
|
|
36576
37049
|
if (sourceDir !== projectPath) candidateDirs.push(sourceDir);
|
|
36577
37050
|
for (const base of candidateDirs) {
|
|
36578
37051
|
try {
|
|
36579
|
-
const raw = await
|
|
36580
|
-
|
|
37052
|
+
const raw = await readFile26(
|
|
37053
|
+
join42(base, "node_modules", dep.name, "package.json"),
|
|
36581
37054
|
"utf-8"
|
|
36582
37055
|
);
|
|
36583
37056
|
const pkg = JSON.parse(raw);
|
|
@@ -36591,8 +37064,8 @@ async function resolveExactVersion(projectPath, dep) {
|
|
|
36591
37064
|
}
|
|
36592
37065
|
async function readVendorDocsPath(projectPath) {
|
|
36593
37066
|
try {
|
|
36594
|
-
const raw = await
|
|
36595
|
-
|
|
37067
|
+
const raw = await readFile26(
|
|
37068
|
+
join42(projectPath, ".codebyplan", "vendor.json"),
|
|
36596
37069
|
"utf-8"
|
|
36597
37070
|
);
|
|
36598
37071
|
const parsed = JSON.parse(raw);
|
|
@@ -36605,7 +37078,7 @@ async function readVendorDocsPath(projectPath) {
|
|
|
36605
37078
|
}
|
|
36606
37079
|
async function resolveDocsDir(projectPath, flags) {
|
|
36607
37080
|
const configured = flags["dir"] ?? await readVendorDocsPath(projectPath) ?? DEFAULT_DOCS_DIR;
|
|
36608
|
-
const absDir = isAbsolute3(configured) ? configured :
|
|
37081
|
+
const absDir = isAbsolute3(configured) ? configured : join42(projectPath, configured);
|
|
36609
37082
|
const rel = relative7(projectPath, absDir);
|
|
36610
37083
|
const relDir = rel === "" || rel.startsWith("..") ? null : rel.split(sep2).join("/");
|
|
36611
37084
|
return { absDir, relDir };
|
|
@@ -36614,7 +37087,7 @@ async function readDocsLock(absDir) {
|
|
|
36614
37087
|
const empty = { generated_at: "", libraries: {} };
|
|
36615
37088
|
let raw;
|
|
36616
37089
|
try {
|
|
36617
|
-
raw = await
|
|
37090
|
+
raw = await readFile26(join42(absDir, LOCK_FILE), "utf-8");
|
|
36618
37091
|
} catch {
|
|
36619
37092
|
return empty;
|
|
36620
37093
|
}
|
|
@@ -36710,10 +37183,10 @@ function buildTopIndex(outcomes) {
|
|
|
36710
37183
|
}
|
|
36711
37184
|
async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
36712
37185
|
const entry = `/${relDir}/`;
|
|
36713
|
-
const gitignorePath =
|
|
37186
|
+
const gitignorePath = join42(projectPath, ".gitignore");
|
|
36714
37187
|
let existing = "";
|
|
36715
37188
|
try {
|
|
36716
|
-
existing = await
|
|
37189
|
+
existing = await readFile26(gitignorePath, "utf-8");
|
|
36717
37190
|
} catch {
|
|
36718
37191
|
}
|
|
36719
37192
|
const lines = existing.split(/\r?\n/).map((l) => l.trim());
|
|
@@ -36725,7 +37198,7 @@ async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
|
36725
37198
|
content += `${GITIGNORE_COMMENT}
|
|
36726
37199
|
${entry}
|
|
36727
37200
|
`;
|
|
36728
|
-
await
|
|
37201
|
+
await writeFile19(gitignorePath, content, "utf-8");
|
|
36729
37202
|
}
|
|
36730
37203
|
return "added";
|
|
36731
37204
|
}
|
|
@@ -36733,7 +37206,7 @@ async function markUncovered(dep, exactVersion, ctx) {
|
|
|
36733
37206
|
console.log(
|
|
36734
37207
|
` uncovered ${dep.name}@${exactVersion || "?"} \u2014 no docs in the library mirror`
|
|
36735
37208
|
);
|
|
36736
|
-
const libPath =
|
|
37209
|
+
const libPath = join42(ctx.absDir, libDirName(dep.name));
|
|
36737
37210
|
if (existsSync12(libPath)) {
|
|
36738
37211
|
if (ctx.dryRun) {
|
|
36739
37212
|
console.log(` would remove stale mirror dir ${libPath}`);
|
|
@@ -36786,14 +37259,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
36786
37259
|
}
|
|
36787
37260
|
}
|
|
36788
37261
|
const lockEntry = ctx.lock.libraries[dep.name];
|
|
36789
|
-
const libPath =
|
|
36790
|
-
const versionPath =
|
|
37262
|
+
const libPath = join42(ctx.absDir, libDirName(dep.name));
|
|
37263
|
+
const versionPath = join42(libPath, manifest.resolved_version);
|
|
36791
37264
|
if (manifestMatchesLock(manifest, lockEntry)) {
|
|
36792
37265
|
console.log(` unchanged ${dep.name}@${manifest.resolved_version}`);
|
|
36793
|
-
if (!ctx.dryRun && !existsSync12(
|
|
36794
|
-
await
|
|
36795
|
-
await
|
|
36796
|
-
|
|
37266
|
+
if (!ctx.dryRun && !existsSync12(join42(libPath, "INDEX.md"))) {
|
|
37267
|
+
await mkdir11(libPath, { recursive: true });
|
|
37268
|
+
await writeFile19(
|
|
37269
|
+
join42(libPath, "INDEX.md"),
|
|
36797
37270
|
buildLibIndex(dep.name, manifest),
|
|
36798
37271
|
"utf-8"
|
|
36799
37272
|
);
|
|
@@ -36815,14 +37288,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
36815
37288
|
);
|
|
36816
37289
|
continue;
|
|
36817
37290
|
}
|
|
36818
|
-
const target =
|
|
37291
|
+
const target = join42(versionPath, rel);
|
|
36819
37292
|
if (sameVersionLockFiles[file.path] === file.content_hash && existsSync12(target)) {
|
|
36820
37293
|
continue;
|
|
36821
37294
|
}
|
|
36822
37295
|
written++;
|
|
36823
37296
|
if (!ctx.dryRun) {
|
|
36824
|
-
await
|
|
36825
|
-
await
|
|
37297
|
+
await mkdir11(dirname13(target), { recursive: true });
|
|
37298
|
+
await writeFile19(target, file.content, "utf-8");
|
|
36826
37299
|
}
|
|
36827
37300
|
}
|
|
36828
37301
|
let removedFiles = 0;
|
|
@@ -36833,13 +37306,13 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
36833
37306
|
const rel = sanitizeDocPath(lockedPath);
|
|
36834
37307
|
if (rel === null) continue;
|
|
36835
37308
|
removedFiles++;
|
|
36836
|
-
if (!ctx.dryRun) await rm2(
|
|
37309
|
+
if (!ctx.dryRun) await rm2(join42(versionPath, rel), { force: true });
|
|
36837
37310
|
}
|
|
36838
37311
|
}
|
|
36839
37312
|
let removedVersionDirs = 0;
|
|
36840
37313
|
let libEntries = [];
|
|
36841
37314
|
try {
|
|
36842
|
-
libEntries = await
|
|
37315
|
+
libEntries = await readdir8(libPath, { withFileTypes: true });
|
|
36843
37316
|
} catch {
|
|
36844
37317
|
}
|
|
36845
37318
|
for (const entry of libEntries) {
|
|
@@ -36848,13 +37321,13 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
36848
37321
|
}
|
|
36849
37322
|
removedVersionDirs++;
|
|
36850
37323
|
if (!ctx.dryRun) {
|
|
36851
|
-
await rm2(
|
|
37324
|
+
await rm2(join42(libPath, entry.name), { recursive: true, force: true });
|
|
36852
37325
|
}
|
|
36853
37326
|
}
|
|
36854
37327
|
if (!ctx.dryRun) {
|
|
36855
|
-
await
|
|
36856
|
-
await
|
|
36857
|
-
|
|
37328
|
+
await mkdir11(libPath, { recursive: true });
|
|
37329
|
+
await writeFile19(
|
|
37330
|
+
join42(libPath, "INDEX.md"),
|
|
36858
37331
|
buildLibIndex(dep.name, manifest),
|
|
36859
37332
|
"utf-8"
|
|
36860
37333
|
);
|
|
@@ -36907,8 +37380,8 @@ async function runDocsSync() {
|
|
|
36907
37380
|
(dep) => syncOneLibrary(dep, ctx)
|
|
36908
37381
|
);
|
|
36909
37382
|
if (!dryRun) {
|
|
36910
|
-
await
|
|
36911
|
-
await
|
|
37383
|
+
await mkdir11(absDir, { recursive: true });
|
|
37384
|
+
await writeFile19(join42(absDir, "INDEX.md"), buildTopIndex(outcomes), "utf-8");
|
|
36912
37385
|
const libraries = {};
|
|
36913
37386
|
for (const o of outcomes) {
|
|
36914
37387
|
if (o.kind === "synced" || o.kind === "unchanged") {
|
|
@@ -36933,8 +37406,8 @@ async function runDocsSync() {
|
|
|
36933
37406
|
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
36934
37407
|
libraries: sortedLibraries
|
|
36935
37408
|
};
|
|
36936
|
-
await
|
|
36937
|
-
|
|
37409
|
+
await writeFile19(
|
|
37410
|
+
join42(absDir, LOCK_FILE),
|
|
36938
37411
|
JSON.stringify(newLock, null, 2) + "\n",
|
|
36939
37412
|
"utf-8"
|
|
36940
37413
|
);
|
|
@@ -36969,14 +37442,14 @@ async function runDocsSync() {
|
|
|
36969
37442
|
async function countFilesRecursively(dirPath) {
|
|
36970
37443
|
let entries;
|
|
36971
37444
|
try {
|
|
36972
|
-
entries = await
|
|
37445
|
+
entries = await readdir8(dirPath, { withFileTypes: true });
|
|
36973
37446
|
} catch {
|
|
36974
37447
|
return 0;
|
|
36975
37448
|
}
|
|
36976
37449
|
let count = 0;
|
|
36977
37450
|
for (const entry of entries) {
|
|
36978
37451
|
if (entry.isDirectory()) {
|
|
36979
|
-
count += await countFilesRecursively(
|
|
37452
|
+
count += await countFilesRecursively(join42(dirPath, entry.name));
|
|
36980
37453
|
} else if (entry.isFile()) {
|
|
36981
37454
|
count++;
|
|
36982
37455
|
}
|
|
@@ -36993,7 +37466,7 @@ async function runDocsStatus() {
|
|
|
36993
37466
|
`);
|
|
36994
37467
|
let raw;
|
|
36995
37468
|
try {
|
|
36996
|
-
raw = await
|
|
37469
|
+
raw = await readFile26(join42(absDir, LOCK_FILE), "utf-8");
|
|
36997
37470
|
} catch {
|
|
36998
37471
|
console.log(
|
|
36999
37472
|
` No ${LOCK_FILE} found \u2014 run \`codebyplan docs sync\` first.
|
|
@@ -37022,7 +37495,7 @@ async function runDocsStatus() {
|
|
|
37022
37495
|
let outOfSync = 0;
|
|
37023
37496
|
for (const name of names) {
|
|
37024
37497
|
const entry = lock.libraries[name];
|
|
37025
|
-
const versionPath =
|
|
37498
|
+
const versionPath = join42(absDir, libDirName(name), entry.resolved_version);
|
|
37026
37499
|
const expected = Object.keys(entry.files).length;
|
|
37027
37500
|
if (!existsSync12(versionPath)) {
|
|
37028
37501
|
outOfSync++;
|
|
@@ -37110,7 +37583,7 @@ var init_docs = __esm({
|
|
|
37110
37583
|
|
|
37111
37584
|
// src/lib/check-baseline.ts
|
|
37112
37585
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
37113
|
-
import { join as
|
|
37586
|
+
import { join as join43 } from "node:path";
|
|
37114
37587
|
function emptyBaseline() {
|
|
37115
37588
|
return {
|
|
37116
37589
|
lint: { known_failing: [] },
|
|
@@ -37120,7 +37593,7 @@ function emptyBaseline() {
|
|
|
37120
37593
|
};
|
|
37121
37594
|
}
|
|
37122
37595
|
function loadBaseline(projectRoot) {
|
|
37123
|
-
const filePath =
|
|
37596
|
+
const filePath = join43(projectRoot, BASELINE_FILENAME);
|
|
37124
37597
|
try {
|
|
37125
37598
|
const raw = readFileSync12(filePath, "utf-8");
|
|
37126
37599
|
const parsed = JSON.parse(raw);
|
|
@@ -37144,7 +37617,7 @@ function loadBaseline(projectRoot) {
|
|
|
37144
37617
|
}
|
|
37145
37618
|
}
|
|
37146
37619
|
function saveBaseline(projectRoot, baseline) {
|
|
37147
|
-
const filePath =
|
|
37620
|
+
const filePath = join43(projectRoot, BASELINE_FILENAME);
|
|
37148
37621
|
writeFileSync8(filePath, JSON.stringify(baseline, null, 2) + "\n", "utf-8");
|
|
37149
37622
|
}
|
|
37150
37623
|
function diffBaseline(check, currentFailingPackages, baseline) {
|
|
@@ -37194,7 +37667,7 @@ var init_check_baseline = __esm({
|
|
|
37194
37667
|
|
|
37195
37668
|
// src/lib/check.ts
|
|
37196
37669
|
import { readFileSync as readFileSync13, existsSync as existsSync13 } from "node:fs";
|
|
37197
|
-
import { join as
|
|
37670
|
+
import { join as join44 } from "node:path";
|
|
37198
37671
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
37199
37672
|
function hasSentinelValue(arrays) {
|
|
37200
37673
|
const SENTINELS = /* @__PURE__ */ new Set([
|
|
@@ -37262,9 +37735,9 @@ function parseFailingPackagesFromSummary(summaryPath) {
|
|
|
37262
37735
|
return Array.from(failing).sort();
|
|
37263
37736
|
}
|
|
37264
37737
|
function resolveTurboBin(projectRoot) {
|
|
37265
|
-
const localBin =
|
|
37738
|
+
const localBin = join44(projectRoot, "node_modules", ".bin", "turbo");
|
|
37266
37739
|
if (existsSync13(localBin)) return localBin;
|
|
37267
|
-
const workspaceRootBin =
|
|
37740
|
+
const workspaceRootBin = join44(
|
|
37268
37741
|
projectRoot,
|
|
37269
37742
|
"..",
|
|
37270
37743
|
"..",
|
|
@@ -37781,7 +38254,7 @@ var init_check2 = __esm({
|
|
|
37781
38254
|
|
|
37782
38255
|
// src/lib/claude-plan.ts
|
|
37783
38256
|
import * as fs13 from "node:fs";
|
|
37784
|
-
import * as
|
|
38257
|
+
import * as path18 from "node:path";
|
|
37785
38258
|
function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
37786
38259
|
const packaged = walkTemplates(templatesDir);
|
|
37787
38260
|
const packagedBySrc = new Map(packaged.map((f) => [f.src, f]));
|
|
@@ -37795,8 +38268,8 @@ function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
|
37795
38268
|
};
|
|
37796
38269
|
for (const pkg of packaged) {
|
|
37797
38270
|
const inManifest = manifestBySrc.get(pkg.src);
|
|
37798
|
-
const absDest =
|
|
37799
|
-
const absSrc =
|
|
38271
|
+
const absDest = path18.join(projectDir, ".claude", pkg.dest);
|
|
38272
|
+
const absSrc = path18.join(templatesDir, pkg.src);
|
|
37800
38273
|
if (!inManifest) {
|
|
37801
38274
|
plan.newOptIn.push({
|
|
37802
38275
|
packaged: { src: pkg.src, dest: pkg.dest, hash: pkg.hash },
|
|
@@ -37845,7 +38318,7 @@ __export(status_exports, {
|
|
|
37845
38318
|
runStatus: () => runStatus2
|
|
37846
38319
|
});
|
|
37847
38320
|
import * as fs14 from "node:fs";
|
|
37848
|
-
import * as
|
|
38321
|
+
import * as path19 from "node:path";
|
|
37849
38322
|
import { execSync as execSync8 } from "node:child_process";
|
|
37850
38323
|
function makeFailSafe(checked_at) {
|
|
37851
38324
|
return {
|
|
@@ -37954,12 +38427,12 @@ async function runStatus2(argv) {
|
|
|
37954
38427
|
const latest = fetchLatestVersion();
|
|
37955
38428
|
const newer = latest !== null && compareSemver(latest, installed) > 0;
|
|
37956
38429
|
let settings_drift = false;
|
|
37957
|
-
const settingsPath =
|
|
37958
|
-
const baseSettingsPath =
|
|
38430
|
+
const settingsPath = path19.join(projectDir, ".claude", "settings.json");
|
|
38431
|
+
const baseSettingsPath = path19.join(
|
|
37959
38432
|
templatesDir,
|
|
37960
38433
|
"settings.project.base.json"
|
|
37961
38434
|
);
|
|
37962
|
-
const hooksJsonPath =
|
|
38435
|
+
const hooksJsonPath = path19.join(templatesDir, "hooks", "hooks.json");
|
|
37963
38436
|
if (fs14.existsSync(settingsPath)) {
|
|
37964
38437
|
try {
|
|
37965
38438
|
const settingsRaw = fs14.readFileSync(settingsPath, "utf8");
|
|
@@ -38029,10 +38502,10 @@ function emitResult(result, writeCache, quiet, projectDir) {
|
|
|
38029
38502
|
const json = JSON.stringify(result, null, 2);
|
|
38030
38503
|
if (writeCache) {
|
|
38031
38504
|
try {
|
|
38032
|
-
const cacheDir =
|
|
38505
|
+
const cacheDir = path19.join(projectDir, ".codebyplan");
|
|
38033
38506
|
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
38034
38507
|
fs14.writeFileSync(
|
|
38035
|
-
|
|
38508
|
+
path19.join(cacheDir, "claude-status.local.json"),
|
|
38036
38509
|
json + "\n",
|
|
38037
38510
|
"utf8"
|
|
38038
38511
|
);
|
|
@@ -38176,7 +38649,7 @@ __export(update_exports, {
|
|
|
38176
38649
|
});
|
|
38177
38650
|
import * as fs15 from "node:fs";
|
|
38178
38651
|
import * as os3 from "node:os";
|
|
38179
|
-
import * as
|
|
38652
|
+
import * as path20 from "node:path";
|
|
38180
38653
|
async function runUpdate(opts, deps = {}) {
|
|
38181
38654
|
await Promise.resolve();
|
|
38182
38655
|
const scope = opts.scope ?? "project";
|
|
@@ -38212,9 +38685,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38212
38685
|
finalManifestEntries.push(e);
|
|
38213
38686
|
}
|
|
38214
38687
|
for (const { packaged, absSrc } of plan.overwriteSafe) {
|
|
38215
|
-
const absDest =
|
|
38688
|
+
const absDest = path20.join(projectDir, ".claude", packaged.dest);
|
|
38216
38689
|
if (!opts.dryRun) {
|
|
38217
|
-
fs15.mkdirSync(
|
|
38690
|
+
fs15.mkdirSync(path20.dirname(absDest), { recursive: true });
|
|
38218
38691
|
fs15.copyFileSync(absSrc, absDest);
|
|
38219
38692
|
if (opts.verbose) console.log(`updated ${packaged.dest}`);
|
|
38220
38693
|
} else if (opts.verbose) {
|
|
@@ -38227,7 +38700,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38227
38700
|
absSrc,
|
|
38228
38701
|
onDiskContent
|
|
38229
38702
|
} of plan.overwriteHandEdited) {
|
|
38230
|
-
const absDest =
|
|
38703
|
+
const absDest = path20.join(projectDir, ".claude", packaged.dest);
|
|
38231
38704
|
const newContent = fs15.readFileSync(absSrc);
|
|
38232
38705
|
const showDiff = () => {
|
|
38233
38706
|
console.log(
|
|
@@ -38240,7 +38713,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38240
38713
|
const answer = await promptOverwrite(packaged.dest, opts, showDiff);
|
|
38241
38714
|
if (answer === "overwrite") {
|
|
38242
38715
|
if (!opts.dryRun) {
|
|
38243
|
-
fs15.mkdirSync(
|
|
38716
|
+
fs15.mkdirSync(path20.dirname(absDest), { recursive: true });
|
|
38244
38717
|
fs15.copyFileSync(absSrc, absDest);
|
|
38245
38718
|
}
|
|
38246
38719
|
finalManifestEntries.push(packaged);
|
|
@@ -38256,9 +38729,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38256
38729
|
for (const { packaged, absSrc } of plan.newOptIn) {
|
|
38257
38730
|
const answer = await promptOptIn(packaged.dest, opts);
|
|
38258
38731
|
if (answer === "opt-in") {
|
|
38259
|
-
const absDest =
|
|
38732
|
+
const absDest = path20.join(projectDir, ".claude", packaged.dest);
|
|
38260
38733
|
if (!opts.dryRun) {
|
|
38261
|
-
fs15.mkdirSync(
|
|
38734
|
+
fs15.mkdirSync(path20.dirname(absDest), { recursive: true });
|
|
38262
38735
|
fs15.copyFileSync(absSrc, absDest);
|
|
38263
38736
|
}
|
|
38264
38737
|
finalManifestEntries.push(packaged);
|
|
@@ -38270,25 +38743,25 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38270
38743
|
for (const e of plan.removedFromPackage) {
|
|
38271
38744
|
const answer = await promptRemove(e.dest, opts);
|
|
38272
38745
|
if (answer === "remove") {
|
|
38273
|
-
const absDest =
|
|
38746
|
+
const absDest = path20.join(projectDir, ".claude", e.dest);
|
|
38274
38747
|
if (!opts.dryRun && fs15.existsSync(absDest)) {
|
|
38275
38748
|
fs15.rmSync(absDest);
|
|
38276
|
-
const claudeDir =
|
|
38277
|
-
let cur =
|
|
38278
|
-
while (cur !== claudeDir && cur !==
|
|
38279
|
-
if (
|
|
38749
|
+
const claudeDir = path20.join(projectDir, ".claude");
|
|
38750
|
+
let cur = path20.dirname(absDest);
|
|
38751
|
+
while (cur !== claudeDir && cur !== path20.dirname(cur)) {
|
|
38752
|
+
if (path20.dirname(cur) === claudeDir) break;
|
|
38280
38753
|
try {
|
|
38281
38754
|
fs15.rmdirSync(cur);
|
|
38282
38755
|
if (opts.verbose)
|
|
38283
38756
|
console.log(
|
|
38284
|
-
`pruned empty dir ${
|
|
38757
|
+
`pruned empty dir ${path20.relative(claudeDir, cur)}`
|
|
38285
38758
|
);
|
|
38286
|
-
cur =
|
|
38759
|
+
cur = path20.dirname(cur);
|
|
38287
38760
|
} catch (err) {
|
|
38288
38761
|
const code = err.code;
|
|
38289
38762
|
if (code !== "ENOTEMPTY" && code !== "ENOENT") {
|
|
38290
38763
|
console.warn(
|
|
38291
|
-
`codebyplan claude: could not prune empty dir ${
|
|
38764
|
+
`codebyplan claude: could not prune empty dir ${path20.relative(claudeDir, cur)}: ${err.message}`
|
|
38292
38765
|
);
|
|
38293
38766
|
}
|
|
38294
38767
|
break;
|
|
@@ -38300,12 +38773,12 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38300
38773
|
if (opts.verbose) console.log(`kept (untracked) ${e.dest}`);
|
|
38301
38774
|
}
|
|
38302
38775
|
}
|
|
38303
|
-
const hooksJsonPath =
|
|
38304
|
-
const baseSettingsPath =
|
|
38776
|
+
const hooksJsonPath = path20.join(templatesDir, "hooks", "hooks.json");
|
|
38777
|
+
const baseSettingsPath = path20.join(
|
|
38305
38778
|
templatesDir,
|
|
38306
38779
|
"settings.project.base.json"
|
|
38307
38780
|
);
|
|
38308
|
-
const settingsPath =
|
|
38781
|
+
const settingsPath = path20.join(projectDir, ".claude", "settings.json");
|
|
38309
38782
|
const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
|
|
38310
38783
|
if (fs15.existsSync(baseSettingsPath)) {
|
|
38311
38784
|
const base = JSON.parse(
|
|
@@ -38332,7 +38805,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38332
38805
|
deps.detectHealDeps
|
|
38333
38806
|
);
|
|
38334
38807
|
if (!opts.dryRun) {
|
|
38335
|
-
fs15.mkdirSync(
|
|
38808
|
+
fs15.mkdirSync(path20.dirname(settingsPath), { recursive: true });
|
|
38336
38809
|
fs15.writeFileSync(
|
|
38337
38810
|
settingsPath,
|
|
38338
38811
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
@@ -38348,7 +38821,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
38348
38821
|
);
|
|
38349
38822
|
if (opts.verbose && gitignoreAction !== "unchanged") {
|
|
38350
38823
|
console.log(
|
|
38351
|
-
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${
|
|
38824
|
+
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${path20.relative(projectDir, path20.join(projectDir, ".gitignore"))}`
|
|
38352
38825
|
);
|
|
38353
38826
|
}
|
|
38354
38827
|
if (!opts.dryRun) {
|
|
@@ -38388,9 +38861,9 @@ function runUpdateUser(opts, deps) {
|
|
|
38388
38861
|
return;
|
|
38389
38862
|
}
|
|
38390
38863
|
try {
|
|
38391
|
-
const userDir = deps.userDir ??
|
|
38392
|
-
const settingsPath =
|
|
38393
|
-
const userBaseSettingsPath =
|
|
38864
|
+
const userDir = deps.userDir ?? path20.join(os3.homedir(), ".claude");
|
|
38865
|
+
const settingsPath = path20.join(userDir, "settings.json");
|
|
38866
|
+
const userBaseSettingsPath = path20.join(
|
|
38394
38867
|
templatesDir,
|
|
38395
38868
|
"settings.user.base.json"
|
|
38396
38869
|
);
|
|
@@ -38462,7 +38935,7 @@ __export(uninstall_exports, {
|
|
|
38462
38935
|
});
|
|
38463
38936
|
import * as fs16 from "node:fs";
|
|
38464
38937
|
import * as os4 from "node:os";
|
|
38465
|
-
import * as
|
|
38938
|
+
import * as path21 from "node:path";
|
|
38466
38939
|
async function runUninstall(opts, deps = {}) {
|
|
38467
38940
|
await Promise.resolve();
|
|
38468
38941
|
const scope = opts.scope ?? "project";
|
|
@@ -38491,7 +38964,7 @@ async function runUninstall(opts, deps = {}) {
|
|
|
38491
38964
|
let removed = 0;
|
|
38492
38965
|
let warnings = 0;
|
|
38493
38966
|
for (const entry of manifest.files) {
|
|
38494
|
-
const abs =
|
|
38967
|
+
const abs = path21.join(projectDir, ".claude", entry.dest);
|
|
38495
38968
|
if (!fs16.existsSync(abs)) {
|
|
38496
38969
|
console.warn(
|
|
38497
38970
|
`codebyplan claude uninstall: ${entry.dest} already absent (skipping).`
|
|
@@ -38515,12 +38988,12 @@ async function runUninstall(opts, deps = {}) {
|
|
|
38515
38988
|
if (!opts.dryRun) {
|
|
38516
38989
|
pruneEmptyManagedDirs(projectDir);
|
|
38517
38990
|
}
|
|
38518
|
-
const settingsPath =
|
|
38991
|
+
const settingsPath = path21.join(projectDir, ".claude", "settings.json");
|
|
38519
38992
|
if (fs16.existsSync(settingsPath)) {
|
|
38520
38993
|
const settings = JSON.parse(
|
|
38521
38994
|
fs16.readFileSync(settingsPath, "utf8")
|
|
38522
38995
|
);
|
|
38523
|
-
const baseSettingsPath = templatesDir ?
|
|
38996
|
+
const baseSettingsPath = templatesDir ? path21.join(templatesDir, "settings.project.base.json") : null;
|
|
38524
38997
|
if (baseSettingsPath && fs16.existsSync(baseSettingsPath)) {
|
|
38525
38998
|
const base = JSON.parse(
|
|
38526
38999
|
fs16.readFileSync(baseSettingsPath, "utf8")
|
|
@@ -38578,7 +39051,7 @@ function runUninstallUser(opts, deps) {
|
|
|
38578
39051
|
}
|
|
38579
39052
|
}
|
|
38580
39053
|
try {
|
|
38581
|
-
const userDir = deps.userDir ??
|
|
39054
|
+
const userDir = deps.userDir ?? path21.join(os4.homedir(), ".claude");
|
|
38582
39055
|
const existingManifest = readManifestForScope("user", userDir);
|
|
38583
39056
|
if (!existingManifest) {
|
|
38584
39057
|
console.error(
|
|
@@ -38587,12 +39060,12 @@ function runUninstallUser(opts, deps) {
|
|
|
38587
39060
|
process.exitCode = 1;
|
|
38588
39061
|
return;
|
|
38589
39062
|
}
|
|
38590
|
-
const settingsPath =
|
|
39063
|
+
const settingsPath = path21.join(userDir, "settings.json");
|
|
38591
39064
|
if (fs16.existsSync(settingsPath)) {
|
|
38592
39065
|
const settings = JSON.parse(
|
|
38593
39066
|
fs16.readFileSync(settingsPath, "utf8")
|
|
38594
39067
|
);
|
|
38595
|
-
const userBaseSettingsPath = templatesDir != null ?
|
|
39068
|
+
const userBaseSettingsPath = templatesDir != null ? path21.join(templatesDir, "settings.user.base.json") : null;
|
|
38596
39069
|
if (userBaseSettingsPath && fs16.existsSync(userBaseSettingsPath)) {
|
|
38597
39070
|
const userBase = JSON.parse(
|
|
38598
39071
|
fs16.readFileSync(userBaseSettingsPath, "utf8")
|
|
@@ -38633,7 +39106,7 @@ function runUninstallUser(opts, deps) {
|
|
|
38633
39106
|
function pruneEmptyManagedDirs(projectDir) {
|
|
38634
39107
|
const managedRoots = ["skills", "agents", "hooks", "rules"];
|
|
38635
39108
|
for (const root of managedRoots) {
|
|
38636
|
-
const abs =
|
|
39109
|
+
const abs = path21.join(projectDir, ".claude", root);
|
|
38637
39110
|
if (!fs16.existsSync(abs)) continue;
|
|
38638
39111
|
pruneLeafFirst(abs);
|
|
38639
39112
|
}
|
|
@@ -38644,7 +39117,7 @@ function pruneLeafFirst(dir) {
|
|
|
38644
39117
|
if (!stat2.isDirectory()) return;
|
|
38645
39118
|
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
38646
39119
|
if (entry.isDirectory()) {
|
|
38647
|
-
pruneLeafFirst(
|
|
39120
|
+
pruneLeafFirst(path21.join(dir, entry.name));
|
|
38648
39121
|
}
|
|
38649
39122
|
}
|
|
38650
39123
|
const remaining = fs16.readdirSync(dir);
|
|
@@ -38665,7 +39138,7 @@ var init_uninstall = __esm({
|
|
|
38665
39138
|
|
|
38666
39139
|
// src/lib/verify-parity.ts
|
|
38667
39140
|
import * as fs17 from "node:fs";
|
|
38668
|
-
import * as
|
|
39141
|
+
import * as path22 from "node:path";
|
|
38669
39142
|
function isValidScope(s) {
|
|
38670
39143
|
return s === "org-shared" || s === "project-shared" || REPO_ONLY_RE.test(s);
|
|
38671
39144
|
}
|
|
@@ -38682,25 +39155,25 @@ function checkSiblingParity(opts) {
|
|
|
38682
39155
|
expectedOneSided = DEFAULT_EXPECTED_ONE_SIDED,
|
|
38683
39156
|
ignoredSubtrees
|
|
38684
39157
|
} = opts;
|
|
38685
|
-
const defaultIgnored = [
|
|
39158
|
+
const defaultIgnored = [path22.join(claudeDir, "hooks", "__test-fixtures__")];
|
|
38686
39159
|
const ignored = ignoredSubtrees ?? defaultIgnored;
|
|
38687
39160
|
const violations = [];
|
|
38688
39161
|
const claudeSideRels = /* @__PURE__ */ new Set();
|
|
38689
39162
|
for (const scanDir of SCAN_DIRS) {
|
|
38690
|
-
const baseDir =
|
|
39163
|
+
const baseDir = path22.join(claudeDir, scanDir);
|
|
38691
39164
|
if (!fs17.existsSync(baseDir)) continue;
|
|
38692
39165
|
const entries = readdirRecursive(baseDir);
|
|
38693
39166
|
for (const entry of entries) {
|
|
38694
|
-
const absPath =
|
|
39167
|
+
const absPath = path22.join(baseDir, entry);
|
|
38695
39168
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
38696
39169
|
if (ignored.some(
|
|
38697
|
-
(ig) => absPath.startsWith(ig +
|
|
39170
|
+
(ig) => absPath.startsWith(ig + path22.sep) || absPath === ig
|
|
38698
39171
|
)) {
|
|
38699
39172
|
continue;
|
|
38700
39173
|
}
|
|
38701
|
-
const relPath =
|
|
39174
|
+
const relPath = path22.join(scanDir, entry).split(path22.sep).join("/");
|
|
38702
39175
|
claudeSideRels.add(relPath);
|
|
38703
|
-
const templatePath =
|
|
39176
|
+
const templatePath = path22.join(templatesDir, relPath);
|
|
38704
39177
|
if (!fs17.existsSync(templatePath)) {
|
|
38705
39178
|
if (!expectedOneSided.has(relPath) && !isScaffoldFile(entry)) {
|
|
38706
39179
|
violations.push({ type: "missing-twin", path: relPath });
|
|
@@ -38715,14 +39188,14 @@ function checkSiblingParity(opts) {
|
|
|
38715
39188
|
}
|
|
38716
39189
|
}
|
|
38717
39190
|
for (const scanDir of SCAN_DIRS) {
|
|
38718
|
-
const tplBase =
|
|
39191
|
+
const tplBase = path22.join(templatesDir, scanDir);
|
|
38719
39192
|
if (!fs17.existsSync(tplBase)) continue;
|
|
38720
39193
|
const entries = readdirRecursive(tplBase);
|
|
38721
39194
|
for (const entry of entries) {
|
|
38722
|
-
const absPath =
|
|
39195
|
+
const absPath = path22.join(tplBase, entry);
|
|
38723
39196
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
38724
39197
|
if (isScaffoldFile(entry)) continue;
|
|
38725
|
-
const relPath =
|
|
39198
|
+
const relPath = path22.join(scanDir, entry).split(path22.sep).join("/");
|
|
38726
39199
|
if (!claudeSideRels.has(relPath) && !expectedOneSided.has(relPath)) {
|
|
38727
39200
|
violations.push({ type: "extra-twin", path: relPath });
|
|
38728
39201
|
}
|
|
@@ -38758,18 +39231,18 @@ function checkScopeMarkers(opts) {
|
|
|
38758
39231
|
const twinDetectionActive = templatesDir != null && fs17.existsSync(templatesDir);
|
|
38759
39232
|
const violations = [];
|
|
38760
39233
|
for (const scanDir of scanDirs) {
|
|
38761
|
-
const baseDir =
|
|
39234
|
+
const baseDir = path22.join(claudeDir, scanDir);
|
|
38762
39235
|
if (!fs17.existsSync(baseDir)) continue;
|
|
38763
39236
|
const entries = readdirRecursive(baseDir);
|
|
38764
39237
|
for (const entry of entries) {
|
|
38765
|
-
const absPath =
|
|
39238
|
+
const absPath = path22.join(baseDir, entry);
|
|
38766
39239
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
38767
39240
|
if (!isStructuralEntry(scanDir, entry)) continue;
|
|
38768
|
-
const ext =
|
|
39241
|
+
const ext = path22.extname(entry).toLowerCase();
|
|
38769
39242
|
const isMd = ext === ".md";
|
|
38770
39243
|
const isSh = ext === ".sh";
|
|
38771
39244
|
if (!isMd && !isSh) continue;
|
|
38772
|
-
const relPath =
|
|
39245
|
+
const relPath = path22.join(scanDir, entry).split(path22.sep).join("/");
|
|
38773
39246
|
if (allowlist.has(relPath)) continue;
|
|
38774
39247
|
let content;
|
|
38775
39248
|
try {
|
|
@@ -38783,7 +39256,7 @@ function checkScopeMarkers(opts) {
|
|
|
38783
39256
|
continue;
|
|
38784
39257
|
}
|
|
38785
39258
|
const scopeValue = isMd ? extractFrontmatterScope(content) : extractShScope(content);
|
|
38786
|
-
const managed = twinDetectionActive && fs17.existsSync(
|
|
39259
|
+
const managed = twinDetectionActive && fs17.existsSync(path22.join(templatesDir, relPath));
|
|
38787
39260
|
if (managed) {
|
|
38788
39261
|
if (scopeValue === null) {
|
|
38789
39262
|
} else if (scopeValue === "org-shared") {
|
|
@@ -38837,7 +39310,7 @@ function readdirRecursive(dir, rel = "", visited = /* @__PURE__ */ new Set()) {
|
|
|
38837
39310
|
visited.add(realDir);
|
|
38838
39311
|
const results = [];
|
|
38839
39312
|
for (const name of fs17.readdirSync(dir)) {
|
|
38840
|
-
const full =
|
|
39313
|
+
const full = path22.join(dir, name);
|
|
38841
39314
|
const relName = rel ? `${rel}/${name}` : name;
|
|
38842
39315
|
if (fs17.lstatSync(full).isDirectory()) {
|
|
38843
39316
|
results.push(...readdirRecursive(full, relName, visited));
|
|
@@ -38910,12 +39383,12 @@ __export(verify_parity_exports, {
|
|
|
38910
39383
|
verifyParity: () => verifyParity
|
|
38911
39384
|
});
|
|
38912
39385
|
import * as fs18 from "node:fs";
|
|
38913
|
-
import * as
|
|
39386
|
+
import * as path23 from "node:path";
|
|
38914
39387
|
function verifyParity(args, deps = {}) {
|
|
38915
39388
|
const warnOnly = args.includes("--warn-only");
|
|
38916
39389
|
const jsonMode = args.includes("--json");
|
|
38917
39390
|
const projectDir = deps.cwd ?? process.cwd();
|
|
38918
|
-
const claudeDir =
|
|
39391
|
+
const claudeDir = path23.join(projectDir, ".claude");
|
|
38919
39392
|
if (!fs18.existsSync(claudeDir)) {
|
|
38920
39393
|
const msg = "codebyplan claude verify-parity: .claude/ not found in cwd \u2014 run from the project root.\n";
|
|
38921
39394
|
process.stderr.write(msg);
|
|
@@ -39422,11 +39895,11 @@ var generate_exports = {};
|
|
|
39422
39895
|
__export(generate_exports, {
|
|
39423
39896
|
runGenerate: () => runGenerate
|
|
39424
39897
|
});
|
|
39425
|
-
import { readFile as
|
|
39426
|
-
import { join as
|
|
39898
|
+
import { readFile as readFile27, mkdir as mkdir12, writeFile as writeFile20 } from "node:fs/promises";
|
|
39899
|
+
import { join as join51, resolve as resolve12 } from "node:path";
|
|
39427
39900
|
async function readJsonFile4(filePath) {
|
|
39428
39901
|
try {
|
|
39429
|
-
const raw = await
|
|
39902
|
+
const raw = await readFile27(filePath, "utf-8");
|
|
39430
39903
|
return JSON.parse(raw);
|
|
39431
39904
|
} catch {
|
|
39432
39905
|
return null;
|
|
@@ -39434,7 +39907,7 @@ async function readJsonFile4(filePath) {
|
|
|
39434
39907
|
}
|
|
39435
39908
|
async function readPkgName(absPath) {
|
|
39436
39909
|
try {
|
|
39437
|
-
const raw = await
|
|
39910
|
+
const raw = await readFile27(join51(absPath, "package.json"), "utf-8");
|
|
39438
39911
|
const pkg = JSON.parse(raw);
|
|
39439
39912
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
39440
39913
|
} catch {
|
|
@@ -39448,7 +39921,7 @@ async function runGenerate(opts) {
|
|
|
39448
39921
|
const rootDir = resolve12(projectDir);
|
|
39449
39922
|
let packageManager;
|
|
39450
39923
|
try {
|
|
39451
|
-
const raw = await
|
|
39924
|
+
const raw = await readFile27(join51(rootDir, "package.json"), "utf-8");
|
|
39452
39925
|
const pkg = JSON.parse(raw);
|
|
39453
39926
|
if (typeof pkg.packageManager === "string") {
|
|
39454
39927
|
packageManager = pkg.packageManager;
|
|
@@ -39456,7 +39929,7 @@ async function runGenerate(opts) {
|
|
|
39456
39929
|
} catch {
|
|
39457
39930
|
}
|
|
39458
39931
|
const serverJson = await readJsonFile4(
|
|
39459
|
-
|
|
39932
|
+
join51(rootDir, ".codebyplan", "server.json")
|
|
39460
39933
|
);
|
|
39461
39934
|
const ports = [];
|
|
39462
39935
|
for (const alloc of serverJson?.port_allocations ?? []) {
|
|
@@ -39469,7 +39942,7 @@ async function runGenerate(opts) {
|
|
|
39469
39942
|
}
|
|
39470
39943
|
}
|
|
39471
39944
|
const gitJson = await readJsonFile4(
|
|
39472
|
-
|
|
39945
|
+
join51(rootDir, ".codebyplan", "git.json")
|
|
39473
39946
|
);
|
|
39474
39947
|
const branchModel = gitJson?.branch_config?.production ? {
|
|
39475
39948
|
production: gitJson.branch_config.production,
|
|
@@ -39478,7 +39951,7 @@ async function runGenerate(opts) {
|
|
|
39478
39951
|
)
|
|
39479
39952
|
} : void 0;
|
|
39480
39953
|
const shipmentJson = await readJsonFile4(
|
|
39481
|
-
|
|
39954
|
+
join51(rootDir, ".codebyplan", "shipment.json")
|
|
39482
39955
|
);
|
|
39483
39956
|
const shipmentSurfaces = [];
|
|
39484
39957
|
const rawSurfaces = shipmentJson?.shipment?.surfaces ?? shipmentJson?.surfaces ?? {};
|
|
@@ -39549,10 +40022,10 @@ async function runGenerate(opts) {
|
|
|
39549
40022
|
const structureMdContent = generateStructureMd(config);
|
|
39550
40023
|
const agentsContent = generateAgentsMd(structureMdContent);
|
|
39551
40024
|
if (check) {
|
|
39552
|
-
const agentsMdPath2 =
|
|
40025
|
+
const agentsMdPath2 = join51(rootDir, "AGENTS.md");
|
|
39553
40026
|
let existingAgents = null;
|
|
39554
40027
|
try {
|
|
39555
|
-
existingAgents = await
|
|
40028
|
+
existingAgents = await readFile27(agentsMdPath2, "utf-8");
|
|
39556
40029
|
} catch {
|
|
39557
40030
|
existingAgents = null;
|
|
39558
40031
|
}
|
|
@@ -39588,16 +40061,16 @@ async function runGenerate(opts) {
|
|
|
39588
40061
|
process.stdout.write(agentsContent);
|
|
39589
40062
|
return;
|
|
39590
40063
|
}
|
|
39591
|
-
const outputDir =
|
|
39592
|
-
await
|
|
39593
|
-
const outputPath =
|
|
39594
|
-
await
|
|
40064
|
+
const outputDir = join51(rootDir, ".claude", "generated");
|
|
40065
|
+
await mkdir12(outputDir, { recursive: true });
|
|
40066
|
+
const outputPath = join51(outputDir, "structure.md");
|
|
40067
|
+
await writeFile20(outputPath, structureMdContent, "utf-8");
|
|
39595
40068
|
process.stdout.write(`Wrote: .claude/generated/structure.md
|
|
39596
40069
|
`);
|
|
39597
|
-
const agentsMdPath =
|
|
40070
|
+
const agentsMdPath = join51(rootDir, "AGENTS.md");
|
|
39598
40071
|
let existingAgentsContent = null;
|
|
39599
40072
|
try {
|
|
39600
|
-
existingAgentsContent = await
|
|
40073
|
+
existingAgentsContent = await readFile27(agentsMdPath, "utf-8");
|
|
39601
40074
|
} catch {
|
|
39602
40075
|
existingAgentsContent = null;
|
|
39603
40076
|
}
|
|
@@ -39605,7 +40078,7 @@ async function runGenerate(opts) {
|
|
|
39605
40078
|
process.stdout.write(`Up to date: AGENTS.md
|
|
39606
40079
|
`);
|
|
39607
40080
|
} else {
|
|
39608
|
-
await
|
|
40081
|
+
await writeFile20(agentsMdPath, agentsContent, "utf-8");
|
|
39609
40082
|
process.stdout.write(`Wrote: AGENTS.md
|
|
39610
40083
|
`);
|
|
39611
40084
|
}
|
|
@@ -39625,11 +40098,11 @@ __export(readme_exports, {
|
|
|
39625
40098
|
runReadme: () => runReadme,
|
|
39626
40099
|
runReadmeCommand: () => runReadmeCommand
|
|
39627
40100
|
});
|
|
39628
|
-
import { readFile as
|
|
39629
|
-
import { join as
|
|
40101
|
+
import { readFile as readFile28, writeFile as writeFile21 } from "node:fs/promises";
|
|
40102
|
+
import { join as join52, resolve as resolve13, relative as relative9 } from "node:path";
|
|
39630
40103
|
async function readJsonFile5(filePath) {
|
|
39631
40104
|
try {
|
|
39632
|
-
const raw = await
|
|
40105
|
+
const raw = await readFile28(filePath, "utf-8");
|
|
39633
40106
|
return JSON.parse(raw);
|
|
39634
40107
|
} catch {
|
|
39635
40108
|
return null;
|
|
@@ -39698,7 +40171,7 @@ async function discoverUnits(rootDir, rootPkgJson) {
|
|
|
39698
40171
|
const discovered = await discoverMonorepoApps(rootDir);
|
|
39699
40172
|
for (const app of discovered) {
|
|
39700
40173
|
const pkgJson = await readJsonFile5(
|
|
39701
|
-
|
|
40174
|
+
join52(app.absPath, "package.json")
|
|
39702
40175
|
);
|
|
39703
40176
|
pkgJsonByPath.set(app.absPath, pkgJson);
|
|
39704
40177
|
allPackages.push({
|
|
@@ -39724,7 +40197,7 @@ async function runReadme(opts) {
|
|
|
39724
40197
|
const init = opts.init ?? opts["init"] ?? false;
|
|
39725
40198
|
const rootDir = resolve13(projectDir);
|
|
39726
40199
|
const rootPkgJson = await readJsonFile5(
|
|
39727
|
-
|
|
40200
|
+
join52(rootDir, "package.json")
|
|
39728
40201
|
);
|
|
39729
40202
|
const { units, allPackages, pkgJsonByPath } = await discoverUnits(
|
|
39730
40203
|
rootDir,
|
|
@@ -39733,11 +40206,11 @@ async function runReadme(opts) {
|
|
|
39733
40206
|
const driftUnits = [];
|
|
39734
40207
|
const missingUnits = [];
|
|
39735
40208
|
for (const unit of units) {
|
|
39736
|
-
const readmePath =
|
|
39737
|
-
const relPath = unit.isRoot ? "README.md" :
|
|
40209
|
+
const readmePath = join52(unit.absPath, "README.md");
|
|
40210
|
+
const relPath = unit.isRoot ? "README.md" : join52(relative9(rootDir, unit.absPath), "README.md");
|
|
39738
40211
|
let existingContent = null;
|
|
39739
40212
|
try {
|
|
39740
|
-
existingContent = await
|
|
40213
|
+
existingContent = await readFile28(readmePath, "utf-8");
|
|
39741
40214
|
} catch {
|
|
39742
40215
|
existingContent = null;
|
|
39743
40216
|
}
|
|
@@ -39772,7 +40245,7 @@ ${newContent}
|
|
|
39772
40245
|
`
|
|
39773
40246
|
);
|
|
39774
40247
|
} else {
|
|
39775
|
-
await
|
|
40248
|
+
await writeFile21(readmePath, newContent, "utf-8");
|
|
39776
40249
|
process.stdout.write(`Wrote (scaffold): ${relPath}
|
|
39777
40250
|
`);
|
|
39778
40251
|
}
|
|
@@ -39810,7 +40283,7 @@ ${newContent}
|
|
|
39810
40283
|
`
|
|
39811
40284
|
);
|
|
39812
40285
|
} else {
|
|
39813
|
-
await
|
|
40286
|
+
await writeFile21(readmePath, newContent, "utf-8");
|
|
39814
40287
|
process.stdout.write(`Wrote (refresh): ${relPath}
|
|
39815
40288
|
`);
|
|
39816
40289
|
}
|
|
@@ -39829,7 +40302,7 @@ ${newContent}
|
|
|
39829
40302
|
`
|
|
39830
40303
|
);
|
|
39831
40304
|
} else {
|
|
39832
|
-
await
|
|
40305
|
+
await writeFile21(readmePath, newContent, "utf-8");
|
|
39833
40306
|
process.stdout.write(`Wrote (init): ${relPath}
|
|
39834
40307
|
`);
|
|
39835
40308
|
}
|
|
@@ -39917,15 +40390,15 @@ __export(migrate_memory_exports, {
|
|
|
39917
40390
|
runMigrateMemory: () => runMigrateMemory
|
|
39918
40391
|
});
|
|
39919
40392
|
import {
|
|
39920
|
-
readFile as
|
|
39921
|
-
writeFile as
|
|
39922
|
-
mkdir as
|
|
39923
|
-
unlink as
|
|
40393
|
+
readFile as readFile29,
|
|
40394
|
+
writeFile as writeFile22,
|
|
40395
|
+
mkdir as mkdir13,
|
|
40396
|
+
unlink as unlink7,
|
|
39924
40397
|
rmdir,
|
|
39925
|
-
readdir as
|
|
40398
|
+
readdir as readdir9
|
|
39926
40399
|
} from "node:fs/promises";
|
|
39927
40400
|
import { existsSync as existsSync20 } from "node:fs";
|
|
39928
|
-
import { join as
|
|
40401
|
+
import { join as join53, resolve as resolve14, dirname as dirname15, sep as sep4 } from "node:path";
|
|
39929
40402
|
import { homedir as homedir8 } from "node:os";
|
|
39930
40403
|
function encodeProjectPath(absPath) {
|
|
39931
40404
|
return resolve14(absPath).replace(/[/\\]/g, "-");
|
|
@@ -39936,7 +40409,7 @@ function resolveAutoMemoryDir(opts) {
|
|
|
39936
40409
|
}
|
|
39937
40410
|
const projectDir = opts.projectDir ?? process.cwd();
|
|
39938
40411
|
const encoded = encodeProjectPath(projectDir);
|
|
39939
|
-
return
|
|
40412
|
+
return join53(homedir8(), ".claude", "projects", encoded, "memory");
|
|
39940
40413
|
}
|
|
39941
40414
|
function parseFrontmatter(content) {
|
|
39942
40415
|
content = content.replace(/\r\n/g, "\n");
|
|
@@ -39995,17 +40468,17 @@ function parseFrontmatter(content) {
|
|
|
39995
40468
|
async function inventoryFiles(dir) {
|
|
39996
40469
|
let filenames;
|
|
39997
40470
|
try {
|
|
39998
|
-
const entries = await
|
|
40471
|
+
const entries = await readdir9(dir);
|
|
39999
40472
|
filenames = entries.filter((f) => f.endsWith(".md") && f !== "MEMORY.md").sort();
|
|
40000
40473
|
} catch {
|
|
40001
40474
|
return [];
|
|
40002
40475
|
}
|
|
40003
40476
|
const results = [];
|
|
40004
40477
|
for (const filename of filenames) {
|
|
40005
|
-
const sourcePath =
|
|
40478
|
+
const sourcePath = join53(dir, filename);
|
|
40006
40479
|
let raw;
|
|
40007
40480
|
try {
|
|
40008
|
-
raw = await
|
|
40481
|
+
raw = await readFile29(sourcePath, "utf-8");
|
|
40009
40482
|
} catch (err) {
|
|
40010
40483
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40011
40484
|
results.push({
|
|
@@ -40091,8 +40564,8 @@ async function applyPlan(plan, opts) {
|
|
|
40091
40564
|
if (entry.suggested_action !== "keep") continue;
|
|
40092
40565
|
if (!entry.suggested_target?.startsWith("nested:")) continue;
|
|
40093
40566
|
const relPath = entry.suggested_target.slice("nested:".length);
|
|
40094
|
-
const targetDir = resolve14(
|
|
40095
|
-
const targetFile =
|
|
40567
|
+
const targetDir = resolve14(join53(projectDir, relPath));
|
|
40568
|
+
const targetFile = join53(targetDir, "CLAUDE.md");
|
|
40096
40569
|
if (!targetDir.startsWith(resolve14(projectDir) + sep4)) {
|
|
40097
40570
|
process.stderr.write(
|
|
40098
40571
|
`migrate-memory: skipping unsafe suggested_target "${entry.suggested_target}" \u2014 resolves outside projectDir
|
|
@@ -40121,18 +40594,18 @@ ${anchor}
|
|
|
40121
40594
|
}
|
|
40122
40595
|
continue;
|
|
40123
40596
|
}
|
|
40124
|
-
await
|
|
40597
|
+
await mkdir13(targetDir, { recursive: true });
|
|
40125
40598
|
let existing = "";
|
|
40126
40599
|
try {
|
|
40127
|
-
existing = await
|
|
40600
|
+
existing = await readFile29(targetFile, "utf-8");
|
|
40128
40601
|
} catch {
|
|
40129
40602
|
}
|
|
40130
40603
|
if (!existing.includes(anchor)) {
|
|
40131
|
-
await
|
|
40604
|
+
await writeFile22(targetFile, existing + appendContent, "utf-8");
|
|
40132
40605
|
}
|
|
40133
40606
|
if (resolve14(entry.source_path).startsWith(resolve14(plan.auto_memory_dir) + sep4)) {
|
|
40134
40607
|
try {
|
|
40135
|
-
await
|
|
40608
|
+
await unlink7(entry.source_path);
|
|
40136
40609
|
} catch {
|
|
40137
40610
|
}
|
|
40138
40611
|
} else {
|
|
@@ -40142,7 +40615,7 @@ ${anchor}
|
|
|
40142
40615
|
);
|
|
40143
40616
|
}
|
|
40144
40617
|
}
|
|
40145
|
-
const rootClaudeMd =
|
|
40618
|
+
const rootClaudeMd = join53(projectDir, ".claude", "CLAUDE.md");
|
|
40146
40619
|
if (dryRun) {
|
|
40147
40620
|
process.stdout.write(
|
|
40148
40621
|
`[dry-run] Would ensure ${rootClaudeMd} contains: ${IMPORT_LINE}
|
|
@@ -40151,12 +40624,12 @@ ${anchor}
|
|
|
40151
40624
|
} else {
|
|
40152
40625
|
let claudeMdContent = "";
|
|
40153
40626
|
try {
|
|
40154
|
-
claudeMdContent = await
|
|
40627
|
+
claudeMdContent = await readFile29(rootClaudeMd, "utf-8");
|
|
40155
40628
|
} catch {
|
|
40156
|
-
await
|
|
40629
|
+
await mkdir13(dirname15(rootClaudeMd), { recursive: true });
|
|
40157
40630
|
}
|
|
40158
40631
|
if (!claudeMdContent.includes(IMPORT_LINE)) {
|
|
40159
|
-
await
|
|
40632
|
+
await writeFile22(
|
|
40160
40633
|
rootClaudeMd,
|
|
40161
40634
|
claudeMdContent + `
|
|
40162
40635
|
${IMPORT_LINE}
|
|
@@ -40182,19 +40655,19 @@ ${IMPORT_LINE}
|
|
|
40182
40655
|
continue;
|
|
40183
40656
|
}
|
|
40184
40657
|
try {
|
|
40185
|
-
await
|
|
40658
|
+
await unlink7(entry.source_path);
|
|
40186
40659
|
} catch {
|
|
40187
40660
|
}
|
|
40188
40661
|
}
|
|
40189
|
-
const memoryMd =
|
|
40190
|
-
const safeRmdirBase =
|
|
40662
|
+
const memoryMd = join53(plan.auto_memory_dir, "MEMORY.md");
|
|
40663
|
+
const safeRmdirBase = join53(homedir8(), ".claude", "projects");
|
|
40191
40664
|
if (dryRun) {
|
|
40192
40665
|
process.stdout.write(`[dry-run] Would delete MEMORY.md: ${memoryMd}
|
|
40193
40666
|
`);
|
|
40194
40667
|
} else {
|
|
40195
40668
|
if (resolve14(plan.auto_memory_dir).startsWith(safeRmdirBase + sep4)) {
|
|
40196
40669
|
try {
|
|
40197
|
-
await
|
|
40670
|
+
await unlink7(memoryMd);
|
|
40198
40671
|
} catch {
|
|
40199
40672
|
}
|
|
40200
40673
|
} else {
|
|
@@ -40217,7 +40690,7 @@ ${IMPORT_LINE}
|
|
|
40217
40690
|
);
|
|
40218
40691
|
} else {
|
|
40219
40692
|
try {
|
|
40220
|
-
const remaining = await
|
|
40693
|
+
const remaining = await readdir9(plan.auto_memory_dir);
|
|
40221
40694
|
if (remaining.length === 0) {
|
|
40222
40695
|
await rmdir(plan.auto_memory_dir);
|
|
40223
40696
|
}
|
|
@@ -40240,7 +40713,7 @@ async function runMigrateMemory(opts) {
|
|
|
40240
40713
|
if (applyFile) {
|
|
40241
40714
|
let planJson;
|
|
40242
40715
|
try {
|
|
40243
|
-
planJson = await
|
|
40716
|
+
planJson = await readFile29(resolve14(applyFile), "utf-8");
|
|
40244
40717
|
} catch (err) {
|
|
40245
40718
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40246
40719
|
process.stderr.write(
|
|
@@ -40311,7 +40784,7 @@ var init_migrate_memory = __esm({
|
|
|
40311
40784
|
|
|
40312
40785
|
// src/lib/claude-mode-audit.ts
|
|
40313
40786
|
import { readdirSync as readdirSync6, readFileSync as readFileSync19, existsSync as existsSync21 } from "node:fs";
|
|
40314
|
-
import { join as
|
|
40787
|
+
import { join as join54, basename as basename4 } from "node:path";
|
|
40315
40788
|
function parseFrontmatter2(content) {
|
|
40316
40789
|
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
40317
40790
|
if (!match) return {};
|
|
@@ -40331,7 +40804,7 @@ function parseFrontmatter2(content) {
|
|
|
40331
40804
|
function auditAgent(filePath) {
|
|
40332
40805
|
const content = readFileSync19(filePath, "utf-8");
|
|
40333
40806
|
const fm = parseFrontmatter2(content);
|
|
40334
|
-
const agentName = fm.name ??
|
|
40807
|
+
const agentName = fm.name ?? basename4(filePath, ".md");
|
|
40335
40808
|
const expected = AGENT_EXCEPTIONS[agentName] ?? AGENT_DEFAULT;
|
|
40336
40809
|
const expectedStr = `model:${expected.model}/effort:${expected.effort}`;
|
|
40337
40810
|
const model = fm.model ?? null;
|
|
@@ -40390,19 +40863,19 @@ function auditSkill(filePath) {
|
|
|
40390
40863
|
}
|
|
40391
40864
|
function auditMode(templatesDir) {
|
|
40392
40865
|
const entries = [];
|
|
40393
|
-
const agentsDir =
|
|
40866
|
+
const agentsDir = join54(templatesDir, "agents");
|
|
40394
40867
|
if (existsSync21(agentsDir)) {
|
|
40395
40868
|
const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md")).sort();
|
|
40396
40869
|
for (const f of agentFiles) {
|
|
40397
|
-
entries.push(auditAgent(
|
|
40870
|
+
entries.push(auditAgent(join54(agentsDir, f)));
|
|
40398
40871
|
}
|
|
40399
40872
|
}
|
|
40400
|
-
const skillsDir =
|
|
40873
|
+
const skillsDir = join54(templatesDir, "skills");
|
|
40401
40874
|
if (existsSync21(skillsDir)) {
|
|
40402
40875
|
const skillDirs = readdirSync6(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
40403
40876
|
for (const dir of skillDirs) {
|
|
40404
|
-
if (existsSync21(
|
|
40405
|
-
const skillMd =
|
|
40877
|
+
if (existsSync21(join54(skillsDir, dir, "PROVENANCE.md"))) continue;
|
|
40878
|
+
const skillMd = join54(skillsDir, dir, "SKILL.md");
|
|
40406
40879
|
if (existsSync21(skillMd)) {
|
|
40407
40880
|
entries.push(auditSkill(skillMd));
|
|
40408
40881
|
}
|
|
@@ -40667,7 +41140,7 @@ __export(new_migration_exports, {
|
|
|
40667
41140
|
newMigration: () => newMigration
|
|
40668
41141
|
});
|
|
40669
41142
|
import * as fs19 from "node:fs";
|
|
40670
|
-
import * as
|
|
41143
|
+
import * as path24 from "node:path";
|
|
40671
41144
|
function slugify(name) {
|
|
40672
41145
|
return name.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_");
|
|
40673
41146
|
}
|
|
@@ -40688,9 +41161,9 @@ function newMigration(args, deps = {}) {
|
|
|
40688
41161
|
}
|
|
40689
41162
|
const slug = slugify(rawName);
|
|
40690
41163
|
const stamp = genTimestamp({ cwd });
|
|
40691
|
-
const migrationsDir =
|
|
41164
|
+
const migrationsDir = path24.join(cwd, "supabase", "migrations");
|
|
40692
41165
|
const filename = `${stamp}_${slug}.sql`;
|
|
40693
|
-
const filePath =
|
|
41166
|
+
const filePath = path24.join(migrationsDir, filename);
|
|
40694
41167
|
mkdirSync12(migrationsDir, { recursive: true });
|
|
40695
41168
|
writeFileSync13(filePath, "");
|
|
40696
41169
|
process.stdout.write(JSON.stringify({ path: filePath }) + "\n");
|
|
@@ -41056,13 +41529,13 @@ function validateWaves(waves) {
|
|
|
41056
41529
|
pathOwners.set(file, owners);
|
|
41057
41530
|
}
|
|
41058
41531
|
}
|
|
41059
|
-
for (const [
|
|
41532
|
+
for (const [path25, owners] of pathOwners) {
|
|
41060
41533
|
if (owners.length > 1) {
|
|
41061
41534
|
violations.push({
|
|
41062
41535
|
invariant: "I",
|
|
41063
41536
|
code: "DUPLICATE_FILE",
|
|
41064
|
-
message: `File "${
|
|
41065
|
-
detail: { path:
|
|
41537
|
+
message: `File "${path25}" appears in multiple waves: ${owners.join(", ")}.`,
|
|
41538
|
+
detail: { path: path25, waves: owners }
|
|
41066
41539
|
});
|
|
41067
41540
|
}
|
|
41068
41541
|
}
|
|
@@ -41156,7 +41629,7 @@ var validate_waves_exports = {};
|
|
|
41156
41629
|
__export(validate_waves_exports, {
|
|
41157
41630
|
runValidateWavesCommand: () => runValidateWavesCommand
|
|
41158
41631
|
});
|
|
41159
|
-
import { readFile as
|
|
41632
|
+
import { readFile as readFile30 } from "node:fs/promises";
|
|
41160
41633
|
async function readStdin() {
|
|
41161
41634
|
return new Promise((resolve17, reject) => {
|
|
41162
41635
|
const chunks = [];
|
|
@@ -41175,7 +41648,7 @@ async function runValidateWavesCommand(args) {
|
|
|
41175
41648
|
let raw;
|
|
41176
41649
|
if (filePath) {
|
|
41177
41650
|
try {
|
|
41178
|
-
raw = await
|
|
41651
|
+
raw = await readFile30(filePath, "utf-8");
|
|
41179
41652
|
} catch (err) {
|
|
41180
41653
|
const msg = err instanceof Error ? err.message : String(err);
|
|
41181
41654
|
process.stderr.write(
|
|
@@ -41255,12 +41728,12 @@ var init_validate_waves2 = __esm({
|
|
|
41255
41728
|
});
|
|
41256
41729
|
|
|
41257
41730
|
// src/cli/worktree/path.ts
|
|
41258
|
-
import { dirname as
|
|
41731
|
+
import { dirname as dirname16, basename as basename5, join as join56 } from "node:path";
|
|
41259
41732
|
function computeWorktreePath(cwd, checkpointNumber) {
|
|
41260
|
-
const parent =
|
|
41261
|
-
const base =
|
|
41733
|
+
const parent = dirname16(cwd);
|
|
41734
|
+
const base = basename5(cwd);
|
|
41262
41735
|
const nnn = String(checkpointNumber).padStart(3, "0");
|
|
41263
|
-
return
|
|
41736
|
+
return join56(parent, `${base}-CHK-${nnn}`);
|
|
41264
41737
|
}
|
|
41265
41738
|
var init_path = __esm({
|
|
41266
41739
|
"src/cli/worktree/path.ts"() {
|
|
@@ -41269,8 +41742,8 @@ var init_path = __esm({
|
|
|
41269
41742
|
});
|
|
41270
41743
|
|
|
41271
41744
|
// src/cli/worktree/add.ts
|
|
41272
|
-
import { join as
|
|
41273
|
-
import { mkdir as
|
|
41745
|
+
import { join as join57 } from "node:path";
|
|
41746
|
+
import { mkdir as mkdir14, readFile as readFile31, writeFile as writeFile23 } from "node:fs/promises";
|
|
41274
41747
|
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
41275
41748
|
async function defaultGetRepoId(cwd) {
|
|
41276
41749
|
const found = await findCodebyplanConfig(cwd);
|
|
@@ -41313,17 +41786,17 @@ function defaultGitRun(args, cwd) {
|
|
|
41313
41786
|
};
|
|
41314
41787
|
}
|
|
41315
41788
|
async function copyClaudeSettings(srcCwd, destPath, deps = {}) {
|
|
41316
|
-
const readFileFn = deps.readFileFn ?? ((p) =>
|
|
41317
|
-
const writeFileFn = deps.writeFileFn ?? ((p, content) =>
|
|
41789
|
+
const readFileFn = deps.readFileFn ?? ((p) => readFile31(p, "utf-8"));
|
|
41790
|
+
const writeFileFn = deps.writeFileFn ?? ((p, content) => writeFile23(p, content, "utf-8"));
|
|
41318
41791
|
const existsFn = deps.existsFn ?? ((p) => import("node:fs/promises").then(
|
|
41319
41792
|
(fsp) => fsp.access(p).then(() => true).catch(() => false)
|
|
41320
41793
|
));
|
|
41321
|
-
const mkdirFn = deps.mkdirFn ?? ((p, opts) =>
|
|
41322
|
-
await mkdirFn(
|
|
41794
|
+
const mkdirFn = deps.mkdirFn ?? ((p, opts) => mkdir14(p, opts));
|
|
41795
|
+
await mkdirFn(join57(destPath, ".claude"), { recursive: true });
|
|
41323
41796
|
const claudeStubs = ["settings.json", "settings.local.json"];
|
|
41324
41797
|
for (const stub of claudeStubs) {
|
|
41325
|
-
const srcFile =
|
|
41326
|
-
const destFile =
|
|
41798
|
+
const srcFile = join57(srcCwd, ".claude", stub);
|
|
41799
|
+
const destFile = join57(destPath, ".claude", stub);
|
|
41327
41800
|
try {
|
|
41328
41801
|
const destExists = await existsFn(destFile);
|
|
41329
41802
|
if (destExists) continue;
|
|
@@ -41334,22 +41807,22 @@ async function copyClaudeSettings(srcCwd, destPath, deps = {}) {
|
|
|
41334
41807
|
}
|
|
41335
41808
|
}
|
|
41336
41809
|
async function defaultCopyConfigStubs(srcCwd, destPath) {
|
|
41337
|
-
await
|
|
41810
|
+
await mkdir14(join57(destPath, ".codebyplan"), { recursive: true });
|
|
41338
41811
|
const topLevelStubs = [".mcp.json", ".env.local"];
|
|
41339
41812
|
for (const stub of topLevelStubs) {
|
|
41340
41813
|
try {
|
|
41341
|
-
const content = await
|
|
41342
|
-
await
|
|
41814
|
+
const content = await readFile31(join57(srcCwd, stub), "utf-8");
|
|
41815
|
+
await writeFile23(join57(destPath, stub), content, "utf-8");
|
|
41343
41816
|
} catch {
|
|
41344
41817
|
}
|
|
41345
41818
|
}
|
|
41346
41819
|
try {
|
|
41347
|
-
const content = await
|
|
41348
|
-
|
|
41820
|
+
const content = await readFile31(
|
|
41821
|
+
join57(srcCwd, ".codebyplan", "repo.json"),
|
|
41349
41822
|
"utf-8"
|
|
41350
41823
|
);
|
|
41351
|
-
await
|
|
41352
|
-
|
|
41824
|
+
await writeFile23(
|
|
41825
|
+
join57(destPath, ".codebyplan", "repo.json"),
|
|
41353
41826
|
content,
|
|
41354
41827
|
"utf-8"
|
|
41355
41828
|
);
|
|
@@ -41483,7 +41956,7 @@ var init_add = __esm({
|
|
|
41483
41956
|
});
|
|
41484
41957
|
|
|
41485
41958
|
// src/cli/worktree/create.ts
|
|
41486
|
-
import { join as
|
|
41959
|
+
import { join as join58 } from "node:path";
|
|
41487
41960
|
async function defaultGetRepoIdentity(cwd) {
|
|
41488
41961
|
const found = await findCodebyplanConfig(cwd);
|
|
41489
41962
|
const contents = found?.contents ?? null;
|
|
@@ -41528,7 +42001,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
41528
42001
|
);
|
|
41529
42002
|
return 1;
|
|
41530
42003
|
}
|
|
41531
|
-
const worktreePath = explicitPath ??
|
|
42004
|
+
const worktreePath = explicitPath ?? join58(cwd, "..", name);
|
|
41532
42005
|
let filesWritten = false;
|
|
41533
42006
|
try {
|
|
41534
42007
|
await createWorktreeFiles(
|
|
@@ -41938,7 +42411,7 @@ var init_e2e = __esm({
|
|
|
41938
42411
|
});
|
|
41939
42412
|
|
|
41940
42413
|
// src/cli/e2e/verify-round.ts
|
|
41941
|
-
import { readFile as
|
|
42414
|
+
import { readFile as readFile32 } from "node:fs/promises";
|
|
41942
42415
|
import { resolve as resolve15 } from "node:path";
|
|
41943
42416
|
async function defaultFetchRounds(taskId) {
|
|
41944
42417
|
return mcpCall("get_rounds", { task_id: taskId });
|
|
@@ -41946,7 +42419,7 @@ async function defaultFetchRounds(taskId) {
|
|
|
41946
42419
|
async function defaultReadE2eConfig(cwd) {
|
|
41947
42420
|
try {
|
|
41948
42421
|
const p = resolve15(cwd, ".codebyplan", "e2e.json");
|
|
41949
|
-
const raw = await
|
|
42422
|
+
const raw = await readFile32(p, "utf-8");
|
|
41950
42423
|
return JSON.parse(raw);
|
|
41951
42424
|
} catch {
|
|
41952
42425
|
return null;
|
|
@@ -42113,7 +42586,7 @@ __export(doctor_exports, {
|
|
|
42113
42586
|
runDoctor: () => runDoctor
|
|
42114
42587
|
});
|
|
42115
42588
|
import { existsSync as existsSync22 } from "node:fs";
|
|
42116
|
-
import { join as
|
|
42589
|
+
import { join as join59 } from "node:path";
|
|
42117
42590
|
import { execSync as execSync10 } from "node:child_process";
|
|
42118
42591
|
async function checkAuth() {
|
|
42119
42592
|
try {
|
|
@@ -42190,7 +42663,7 @@ function checkSettings() {
|
|
|
42190
42663
|
detail: "codebyplan not installed (no .cbp.manifest.json)"
|
|
42191
42664
|
};
|
|
42192
42665
|
}
|
|
42193
|
-
if (!existsSync22(
|
|
42666
|
+
if (!existsSync22(join59(projectDir, ".claude", "settings.json"))) {
|
|
42194
42667
|
return {
|
|
42195
42668
|
name: "settings",
|
|
42196
42669
|
status: "warn",
|
|
@@ -42435,6 +42908,11 @@ void (async () => {
|
|
|
42435
42908
|
await runRoundCommand2(rest);
|
|
42436
42909
|
process.exit(0);
|
|
42437
42910
|
}
|
|
42911
|
+
if (arg === "handoff") {
|
|
42912
|
+
const { runHandoffCommand: runHandoffCommand2 } = await Promise.resolve().then(() => (init_handoff(), handoff_exports));
|
|
42913
|
+
await runHandoffCommand2(process.argv.slice(3));
|
|
42914
|
+
process.exit(process.exitCode ?? 0);
|
|
42915
|
+
}
|
|
42438
42916
|
if (arg === "branch") {
|
|
42439
42917
|
const { runBranchCommand: runBranchCommand2 } = await Promise.resolve().then(() => (init_branch(), branch_exports));
|
|
42440
42918
|
const rest = process.argv.slice(3);
|
|
@@ -42772,6 +43250,8 @@ void (async () => {
|
|
|
42772
43250
|
codebyplan watch stop Stop the running daemon
|
|
42773
43251
|
codebyplan watch status Show daemon status (--json for machine-readable)
|
|
42774
43252
|
codebyplan watch run Run daemon in foreground (used internally by start)
|
|
43253
|
+
codebyplan handoff Manage per-level handoff notes in .codebyplan/handoff/
|
|
43254
|
+
(read/write/append/clear/status -- --level repo|checkpoint|task|standalone)
|
|
42775
43255
|
codebyplan round sync-approvals Sync git diff and approvals with round/task state
|
|
42776
43256
|
codebyplan standalone-task Standalone task writes via MCP (create/update/complete)
|
|
42777
43257
|
(create --title; update --id; complete --id \u2014 no --checkpoint-id)
|