codebyplan 1.13.57 → 1.13.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -5,11 +5,20 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
10
15
|
};
|
|
11
16
|
var __commonJS = (cb, mod) => function __require() {
|
|
12
|
-
|
|
17
|
+
try {
|
|
18
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw mod = 0, e;
|
|
21
|
+
}
|
|
13
22
|
};
|
|
14
23
|
var __export = (target, all) => {
|
|
15
24
|
for (var name in all)
|
|
@@ -39,7 +48,7 @@ var VERSION, PACKAGE_NAME;
|
|
|
39
48
|
var init_version = __esm({
|
|
40
49
|
"src/lib/version.ts"() {
|
|
41
50
|
"use strict";
|
|
42
|
-
VERSION = "1.13.
|
|
51
|
+
VERSION = "1.13.58";
|
|
43
52
|
PACKAGE_NAME = "codebyplan";
|
|
44
53
|
}
|
|
45
54
|
});
|
|
@@ -14526,8 +14535,8 @@ var require_RealtimeChannel = __commonJS({
|
|
|
14526
14535
|
}
|
|
14527
14536
|
/** @internal */
|
|
14528
14537
|
_notThisChannelEvent(event, ref) {
|
|
14529
|
-
const { close, error, leave, join:
|
|
14530
|
-
const events = [close, error, leave,
|
|
14538
|
+
const { close, error, leave, join: join57 } = constants_1.CHANNEL_EVENTS;
|
|
14539
|
+
const events = [close, error, leave, join57];
|
|
14531
14540
|
return ref && events.includes(event) && ref !== this.joinPush.ref;
|
|
14532
14541
|
}
|
|
14533
14542
|
/** @internal */
|
|
@@ -29578,6 +29587,1264 @@ var init_standalone_task = __esm({
|
|
|
29578
29587
|
}
|
|
29579
29588
|
});
|
|
29580
29589
|
|
|
29590
|
+
// src/lib/supabase.ts
|
|
29591
|
+
import * as fs5 from "node:fs";
|
|
29592
|
+
import * as path7 from "node:path";
|
|
29593
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
29594
|
+
function defaultRun(cmd, args) {
|
|
29595
|
+
const result = spawnSync6(cmd, args, {
|
|
29596
|
+
encoding: "utf-8",
|
|
29597
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
29598
|
+
});
|
|
29599
|
+
if (result.error) throw result.error;
|
|
29600
|
+
return (result.stdout ?? "").toString();
|
|
29601
|
+
}
|
|
29602
|
+
function readJsonFile2(filePath) {
|
|
29603
|
+
try {
|
|
29604
|
+
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
29605
|
+
const parsed = JSON.parse(raw);
|
|
29606
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
29607
|
+
return parsed;
|
|
29608
|
+
}
|
|
29609
|
+
return null;
|
|
29610
|
+
} catch {
|
|
29611
|
+
return null;
|
|
29612
|
+
}
|
|
29613
|
+
}
|
|
29614
|
+
function getSupabaseSection(obj) {
|
|
29615
|
+
const tryPath = (root) => {
|
|
29616
|
+
const surfaces = root["surfaces"];
|
|
29617
|
+
if (typeof surfaces !== "object" || surfaces === null || Array.isArray(surfaces))
|
|
29618
|
+
return null;
|
|
29619
|
+
const sb = surfaces["supabase"];
|
|
29620
|
+
if (typeof sb === "object" && sb !== null && !Array.isArray(sb)) {
|
|
29621
|
+
return sb;
|
|
29622
|
+
}
|
|
29623
|
+
return null;
|
|
29624
|
+
};
|
|
29625
|
+
const shipment = obj["shipment"];
|
|
29626
|
+
if (typeof shipment === "object" && shipment !== null && !Array.isArray(shipment)) {
|
|
29627
|
+
const found = tryPath(shipment);
|
|
29628
|
+
if (found) return found;
|
|
29629
|
+
}
|
|
29630
|
+
return tryPath(obj);
|
|
29631
|
+
}
|
|
29632
|
+
function globToRegex(pattern) {
|
|
29633
|
+
const special = ".+^${}()|[]\\";
|
|
29634
|
+
let r = "";
|
|
29635
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
29636
|
+
const ch = pattern[i] ?? "";
|
|
29637
|
+
if (ch === "*") {
|
|
29638
|
+
if (pattern[i + 1] === "*") {
|
|
29639
|
+
r += ".*";
|
|
29640
|
+
i++;
|
|
29641
|
+
} else {
|
|
29642
|
+
r += "[^/]*";
|
|
29643
|
+
}
|
|
29644
|
+
} else if (ch === "?") {
|
|
29645
|
+
r += "[^/]";
|
|
29646
|
+
} else if (special.includes(ch)) {
|
|
29647
|
+
r += "\\" + ch;
|
|
29648
|
+
} else {
|
|
29649
|
+
r += ch;
|
|
29650
|
+
}
|
|
29651
|
+
}
|
|
29652
|
+
return new RegExp(`^${r}$`);
|
|
29653
|
+
}
|
|
29654
|
+
function dateToStamp(d) {
|
|
29655
|
+
const pad2 = (n) => String(n).padStart(2, "0");
|
|
29656
|
+
return String(d.getUTCFullYear()) + pad2(d.getUTCMonth() + 1) + pad2(d.getUTCDate()) + pad2(d.getUTCHours()) + pad2(d.getUTCMinutes()) + pad2(d.getUTCSeconds());
|
|
29657
|
+
}
|
|
29658
|
+
function extractStampToken(filename) {
|
|
29659
|
+
if (!filename.endsWith(".sql")) return null;
|
|
29660
|
+
const base = filename.slice(0, -4);
|
|
29661
|
+
const parts = base.split("_");
|
|
29662
|
+
const first = parts[0];
|
|
29663
|
+
if (!first || !/^\d{14}$/.test(first)) return null;
|
|
29664
|
+
const second = parts[1];
|
|
29665
|
+
if (second && /^\d{2}$/.test(second)) {
|
|
29666
|
+
return `${first}_${second}`;
|
|
29667
|
+
}
|
|
29668
|
+
return first;
|
|
29669
|
+
}
|
|
29670
|
+
function readShipmentConfig(cwd) {
|
|
29671
|
+
const dir = cwd ?? process.cwd();
|
|
29672
|
+
const obj = readJsonFile2(path7.join(dir, ".codebyplan", "shipment.json"));
|
|
29673
|
+
if (!obj) return { parentRef: null, previewBranches: [] };
|
|
29674
|
+
const section = getSupabaseSection(obj);
|
|
29675
|
+
if (!section) return { parentRef: null, previewBranches: [] };
|
|
29676
|
+
const parentRef = typeof section["project_ref"] === "string" ? section["project_ref"] : null;
|
|
29677
|
+
const previewBranches = [];
|
|
29678
|
+
const rawBranches = section["preview_branches"];
|
|
29679
|
+
if (Array.isArray(rawBranches)) {
|
|
29680
|
+
for (const b of rawBranches) {
|
|
29681
|
+
if (typeof b !== "object" || b === null || Array.isArray(b)) continue;
|
|
29682
|
+
const entry = b;
|
|
29683
|
+
if (typeof entry["branch"] !== "string" || typeof entry["project_ref"] !== "string")
|
|
29684
|
+
continue;
|
|
29685
|
+
previewBranches.push({
|
|
29686
|
+
branch: entry["branch"],
|
|
29687
|
+
project_ref: entry["project_ref"],
|
|
29688
|
+
created_at: typeof entry["created_at"] === "string" ? entry["created_at"] : void 0
|
|
29689
|
+
});
|
|
29690
|
+
}
|
|
29691
|
+
}
|
|
29692
|
+
return { parentRef, previewBranches };
|
|
29693
|
+
}
|
|
29694
|
+
function readGitConfig(cwd) {
|
|
29695
|
+
const dir = cwd ?? process.cwd();
|
|
29696
|
+
const obj = readJsonFile2(path7.join(dir, ".codebyplan", "git.json"));
|
|
29697
|
+
if (!obj) return { ...GIT_DEFAULTS };
|
|
29698
|
+
const bc = obj["branch_config"];
|
|
29699
|
+
if (typeof bc !== "object" || bc === null || Array.isArray(bc)) {
|
|
29700
|
+
return { ...GIT_DEFAULTS };
|
|
29701
|
+
}
|
|
29702
|
+
const bcObj = bc;
|
|
29703
|
+
const production = typeof bcObj["production"] === "string" && bcObj["production"] ? bcObj["production"] : "main";
|
|
29704
|
+
const protectedArr = [];
|
|
29705
|
+
const rawProtected = bcObj["protected"];
|
|
29706
|
+
if (Array.isArray(rawProtected)) {
|
|
29707
|
+
for (const p of rawProtected) {
|
|
29708
|
+
if (typeof p === "string" && p) protectedArr.push(p);
|
|
29709
|
+
}
|
|
29710
|
+
}
|
|
29711
|
+
if (protectedArr.length === 0) protectedArr.push(production);
|
|
29712
|
+
const integration = typeof bcObj["integration"] === "string" && bcObj["integration"] ? bcObj["integration"] : null;
|
|
29713
|
+
return { production, protected: protectedArr, integration };
|
|
29714
|
+
}
|
|
29715
|
+
function readDbPaths(cwd) {
|
|
29716
|
+
const dir = cwd ?? process.cwd();
|
|
29717
|
+
const obj = readJsonFile2(path7.join(dir, ".codebyplan", "shipment.json"));
|
|
29718
|
+
if (!obj) return [...DEFAULT_DB_PATHS];
|
|
29719
|
+
const section = getSupabaseSection(obj);
|
|
29720
|
+
if (!section) return [...DEFAULT_DB_PATHS];
|
|
29721
|
+
const rawPaths = section["db_paths"];
|
|
29722
|
+
if (!Array.isArray(rawPaths) || rawPaths.length === 0)
|
|
29723
|
+
return [...DEFAULT_DB_PATHS];
|
|
29724
|
+
const paths = [];
|
|
29725
|
+
for (const p of rawPaths) {
|
|
29726
|
+
if (typeof p === "string" && p) paths.push(p);
|
|
29727
|
+
}
|
|
29728
|
+
return paths.length > 0 ? paths : [...DEFAULT_DB_PATHS];
|
|
29729
|
+
}
|
|
29730
|
+
function detectDbChanged(opts = {}) {
|
|
29731
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
29732
|
+
const run = opts.run ?? defaultRun;
|
|
29733
|
+
const base = opts.base ?? readGitConfig(cwd).production;
|
|
29734
|
+
const dbPaths = opts.dbPaths ?? readDbPaths(cwd);
|
|
29735
|
+
if (dbPaths.length === 0) return false;
|
|
29736
|
+
const regexes = dbPaths.map(globToRegex);
|
|
29737
|
+
let output;
|
|
29738
|
+
try {
|
|
29739
|
+
output = run("git", ["diff", "--name-only", `origin/${base}...HEAD`]);
|
|
29740
|
+
} catch {
|
|
29741
|
+
return false;
|
|
29742
|
+
}
|
|
29743
|
+
const changedFiles = output.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
29744
|
+
return changedFiles.some((file) => regexes.some((re) => re.test(file)));
|
|
29745
|
+
}
|
|
29746
|
+
function defaultListDir(dir) {
|
|
29747
|
+
try {
|
|
29748
|
+
return fs5.readdirSync(dir);
|
|
29749
|
+
} catch {
|
|
29750
|
+
return [];
|
|
29751
|
+
}
|
|
29752
|
+
}
|
|
29753
|
+
function generateMonotonicTimestamp(opts = {}) {
|
|
29754
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
29755
|
+
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
29756
|
+
const listDir = opts.listDir ?? defaultListDir;
|
|
29757
|
+
const migrationsDir = path7.join(cwd, "supabase", "migrations");
|
|
29758
|
+
const files = listDir(migrationsDir);
|
|
29759
|
+
const existingStamps = /* @__PURE__ */ new Set();
|
|
29760
|
+
for (const file of files) {
|
|
29761
|
+
const token = extractStampToken(file);
|
|
29762
|
+
if (token) existingStamps.add(token);
|
|
29763
|
+
}
|
|
29764
|
+
let maxStamp = "";
|
|
29765
|
+
for (const s of existingStamps) {
|
|
29766
|
+
if (s > maxStamp) maxStamp = s;
|
|
29767
|
+
}
|
|
29768
|
+
const computed = dateToStamp(now);
|
|
29769
|
+
if (computed > maxStamp && !existingStamps.has(computed)) {
|
|
29770
|
+
return computed;
|
|
29771
|
+
}
|
|
29772
|
+
const collisionBase14 = computed > maxStamp ? computed : maxStamp.slice(0, 14);
|
|
29773
|
+
for (let i = 1; i <= 99; i++) {
|
|
29774
|
+
const suffix = String(i).padStart(2, "0");
|
|
29775
|
+
const candidate = `${collisionBase14}_${suffix}`;
|
|
29776
|
+
if (!existingStamps.has(candidate) && candidate > maxStamp) {
|
|
29777
|
+
return candidate;
|
|
29778
|
+
}
|
|
29779
|
+
}
|
|
29780
|
+
return `${collisionBase14}_99`;
|
|
29781
|
+
}
|
|
29782
|
+
async function pollGhPreviewCheck(opts = {}) {
|
|
29783
|
+
const run = opts.run ?? defaultRun;
|
|
29784
|
+
const sleep3 = opts.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
29785
|
+
const maxPolls = opts.maxPolls ?? 20;
|
|
29786
|
+
const intervalMs = opts.intervalMs ?? 15e3;
|
|
29787
|
+
if (!opts.prNumber) {
|
|
29788
|
+
return {
|
|
29789
|
+
status: "pending_pr",
|
|
29790
|
+
reason: "No PR number \u2014 branch has no open pull request yet."
|
|
29791
|
+
};
|
|
29792
|
+
}
|
|
29793
|
+
try {
|
|
29794
|
+
run("gh", ["--version"]);
|
|
29795
|
+
} catch {
|
|
29796
|
+
return {
|
|
29797
|
+
status: "blocked",
|
|
29798
|
+
reason: "gh CLI not available"
|
|
29799
|
+
};
|
|
29800
|
+
}
|
|
29801
|
+
const prNumber = opts.prNumber;
|
|
29802
|
+
for (let poll = 0; poll < maxPolls; poll++) {
|
|
29803
|
+
if (poll > 0) {
|
|
29804
|
+
await sleep3(intervalMs);
|
|
29805
|
+
}
|
|
29806
|
+
let checksOutput;
|
|
29807
|
+
try {
|
|
29808
|
+
try {
|
|
29809
|
+
checksOutput = run("gh", [
|
|
29810
|
+
"pr",
|
|
29811
|
+
"checks",
|
|
29812
|
+
prNumber,
|
|
29813
|
+
"--json",
|
|
29814
|
+
"name,bucket,state"
|
|
29815
|
+
]);
|
|
29816
|
+
} catch {
|
|
29817
|
+
checksOutput = run("gh", [
|
|
29818
|
+
"pr",
|
|
29819
|
+
"checks",
|
|
29820
|
+
prNumber,
|
|
29821
|
+
"--json",
|
|
29822
|
+
"name,state"
|
|
29823
|
+
]);
|
|
29824
|
+
}
|
|
29825
|
+
} catch {
|
|
29826
|
+
if (poll === maxPolls - 1) {
|
|
29827
|
+
return {
|
|
29828
|
+
status: "blocked",
|
|
29829
|
+
reason: `gh pr checks failed after ${maxPolls} polls`
|
|
29830
|
+
};
|
|
29831
|
+
}
|
|
29832
|
+
continue;
|
|
29833
|
+
}
|
|
29834
|
+
let checks;
|
|
29835
|
+
try {
|
|
29836
|
+
const parsed = JSON.parse(checksOutput);
|
|
29837
|
+
checks = Array.isArray(parsed) ? parsed : [];
|
|
29838
|
+
} catch {
|
|
29839
|
+
checks = [];
|
|
29840
|
+
}
|
|
29841
|
+
const supabaseCheck = checks.find(
|
|
29842
|
+
(c) => typeof c["name"] === "string" && c["name"].toLowerCase().includes("supabase preview")
|
|
29843
|
+
);
|
|
29844
|
+
if (!supabaseCheck) {
|
|
29845
|
+
continue;
|
|
29846
|
+
}
|
|
29847
|
+
const bucket = typeof supabaseCheck["bucket"] === "string" ? supabaseCheck["bucket"].toLowerCase() : null;
|
|
29848
|
+
const state = typeof supabaseCheck["state"] === "string" ? supabaseCheck["state"].toLowerCase() : null;
|
|
29849
|
+
if (bucket === "pass") {
|
|
29850
|
+
return { status: "passed", reason: "Supabase Preview check passed." };
|
|
29851
|
+
}
|
|
29852
|
+
if (bucket === "skipping") {
|
|
29853
|
+
return {
|
|
29854
|
+
status: "skipped",
|
|
29855
|
+
reason: "Supabase Preview check skipped at CI."
|
|
29856
|
+
};
|
|
29857
|
+
}
|
|
29858
|
+
if (bucket === "fail" || bucket === "cancel") {
|
|
29859
|
+
return {
|
|
29860
|
+
status: "blocked",
|
|
29861
|
+
reason: `Supabase Preview check ${bucket}ed.`
|
|
29862
|
+
};
|
|
29863
|
+
}
|
|
29864
|
+
if (state === "success") {
|
|
29865
|
+
return { status: "passed", reason: "Supabase Preview check passed." };
|
|
29866
|
+
}
|
|
29867
|
+
if (state === "skipped" || state === "neutral") {
|
|
29868
|
+
return {
|
|
29869
|
+
status: "skipped",
|
|
29870
|
+
reason: "Supabase Preview check skipped at CI."
|
|
29871
|
+
};
|
|
29872
|
+
}
|
|
29873
|
+
if (state === "failure" || state === "cancelled" || state === "error" || state === "timed_out" || state === "stale" || state === "action_required") {
|
|
29874
|
+
return {
|
|
29875
|
+
status: "blocked",
|
|
29876
|
+
reason: `Supabase Preview check ${state}.`
|
|
29877
|
+
};
|
|
29878
|
+
}
|
|
29879
|
+
}
|
|
29880
|
+
const minutesStr = Math.round(maxPolls * intervalMs / 6e4);
|
|
29881
|
+
return {
|
|
29882
|
+
status: "blocked",
|
|
29883
|
+
reason: `Supabase Preview check still pending after ${minutesStr} min (${maxPolls} polls)`
|
|
29884
|
+
};
|
|
29885
|
+
}
|
|
29886
|
+
var GIT_DEFAULTS, DEFAULT_DB_PATHS;
|
|
29887
|
+
var init_supabase = __esm({
|
|
29888
|
+
"src/lib/supabase.ts"() {
|
|
29889
|
+
"use strict";
|
|
29890
|
+
GIT_DEFAULTS = {
|
|
29891
|
+
production: "main",
|
|
29892
|
+
protected: ["main"],
|
|
29893
|
+
integration: null
|
|
29894
|
+
};
|
|
29895
|
+
DEFAULT_DB_PATHS = [
|
|
29896
|
+
"supabase/**",
|
|
29897
|
+
"apps/backend/**",
|
|
29898
|
+
"packages/**/db/**"
|
|
29899
|
+
];
|
|
29900
|
+
}
|
|
29901
|
+
});
|
|
29902
|
+
|
|
29903
|
+
// src/lib/session.ts
|
|
29904
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
29905
|
+
import { existsSync as nodeExistsSync } from "node:fs";
|
|
29906
|
+
import * as path8 from "node:path";
|
|
29907
|
+
function defaultRun2(cmd, args, cwd) {
|
|
29908
|
+
const result = spawnSync7(cmd, args, {
|
|
29909
|
+
cwd,
|
|
29910
|
+
encoding: "utf-8",
|
|
29911
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
29912
|
+
});
|
|
29913
|
+
if (result.error) throw result.error;
|
|
29914
|
+
if (result.status !== 0) {
|
|
29915
|
+
const stderr = (result.stderr ?? "").toString().trim();
|
|
29916
|
+
throw new Error(
|
|
29917
|
+
`${cmd} ${args.join(" ")} exited ${result.status ?? "null"}${stderr ? `: ${stderr}` : ""}`
|
|
29918
|
+
);
|
|
29919
|
+
}
|
|
29920
|
+
return (result.stdout ?? "").toString();
|
|
29921
|
+
}
|
|
29922
|
+
function homeFf(opts = {}) {
|
|
29923
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
29924
|
+
const run = opts.run ?? defaultRun2;
|
|
29925
|
+
const gitCfg = readGitConfig(cwd);
|
|
29926
|
+
const production = gitCfg.production;
|
|
29927
|
+
let repoRoot;
|
|
29928
|
+
try {
|
|
29929
|
+
repoRoot = run("git", ["rev-parse", "--show-toplevel"], cwd).trim();
|
|
29930
|
+
} catch {
|
|
29931
|
+
return {
|
|
29932
|
+
result: "skipped",
|
|
29933
|
+
reason: "git rev-parse --show-toplevel failed"
|
|
29934
|
+
};
|
|
29935
|
+
}
|
|
29936
|
+
const folder = path8.basename(repoRoot);
|
|
29937
|
+
let current;
|
|
29938
|
+
try {
|
|
29939
|
+
current = run("git", ["rev-parse", "--abbrev-ref", "HEAD"], cwd).trim();
|
|
29940
|
+
} catch {
|
|
29941
|
+
return {
|
|
29942
|
+
result: "skipped",
|
|
29943
|
+
reason: "git rev-parse --abbrev-ref HEAD failed"
|
|
29944
|
+
};
|
|
29945
|
+
}
|
|
29946
|
+
if (current !== folder) {
|
|
29947
|
+
return { result: "skipped", reason: "not on home branch" };
|
|
29948
|
+
}
|
|
29949
|
+
try {
|
|
29950
|
+
run("git", ["fetch", "origin", production], cwd);
|
|
29951
|
+
} catch {
|
|
29952
|
+
return {
|
|
29953
|
+
result: "warn",
|
|
29954
|
+
warn: `fetch failed \u2014 staying on local ${current}`
|
|
29955
|
+
};
|
|
29956
|
+
}
|
|
29957
|
+
try {
|
|
29958
|
+
run("git", ["merge", "--ff-only", `origin/${production}`], cwd);
|
|
29959
|
+
} catch {
|
|
29960
|
+
return {
|
|
29961
|
+
result: "warn",
|
|
29962
|
+
warn: `${current} not fast-forwardable (ahead/diverged) \u2014 left untouched`
|
|
29963
|
+
};
|
|
29964
|
+
}
|
|
29965
|
+
return { result: "fast_forwarded" };
|
|
29966
|
+
}
|
|
29967
|
+
function spawnVersionStatus(cwd) {
|
|
29968
|
+
try {
|
|
29969
|
+
const result = spawnSync7("npx", ["codebyplan", "version-status"], {
|
|
29970
|
+
cwd,
|
|
29971
|
+
encoding: "utf-8",
|
|
29972
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
29973
|
+
});
|
|
29974
|
+
if (result.error) return null;
|
|
29975
|
+
const raw = (result.stdout ?? "").toString().trim();
|
|
29976
|
+
if (!raw) return null;
|
|
29977
|
+
const parsed = JSON.parse(raw);
|
|
29978
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
29979
|
+
return null;
|
|
29980
|
+
}
|
|
29981
|
+
const obj = parsed;
|
|
29982
|
+
if (typeof obj["installed"] !== "string" || typeof obj["newer"] !== "boolean" || typeof obj["guarded"] !== "boolean" || typeof obj["installCommand"] !== "string") {
|
|
29983
|
+
return null;
|
|
29984
|
+
}
|
|
29985
|
+
return {
|
|
29986
|
+
installed: obj["installed"],
|
|
29987
|
+
latest: typeof obj["latest"] === "string" ? obj["latest"] : null,
|
|
29988
|
+
newer: obj["newer"],
|
|
29989
|
+
packageManager: typeof obj["packageManager"] === "string" ? obj["packageManager"] : "npm",
|
|
29990
|
+
installCommand: obj["installCommand"],
|
|
29991
|
+
guarded: obj["guarded"],
|
|
29992
|
+
guardReason: typeof obj["guardReason"] === "string" ? obj["guardReason"] : null
|
|
29993
|
+
};
|
|
29994
|
+
} catch {
|
|
29995
|
+
return null;
|
|
29996
|
+
}
|
|
29997
|
+
}
|
|
29998
|
+
function defaultRunInstall(installCommand, cwd) {
|
|
29999
|
+
const parts = installCommand.trim().split(/\s+/);
|
|
30000
|
+
const cmd = parts[0];
|
|
30001
|
+
const args = parts.slice(1);
|
|
30002
|
+
if (!cmd) throw new Error("empty installCommand");
|
|
30003
|
+
const result = spawnSync7(cmd, args, {
|
|
30004
|
+
cwd,
|
|
30005
|
+
encoding: "utf-8",
|
|
30006
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
30007
|
+
});
|
|
30008
|
+
if (result.error) throw result.error;
|
|
30009
|
+
if (result.status !== 0) {
|
|
30010
|
+
const stderr = (result.stderr ?? "").toString().trim();
|
|
30011
|
+
throw new Error(
|
|
30012
|
+
`install exited ${result.status}${stderr ? `: ${stderr}` : ""}`
|
|
30013
|
+
);
|
|
30014
|
+
}
|
|
30015
|
+
}
|
|
30016
|
+
function defaultRunClaudeUpdate(cwd) {
|
|
30017
|
+
const result = spawnSync7("npx", ["codebyplan", "claude", "update", "--yes"], {
|
|
30018
|
+
cwd,
|
|
30019
|
+
encoding: "utf-8",
|
|
30020
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
30021
|
+
});
|
|
30022
|
+
if (result.error) throw result.error;
|
|
30023
|
+
if (result.status !== 0) {
|
|
30024
|
+
const stderr = (result.stderr ?? "").toString().trim();
|
|
30025
|
+
throw new Error(
|
|
30026
|
+
`claude update exited ${result.status}${stderr ? `: ${stderr}` : ""}`
|
|
30027
|
+
);
|
|
30028
|
+
}
|
|
30029
|
+
}
|
|
30030
|
+
function defaultRunGitStatus(cwd) {
|
|
30031
|
+
const result = spawnSync7(
|
|
30032
|
+
"git",
|
|
30033
|
+
["status", "--porcelain", "--", ".claude/", ".codebyplan/"],
|
|
30034
|
+
{
|
|
30035
|
+
cwd,
|
|
30036
|
+
encoding: "utf-8",
|
|
30037
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
30038
|
+
}
|
|
30039
|
+
);
|
|
30040
|
+
if (result.error) throw result.error;
|
|
30041
|
+
return (result.stdout ?? "").toString();
|
|
30042
|
+
}
|
|
30043
|
+
async function freshnessGate(opts = {}) {
|
|
30044
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
30045
|
+
const probeVersionStatus = opts.probeVersionStatus ?? ((c) => spawnVersionStatus(c));
|
|
30046
|
+
const runInstall2 = opts.runInstall ?? defaultRunInstall;
|
|
30047
|
+
const runClaudeUpdate = opts.runClaudeUpdate ?? defaultRunClaudeUpdate;
|
|
30048
|
+
const runGitStatus = opts.runGitStatus ?? defaultRunGitStatus;
|
|
30049
|
+
const haltOnUpdate = opts.haltOnUpdate ?? false;
|
|
30050
|
+
let probe;
|
|
30051
|
+
try {
|
|
30052
|
+
probe = probeVersionStatus(cwd);
|
|
30053
|
+
} catch {
|
|
30054
|
+
probe = null;
|
|
30055
|
+
}
|
|
30056
|
+
if (!probe) {
|
|
30057
|
+
return { result: "skipped", reason: "probe failed (fail-safe)" };
|
|
30058
|
+
}
|
|
30059
|
+
if (probe.guarded) {
|
|
30060
|
+
return { result: "guarded" };
|
|
30061
|
+
}
|
|
30062
|
+
if (!probe.newer) {
|
|
30063
|
+
return { result: "up_to_date" };
|
|
30064
|
+
}
|
|
30065
|
+
try {
|
|
30066
|
+
runInstall2(probe.installCommand, cwd);
|
|
30067
|
+
} catch (err) {
|
|
30068
|
+
const reason = err instanceof Error ? err.message : "install failed (unknown error)";
|
|
30069
|
+
return { result: "error", reason };
|
|
30070
|
+
}
|
|
30071
|
+
try {
|
|
30072
|
+
runClaudeUpdate(cwd);
|
|
30073
|
+
} catch (err) {
|
|
30074
|
+
const reason = err instanceof Error ? err.message : "claude update failed (unknown error)";
|
|
30075
|
+
return { result: "error", reason };
|
|
30076
|
+
}
|
|
30077
|
+
let gitStatusOutput = "";
|
|
30078
|
+
try {
|
|
30079
|
+
gitStatusOutput = runGitStatus(cwd);
|
|
30080
|
+
} catch {
|
|
30081
|
+
gitStatusOutput = "";
|
|
30082
|
+
}
|
|
30083
|
+
const changedFiles = gitStatusOutput.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
30084
|
+
const parts = line.split(/\s+/);
|
|
30085
|
+
return parts.slice(1).join(" ");
|
|
30086
|
+
}).filter(Boolean);
|
|
30087
|
+
return {
|
|
30088
|
+
result: "updated",
|
|
30089
|
+
latest: probe.latest ?? probe.installed,
|
|
30090
|
+
changed_files: changedFiles,
|
|
30091
|
+
halt: haltOnUpdate
|
|
30092
|
+
};
|
|
30093
|
+
}
|
|
30094
|
+
async function infraFiles(opts = {}) {
|
|
30095
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
30096
|
+
const run = opts.run ?? defaultRun2;
|
|
30097
|
+
const getTaskFiles = opts.getTaskFiles ?? (() => Promise.resolve([]));
|
|
30098
|
+
let firstOutput;
|
|
30099
|
+
try {
|
|
30100
|
+
firstOutput = run("git", ["status", "--porcelain"], cwd);
|
|
30101
|
+
} catch {
|
|
30102
|
+
firstOutput = "";
|
|
30103
|
+
}
|
|
30104
|
+
const firstChanged = parseGitStatus2(firstOutput);
|
|
30105
|
+
if (firstChanged.length === 0) {
|
|
30106
|
+
return { infra_files: [], task_files: [], note: "clean tree" };
|
|
30107
|
+
}
|
|
30108
|
+
const taskFiles = await getTaskFiles();
|
|
30109
|
+
const taskSet = new Set(taskFiles);
|
|
30110
|
+
let secondOutput;
|
|
30111
|
+
try {
|
|
30112
|
+
secondOutput = run("git", ["status", "--porcelain"], cwd);
|
|
30113
|
+
} catch {
|
|
30114
|
+
secondOutput = "";
|
|
30115
|
+
}
|
|
30116
|
+
const freshChanged = parseGitStatus2(secondOutput);
|
|
30117
|
+
const infraFilesList = freshChanged.filter((f) => !taskSet.has(f));
|
|
30118
|
+
return {
|
|
30119
|
+
infra_files: infraFilesList,
|
|
30120
|
+
task_files: taskFiles
|
|
30121
|
+
};
|
|
30122
|
+
}
|
|
30123
|
+
function resolveWorktreeJson(opts = {}) {
|
|
30124
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
30125
|
+
const run = opts.run ?? defaultRun2;
|
|
30126
|
+
try {
|
|
30127
|
+
const stdout7 = run(
|
|
30128
|
+
"npx",
|
|
30129
|
+
["codebyplan", "resolve-worktree", "--json"],
|
|
30130
|
+
cwd
|
|
30131
|
+
);
|
|
30132
|
+
const raw = stdout7.trim();
|
|
30133
|
+
if (!raw) {
|
|
30134
|
+
return { worktree_id: null, error_kind: "tuple_miss" };
|
|
30135
|
+
}
|
|
30136
|
+
const parsed = JSON.parse(raw);
|
|
30137
|
+
const worktree_id = typeof parsed["worktree_id"] === "string" ? parsed["worktree_id"] : null;
|
|
30138
|
+
const error_kind = typeof parsed["error_kind"] === "string" ? parsed["error_kind"] : null;
|
|
30139
|
+
return { worktree_id, error_kind };
|
|
30140
|
+
} catch (err) {
|
|
30141
|
+
process.stderr.write(
|
|
30142
|
+
`session: resolveWorktreeJson failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30143
|
+
`
|
|
30144
|
+
);
|
|
30145
|
+
return { worktree_id: null, error_kind: "unhandled" };
|
|
30146
|
+
}
|
|
30147
|
+
}
|
|
30148
|
+
function infraDriftNudge(opts = {}) {
|
|
30149
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
30150
|
+
const run = opts.run ?? defaultRun2;
|
|
30151
|
+
const existsSync24 = opts.existsSync ?? ((p) => {
|
|
30152
|
+
try {
|
|
30153
|
+
return nodeExistsSync(p);
|
|
30154
|
+
} catch {
|
|
30155
|
+
return false;
|
|
30156
|
+
}
|
|
30157
|
+
});
|
|
30158
|
+
try {
|
|
30159
|
+
const driftScript = path8.join(cwd, "scripts", "infra-drift.mjs");
|
|
30160
|
+
const templatesDir = path8.join(
|
|
30161
|
+
cwd,
|
|
30162
|
+
"packages",
|
|
30163
|
+
"codebyplan-package",
|
|
30164
|
+
"templates"
|
|
30165
|
+
);
|
|
30166
|
+
if (!existsSync24(driftScript) || !existsSync24(templatesDir)) {
|
|
30167
|
+
return null;
|
|
30168
|
+
}
|
|
30169
|
+
try {
|
|
30170
|
+
const production = readGitConfig(cwd).production || "main";
|
|
30171
|
+
run("git", ["fetch", "origin", production], cwd);
|
|
30172
|
+
} catch {
|
|
30173
|
+
}
|
|
30174
|
+
let output = "";
|
|
30175
|
+
try {
|
|
30176
|
+
output = run("node", [driftScript], cwd);
|
|
30177
|
+
} catch {
|
|
30178
|
+
return null;
|
|
30179
|
+
}
|
|
30180
|
+
const line = output.trim();
|
|
30181
|
+
return line || null;
|
|
30182
|
+
} catch (err) {
|
|
30183
|
+
process.stderr.write(
|
|
30184
|
+
`session: infraDriftNudge failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30185
|
+
`
|
|
30186
|
+
);
|
|
30187
|
+
return null;
|
|
30188
|
+
}
|
|
30189
|
+
}
|
|
30190
|
+
function archMapDriftNudge(opts = {}) {
|
|
30191
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
30192
|
+
const run = opts.run ?? defaultRun2;
|
|
30193
|
+
const existsSync24 = opts.existsSync ?? ((p) => {
|
|
30194
|
+
try {
|
|
30195
|
+
return nodeExistsSync(p);
|
|
30196
|
+
} catch {
|
|
30197
|
+
return false;
|
|
30198
|
+
}
|
|
30199
|
+
});
|
|
30200
|
+
try {
|
|
30201
|
+
const manifestPath2 = path8.join(cwd, ".codebyplan", "architecture.json");
|
|
30202
|
+
if (!existsSync24(manifestPath2)) {
|
|
30203
|
+
return null;
|
|
30204
|
+
}
|
|
30205
|
+
let output = "";
|
|
30206
|
+
try {
|
|
30207
|
+
output = run("npx", ["codebyplan", "arch-map", "drift"], cwd);
|
|
30208
|
+
} catch {
|
|
30209
|
+
return null;
|
|
30210
|
+
}
|
|
30211
|
+
const driftedCount = output.split("\n").filter((line) => /^\s*DRIFTED/.test(line)).length;
|
|
30212
|
+
if (driftedCount > 0) {
|
|
30213
|
+
return `\u26A0 .claude/architecture is ${driftedCount} module(s) stale \u2014 run /cbp-refresh-arch-map`;
|
|
30214
|
+
}
|
|
30215
|
+
return null;
|
|
30216
|
+
} catch (err) {
|
|
30217
|
+
process.stderr.write(
|
|
30218
|
+
`session: archMapDriftNudge failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30219
|
+
`
|
|
30220
|
+
);
|
|
30221
|
+
return null;
|
|
30222
|
+
}
|
|
30223
|
+
}
|
|
30224
|
+
function lspNudge(opts = {}) {
|
|
30225
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
30226
|
+
const run = opts.run ?? defaultRun2;
|
|
30227
|
+
try {
|
|
30228
|
+
let output = "";
|
|
30229
|
+
try {
|
|
30230
|
+
output = run("npx", ["codebyplan", "lsp", "--check"], cwd);
|
|
30231
|
+
} catch {
|
|
30232
|
+
return [];
|
|
30233
|
+
}
|
|
30234
|
+
return output.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
30235
|
+
} catch (err) {
|
|
30236
|
+
process.stderr.write(
|
|
30237
|
+
`session: lspNudge failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30238
|
+
`
|
|
30239
|
+
);
|
|
30240
|
+
return [];
|
|
30241
|
+
}
|
|
30242
|
+
}
|
|
30243
|
+
async function probeHandoff(opts) {
|
|
30244
|
+
const stale = { fresh: false };
|
|
30245
|
+
try {
|
|
30246
|
+
const {
|
|
30247
|
+
repoRoot,
|
|
30248
|
+
worktreeId,
|
|
30249
|
+
previousSessionRow,
|
|
30250
|
+
freshnessWindowHours = 24,
|
|
30251
|
+
readEntity
|
|
30252
|
+
} = opts;
|
|
30253
|
+
if (!previousSessionRow) return stale;
|
|
30254
|
+
if (!previousSessionRow.closed_at) return stale;
|
|
30255
|
+
if (previousSessionRow.content == null) return stale;
|
|
30256
|
+
let handoff;
|
|
30257
|
+
try {
|
|
30258
|
+
const raw = typeof previousSessionRow.content === "string" ? JSON.parse(previousSessionRow.content) : previousSessionRow.content;
|
|
30259
|
+
if (typeof raw !== "object" || raw === null) return stale;
|
|
30260
|
+
const obj = raw;
|
|
30261
|
+
if (!obj["command"] || typeof obj["command"] !== "string") return stale;
|
|
30262
|
+
if (!obj["command"].trim()) return stale;
|
|
30263
|
+
handoff = {
|
|
30264
|
+
command: obj["command"],
|
|
30265
|
+
captured_at: typeof obj["captured_at"] === "string" ? obj["captured_at"] : void 0,
|
|
30266
|
+
context: typeof obj["context"] === "object" && obj["context"] !== null ? obj["context"] : {},
|
|
30267
|
+
state: obj["state"]
|
|
30268
|
+
};
|
|
30269
|
+
} catch {
|
|
30270
|
+
return stale;
|
|
30271
|
+
}
|
|
30272
|
+
const closedAt = new Date(previousSessionRow.closed_at).getTime();
|
|
30273
|
+
const windowMs = freshnessWindowHours * 60 * 60 * 1e3;
|
|
30274
|
+
if (Date.now() - closedAt > windowMs) return stale;
|
|
30275
|
+
const capturedAt = handoff.captured_at ?? previousSessionRow.closed_at;
|
|
30276
|
+
const ctx = handoff.context ?? {};
|
|
30277
|
+
const resolveEntityPath = (entityType, id) => {
|
|
30278
|
+
const stateDir2 = path8.join(repoRoot, ".codebyplan", "state");
|
|
30279
|
+
if (entityType === "checkpoint") {
|
|
30280
|
+
return path8.join(stateDir2, "checkpoints", `${id}.json`);
|
|
30281
|
+
}
|
|
30282
|
+
if (entityType === "task" && ctx.checkpoint_id) {
|
|
30283
|
+
return path8.join(
|
|
30284
|
+
stateDir2,
|
|
30285
|
+
"checkpoints",
|
|
30286
|
+
ctx.checkpoint_id,
|
|
30287
|
+
"tasks",
|
|
30288
|
+
`${id}.json`
|
|
30289
|
+
);
|
|
30290
|
+
}
|
|
30291
|
+
if (entityType === "round" && ctx.checkpoint_id && ctx.task_id) {
|
|
30292
|
+
return path8.join(
|
|
30293
|
+
stateDir2,
|
|
30294
|
+
"checkpoints",
|
|
30295
|
+
ctx.checkpoint_id,
|
|
30296
|
+
"tasks",
|
|
30297
|
+
ctx.task_id,
|
|
30298
|
+
"rounds",
|
|
30299
|
+
`${id}.json`
|
|
30300
|
+
);
|
|
30301
|
+
}
|
|
30302
|
+
return "";
|
|
30303
|
+
};
|
|
30304
|
+
const reader = readEntity ?? (async (filePath) => {
|
|
30305
|
+
const { readEntityFile: ref } = await Promise.resolve().then(() => (init_state_store(), state_store_exports));
|
|
30306
|
+
return ref(filePath);
|
|
30307
|
+
});
|
|
30308
|
+
if (ctx.checkpoint_id) {
|
|
30309
|
+
const chkPath = resolveEntityPath("checkpoint", ctx.checkpoint_id);
|
|
30310
|
+
if (!chkPath) return stale;
|
|
30311
|
+
const chk = await reader(chkPath);
|
|
30312
|
+
if (!chk) return stale;
|
|
30313
|
+
if (chk.worktree_id != null && (worktreeId === null || worktreeId !== chk.worktree_id)) {
|
|
30314
|
+
return stale;
|
|
30315
|
+
}
|
|
30316
|
+
if (chk.updated_at && capturedAt && chk.updated_at > capturedAt) {
|
|
30317
|
+
return stale;
|
|
30318
|
+
}
|
|
30319
|
+
}
|
|
30320
|
+
if (ctx.task_id) {
|
|
30321
|
+
const taskPath2 = resolveEntityPath("task", ctx.task_id);
|
|
30322
|
+
if (!taskPath2) return stale;
|
|
30323
|
+
const task = await reader(taskPath2);
|
|
30324
|
+
if (!task) return stale;
|
|
30325
|
+
if (task.updated_at && capturedAt && task.updated_at > capturedAt) {
|
|
30326
|
+
return stale;
|
|
30327
|
+
}
|
|
30328
|
+
}
|
|
30329
|
+
if (ctx.round_id) {
|
|
30330
|
+
const roundPath2 = resolveEntityPath("round", ctx.round_id);
|
|
30331
|
+
if (!roundPath2) return stale;
|
|
30332
|
+
const round = await reader(roundPath2);
|
|
30333
|
+
if (!round) return stale;
|
|
30334
|
+
if (round.updated_at && capturedAt && round.updated_at > capturedAt) {
|
|
30335
|
+
return stale;
|
|
30336
|
+
}
|
|
30337
|
+
}
|
|
30338
|
+
return {
|
|
30339
|
+
fresh: true,
|
|
30340
|
+
command: handoff.command,
|
|
30341
|
+
context: ctx,
|
|
30342
|
+
state: handoff.state
|
|
30343
|
+
};
|
|
30344
|
+
} catch (err) {
|
|
30345
|
+
process.stderr.write(
|
|
30346
|
+
`session: probeHandoff failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30347
|
+
`
|
|
30348
|
+
);
|
|
30349
|
+
return stale;
|
|
30350
|
+
}
|
|
30351
|
+
}
|
|
30352
|
+
function partitionOwnership(checkpoints, worktreeId) {
|
|
30353
|
+
const owned = [];
|
|
30354
|
+
const cross = [];
|
|
30355
|
+
for (const chk of checkpoints) {
|
|
30356
|
+
const id = chk.id ?? "";
|
|
30357
|
+
const title = chk.title ?? (chk.number != null ? `CHK-${chk.number}` : id);
|
|
30358
|
+
const chkWorktreeId = chk.worktree_id ?? null;
|
|
30359
|
+
if (chkWorktreeId === null || chkWorktreeId === worktreeId) {
|
|
30360
|
+
owned.push({ id, title });
|
|
30361
|
+
} else {
|
|
30362
|
+
cross.push({ id, title });
|
|
30363
|
+
}
|
|
30364
|
+
}
|
|
30365
|
+
return { owned, cross };
|
|
30366
|
+
}
|
|
30367
|
+
function computeNextAction(input) {
|
|
30368
|
+
const { status, owned_count, total_count, handoff_fresh, infra_files_count } = input;
|
|
30369
|
+
if (status === "update_halt") return "mcp_update_halt";
|
|
30370
|
+
if (handoff_fresh) return "resume_handoff";
|
|
30371
|
+
if (infra_files_count > 0 && owned_count >= 1) return "commit_then_todo";
|
|
30372
|
+
if (owned_count >= 1) return "trigger_todo";
|
|
30373
|
+
if (total_count >= 1 && owned_count === 0) return "stop";
|
|
30374
|
+
return "trigger_todo";
|
|
30375
|
+
}
|
|
30376
|
+
function renderBlock(envelope) {
|
|
30377
|
+
const lines = [];
|
|
30378
|
+
const worktreeDisplay = envelope.worktree_id ?? "unregistered";
|
|
30379
|
+
lines.push(`Session active | Worktree: ${worktreeDisplay}`);
|
|
30380
|
+
lines.push("");
|
|
30381
|
+
if (envelope.worktree_error_kind !== null && envelope.worktree_error_kind !== "tuple_miss") {
|
|
30382
|
+
lines.push(
|
|
30383
|
+
`\u26A0 resolve-worktree: ${envelope.worktree_error_kind} \u2014 local state is broken; routing may be unreliable. Run \`npx codebyplan setup\` to repair.`
|
|
30384
|
+
);
|
|
30385
|
+
lines.push("");
|
|
30386
|
+
}
|
|
30387
|
+
if (envelope.infra_drift_nudge) {
|
|
30388
|
+
lines.push(envelope.infra_drift_nudge);
|
|
30389
|
+
}
|
|
30390
|
+
if (envelope.arch_map_nudge) {
|
|
30391
|
+
lines.push(envelope.arch_map_nudge);
|
|
30392
|
+
}
|
|
30393
|
+
if (envelope.infra_drift_nudge || envelope.arch_map_nudge) {
|
|
30394
|
+
lines.push("");
|
|
30395
|
+
}
|
|
30396
|
+
const prevTitle = envelope.previous_session?.title ?? "none";
|
|
30397
|
+
lines.push(`Previous session: ${prevTitle}`);
|
|
30398
|
+
const pending = envelope.previous_session?.pending ?? "\u2014";
|
|
30399
|
+
lines.push(` Pending: ${pending}`);
|
|
30400
|
+
lines.push("");
|
|
30401
|
+
lines.push(
|
|
30402
|
+
`Ownership: ${envelope.total_count} active CHK(s), ${envelope.owned_count} owned by this worktree`
|
|
30403
|
+
);
|
|
30404
|
+
if (envelope.owned_count > 0) {
|
|
30405
|
+
const ownedStr = envelope.owned_checkpoints.map((c) => c.title).join(", ");
|
|
30406
|
+
lines.push(`Owned: ${ownedStr}`);
|
|
30407
|
+
}
|
|
30408
|
+
if (envelope.cross_checkpoints.length > 0) {
|
|
30409
|
+
const crossStr = envelope.cross_checkpoints.map((c) => c.title).join(", ");
|
|
30410
|
+
lines.push(`Cross-worktree: ${crossStr}`);
|
|
30411
|
+
}
|
|
30412
|
+
if (envelope.lsp_nudges.length > 0) {
|
|
30413
|
+
lines.push("");
|
|
30414
|
+
for (const hint of envelope.lsp_nudges) {
|
|
30415
|
+
lines.push(`LSP: ${hint}`);
|
|
30416
|
+
}
|
|
30417
|
+
}
|
|
30418
|
+
if (envelope.worktree_id === null && (envelope.worktree_error_kind === null || envelope.worktree_error_kind === "tuple_miss")) {
|
|
30419
|
+
lines.push("");
|
|
30420
|
+
lines.push(
|
|
30421
|
+
`\u26A0 Worktree unregistered \u2014 run \`npx codebyplan setup\` to register`
|
|
30422
|
+
);
|
|
30423
|
+
}
|
|
30424
|
+
return lines.join("\n");
|
|
30425
|
+
}
|
|
30426
|
+
function parseGitStatus2(output) {
|
|
30427
|
+
return output.split("\n").filter(Boolean).map((line) => {
|
|
30428
|
+
if (line.length > 3) {
|
|
30429
|
+
const rest = line.slice(3);
|
|
30430
|
+
const arrow = rest.indexOf(" -> ");
|
|
30431
|
+
if (arrow !== -1) {
|
|
30432
|
+
return rest.slice(arrow + 4).trim();
|
|
30433
|
+
}
|
|
30434
|
+
return rest.trim();
|
|
30435
|
+
}
|
|
30436
|
+
return "";
|
|
30437
|
+
}).filter(Boolean);
|
|
30438
|
+
}
|
|
30439
|
+
var init_session = __esm({
|
|
30440
|
+
"src/lib/session.ts"() {
|
|
30441
|
+
"use strict";
|
|
30442
|
+
init_supabase();
|
|
30443
|
+
}
|
|
30444
|
+
});
|
|
30445
|
+
|
|
30446
|
+
// src/cli/session/start.ts
|
|
30447
|
+
var start_exports = {};
|
|
30448
|
+
__export(start_exports, {
|
|
30449
|
+
buildCreateLogBody: () => buildCreateLogBody,
|
|
30450
|
+
defaultGetCheckpoints: () => defaultGetCheckpoints,
|
|
30451
|
+
runSessionStartCli: () => runSessionStartCli
|
|
30452
|
+
});
|
|
30453
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
30454
|
+
import { dirname as dirname9 } from "node:path";
|
|
30455
|
+
async function updateCursorHashLocal(repoRoot, entityId, row) {
|
|
30456
|
+
const cursor = await readCursor(repoRoot);
|
|
30457
|
+
if (!cursor) return;
|
|
30458
|
+
const hash = hashEntity(row);
|
|
30459
|
+
cursor.entity_hashes[entityId] = hash;
|
|
30460
|
+
await writeCursor(repoRoot, cursor);
|
|
30461
|
+
}
|
|
30462
|
+
async function defaultUpdateStateActivate(repoId, repoRoot) {
|
|
30463
|
+
const snakePatch = { action: "activate" };
|
|
30464
|
+
const stateFilePath = sessionLogPath(repoRoot).replace(
|
|
30465
|
+
"current.json",
|
|
30466
|
+
"state.json"
|
|
30467
|
+
);
|
|
30468
|
+
const snapshot = await readEntityFile(stateFilePath);
|
|
30469
|
+
const optimistic = { ...snapshot ?? {}, ...snakePatch, repo_id: repoId };
|
|
30470
|
+
await writeEntityFile(stateFilePath, optimistic);
|
|
30471
|
+
try {
|
|
30472
|
+
const updated = await apiBackendPatch(
|
|
30473
|
+
new URL(backendSessionStateEndpoint(repoId)).pathname,
|
|
30474
|
+
snakePatch
|
|
30475
|
+
);
|
|
30476
|
+
await writeEntityFile(stateFilePath, updated);
|
|
30477
|
+
} catch (err) {
|
|
30478
|
+
if (err instanceof BackendError && err.status < 500) {
|
|
30479
|
+
if (snapshot !== null) {
|
|
30480
|
+
await writeEntityFile(stateFilePath, snapshot);
|
|
30481
|
+
} else {
|
|
30482
|
+
await deleteEntityFile(stateFilePath);
|
|
30483
|
+
}
|
|
30484
|
+
} else {
|
|
30485
|
+
await writeEntityFile(
|
|
30486
|
+
pendingMarkerPath(repoRoot, `session-state-${repoId}`),
|
|
30487
|
+
{
|
|
30488
|
+
entity: "session_state",
|
|
30489
|
+
repo_id: repoId,
|
|
30490
|
+
operation: "update-state",
|
|
30491
|
+
attempted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30492
|
+
error: err instanceof Error ? err.message : String(err)
|
|
30493
|
+
}
|
|
30494
|
+
);
|
|
30495
|
+
}
|
|
30496
|
+
process.stderr.write(
|
|
30497
|
+
`session start: update-state activate failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30498
|
+
`
|
|
30499
|
+
);
|
|
30500
|
+
}
|
|
30501
|
+
}
|
|
30502
|
+
function buildCreateLogBody(repoId, worktreeId, now = /* @__PURE__ */ new Date()) {
|
|
30503
|
+
const session_date = now.toISOString().slice(0, 10);
|
|
30504
|
+
const jan1 = Date.UTC(now.getUTCFullYear(), 0, 1);
|
|
30505
|
+
const day_number = Math.floor((now.getTime() - jan1) / 864e5) + 1;
|
|
30506
|
+
return {
|
|
30507
|
+
repo_id: repoId,
|
|
30508
|
+
session_date,
|
|
30509
|
+
day_number,
|
|
30510
|
+
started_at: now.toISOString(),
|
|
30511
|
+
summary: "",
|
|
30512
|
+
...worktreeId != null ? { worktree_id: worktreeId } : {}
|
|
30513
|
+
};
|
|
30514
|
+
}
|
|
30515
|
+
async function defaultCreateLog(repoId, repoRoot, worktreeId) {
|
|
30516
|
+
const body = buildCreateLogBody(repoId, worktreeId);
|
|
30517
|
+
try {
|
|
30518
|
+
const created = await apiBackendPost(new URL(backendSessionLogsEndpoint()).pathname, body);
|
|
30519
|
+
const sessionLog = created.session_log ?? created;
|
|
30520
|
+
const filePath = sessionLogPath(repoRoot);
|
|
30521
|
+
await writeEntityFile(filePath, sessionLog);
|
|
30522
|
+
const sessionLogId = sessionLog.id;
|
|
30523
|
+
if (sessionLogId) {
|
|
30524
|
+
await updateCursorHashLocal(repoRoot, sessionLogId, sessionLog);
|
|
30525
|
+
}
|
|
30526
|
+
return sessionLogId ?? null;
|
|
30527
|
+
} catch (err) {
|
|
30528
|
+
process.stderr.write(
|
|
30529
|
+
`session start: create-log failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30530
|
+
`
|
|
30531
|
+
);
|
|
30532
|
+
return null;
|
|
30533
|
+
}
|
|
30534
|
+
}
|
|
30535
|
+
async function defaultGetCheckpoints(repoId) {
|
|
30536
|
+
try {
|
|
30537
|
+
const result = await apiGet("/checkpoints", {
|
|
30538
|
+
repo_id: repoId,
|
|
30539
|
+
status: "active"
|
|
30540
|
+
});
|
|
30541
|
+
if (Array.isArray(result)) {
|
|
30542
|
+
return result;
|
|
30543
|
+
}
|
|
30544
|
+
const res = result ?? {};
|
|
30545
|
+
if (Array.isArray(res["data"])) {
|
|
30546
|
+
return res["data"];
|
|
30547
|
+
}
|
|
30548
|
+
if (Array.isArray(res["checkpoints"])) {
|
|
30549
|
+
return res["checkpoints"];
|
|
30550
|
+
}
|
|
30551
|
+
return [];
|
|
30552
|
+
} catch {
|
|
30553
|
+
return [];
|
|
30554
|
+
}
|
|
30555
|
+
}
|
|
30556
|
+
function defaultRunSync(cwd) {
|
|
30557
|
+
try {
|
|
30558
|
+
spawnSync8("npx", ["codebyplan", "sync"], {
|
|
30559
|
+
cwd,
|
|
30560
|
+
encoding: "utf-8",
|
|
30561
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
30562
|
+
});
|
|
30563
|
+
} catch {
|
|
30564
|
+
}
|
|
30565
|
+
}
|
|
30566
|
+
async function resolveRepoInfo(cwd) {
|
|
30567
|
+
const found = await findCodebyplanConfig(cwd);
|
|
30568
|
+
if (!found?.contents.repo_id) return null;
|
|
30569
|
+
const repoRoot = deriveRepoRoot(found.path);
|
|
30570
|
+
return { repoRoot, repoId: found.contents.repo_id };
|
|
30571
|
+
}
|
|
30572
|
+
async function resolveTaskFilesFromState(repoRoot) {
|
|
30573
|
+
try {
|
|
30574
|
+
const todos = await readEntityFile(todosPath(repoRoot));
|
|
30575
|
+
const rows = Array.isArray(todos) ? todos : [];
|
|
30576
|
+
const active = rows.find((t) => t["status"] === "current");
|
|
30577
|
+
if (!active) return [];
|
|
30578
|
+
const checkpoint_id = active["checkpoint_id"];
|
|
30579
|
+
const task_id = active["task_id"];
|
|
30580
|
+
if (!checkpoint_id || !task_id) return [];
|
|
30581
|
+
const roundsDir = dirname9(roundPath(repoRoot, checkpoint_id, task_id, "_"));
|
|
30582
|
+
const roundFiles = await listEntityFiles(roundsDir);
|
|
30583
|
+
const fileSet = /* @__PURE__ */ new Set();
|
|
30584
|
+
for (const rPath of roundFiles) {
|
|
30585
|
+
const round = await readEntityFile(rPath);
|
|
30586
|
+
if (!round) continue;
|
|
30587
|
+
const status = round.status ?? "";
|
|
30588
|
+
if (status === "completed" || status === "cancelled") continue;
|
|
30589
|
+
const files = round.files_changed ?? round.context?.files_changed ?? [];
|
|
30590
|
+
for (const f of files) {
|
|
30591
|
+
if (f.path) fileSet.add(f.path);
|
|
30592
|
+
}
|
|
30593
|
+
}
|
|
30594
|
+
return [...fileSet];
|
|
30595
|
+
} catch {
|
|
30596
|
+
return [];
|
|
30597
|
+
}
|
|
30598
|
+
}
|
|
30599
|
+
async function runSessionStartCli(_args, deps = {}) {
|
|
30600
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
30601
|
+
const repoInfo = await (deps.resolveRepo ?? resolveRepoInfo)(cwd);
|
|
30602
|
+
if (!repoInfo) {
|
|
30603
|
+
const envelope2 = {
|
|
30604
|
+
status: "ok",
|
|
30605
|
+
session_log_id: null,
|
|
30606
|
+
worktree_id: null,
|
|
30607
|
+
worktree_error_kind: "unhandled",
|
|
30608
|
+
infra_drift_nudge: null,
|
|
30609
|
+
arch_map_nudge: null,
|
|
30610
|
+
lsp_nudges: [],
|
|
30611
|
+
handoff: { fresh: false },
|
|
30612
|
+
infra_files_to_commit: [],
|
|
30613
|
+
owned_checkpoints: [],
|
|
30614
|
+
cross_checkpoints: [],
|
|
30615
|
+
owned_count: 0,
|
|
30616
|
+
total_count: 0,
|
|
30617
|
+
next_action: "trigger_todo",
|
|
30618
|
+
rendered_block: "session start: no .codebyplan/repo.json found \u2014 run `codebyplan setup`",
|
|
30619
|
+
previous_session: null
|
|
30620
|
+
};
|
|
30621
|
+
process.stdout.write(JSON.stringify(envelope2) + "\n");
|
|
30622
|
+
return 0;
|
|
30623
|
+
}
|
|
30624
|
+
const { repoRoot, repoId } = repoInfo;
|
|
30625
|
+
const { worktree_id: worktreeId, error_kind: worktreeErrorKind } = resolveWorktreeJson({ cwd, run: deps.resolveWorktreeRunner });
|
|
30626
|
+
const freshnessGateFn = deps.freshnessGate ?? freshnessGate;
|
|
30627
|
+
let freshnessResult;
|
|
30628
|
+
try {
|
|
30629
|
+
freshnessResult = await freshnessGateFn({
|
|
30630
|
+
cwd,
|
|
30631
|
+
haltOnUpdate: true
|
|
30632
|
+
});
|
|
30633
|
+
} catch {
|
|
30634
|
+
freshnessResult = { result: "skipped", reason: "gate error (fail-safe)" };
|
|
30635
|
+
}
|
|
30636
|
+
if (freshnessResult.result === "updated" && "halt" in freshnessResult && freshnessResult.halt) {
|
|
30637
|
+
const haltMsg = "codebyplan updated. Start a FRESH Claude Code session\n(run /clear or open a new window) so the updated .claude/ takes effect.";
|
|
30638
|
+
const envelope2 = {
|
|
30639
|
+
status: "update_halt",
|
|
30640
|
+
session_log_id: null,
|
|
30641
|
+
worktree_id: worktreeId,
|
|
30642
|
+
worktree_error_kind: worktreeErrorKind,
|
|
30643
|
+
infra_drift_nudge: null,
|
|
30644
|
+
arch_map_nudge: null,
|
|
30645
|
+
lsp_nudges: [],
|
|
30646
|
+
handoff: { fresh: false },
|
|
30647
|
+
infra_files_to_commit: "changed_files" in freshnessResult ? freshnessResult.changed_files ?? [] : [],
|
|
30648
|
+
owned_checkpoints: [],
|
|
30649
|
+
cross_checkpoints: [],
|
|
30650
|
+
owned_count: 0,
|
|
30651
|
+
total_count: 0,
|
|
30652
|
+
next_action: "mcp_update_halt",
|
|
30653
|
+
rendered_block: haltMsg,
|
|
30654
|
+
previous_session: null
|
|
30655
|
+
};
|
|
30656
|
+
process.stdout.write(JSON.stringify(envelope2) + "\n");
|
|
30657
|
+
return 0;
|
|
30658
|
+
}
|
|
30659
|
+
const infraDriftNudgeVal = infraDriftNudge({
|
|
30660
|
+
cwd,
|
|
30661
|
+
run: deps.infraDriftRunner,
|
|
30662
|
+
existsSync: deps.infraDriftExistsSync
|
|
30663
|
+
});
|
|
30664
|
+
const archMapNudgeVal = archMapDriftNudge({
|
|
30665
|
+
cwd,
|
|
30666
|
+
run: deps.archMapDriftRunner,
|
|
30667
|
+
existsSync: deps.archMapDriftExistsSync
|
|
30668
|
+
});
|
|
30669
|
+
const lspNudgesVal = lspNudge({ cwd, run: deps.lspRunner });
|
|
30670
|
+
const runSync2 = deps.runSync ?? defaultRunSync;
|
|
30671
|
+
const readPreviousSession = deps.readPreviousSession ?? ((rr) => readEntityFile(sessionLogPath(rr)));
|
|
30672
|
+
let previousSessionRow = await readPreviousSession(repoRoot);
|
|
30673
|
+
if (!previousSessionRow) {
|
|
30674
|
+
runSync2(cwd);
|
|
30675
|
+
previousSessionRow = await readPreviousSession(repoRoot);
|
|
30676
|
+
}
|
|
30677
|
+
const handoffResult = await probeHandoff({
|
|
30678
|
+
repoRoot,
|
|
30679
|
+
worktreeId,
|
|
30680
|
+
previousSessionRow,
|
|
30681
|
+
readEntity: deps.readEntity ?? (async (filePath) => {
|
|
30682
|
+
return readEntityFile(filePath);
|
|
30683
|
+
})
|
|
30684
|
+
});
|
|
30685
|
+
const updateStateActivateFn = deps.updateStateActivate ?? defaultUpdateStateActivate;
|
|
30686
|
+
await updateStateActivateFn(repoId, repoRoot).catch((err) => {
|
|
30687
|
+
process.stderr.write(
|
|
30688
|
+
`session start: update-state activate threw (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30689
|
+
`
|
|
30690
|
+
);
|
|
30691
|
+
});
|
|
30692
|
+
const createLogFn = deps.createLog ?? defaultCreateLog;
|
|
30693
|
+
const sessionLogId = await createLogFn(repoId, repoRoot, worktreeId).catch(
|
|
30694
|
+
(err) => {
|
|
30695
|
+
process.stderr.write(
|
|
30696
|
+
`session start: create-log threw (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
30697
|
+
`
|
|
30698
|
+
);
|
|
30699
|
+
return null;
|
|
30700
|
+
}
|
|
30701
|
+
);
|
|
30702
|
+
const resolveTaskFiles = deps.resolveTaskFiles ?? resolveTaskFilesFromState;
|
|
30703
|
+
const taskFilesFromState = await resolveTaskFiles(repoRoot);
|
|
30704
|
+
let infraFilesToCommit = [];
|
|
30705
|
+
try {
|
|
30706
|
+
const infraResult = await infraFiles({
|
|
30707
|
+
cwd,
|
|
30708
|
+
run: deps.infraFilesRunner,
|
|
30709
|
+
getTaskFiles: () => Promise.resolve(taskFilesFromState)
|
|
30710
|
+
});
|
|
30711
|
+
infraFilesToCommit = infraResult.infra_files;
|
|
30712
|
+
} catch {
|
|
30713
|
+
infraFilesToCommit = [];
|
|
30714
|
+
}
|
|
30715
|
+
const getCheckpointsFn = deps.getCheckpoints ?? defaultGetCheckpoints;
|
|
30716
|
+
let checkpoints = [];
|
|
30717
|
+
try {
|
|
30718
|
+
checkpoints = await getCheckpointsFn(repoId);
|
|
30719
|
+
} catch {
|
|
30720
|
+
checkpoints = [];
|
|
30721
|
+
}
|
|
30722
|
+
const { owned, cross } = partitionOwnership(checkpoints, worktreeId);
|
|
30723
|
+
const ownedCount = owned.length;
|
|
30724
|
+
const totalCount = owned.length + cross.length;
|
|
30725
|
+
const nextAction = computeNextAction({
|
|
30726
|
+
status: "ok",
|
|
30727
|
+
owned_count: ownedCount,
|
|
30728
|
+
total_count: totalCount,
|
|
30729
|
+
handoff_fresh: handoffResult.fresh,
|
|
30730
|
+
infra_files_count: infraFilesToCommit.length
|
|
30731
|
+
});
|
|
30732
|
+
let previousSession = null;
|
|
30733
|
+
if (previousSessionRow) {
|
|
30734
|
+
previousSession = {
|
|
30735
|
+
title: typeof previousSessionRow["title"] === "string" ? previousSessionRow["title"] : void 0,
|
|
30736
|
+
summary: typeof previousSessionRow["summary"] === "string" ? previousSessionRow["summary"] : void 0,
|
|
30737
|
+
pending: typeof previousSessionRow["pending"] === "string" ? previousSessionRow["pending"] : void 0
|
|
30738
|
+
};
|
|
30739
|
+
}
|
|
30740
|
+
const envelope = {
|
|
30741
|
+
status: "ok",
|
|
30742
|
+
session_log_id: sessionLogId,
|
|
30743
|
+
worktree_id: worktreeId,
|
|
30744
|
+
worktree_error_kind: worktreeErrorKind,
|
|
30745
|
+
infra_drift_nudge: infraDriftNudgeVal,
|
|
30746
|
+
arch_map_nudge: archMapNudgeVal,
|
|
30747
|
+
lsp_nudges: lspNudgesVal,
|
|
30748
|
+
handoff: handoffResult.fresh ? {
|
|
30749
|
+
fresh: true,
|
|
30750
|
+
command: handoffResult.command,
|
|
30751
|
+
context: handoffResult.context,
|
|
30752
|
+
state: handoffResult.state
|
|
30753
|
+
} : { fresh: false },
|
|
30754
|
+
infra_files_to_commit: infraFilesToCommit,
|
|
30755
|
+
owned_checkpoints: owned,
|
|
30756
|
+
cross_checkpoints: cross,
|
|
30757
|
+
owned_count: ownedCount,
|
|
30758
|
+
total_count: totalCount,
|
|
30759
|
+
next_action: nextAction,
|
|
30760
|
+
rendered_block: "",
|
|
30761
|
+
// filled below
|
|
30762
|
+
previous_session: previousSession
|
|
30763
|
+
};
|
|
30764
|
+
envelope.rendered_block = renderBlock(envelope);
|
|
30765
|
+
process.stdout.write(JSON.stringify(envelope) + "\n");
|
|
30766
|
+
return 0;
|
|
30767
|
+
}
|
|
30768
|
+
var init_start = __esm({
|
|
30769
|
+
"src/cli/session/start.ts"() {
|
|
30770
|
+
"use strict";
|
|
30771
|
+
init_session();
|
|
30772
|
+
init_flags();
|
|
30773
|
+
init_state_store();
|
|
30774
|
+
init_state_client();
|
|
30775
|
+
init_urls();
|
|
30776
|
+
init_api();
|
|
30777
|
+
}
|
|
30778
|
+
});
|
|
30779
|
+
|
|
30780
|
+
// src/cli/session/home-ff.ts
|
|
30781
|
+
var home_ff_exports = {};
|
|
30782
|
+
__export(home_ff_exports, {
|
|
30783
|
+
homeFfCli: () => homeFfCli
|
|
30784
|
+
});
|
|
30785
|
+
function homeFfCli(_args, deps = {}) {
|
|
30786
|
+
const result = homeFf(deps);
|
|
30787
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
30788
|
+
return 0;
|
|
30789
|
+
}
|
|
30790
|
+
var init_home_ff = __esm({
|
|
30791
|
+
"src/cli/session/home-ff.ts"() {
|
|
30792
|
+
"use strict";
|
|
30793
|
+
init_session();
|
|
30794
|
+
}
|
|
30795
|
+
});
|
|
30796
|
+
|
|
30797
|
+
// src/cli/session/freshness-gate.ts
|
|
30798
|
+
var freshness_gate_exports = {};
|
|
30799
|
+
__export(freshness_gate_exports, {
|
|
30800
|
+
freshnessGateCli: () => freshnessGateCli
|
|
30801
|
+
});
|
|
30802
|
+
async function freshnessGateCli(args, deps = {}) {
|
|
30803
|
+
const haltOnUpdate = args.includes("--halt-on-update");
|
|
30804
|
+
const result = await freshnessGate({
|
|
30805
|
+
...deps,
|
|
30806
|
+
haltOnUpdate: deps.haltOnUpdate ?? haltOnUpdate
|
|
30807
|
+
});
|
|
30808
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
30809
|
+
return 0;
|
|
30810
|
+
}
|
|
30811
|
+
var init_freshness_gate = __esm({
|
|
30812
|
+
"src/cli/session/freshness-gate.ts"() {
|
|
30813
|
+
"use strict";
|
|
30814
|
+
init_session();
|
|
30815
|
+
}
|
|
30816
|
+
});
|
|
30817
|
+
|
|
30818
|
+
// src/cli/session/infra-files.ts
|
|
30819
|
+
var infra_files_exports = {};
|
|
30820
|
+
__export(infra_files_exports, {
|
|
30821
|
+
infraFilesCli: () => infraFilesCli
|
|
30822
|
+
});
|
|
30823
|
+
async function infraFilesCli(args, deps = {}) {
|
|
30824
|
+
let taskFilesFromFlag = [];
|
|
30825
|
+
const tfIdx = args.indexOf("--task-files");
|
|
30826
|
+
if (tfIdx !== -1 && tfIdx + 1 < args.length) {
|
|
30827
|
+
const raw = args[tfIdx + 1];
|
|
30828
|
+
if (raw && !raw.startsWith("--")) {
|
|
30829
|
+
taskFilesFromFlag = raw.split(",").map((f) => f.trim()).filter(Boolean);
|
|
30830
|
+
}
|
|
30831
|
+
}
|
|
30832
|
+
const result = await infraFiles({
|
|
30833
|
+
...deps,
|
|
30834
|
+
// When the caller passes --task-files, use those as the task file list.
|
|
30835
|
+
// The deps injection wins when explicitly provided (test path).
|
|
30836
|
+
getTaskFiles: deps.getTaskFiles ?? (taskFilesFromFlag.length > 0 ? () => Promise.resolve(taskFilesFromFlag) : () => Promise.resolve([]))
|
|
30837
|
+
});
|
|
30838
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
30839
|
+
return 0;
|
|
30840
|
+
}
|
|
30841
|
+
var init_infra_files = __esm({
|
|
30842
|
+
"src/cli/session/infra-files.ts"() {
|
|
30843
|
+
"use strict";
|
|
30844
|
+
init_session();
|
|
30845
|
+
}
|
|
30846
|
+
});
|
|
30847
|
+
|
|
29581
30848
|
// src/cli/session.ts
|
|
29582
30849
|
var session_exports = {};
|
|
29583
30850
|
__export(session_exports, {
|
|
@@ -29774,11 +31041,27 @@ async function runSessionUpdateState(args) {
|
|
|
29774
31041
|
}
|
|
29775
31042
|
function printSessionHelp() {
|
|
29776
31043
|
process.stdout.write(
|
|
29777
|
-
"\n codebyplan session <subcommand>\n\n Subcommands:\n create-log Create a session log (fields as --key value pairs)\n update-log Update a session log (--id <uuid> required, then --key value pairs)\n update-state Update session state for the current repo (--key value pairs)\n\n"
|
|
31044
|
+
"\n codebyplan session <subcommand>\n\n Subcommands:\n start Run the session-start orchestrator; emits one JSON envelope on stdout\n home-ff Fast-forward the home branch to HEAD; emits { result, reason? } JSON\n freshness-gate Check package version freshness [--halt-on-update]; emits { result, ... } JSON\n infra-files Compute the infra-file set for the active session [--task-files <csv>] [--json]\n create-log Create a session log (fields as --key value pairs)\n update-log Update a session log (--id <uuid> required, then --key value pairs)\n update-state Update session state for the current repo (--key value pairs)\n\n"
|
|
29778
31045
|
);
|
|
29779
31046
|
}
|
|
29780
31047
|
async function runSessionCommand(args) {
|
|
29781
31048
|
const subcommand = args[0];
|
|
31049
|
+
if (subcommand === "start") {
|
|
31050
|
+
const { runSessionStartCli: runSessionStartCli2 } = await Promise.resolve().then(() => (init_start(), start_exports));
|
|
31051
|
+
process.exit(await runSessionStartCli2(args.slice(1)));
|
|
31052
|
+
}
|
|
31053
|
+
if (subcommand === "home-ff") {
|
|
31054
|
+
const { homeFfCli: homeFfCli2 } = await Promise.resolve().then(() => (init_home_ff(), home_ff_exports));
|
|
31055
|
+
process.exit(homeFfCli2(args.slice(1)));
|
|
31056
|
+
}
|
|
31057
|
+
if (subcommand === "freshness-gate") {
|
|
31058
|
+
const { freshnessGateCli: freshnessGateCli2 } = await Promise.resolve().then(() => (init_freshness_gate(), freshness_gate_exports));
|
|
31059
|
+
process.exit(await freshnessGateCli2(args.slice(1)));
|
|
31060
|
+
}
|
|
31061
|
+
if (subcommand === "infra-files") {
|
|
31062
|
+
const { infraFilesCli: infraFilesCli2 } = await Promise.resolve().then(() => (init_infra_files(), infra_files_exports));
|
|
31063
|
+
process.exit(await infraFilesCli2(args.slice(1)));
|
|
31064
|
+
}
|
|
29782
31065
|
if (subcommand === "create-log") {
|
|
29783
31066
|
await runSessionCreateLog(args.slice(1));
|
|
29784
31067
|
return;
|
|
@@ -29806,7 +31089,7 @@ Run 'codebyplan session help' for usage.
|
|
|
29806
31089
|
}
|
|
29807
31090
|
process.exit(1);
|
|
29808
31091
|
}
|
|
29809
|
-
var
|
|
31092
|
+
var init_session2 = __esm({
|
|
29810
31093
|
"src/cli/session.ts"() {
|
|
29811
31094
|
"use strict";
|
|
29812
31095
|
init_flags();
|
|
@@ -29818,7 +31101,7 @@ var init_session = __esm({
|
|
|
29818
31101
|
|
|
29819
31102
|
// src/lib/migrate-branch-model.ts
|
|
29820
31103
|
import { readFile as readFile18, writeFile as writeFile15 } from "node:fs/promises";
|
|
29821
|
-
import { join as
|
|
31104
|
+
import { join as join24 } from "node:path";
|
|
29822
31105
|
import { execSync as execSync4 } from "node:child_process";
|
|
29823
31106
|
function assertValidBranchName(branch) {
|
|
29824
31107
|
if (!/^[a-zA-Z0-9/_.-]+$/.test(branch)) {
|
|
@@ -29827,7 +31110,7 @@ function assertValidBranchName(branch) {
|
|
|
29827
31110
|
);
|
|
29828
31111
|
}
|
|
29829
31112
|
}
|
|
29830
|
-
async function
|
|
31113
|
+
async function readJsonFile3(filePath) {
|
|
29831
31114
|
const raw = await readFile18(filePath, "utf-8");
|
|
29832
31115
|
const parsed = JSON.parse(raw);
|
|
29833
31116
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
@@ -29897,17 +31180,17 @@ async function runBranchMigration(opts) {
|
|
|
29897
31180
|
if (found) {
|
|
29898
31181
|
if (found.path.endsWith("/repo.json")) {
|
|
29899
31182
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
29900
|
-
configPath =
|
|
31183
|
+
configPath = join24(dir, "git.json");
|
|
29901
31184
|
} else {
|
|
29902
31185
|
configPath = found.path;
|
|
29903
31186
|
}
|
|
29904
31187
|
} else {
|
|
29905
|
-
configPath =
|
|
31188
|
+
configPath = join24(cwd, ".codebyplan", "git.json");
|
|
29906
31189
|
}
|
|
29907
31190
|
let fileRaw;
|
|
29908
31191
|
let fileParsed;
|
|
29909
31192
|
try {
|
|
29910
|
-
const result = await
|
|
31193
|
+
const result = await readJsonFile3(configPath);
|
|
29911
31194
|
fileRaw = result.raw;
|
|
29912
31195
|
fileParsed = result.parsed;
|
|
29913
31196
|
} catch (err) {
|
|
@@ -29995,323 +31278,10 @@ var init_migrate_branch_model = __esm({
|
|
|
29995
31278
|
}
|
|
29996
31279
|
});
|
|
29997
31280
|
|
|
29998
|
-
// src/lib/supabase.ts
|
|
29999
|
-
import * as fs5 from "node:fs";
|
|
30000
|
-
import * as path7 from "node:path";
|
|
30001
|
-
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
30002
|
-
function defaultRun(cmd, args) {
|
|
30003
|
-
const result = spawnSync6(cmd, args, {
|
|
30004
|
-
encoding: "utf-8",
|
|
30005
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
30006
|
-
});
|
|
30007
|
-
if (result.error) throw result.error;
|
|
30008
|
-
return (result.stdout ?? "").toString();
|
|
30009
|
-
}
|
|
30010
|
-
function readJsonFile3(filePath) {
|
|
30011
|
-
try {
|
|
30012
|
-
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
30013
|
-
const parsed = JSON.parse(raw);
|
|
30014
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
30015
|
-
return parsed;
|
|
30016
|
-
}
|
|
30017
|
-
return null;
|
|
30018
|
-
} catch {
|
|
30019
|
-
return null;
|
|
30020
|
-
}
|
|
30021
|
-
}
|
|
30022
|
-
function getSupabaseSection(obj) {
|
|
30023
|
-
const tryPath = (root) => {
|
|
30024
|
-
const surfaces = root["surfaces"];
|
|
30025
|
-
if (typeof surfaces !== "object" || surfaces === null || Array.isArray(surfaces))
|
|
30026
|
-
return null;
|
|
30027
|
-
const sb = surfaces["supabase"];
|
|
30028
|
-
if (typeof sb === "object" && sb !== null && !Array.isArray(sb)) {
|
|
30029
|
-
return sb;
|
|
30030
|
-
}
|
|
30031
|
-
return null;
|
|
30032
|
-
};
|
|
30033
|
-
const shipment = obj["shipment"];
|
|
30034
|
-
if (typeof shipment === "object" && shipment !== null && !Array.isArray(shipment)) {
|
|
30035
|
-
const found = tryPath(shipment);
|
|
30036
|
-
if (found) return found;
|
|
30037
|
-
}
|
|
30038
|
-
return tryPath(obj);
|
|
30039
|
-
}
|
|
30040
|
-
function globToRegex(pattern) {
|
|
30041
|
-
const special = ".+^${}()|[]\\";
|
|
30042
|
-
let r = "";
|
|
30043
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
30044
|
-
const ch = pattern[i] ?? "";
|
|
30045
|
-
if (ch === "*") {
|
|
30046
|
-
if (pattern[i + 1] === "*") {
|
|
30047
|
-
r += ".*";
|
|
30048
|
-
i++;
|
|
30049
|
-
} else {
|
|
30050
|
-
r += "[^/]*";
|
|
30051
|
-
}
|
|
30052
|
-
} else if (ch === "?") {
|
|
30053
|
-
r += "[^/]";
|
|
30054
|
-
} else if (special.includes(ch)) {
|
|
30055
|
-
r += "\\" + ch;
|
|
30056
|
-
} else {
|
|
30057
|
-
r += ch;
|
|
30058
|
-
}
|
|
30059
|
-
}
|
|
30060
|
-
return new RegExp(`^${r}$`);
|
|
30061
|
-
}
|
|
30062
|
-
function dateToStamp(d) {
|
|
30063
|
-
const pad2 = (n) => String(n).padStart(2, "0");
|
|
30064
|
-
return String(d.getUTCFullYear()) + pad2(d.getUTCMonth() + 1) + pad2(d.getUTCDate()) + pad2(d.getUTCHours()) + pad2(d.getUTCMinutes()) + pad2(d.getUTCSeconds());
|
|
30065
|
-
}
|
|
30066
|
-
function extractStampToken(filename) {
|
|
30067
|
-
if (!filename.endsWith(".sql")) return null;
|
|
30068
|
-
const base = filename.slice(0, -4);
|
|
30069
|
-
const parts = base.split("_");
|
|
30070
|
-
const first = parts[0];
|
|
30071
|
-
if (!first || !/^\d{14}$/.test(first)) return null;
|
|
30072
|
-
const second = parts[1];
|
|
30073
|
-
if (second && /^\d{2}$/.test(second)) {
|
|
30074
|
-
return `${first}_${second}`;
|
|
30075
|
-
}
|
|
30076
|
-
return first;
|
|
30077
|
-
}
|
|
30078
|
-
function readShipmentConfig(cwd) {
|
|
30079
|
-
const dir = cwd ?? process.cwd();
|
|
30080
|
-
const obj = readJsonFile3(path7.join(dir, ".codebyplan", "shipment.json"));
|
|
30081
|
-
if (!obj) return { parentRef: null, previewBranches: [] };
|
|
30082
|
-
const section = getSupabaseSection(obj);
|
|
30083
|
-
if (!section) return { parentRef: null, previewBranches: [] };
|
|
30084
|
-
const parentRef = typeof section["project_ref"] === "string" ? section["project_ref"] : null;
|
|
30085
|
-
const previewBranches = [];
|
|
30086
|
-
const rawBranches = section["preview_branches"];
|
|
30087
|
-
if (Array.isArray(rawBranches)) {
|
|
30088
|
-
for (const b of rawBranches) {
|
|
30089
|
-
if (typeof b !== "object" || b === null || Array.isArray(b)) continue;
|
|
30090
|
-
const entry = b;
|
|
30091
|
-
if (typeof entry["branch"] !== "string" || typeof entry["project_ref"] !== "string")
|
|
30092
|
-
continue;
|
|
30093
|
-
previewBranches.push({
|
|
30094
|
-
branch: entry["branch"],
|
|
30095
|
-
project_ref: entry["project_ref"],
|
|
30096
|
-
created_at: typeof entry["created_at"] === "string" ? entry["created_at"] : void 0
|
|
30097
|
-
});
|
|
30098
|
-
}
|
|
30099
|
-
}
|
|
30100
|
-
return { parentRef, previewBranches };
|
|
30101
|
-
}
|
|
30102
|
-
function readGitConfig(cwd) {
|
|
30103
|
-
const dir = cwd ?? process.cwd();
|
|
30104
|
-
const obj = readJsonFile3(path7.join(dir, ".codebyplan", "git.json"));
|
|
30105
|
-
if (!obj) return { ...GIT_DEFAULTS };
|
|
30106
|
-
const bc = obj["branch_config"];
|
|
30107
|
-
if (typeof bc !== "object" || bc === null || Array.isArray(bc)) {
|
|
30108
|
-
return { ...GIT_DEFAULTS };
|
|
30109
|
-
}
|
|
30110
|
-
const bcObj = bc;
|
|
30111
|
-
const production = typeof bcObj["production"] === "string" && bcObj["production"] ? bcObj["production"] : "main";
|
|
30112
|
-
const protectedArr = [];
|
|
30113
|
-
const rawProtected = bcObj["protected"];
|
|
30114
|
-
if (Array.isArray(rawProtected)) {
|
|
30115
|
-
for (const p of rawProtected) {
|
|
30116
|
-
if (typeof p === "string" && p) protectedArr.push(p);
|
|
30117
|
-
}
|
|
30118
|
-
}
|
|
30119
|
-
if (protectedArr.length === 0) protectedArr.push(production);
|
|
30120
|
-
const integration = typeof bcObj["integration"] === "string" && bcObj["integration"] ? bcObj["integration"] : null;
|
|
30121
|
-
return { production, protected: protectedArr, integration };
|
|
30122
|
-
}
|
|
30123
|
-
function readDbPaths(cwd) {
|
|
30124
|
-
const dir = cwd ?? process.cwd();
|
|
30125
|
-
const obj = readJsonFile3(path7.join(dir, ".codebyplan", "shipment.json"));
|
|
30126
|
-
if (!obj) return [...DEFAULT_DB_PATHS];
|
|
30127
|
-
const section = getSupabaseSection(obj);
|
|
30128
|
-
if (!section) return [...DEFAULT_DB_PATHS];
|
|
30129
|
-
const rawPaths = section["db_paths"];
|
|
30130
|
-
if (!Array.isArray(rawPaths) || rawPaths.length === 0)
|
|
30131
|
-
return [...DEFAULT_DB_PATHS];
|
|
30132
|
-
const paths = [];
|
|
30133
|
-
for (const p of rawPaths) {
|
|
30134
|
-
if (typeof p === "string" && p) paths.push(p);
|
|
30135
|
-
}
|
|
30136
|
-
return paths.length > 0 ? paths : [...DEFAULT_DB_PATHS];
|
|
30137
|
-
}
|
|
30138
|
-
function detectDbChanged(opts = {}) {
|
|
30139
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
30140
|
-
const run = opts.run ?? defaultRun;
|
|
30141
|
-
const base = opts.base ?? readGitConfig(cwd).production;
|
|
30142
|
-
const dbPaths = opts.dbPaths ?? readDbPaths(cwd);
|
|
30143
|
-
if (dbPaths.length === 0) return false;
|
|
30144
|
-
const regexes = dbPaths.map(globToRegex);
|
|
30145
|
-
let output;
|
|
30146
|
-
try {
|
|
30147
|
-
output = run("git", ["diff", "--name-only", `origin/${base}...HEAD`]);
|
|
30148
|
-
} catch {
|
|
30149
|
-
return false;
|
|
30150
|
-
}
|
|
30151
|
-
const changedFiles = output.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
30152
|
-
return changedFiles.some((file) => regexes.some((re) => re.test(file)));
|
|
30153
|
-
}
|
|
30154
|
-
function defaultListDir(dir) {
|
|
30155
|
-
try {
|
|
30156
|
-
return fs5.readdirSync(dir);
|
|
30157
|
-
} catch {
|
|
30158
|
-
return [];
|
|
30159
|
-
}
|
|
30160
|
-
}
|
|
30161
|
-
function generateMonotonicTimestamp(opts = {}) {
|
|
30162
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
30163
|
-
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
30164
|
-
const listDir = opts.listDir ?? defaultListDir;
|
|
30165
|
-
const migrationsDir = path7.join(cwd, "supabase", "migrations");
|
|
30166
|
-
const files = listDir(migrationsDir);
|
|
30167
|
-
const existingStamps = /* @__PURE__ */ new Set();
|
|
30168
|
-
for (const file of files) {
|
|
30169
|
-
const token = extractStampToken(file);
|
|
30170
|
-
if (token) existingStamps.add(token);
|
|
30171
|
-
}
|
|
30172
|
-
let maxStamp = "";
|
|
30173
|
-
for (const s of existingStamps) {
|
|
30174
|
-
if (s > maxStamp) maxStamp = s;
|
|
30175
|
-
}
|
|
30176
|
-
const computed = dateToStamp(now);
|
|
30177
|
-
if (computed > maxStamp && !existingStamps.has(computed)) {
|
|
30178
|
-
return computed;
|
|
30179
|
-
}
|
|
30180
|
-
const collisionBase14 = computed > maxStamp ? computed : maxStamp.slice(0, 14);
|
|
30181
|
-
for (let i = 1; i <= 99; i++) {
|
|
30182
|
-
const suffix = String(i).padStart(2, "0");
|
|
30183
|
-
const candidate = `${collisionBase14}_${suffix}`;
|
|
30184
|
-
if (!existingStamps.has(candidate) && candidate > maxStamp) {
|
|
30185
|
-
return candidate;
|
|
30186
|
-
}
|
|
30187
|
-
}
|
|
30188
|
-
return `${collisionBase14}_99`;
|
|
30189
|
-
}
|
|
30190
|
-
async function pollGhPreviewCheck(opts = {}) {
|
|
30191
|
-
const run = opts.run ?? defaultRun;
|
|
30192
|
-
const sleep3 = opts.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
30193
|
-
const maxPolls = opts.maxPolls ?? 20;
|
|
30194
|
-
const intervalMs = opts.intervalMs ?? 15e3;
|
|
30195
|
-
if (!opts.prNumber) {
|
|
30196
|
-
return {
|
|
30197
|
-
status: "pending_pr",
|
|
30198
|
-
reason: "No PR number \u2014 branch has no open pull request yet."
|
|
30199
|
-
};
|
|
30200
|
-
}
|
|
30201
|
-
try {
|
|
30202
|
-
run("gh", ["--version"]);
|
|
30203
|
-
} catch {
|
|
30204
|
-
return {
|
|
30205
|
-
status: "blocked",
|
|
30206
|
-
reason: "gh CLI not available"
|
|
30207
|
-
};
|
|
30208
|
-
}
|
|
30209
|
-
const prNumber = opts.prNumber;
|
|
30210
|
-
for (let poll = 0; poll < maxPolls; poll++) {
|
|
30211
|
-
if (poll > 0) {
|
|
30212
|
-
await sleep3(intervalMs);
|
|
30213
|
-
}
|
|
30214
|
-
let checksOutput;
|
|
30215
|
-
try {
|
|
30216
|
-
try {
|
|
30217
|
-
checksOutput = run("gh", [
|
|
30218
|
-
"pr",
|
|
30219
|
-
"checks",
|
|
30220
|
-
prNumber,
|
|
30221
|
-
"--json",
|
|
30222
|
-
"name,bucket,state"
|
|
30223
|
-
]);
|
|
30224
|
-
} catch {
|
|
30225
|
-
checksOutput = run("gh", [
|
|
30226
|
-
"pr",
|
|
30227
|
-
"checks",
|
|
30228
|
-
prNumber,
|
|
30229
|
-
"--json",
|
|
30230
|
-
"name,state"
|
|
30231
|
-
]);
|
|
30232
|
-
}
|
|
30233
|
-
} catch {
|
|
30234
|
-
if (poll === maxPolls - 1) {
|
|
30235
|
-
return {
|
|
30236
|
-
status: "blocked",
|
|
30237
|
-
reason: `gh pr checks failed after ${maxPolls} polls`
|
|
30238
|
-
};
|
|
30239
|
-
}
|
|
30240
|
-
continue;
|
|
30241
|
-
}
|
|
30242
|
-
let checks;
|
|
30243
|
-
try {
|
|
30244
|
-
const parsed = JSON.parse(checksOutput);
|
|
30245
|
-
checks = Array.isArray(parsed) ? parsed : [];
|
|
30246
|
-
} catch {
|
|
30247
|
-
checks = [];
|
|
30248
|
-
}
|
|
30249
|
-
const supabaseCheck = checks.find(
|
|
30250
|
-
(c) => typeof c["name"] === "string" && c["name"].toLowerCase().includes("supabase preview")
|
|
30251
|
-
);
|
|
30252
|
-
if (!supabaseCheck) {
|
|
30253
|
-
continue;
|
|
30254
|
-
}
|
|
30255
|
-
const bucket = typeof supabaseCheck["bucket"] === "string" ? supabaseCheck["bucket"].toLowerCase() : null;
|
|
30256
|
-
const state = typeof supabaseCheck["state"] === "string" ? supabaseCheck["state"].toLowerCase() : null;
|
|
30257
|
-
if (bucket === "pass") {
|
|
30258
|
-
return { status: "passed", reason: "Supabase Preview check passed." };
|
|
30259
|
-
}
|
|
30260
|
-
if (bucket === "skipping") {
|
|
30261
|
-
return {
|
|
30262
|
-
status: "skipped",
|
|
30263
|
-
reason: "Supabase Preview check skipped at CI."
|
|
30264
|
-
};
|
|
30265
|
-
}
|
|
30266
|
-
if (bucket === "fail" || bucket === "cancel") {
|
|
30267
|
-
return {
|
|
30268
|
-
status: "blocked",
|
|
30269
|
-
reason: `Supabase Preview check ${bucket}ed.`
|
|
30270
|
-
};
|
|
30271
|
-
}
|
|
30272
|
-
if (state === "success") {
|
|
30273
|
-
return { status: "passed", reason: "Supabase Preview check passed." };
|
|
30274
|
-
}
|
|
30275
|
-
if (state === "skipped" || state === "neutral") {
|
|
30276
|
-
return {
|
|
30277
|
-
status: "skipped",
|
|
30278
|
-
reason: "Supabase Preview check skipped at CI."
|
|
30279
|
-
};
|
|
30280
|
-
}
|
|
30281
|
-
if (state === "failure" || state === "cancelled" || state === "error" || state === "timed_out" || state === "stale" || state === "action_required") {
|
|
30282
|
-
return {
|
|
30283
|
-
status: "blocked",
|
|
30284
|
-
reason: `Supabase Preview check ${state}.`
|
|
30285
|
-
};
|
|
30286
|
-
}
|
|
30287
|
-
}
|
|
30288
|
-
const minutesStr = Math.round(maxPolls * intervalMs / 6e4);
|
|
30289
|
-
return {
|
|
30290
|
-
status: "blocked",
|
|
30291
|
-
reason: `Supabase Preview check still pending after ${minutesStr} min (${maxPolls} polls)`
|
|
30292
|
-
};
|
|
30293
|
-
}
|
|
30294
|
-
var GIT_DEFAULTS, DEFAULT_DB_PATHS;
|
|
30295
|
-
var init_supabase = __esm({
|
|
30296
|
-
"src/lib/supabase.ts"() {
|
|
30297
|
-
"use strict";
|
|
30298
|
-
GIT_DEFAULTS = {
|
|
30299
|
-
production: "main",
|
|
30300
|
-
protected: ["main"],
|
|
30301
|
-
integration: null
|
|
30302
|
-
};
|
|
30303
|
-
DEFAULT_DB_PATHS = [
|
|
30304
|
-
"supabase/**",
|
|
30305
|
-
"apps/backend/**",
|
|
30306
|
-
"packages/**/db/**"
|
|
30307
|
-
];
|
|
30308
|
-
}
|
|
30309
|
-
});
|
|
30310
|
-
|
|
30311
31281
|
// src/lib/branch-checkout.ts
|
|
30312
|
-
import { spawnSync as
|
|
30313
|
-
function
|
|
30314
|
-
const result =
|
|
31282
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
31283
|
+
function defaultRun3(cmd, args, cwd) {
|
|
31284
|
+
const result = spawnSync9(cmd, args, {
|
|
30315
31285
|
cwd,
|
|
30316
31286
|
encoding: "utf-8",
|
|
30317
31287
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30325,7 +31295,7 @@ function defaultRun2(cmd, args, cwd) {
|
|
|
30325
31295
|
function makeRun(cwd, userRun) {
|
|
30326
31296
|
if (userRun) return userRun;
|
|
30327
31297
|
return (cmd, args) => {
|
|
30328
|
-
const r =
|
|
31298
|
+
const r = defaultRun3(cmd, args, cwd);
|
|
30329
31299
|
if (r.status !== 0) {
|
|
30330
31300
|
const msg = r.stderr.trim();
|
|
30331
31301
|
throw new Error(
|
|
@@ -30346,7 +31316,7 @@ function makeRunRaw(cwd, userRun) {
|
|
|
30346
31316
|
}
|
|
30347
31317
|
};
|
|
30348
31318
|
}
|
|
30349
|
-
return (cmd, args) =>
|
|
31319
|
+
return (cmd, args) => defaultRun3(cmd, args, cwd);
|
|
30350
31320
|
}
|
|
30351
31321
|
function checkoutBranch(opts) {
|
|
30352
31322
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -30562,8 +31532,8 @@ var init_branch = __esm({
|
|
|
30562
31532
|
|
|
30563
31533
|
// src/lib/bump.ts
|
|
30564
31534
|
import { readFile as readFile19, writeFile as writeFile16, access as access5, readdir as readdir4 } from "node:fs/promises";
|
|
30565
|
-
import { join as
|
|
30566
|
-
import { spawnSync as
|
|
31535
|
+
import { join as join25, relative as relative5, resolve as resolve3 } from "node:path";
|
|
31536
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
30567
31537
|
function parsePnpmWorkspaceGlobs(raw) {
|
|
30568
31538
|
const lines = raw.split("\n");
|
|
30569
31539
|
const globs = [];
|
|
@@ -30592,18 +31562,18 @@ async function expandGlob(cwd, glob) {
|
|
|
30592
31562
|
if (parts.length !== 2 || parts[1] !== "*") {
|
|
30593
31563
|
return [];
|
|
30594
31564
|
}
|
|
30595
|
-
const parentDir =
|
|
31565
|
+
const parentDir = join25(cwd, parts[0]);
|
|
30596
31566
|
let dirs;
|
|
30597
31567
|
try {
|
|
30598
31568
|
const entries = await readdir4(parentDir, { withFileTypes: true });
|
|
30599
|
-
dirs = entries.filter((e) => e.isDirectory()).map((e) =>
|
|
31569
|
+
dirs = entries.filter((e) => e.isDirectory()).map((e) => join25(parentDir, e.name));
|
|
30600
31570
|
} catch {
|
|
30601
31571
|
return [];
|
|
30602
31572
|
}
|
|
30603
31573
|
const results = [];
|
|
30604
31574
|
for (const dir of dirs) {
|
|
30605
31575
|
try {
|
|
30606
|
-
await access5(
|
|
31576
|
+
await access5(join25(dir, "package.json"));
|
|
30607
31577
|
results.push(dir);
|
|
30608
31578
|
} catch {
|
|
30609
31579
|
}
|
|
@@ -30614,7 +31584,7 @@ async function buildPackageMap(cwd) {
|
|
|
30614
31584
|
const map = /* @__PURE__ */ new Map();
|
|
30615
31585
|
let globs = [];
|
|
30616
31586
|
try {
|
|
30617
|
-
const raw = await readFile19(
|
|
31587
|
+
const raw = await readFile19(join25(cwd, "pnpm-workspace.yaml"), "utf-8");
|
|
30618
31588
|
globs = parsePnpmWorkspaceGlobs(raw);
|
|
30619
31589
|
} catch {
|
|
30620
31590
|
}
|
|
@@ -30622,7 +31592,7 @@ async function buildPackageMap(cwd) {
|
|
|
30622
31592
|
const dirs = await expandGlob(cwd, glob);
|
|
30623
31593
|
for (const dir of dirs) {
|
|
30624
31594
|
try {
|
|
30625
|
-
const pkgRaw = await readFile19(
|
|
31595
|
+
const pkgRaw = await readFile19(join25(dir, "package.json"), "utf-8");
|
|
30626
31596
|
const pkg = JSON.parse(pkgRaw);
|
|
30627
31597
|
const name = pkg.name ?? relative5(cwd, dir);
|
|
30628
31598
|
map.set(dir, { name, dir });
|
|
@@ -30700,7 +31670,7 @@ function compareSemver(a, b) {
|
|
|
30700
31670
|
return 0;
|
|
30701
31671
|
}
|
|
30702
31672
|
function gitShowFile(cwd, ref, relPath) {
|
|
30703
|
-
const result =
|
|
31673
|
+
const result = spawnSync10("git", ["show", `${ref}:${relPath}`], {
|
|
30704
31674
|
cwd,
|
|
30705
31675
|
encoding: "utf-8",
|
|
30706
31676
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -30765,7 +31735,7 @@ async function runBump(opts) {
|
|
|
30765
31735
|
const prereleaseId = opts?.prereleaseId;
|
|
30766
31736
|
const baseBranch = await readBaseBranch(cwd);
|
|
30767
31737
|
const baseRef = resolveBaseRef(cwd, baseBranch);
|
|
30768
|
-
const diffResult =
|
|
31738
|
+
const diffResult = spawnSync10(
|
|
30769
31739
|
"git",
|
|
30770
31740
|
["diff", "--name-only", `${baseRef}...HEAD`],
|
|
30771
31741
|
{
|
|
@@ -30781,7 +31751,7 @@ async function runBump(opts) {
|
|
|
30781
31751
|
const changedFiles = (diffResult.stdout ?? "").trim().split("\n").filter(Boolean).map((f) => resolve3(cwd, f));
|
|
30782
31752
|
const packageMap = await buildPackageMap(cwd);
|
|
30783
31753
|
const packageDirs = Array.from(packageMap.keys());
|
|
30784
|
-
const rootPkgPath =
|
|
31754
|
+
const rootPkgPath = join25(cwd, "package.json");
|
|
30785
31755
|
const changedPackageDirs = /* @__PURE__ */ new Set();
|
|
30786
31756
|
for (const absFile of changedFiles) {
|
|
30787
31757
|
const owner = findOwningPackage(absFile, packageDirs);
|
|
@@ -30792,19 +31762,19 @@ async function runBump(opts) {
|
|
|
30792
31762
|
const entries = [];
|
|
30793
31763
|
for (const pkgDir of changedPackageDirs) {
|
|
30794
31764
|
const pkgInfo = packageMap.get(pkgDir);
|
|
30795
|
-
const pkgJsonPath =
|
|
31765
|
+
const pkgJsonPath = join25(pkgDir, "package.json");
|
|
30796
31766
|
if (pkgJsonPath === rootPkgPath) continue;
|
|
30797
31767
|
const versionFileCandidates = [
|
|
30798
31768
|
{ abs: pkgJsonPath, rel: relative5(cwd, pkgJsonPath).replace(/\\/g, "/") }
|
|
30799
31769
|
];
|
|
30800
|
-
const tauriConfPath =
|
|
31770
|
+
const tauriConfPath = join25(pkgDir, "src-tauri", "tauri.conf.json");
|
|
30801
31771
|
const tauriRelPath = relative5(cwd, tauriConfPath).replace(/\\/g, "/");
|
|
30802
31772
|
try {
|
|
30803
31773
|
await access5(tauriConfPath);
|
|
30804
31774
|
versionFileCandidates.push({ abs: tauriConfPath, rel: tauriRelPath });
|
|
30805
31775
|
} catch {
|
|
30806
31776
|
}
|
|
30807
|
-
const appJsonPath =
|
|
31777
|
+
const appJsonPath = join25(pkgDir, "app.json");
|
|
30808
31778
|
const appJsonRelPath = relative5(cwd, appJsonPath).replace(/\\/g, "/");
|
|
30809
31779
|
try {
|
|
30810
31780
|
await access5(appJsonPath);
|
|
@@ -30876,7 +31846,7 @@ async function runBump(opts) {
|
|
|
30876
31846
|
}
|
|
30877
31847
|
updatedVersionFiles.push(rel);
|
|
30878
31848
|
}
|
|
30879
|
-
const changelogPath =
|
|
31849
|
+
const changelogPath = join25(pkgDir, "CHANGELOG.md");
|
|
30880
31850
|
const changelogUpdated = await prependChangelog(
|
|
30881
31851
|
changelogPath,
|
|
30882
31852
|
pkgInfo.name,
|
|
@@ -30986,7 +31956,7 @@ var init_bump2 = __esm({
|
|
|
30986
31956
|
});
|
|
30987
31957
|
|
|
30988
31958
|
// src/lib/ship.ts
|
|
30989
|
-
import { execSync as execSync5, spawnSync as
|
|
31959
|
+
import { execSync as execSync5, spawnSync as spawnSync11 } from "node:child_process";
|
|
30990
31960
|
import { relative as relative6 } from "node:path";
|
|
30991
31961
|
function assertValidBranchName2(branch, label) {
|
|
30992
31962
|
if (!/^[a-zA-Z0-9/_.-]+$/.test(branch)) {
|
|
@@ -31018,7 +31988,7 @@ async function pollChecks(feat, timeoutSeconds, cwd, _sleepMs = (ms) => new Prom
|
|
|
31018
31988
|
let totalGhErrors = 0;
|
|
31019
31989
|
let iteration = 0;
|
|
31020
31990
|
while (Date.now() < deadline) {
|
|
31021
|
-
const ghResult =
|
|
31991
|
+
const ghResult = spawnSync11(
|
|
31022
31992
|
"gh",
|
|
31023
31993
|
["pr", "checks", feat, "--json", "name,state,bucket"],
|
|
31024
31994
|
{
|
|
@@ -31169,7 +32139,7 @@ ${statusOut.trim()}`
|
|
|
31169
32139
|
...e.changelogUpdated ? [relative6(cwd, e.packageDir).replace(/\\/g, "/") + "/CHANGELOG.md"] : []
|
|
31170
32140
|
]);
|
|
31171
32141
|
if (toStage.length > 0) {
|
|
31172
|
-
const addResult =
|
|
32142
|
+
const addResult = spawnSync11("git", ["add", "--", ...toStage], {
|
|
31173
32143
|
cwd,
|
|
31174
32144
|
encoding: "utf-8",
|
|
31175
32145
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -31179,13 +32149,13 @@ ${statusOut.trim()}`
|
|
|
31179
32149
|
`Failed to stage bump files: ${addResult.stderr?.trim() ?? addResult.error?.message}`
|
|
31180
32150
|
);
|
|
31181
32151
|
}
|
|
31182
|
-
const commitResult =
|
|
32152
|
+
const commitResult = spawnSync11(
|
|
31183
32153
|
"git",
|
|
31184
32154
|
["commit", "-m", "chore(release): bump versions"],
|
|
31185
32155
|
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
31186
32156
|
);
|
|
31187
32157
|
if (commitResult.status !== 0 || commitResult.error) {
|
|
31188
|
-
|
|
32158
|
+
spawnSync11(
|
|
31189
32159
|
"git",
|
|
31190
32160
|
["restore", "--staged", "--worktree", "--", ...toStage],
|
|
31191
32161
|
{
|
|
@@ -31230,7 +32200,7 @@ ${statusOut.trim()}`
|
|
|
31230
32200
|
} else {
|
|
31231
32201
|
createArgs.push("--body", defaultPrBody(feat, base));
|
|
31232
32202
|
}
|
|
31233
|
-
const createResult =
|
|
32203
|
+
const createResult = spawnSync11("gh", createArgs, {
|
|
31234
32204
|
cwd,
|
|
31235
32205
|
encoding: "utf-8",
|
|
31236
32206
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -31261,7 +32231,7 @@ ${statusOut.trim()}`
|
|
|
31261
32231
|
});
|
|
31262
32232
|
let mergeCommit = null;
|
|
31263
32233
|
try {
|
|
31264
|
-
const prViewResult =
|
|
32234
|
+
const prViewResult = spawnSync11(
|
|
31265
32235
|
"gh",
|
|
31266
32236
|
["pr", "view", feat, "--json", "state,mergeCommit"],
|
|
31267
32237
|
{
|
|
@@ -31419,14 +32389,14 @@ var init_ship2 = __esm({
|
|
|
31419
32389
|
|
|
31420
32390
|
// src/lib/scaffold-publish-workflow.ts
|
|
31421
32391
|
import * as fs6 from "node:fs";
|
|
31422
|
-
import * as
|
|
32392
|
+
import * as path9 from "node:path";
|
|
31423
32393
|
async function runScaffoldPublishWorkflow(opts) {
|
|
31424
32394
|
await Promise.resolve();
|
|
31425
32395
|
const dryRun = opts?.dryRun ?? false;
|
|
31426
32396
|
const force = opts?.force ?? false;
|
|
31427
|
-
const projectDir =
|
|
32397
|
+
const projectDir = path9.resolve(opts?.projectDir ?? process.cwd());
|
|
31428
32398
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
31429
|
-
const templatePath =
|
|
32399
|
+
const templatePath = path9.join(
|
|
31430
32400
|
templatesDir,
|
|
31431
32401
|
"github-workflows",
|
|
31432
32402
|
"publish.yml"
|
|
@@ -31437,7 +32407,7 @@ async function runScaffoldPublishWorkflow(opts) {
|
|
|
31437
32407
|
);
|
|
31438
32408
|
}
|
|
31439
32409
|
const templateContent = fs6.readFileSync(templatePath, "utf-8");
|
|
31440
|
-
const targetPath =
|
|
32410
|
+
const targetPath = path9.join(
|
|
31441
32411
|
projectDir,
|
|
31442
32412
|
".github",
|
|
31443
32413
|
"workflows",
|
|
@@ -31461,7 +32431,7 @@ async function runScaffoldPublishWorkflow(opts) {
|
|
|
31461
32431
|
);
|
|
31462
32432
|
}
|
|
31463
32433
|
}
|
|
31464
|
-
const targetDir =
|
|
32434
|
+
const targetDir = path9.dirname(targetPath);
|
|
31465
32435
|
fs6.mkdirSync(targetDir, { recursive: true });
|
|
31466
32436
|
fs6.writeFileSync(targetPath, templateContent, "utf-8");
|
|
31467
32437
|
return { status: "written", path: targetPath };
|
|
@@ -31558,7 +32528,7 @@ var init_atomic_write = __esm({
|
|
|
31558
32528
|
|
|
31559
32529
|
// src/lib/ci-init.ts
|
|
31560
32530
|
import * as fs8 from "node:fs";
|
|
31561
|
-
import * as
|
|
32531
|
+
import * as path10 from "node:path";
|
|
31562
32532
|
function tryReadJson(filePath) {
|
|
31563
32533
|
try {
|
|
31564
32534
|
return JSON.parse(fs8.readFileSync(filePath, "utf-8"));
|
|
@@ -31580,27 +32550,27 @@ function hasDevDep(pkg, name) {
|
|
|
31580
32550
|
function detectPlatforms(projectDir) {
|
|
31581
32551
|
const detected = /* @__PURE__ */ new Set();
|
|
31582
32552
|
const dirsToScan = [projectDir];
|
|
31583
|
-
const appsDir =
|
|
32553
|
+
const appsDir = path10.join(projectDir, "apps");
|
|
31584
32554
|
if (fs8.existsSync(appsDir)) {
|
|
31585
32555
|
try {
|
|
31586
32556
|
const appsEntries = fs8.readdirSync(appsDir, { withFileTypes: true });
|
|
31587
32557
|
for (const entry of appsEntries) {
|
|
31588
32558
|
if (entry.isDirectory()) {
|
|
31589
|
-
dirsToScan.push(
|
|
32559
|
+
dirsToScan.push(path10.join(appsDir, entry.name));
|
|
31590
32560
|
}
|
|
31591
32561
|
}
|
|
31592
32562
|
} catch {
|
|
31593
32563
|
}
|
|
31594
32564
|
}
|
|
31595
32565
|
for (const dir of dirsToScan) {
|
|
31596
|
-
const pkg = tryReadJson(
|
|
31597
|
-
if (fs8.existsSync(
|
|
32566
|
+
const pkg = tryReadJson(path10.join(dir, "package.json"));
|
|
32567
|
+
if (fs8.existsSync(path10.join(dir, "next.config.ts")) || fs8.existsSync(path10.join(dir, "next.config.js")) || fs8.existsSync(path10.join(dir, "next.config.mjs"))) {
|
|
31598
32568
|
detected.add("next_js");
|
|
31599
32569
|
}
|
|
31600
32570
|
if (hasDep(pkg, "@nestjs/core")) {
|
|
31601
32571
|
detected.add("nestjs");
|
|
31602
32572
|
}
|
|
31603
|
-
if (fs8.existsSync(
|
|
32573
|
+
if (fs8.existsSync(path10.join(dir, "tauri.conf.json")) || fs8.existsSync(path10.join(dir, "src-tauri"))) {
|
|
31604
32574
|
detected.add("tauri");
|
|
31605
32575
|
}
|
|
31606
32576
|
if (hasDevDep(pkg, "@types/vscode")) {
|
|
@@ -31611,7 +32581,7 @@ function detectPlatforms(projectDir) {
|
|
|
31611
32581
|
detected.add("expo");
|
|
31612
32582
|
}
|
|
31613
32583
|
}
|
|
31614
|
-
const packagesDir =
|
|
32584
|
+
const packagesDir = path10.join(projectDir, "packages");
|
|
31615
32585
|
if (fs8.existsSync(packagesDir)) {
|
|
31616
32586
|
try {
|
|
31617
32587
|
const pkgEntries = fs8.readdirSync(packagesDir, { withFileTypes: true });
|
|
@@ -31648,10 +32618,10 @@ function buildDefaultCiConfig(platforms) {
|
|
|
31648
32618
|
}
|
|
31649
32619
|
async function runCiInit(opts) {
|
|
31650
32620
|
await Promise.resolve();
|
|
31651
|
-
const projectDir =
|
|
32621
|
+
const projectDir = path10.resolve(opts?.projectDir ?? process.cwd());
|
|
31652
32622
|
const dryRun = opts?.dryRun ?? false;
|
|
31653
32623
|
const force = opts?.force ?? false;
|
|
31654
|
-
const ciPath =
|
|
32624
|
+
const ciPath = path10.join(projectDir, ".codebyplan", "ci.json");
|
|
31655
32625
|
const platforms = detectPlatforms(projectDir);
|
|
31656
32626
|
if (dryRun) {
|
|
31657
32627
|
return { status: "dry_run", path: ciPath, platforms };
|
|
@@ -31696,7 +32666,7 @@ async function runCiInit(opts) {
|
|
|
31696
32666
|
platforms: newPlatforms.length > 0 ? newPlatforms : platforms
|
|
31697
32667
|
};
|
|
31698
32668
|
}
|
|
31699
|
-
const codebyplanDir =
|
|
32669
|
+
const codebyplanDir = path10.join(projectDir, ".codebyplan");
|
|
31700
32670
|
fs8.mkdirSync(codebyplanDir, { recursive: true });
|
|
31701
32671
|
writeJsonAtomic(ciPath, newConfig);
|
|
31702
32672
|
return { status: "written", path: ciPath, platforms };
|
|
@@ -31905,7 +32875,7 @@ var init_ci_init = __esm({
|
|
|
31905
32875
|
|
|
31906
32876
|
// src/lib/scaffold-ci-workflow.ts
|
|
31907
32877
|
import * as fs9 from "node:fs";
|
|
31908
|
-
import * as
|
|
32878
|
+
import * as path11 from "node:path";
|
|
31909
32879
|
function substituteTokens(template, tokens) {
|
|
31910
32880
|
let result = template;
|
|
31911
32881
|
for (const [token, value] of Object.entries(tokens)) {
|
|
@@ -31915,7 +32885,7 @@ function substituteTokens(template, tokens) {
|
|
|
31915
32885
|
}
|
|
31916
32886
|
function detectPnpmVersionFromPackageJson(projectDir) {
|
|
31917
32887
|
try {
|
|
31918
|
-
const pkgPath =
|
|
32888
|
+
const pkgPath = path11.join(projectDir, "package.json");
|
|
31919
32889
|
const raw = fs9.readFileSync(pkgPath, "utf-8");
|
|
31920
32890
|
const pkg = JSON.parse(raw);
|
|
31921
32891
|
const pm = pkg.packageManager;
|
|
@@ -31932,7 +32902,7 @@ function detectPnpmVersionFromPackageJson(projectDir) {
|
|
|
31932
32902
|
}
|
|
31933
32903
|
function detectStrictEnforcedFromCiJson(projectDir) {
|
|
31934
32904
|
try {
|
|
31935
|
-
const ciJsonPath =
|
|
32905
|
+
const ciJsonPath = path11.join(projectDir, ".codebyplan", "ci.json");
|
|
31936
32906
|
const raw = fs9.readFileSync(ciJsonPath, "utf-8");
|
|
31937
32907
|
const parsed = JSON.parse(raw);
|
|
31938
32908
|
return parsed.workflow?.strict_check_enforced === true;
|
|
@@ -31944,12 +32914,12 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31944
32914
|
await Promise.resolve();
|
|
31945
32915
|
const dryRun = opts?.dryRun ?? false;
|
|
31946
32916
|
const force = opts?.force ?? false;
|
|
31947
|
-
const projectDir =
|
|
32917
|
+
const projectDir = path11.resolve(opts?.projectDir ?? process.cwd());
|
|
31948
32918
|
const pnpmVersion = opts?.pnpmVersion ?? detectPnpmVersionFromPackageJson(projectDir);
|
|
31949
32919
|
const nodeVersion = opts?.nodeVersion ?? "22";
|
|
31950
32920
|
const strictEnforced = opts?.strictEnforced ?? detectStrictEnforcedFromCiJson(projectDir);
|
|
31951
32921
|
const templatesDir = opts?.templatesDir ?? resolveTemplatesDir();
|
|
31952
|
-
const templatePath =
|
|
32922
|
+
const templatePath = path11.join(templatesDir, "github-workflows", "ci.yml");
|
|
31953
32923
|
if (!fs9.existsSync(templatePath)) {
|
|
31954
32924
|
throw new Error(
|
|
31955
32925
|
`scaffold-ci-workflow: template not found at ${templatePath}`
|
|
@@ -31962,7 +32932,7 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31962
32932
|
STRICT_NAME_SUFFIX: strictEnforced ? "" : " (report-only)",
|
|
31963
32933
|
STRICT_CONTINUE_ON_ERROR_LINE: strictEnforced ? "" : "\n continue-on-error: true"
|
|
31964
32934
|
});
|
|
31965
|
-
const targetPath =
|
|
32935
|
+
const targetPath = path11.join(projectDir, ".github", "workflows", "ci.yml");
|
|
31966
32936
|
if (dryRun) {
|
|
31967
32937
|
return { status: "dry_run", path: targetPath };
|
|
31968
32938
|
}
|
|
@@ -31981,7 +32951,7 @@ async function runScaffoldCiWorkflow(opts) {
|
|
|
31981
32951
|
);
|
|
31982
32952
|
}
|
|
31983
32953
|
}
|
|
31984
|
-
const targetDir =
|
|
32954
|
+
const targetDir = path11.dirname(targetPath);
|
|
31985
32955
|
fs9.mkdirSync(targetDir, { recursive: true });
|
|
31986
32956
|
const tmpPath = targetPath + ".tmp";
|
|
31987
32957
|
try {
|
|
@@ -32005,10 +32975,10 @@ var init_scaffold_ci_workflow = __esm({
|
|
|
32005
32975
|
|
|
32006
32976
|
// src/lib/gh-required-checks.ts
|
|
32007
32977
|
import * as fs10 from "node:fs";
|
|
32008
|
-
import * as
|
|
32978
|
+
import * as path12 from "node:path";
|
|
32009
32979
|
import { execSync as execSync6 } from "node:child_process";
|
|
32010
32980
|
function readCiJson(projectDir) {
|
|
32011
|
-
const ciPath =
|
|
32981
|
+
const ciPath = path12.join(projectDir, ".codebyplan", "ci.json");
|
|
32012
32982
|
if (!fs10.existsSync(ciPath)) {
|
|
32013
32983
|
return {
|
|
32014
32984
|
platforms: {},
|
|
@@ -32027,15 +32997,15 @@ function readCiJson(projectDir) {
|
|
|
32027
32997
|
}
|
|
32028
32998
|
}
|
|
32029
32999
|
function writeCiJsonAtomic(projectDir, config) {
|
|
32030
|
-
const ciPath =
|
|
33000
|
+
const ciPath = path12.join(projectDir, ".codebyplan", "ci.json");
|
|
32031
33001
|
writeJsonAtomic(ciPath, config);
|
|
32032
33002
|
}
|
|
32033
33003
|
function enforceRequiredCheck(opts) {
|
|
32034
|
-
const projectDir =
|
|
33004
|
+
const projectDir = path12.resolve(opts?.projectDir ?? process.cwd());
|
|
32035
33005
|
const branch = opts?.branch ?? "main";
|
|
32036
33006
|
const checkName = opts?.checkName ?? "Lint + typecheck + test + build";
|
|
32037
33007
|
const dryRun = opts?.dryRun ?? false;
|
|
32038
|
-
const ciPath =
|
|
33008
|
+
const ciPath = path12.join(projectDir, ".codebyplan", "ci.json");
|
|
32039
33009
|
const config = readCiJson(projectDir);
|
|
32040
33010
|
if (config.workflow?.required_check_enforced === true) {
|
|
32041
33011
|
return { status: "already_enforced", path: ciPath };
|
|
@@ -32442,9 +33412,9 @@ var init_ci = __esm({
|
|
|
32442
33412
|
|
|
32443
33413
|
// src/lib/cd-init.ts
|
|
32444
33414
|
import * as fs11 from "node:fs";
|
|
32445
|
-
import * as
|
|
33415
|
+
import * as path13 from "node:path";
|
|
32446
33416
|
function detectSurfaces(projectDir) {
|
|
32447
|
-
const shipmentPath =
|
|
33417
|
+
const shipmentPath = path13.join(projectDir, ".codebyplan", "shipment.json");
|
|
32448
33418
|
let shipment;
|
|
32449
33419
|
try {
|
|
32450
33420
|
shipment = JSON.parse(fs11.readFileSync(shipmentPath, "utf-8"));
|
|
@@ -32497,10 +33467,10 @@ function buildDefaultCdConfig(rawSurfaceKeys) {
|
|
|
32497
33467
|
}
|
|
32498
33468
|
async function runCdInit(opts) {
|
|
32499
33469
|
await Promise.resolve();
|
|
32500
|
-
const projectDir =
|
|
33470
|
+
const projectDir = path13.resolve(opts?.projectDir ?? process.cwd());
|
|
32501
33471
|
const dryRun = opts?.dryRun ?? false;
|
|
32502
33472
|
const force = opts?.force ?? false;
|
|
32503
|
-
const cdPath =
|
|
33473
|
+
const cdPath = path13.join(projectDir, ".codebyplan", "cd.json");
|
|
32504
33474
|
const rawSurfaceKeys = detectSurfaces(projectDir);
|
|
32505
33475
|
const seen = /* @__PURE__ */ new Set();
|
|
32506
33476
|
const surfaces = [];
|
|
@@ -32541,7 +33511,7 @@ async function runCdInit(opts) {
|
|
|
32541
33511
|
surfaces: newSurfaces
|
|
32542
33512
|
};
|
|
32543
33513
|
}
|
|
32544
|
-
const codebyplanDir =
|
|
33514
|
+
const codebyplanDir = path13.join(projectDir, ".codebyplan");
|
|
32545
33515
|
fs11.mkdirSync(codebyplanDir, { recursive: true });
|
|
32546
33516
|
writeJsonAtomic(cdPath, newConfig);
|
|
32547
33517
|
return { status: "written", path: cdPath, surfaces };
|
|
@@ -32631,14 +33601,14 @@ var init_cd_init = __esm({
|
|
|
32631
33601
|
|
|
32632
33602
|
// src/lib/scaffold-cd-workflow.ts
|
|
32633
33603
|
import * as fs12 from "node:fs";
|
|
32634
|
-
import * as
|
|
33604
|
+
import * as path14 from "node:path";
|
|
32635
33605
|
async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
32636
33606
|
await Promise.resolve();
|
|
32637
33607
|
const dryRun = opts.dryRun ?? false;
|
|
32638
33608
|
const force = opts.force ?? false;
|
|
32639
|
-
const projectDir =
|
|
33609
|
+
const projectDir = path14.resolve(opts.projectDir ?? process.cwd());
|
|
32640
33610
|
const templatesDir = opts.templatesDir ?? resolveTemplatesDir();
|
|
32641
|
-
const templatePath =
|
|
33611
|
+
const templatePath = path14.join(
|
|
32642
33612
|
templatesDir,
|
|
32643
33613
|
"github-workflows",
|
|
32644
33614
|
templateName
|
|
@@ -32649,7 +33619,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
32649
33619
|
);
|
|
32650
33620
|
}
|
|
32651
33621
|
const templateContent = fs12.readFileSync(templatePath, "utf-8");
|
|
32652
|
-
const targetPath =
|
|
33622
|
+
const targetPath = path14.join(projectDir, ".github", "workflows", targetName);
|
|
32653
33623
|
if (dryRun) {
|
|
32654
33624
|
return { status: "dry_run", path: targetPath };
|
|
32655
33625
|
}
|
|
@@ -32668,7 +33638,7 @@ async function scaffoldOneWorkflow(templateName, targetName, opts) {
|
|
|
32668
33638
|
);
|
|
32669
33639
|
}
|
|
32670
33640
|
}
|
|
32671
|
-
const targetDir =
|
|
33641
|
+
const targetDir = path14.dirname(targetPath);
|
|
32672
33642
|
fs12.mkdirSync(targetDir, { recursive: true });
|
|
32673
33643
|
const tmpPath = targetPath + ".tmp";
|
|
32674
33644
|
try {
|
|
@@ -33344,7 +34314,7 @@ __export(version_status_exports, {
|
|
|
33344
34314
|
});
|
|
33345
34315
|
import { execFileSync, execSync as execSync7 } from "node:child_process";
|
|
33346
34316
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
33347
|
-
import { dirname as
|
|
34317
|
+
import { dirname as dirname13, join as join32 } from "node:path";
|
|
33348
34318
|
function fetchLatestVersion() {
|
|
33349
34319
|
try {
|
|
33350
34320
|
return execFileSync("npm", ["view", "codebyplan", "version"], {
|
|
@@ -33368,11 +34338,11 @@ function detectPackageManager2(gitRoot) {
|
|
|
33368
34338
|
let dir = process.cwd();
|
|
33369
34339
|
const stopAt = gitRoot ?? null;
|
|
33370
34340
|
while (true) {
|
|
33371
|
-
if (existsSync10(
|
|
33372
|
-
if (existsSync10(
|
|
33373
|
-
if (existsSync10(
|
|
34341
|
+
if (existsSync10(join32(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
34342
|
+
if (existsSync10(join32(dir, "yarn.lock"))) return "yarn";
|
|
34343
|
+
if (existsSync10(join32(dir, "package-lock.json"))) return "npm";
|
|
33374
34344
|
if (stopAt !== null && dir === stopAt) break;
|
|
33375
|
-
const parent =
|
|
34345
|
+
const parent = dirname13(dir);
|
|
33376
34346
|
if (parent === dir) break;
|
|
33377
34347
|
dir = parent;
|
|
33378
34348
|
}
|
|
@@ -33390,7 +34360,7 @@ function buildInstallCommand2(pm) {
|
|
|
33390
34360
|
}
|
|
33391
34361
|
async function resolveGuard(gitRoot, currentBranch) {
|
|
33392
34362
|
if (gitRoot !== null) {
|
|
33393
|
-
const canonicalPkgPath =
|
|
34363
|
+
const canonicalPkgPath = join32(
|
|
33394
34364
|
gitRoot,
|
|
33395
34365
|
"packages",
|
|
33396
34366
|
"codebyplan-package",
|
|
@@ -33414,10 +34384,10 @@ async function resolveGuard(gitRoot, currentBranch) {
|
|
|
33414
34384
|
let gitJsonPath;
|
|
33415
34385
|
if (found.path.endsWith("/repo.json")) {
|
|
33416
34386
|
const dir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
33417
|
-
gitJsonPath =
|
|
34387
|
+
gitJsonPath = join32(dir, "git.json");
|
|
33418
34388
|
} else {
|
|
33419
34389
|
const legacyDir = found.path.slice(0, found.path.lastIndexOf("/"));
|
|
33420
|
-
gitJsonPath =
|
|
34390
|
+
gitJsonPath = join32(legacyDir, ".codebyplan", "git.json");
|
|
33421
34391
|
}
|
|
33422
34392
|
const raw = readFileSync11(gitJsonPath, "utf-8");
|
|
33423
34393
|
const parsed = JSON.parse(raw);
|
|
@@ -33502,7 +34472,7 @@ __export(upload_e2e_images_exports, {
|
|
|
33502
34472
|
runUploadE2eImagesCommand: () => runUploadE2eImagesCommand
|
|
33503
34473
|
});
|
|
33504
34474
|
import { readFile as readFile20 } from "node:fs/promises";
|
|
33505
|
-
import { join as
|
|
34475
|
+
import { join as join33, basename as basename2, resolve as resolve10 } from "node:path";
|
|
33506
34476
|
import { execSync as execSync8 } from "node:child_process";
|
|
33507
34477
|
function baseUrl2() {
|
|
33508
34478
|
return (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
|
|
@@ -33537,7 +34507,7 @@ function parseArgs(args) {
|
|
|
33537
34507
|
async function readE2eConfig(projectPath) {
|
|
33538
34508
|
try {
|
|
33539
34509
|
const raw = await readFile20(
|
|
33540
|
-
|
|
34510
|
+
join33(projectPath, ".codebyplan", "e2e.json"),
|
|
33541
34511
|
"utf-8"
|
|
33542
34512
|
);
|
|
33543
34513
|
return JSON.parse(raw);
|
|
@@ -33578,8 +34548,8 @@ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, bas
|
|
|
33578
34548
|
continue;
|
|
33579
34549
|
const isNew = status === "A";
|
|
33580
34550
|
results.push({
|
|
33581
|
-
absolutePath:
|
|
33582
|
-
filename:
|
|
34551
|
+
absolutePath: join33(projectPath, filePath),
|
|
34552
|
+
filename: basename2(filePath),
|
|
33583
34553
|
framework: frameworkName,
|
|
33584
34554
|
is_new: isNew
|
|
33585
34555
|
});
|
|
@@ -33594,11 +34564,11 @@ function deriveTestName(absolutePath) {
|
|
|
33594
34564
|
return seg.replace(".spec.ts-snapshots", "");
|
|
33595
34565
|
}
|
|
33596
34566
|
}
|
|
33597
|
-
return
|
|
34567
|
+
return basename2(absolutePath, ".png");
|
|
33598
34568
|
}
|
|
33599
34569
|
function buildManifestItem(png) {
|
|
33600
34570
|
const testName = deriveTestName(png.absolutePath);
|
|
33601
|
-
const pageOrScreen =
|
|
34571
|
+
const pageOrScreen = basename2(png.absolutePath, ".png");
|
|
33602
34572
|
return {
|
|
33603
34573
|
filename: png.filename,
|
|
33604
34574
|
test_name: testName,
|
|
@@ -33754,8 +34724,8 @@ __export(arch_map_exports, {
|
|
|
33754
34724
|
});
|
|
33755
34725
|
import { readFile as readFile21, writeFile as writeFile17 } from "node:fs/promises";
|
|
33756
34726
|
import { existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
|
|
33757
|
-
import { join as
|
|
33758
|
-
import { spawnSync as
|
|
34727
|
+
import { join as join34 } from "node:path";
|
|
34728
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
33759
34729
|
function normalizeModulePath(modulePath) {
|
|
33760
34730
|
return modulePath.replace(/\/+$/, "");
|
|
33761
34731
|
}
|
|
@@ -33779,7 +34749,7 @@ async function resolveCodebyplanDir(startDir) {
|
|
|
33779
34749
|
}
|
|
33780
34750
|
}
|
|
33781
34751
|
async function readArchitectureConfig(codebyplanDir) {
|
|
33782
|
-
const filePath =
|
|
34752
|
+
const filePath = join34(codebyplanDir, "architecture.json");
|
|
33783
34753
|
try {
|
|
33784
34754
|
const raw = await readFile21(filePath, "utf-8");
|
|
33785
34755
|
const parsed = JSON.parse(raw);
|
|
@@ -33792,12 +34762,12 @@ async function readArchitectureConfig(codebyplanDir) {
|
|
|
33792
34762
|
}
|
|
33793
34763
|
}
|
|
33794
34764
|
async function writeArchitectureConfig(codebyplanDir, config) {
|
|
33795
|
-
const filePath =
|
|
34765
|
+
const filePath = join34(codebyplanDir, "architecture.json");
|
|
33796
34766
|
await writeFile17(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
33797
34767
|
}
|
|
33798
34768
|
function resolveGitSha(modulePath, cwd) {
|
|
33799
34769
|
try {
|
|
33800
|
-
const result =
|
|
34770
|
+
const result = spawnSync12(
|
|
33801
34771
|
"git",
|
|
33802
34772
|
["log", "--format=%H", "-1", "--", modulePath],
|
|
33803
34773
|
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -33811,7 +34781,7 @@ function resolveGitSha(modulePath, cwd) {
|
|
|
33811
34781
|
}
|
|
33812
34782
|
async function discoverModulePaths(projectRoot) {
|
|
33813
34783
|
const paths = [];
|
|
33814
|
-
const workspacePath =
|
|
34784
|
+
const workspacePath = join34(projectRoot, "pnpm-workspace.yaml");
|
|
33815
34785
|
let patterns = [];
|
|
33816
34786
|
try {
|
|
33817
34787
|
const raw = await readFile21(workspacePath, "utf-8");
|
|
@@ -33838,7 +34808,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33838
34808
|
for (const pattern of patterns) {
|
|
33839
34809
|
if (pattern.endsWith("/*")) {
|
|
33840
34810
|
const dir = pattern.slice(0, -2);
|
|
33841
|
-
const absDir =
|
|
34811
|
+
const absDir = join34(projectRoot, dir);
|
|
33842
34812
|
try {
|
|
33843
34813
|
if (existsSync11(absDir)) {
|
|
33844
34814
|
const entries = readdirSync4(absDir, { withFileTypes: true });
|
|
@@ -33851,7 +34821,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33851
34821
|
} catch {
|
|
33852
34822
|
}
|
|
33853
34823
|
} else if (!pattern.includes("*")) {
|
|
33854
|
-
const absPath =
|
|
34824
|
+
const absPath = join34(projectRoot, pattern);
|
|
33855
34825
|
if (existsSync11(absPath)) {
|
|
33856
34826
|
paths.push(pattern);
|
|
33857
34827
|
}
|
|
@@ -33859,7 +34829,7 @@ async function discoverModulePaths(projectRoot) {
|
|
|
33859
34829
|
}
|
|
33860
34830
|
const crossCutting = ["supabase", ".github", "scripts"];
|
|
33861
34831
|
for (const dir of crossCutting) {
|
|
33862
|
-
const absPath =
|
|
34832
|
+
const absPath = join34(projectRoot, dir);
|
|
33863
34833
|
try {
|
|
33864
34834
|
if (existsSync11(absPath)) {
|
|
33865
34835
|
paths.push(dir);
|
|
@@ -34045,7 +35015,7 @@ async function runStamp(modulePath, sha, depthArg, projectRoot) {
|
|
|
34045
35015
|
}
|
|
34046
35016
|
await writeArchitectureConfig(codebyplanDir, config);
|
|
34047
35017
|
const stampedEntry = existingIndex >= 0 ? config.modules[existingIndex] : config.modules[config.modules.length - 1];
|
|
34048
|
-
const mapAbsPath =
|
|
35018
|
+
const mapAbsPath = join34(repoRoot, stampedEntry.map_file);
|
|
34049
35019
|
let mapContent = null;
|
|
34050
35020
|
try {
|
|
34051
35021
|
mapContent = await readFile21(mapAbsPath, "utf-8");
|
|
@@ -34251,18 +35221,18 @@ var init_worktree_port_resolver = __esm({
|
|
|
34251
35221
|
|
|
34252
35222
|
// src/lib/migrate-local-config.ts
|
|
34253
35223
|
import { mkdir as mkdir9, readFile as readFile22, unlink as unlink5, writeFile as writeFile18 } from "node:fs/promises";
|
|
34254
|
-
import { join as
|
|
35224
|
+
import { join as join35 } from "node:path";
|
|
34255
35225
|
function legacySharedPath(projectPath) {
|
|
34256
|
-
return
|
|
35226
|
+
return join35(projectPath, ".codebyplan.json");
|
|
34257
35227
|
}
|
|
34258
35228
|
function legacyLocalPath(projectPath) {
|
|
34259
|
-
return
|
|
35229
|
+
return join35(projectPath, ".codebyplan.local.json");
|
|
34260
35230
|
}
|
|
34261
35231
|
function newDirPath(projectPath) {
|
|
34262
|
-
return
|
|
35232
|
+
return join35(projectPath, ".codebyplan");
|
|
34263
35233
|
}
|
|
34264
35234
|
function sentinelPath(projectPath) {
|
|
34265
|
-
return
|
|
35235
|
+
return join35(projectPath, ".codebyplan", "repo.json");
|
|
34266
35236
|
}
|
|
34267
35237
|
async function statSafe(p) {
|
|
34268
35238
|
const { stat: stat3 } = await import("node:fs/promises");
|
|
@@ -34356,7 +35326,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34356
35326
|
if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
|
|
34357
35327
|
if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
|
|
34358
35328
|
await writeFile18(
|
|
34359
|
-
|
|
35329
|
+
join35(projectPath, ".codebyplan", "repo.json"),
|
|
34360
35330
|
JSON.stringify(repoJson, null, 2) + "\n",
|
|
34361
35331
|
"utf-8"
|
|
34362
35332
|
);
|
|
@@ -34369,7 +35339,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34369
35339
|
if ("port_allocations" in cfg)
|
|
34370
35340
|
serverJson.port_allocations = cfg.port_allocations;
|
|
34371
35341
|
await writeFile18(
|
|
34372
|
-
|
|
35342
|
+
join35(projectPath, ".codebyplan", "server.json"),
|
|
34373
35343
|
JSON.stringify(serverJson, null, 2) + "\n",
|
|
34374
35344
|
"utf-8"
|
|
34375
35345
|
);
|
|
@@ -34378,7 +35348,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34378
35348
|
if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
|
|
34379
35349
|
if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
|
|
34380
35350
|
await writeFile18(
|
|
34381
|
-
|
|
35351
|
+
join35(projectPath, ".codebyplan", "git.json"),
|
|
34382
35352
|
JSON.stringify(gitJson, null, 2) + "\n",
|
|
34383
35353
|
"utf-8"
|
|
34384
35354
|
);
|
|
@@ -34386,35 +35356,35 @@ async function runLocalMigration(projectPath) {
|
|
|
34386
35356
|
const shipmentJson = {};
|
|
34387
35357
|
if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
|
|
34388
35358
|
await writeFile18(
|
|
34389
|
-
|
|
35359
|
+
join35(projectPath, ".codebyplan", "shipment.json"),
|
|
34390
35360
|
JSON.stringify(shipmentJson, null, 2) + "\n",
|
|
34391
35361
|
"utf-8"
|
|
34392
35362
|
);
|
|
34393
35363
|
filesChanged.push(".codebyplan/shipment.json");
|
|
34394
35364
|
const vendorJson = {};
|
|
34395
35365
|
await writeFile18(
|
|
34396
|
-
|
|
35366
|
+
join35(projectPath, ".codebyplan", "vendor.json"),
|
|
34397
35367
|
JSON.stringify(vendorJson, null, 2) + "\n",
|
|
34398
35368
|
"utf-8"
|
|
34399
35369
|
);
|
|
34400
35370
|
filesChanged.push(".codebyplan/vendor.json");
|
|
34401
35371
|
const e2eJson = {};
|
|
34402
35372
|
await writeFile18(
|
|
34403
|
-
|
|
35373
|
+
join35(projectPath, ".codebyplan", "e2e.json"),
|
|
34404
35374
|
JSON.stringify(e2eJson, null, 2) + "\n",
|
|
34405
35375
|
"utf-8"
|
|
34406
35376
|
);
|
|
34407
35377
|
filesChanged.push(".codebyplan/e2e.json");
|
|
34408
35378
|
const eslintJson = {};
|
|
34409
35379
|
await writeFile18(
|
|
34410
|
-
|
|
35380
|
+
join35(projectPath, ".codebyplan", "eslint.json"),
|
|
34411
35381
|
JSON.stringify(eslintJson, null, 2) + "\n",
|
|
34412
35382
|
"utf-8"
|
|
34413
35383
|
);
|
|
34414
35384
|
filesChanged.push(".codebyplan/eslint.json");
|
|
34415
35385
|
if (!deviceWrittenByHelper) {
|
|
34416
35386
|
await writeFile18(
|
|
34417
|
-
|
|
35387
|
+
join35(projectPath, ".codebyplan", "device.local.json"),
|
|
34418
35388
|
JSON.stringify({ device_id: deviceId }, null, 2) + "\n",
|
|
34419
35389
|
"utf-8"
|
|
34420
35390
|
);
|
|
@@ -34426,7 +35396,7 @@ async function runLocalMigration(projectPath) {
|
|
|
34426
35396
|
"Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
|
|
34427
35397
|
);
|
|
34428
35398
|
}
|
|
34429
|
-
const gitignorePath =
|
|
35399
|
+
const gitignorePath = join35(projectPath, ".gitignore");
|
|
34430
35400
|
try {
|
|
34431
35401
|
const gitignoreContent = await readFile22(gitignorePath, "utf-8");
|
|
34432
35402
|
const legacyLine = ".codebyplan.local.json";
|
|
@@ -34490,7 +35460,7 @@ __export(config_exports, {
|
|
|
34490
35460
|
runConfigMigrate: () => runConfigMigrate
|
|
34491
35461
|
});
|
|
34492
35462
|
import { mkdir as mkdir10, readFile as readFile23, writeFile as writeFile19 } from "node:fs/promises";
|
|
34493
|
-
import { join as
|
|
35463
|
+
import { join as join36 } from "node:path";
|
|
34494
35464
|
async function runConfig() {
|
|
34495
35465
|
const flags = parseFlags(3);
|
|
34496
35466
|
const dryRun = hasFlag("dry-run", 3);
|
|
@@ -34523,7 +35493,7 @@ async function runConfig() {
|
|
|
34523
35493
|
console.log("\n Config complete.\n");
|
|
34524
35494
|
}
|
|
34525
35495
|
async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
34526
|
-
const codebyplanDir =
|
|
35496
|
+
const codebyplanDir = join36(projectPath, ".codebyplan");
|
|
34527
35497
|
const {
|
|
34528
35498
|
resolvedWorktreeId,
|
|
34529
35499
|
portAllocations,
|
|
@@ -34616,7 +35586,7 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
34616
35586
|
];
|
|
34617
35587
|
let anyUpdated = false;
|
|
34618
35588
|
for (const { name, payload, createOnly } of files) {
|
|
34619
|
-
const filePath =
|
|
35589
|
+
const filePath = join36(codebyplanDir, name);
|
|
34620
35590
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
34621
35591
|
let currentJson = "";
|
|
34622
35592
|
try {
|
|
@@ -34636,7 +35606,7 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
|
|
|
34636
35606
|
async function readRepoConfig(projectPath) {
|
|
34637
35607
|
try {
|
|
34638
35608
|
const raw = await readFile23(
|
|
34639
|
-
|
|
35609
|
+
join36(projectPath, ".codebyplan", "repo.json"),
|
|
34640
35610
|
"utf-8"
|
|
34641
35611
|
);
|
|
34642
35612
|
return JSON.parse(raw);
|
|
@@ -34647,7 +35617,7 @@ async function readRepoConfig(projectPath) {
|
|
|
34647
35617
|
async function readServerConfig(projectPath) {
|
|
34648
35618
|
try {
|
|
34649
35619
|
const raw = await readFile23(
|
|
34650
|
-
|
|
35620
|
+
join36(projectPath, ".codebyplan", "server.json"),
|
|
34651
35621
|
"utf-8"
|
|
34652
35622
|
);
|
|
34653
35623
|
return JSON.parse(raw);
|
|
@@ -34658,7 +35628,7 @@ async function readServerConfig(projectPath) {
|
|
|
34658
35628
|
async function readGitConfig2(projectPath) {
|
|
34659
35629
|
try {
|
|
34660
35630
|
const raw = await readFile23(
|
|
34661
|
-
|
|
35631
|
+
join36(projectPath, ".codebyplan", "git.json"),
|
|
34662
35632
|
"utf-8"
|
|
34663
35633
|
);
|
|
34664
35634
|
return JSON.parse(raw);
|
|
@@ -34669,7 +35639,7 @@ async function readGitConfig2(projectPath) {
|
|
|
34669
35639
|
async function readShipmentConfig2(projectPath) {
|
|
34670
35640
|
try {
|
|
34671
35641
|
const raw = await readFile23(
|
|
34672
|
-
|
|
35642
|
+
join36(projectPath, ".codebyplan", "shipment.json"),
|
|
34673
35643
|
"utf-8"
|
|
34674
35644
|
);
|
|
34675
35645
|
return JSON.parse(raw);
|
|
@@ -34680,7 +35650,7 @@ async function readShipmentConfig2(projectPath) {
|
|
|
34680
35650
|
async function readVendorConfig(projectPath) {
|
|
34681
35651
|
try {
|
|
34682
35652
|
const raw = await readFile23(
|
|
34683
|
-
|
|
35653
|
+
join36(projectPath, ".codebyplan", "vendor.json"),
|
|
34684
35654
|
"utf-8"
|
|
34685
35655
|
);
|
|
34686
35656
|
return JSON.parse(raw);
|
|
@@ -34691,7 +35661,7 @@ async function readVendorConfig(projectPath) {
|
|
|
34691
35661
|
async function readE2eConfig2(projectPath) {
|
|
34692
35662
|
try {
|
|
34693
35663
|
const raw = await readFile23(
|
|
34694
|
-
|
|
35664
|
+
join36(projectPath, ".codebyplan", "e2e.json"),
|
|
34695
35665
|
"utf-8"
|
|
34696
35666
|
);
|
|
34697
35667
|
return JSON.parse(raw);
|
|
@@ -34702,7 +35672,7 @@ async function readE2eConfig2(projectPath) {
|
|
|
34702
35672
|
async function readServerLocalConfig(projectPath) {
|
|
34703
35673
|
try {
|
|
34704
35674
|
const raw = await readFile23(
|
|
34705
|
-
|
|
35675
|
+
join36(projectPath, ".codebyplan", "server.local.json"),
|
|
34706
35676
|
"utf-8"
|
|
34707
35677
|
);
|
|
34708
35678
|
return JSON.parse(raw);
|
|
@@ -34775,7 +35745,7 @@ var init_config = __esm({
|
|
|
34775
35745
|
|
|
34776
35746
|
// src/lib/server-detect.ts
|
|
34777
35747
|
import { readFile as readFile24, readdir as readdir5, access as access6 } from "node:fs/promises";
|
|
34778
|
-
import { join as
|
|
35748
|
+
import { join as join37 } from "node:path";
|
|
34779
35749
|
async function fileExists4(filePath) {
|
|
34780
35750
|
try {
|
|
34781
35751
|
await access6(filePath);
|
|
@@ -34786,8 +35756,8 @@ async function fileExists4(filePath) {
|
|
|
34786
35756
|
}
|
|
34787
35757
|
function detectPackageManager3(dir) {
|
|
34788
35758
|
return (async () => {
|
|
34789
|
-
if (await fileExists4(
|
|
34790
|
-
if (await fileExists4(
|
|
35759
|
+
if (await fileExists4(join37(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
35760
|
+
if (await fileExists4(join37(dir, "yarn.lock"))) return "yarn";
|
|
34791
35761
|
return "npm";
|
|
34792
35762
|
})();
|
|
34793
35763
|
}
|
|
@@ -34819,12 +35789,12 @@ function detectPortFromScripts(pkg) {
|
|
|
34819
35789
|
return null;
|
|
34820
35790
|
}
|
|
34821
35791
|
async function isMonorepo(dir) {
|
|
34822
|
-
return await fileExists4(
|
|
35792
|
+
return await fileExists4(join37(dir, "turbo.json")) || await fileExists4(join37(dir, "pnpm-workspace.yaml"));
|
|
34823
35793
|
}
|
|
34824
35794
|
async function detectServers(projectPath) {
|
|
34825
35795
|
let pkg;
|
|
34826
35796
|
try {
|
|
34827
|
-
const raw = await readFile24(
|
|
35797
|
+
const raw = await readFile24(join37(projectPath, "package.json"), "utf-8");
|
|
34828
35798
|
pkg = JSON.parse(raw);
|
|
34829
35799
|
} catch {
|
|
34830
35800
|
return {
|
|
@@ -34840,13 +35810,13 @@ async function detectServers(projectPath) {
|
|
|
34840
35810
|
const mono = await isMonorepo(projectPath);
|
|
34841
35811
|
const servers = [];
|
|
34842
35812
|
if (mono) {
|
|
34843
|
-
const appsDir =
|
|
35813
|
+
const appsDir = join37(projectPath, "apps");
|
|
34844
35814
|
try {
|
|
34845
35815
|
const entries = await readdir5(appsDir, { withFileTypes: true });
|
|
34846
35816
|
const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
34847
35817
|
for (const entry of sorted) {
|
|
34848
35818
|
if (!entry.isDirectory()) continue;
|
|
34849
|
-
const appPkgPath =
|
|
35819
|
+
const appPkgPath = join37(appsDir, entry.name, "package.json");
|
|
34850
35820
|
try {
|
|
34851
35821
|
const appRaw = await readFile24(appPkgPath, "utf-8");
|
|
34852
35822
|
const appPkg = JSON.parse(appRaw);
|
|
@@ -35012,7 +35982,7 @@ __export(ports_exports, {
|
|
|
35012
35982
|
runPorts: () => runPorts
|
|
35013
35983
|
});
|
|
35014
35984
|
import { mkdir as mkdir11, readFile as readFile26, writeFile as writeFile20 } from "node:fs/promises";
|
|
35015
|
-
import { join as
|
|
35985
|
+
import { join as join38 } from "node:path";
|
|
35016
35986
|
function printDetectionResult(result, projectPath) {
|
|
35017
35987
|
console.log(`
|
|
35018
35988
|
CodeByPlan Ports - List`);
|
|
@@ -35168,8 +36138,8 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
35168
36138
|
// and ServerLocalConfig.port_allocations is typed the same — honest end-to-end.
|
|
35169
36139
|
port_allocations: portAllocations
|
|
35170
36140
|
};
|
|
35171
|
-
const codebyplanDir =
|
|
35172
|
-
const filePath =
|
|
36141
|
+
const codebyplanDir = join38(projectPath, ".codebyplan");
|
|
36142
|
+
const filePath = join38(codebyplanDir, "server.local.json");
|
|
35173
36143
|
const newJson = JSON.stringify(payload, null, 2) + "\n";
|
|
35174
36144
|
let currentJson = "";
|
|
35175
36145
|
try {
|
|
@@ -35191,8 +36161,8 @@ async function writeServerLocalConfig(repoId, projectPath, dryRun) {
|
|
|
35191
36161
|
);
|
|
35192
36162
|
}
|
|
35193
36163
|
async function provisionE2eEnv(projectPath, dryRun) {
|
|
35194
|
-
const relSource =
|
|
35195
|
-
const sourcePath =
|
|
36164
|
+
const relSource = join38("apps", "web", ".env.local");
|
|
36165
|
+
const sourcePath = join38(projectPath, relSource);
|
|
35196
36166
|
let sourceRaw;
|
|
35197
36167
|
try {
|
|
35198
36168
|
sourceRaw = await readFile26(sourcePath, "utf-8");
|
|
@@ -35224,8 +36194,8 @@ async function provisionE2eEnv(projectPath, dryRun) {
|
|
|
35224
36194
|
);
|
|
35225
36195
|
return;
|
|
35226
36196
|
}
|
|
35227
|
-
const codebyplanDir =
|
|
35228
|
-
const filePath =
|
|
36197
|
+
const codebyplanDir = join38(projectPath, ".codebyplan");
|
|
36198
|
+
const filePath = join38(codebyplanDir, "e2e.env");
|
|
35229
36199
|
const newContent = lines.join("\n") + "\n";
|
|
35230
36200
|
let currentContent = "";
|
|
35231
36201
|
try {
|
|
@@ -35510,7 +36480,7 @@ __export(docs_exports, {
|
|
|
35510
36480
|
});
|
|
35511
36481
|
import { existsSync as existsSync13 } from "node:fs";
|
|
35512
36482
|
import { mkdir as mkdir12, readFile as readFile27, readdir as readdir6, rm as rm2, writeFile as writeFile21 } from "node:fs/promises";
|
|
35513
|
-
import { dirname as
|
|
36483
|
+
import { dirname as dirname14, isAbsolute as isAbsolute2, join as join39, relative as relative7, sep as sep2 } from "node:path";
|
|
35514
36484
|
function selectDependencies(deps) {
|
|
35515
36485
|
const byName = /* @__PURE__ */ new Map();
|
|
35516
36486
|
for (const dep of deps) {
|
|
@@ -35564,12 +36534,12 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
35564
36534
|
}
|
|
35565
36535
|
async function resolveExactVersion(projectPath, dep) {
|
|
35566
36536
|
const candidateDirs = [projectPath];
|
|
35567
|
-
const sourceDir =
|
|
36537
|
+
const sourceDir = join39(projectPath, dirname14(dep.sourcePath));
|
|
35568
36538
|
if (sourceDir !== projectPath) candidateDirs.push(sourceDir);
|
|
35569
36539
|
for (const base of candidateDirs) {
|
|
35570
36540
|
try {
|
|
35571
36541
|
const raw = await readFile27(
|
|
35572
|
-
|
|
36542
|
+
join39(base, "node_modules", dep.name, "package.json"),
|
|
35573
36543
|
"utf-8"
|
|
35574
36544
|
);
|
|
35575
36545
|
const pkg = JSON.parse(raw);
|
|
@@ -35584,7 +36554,7 @@ async function resolveExactVersion(projectPath, dep) {
|
|
|
35584
36554
|
async function readVendorDocsPath(projectPath) {
|
|
35585
36555
|
try {
|
|
35586
36556
|
const raw = await readFile27(
|
|
35587
|
-
|
|
36557
|
+
join39(projectPath, ".codebyplan", "vendor.json"),
|
|
35588
36558
|
"utf-8"
|
|
35589
36559
|
);
|
|
35590
36560
|
const parsed = JSON.parse(raw);
|
|
@@ -35597,7 +36567,7 @@ async function readVendorDocsPath(projectPath) {
|
|
|
35597
36567
|
}
|
|
35598
36568
|
async function resolveDocsDir(projectPath, flags) {
|
|
35599
36569
|
const configured = flags["dir"] ?? await readVendorDocsPath(projectPath) ?? DEFAULT_DOCS_DIR;
|
|
35600
|
-
const absDir = isAbsolute2(configured) ? configured :
|
|
36570
|
+
const absDir = isAbsolute2(configured) ? configured : join39(projectPath, configured);
|
|
35601
36571
|
const rel = relative7(projectPath, absDir);
|
|
35602
36572
|
const relDir = rel === "" || rel.startsWith("..") ? null : rel.split(sep2).join("/");
|
|
35603
36573
|
return { absDir, relDir };
|
|
@@ -35606,7 +36576,7 @@ async function readDocsLock(absDir) {
|
|
|
35606
36576
|
const empty = { generated_at: "", libraries: {} };
|
|
35607
36577
|
let raw;
|
|
35608
36578
|
try {
|
|
35609
|
-
raw = await readFile27(
|
|
36579
|
+
raw = await readFile27(join39(absDir, LOCK_FILE), "utf-8");
|
|
35610
36580
|
} catch {
|
|
35611
36581
|
return empty;
|
|
35612
36582
|
}
|
|
@@ -35702,7 +36672,7 @@ function buildTopIndex(outcomes) {
|
|
|
35702
36672
|
}
|
|
35703
36673
|
async function ensureDocsGitignoreEntry(projectPath, relDir, dryRun) {
|
|
35704
36674
|
const entry = `/${relDir}/`;
|
|
35705
|
-
const gitignorePath =
|
|
36675
|
+
const gitignorePath = join39(projectPath, ".gitignore");
|
|
35706
36676
|
let existing = "";
|
|
35707
36677
|
try {
|
|
35708
36678
|
existing = await readFile27(gitignorePath, "utf-8");
|
|
@@ -35725,7 +36695,7 @@ async function markUncovered(dep, exactVersion, ctx) {
|
|
|
35725
36695
|
console.log(
|
|
35726
36696
|
` uncovered ${dep.name}@${exactVersion || "?"} \u2014 no docs in the library mirror`
|
|
35727
36697
|
);
|
|
35728
|
-
const libPath =
|
|
36698
|
+
const libPath = join39(ctx.absDir, libDirName(dep.name));
|
|
35729
36699
|
if (existsSync13(libPath)) {
|
|
35730
36700
|
if (ctx.dryRun) {
|
|
35731
36701
|
console.log(` would remove stale mirror dir ${libPath}`);
|
|
@@ -35778,14 +36748,14 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35778
36748
|
}
|
|
35779
36749
|
}
|
|
35780
36750
|
const lockEntry = ctx.lock.libraries[dep.name];
|
|
35781
|
-
const libPath =
|
|
35782
|
-
const versionPath =
|
|
36751
|
+
const libPath = join39(ctx.absDir, libDirName(dep.name));
|
|
36752
|
+
const versionPath = join39(libPath, manifest.resolved_version);
|
|
35783
36753
|
if (manifestMatchesLock(manifest, lockEntry)) {
|
|
35784
36754
|
console.log(` unchanged ${dep.name}@${manifest.resolved_version}`);
|
|
35785
|
-
if (!ctx.dryRun && !existsSync13(
|
|
36755
|
+
if (!ctx.dryRun && !existsSync13(join39(libPath, "INDEX.md"))) {
|
|
35786
36756
|
await mkdir12(libPath, { recursive: true });
|
|
35787
36757
|
await writeFile21(
|
|
35788
|
-
|
|
36758
|
+
join39(libPath, "INDEX.md"),
|
|
35789
36759
|
buildLibIndex(dep.name, manifest),
|
|
35790
36760
|
"utf-8"
|
|
35791
36761
|
);
|
|
@@ -35807,13 +36777,13 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35807
36777
|
);
|
|
35808
36778
|
continue;
|
|
35809
36779
|
}
|
|
35810
|
-
const target =
|
|
36780
|
+
const target = join39(versionPath, rel);
|
|
35811
36781
|
if (sameVersionLockFiles[file.path] === file.content_hash && existsSync13(target)) {
|
|
35812
36782
|
continue;
|
|
35813
36783
|
}
|
|
35814
36784
|
written++;
|
|
35815
36785
|
if (!ctx.dryRun) {
|
|
35816
|
-
await mkdir12(
|
|
36786
|
+
await mkdir12(dirname14(target), { recursive: true });
|
|
35817
36787
|
await writeFile21(target, file.content, "utf-8");
|
|
35818
36788
|
}
|
|
35819
36789
|
}
|
|
@@ -35825,7 +36795,7 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35825
36795
|
const rel = sanitizeDocPath(lockedPath);
|
|
35826
36796
|
if (rel === null) continue;
|
|
35827
36797
|
removedFiles++;
|
|
35828
|
-
if (!ctx.dryRun) await rm2(
|
|
36798
|
+
if (!ctx.dryRun) await rm2(join39(versionPath, rel), { force: true });
|
|
35829
36799
|
}
|
|
35830
36800
|
}
|
|
35831
36801
|
let removedVersionDirs = 0;
|
|
@@ -35840,13 +36810,13 @@ async function syncOneLibrary(dep, ctx) {
|
|
|
35840
36810
|
}
|
|
35841
36811
|
removedVersionDirs++;
|
|
35842
36812
|
if (!ctx.dryRun) {
|
|
35843
|
-
await rm2(
|
|
36813
|
+
await rm2(join39(libPath, entry.name), { recursive: true, force: true });
|
|
35844
36814
|
}
|
|
35845
36815
|
}
|
|
35846
36816
|
if (!ctx.dryRun) {
|
|
35847
36817
|
await mkdir12(libPath, { recursive: true });
|
|
35848
36818
|
await writeFile21(
|
|
35849
|
-
|
|
36819
|
+
join39(libPath, "INDEX.md"),
|
|
35850
36820
|
buildLibIndex(dep.name, manifest),
|
|
35851
36821
|
"utf-8"
|
|
35852
36822
|
);
|
|
@@ -35900,7 +36870,7 @@ async function runDocsSync() {
|
|
|
35900
36870
|
);
|
|
35901
36871
|
if (!dryRun) {
|
|
35902
36872
|
await mkdir12(absDir, { recursive: true });
|
|
35903
|
-
await writeFile21(
|
|
36873
|
+
await writeFile21(join39(absDir, "INDEX.md"), buildTopIndex(outcomes), "utf-8");
|
|
35904
36874
|
const libraries = {};
|
|
35905
36875
|
for (const o of outcomes) {
|
|
35906
36876
|
if (o.kind === "synced" || o.kind === "unchanged") {
|
|
@@ -35926,7 +36896,7 @@ async function runDocsSync() {
|
|
|
35926
36896
|
libraries: sortedLibraries
|
|
35927
36897
|
};
|
|
35928
36898
|
await writeFile21(
|
|
35929
|
-
|
|
36899
|
+
join39(absDir, LOCK_FILE),
|
|
35930
36900
|
JSON.stringify(newLock, null, 2) + "\n",
|
|
35931
36901
|
"utf-8"
|
|
35932
36902
|
);
|
|
@@ -35968,7 +36938,7 @@ async function countFilesRecursively(dirPath) {
|
|
|
35968
36938
|
let count = 0;
|
|
35969
36939
|
for (const entry of entries) {
|
|
35970
36940
|
if (entry.isDirectory()) {
|
|
35971
|
-
count += await countFilesRecursively(
|
|
36941
|
+
count += await countFilesRecursively(join39(dirPath, entry.name));
|
|
35972
36942
|
} else if (entry.isFile()) {
|
|
35973
36943
|
count++;
|
|
35974
36944
|
}
|
|
@@ -35985,7 +36955,7 @@ async function runDocsStatus() {
|
|
|
35985
36955
|
`);
|
|
35986
36956
|
let raw;
|
|
35987
36957
|
try {
|
|
35988
|
-
raw = await readFile27(
|
|
36958
|
+
raw = await readFile27(join39(absDir, LOCK_FILE), "utf-8");
|
|
35989
36959
|
} catch {
|
|
35990
36960
|
console.log(
|
|
35991
36961
|
` No ${LOCK_FILE} found \u2014 run \`codebyplan docs sync\` first.
|
|
@@ -36014,7 +36984,7 @@ async function runDocsStatus() {
|
|
|
36014
36984
|
let outOfSync = 0;
|
|
36015
36985
|
for (const name of names) {
|
|
36016
36986
|
const entry = lock.libraries[name];
|
|
36017
|
-
const versionPath =
|
|
36987
|
+
const versionPath = join39(absDir, libDirName(name), entry.resolved_version);
|
|
36018
36988
|
const expected = Object.keys(entry.files).length;
|
|
36019
36989
|
if (!existsSync13(versionPath)) {
|
|
36020
36990
|
outOfSync++;
|
|
@@ -36102,7 +37072,7 @@ var init_docs = __esm({
|
|
|
36102
37072
|
|
|
36103
37073
|
// src/lib/check-baseline.ts
|
|
36104
37074
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
36105
|
-
import { join as
|
|
37075
|
+
import { join as join40 } from "node:path";
|
|
36106
37076
|
function emptyBaseline() {
|
|
36107
37077
|
return {
|
|
36108
37078
|
lint: { known_failing: [] },
|
|
@@ -36112,7 +37082,7 @@ function emptyBaseline() {
|
|
|
36112
37082
|
};
|
|
36113
37083
|
}
|
|
36114
37084
|
function loadBaseline(projectRoot) {
|
|
36115
|
-
const filePath =
|
|
37085
|
+
const filePath = join40(projectRoot, BASELINE_FILENAME);
|
|
36116
37086
|
try {
|
|
36117
37087
|
const raw = readFileSync12(filePath, "utf-8");
|
|
36118
37088
|
const parsed = JSON.parse(raw);
|
|
@@ -36136,7 +37106,7 @@ function loadBaseline(projectRoot) {
|
|
|
36136
37106
|
}
|
|
36137
37107
|
}
|
|
36138
37108
|
function saveBaseline(projectRoot, baseline) {
|
|
36139
|
-
const filePath =
|
|
37109
|
+
const filePath = join40(projectRoot, BASELINE_FILENAME);
|
|
36140
37110
|
writeFileSync7(filePath, JSON.stringify(baseline, null, 2) + "\n", "utf-8");
|
|
36141
37111
|
}
|
|
36142
37112
|
function diffBaseline(check, currentFailingPackages, baseline) {
|
|
@@ -36186,8 +37156,8 @@ var init_check_baseline = __esm({
|
|
|
36186
37156
|
|
|
36187
37157
|
// src/lib/check.ts
|
|
36188
37158
|
import { readFileSync as readFileSync13, existsSync as existsSync14 } from "node:fs";
|
|
36189
|
-
import { join as
|
|
36190
|
-
import { spawnSync as
|
|
37159
|
+
import { join as join41 } from "node:path";
|
|
37160
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
36191
37161
|
function hasSentinelValue(arrays) {
|
|
36192
37162
|
const SENTINELS = /* @__PURE__ */ new Set([
|
|
36193
37163
|
SUMMARY_UNREADABLE,
|
|
@@ -36202,7 +37172,7 @@ function resolveNewFailures(check, failingPackages, baseline, updateBaseline, no
|
|
|
36202
37172
|
return diffBaseline(check, failingPackages, baseline);
|
|
36203
37173
|
}
|
|
36204
37174
|
function defaultSpawnFn(command, opts) {
|
|
36205
|
-
const result =
|
|
37175
|
+
const result = spawnSync13(command, {
|
|
36206
37176
|
shell: true,
|
|
36207
37177
|
cwd: opts.cwd,
|
|
36208
37178
|
encoding: "utf-8",
|
|
@@ -36254,9 +37224,9 @@ function parseFailingPackagesFromSummary(summaryPath) {
|
|
|
36254
37224
|
return Array.from(failing).sort();
|
|
36255
37225
|
}
|
|
36256
37226
|
function resolveTurboBin(projectRoot) {
|
|
36257
|
-
const localBin =
|
|
37227
|
+
const localBin = join41(projectRoot, "node_modules", ".bin", "turbo");
|
|
36258
37228
|
if (existsSync14(localBin)) return localBin;
|
|
36259
|
-
const workspaceRootBin =
|
|
37229
|
+
const workspaceRootBin = join41(
|
|
36260
37230
|
projectRoot,
|
|
36261
37231
|
"..",
|
|
36262
37232
|
"..",
|
|
@@ -36753,7 +37723,7 @@ var init_check2 = __esm({
|
|
|
36753
37723
|
|
|
36754
37724
|
// src/lib/claude-plan.ts
|
|
36755
37725
|
import * as fs13 from "node:fs";
|
|
36756
|
-
import * as
|
|
37726
|
+
import * as path15 from "node:path";
|
|
36757
37727
|
function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
36758
37728
|
const packaged = walkTemplates(templatesDir);
|
|
36759
37729
|
const packagedBySrc = new Map(packaged.map((f) => [f.src, f]));
|
|
@@ -36767,8 +37737,8 @@ function buildDriftPlan(projectDir, templatesDir, manifest) {
|
|
|
36767
37737
|
};
|
|
36768
37738
|
for (const pkg of packaged) {
|
|
36769
37739
|
const inManifest = manifestBySrc.get(pkg.src);
|
|
36770
|
-
const absDest =
|
|
36771
|
-
const absSrc =
|
|
37740
|
+
const absDest = path15.join(projectDir, ".claude", pkg.dest);
|
|
37741
|
+
const absSrc = path15.join(templatesDir, pkg.src);
|
|
36772
37742
|
if (!inManifest) {
|
|
36773
37743
|
plan.newOptIn.push({
|
|
36774
37744
|
packaged: { src: pkg.src, dest: pkg.dest, hash: pkg.hash },
|
|
@@ -36817,7 +37787,7 @@ __export(status_exports, {
|
|
|
36817
37787
|
runStatus: () => runStatus2
|
|
36818
37788
|
});
|
|
36819
37789
|
import * as fs14 from "node:fs";
|
|
36820
|
-
import * as
|
|
37790
|
+
import * as path16 from "node:path";
|
|
36821
37791
|
import { execSync as execSync9 } from "node:child_process";
|
|
36822
37792
|
function makeFailSafe(checked_at) {
|
|
36823
37793
|
return {
|
|
@@ -36926,12 +37896,12 @@ async function runStatus2(argv) {
|
|
|
36926
37896
|
const latest = fetchLatestVersion();
|
|
36927
37897
|
const newer = latest !== null && compareSemver(latest, installed) > 0;
|
|
36928
37898
|
let settings_drift = false;
|
|
36929
|
-
const settingsPath =
|
|
36930
|
-
const baseSettingsPath =
|
|
37899
|
+
const settingsPath = path16.join(projectDir, ".claude", "settings.json");
|
|
37900
|
+
const baseSettingsPath = path16.join(
|
|
36931
37901
|
templatesDir,
|
|
36932
37902
|
"settings.project.base.json"
|
|
36933
37903
|
);
|
|
36934
|
-
const hooksJsonPath =
|
|
37904
|
+
const hooksJsonPath = path16.join(templatesDir, "hooks", "hooks.json");
|
|
36935
37905
|
if (fs14.existsSync(settingsPath)) {
|
|
36936
37906
|
try {
|
|
36937
37907
|
const settingsRaw = fs14.readFileSync(settingsPath, "utf8");
|
|
@@ -37001,10 +37971,10 @@ function emitResult(result, writeCache, quiet, projectDir) {
|
|
|
37001
37971
|
const json = JSON.stringify(result, null, 2);
|
|
37002
37972
|
if (writeCache) {
|
|
37003
37973
|
try {
|
|
37004
|
-
const cacheDir =
|
|
37974
|
+
const cacheDir = path16.join(projectDir, ".codebyplan");
|
|
37005
37975
|
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
37006
37976
|
fs14.writeFileSync(
|
|
37007
|
-
|
|
37977
|
+
path16.join(cacheDir, "claude-status.local.json"),
|
|
37008
37978
|
json + "\n",
|
|
37009
37979
|
"utf8"
|
|
37010
37980
|
);
|
|
@@ -37148,7 +38118,7 @@ __export(update_exports, {
|
|
|
37148
38118
|
});
|
|
37149
38119
|
import * as fs15 from "node:fs";
|
|
37150
38120
|
import * as os3 from "node:os";
|
|
37151
|
-
import * as
|
|
38121
|
+
import * as path17 from "node:path";
|
|
37152
38122
|
async function runUpdate(opts, deps = {}) {
|
|
37153
38123
|
await Promise.resolve();
|
|
37154
38124
|
const scope = opts.scope ?? "project";
|
|
@@ -37184,9 +38154,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37184
38154
|
finalManifestEntries.push(e);
|
|
37185
38155
|
}
|
|
37186
38156
|
for (const { packaged, absSrc } of plan.overwriteSafe) {
|
|
37187
|
-
const absDest =
|
|
38157
|
+
const absDest = path17.join(projectDir, ".claude", packaged.dest);
|
|
37188
38158
|
if (!opts.dryRun) {
|
|
37189
|
-
fs15.mkdirSync(
|
|
38159
|
+
fs15.mkdirSync(path17.dirname(absDest), { recursive: true });
|
|
37190
38160
|
fs15.copyFileSync(absSrc, absDest);
|
|
37191
38161
|
if (opts.verbose) console.log(`updated ${packaged.dest}`);
|
|
37192
38162
|
} else if (opts.verbose) {
|
|
@@ -37199,7 +38169,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37199
38169
|
absSrc,
|
|
37200
38170
|
onDiskContent
|
|
37201
38171
|
} of plan.overwriteHandEdited) {
|
|
37202
|
-
const absDest =
|
|
38172
|
+
const absDest = path17.join(projectDir, ".claude", packaged.dest);
|
|
37203
38173
|
const newContent = fs15.readFileSync(absSrc);
|
|
37204
38174
|
const showDiff = () => {
|
|
37205
38175
|
console.log(
|
|
@@ -37212,7 +38182,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37212
38182
|
const answer = await promptOverwrite(packaged.dest, opts, showDiff);
|
|
37213
38183
|
if (answer === "overwrite") {
|
|
37214
38184
|
if (!opts.dryRun) {
|
|
37215
|
-
fs15.mkdirSync(
|
|
38185
|
+
fs15.mkdirSync(path17.dirname(absDest), { recursive: true });
|
|
37216
38186
|
fs15.copyFileSync(absSrc, absDest);
|
|
37217
38187
|
}
|
|
37218
38188
|
finalManifestEntries.push(packaged);
|
|
@@ -37228,9 +38198,9 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37228
38198
|
for (const { packaged, absSrc } of plan.newOptIn) {
|
|
37229
38199
|
const answer = await promptOptIn(packaged.dest, opts);
|
|
37230
38200
|
if (answer === "opt-in") {
|
|
37231
|
-
const absDest =
|
|
38201
|
+
const absDest = path17.join(projectDir, ".claude", packaged.dest);
|
|
37232
38202
|
if (!opts.dryRun) {
|
|
37233
|
-
fs15.mkdirSync(
|
|
38203
|
+
fs15.mkdirSync(path17.dirname(absDest), { recursive: true });
|
|
37234
38204
|
fs15.copyFileSync(absSrc, absDest);
|
|
37235
38205
|
}
|
|
37236
38206
|
finalManifestEntries.push(packaged);
|
|
@@ -37242,25 +38212,25 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37242
38212
|
for (const e of plan.removedFromPackage) {
|
|
37243
38213
|
const answer = await promptRemove(e.dest, opts);
|
|
37244
38214
|
if (answer === "remove") {
|
|
37245
|
-
const absDest =
|
|
38215
|
+
const absDest = path17.join(projectDir, ".claude", e.dest);
|
|
37246
38216
|
if (!opts.dryRun && fs15.existsSync(absDest)) {
|
|
37247
38217
|
fs15.rmSync(absDest);
|
|
37248
|
-
const claudeDir =
|
|
37249
|
-
let cur =
|
|
37250
|
-
while (cur !== claudeDir && cur !==
|
|
37251
|
-
if (
|
|
38218
|
+
const claudeDir = path17.join(projectDir, ".claude");
|
|
38219
|
+
let cur = path17.dirname(absDest);
|
|
38220
|
+
while (cur !== claudeDir && cur !== path17.dirname(cur)) {
|
|
38221
|
+
if (path17.dirname(cur) === claudeDir) break;
|
|
37252
38222
|
try {
|
|
37253
38223
|
fs15.rmdirSync(cur);
|
|
37254
38224
|
if (opts.verbose)
|
|
37255
38225
|
console.log(
|
|
37256
|
-
`pruned empty dir ${
|
|
38226
|
+
`pruned empty dir ${path17.relative(claudeDir, cur)}`
|
|
37257
38227
|
);
|
|
37258
|
-
cur =
|
|
38228
|
+
cur = path17.dirname(cur);
|
|
37259
38229
|
} catch (err) {
|
|
37260
38230
|
const code = err.code;
|
|
37261
38231
|
if (code !== "ENOTEMPTY" && code !== "ENOENT") {
|
|
37262
38232
|
console.warn(
|
|
37263
|
-
`codebyplan claude: could not prune empty dir ${
|
|
38233
|
+
`codebyplan claude: could not prune empty dir ${path17.relative(claudeDir, cur)}: ${err.message}`
|
|
37264
38234
|
);
|
|
37265
38235
|
}
|
|
37266
38236
|
break;
|
|
@@ -37272,12 +38242,12 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37272
38242
|
if (opts.verbose) console.log(`kept (untracked) ${e.dest}`);
|
|
37273
38243
|
}
|
|
37274
38244
|
}
|
|
37275
|
-
const hooksJsonPath =
|
|
37276
|
-
const baseSettingsPath =
|
|
38245
|
+
const hooksJsonPath = path17.join(templatesDir, "hooks", "hooks.json");
|
|
38246
|
+
const baseSettingsPath = path17.join(
|
|
37277
38247
|
templatesDir,
|
|
37278
38248
|
"settings.project.base.json"
|
|
37279
38249
|
);
|
|
37280
|
-
const settingsPath =
|
|
38250
|
+
const settingsPath = path17.join(projectDir, ".claude", "settings.json");
|
|
37281
38251
|
const existingSettings = fs15.existsSync(settingsPath) ? JSON.parse(fs15.readFileSync(settingsPath, "utf8")) : {};
|
|
37282
38252
|
if (fs15.existsSync(baseSettingsPath)) {
|
|
37283
38253
|
const base = JSON.parse(
|
|
@@ -37304,7 +38274,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37304
38274
|
deps.detectHealDeps
|
|
37305
38275
|
);
|
|
37306
38276
|
if (!opts.dryRun) {
|
|
37307
|
-
fs15.mkdirSync(
|
|
38277
|
+
fs15.mkdirSync(path17.dirname(settingsPath), { recursive: true });
|
|
37308
38278
|
fs15.writeFileSync(
|
|
37309
38279
|
settingsPath,
|
|
37310
38280
|
JSON.stringify(existingSettings, null, 2) + "\n",
|
|
@@ -37320,7 +38290,7 @@ async function runUpdate(opts, deps = {}) {
|
|
|
37320
38290
|
);
|
|
37321
38291
|
if (opts.verbose && gitignoreAction !== "unchanged") {
|
|
37322
38292
|
console.log(
|
|
37323
|
-
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${
|
|
38293
|
+
`${opts.dryRun ? "[dry-run] would " : ""}${gitignoreAction} managed .gitignore block in ${path17.relative(projectDir, path17.join(projectDir, ".gitignore"))}`
|
|
37324
38294
|
);
|
|
37325
38295
|
}
|
|
37326
38296
|
if (!opts.dryRun) {
|
|
@@ -37360,9 +38330,9 @@ function runUpdateUser(opts, deps) {
|
|
|
37360
38330
|
return;
|
|
37361
38331
|
}
|
|
37362
38332
|
try {
|
|
37363
|
-
const userDir = deps.userDir ??
|
|
37364
|
-
const settingsPath =
|
|
37365
|
-
const userBaseSettingsPath =
|
|
38333
|
+
const userDir = deps.userDir ?? path17.join(os3.homedir(), ".claude");
|
|
38334
|
+
const settingsPath = path17.join(userDir, "settings.json");
|
|
38335
|
+
const userBaseSettingsPath = path17.join(
|
|
37366
38336
|
templatesDir,
|
|
37367
38337
|
"settings.user.base.json"
|
|
37368
38338
|
);
|
|
@@ -37434,7 +38404,7 @@ __export(uninstall_exports, {
|
|
|
37434
38404
|
});
|
|
37435
38405
|
import * as fs16 from "node:fs";
|
|
37436
38406
|
import * as os4 from "node:os";
|
|
37437
|
-
import * as
|
|
38407
|
+
import * as path18 from "node:path";
|
|
37438
38408
|
async function runUninstall(opts, deps = {}) {
|
|
37439
38409
|
await Promise.resolve();
|
|
37440
38410
|
const scope = opts.scope ?? "project";
|
|
@@ -37463,7 +38433,7 @@ async function runUninstall(opts, deps = {}) {
|
|
|
37463
38433
|
let removed = 0;
|
|
37464
38434
|
let warnings = 0;
|
|
37465
38435
|
for (const entry of manifest.files) {
|
|
37466
|
-
const abs =
|
|
38436
|
+
const abs = path18.join(projectDir, ".claude", entry.dest);
|
|
37467
38437
|
if (!fs16.existsSync(abs)) {
|
|
37468
38438
|
console.warn(
|
|
37469
38439
|
`codebyplan claude uninstall: ${entry.dest} already absent (skipping).`
|
|
@@ -37487,12 +38457,12 @@ async function runUninstall(opts, deps = {}) {
|
|
|
37487
38457
|
if (!opts.dryRun) {
|
|
37488
38458
|
pruneEmptyManagedDirs(projectDir);
|
|
37489
38459
|
}
|
|
37490
|
-
const settingsPath =
|
|
38460
|
+
const settingsPath = path18.join(projectDir, ".claude", "settings.json");
|
|
37491
38461
|
if (fs16.existsSync(settingsPath)) {
|
|
37492
38462
|
const settings = JSON.parse(
|
|
37493
38463
|
fs16.readFileSync(settingsPath, "utf8")
|
|
37494
38464
|
);
|
|
37495
|
-
const baseSettingsPath = templatesDir ?
|
|
38465
|
+
const baseSettingsPath = templatesDir ? path18.join(templatesDir, "settings.project.base.json") : null;
|
|
37496
38466
|
if (baseSettingsPath && fs16.existsSync(baseSettingsPath)) {
|
|
37497
38467
|
const base = JSON.parse(
|
|
37498
38468
|
fs16.readFileSync(baseSettingsPath, "utf8")
|
|
@@ -37550,7 +38520,7 @@ function runUninstallUser(opts, deps) {
|
|
|
37550
38520
|
}
|
|
37551
38521
|
}
|
|
37552
38522
|
try {
|
|
37553
|
-
const userDir = deps.userDir ??
|
|
38523
|
+
const userDir = deps.userDir ?? path18.join(os4.homedir(), ".claude");
|
|
37554
38524
|
const existingManifest = readManifestForScope("user", userDir);
|
|
37555
38525
|
if (!existingManifest) {
|
|
37556
38526
|
console.error(
|
|
@@ -37559,12 +38529,12 @@ function runUninstallUser(opts, deps) {
|
|
|
37559
38529
|
process.exitCode = 1;
|
|
37560
38530
|
return;
|
|
37561
38531
|
}
|
|
37562
|
-
const settingsPath =
|
|
38532
|
+
const settingsPath = path18.join(userDir, "settings.json");
|
|
37563
38533
|
if (fs16.existsSync(settingsPath)) {
|
|
37564
38534
|
const settings = JSON.parse(
|
|
37565
38535
|
fs16.readFileSync(settingsPath, "utf8")
|
|
37566
38536
|
);
|
|
37567
|
-
const userBaseSettingsPath = templatesDir != null ?
|
|
38537
|
+
const userBaseSettingsPath = templatesDir != null ? path18.join(templatesDir, "settings.user.base.json") : null;
|
|
37568
38538
|
if (userBaseSettingsPath && fs16.existsSync(userBaseSettingsPath)) {
|
|
37569
38539
|
const userBase = JSON.parse(
|
|
37570
38540
|
fs16.readFileSync(userBaseSettingsPath, "utf8")
|
|
@@ -37605,7 +38575,7 @@ function runUninstallUser(opts, deps) {
|
|
|
37605
38575
|
function pruneEmptyManagedDirs(projectDir) {
|
|
37606
38576
|
const managedRoots = ["skills", "agents", "hooks", "rules"];
|
|
37607
38577
|
for (const root of managedRoots) {
|
|
37608
|
-
const abs =
|
|
38578
|
+
const abs = path18.join(projectDir, ".claude", root);
|
|
37609
38579
|
if (!fs16.existsSync(abs)) continue;
|
|
37610
38580
|
pruneLeafFirst(abs);
|
|
37611
38581
|
}
|
|
@@ -37616,7 +38586,7 @@ function pruneLeafFirst(dir) {
|
|
|
37616
38586
|
if (!stat3.isDirectory()) return;
|
|
37617
38587
|
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
37618
38588
|
if (entry.isDirectory()) {
|
|
37619
|
-
pruneLeafFirst(
|
|
38589
|
+
pruneLeafFirst(path18.join(dir, entry.name));
|
|
37620
38590
|
}
|
|
37621
38591
|
}
|
|
37622
38592
|
const remaining = fs16.readdirSync(dir);
|
|
@@ -37637,7 +38607,7 @@ var init_uninstall = __esm({
|
|
|
37637
38607
|
|
|
37638
38608
|
// src/lib/verify-parity.ts
|
|
37639
38609
|
import * as fs17 from "node:fs";
|
|
37640
|
-
import * as
|
|
38610
|
+
import * as path19 from "node:path";
|
|
37641
38611
|
function isValidScope(s) {
|
|
37642
38612
|
return s === "org-shared" || s === "project-shared" || REPO_ONLY_RE.test(s);
|
|
37643
38613
|
}
|
|
@@ -37654,25 +38624,25 @@ function checkSiblingParity(opts) {
|
|
|
37654
38624
|
expectedOneSided = DEFAULT_EXPECTED_ONE_SIDED,
|
|
37655
38625
|
ignoredSubtrees
|
|
37656
38626
|
} = opts;
|
|
37657
|
-
const defaultIgnored = [
|
|
38627
|
+
const defaultIgnored = [path19.join(claudeDir, "hooks", "__test-fixtures__")];
|
|
37658
38628
|
const ignored = ignoredSubtrees ?? defaultIgnored;
|
|
37659
38629
|
const violations = [];
|
|
37660
38630
|
const claudeSideRels = /* @__PURE__ */ new Set();
|
|
37661
38631
|
for (const scanDir of SCAN_DIRS) {
|
|
37662
|
-
const baseDir =
|
|
38632
|
+
const baseDir = path19.join(claudeDir, scanDir);
|
|
37663
38633
|
if (!fs17.existsSync(baseDir)) continue;
|
|
37664
38634
|
const entries = readdirRecursive(baseDir);
|
|
37665
38635
|
for (const entry of entries) {
|
|
37666
|
-
const absPath =
|
|
38636
|
+
const absPath = path19.join(baseDir, entry);
|
|
37667
38637
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37668
38638
|
if (ignored.some(
|
|
37669
|
-
(ig) => absPath.startsWith(ig +
|
|
38639
|
+
(ig) => absPath.startsWith(ig + path19.sep) || absPath === ig
|
|
37670
38640
|
)) {
|
|
37671
38641
|
continue;
|
|
37672
38642
|
}
|
|
37673
|
-
const relPath =
|
|
38643
|
+
const relPath = path19.join(scanDir, entry).split(path19.sep).join("/");
|
|
37674
38644
|
claudeSideRels.add(relPath);
|
|
37675
|
-
const templatePath =
|
|
38645
|
+
const templatePath = path19.join(templatesDir, relPath);
|
|
37676
38646
|
if (!fs17.existsSync(templatePath)) {
|
|
37677
38647
|
if (!expectedOneSided.has(relPath) && !isScaffoldFile(entry)) {
|
|
37678
38648
|
violations.push({ type: "missing-twin", path: relPath });
|
|
@@ -37687,14 +38657,14 @@ function checkSiblingParity(opts) {
|
|
|
37687
38657
|
}
|
|
37688
38658
|
}
|
|
37689
38659
|
for (const scanDir of SCAN_DIRS) {
|
|
37690
|
-
const tplBase =
|
|
38660
|
+
const tplBase = path19.join(templatesDir, scanDir);
|
|
37691
38661
|
if (!fs17.existsSync(tplBase)) continue;
|
|
37692
38662
|
const entries = readdirRecursive(tplBase);
|
|
37693
38663
|
for (const entry of entries) {
|
|
37694
|
-
const absPath =
|
|
38664
|
+
const absPath = path19.join(tplBase, entry);
|
|
37695
38665
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37696
38666
|
if (isScaffoldFile(entry)) continue;
|
|
37697
|
-
const relPath =
|
|
38667
|
+
const relPath = path19.join(scanDir, entry).split(path19.sep).join("/");
|
|
37698
38668
|
if (!claudeSideRels.has(relPath) && !expectedOneSided.has(relPath)) {
|
|
37699
38669
|
violations.push({ type: "extra-twin", path: relPath });
|
|
37700
38670
|
}
|
|
@@ -37730,18 +38700,18 @@ function checkScopeMarkers(opts) {
|
|
|
37730
38700
|
const twinDetectionActive = templatesDir != null && fs17.existsSync(templatesDir);
|
|
37731
38701
|
const violations = [];
|
|
37732
38702
|
for (const scanDir of scanDirs) {
|
|
37733
|
-
const baseDir =
|
|
38703
|
+
const baseDir = path19.join(claudeDir, scanDir);
|
|
37734
38704
|
if (!fs17.existsSync(baseDir)) continue;
|
|
37735
38705
|
const entries = readdirRecursive(baseDir);
|
|
37736
38706
|
for (const entry of entries) {
|
|
37737
|
-
const absPath =
|
|
38707
|
+
const absPath = path19.join(baseDir, entry);
|
|
37738
38708
|
if (!fs17.lstatSync(absPath).isFile()) continue;
|
|
37739
38709
|
if (!isStructuralEntry(scanDir, entry)) continue;
|
|
37740
|
-
const ext =
|
|
38710
|
+
const ext = path19.extname(entry).toLowerCase();
|
|
37741
38711
|
const isMd = ext === ".md";
|
|
37742
38712
|
const isSh = ext === ".sh";
|
|
37743
38713
|
if (!isMd && !isSh) continue;
|
|
37744
|
-
const relPath =
|
|
38714
|
+
const relPath = path19.join(scanDir, entry).split(path19.sep).join("/");
|
|
37745
38715
|
if (allowlist.has(relPath)) continue;
|
|
37746
38716
|
let content;
|
|
37747
38717
|
try {
|
|
@@ -37755,7 +38725,7 @@ function checkScopeMarkers(opts) {
|
|
|
37755
38725
|
continue;
|
|
37756
38726
|
}
|
|
37757
38727
|
const scopeValue = isMd ? extractFrontmatterScope(content) : extractShScope(content);
|
|
37758
|
-
const managed = twinDetectionActive && fs17.existsSync(
|
|
38728
|
+
const managed = twinDetectionActive && fs17.existsSync(path19.join(templatesDir, relPath));
|
|
37759
38729
|
if (managed) {
|
|
37760
38730
|
if (scopeValue === null) {
|
|
37761
38731
|
} else if (scopeValue === "org-shared") {
|
|
@@ -37809,7 +38779,7 @@ function readdirRecursive(dir, rel = "", visited = /* @__PURE__ */ new Set()) {
|
|
|
37809
38779
|
visited.add(realDir);
|
|
37810
38780
|
const results = [];
|
|
37811
38781
|
for (const name of fs17.readdirSync(dir)) {
|
|
37812
|
-
const full =
|
|
38782
|
+
const full = path19.join(dir, name);
|
|
37813
38783
|
const relName = rel ? `${rel}/${name}` : name;
|
|
37814
38784
|
if (fs17.lstatSync(full).isDirectory()) {
|
|
37815
38785
|
results.push(...readdirRecursive(full, relName, visited));
|
|
@@ -37882,12 +38852,12 @@ __export(verify_parity_exports, {
|
|
|
37882
38852
|
verifyParity: () => verifyParity
|
|
37883
38853
|
});
|
|
37884
38854
|
import * as fs18 from "node:fs";
|
|
37885
|
-
import * as
|
|
38855
|
+
import * as path20 from "node:path";
|
|
37886
38856
|
function verifyParity(args, deps = {}) {
|
|
37887
38857
|
const warnOnly = args.includes("--warn-only");
|
|
37888
38858
|
const jsonMode = args.includes("--json");
|
|
37889
38859
|
const projectDir = deps.cwd ?? process.cwd();
|
|
37890
|
-
const claudeDir =
|
|
38860
|
+
const claudeDir = path20.join(projectDir, ".claude");
|
|
37891
38861
|
if (!fs18.existsSync(claudeDir)) {
|
|
37892
38862
|
const msg = "codebyplan claude verify-parity: .claude/ not found in cwd \u2014 run from the project root.\n";
|
|
37893
38863
|
process.stderr.write(msg);
|
|
@@ -38395,7 +39365,7 @@ __export(generate_exports, {
|
|
|
38395
39365
|
runGenerate: () => runGenerate
|
|
38396
39366
|
});
|
|
38397
39367
|
import { readFile as readFile28, mkdir as mkdir13, writeFile as writeFile22 } from "node:fs/promises";
|
|
38398
|
-
import { join as
|
|
39368
|
+
import { join as join48, resolve as resolve11 } from "node:path";
|
|
38399
39369
|
async function readJsonFile4(filePath) {
|
|
38400
39370
|
try {
|
|
38401
39371
|
const raw = await readFile28(filePath, "utf-8");
|
|
@@ -38406,7 +39376,7 @@ async function readJsonFile4(filePath) {
|
|
|
38406
39376
|
}
|
|
38407
39377
|
async function readPkgName(absPath) {
|
|
38408
39378
|
try {
|
|
38409
|
-
const raw = await readFile28(
|
|
39379
|
+
const raw = await readFile28(join48(absPath, "package.json"), "utf-8");
|
|
38410
39380
|
const pkg = JSON.parse(raw);
|
|
38411
39381
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
38412
39382
|
} catch {
|
|
@@ -38420,7 +39390,7 @@ async function runGenerate(opts) {
|
|
|
38420
39390
|
const rootDir = resolve11(projectDir);
|
|
38421
39391
|
let packageManager;
|
|
38422
39392
|
try {
|
|
38423
|
-
const raw = await readFile28(
|
|
39393
|
+
const raw = await readFile28(join48(rootDir, "package.json"), "utf-8");
|
|
38424
39394
|
const pkg = JSON.parse(raw);
|
|
38425
39395
|
if (typeof pkg.packageManager === "string") {
|
|
38426
39396
|
packageManager = pkg.packageManager;
|
|
@@ -38428,7 +39398,7 @@ async function runGenerate(opts) {
|
|
|
38428
39398
|
} catch {
|
|
38429
39399
|
}
|
|
38430
39400
|
const serverJson = await readJsonFile4(
|
|
38431
|
-
|
|
39401
|
+
join48(rootDir, ".codebyplan", "server.json")
|
|
38432
39402
|
);
|
|
38433
39403
|
const ports = [];
|
|
38434
39404
|
for (const alloc of serverJson?.port_allocations ?? []) {
|
|
@@ -38441,7 +39411,7 @@ async function runGenerate(opts) {
|
|
|
38441
39411
|
}
|
|
38442
39412
|
}
|
|
38443
39413
|
const gitJson = await readJsonFile4(
|
|
38444
|
-
|
|
39414
|
+
join48(rootDir, ".codebyplan", "git.json")
|
|
38445
39415
|
);
|
|
38446
39416
|
const branchModel = gitJson?.branch_config?.production ? {
|
|
38447
39417
|
production: gitJson.branch_config.production,
|
|
@@ -38450,7 +39420,7 @@ async function runGenerate(opts) {
|
|
|
38450
39420
|
)
|
|
38451
39421
|
} : void 0;
|
|
38452
39422
|
const shipmentJson = await readJsonFile4(
|
|
38453
|
-
|
|
39423
|
+
join48(rootDir, ".codebyplan", "shipment.json")
|
|
38454
39424
|
);
|
|
38455
39425
|
const shipmentSurfaces = [];
|
|
38456
39426
|
const rawSurfaces = shipmentJson?.shipment?.surfaces ?? shipmentJson?.surfaces ?? {};
|
|
@@ -38521,7 +39491,7 @@ async function runGenerate(opts) {
|
|
|
38521
39491
|
const structureMdContent = generateStructureMd(config);
|
|
38522
39492
|
const agentsContent = generateAgentsMd(structureMdContent);
|
|
38523
39493
|
if (check) {
|
|
38524
|
-
const agentsMdPath2 =
|
|
39494
|
+
const agentsMdPath2 = join48(rootDir, "AGENTS.md");
|
|
38525
39495
|
let existingAgents = null;
|
|
38526
39496
|
try {
|
|
38527
39497
|
existingAgents = await readFile28(agentsMdPath2, "utf-8");
|
|
@@ -38560,13 +39530,13 @@ async function runGenerate(opts) {
|
|
|
38560
39530
|
process.stdout.write(agentsContent);
|
|
38561
39531
|
return;
|
|
38562
39532
|
}
|
|
38563
|
-
const outputDir =
|
|
39533
|
+
const outputDir = join48(rootDir, ".claude", "generated");
|
|
38564
39534
|
await mkdir13(outputDir, { recursive: true });
|
|
38565
|
-
const outputPath =
|
|
39535
|
+
const outputPath = join48(outputDir, "structure.md");
|
|
38566
39536
|
await writeFile22(outputPath, structureMdContent, "utf-8");
|
|
38567
39537
|
process.stdout.write(`Wrote: .claude/generated/structure.md
|
|
38568
39538
|
`);
|
|
38569
|
-
const agentsMdPath =
|
|
39539
|
+
const agentsMdPath = join48(rootDir, "AGENTS.md");
|
|
38570
39540
|
let existingAgentsContent = null;
|
|
38571
39541
|
try {
|
|
38572
39542
|
existingAgentsContent = await readFile28(agentsMdPath, "utf-8");
|
|
@@ -38598,7 +39568,7 @@ __export(readme_exports, {
|
|
|
38598
39568
|
runReadmeCommand: () => runReadmeCommand
|
|
38599
39569
|
});
|
|
38600
39570
|
import { readFile as readFile29, writeFile as writeFile23 } from "node:fs/promises";
|
|
38601
|
-
import { join as
|
|
39571
|
+
import { join as join49, resolve as resolve12, relative as relative9 } from "node:path";
|
|
38602
39572
|
async function readJsonFile5(filePath) {
|
|
38603
39573
|
try {
|
|
38604
39574
|
const raw = await readFile29(filePath, "utf-8");
|
|
@@ -38670,7 +39640,7 @@ async function discoverUnits(rootDir, rootPkgJson) {
|
|
|
38670
39640
|
const discovered = await discoverMonorepoApps(rootDir);
|
|
38671
39641
|
for (const app of discovered) {
|
|
38672
39642
|
const pkgJson = await readJsonFile5(
|
|
38673
|
-
|
|
39643
|
+
join49(app.absPath, "package.json")
|
|
38674
39644
|
);
|
|
38675
39645
|
pkgJsonByPath.set(app.absPath, pkgJson);
|
|
38676
39646
|
allPackages.push({
|
|
@@ -38696,7 +39666,7 @@ async function runReadme(opts) {
|
|
|
38696
39666
|
const init = opts.init ?? opts["init"] ?? false;
|
|
38697
39667
|
const rootDir = resolve12(projectDir);
|
|
38698
39668
|
const rootPkgJson = await readJsonFile5(
|
|
38699
|
-
|
|
39669
|
+
join49(rootDir, "package.json")
|
|
38700
39670
|
);
|
|
38701
39671
|
const { units, allPackages, pkgJsonByPath } = await discoverUnits(
|
|
38702
39672
|
rootDir,
|
|
@@ -38705,8 +39675,8 @@ async function runReadme(opts) {
|
|
|
38705
39675
|
const driftUnits = [];
|
|
38706
39676
|
const missingUnits = [];
|
|
38707
39677
|
for (const unit of units) {
|
|
38708
|
-
const readmePath =
|
|
38709
|
-
const relPath = unit.isRoot ? "README.md" :
|
|
39678
|
+
const readmePath = join49(unit.absPath, "README.md");
|
|
39679
|
+
const relPath = unit.isRoot ? "README.md" : join49(relative9(rootDir, unit.absPath), "README.md");
|
|
38710
39680
|
let existingContent = null;
|
|
38711
39681
|
try {
|
|
38712
39682
|
existingContent = await readFile29(readmePath, "utf-8");
|
|
@@ -38897,7 +39867,7 @@ import {
|
|
|
38897
39867
|
readdir as readdir7
|
|
38898
39868
|
} from "node:fs/promises";
|
|
38899
39869
|
import { existsSync as existsSync21 } from "node:fs";
|
|
38900
|
-
import { join as
|
|
39870
|
+
import { join as join50, resolve as resolve13, dirname as dirname16, sep as sep4 } from "node:path";
|
|
38901
39871
|
import { homedir as homedir8 } from "node:os";
|
|
38902
39872
|
function encodeProjectPath(absPath) {
|
|
38903
39873
|
return resolve13(absPath).replace(/[/\\]/g, "-");
|
|
@@ -38908,7 +39878,7 @@ function resolveAutoMemoryDir(opts) {
|
|
|
38908
39878
|
}
|
|
38909
39879
|
const projectDir = opts.projectDir ?? process.cwd();
|
|
38910
39880
|
const encoded = encodeProjectPath(projectDir);
|
|
38911
|
-
return
|
|
39881
|
+
return join50(homedir8(), ".claude", "projects", encoded, "memory");
|
|
38912
39882
|
}
|
|
38913
39883
|
function parseFrontmatter(content) {
|
|
38914
39884
|
content = content.replace(/\r\n/g, "\n");
|
|
@@ -38974,7 +39944,7 @@ async function inventoryFiles(dir) {
|
|
|
38974
39944
|
}
|
|
38975
39945
|
const results = [];
|
|
38976
39946
|
for (const filename of filenames) {
|
|
38977
|
-
const sourcePath =
|
|
39947
|
+
const sourcePath = join50(dir, filename);
|
|
38978
39948
|
let raw;
|
|
38979
39949
|
try {
|
|
38980
39950
|
raw = await readFile30(sourcePath, "utf-8");
|
|
@@ -39063,8 +40033,8 @@ async function applyPlan(plan, opts) {
|
|
|
39063
40033
|
if (entry.suggested_action !== "keep") continue;
|
|
39064
40034
|
if (!entry.suggested_target?.startsWith("nested:")) continue;
|
|
39065
40035
|
const relPath = entry.suggested_target.slice("nested:".length);
|
|
39066
|
-
const targetDir = resolve13(
|
|
39067
|
-
const targetFile =
|
|
40036
|
+
const targetDir = resolve13(join50(projectDir, relPath));
|
|
40037
|
+
const targetFile = join50(targetDir, "CLAUDE.md");
|
|
39068
40038
|
if (!targetDir.startsWith(resolve13(projectDir) + sep4)) {
|
|
39069
40039
|
process.stderr.write(
|
|
39070
40040
|
`migrate-memory: skipping unsafe suggested_target "${entry.suggested_target}" \u2014 resolves outside projectDir
|
|
@@ -39114,7 +40084,7 @@ ${anchor}
|
|
|
39114
40084
|
);
|
|
39115
40085
|
}
|
|
39116
40086
|
}
|
|
39117
|
-
const rootClaudeMd =
|
|
40087
|
+
const rootClaudeMd = join50(projectDir, ".claude", "CLAUDE.md");
|
|
39118
40088
|
if (dryRun) {
|
|
39119
40089
|
process.stdout.write(
|
|
39120
40090
|
`[dry-run] Would ensure ${rootClaudeMd} contains: ${IMPORT_LINE}
|
|
@@ -39125,7 +40095,7 @@ ${anchor}
|
|
|
39125
40095
|
try {
|
|
39126
40096
|
claudeMdContent = await readFile30(rootClaudeMd, "utf-8");
|
|
39127
40097
|
} catch {
|
|
39128
|
-
await mkdir14(
|
|
40098
|
+
await mkdir14(dirname16(rootClaudeMd), { recursive: true });
|
|
39129
40099
|
}
|
|
39130
40100
|
if (!claudeMdContent.includes(IMPORT_LINE)) {
|
|
39131
40101
|
await writeFile24(
|
|
@@ -39158,8 +40128,8 @@ ${IMPORT_LINE}
|
|
|
39158
40128
|
} catch {
|
|
39159
40129
|
}
|
|
39160
40130
|
}
|
|
39161
|
-
const memoryMd =
|
|
39162
|
-
const safeRmdirBase =
|
|
40131
|
+
const memoryMd = join50(plan.auto_memory_dir, "MEMORY.md");
|
|
40132
|
+
const safeRmdirBase = join50(homedir8(), ".claude", "projects");
|
|
39163
40133
|
if (dryRun) {
|
|
39164
40134
|
process.stdout.write(`[dry-run] Would delete MEMORY.md: ${memoryMd}
|
|
39165
40135
|
`);
|
|
@@ -39283,7 +40253,7 @@ var init_migrate_memory = __esm({
|
|
|
39283
40253
|
|
|
39284
40254
|
// src/lib/claude-mode-audit.ts
|
|
39285
40255
|
import { readdirSync as readdirSync7, readFileSync as readFileSync19, existsSync as existsSync22 } from "node:fs";
|
|
39286
|
-
import { join as
|
|
40256
|
+
import { join as join51, basename as basename3 } from "node:path";
|
|
39287
40257
|
function parseFrontmatter2(content) {
|
|
39288
40258
|
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
39289
40259
|
if (!match) return {};
|
|
@@ -39303,7 +40273,7 @@ function parseFrontmatter2(content) {
|
|
|
39303
40273
|
function auditAgent(filePath) {
|
|
39304
40274
|
const content = readFileSync19(filePath, "utf-8");
|
|
39305
40275
|
const fm = parseFrontmatter2(content);
|
|
39306
|
-
const agentName = fm.name ??
|
|
40276
|
+
const agentName = fm.name ?? basename3(filePath, ".md");
|
|
39307
40277
|
const expected = AGENT_EXCEPTIONS[agentName] ?? AGENT_DEFAULT;
|
|
39308
40278
|
const expectedStr = `model:${expected.model}/effort:${expected.effort}`;
|
|
39309
40279
|
const model = fm.model ?? null;
|
|
@@ -39360,19 +40330,19 @@ function auditSkill(filePath) {
|
|
|
39360
40330
|
}
|
|
39361
40331
|
function auditMode(templatesDir) {
|
|
39362
40332
|
const entries = [];
|
|
39363
|
-
const agentsDir =
|
|
40333
|
+
const agentsDir = join51(templatesDir, "agents");
|
|
39364
40334
|
if (existsSync22(agentsDir)) {
|
|
39365
40335
|
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md")).sort();
|
|
39366
40336
|
for (const f of agentFiles) {
|
|
39367
|
-
entries.push(auditAgent(
|
|
40337
|
+
entries.push(auditAgent(join51(agentsDir, f)));
|
|
39368
40338
|
}
|
|
39369
40339
|
}
|
|
39370
|
-
const skillsDir =
|
|
40340
|
+
const skillsDir = join51(templatesDir, "skills");
|
|
39371
40341
|
if (existsSync22(skillsDir)) {
|
|
39372
40342
|
const skillDirs = readdirSync7(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
39373
40343
|
for (const dir of skillDirs) {
|
|
39374
|
-
if (existsSync22(
|
|
39375
|
-
const skillMd =
|
|
40344
|
+
if (existsSync22(join51(skillsDir, dir, "PROVENANCE.md"))) continue;
|
|
40345
|
+
const skillMd = join51(skillsDir, dir, "SKILL.md");
|
|
39376
40346
|
if (existsSync22(skillMd)) {
|
|
39377
40347
|
entries.push(auditSkill(skillMd));
|
|
39378
40348
|
}
|
|
@@ -39477,9 +40447,9 @@ var resolve_preview_exports = {};
|
|
|
39477
40447
|
__export(resolve_preview_exports, {
|
|
39478
40448
|
resolvePreview: () => resolvePreview
|
|
39479
40449
|
});
|
|
39480
|
-
import { spawnSync as
|
|
40450
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
39481
40451
|
function defaultGetCurrentBranch(cwd) {
|
|
39482
|
-
const result =
|
|
40452
|
+
const result = spawnSync14("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
39483
40453
|
cwd,
|
|
39484
40454
|
encoding: "utf-8",
|
|
39485
40455
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -39631,7 +40601,7 @@ __export(new_migration_exports, {
|
|
|
39631
40601
|
newMigration: () => newMigration
|
|
39632
40602
|
});
|
|
39633
40603
|
import * as fs19 from "node:fs";
|
|
39634
|
-
import * as
|
|
40604
|
+
import * as path21 from "node:path";
|
|
39635
40605
|
function slugify(name) {
|
|
39636
40606
|
return name.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").replace(/_+/g, "_");
|
|
39637
40607
|
}
|
|
@@ -39652,9 +40622,9 @@ function newMigration(args, deps = {}) {
|
|
|
39652
40622
|
}
|
|
39653
40623
|
const slug = slugify(rawName);
|
|
39654
40624
|
const stamp = genTimestamp({ cwd });
|
|
39655
|
-
const migrationsDir =
|
|
40625
|
+
const migrationsDir = path21.join(cwd, "supabase", "migrations");
|
|
39656
40626
|
const filename = `${stamp}_${slug}.sql`;
|
|
39657
|
-
const filePath =
|
|
40627
|
+
const filePath = path21.join(migrationsDir, filename);
|
|
39658
40628
|
mkdirSync11(migrationsDir, { recursive: true });
|
|
39659
40629
|
writeFileSync12(filePath, "");
|
|
39660
40630
|
process.stdout.write(JSON.stringify({ path: filePath }) + "\n");
|
|
@@ -39672,9 +40642,9 @@ var preview_check_exports = {};
|
|
|
39672
40642
|
__export(preview_check_exports, {
|
|
39673
40643
|
previewCheck: () => previewCheck
|
|
39674
40644
|
});
|
|
39675
|
-
import { spawnSync as
|
|
39676
|
-
function
|
|
39677
|
-
const result =
|
|
40645
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
40646
|
+
function defaultRun4(cmd, args) {
|
|
40647
|
+
const result = spawnSync15(cmd, args, {
|
|
39678
40648
|
encoding: "utf-8",
|
|
39679
40649
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39680
40650
|
});
|
|
@@ -39699,7 +40669,7 @@ function defaultGetPrNumber(cwd, run) {
|
|
|
39699
40669
|
}
|
|
39700
40670
|
async function previewCheck(args, deps = {}) {
|
|
39701
40671
|
const cwd = deps.cwd ?? process.cwd();
|
|
39702
|
-
const run = deps.run ??
|
|
40672
|
+
const run = deps.run ?? defaultRun4;
|
|
39703
40673
|
const sleep3 = deps.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
39704
40674
|
const getPrNumber = deps.getPrNumber ?? defaultGetPrNumber;
|
|
39705
40675
|
const poll = deps.pollCheck ?? pollGhPreviewCheck;
|
|
@@ -39728,313 +40698,6 @@ var init_preview_check = __esm({
|
|
|
39728
40698
|
}
|
|
39729
40699
|
});
|
|
39730
40700
|
|
|
39731
|
-
// src/lib/session.ts
|
|
39732
|
-
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
39733
|
-
import * as path21 from "node:path";
|
|
39734
|
-
function defaultRun4(cmd, args, cwd) {
|
|
39735
|
-
const result = spawnSync14(cmd, args, {
|
|
39736
|
-
cwd,
|
|
39737
|
-
encoding: "utf-8",
|
|
39738
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
39739
|
-
});
|
|
39740
|
-
if (result.error) throw result.error;
|
|
39741
|
-
if (result.status !== 0) {
|
|
39742
|
-
const stderr = (result.stderr ?? "").toString().trim();
|
|
39743
|
-
throw new Error(
|
|
39744
|
-
`${cmd} ${args.join(" ")} exited ${result.status ?? "null"}${stderr ? `: ${stderr}` : ""}`
|
|
39745
|
-
);
|
|
39746
|
-
}
|
|
39747
|
-
return (result.stdout ?? "").toString();
|
|
39748
|
-
}
|
|
39749
|
-
function homeFf(opts = {}) {
|
|
39750
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
39751
|
-
const run = opts.run ?? defaultRun4;
|
|
39752
|
-
const gitCfg = readGitConfig(cwd);
|
|
39753
|
-
const production = gitCfg.production;
|
|
39754
|
-
let repoRoot;
|
|
39755
|
-
try {
|
|
39756
|
-
repoRoot = run("git", ["rev-parse", "--show-toplevel"], cwd).trim();
|
|
39757
|
-
} catch {
|
|
39758
|
-
return {
|
|
39759
|
-
result: "skipped",
|
|
39760
|
-
reason: "git rev-parse --show-toplevel failed"
|
|
39761
|
-
};
|
|
39762
|
-
}
|
|
39763
|
-
const folder = path21.basename(repoRoot);
|
|
39764
|
-
let current;
|
|
39765
|
-
try {
|
|
39766
|
-
current = run("git", ["rev-parse", "--abbrev-ref", "HEAD"], cwd).trim();
|
|
39767
|
-
} catch {
|
|
39768
|
-
return {
|
|
39769
|
-
result: "skipped",
|
|
39770
|
-
reason: "git rev-parse --abbrev-ref HEAD failed"
|
|
39771
|
-
};
|
|
39772
|
-
}
|
|
39773
|
-
if (current !== folder) {
|
|
39774
|
-
return { result: "skipped", reason: "not on home branch" };
|
|
39775
|
-
}
|
|
39776
|
-
try {
|
|
39777
|
-
run("git", ["fetch", "origin", production], cwd);
|
|
39778
|
-
} catch {
|
|
39779
|
-
return {
|
|
39780
|
-
result: "warn",
|
|
39781
|
-
warn: `fetch failed \u2014 staying on local ${current}`
|
|
39782
|
-
};
|
|
39783
|
-
}
|
|
39784
|
-
try {
|
|
39785
|
-
run("git", ["merge", "--ff-only", `origin/${production}`], cwd);
|
|
39786
|
-
} catch {
|
|
39787
|
-
return {
|
|
39788
|
-
result: "warn",
|
|
39789
|
-
warn: `${current} not fast-forwardable (ahead/diverged) \u2014 left untouched`
|
|
39790
|
-
};
|
|
39791
|
-
}
|
|
39792
|
-
return { result: "fast_forwarded" };
|
|
39793
|
-
}
|
|
39794
|
-
function spawnVersionStatus(cwd) {
|
|
39795
|
-
try {
|
|
39796
|
-
const result = spawnSync14("npx", ["codebyplan", "version-status"], {
|
|
39797
|
-
cwd,
|
|
39798
|
-
encoding: "utf-8",
|
|
39799
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
39800
|
-
});
|
|
39801
|
-
if (result.error) return null;
|
|
39802
|
-
const raw = (result.stdout ?? "").toString().trim();
|
|
39803
|
-
if (!raw) return null;
|
|
39804
|
-
const parsed = JSON.parse(raw);
|
|
39805
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
39806
|
-
return null;
|
|
39807
|
-
}
|
|
39808
|
-
const obj = parsed;
|
|
39809
|
-
if (typeof obj["installed"] !== "string" || typeof obj["newer"] !== "boolean" || typeof obj["guarded"] !== "boolean" || typeof obj["installCommand"] !== "string") {
|
|
39810
|
-
return null;
|
|
39811
|
-
}
|
|
39812
|
-
return {
|
|
39813
|
-
installed: obj["installed"],
|
|
39814
|
-
latest: typeof obj["latest"] === "string" ? obj["latest"] : null,
|
|
39815
|
-
newer: obj["newer"],
|
|
39816
|
-
packageManager: typeof obj["packageManager"] === "string" ? obj["packageManager"] : "npm",
|
|
39817
|
-
installCommand: obj["installCommand"],
|
|
39818
|
-
guarded: obj["guarded"],
|
|
39819
|
-
guardReason: typeof obj["guardReason"] === "string" ? obj["guardReason"] : null
|
|
39820
|
-
};
|
|
39821
|
-
} catch {
|
|
39822
|
-
return null;
|
|
39823
|
-
}
|
|
39824
|
-
}
|
|
39825
|
-
function defaultRunInstall(installCommand, cwd) {
|
|
39826
|
-
const parts = installCommand.trim().split(/\s+/);
|
|
39827
|
-
const cmd = parts[0];
|
|
39828
|
-
const args = parts.slice(1);
|
|
39829
|
-
if (!cmd) throw new Error("empty installCommand");
|
|
39830
|
-
const result = spawnSync14(cmd, args, {
|
|
39831
|
-
cwd,
|
|
39832
|
-
encoding: "utf-8",
|
|
39833
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
39834
|
-
});
|
|
39835
|
-
if (result.error) throw result.error;
|
|
39836
|
-
if (result.status !== 0) {
|
|
39837
|
-
const stderr = (result.stderr ?? "").toString().trim();
|
|
39838
|
-
throw new Error(
|
|
39839
|
-
`install exited ${result.status}${stderr ? `: ${stderr}` : ""}`
|
|
39840
|
-
);
|
|
39841
|
-
}
|
|
39842
|
-
}
|
|
39843
|
-
function defaultRunClaudeUpdate(cwd) {
|
|
39844
|
-
const result = spawnSync14("npx", ["codebyplan", "claude", "update", "--yes"], {
|
|
39845
|
-
cwd,
|
|
39846
|
-
encoding: "utf-8",
|
|
39847
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
39848
|
-
});
|
|
39849
|
-
if (result.error) throw result.error;
|
|
39850
|
-
if (result.status !== 0) {
|
|
39851
|
-
const stderr = (result.stderr ?? "").toString().trim();
|
|
39852
|
-
throw new Error(
|
|
39853
|
-
`claude update exited ${result.status}${stderr ? `: ${stderr}` : ""}`
|
|
39854
|
-
);
|
|
39855
|
-
}
|
|
39856
|
-
}
|
|
39857
|
-
function defaultRunGitStatus(cwd) {
|
|
39858
|
-
const result = spawnSync14(
|
|
39859
|
-
"git",
|
|
39860
|
-
["status", "--porcelain", "--", ".claude/", ".codebyplan/"],
|
|
39861
|
-
{
|
|
39862
|
-
cwd,
|
|
39863
|
-
encoding: "utf-8",
|
|
39864
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
39865
|
-
}
|
|
39866
|
-
);
|
|
39867
|
-
if (result.error) throw result.error;
|
|
39868
|
-
return (result.stdout ?? "").toString();
|
|
39869
|
-
}
|
|
39870
|
-
async function freshnessGate(opts = {}) {
|
|
39871
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
39872
|
-
const probeVersionStatus = opts.probeVersionStatus ?? ((c) => spawnVersionStatus(c));
|
|
39873
|
-
const runInstall2 = opts.runInstall ?? defaultRunInstall;
|
|
39874
|
-
const runClaudeUpdate = opts.runClaudeUpdate ?? defaultRunClaudeUpdate;
|
|
39875
|
-
const runGitStatus = opts.runGitStatus ?? defaultRunGitStatus;
|
|
39876
|
-
const haltOnUpdate = opts.haltOnUpdate ?? false;
|
|
39877
|
-
let probe;
|
|
39878
|
-
try {
|
|
39879
|
-
probe = probeVersionStatus(cwd);
|
|
39880
|
-
} catch {
|
|
39881
|
-
probe = null;
|
|
39882
|
-
}
|
|
39883
|
-
if (!probe) {
|
|
39884
|
-
return { result: "skipped", reason: "probe failed (fail-safe)" };
|
|
39885
|
-
}
|
|
39886
|
-
if (probe.guarded) {
|
|
39887
|
-
return { result: "guarded" };
|
|
39888
|
-
}
|
|
39889
|
-
if (!probe.newer) {
|
|
39890
|
-
return { result: "up_to_date" };
|
|
39891
|
-
}
|
|
39892
|
-
try {
|
|
39893
|
-
runInstall2(probe.installCommand, cwd);
|
|
39894
|
-
} catch (err) {
|
|
39895
|
-
const reason = err instanceof Error ? err.message : "install failed (unknown error)";
|
|
39896
|
-
return { result: "error", reason };
|
|
39897
|
-
}
|
|
39898
|
-
try {
|
|
39899
|
-
runClaudeUpdate(cwd);
|
|
39900
|
-
} catch (err) {
|
|
39901
|
-
const reason = err instanceof Error ? err.message : "claude update failed (unknown error)";
|
|
39902
|
-
return { result: "error", reason };
|
|
39903
|
-
}
|
|
39904
|
-
let gitStatusOutput = "";
|
|
39905
|
-
try {
|
|
39906
|
-
gitStatusOutput = runGitStatus(cwd);
|
|
39907
|
-
} catch {
|
|
39908
|
-
gitStatusOutput = "";
|
|
39909
|
-
}
|
|
39910
|
-
const changedFiles = gitStatusOutput.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
39911
|
-
const parts = line.split(/\s+/);
|
|
39912
|
-
return parts.slice(1).join(" ");
|
|
39913
|
-
}).filter(Boolean);
|
|
39914
|
-
return {
|
|
39915
|
-
result: "updated",
|
|
39916
|
-
latest: probe.latest ?? probe.installed,
|
|
39917
|
-
changed_files: changedFiles,
|
|
39918
|
-
halt: haltOnUpdate
|
|
39919
|
-
};
|
|
39920
|
-
}
|
|
39921
|
-
async function infraFiles(opts = {}) {
|
|
39922
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
39923
|
-
const run = opts.run ?? defaultRun4;
|
|
39924
|
-
const getTaskFiles = opts.getTaskFiles ?? (() => Promise.resolve([]));
|
|
39925
|
-
let firstOutput;
|
|
39926
|
-
try {
|
|
39927
|
-
firstOutput = run("git", ["status", "--porcelain"], cwd);
|
|
39928
|
-
} catch {
|
|
39929
|
-
firstOutput = "";
|
|
39930
|
-
}
|
|
39931
|
-
const firstChanged = parseGitStatus2(firstOutput);
|
|
39932
|
-
if (firstChanged.length === 0) {
|
|
39933
|
-
return { infra_files: [], task_files: [], note: "clean tree" };
|
|
39934
|
-
}
|
|
39935
|
-
const taskFiles = await getTaskFiles();
|
|
39936
|
-
const taskSet = new Set(taskFiles);
|
|
39937
|
-
let secondOutput;
|
|
39938
|
-
try {
|
|
39939
|
-
secondOutput = run("git", ["status", "--porcelain"], cwd);
|
|
39940
|
-
} catch {
|
|
39941
|
-
secondOutput = "";
|
|
39942
|
-
}
|
|
39943
|
-
const freshChanged = parseGitStatus2(secondOutput);
|
|
39944
|
-
const infraFilesList = freshChanged.filter((f) => !taskSet.has(f));
|
|
39945
|
-
return {
|
|
39946
|
-
infra_files: infraFilesList,
|
|
39947
|
-
task_files: taskFiles
|
|
39948
|
-
};
|
|
39949
|
-
}
|
|
39950
|
-
function parseGitStatus2(output) {
|
|
39951
|
-
return output.split("\n").filter(Boolean).map((line) => {
|
|
39952
|
-
if (line.length > 3) {
|
|
39953
|
-
const rest = line.slice(3);
|
|
39954
|
-
const arrow = rest.indexOf(" -> ");
|
|
39955
|
-
if (arrow !== -1) {
|
|
39956
|
-
return rest.slice(arrow + 4).trim();
|
|
39957
|
-
}
|
|
39958
|
-
return rest.trim();
|
|
39959
|
-
}
|
|
39960
|
-
return "";
|
|
39961
|
-
}).filter(Boolean);
|
|
39962
|
-
}
|
|
39963
|
-
var init_session2 = __esm({
|
|
39964
|
-
"src/lib/session.ts"() {
|
|
39965
|
-
"use strict";
|
|
39966
|
-
init_supabase();
|
|
39967
|
-
}
|
|
39968
|
-
});
|
|
39969
|
-
|
|
39970
|
-
// src/cli/session/home-ff.ts
|
|
39971
|
-
var home_ff_exports = {};
|
|
39972
|
-
__export(home_ff_exports, {
|
|
39973
|
-
homeFfCli: () => homeFfCli
|
|
39974
|
-
});
|
|
39975
|
-
function homeFfCli(_args, deps = {}) {
|
|
39976
|
-
const result = homeFf(deps);
|
|
39977
|
-
process.stdout.write(JSON.stringify(result) + "\n");
|
|
39978
|
-
return 0;
|
|
39979
|
-
}
|
|
39980
|
-
var init_home_ff = __esm({
|
|
39981
|
-
"src/cli/session/home-ff.ts"() {
|
|
39982
|
-
"use strict";
|
|
39983
|
-
init_session2();
|
|
39984
|
-
}
|
|
39985
|
-
});
|
|
39986
|
-
|
|
39987
|
-
// src/cli/session/freshness-gate.ts
|
|
39988
|
-
var freshness_gate_exports = {};
|
|
39989
|
-
__export(freshness_gate_exports, {
|
|
39990
|
-
freshnessGateCli: () => freshnessGateCli
|
|
39991
|
-
});
|
|
39992
|
-
async function freshnessGateCli(args, deps = {}) {
|
|
39993
|
-
const haltOnUpdate = args.includes("--halt-on-update");
|
|
39994
|
-
const result = await freshnessGate({
|
|
39995
|
-
...deps,
|
|
39996
|
-
haltOnUpdate: deps.haltOnUpdate ?? haltOnUpdate
|
|
39997
|
-
});
|
|
39998
|
-
process.stdout.write(JSON.stringify(result) + "\n");
|
|
39999
|
-
return 0;
|
|
40000
|
-
}
|
|
40001
|
-
var init_freshness_gate = __esm({
|
|
40002
|
-
"src/cli/session/freshness-gate.ts"() {
|
|
40003
|
-
"use strict";
|
|
40004
|
-
init_session2();
|
|
40005
|
-
}
|
|
40006
|
-
});
|
|
40007
|
-
|
|
40008
|
-
// src/cli/session/infra-files.ts
|
|
40009
|
-
var infra_files_exports = {};
|
|
40010
|
-
__export(infra_files_exports, {
|
|
40011
|
-
infraFilesCli: () => infraFilesCli
|
|
40012
|
-
});
|
|
40013
|
-
async function infraFilesCli(args, deps = {}) {
|
|
40014
|
-
let taskFilesFromFlag = [];
|
|
40015
|
-
const tfIdx = args.indexOf("--task-files");
|
|
40016
|
-
if (tfIdx !== -1 && tfIdx + 1 < args.length) {
|
|
40017
|
-
const raw = args[tfIdx + 1];
|
|
40018
|
-
if (raw && !raw.startsWith("--")) {
|
|
40019
|
-
taskFilesFromFlag = raw.split(",").map((f) => f.trim()).filter(Boolean);
|
|
40020
|
-
}
|
|
40021
|
-
}
|
|
40022
|
-
const result = await infraFiles({
|
|
40023
|
-
...deps,
|
|
40024
|
-
// When the caller passes --task-files, use those as the task file list.
|
|
40025
|
-
// The deps injection wins when explicitly provided (test path).
|
|
40026
|
-
getTaskFiles: deps.getTaskFiles ?? (taskFilesFromFlag.length > 0 ? () => Promise.resolve(taskFilesFromFlag) : () => Promise.resolve([]))
|
|
40027
|
-
});
|
|
40028
|
-
process.stdout.write(JSON.stringify(result) + "\n");
|
|
40029
|
-
return 0;
|
|
40030
|
-
}
|
|
40031
|
-
var init_infra_files = __esm({
|
|
40032
|
-
"src/cli/session/infra-files.ts"() {
|
|
40033
|
-
"use strict";
|
|
40034
|
-
init_session2();
|
|
40035
|
-
}
|
|
40036
|
-
});
|
|
40037
|
-
|
|
40038
40701
|
// src/lib/slug.ts
|
|
40039
40702
|
function slugify2(title) {
|
|
40040
40703
|
if (!title) return "";
|
|
@@ -40108,9 +40771,9 @@ var commit_exports = {};
|
|
|
40108
40771
|
__export(commit_exports, {
|
|
40109
40772
|
runCommitCommand: () => runCommitCommand
|
|
40110
40773
|
});
|
|
40111
|
-
import { spawnSync as
|
|
40774
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
40112
40775
|
function defaultRun5(cmd, args) {
|
|
40113
|
-
const result =
|
|
40776
|
+
const result = spawnSync16(cmd, args, {
|
|
40114
40777
|
encoding: "utf-8",
|
|
40115
40778
|
stdio: ["pipe", "pipe", "pipe"]
|
|
40116
40779
|
});
|
|
@@ -40158,7 +40821,7 @@ var init_commit = __esm({
|
|
|
40158
40821
|
});
|
|
40159
40822
|
|
|
40160
40823
|
// src/lib/migration-collisions.ts
|
|
40161
|
-
import { spawnSync as
|
|
40824
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
40162
40825
|
function extractPrefix(filename) {
|
|
40163
40826
|
const base = filename.endsWith(".sql") ? filename.slice(0, -4) : filename;
|
|
40164
40827
|
const underscoreIdx = base.indexOf("_");
|
|
@@ -40170,7 +40833,7 @@ function extractPrefix(filename) {
|
|
|
40170
40833
|
}
|
|
40171
40834
|
function makeDefaultRun(cwd) {
|
|
40172
40835
|
return (cmd, args) => {
|
|
40173
|
-
const result =
|
|
40836
|
+
const result = spawnSync17(cmd, args, {
|
|
40174
40837
|
cwd,
|
|
40175
40838
|
encoding: "utf-8",
|
|
40176
40839
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40526,12 +41189,12 @@ var init_validate_waves2 = __esm({
|
|
|
40526
41189
|
});
|
|
40527
41190
|
|
|
40528
41191
|
// src/cli/worktree/path.ts
|
|
40529
|
-
import { dirname as
|
|
41192
|
+
import { dirname as dirname17, basename as basename4, join as join53 } from "node:path";
|
|
40530
41193
|
function computeWorktreePath(cwd, checkpointNumber) {
|
|
40531
|
-
const parent =
|
|
41194
|
+
const parent = dirname17(cwd);
|
|
40532
41195
|
const base = basename4(cwd);
|
|
40533
41196
|
const nnn = String(checkpointNumber).padStart(3, "0");
|
|
40534
|
-
return
|
|
41197
|
+
return join53(parent, `${base}-CHK-${nnn}`);
|
|
40535
41198
|
}
|
|
40536
41199
|
var init_path = __esm({
|
|
40537
41200
|
"src/cli/worktree/path.ts"() {
|
|
@@ -40540,9 +41203,9 @@ var init_path = __esm({
|
|
|
40540
41203
|
});
|
|
40541
41204
|
|
|
40542
41205
|
// src/cli/worktree/add.ts
|
|
40543
|
-
import { join as
|
|
41206
|
+
import { join as join54, basename as basename5 } from "node:path";
|
|
40544
41207
|
import { mkdir as mkdir15, readFile as readFile32, writeFile as writeFile25 } from "node:fs/promises";
|
|
40545
|
-
import { spawnSync as
|
|
41208
|
+
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
40546
41209
|
async function defaultGetRepoId(cwd) {
|
|
40547
41210
|
const found = await findCodebyplanConfig(cwd);
|
|
40548
41211
|
return found?.contents.repo_id ?? null;
|
|
@@ -40571,7 +41234,7 @@ async function defaultLookupBranch(repoId, checkpointNumber) {
|
|
|
40571
41234
|
return { found: true, branch_name: chk.branch_name };
|
|
40572
41235
|
}
|
|
40573
41236
|
function defaultGitRun(args, cwd) {
|
|
40574
|
-
const result =
|
|
41237
|
+
const result = spawnSync18("git", args, {
|
|
40575
41238
|
cwd,
|
|
40576
41239
|
encoding: "utf-8",
|
|
40577
41240
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40590,11 +41253,11 @@ async function copyClaudeSettings(srcCwd, destPath, deps = {}) {
|
|
|
40590
41253
|
(fsp) => fsp.access(p).then(() => true).catch(() => false)
|
|
40591
41254
|
));
|
|
40592
41255
|
const mkdirFn = deps.mkdirFn ?? ((p, opts) => mkdir15(p, opts));
|
|
40593
|
-
await mkdirFn(
|
|
41256
|
+
await mkdirFn(join54(destPath, ".claude"), { recursive: true });
|
|
40594
41257
|
const claudeStubs = ["settings.json", "settings.local.json"];
|
|
40595
41258
|
for (const stub of claudeStubs) {
|
|
40596
|
-
const srcFile =
|
|
40597
|
-
const destFile =
|
|
41259
|
+
const srcFile = join54(srcCwd, ".claude", stub);
|
|
41260
|
+
const destFile = join54(destPath, ".claude", stub);
|
|
40598
41261
|
try {
|
|
40599
41262
|
const destExists = await existsFn(destFile);
|
|
40600
41263
|
if (destExists) continue;
|
|
@@ -40605,22 +41268,22 @@ async function copyClaudeSettings(srcCwd, destPath, deps = {}) {
|
|
|
40605
41268
|
}
|
|
40606
41269
|
}
|
|
40607
41270
|
async function defaultCopyConfigStubs(srcCwd, destPath) {
|
|
40608
|
-
await mkdir15(
|
|
41271
|
+
await mkdir15(join54(destPath, ".codebyplan"), { recursive: true });
|
|
40609
41272
|
const topLevelStubs = [".mcp.json", ".env.local"];
|
|
40610
41273
|
for (const stub of topLevelStubs) {
|
|
40611
41274
|
try {
|
|
40612
|
-
const content = await readFile32(
|
|
40613
|
-
await writeFile25(
|
|
41275
|
+
const content = await readFile32(join54(srcCwd, stub), "utf-8");
|
|
41276
|
+
await writeFile25(join54(destPath, stub), content, "utf-8");
|
|
40614
41277
|
} catch {
|
|
40615
41278
|
}
|
|
40616
41279
|
}
|
|
40617
41280
|
try {
|
|
40618
41281
|
const content = await readFile32(
|
|
40619
|
-
|
|
41282
|
+
join54(srcCwd, ".codebyplan", "repo.json"),
|
|
40620
41283
|
"utf-8"
|
|
40621
41284
|
);
|
|
40622
41285
|
await writeFile25(
|
|
40623
|
-
|
|
41286
|
+
join54(destPath, ".codebyplan", "repo.json"),
|
|
40624
41287
|
content,
|
|
40625
41288
|
"utf-8"
|
|
40626
41289
|
);
|
|
@@ -40785,7 +41448,7 @@ var init_add = __esm({
|
|
|
40785
41448
|
});
|
|
40786
41449
|
|
|
40787
41450
|
// src/cli/worktree/create.ts
|
|
40788
|
-
import { join as
|
|
41451
|
+
import { join as join55 } from "node:path";
|
|
40789
41452
|
async function defaultGetRepoIdentity(cwd) {
|
|
40790
41453
|
const found = await findCodebyplanConfig(cwd);
|
|
40791
41454
|
const contents = found?.contents ?? null;
|
|
@@ -40841,7 +41504,7 @@ async function runWorktreeCreate(args, deps = {}) {
|
|
|
40841
41504
|
);
|
|
40842
41505
|
return 1;
|
|
40843
41506
|
}
|
|
40844
|
-
const worktreePath = explicitPath ??
|
|
41507
|
+
const worktreePath = explicitPath ?? join55(cwd, "..", name);
|
|
40845
41508
|
const deviceId = await getDeviceId(cwd);
|
|
40846
41509
|
let filesWritten = false;
|
|
40847
41510
|
try {
|
|
@@ -40906,7 +41569,7 @@ var init_create = __esm({
|
|
|
40906
41569
|
|
|
40907
41570
|
// src/cli/worktree/remove.ts
|
|
40908
41571
|
import { basename as basename6 } from "node:path";
|
|
40909
|
-
import { spawnSync as
|
|
41572
|
+
import { spawnSync as spawnSync19 } from "node:child_process";
|
|
40910
41573
|
async function defaultGetRepoId2(cwd) {
|
|
40911
41574
|
const found = await findCodebyplanConfig(cwd);
|
|
40912
41575
|
return found?.contents.repo_id ?? null;
|
|
@@ -40928,7 +41591,7 @@ async function defaultDeregisterWorktree(worktreeId) {
|
|
|
40928
41591
|
await mcpCall("delete_worktree", { worktree_id: worktreeId });
|
|
40929
41592
|
}
|
|
40930
41593
|
function defaultGitRun2(args, cwd) {
|
|
40931
|
-
const result =
|
|
41594
|
+
const result = spawnSync19("git", args, {
|
|
40932
41595
|
cwd,
|
|
40933
41596
|
encoding: "utf-8",
|
|
40934
41597
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40941,7 +41604,7 @@ function defaultGitRun2(args, cwd) {
|
|
|
40941
41604
|
};
|
|
40942
41605
|
}
|
|
40943
41606
|
function defaultGetWorktreeBranchName(worktreePath) {
|
|
40944
|
-
const result =
|
|
41607
|
+
const result = spawnSync19("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
40945
41608
|
cwd: worktreePath,
|
|
40946
41609
|
encoding: "utf-8",
|
|
40947
41610
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -41486,7 +42149,7 @@ __export(doctor_exports, {
|
|
|
41486
42149
|
runDoctor: () => runDoctor
|
|
41487
42150
|
});
|
|
41488
42151
|
import { existsSync as existsSync23 } from "node:fs";
|
|
41489
|
-
import { join as
|
|
42152
|
+
import { join as join56 } from "node:path";
|
|
41490
42153
|
import { execSync as execSync10 } from "node:child_process";
|
|
41491
42154
|
async function checkAuth() {
|
|
41492
42155
|
try {
|
|
@@ -41610,7 +42273,7 @@ function checkSettings() {
|
|
|
41610
42273
|
detail: "codebyplan not installed (no .cbp.manifest.json)"
|
|
41611
42274
|
};
|
|
41612
42275
|
}
|
|
41613
|
-
if (!existsSync23(
|
|
42276
|
+
if (!existsSync23(join56(projectDir, ".claude", "settings.json"))) {
|
|
41614
42277
|
return {
|
|
41615
42278
|
name: "settings",
|
|
41616
42279
|
status: "warn",
|
|
@@ -41847,7 +42510,7 @@ void (async () => {
|
|
|
41847
42510
|
process.exit(0);
|
|
41848
42511
|
}
|
|
41849
42512
|
if (arg === "session") {
|
|
41850
|
-
const { runSessionCommand: runSessionCommand2 } = await Promise.resolve().then(() => (
|
|
42513
|
+
const { runSessionCommand: runSessionCommand2 } = await Promise.resolve().then(() => (init_session2(), session_exports));
|
|
41851
42514
|
const rest = process.argv.slice(3);
|
|
41852
42515
|
await runSessionCommand2(rest);
|
|
41853
42516
|
process.exit(0);
|
|
@@ -42123,36 +42786,6 @@ void (async () => {
|
|
|
42123
42786
|
|
|
42124
42787
|
The parent project ref is always read from .codebyplan/shipment.json
|
|
42125
42788
|
(.shipment.surfaces.supabase.project_ref) \u2014 never hardcoded.
|
|
42126
|
-
`);
|
|
42127
|
-
process.exit(0);
|
|
42128
|
-
}
|
|
42129
|
-
if (arg === "session") {
|
|
42130
|
-
const subcommand = process.argv[3];
|
|
42131
|
-
const rest = process.argv.slice(4);
|
|
42132
|
-
if (subcommand === "home-ff") {
|
|
42133
|
-
const { homeFfCli: homeFfCli2 } = await Promise.resolve().then(() => (init_home_ff(), home_ff_exports));
|
|
42134
|
-
process.exit(homeFfCli2(rest));
|
|
42135
|
-
}
|
|
42136
|
-
if (subcommand === "freshness-gate") {
|
|
42137
|
-
const { freshnessGateCli: freshnessGateCli2 } = await Promise.resolve().then(() => (init_freshness_gate(), freshness_gate_exports));
|
|
42138
|
-
process.exit(await freshnessGateCli2(rest));
|
|
42139
|
-
}
|
|
42140
|
-
if (subcommand === "infra-files") {
|
|
42141
|
-
const { infraFilesCli: infraFilesCli2 } = await Promise.resolve().then(() => (init_infra_files(), infra_files_exports));
|
|
42142
|
-
process.exit(await infraFilesCli2(rest));
|
|
42143
|
-
}
|
|
42144
|
-
console.log(`
|
|
42145
|
-
CodeByPlan session helpers v${VERSION}
|
|
42146
|
-
|
|
42147
|
-
Usage:
|
|
42148
|
-
codebyplan session home-ff
|
|
42149
|
-
Fast-forward the home branch to HEAD; outputs { result, reason?, warn? } JSON
|
|
42150
|
-
codebyplan session freshness-gate [--halt-on-update]
|
|
42151
|
-
Check package version freshness; outputs { result, ... } JSON
|
|
42152
|
-
codebyplan session infra-files [--task-files <csv>] [--json]
|
|
42153
|
-
Compute the infra-file set for the active session; outputs { infra_files, task_files } JSON
|
|
42154
|
-
|
|
42155
|
-
Output is always JSON on stdout. Exit 0 always \u2014 callers branch on the result field.
|
|
42156
42789
|
`);
|
|
42157
42790
|
process.exit(0);
|
|
42158
42791
|
}
|