@episoda/cli 0.2.165 → 0.2.167
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/daemon/daemon-process.js +106 -23
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -2978,7 +2978,7 @@ var require_package = __commonJS({
|
|
|
2978
2978
|
"package.json"(exports2, module2) {
|
|
2979
2979
|
module2.exports = {
|
|
2980
2980
|
name: "@episoda/cli",
|
|
2981
|
-
version: "0.2.
|
|
2981
|
+
version: "0.2.167",
|
|
2982
2982
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2983
2983
|
main: "dist/index.js",
|
|
2984
2984
|
types: "dist/index.d.ts",
|
|
@@ -9059,8 +9059,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
9059
9059
|
console.log(`[WorktreeManager] EP959: Timeout: ${TIMEOUT_MINUTES} minutes`);
|
|
9060
9060
|
console.log(`[WorktreeManager] EP959: Script: ${scriptPreview}`);
|
|
9061
9061
|
try {
|
|
9062
|
-
const { execSync:
|
|
9063
|
-
|
|
9062
|
+
const { execSync: execSync11 } = require("child_process");
|
|
9063
|
+
execSync11(script, {
|
|
9064
9064
|
cwd: worktree.worktreePath,
|
|
9065
9065
|
stdio: "inherit",
|
|
9066
9066
|
timeout: TIMEOUT_MINUTES * 60 * 1e3,
|
|
@@ -9094,8 +9094,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
9094
9094
|
console.log(`[WorktreeManager] EP959: Timeout: ${TIMEOUT_MINUTES} minutes`);
|
|
9095
9095
|
console.log(`[WorktreeManager] EP959: Script: ${scriptPreview}`);
|
|
9096
9096
|
try {
|
|
9097
|
-
const { execSync:
|
|
9098
|
-
|
|
9097
|
+
const { execSync: execSync11 } = require("child_process");
|
|
9098
|
+
execSync11(script, {
|
|
9099
9099
|
cwd: worktree.worktreePath,
|
|
9100
9100
|
stdio: "inherit",
|
|
9101
9101
|
timeout: TIMEOUT_MINUTES * 60 * 1e3,
|
|
@@ -11635,7 +11635,7 @@ function pnpmCommand(args) {
|
|
|
11635
11635
|
' echo "[setup] ERROR: pnpm is not installed and corepack is unavailable" >&2',
|
|
11636
11636
|
" exit 127",
|
|
11637
11637
|
"fi"
|
|
11638
|
-
].join("
|
|
11638
|
+
].join("\n");
|
|
11639
11639
|
}
|
|
11640
11640
|
var PACKAGE_MANAGERS = {
|
|
11641
11641
|
javascript: [
|
|
@@ -11793,7 +11793,16 @@ function getBuildPackagesCommand(packageManagerName, hasBuildPackagesScript) {
|
|
|
11793
11793
|
}
|
|
11794
11794
|
switch (packageManagerName) {
|
|
11795
11795
|
case "pnpm":
|
|
11796
|
-
return
|
|
11796
|
+
return [
|
|
11797
|
+
"if command -v pnpm >/dev/null 2>&1; then",
|
|
11798
|
+
" pnpm run build:packages",
|
|
11799
|
+
"elif command -v corepack >/dev/null 2>&1; then",
|
|
11800
|
+
" corepack pnpm run build:packages",
|
|
11801
|
+
"else",
|
|
11802
|
+
' echo "[setup] ERROR: pnpm is not installed and corepack is unavailable" >&2',
|
|
11803
|
+
" exit 127",
|
|
11804
|
+
"fi"
|
|
11805
|
+
].join("\n");
|
|
11797
11806
|
case "yarn":
|
|
11798
11807
|
return "yarn build:packages";
|
|
11799
11808
|
case "npm":
|
|
@@ -13223,6 +13232,13 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
13223
13232
|
static {
|
|
13224
13233
|
this.WORKTREE_CLEANUP_EVERY_N_CHECKS = 5;
|
|
13225
13234
|
}
|
|
13235
|
+
static {
|
|
13236
|
+
// EP1395: Avoid racing module-state propagation during startup/transition.
|
|
13237
|
+
this.ORPHAN_GRACE_PERIOD_MS = 60 * 60 * 1e3;
|
|
13238
|
+
}
|
|
13239
|
+
static {
|
|
13240
|
+
this.PROTECTED_SETUP_STATUSES = /* @__PURE__ */ new Set(["pending", "setup", "ready"]);
|
|
13241
|
+
}
|
|
13226
13242
|
static {
|
|
13227
13243
|
// EP1351: Log rotation constants
|
|
13228
13244
|
this.MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024;
|
|
@@ -13484,13 +13500,58 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
13484
13500
|
return;
|
|
13485
13501
|
}
|
|
13486
13502
|
const { orphaned } = manager.auditWorktrees(activeModuleUids);
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13503
|
+
const nowMs = Date.now();
|
|
13504
|
+
const skippedRecent = [];
|
|
13505
|
+
const skippedSetup = [];
|
|
13506
|
+
const skippedUnknownAge = [];
|
|
13507
|
+
const fallbackAgeSource = [];
|
|
13508
|
+
const cleanupCandidates = orphaned.filter((w) => {
|
|
13509
|
+
const status = (w.setupStatus || "").toLowerCase();
|
|
13510
|
+
if (status && _HealthOrchestrator.PROTECTED_SETUP_STATUSES.has(status)) {
|
|
13511
|
+
skippedSetup.push(`${w.moduleUid}(${status})`);
|
|
13512
|
+
return false;
|
|
13513
|
+
}
|
|
13514
|
+
let referenceTimestampMs = Date.parse(w.createdAt || "");
|
|
13515
|
+
if (!Number.isFinite(referenceTimestampMs)) {
|
|
13516
|
+
const lastAccessedMs = Date.parse(w.lastAccessed || "");
|
|
13517
|
+
if (Number.isFinite(lastAccessedMs)) {
|
|
13518
|
+
referenceTimestampMs = lastAccessedMs;
|
|
13519
|
+
fallbackAgeSource.push(`${w.moduleUid}(lastAccessed)`);
|
|
13520
|
+
} else if (w.worktreePath && fs27.existsSync(w.worktreePath)) {
|
|
13521
|
+
try {
|
|
13522
|
+
const stats = fs27.statSync(w.worktreePath);
|
|
13523
|
+
referenceTimestampMs = stats.mtimeMs;
|
|
13524
|
+
fallbackAgeSource.push(`${w.moduleUid}(fs.mtime)`);
|
|
13525
|
+
} catch {
|
|
13526
|
+
}
|
|
13527
|
+
}
|
|
13528
|
+
}
|
|
13529
|
+
if (!Number.isFinite(referenceTimestampMs)) {
|
|
13530
|
+
skippedUnknownAge.push(w.moduleUid);
|
|
13531
|
+
return false;
|
|
13532
|
+
}
|
|
13533
|
+
if (nowMs - referenceTimestampMs < _HealthOrchestrator.ORPHAN_GRACE_PERIOD_MS) {
|
|
13534
|
+
skippedRecent.push(w.moduleUid);
|
|
13535
|
+
return false;
|
|
13536
|
+
}
|
|
13537
|
+
return true;
|
|
13538
|
+
});
|
|
13539
|
+
if (cleanupCandidates.length > 0) {
|
|
13540
|
+
console.log(`[Daemon] EP1035: Found ${orphaned.length} orphaned worktree(s) in ${config.workspaceSlug}/${config.projectSlug} (${cleanupCandidates.length} eligible for cleanup):`);
|
|
13541
|
+
for (const w of cleanupCandidates) {
|
|
13490
13542
|
console.log(` - ${w.moduleUid} (branch: ${w.branchName})`);
|
|
13491
13543
|
}
|
|
13492
|
-
|
|
13493
|
-
|
|
13544
|
+
} else if (orphaned.length > 0) {
|
|
13545
|
+
console.log(`[Daemon] EP1395: Found ${orphaned.length} orphaned worktree(s) in ${config.workspaceSlug}/${config.projectSlug}, but none are eligible for cleanup after filters.`);
|
|
13546
|
+
}
|
|
13547
|
+
if (skippedRecent.length > 0 || skippedSetup.length > 0 || fallbackAgeSource.length > 0 || skippedUnknownAge.length > 0) {
|
|
13548
|
+
console.log(
|
|
13549
|
+
`[Daemon] EP1395: Orphan cleanup filters applied - recent=${skippedRecent.length}, setup=${skippedSetup.length}, fallbackAge=${fallbackAgeSource.length}, unknownAge=${skippedUnknownAge.length}`
|
|
13550
|
+
);
|
|
13551
|
+
}
|
|
13552
|
+
if (cleanupCandidates.length > 0) {
|
|
13553
|
+
console.log(`[Daemon] EP1035: Auto-cleaning ${cleanupCandidates.length} orphaned worktree(s)...`);
|
|
13554
|
+
for (const w of cleanupCandidates) {
|
|
13494
13555
|
try {
|
|
13495
13556
|
const removeResult = await manager.removeWorktree(w.moduleUid, true);
|
|
13496
13557
|
if (removeResult.success) {
|
|
@@ -13698,13 +13759,35 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
13698
13759
|
};
|
|
13699
13760
|
|
|
13700
13761
|
// src/daemon/daemon-core.ts
|
|
13762
|
+
var import_child_process19 = require("child_process");
|
|
13701
13763
|
var DaemonCore = class {
|
|
13702
13764
|
constructor(host) {
|
|
13703
13765
|
this.host = host;
|
|
13704
13766
|
}
|
|
13767
|
+
getParentCommand() {
|
|
13768
|
+
const ppid = process.ppid;
|
|
13769
|
+
if (!ppid || ppid <= 0) return void 0;
|
|
13770
|
+
try {
|
|
13771
|
+
return (0, import_child_process19.execSync)(`ps -p ${ppid} -o command=`, {
|
|
13772
|
+
encoding: "utf-8",
|
|
13773
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
13774
|
+
timeout: 3e3
|
|
13775
|
+
}).trim();
|
|
13776
|
+
} catch {
|
|
13777
|
+
return void 0;
|
|
13778
|
+
}
|
|
13779
|
+
}
|
|
13705
13780
|
setupShutdownHandlers() {
|
|
13706
13781
|
const shutdownHandler = async (signal) => {
|
|
13707
|
-
|
|
13782
|
+
const payload = {
|
|
13783
|
+
signal,
|
|
13784
|
+
pid: process.pid,
|
|
13785
|
+
ppid: process.ppid,
|
|
13786
|
+
uptimeSec: Math.round(process.uptime()),
|
|
13787
|
+
parentCommand: this.getParentCommand(),
|
|
13788
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
13789
|
+
};
|
|
13790
|
+
console.log(`[Daemon] SignalReceived ${JSON.stringify(payload)}`);
|
|
13708
13791
|
await this.host.cleanupAndExit();
|
|
13709
13792
|
};
|
|
13710
13793
|
process.on("SIGTERM", () => {
|
|
@@ -14271,31 +14354,31 @@ function getGitDirs(projectPath) {
|
|
|
14271
14354
|
}
|
|
14272
14355
|
async function configureGitUser(projectPath, userId, workspaceId, machineId, projectId, machineUuid) {
|
|
14273
14356
|
try {
|
|
14274
|
-
const { execSync:
|
|
14357
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
14275
14358
|
const { gitDir, workDir } = getGitDirs(projectPath);
|
|
14276
14359
|
const gitCmd = gitDir ? `git --git-dir="${gitDir}"` : "git";
|
|
14277
|
-
|
|
14360
|
+
execSync11(`${gitCmd} config episoda.userId ${userId}`, {
|
|
14278
14361
|
cwd: workDir,
|
|
14279
14362
|
encoding: "utf8",
|
|
14280
14363
|
stdio: "pipe"
|
|
14281
14364
|
});
|
|
14282
|
-
|
|
14365
|
+
execSync11(`${gitCmd} config episoda.workspaceId ${workspaceId}`, {
|
|
14283
14366
|
cwd: workDir,
|
|
14284
14367
|
encoding: "utf8",
|
|
14285
14368
|
stdio: "pipe"
|
|
14286
14369
|
});
|
|
14287
|
-
|
|
14370
|
+
execSync11(`${gitCmd} config episoda.machineId ${machineId}`, {
|
|
14288
14371
|
cwd: workDir,
|
|
14289
14372
|
encoding: "utf8",
|
|
14290
14373
|
stdio: "pipe"
|
|
14291
14374
|
});
|
|
14292
|
-
|
|
14375
|
+
execSync11(`${gitCmd} config episoda.projectId ${projectId}`, {
|
|
14293
14376
|
cwd: workDir,
|
|
14294
14377
|
encoding: "utf8",
|
|
14295
14378
|
stdio: "pipe"
|
|
14296
14379
|
});
|
|
14297
14380
|
if (machineUuid) {
|
|
14298
|
-
|
|
14381
|
+
execSync11(`${gitCmd} config episoda.deviceId ${machineUuid}`, {
|
|
14299
14382
|
cwd: workDir,
|
|
14300
14383
|
encoding: "utf8",
|
|
14301
14384
|
stdio: "pipe"
|
|
@@ -15618,8 +15701,8 @@ var Daemon = class _Daemon {
|
|
|
15618
15701
|
console.log(`[Daemon] EP1002: ${installCmd.description} (detected from ${installCmd.detectedFrom})`);
|
|
15619
15702
|
console.log(`[Daemon] EP1002: Running: ${installCmd.command.join(" ")}`);
|
|
15620
15703
|
try {
|
|
15621
|
-
const { execSync:
|
|
15622
|
-
|
|
15704
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
15705
|
+
execSync11(installCmd.command.join(" "), {
|
|
15623
15706
|
cwd: worktreePath,
|
|
15624
15707
|
stdio: "inherit",
|
|
15625
15708
|
timeout: 10 * 60 * 1e3,
|
|
@@ -15641,8 +15724,8 @@ var Daemon = class _Daemon {
|
|
|
15641
15724
|
const bootstrapCmd = buildCmd;
|
|
15642
15725
|
console.log(`[Daemon] EP1386: Bootstrapping packages after dependency install (${bootstrapCmd})`);
|
|
15643
15726
|
try {
|
|
15644
|
-
const { execSync:
|
|
15645
|
-
|
|
15727
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
15728
|
+
execSync11(bootstrapCmd, {
|
|
15646
15729
|
cwd: worktreePath,
|
|
15647
15730
|
stdio: "inherit",
|
|
15648
15731
|
timeout: 10 * 60 * 1e3,
|