episoda 0.2.61 → 0.2.63
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 +79 -3
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +111 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -2726,7 +2726,7 @@ var require_package = __commonJS({
|
|
|
2726
2726
|
"package.json"(exports2, module2) {
|
|
2727
2727
|
module2.exports = {
|
|
2728
2728
|
name: "episoda",
|
|
2729
|
-
version: "0.2.
|
|
2729
|
+
version: "0.2.63",
|
|
2730
2730
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2731
2731
|
main: "dist/index.js",
|
|
2732
2732
|
types: "dist/index.d.ts",
|
|
@@ -7091,23 +7091,40 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
7091
7091
|
/**
|
|
7092
7092
|
* Initialize worktree manager from existing project root
|
|
7093
7093
|
* EP971: All projects use worktree architecture
|
|
7094
|
+
* EP1093: Added debug logging for cloud container diagnostics
|
|
7094
7095
|
* @returns true if valid project, false otherwise
|
|
7095
7096
|
*/
|
|
7096
7097
|
async initialize() {
|
|
7098
|
+
const debug = process.env.EPISODA_DEBUG === "1" || process.env.GIT_CREDENTIAL_EPISODA_DEBUG === "1";
|
|
7097
7099
|
if (!fs15.existsSync(this.bareRepoPath)) {
|
|
7100
|
+
if (debug) {
|
|
7101
|
+
console.log(`[WorktreeManager] initialize: .bare not found at ${this.bareRepoPath}`);
|
|
7102
|
+
}
|
|
7098
7103
|
return false;
|
|
7099
7104
|
}
|
|
7100
7105
|
if (!fs15.existsSync(this.configPath)) {
|
|
7106
|
+
if (debug) {
|
|
7107
|
+
console.log(`[WorktreeManager] initialize: config not found at ${this.configPath}`);
|
|
7108
|
+
}
|
|
7101
7109
|
return false;
|
|
7102
7110
|
}
|
|
7103
7111
|
try {
|
|
7104
7112
|
const config = this.readConfig();
|
|
7105
7113
|
if (config === null) {
|
|
7114
|
+
if (debug) {
|
|
7115
|
+
console.log(`[WorktreeManager] initialize: readConfig returned null`);
|
|
7116
|
+
}
|
|
7106
7117
|
return false;
|
|
7107
7118
|
}
|
|
7119
|
+
if (debug) {
|
|
7120
|
+
console.log(`[WorktreeManager] initialize: config loaded, projectId=${config.projectId}`);
|
|
7121
|
+
}
|
|
7108
7122
|
await this.ensureFetchRefspecConfigured();
|
|
7109
7123
|
return true;
|
|
7110
|
-
} catch {
|
|
7124
|
+
} catch (error) {
|
|
7125
|
+
if (debug) {
|
|
7126
|
+
console.log(`[WorktreeManager] initialize: exception - ${error.message}`);
|
|
7127
|
+
}
|
|
7111
7128
|
return false;
|
|
7112
7129
|
}
|
|
7113
7130
|
}
|
|
@@ -7242,6 +7259,7 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
7242
7259
|
/**
|
|
7243
7260
|
* Remove a worktree for a module
|
|
7244
7261
|
* P1-2: Wrapped entire operation in lock to prevent race with createWorktree
|
|
7262
|
+
* EP1070: Clean build caches before git worktree remove to prevent orphaned directories
|
|
7245
7263
|
*/
|
|
7246
7264
|
async removeWorktree(moduleUid, force = false) {
|
|
7247
7265
|
if (!validateModuleUid(moduleUid)) {
|
|
@@ -7265,6 +7283,7 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
7265
7283
|
error: `No worktree found for module ${moduleUid}`
|
|
7266
7284
|
};
|
|
7267
7285
|
}
|
|
7286
|
+
await this.cleanBuildCaches(existing.worktreePath);
|
|
7268
7287
|
const result = await this.gitExecutor.execute({
|
|
7269
7288
|
action: "worktree_remove",
|
|
7270
7289
|
path: existing.worktreePath,
|
|
@@ -7489,6 +7508,37 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
7489
7508
|
} catch {
|
|
7490
7509
|
}
|
|
7491
7510
|
}
|
|
7511
|
+
/**
|
|
7512
|
+
* EP1070: Clean build caches before worktree removal
|
|
7513
|
+
*
|
|
7514
|
+
* Removes common build cache directories that can cause:
|
|
7515
|
+
* 1. git worktree remove to fail (locked files on Windows)
|
|
7516
|
+
* 2. Orphaned directories if removal partially fails
|
|
7517
|
+
* 3. Disk space waste from abandoned build artifacts
|
|
7518
|
+
*
|
|
7519
|
+
* @param worktreePath - Absolute path to the worktree directory
|
|
7520
|
+
*/
|
|
7521
|
+
async cleanBuildCaches(worktreePath) {
|
|
7522
|
+
const cacheDirs = [
|
|
7523
|
+
".next",
|
|
7524
|
+
// Next.js build cache
|
|
7525
|
+
"node_modules/.cache",
|
|
7526
|
+
// Various build tool caches (babel, eslint, etc.)
|
|
7527
|
+
".turbo"
|
|
7528
|
+
// Turborepo cache
|
|
7529
|
+
];
|
|
7530
|
+
for (const cacheDir of cacheDirs) {
|
|
7531
|
+
const cachePath = path16.join(worktreePath, cacheDir);
|
|
7532
|
+
try {
|
|
7533
|
+
if (fs15.existsSync(cachePath)) {
|
|
7534
|
+
console.log(`[WorktreeManager] EP1070: Cleaning build cache: ${cacheDir}`);
|
|
7535
|
+
fs15.rmSync(cachePath, { recursive: true, force: true });
|
|
7536
|
+
}
|
|
7537
|
+
} catch (error) {
|
|
7538
|
+
console.warn(`[WorktreeManager] EP1070: Failed to clean ${cacheDir} (non-blocking):`, error.message);
|
|
7539
|
+
}
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7492
7542
|
readConfig() {
|
|
7493
7543
|
try {
|
|
7494
7544
|
if (!fs15.existsSync(this.configPath)) {
|
|
@@ -7686,20 +7736,43 @@ function getEpisodaRoot() {
|
|
|
7686
7736
|
return process.env.EPISODA_ROOT || path16.join(require("os").homedir(), "episoda");
|
|
7687
7737
|
}
|
|
7688
7738
|
async function isWorktreeProject(projectRoot) {
|
|
7739
|
+
const debug = process.env.EPISODA_DEBUG === "1" || process.env.GIT_CREDENTIAL_EPISODA_DEBUG === "1";
|
|
7740
|
+
if (debug) {
|
|
7741
|
+
console.log(`[WorktreeManager] isWorktreeProject: checking ${projectRoot}`);
|
|
7742
|
+
}
|
|
7689
7743
|
const manager = new WorktreeManager(projectRoot);
|
|
7690
|
-
|
|
7744
|
+
const result = await manager.initialize();
|
|
7745
|
+
if (debug) {
|
|
7746
|
+
console.log(`[WorktreeManager] isWorktreeProject: ${projectRoot} -> ${result}`);
|
|
7747
|
+
}
|
|
7748
|
+
return result;
|
|
7691
7749
|
}
|
|
7692
7750
|
async function findProjectRoot(startPath) {
|
|
7693
7751
|
let current = path16.resolve(startPath);
|
|
7694
7752
|
const episodaRoot = getEpisodaRoot();
|
|
7753
|
+
const debug = process.env.EPISODA_DEBUG === "1" || process.env.GIT_CREDENTIAL_EPISODA_DEBUG === "1";
|
|
7754
|
+
if (debug) {
|
|
7755
|
+
console.log(`[WorktreeManager] findProjectRoot: start=${startPath}, episodaRoot=${episodaRoot}`);
|
|
7756
|
+
}
|
|
7695
7757
|
if (!current.startsWith(episodaRoot)) {
|
|
7758
|
+
if (debug) {
|
|
7759
|
+
console.log(`[WorktreeManager] findProjectRoot: ${current} is not under ${episodaRoot}`);
|
|
7760
|
+
}
|
|
7696
7761
|
return null;
|
|
7697
7762
|
}
|
|
7698
7763
|
for (let i = 0; i < 10; i++) {
|
|
7699
7764
|
const bareDir = path16.join(current, ".bare");
|
|
7700
7765
|
const episodaDir = path16.join(current, ".episoda");
|
|
7766
|
+
if (debug) {
|
|
7767
|
+
const bareExists = fs15.existsSync(bareDir);
|
|
7768
|
+
const episodaExists = fs15.existsSync(episodaDir);
|
|
7769
|
+
console.log(`[WorktreeManager] findProjectRoot: checking ${current} (.bare=${bareExists}, .episoda=${episodaExists})`);
|
|
7770
|
+
}
|
|
7701
7771
|
if (fs15.existsSync(bareDir) && fs15.existsSync(episodaDir)) {
|
|
7702
7772
|
if (await isWorktreeProject(current)) {
|
|
7773
|
+
if (debug) {
|
|
7774
|
+
console.log(`[WorktreeManager] findProjectRoot: found valid project at ${current}`);
|
|
7775
|
+
}
|
|
7703
7776
|
return current;
|
|
7704
7777
|
}
|
|
7705
7778
|
}
|
|
@@ -7709,6 +7782,9 @@ async function findProjectRoot(startPath) {
|
|
|
7709
7782
|
}
|
|
7710
7783
|
current = parent;
|
|
7711
7784
|
}
|
|
7785
|
+
if (debug) {
|
|
7786
|
+
console.log(`[WorktreeManager] findProjectRoot: no project found`);
|
|
7787
|
+
}
|
|
7712
7788
|
return null;
|
|
7713
7789
|
}
|
|
7714
7790
|
|