@episoda/cli 0.2.166 → 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 +95 -21
- 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,
|
|
@@ -13232,6 +13232,13 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
13232
13232
|
static {
|
|
13233
13233
|
this.WORKTREE_CLEANUP_EVERY_N_CHECKS = 5;
|
|
13234
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
|
+
}
|
|
13235
13242
|
static {
|
|
13236
13243
|
// EP1351: Log rotation constants
|
|
13237
13244
|
this.MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024;
|
|
@@ -13493,13 +13500,58 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
13493
13500
|
return;
|
|
13494
13501
|
}
|
|
13495
13502
|
const { orphaned } = manager.auditWorktrees(activeModuleUids);
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
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) {
|
|
13499
13542
|
console.log(` - ${w.moduleUid} (branch: ${w.branchName})`);
|
|
13500
13543
|
}
|
|
13501
|
-
|
|
13502
|
-
|
|
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) {
|
|
13503
13555
|
try {
|
|
13504
13556
|
const removeResult = await manager.removeWorktree(w.moduleUid, true);
|
|
13505
13557
|
if (removeResult.success) {
|
|
@@ -13707,13 +13759,35 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
13707
13759
|
};
|
|
13708
13760
|
|
|
13709
13761
|
// src/daemon/daemon-core.ts
|
|
13762
|
+
var import_child_process19 = require("child_process");
|
|
13710
13763
|
var DaemonCore = class {
|
|
13711
13764
|
constructor(host) {
|
|
13712
13765
|
this.host = host;
|
|
13713
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
|
+
}
|
|
13714
13780
|
setupShutdownHandlers() {
|
|
13715
13781
|
const shutdownHandler = async (signal) => {
|
|
13716
|
-
|
|
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)}`);
|
|
13717
13791
|
await this.host.cleanupAndExit();
|
|
13718
13792
|
};
|
|
13719
13793
|
process.on("SIGTERM", () => {
|
|
@@ -14280,31 +14354,31 @@ function getGitDirs(projectPath) {
|
|
|
14280
14354
|
}
|
|
14281
14355
|
async function configureGitUser(projectPath, userId, workspaceId, machineId, projectId, machineUuid) {
|
|
14282
14356
|
try {
|
|
14283
|
-
const { execSync:
|
|
14357
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
14284
14358
|
const { gitDir, workDir } = getGitDirs(projectPath);
|
|
14285
14359
|
const gitCmd = gitDir ? `git --git-dir="${gitDir}"` : "git";
|
|
14286
|
-
|
|
14360
|
+
execSync11(`${gitCmd} config episoda.userId ${userId}`, {
|
|
14287
14361
|
cwd: workDir,
|
|
14288
14362
|
encoding: "utf8",
|
|
14289
14363
|
stdio: "pipe"
|
|
14290
14364
|
});
|
|
14291
|
-
|
|
14365
|
+
execSync11(`${gitCmd} config episoda.workspaceId ${workspaceId}`, {
|
|
14292
14366
|
cwd: workDir,
|
|
14293
14367
|
encoding: "utf8",
|
|
14294
14368
|
stdio: "pipe"
|
|
14295
14369
|
});
|
|
14296
|
-
|
|
14370
|
+
execSync11(`${gitCmd} config episoda.machineId ${machineId}`, {
|
|
14297
14371
|
cwd: workDir,
|
|
14298
14372
|
encoding: "utf8",
|
|
14299
14373
|
stdio: "pipe"
|
|
14300
14374
|
});
|
|
14301
|
-
|
|
14375
|
+
execSync11(`${gitCmd} config episoda.projectId ${projectId}`, {
|
|
14302
14376
|
cwd: workDir,
|
|
14303
14377
|
encoding: "utf8",
|
|
14304
14378
|
stdio: "pipe"
|
|
14305
14379
|
});
|
|
14306
14380
|
if (machineUuid) {
|
|
14307
|
-
|
|
14381
|
+
execSync11(`${gitCmd} config episoda.deviceId ${machineUuid}`, {
|
|
14308
14382
|
cwd: workDir,
|
|
14309
14383
|
encoding: "utf8",
|
|
14310
14384
|
stdio: "pipe"
|
|
@@ -15627,8 +15701,8 @@ var Daemon = class _Daemon {
|
|
|
15627
15701
|
console.log(`[Daemon] EP1002: ${installCmd.description} (detected from ${installCmd.detectedFrom})`);
|
|
15628
15702
|
console.log(`[Daemon] EP1002: Running: ${installCmd.command.join(" ")}`);
|
|
15629
15703
|
try {
|
|
15630
|
-
const { execSync:
|
|
15631
|
-
|
|
15704
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
15705
|
+
execSync11(installCmd.command.join(" "), {
|
|
15632
15706
|
cwd: worktreePath,
|
|
15633
15707
|
stdio: "inherit",
|
|
15634
15708
|
timeout: 10 * 60 * 1e3,
|
|
@@ -15650,8 +15724,8 @@ var Daemon = class _Daemon {
|
|
|
15650
15724
|
const bootstrapCmd = buildCmd;
|
|
15651
15725
|
console.log(`[Daemon] EP1386: Bootstrapping packages after dependency install (${bootstrapCmd})`);
|
|
15652
15726
|
try {
|
|
15653
|
-
const { execSync:
|
|
15654
|
-
|
|
15727
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
15728
|
+
execSync11(bootstrapCmd, {
|
|
15655
15729
|
cwd: worktreePath,
|
|
15656
15730
|
stdio: "inherit",
|
|
15657
15731
|
timeout: 10 * 60 * 1e3,
|