@iloom/cli 0.1.19 → 0.3.0
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/README.md +290 -30
- package/dist/BranchNamingService-3OQPRSWT.js +13 -0
- package/dist/ClaudeContextManager-MUQSDY2E.js +13 -0
- package/dist/ClaudeService-HG4VQ7AW.js +12 -0
- package/dist/GitHubService-EBOETDIW.js +11 -0
- package/dist/{LoomLauncher-UMMLPIZO.js → LoomLauncher-FLEMBCSQ.js} +64 -33
- package/dist/LoomLauncher-FLEMBCSQ.js.map +1 -0
- package/dist/ProjectCapabilityDetector-34LU7JJ4.js +9 -0
- package/dist/{PromptTemplateManager-WII75TKH.js → PromptTemplateManager-A52RUAMS.js} +2 -2
- package/dist/README.md +290 -30
- package/dist/{SettingsManager-SKLUVE3K.js → SettingsManager-WHHFGSL7.js} +12 -4
- package/dist/SettingsMigrationManager-AGIIIPDQ.js +10 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +125 -35
- package/dist/agents/iloom-issue-analyzer.md +284 -32
- package/dist/agents/iloom-issue-complexity-evaluator.md +40 -21
- package/dist/agents/iloom-issue-enhancer.md +69 -48
- package/dist/agents/iloom-issue-implementer.md +36 -25
- package/dist/agents/iloom-issue-planner.md +35 -24
- package/dist/agents/iloom-issue-reviewer.md +62 -9
- package/dist/chunk-3KATJIKO.js +55 -0
- package/dist/chunk-3KATJIKO.js.map +1 -0
- package/dist/{chunk-JXQXSC45.js → chunk-3RUPPQRG.js} +1 -18
- package/dist/chunk-3RUPPQRG.js.map +1 -0
- package/dist/{chunk-PR7FKQBG.js → chunk-47KSHUCR.js} +3 -3
- package/dist/chunk-47KSHUCR.js.map +1 -0
- package/dist/{chunk-IO4WFTL2.js → chunk-4HHRTA7Q.js} +3 -3
- package/dist/{chunk-IO4WFTL2.js.map → chunk-4HHRTA7Q.js.map} +1 -1
- package/dist/chunk-5EF7Z346.js +1987 -0
- package/dist/chunk-5EF7Z346.js.map +1 -0
- package/dist/{chunk-VVH3ANF2.js → chunk-AWOFAD5O.js} +12 -12
- package/dist/chunk-AWOFAD5O.js.map +1 -0
- package/dist/{chunk-DEPYQRRB.js → chunk-C5QCTEQK.js} +2 -2
- package/dist/{chunk-CWR2SANQ.js → chunk-EBISESAP.js} +1 -1
- package/dist/{chunk-ELFT36PV.js → chunk-FIAT22G7.js} +4 -16
- package/dist/chunk-FIAT22G7.js.map +1 -0
- package/dist/{chunk-ZWXJBSUW.js → chunk-G2IEYOLQ.js} +11 -38
- package/dist/chunk-G2IEYOLQ.js.map +1 -0
- package/dist/{chunk-ZMNQBJUI.js → chunk-IP7SMKIF.js} +61 -22
- package/dist/chunk-IP7SMKIF.js.map +1 -0
- package/dist/{chunk-JNKJ7NJV.js → chunk-JKXJ7BGL.js} +6 -2
- package/dist/{chunk-JNKJ7NJV.js.map → chunk-JKXJ7BGL.js.map} +1 -1
- package/dist/{chunk-LAPY6NAE.js → chunk-JQFO7QQN.js} +68 -12
- package/dist/{chunk-LAPY6NAE.js.map → chunk-JQFO7QQN.js.map} +1 -1
- package/dist/{SettingsMigrationManager-MTQIMI54.js → chunk-KLBYVHPK.js} +3 -2
- package/dist/{chunk-KOCQAD2E.js → chunk-MAVL6PJF.js} +26 -3
- package/dist/chunk-MAVL6PJF.js.map +1 -0
- package/dist/{chunk-USVVV3FP.js → chunk-MKWYLDFK.js} +5 -5
- package/dist/chunk-ML3NRPNB.js +396 -0
- package/dist/chunk-ML3NRPNB.js.map +1 -0
- package/dist/{chunk-FXV24OYZ.js → chunk-PA6Q6AWM.js} +24 -4
- package/dist/chunk-PA6Q6AWM.js.map +1 -0
- package/dist/chunk-RO26VS3W.js +444 -0
- package/dist/chunk-RO26VS3W.js.map +1 -0
- package/dist/{chunk-PV3GAXQO.js → chunk-VAYCCUXW.js} +72 -2
- package/dist/{chunk-PV3GAXQO.js.map → chunk-VAYCCUXW.js.map} +1 -1
- package/dist/{chunk-SPYPLHMK.js → chunk-VU3QMIP2.js} +34 -2
- package/dist/chunk-VU3QMIP2.js.map +1 -0
- package/dist/{chunk-PVAVNJKS.js → chunk-WEN5C5DM.js} +10 -1
- package/dist/chunk-WEN5C5DM.js.map +1 -0
- package/dist/{chunk-PXZBAC2M.js → chunk-XXV3UFZL.js} +4 -4
- package/dist/{chunk-PXZBAC2M.js.map → chunk-XXV3UFZL.js.map} +1 -1
- package/dist/{chunk-RSRO7564.js → chunk-ZE74H5BR.js} +28 -3
- package/dist/chunk-ZE74H5BR.js.map +1 -0
- package/dist/{chunk-GZP4UGGM.js → chunk-ZM3CFL5L.js} +2 -2
- package/dist/{chunk-BLCTGFZN.js → chunk-ZT3YZB4K.js} +3 -4
- package/dist/chunk-ZT3YZB4K.js.map +1 -0
- package/dist/{claude-7LUVDZZ4.js → claude-GOP6PFC7.js} +2 -2
- package/dist/{cleanup-ZHROIBSQ.js → cleanup-7RWLBSLE.js} +86 -25
- package/dist/cleanup-7RWLBSLE.js.map +1 -0
- package/dist/cli.js +2513 -64
- package/dist/cli.js.map +1 -1
- package/dist/{contribute-3MQJ3XAQ.js → contribute-BS2L4FZR.js} +9 -6
- package/dist/{contribute-3MQJ3XAQ.js.map → contribute-BS2L4FZR.js.map} +1 -1
- package/dist/{feedback-ZOUCCHN4.js → feedback-N4ECWIPF.js} +15 -14
- package/dist/{feedback-ZOUCCHN4.js.map → feedback-N4ECWIPF.js.map} +1 -1
- package/dist/{git-OUYMVYJX.js → git-TDXKRTXM.js} +4 -2
- package/dist/{ignite-HICLZEYU.js → ignite-VM64QO3J.js} +32 -27
- package/dist/ignite-VM64QO3J.js.map +1 -0
- package/dist/index.d.ts +379 -45
- package/dist/index.js +1241 -448
- package/dist/index.js.map +1 -1
- package/dist/{init-UMKNHNV5.js → init-G3T64SC4.js} +104 -40
- package/dist/init-G3T64SC4.js.map +1 -0
- package/dist/mcp/issue-management-server.js +934 -0
- package/dist/mcp/issue-management-server.js.map +1 -0
- package/dist/{neon-helpers-ZVIRPKCI.js → neon-helpers-WPUACUVC.js} +3 -3
- package/dist/{open-ETZUFSE4.js → open-KXDXEKRZ.js} +39 -36
- package/dist/open-KXDXEKRZ.js.map +1 -0
- package/dist/{prompt-ANTQWHUF.js → prompt-7INJ7YRU.js} +4 -2
- package/dist/prompt-7INJ7YRU.js.map +1 -0
- package/dist/prompts/init-prompt.txt +563 -91
- package/dist/prompts/issue-prompt.txt +27 -27
- package/dist/{rebase-KBWFDZCN.js → rebase-Q7GMM7EI.js} +6 -6
- package/dist/{remote-GJEZWRCC.js → remote-VUNCQZ6J.js} +5 -2
- package/dist/remote-VUNCQZ6J.js.map +1 -0
- package/dist/{run-4SVQ3WEU.js → run-PAWJJCSX.js} +39 -36
- package/dist/run-PAWJJCSX.js.map +1 -0
- package/dist/schema/settings.schema.json +74 -0
- package/dist/{terminal-3D6TUAKJ.js → terminal-BIRBZ4AZ.js} +2 -2
- package/dist/terminal-BIRBZ4AZ.js.map +1 -0
- package/dist/{test-git-MKZATGZN.js → test-git-3WDLNQCA.js} +3 -3
- package/dist/{test-prefix-ZNLWDI3K.js → test-prefix-EVGAWAJW.js} +3 -3
- package/dist/{test-tabs-JRKY3QMM.js → test-tabs-RXDBZ6J7.js} +2 -2
- package/dist/{test-webserver-M2I3EV4J.js → test-webserver-DAHONWCS.js} +4 -4
- package/dist/test-webserver-DAHONWCS.js.map +1 -0
- package/package.json +2 -1
- package/dist/ClaudeContextManager-JKR4WGNU.js +0 -13
- package/dist/ClaudeService-55DQGB7T.js +0 -12
- package/dist/GitHubService-LWP4GKGH.js +0 -11
- package/dist/LoomLauncher-UMMLPIZO.js.map +0 -1
- package/dist/add-issue-X56V3XPB.js +0 -69
- package/dist/add-issue-X56V3XPB.js.map +0 -1
- package/dist/chunk-BLCTGFZN.js.map +0 -1
- package/dist/chunk-ELFT36PV.js.map +0 -1
- package/dist/chunk-FXV24OYZ.js.map +0 -1
- package/dist/chunk-H4E4THUZ.js +0 -55
- package/dist/chunk-H4E4THUZ.js.map +0 -1
- package/dist/chunk-H5LDRGVK.js +0 -642
- package/dist/chunk-H5LDRGVK.js.map +0 -1
- package/dist/chunk-JXQXSC45.js.map +0 -1
- package/dist/chunk-KOCQAD2E.js.map +0 -1
- package/dist/chunk-PR7FKQBG.js.map +0 -1
- package/dist/chunk-PVAVNJKS.js.map +0 -1
- package/dist/chunk-Q2KYPAH2.js +0 -545
- package/dist/chunk-Q2KYPAH2.js.map +0 -1
- package/dist/chunk-RSRO7564.js.map +0 -1
- package/dist/chunk-SPYPLHMK.js.map +0 -1
- package/dist/chunk-VCMMAFXQ.js +0 -54
- package/dist/chunk-VCMMAFXQ.js.map +0 -1
- package/dist/chunk-VVH3ANF2.js.map +0 -1
- package/dist/chunk-VYQLLHZ7.js +0 -239
- package/dist/chunk-VYQLLHZ7.js.map +0 -1
- package/dist/chunk-ZMNQBJUI.js.map +0 -1
- package/dist/chunk-ZWXJBSUW.js.map +0 -1
- package/dist/cleanup-ZHROIBSQ.js.map +0 -1
- package/dist/enhance-VGWUX474.js +0 -176
- package/dist/enhance-VGWUX474.js.map +0 -1
- package/dist/finish-QJSK6Z7J.js +0 -1355
- package/dist/finish-QJSK6Z7J.js.map +0 -1
- package/dist/ignite-HICLZEYU.js.map +0 -1
- package/dist/init-UMKNHNV5.js.map +0 -1
- package/dist/mcp/chunk-6SDFJ42P.js +0 -62
- package/dist/mcp/chunk-6SDFJ42P.js.map +0 -1
- package/dist/mcp/claude-YHHHLSXH.js +0 -249
- package/dist/mcp/claude-YHHHLSXH.js.map +0 -1
- package/dist/mcp/color-QS5BFCNN.js +0 -168
- package/dist/mcp/color-QS5BFCNN.js.map +0 -1
- package/dist/mcp/github-comment-server.js +0 -168
- package/dist/mcp/github-comment-server.js.map +0 -1
- package/dist/mcp/terminal-SDCMDVD7.js +0 -202
- package/dist/mcp/terminal-SDCMDVD7.js.map +0 -1
- package/dist/open-ETZUFSE4.js.map +0 -1
- package/dist/run-4SVQ3WEU.js.map +0 -1
- package/dist/start-CT2ZEFP2.js +0 -983
- package/dist/start-CT2ZEFP2.js.map +0 -1
- package/dist/test-webserver-M2I3EV4J.js.map +0 -1
- /package/dist/{ClaudeContextManager-JKR4WGNU.js.map → BranchNamingService-3OQPRSWT.js.map} +0 -0
- /package/dist/{ClaudeService-55DQGB7T.js.map → ClaudeContextManager-MUQSDY2E.js.map} +0 -0
- /package/dist/{GitHubService-LWP4GKGH.js.map → ClaudeService-HG4VQ7AW.js.map} +0 -0
- /package/dist/{PromptTemplateManager-WII75TKH.js.map → GitHubService-EBOETDIW.js.map} +0 -0
- /package/dist/{SettingsManager-SKLUVE3K.js.map → ProjectCapabilityDetector-34LU7JJ4.js.map} +0 -0
- /package/dist/{claude-7LUVDZZ4.js.map → PromptTemplateManager-A52RUAMS.js.map} +0 -0
- /package/dist/{git-OUYMVYJX.js.map → SettingsManager-WHHFGSL7.js.map} +0 -0
- /package/dist/{neon-helpers-ZVIRPKCI.js.map → SettingsMigrationManager-AGIIIPDQ.js.map} +0 -0
- /package/dist/{chunk-DEPYQRRB.js.map → chunk-C5QCTEQK.js.map} +0 -0
- /package/dist/{chunk-CWR2SANQ.js.map → chunk-EBISESAP.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-MTQIMI54.js.map → chunk-KLBYVHPK.js.map} +0 -0
- /package/dist/{chunk-USVVV3FP.js.map → chunk-MKWYLDFK.js.map} +0 -0
- /package/dist/{chunk-GZP4UGGM.js.map → chunk-ZM3CFL5L.js.map} +0 -0
- /package/dist/{prompt-ANTQWHUF.js.map → claude-GOP6PFC7.js.map} +0 -0
- /package/dist/{remote-GJEZWRCC.js.map → git-TDXKRTXM.js.map} +0 -0
- /package/dist/{terminal-3D6TUAKJ.js.map → neon-helpers-WPUACUVC.js.map} +0 -0
- /package/dist/{rebase-KBWFDZCN.js.map → rebase-Q7GMM7EI.js.map} +0 -0
- /package/dist/{test-git-MKZATGZN.js.map → test-git-3WDLNQCA.js.map} +0 -0
- /package/dist/{test-prefix-ZNLWDI3K.js.map → test-prefix-EVGAWAJW.js.map} +0 -0
- /package/dist/{test-tabs-JRKY3QMM.js.map → test-tabs-RXDBZ6J7.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/LoomManager.ts","../src/lib/VSCodeIntegration.ts","../src/commands/start.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { GitWorktreeManager } from './GitWorktreeManager.js'\nimport { GitHubService } from './GitHubService.js'\nimport { EnvironmentManager } from './EnvironmentManager.js'\nimport { ClaudeContextManager } from './ClaudeContextManager.js'\nimport { ProjectCapabilityDetector } from './ProjectCapabilityDetector.js'\nimport { CLIIsolationManager } from './CLIIsolationManager.js'\nimport { VSCodeIntegration } from './VSCodeIntegration.js'\nimport { SettingsManager } from './SettingsManager.js'\nimport { branchExists, executeGitCommand, ensureRepositoryHasCommits } from '../utils/git.js'\nimport { installDependencies } from '../utils/package-manager.js'\nimport { generateColorFromBranchName } from '../utils/color.js'\nimport { DatabaseManager } from './DatabaseManager.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport type { Loom, CreateLoomInput } from '../types/loom.js'\nimport type { GitWorktree } from '../types/worktree.js'\nimport type { Issue, PullRequest } from '../types/index.js'\nimport { logger } from '../utils/logger.js'\n\n/**\n * LoomManager orchestrates the creation and management of looms (isolated workspaces)\n * Bridges the gap between input validation and workspace operations\n */\nexport class LoomManager {\n constructor(\n private gitWorktree: GitWorktreeManager,\n private github: GitHubService,\n private environment: EnvironmentManager,\n _claude: ClaudeContextManager, // Not stored - kept for DI compatibility, LoomLauncher creates its own\n private capabilityDetector: ProjectCapabilityDetector,\n private cliIsolation: CLIIsolationManager,\n private settings: SettingsManager,\n private database?: DatabaseManager\n ) {}\n\n /**\n * Create a new loom (isolated workspace)\n * Orchestrates worktree creation, environment setup, and Claude context generation\n * NEW: Checks for existing worktrees and reuses them if found\n */\n async createIloom(input: CreateLoomInput): Promise<Loom> {\n // 1. Fetch GitHub data if needed\n logger.info('Fetching GitHub data...')\n const githubData = await this.fetchGitHubData(input)\n\n // NEW: Check for existing worktree BEFORE generating branch name (for efficiency)\n if (input.type === 'issue' || input.type === 'pr') {\n logger.info('Checking for existing worktree...')\n const existing = await this.findExistingIloom(input, githubData)\n if (existing) {\n logger.success(`Found existing worktree, reusing: ${existing.path}`)\n return await this.reuseIloom(existing, input, githubData)\n }\n logger.info('No existing worktree found, creating new one...')\n }\n\n // 2. Generate or validate branch name\n logger.info('Preparing branch name...')\n const branchName = await this.prepareBranchName(input, githubData)\n\n // 3. Create git worktree (WITHOUT dependency installation)\n logger.info('Creating git worktree...')\n const worktreePath = await this.createWorktreeOnly(input, branchName)\n\n // 4. Load main .env variables into process.env (like bash script lines 336-339)\n this.loadMainEnvFile()\n\n // 5. Detect project capabilities\n const { capabilities, binEntries } = await this.capabilityDetector.detectCapabilities(worktreePath)\n\n // 6. Copy environment files (.env) - ALWAYS done regardless of capabilities\n await this.copyEnvironmentFiles(worktreePath)\n\n // 7. Copy Loom settings (settings.local.json) - ALWAYS done regardless of capabilities\n await this.copyIloomSettings(worktreePath)\n\n // 8. Setup PORT environment variable - ONLY for web projects\n // Load base port from settings\n const settingsData = await this.settings.loadSettings()\n const basePort = settingsData.capabilities?.web?.basePort ?? 3000\n\n let port = basePort // default\n if (capabilities.includes('web')) {\n port = await this.setupPortForWeb(worktreePath, input, basePort)\n }\n\n // 9. Install dependencies AFTER environment setup (like bash script line 757-769)\n try {\n await installDependencies(worktreePath, true)\n } catch (error) {\n // Log warning but don't fail - matches bash script behavior\n logger.warn(`Failed to install dependencies: ${error instanceof Error ? error.message : 'Unknown error'}`, error)\n }\n\n // 10. Setup database branch if configured\n let databaseBranch: string | undefined = undefined\n if (this.database && !input.options?.skipDatabase) {\n try {\n const connectionString = await this.database.createBranchIfConfigured(\n branchName,\n path.join(worktreePath, '.env')\n )\n\n if (connectionString) {\n await this.environment.setEnvVar(\n path.join(worktreePath, '.env'),\n this.database.getConfiguredVariableName(),\n connectionString\n )\n logger.success('Database branch configured')\n databaseBranch = branchName\n }\n } catch (error) {\n logger.error(\n `Failed to setup database branch: ${error instanceof Error ? error.message : 'Unknown error'}`\n )\n throw error // Database creation failures are fatal\n }\n }\n\n // 10. Setup CLI isolation if project has CLI capability\n let cliSymlinks: string[] | undefined = undefined\n if (capabilities.includes('cli')) {\n try {\n cliSymlinks = await this.cliIsolation.setupCLIIsolation(\n worktreePath,\n input.identifier,\n binEntries\n )\n } catch (error) {\n // Log warning but don't fail - matches dependency installation behavior\n logger.warn(\n `Failed to setup CLI isolation: ${error instanceof Error ? error.message : 'Unknown error'}`,\n error\n )\n }\n }\n\n // 11. Apply color synchronization (terminal and VSCode)\n if (!input.options?.skipColorSync) {\n try {\n await this.applyColorSynchronization(worktreePath, branchName)\n } catch (error) {\n // Log warning but don't fail - colors are cosmetic\n logger.warn(\n `Failed to apply color synchronization: ${error instanceof Error ? error.message : 'Unknown error'}`,\n error\n )\n }\n }\n\n // NEW: Move issue to In Progress (for new worktrees)\n if (input.type === 'issue') {\n try {\n logger.info('Moving issue to In Progress...')\n await this.github.moveIssueToInProgress(input.identifier as number)\n } catch (error) {\n // Warn but don't fail - matches bash script behavior\n logger.warn(\n `Failed to move issue to In Progress: ${error instanceof Error ? error.message : 'Unknown error'}`,\n error\n )\n }\n }\n\n // 8. Launch workspace components based on individual flags\n const enableClaude = input.options?.enableClaude !== false\n const enableCode = input.options?.enableCode !== false\n const enableDevServer = input.options?.enableDevServer !== false\n const enableTerminal = input.options?.enableTerminal ?? false\n const oneShot = input.options?.oneShot ?? 'default'\n const setArguments = input.options?.setArguments\n const executablePath = input.options?.executablePath\n\n // Only launch if at least one component is enabled\n if (enableClaude || enableCode || enableDevServer || enableTerminal) {\n const { LoomLauncher } = await import('./LoomLauncher.js')\n const { ClaudeContextManager } = await import('./ClaudeContextManager.js')\n\n // Create ClaudeContextManager with shared SettingsManager to ensure CLI overrides work\n const claudeContext = new ClaudeContextManager(undefined, undefined, this.settings)\n const launcher = new LoomLauncher(claudeContext)\n\n await launcher.launchLoom({\n enableClaude,\n enableCode,\n enableDevServer,\n enableTerminal,\n worktreePath,\n branchName,\n port,\n capabilities,\n workflowType: input.type === 'branch' ? 'regular' : input.type,\n identifier: input.identifier,\n ...(githubData?.title && { title: githubData.title }),\n oneShot,\n ...(setArguments && { setArguments }),\n ...(executablePath && { executablePath }),\n })\n }\n\n // 9. Create and return loom metadata\n const loom: Loom = {\n id: this.generateLoomId(input),\n path: worktreePath,\n branch: branchName,\n type: input.type,\n identifier: input.identifier,\n port,\n createdAt: new Date(),\n lastAccessed: new Date(),\n ...(databaseBranch !== undefined && { databaseBranch }),\n ...(capabilities.length > 0 && { capabilities }),\n ...(Object.keys(binEntries).length > 0 && { binEntries }),\n ...(cliSymlinks && cliSymlinks.length > 0 && { cliSymlinks }),\n ...(githubData !== null && {\n githubData: {\n title: githubData.title,\n body: githubData.body,\n url: githubData.url,\n state: githubData.state,\n },\n }),\n }\n\n logger.success(`Created loom: ${loom.id} at ${loom.path}`)\n return loom\n }\n\n /**\n * Finish a loom (merge work and cleanup)\n * Not yet implemented - see Issue #7\n */\n async finishIloom(_identifier: string): Promise<void> {\n throw new Error('Not implemented - see Issue #7')\n }\n\n\n /**\n * List all active looms\n */\n async listLooms(): Promise<Loom[]> {\n const worktrees = await this.gitWorktree.listWorktrees()\n return await this.mapWorktreesToLooms(worktrees)\n }\n\n /**\n * Find a specific loom by identifier\n */\n async findIloom(identifier: string): Promise<Loom | null> {\n const looms = await this.listLooms()\n return (\n looms.find(\n h =>\n h.id === identifier ||\n h.identifier.toString() === identifier ||\n h.branch === identifier\n ) ?? null\n )\n }\n\n /**\n * Fetch GitHub data based on input type\n */\n private async fetchGitHubData(\n input: CreateLoomInput\n ): Promise<Issue | PullRequest | null> {\n if (input.type === 'issue') {\n return await this.github.fetchIssue(input.identifier as number)\n } else if (input.type === 'pr') {\n return await this.github.fetchPR(input.identifier as number)\n }\n return null\n }\n\n /**\n * Prepare branch name based on input type and GitHub data\n */\n private async prepareBranchName(\n input: CreateLoomInput,\n githubData: Issue | PullRequest | null\n ): Promise<string> {\n if (input.type === 'branch') {\n return input.identifier as string\n }\n\n if (input.type === 'pr' && githubData && 'branch' in githubData) {\n return githubData.branch\n }\n\n if (input.type === 'issue' && githubData) {\n // Use Claude AI-powered branch name generation\n const branchName = await this.github.generateBranchName({\n issueNumber: input.identifier as number,\n title: githubData.title,\n })\n return branchName\n }\n\n // Fallback for edge cases\n if (input.type === 'pr') {\n return `pr-${input.identifier}`\n }\n\n throw new Error(`Unable to determine branch name for input type: ${input.type}`)\n }\n\n /**\n * Create worktree for the loom (without dependency installation)\n */\n private async createWorktreeOnly(\n input: CreateLoomInput,\n branchName: string\n ): Promise<string> {\n // Ensure repository has at least one commit (needed for worktree creation)\n // This handles the case where the repo is completely empty (post git init, pre-first commit)\n logger.info('Ensuring repository has initial commit...')\n await ensureRepositoryHasCommits(this.gitWorktree.workingDirectory)\n\n // Load worktree prefix from settings\n const settingsData = await this.settings.loadSettings()\n const worktreePrefix = settingsData.worktreePrefix\n\n // Build options object, only including prefix if it's defined\n const pathOptions: { isPR?: boolean; prNumber?: number; prefix?: string } =\n input.type === 'pr'\n ? { isPR: true, prNumber: input.identifier as number }\n : {}\n\n if (worktreePrefix !== undefined) {\n pathOptions.prefix = worktreePrefix\n }\n\n const worktreePath = this.gitWorktree.generateWorktreePath(\n branchName,\n undefined,\n pathOptions\n )\n\n // Fetch all remote branches to ensure we have latest refs (especially for PRs)\n // Ports: bash script lines 667-674\n if (input.type === 'pr') {\n logger.info('Fetching all remote branches...')\n try {\n await executeGitCommand(['fetch', 'origin'], { cwd: this.gitWorktree.workingDirectory })\n logger.success('Successfully fetched from remote')\n } catch (error) {\n throw new Error(\n `Failed to fetch from remote: ${error instanceof Error ? error.message : 'Unknown error'}. ` +\n `Make sure you have access to the repository.`\n )\n }\n }\n\n // Check if branch exists locally (used for different purposes depending on type)\n const branchExistedLocally = await branchExists(branchName)\n\n // For non-PRs, throw error if branch exists\n // For PRs, we'll use this to determine if we need to reset later\n if (input.type !== 'pr' && branchExistedLocally) {\n throw new Error(\n `Cannot create worktree: branch '${branchName}' already exists. ` +\n `Use 'git branch -D ${branchName}' to delete it first if needed.`\n )\n }\n\n await this.gitWorktree.createWorktree({\n path: worktreePath,\n branch: branchName,\n createBranch: input.type !== 'pr', // PRs use existing branches\n ...(input.baseBranch && { baseBranch: input.baseBranch }),\n })\n\n // Reset PR branch to match remote exactly (if we created a new local branch)\n // Ports: bash script lines 689-713\n if (input.type === 'pr' && !branchExistedLocally) {\n logger.info('Resetting new PR branch to match remote exactly...')\n try {\n await executeGitCommand(['reset', '--hard', `origin/${branchName}`], { cwd: worktreePath })\n await executeGitCommand(['branch', '--set-upstream-to', `origin/${branchName}`], { cwd: worktreePath })\n logger.success('Successfully reset to match remote')\n } catch (error) {\n logger.warn(`Failed to reset to match remote: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n return worktreePath\n }\n\n /**\n * Copy user application environment files (.env) from main repo to worktree\n * Always called regardless of project capabilities\n */\n private async copyEnvironmentFiles(worktreePath: string): Promise<void> {\n const envFilePath = path.join(worktreePath, '.env')\n\n try {\n const mainEnvPath = path.join(process.cwd(), '.env')\n if (await fs.pathExists(envFilePath)) {\n logger.warn('.env file already exists in worktree, skipping copy')\n } else {\n //TODO: Update this to handle .env.local, .env.development and .env.development.local as well.\n await this.environment.copyIfExists(mainEnvPath, envFilePath)\n }\n } catch (error) {\n // Handle gracefully if main .env fails to copy\n logger.warn(`Warning: Failed to copy main .env file: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n /**\n * Copy iloom configuration (settings.local.json) from main repo to worktree\n * Always called regardless of project capabilities\n */\n private async copyIloomSettings(worktreePath: string): Promise<void> {\n const mainSettingsLocalPath = path.join(process.cwd(), '.iloom', 'settings.local.json')\n\n try {\n const worktreeIloomDir = path.join(worktreePath, '.iloom')\n\n // Ensure .iloom directory exists in worktree\n await fs.ensureDir(worktreeIloomDir)\n\n const worktreeSettingsLocalPath = path.join(worktreeIloomDir, 'settings.local.json')\n // Check if settings.local.json already exists in worktree\n if (await fs.pathExists(worktreeSettingsLocalPath)) {\n logger.warn('settings.local.json already exists in worktree, skipping copy')\n } else {\n await this.environment.copyIfExists(mainSettingsLocalPath, worktreeSettingsLocalPath)\n }\n } catch (error) {\n logger.warn(`Warning: Failed to copy settings.local.json: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n /**\n * Setup PORT environment variable for web projects\n * Only called when project has web capabilities\n */\n private async setupPortForWeb(\n worktreePath: string,\n input: CreateLoomInput,\n basePort: number\n ): Promise<number> {\n const envFilePath = path.join(worktreePath, '.env')\n\n // Calculate port based on input type\n const options: { basePort: number; issueNumber?: number; prNumber?: number; branchName?: string } = { basePort }\n\n if (input.type === 'issue') {\n options.issueNumber = input.identifier as number\n } else if (input.type === 'pr') {\n options.prNumber = input.identifier as number\n } else if (input.type === 'branch') {\n options.branchName = input.identifier as string\n }\n\n const port = this.environment.calculatePort(options)\n\n await this.environment.setEnvVar(envFilePath, 'PORT', String(port))\n return port\n }\n\n /**\n * Load environment variables from main .env file into process.env\n * Uses dotenv-flow to handle various .env file patterns\n */\n private loadMainEnvFile(): void {\n const result = loadEnvIntoProcess({ path: process.cwd() })\n\n if (result.error) {\n // Handle gracefully if .env files don't exist\n logger.warn(`Warning: Could not load .env files: ${result.error.message}`)\n } else {\n logger.info('Loaded environment variables using dotenv-flow')\n if (result.parsed && Object.keys(result.parsed).length > 0) {\n logger.debug(`Loaded ${Object.keys(result.parsed).length} environment variables`)\n }\n }\n }\n\n /**\n * Generate a unique loom ID\n */\n private generateLoomId(input: CreateLoomInput): string {\n const prefix = input.type\n return `${prefix}-${input.identifier}`\n }\n\n /**\n * Calculate port for the loom\n * Base port: configurable via settings.capabilities.web.basePort (default 3000) + issue/PR number (or deterministic hash for branches)\n */\n private async calculatePort(input: CreateLoomInput): Promise<number> {\n // Load base port from settings\n const settingsData = await this.settings.loadSettings()\n const basePort = settingsData.capabilities?.web?.basePort ?? 3000\n\n if (input.type === 'issue' && typeof input.identifier === 'number') {\n return this.environment.calculatePort({ basePort, issueNumber: input.identifier })\n }\n\n if (input.type === 'pr' && typeof input.identifier === 'number') {\n return this.environment.calculatePort({ basePort, prNumber: input.identifier })\n }\n\n if (input.type === 'branch' && typeof input.identifier === 'string') {\n // Use deterministic hash for branch-based ports\n return this.environment.calculatePort({ basePort, branchName: input.identifier })\n }\n\n // Fallback: basePort only (shouldn't reach here with valid input)\n throw new Error(`Unknown input type: ${input.type}`)\n }\n\n\n /**\n * Apply color synchronization to both VSCode and terminal\n * Colors are cosmetic - errors are logged but don't block workflow\n */\n private async applyColorSynchronization(\n worktreePath: string,\n branchName: string\n ): Promise<void> {\n const colorData = generateColorFromBranchName(branchName)\n\n // Apply VSCode title bar color\n const vscode = new VSCodeIntegration()\n await vscode.setTitleBarColor(worktreePath, colorData.hex)\n\n logger.info(`Applied VSCode title bar color: ${colorData.hex} for branch: ${branchName}`)\n\n // Note: Terminal color is applied during window creation in ClaudeContextManager\n // This ensures the color is set when the new terminal window is opened\n }\n\n /**\n * Map worktrees to loom objects\n * This is a simplified conversion - in production we'd store loom metadata\n */\n private async mapWorktreesToLooms(worktrees: GitWorktree[]): Promise<Loom[]> {\n return await Promise.all(worktrees.map(async (wt) => {\n // Extract identifier from branch name\n let type: 'issue' | 'pr' | 'branch' = 'branch'\n let identifier: string | number = wt.branch\n\n if (wt.branch.startsWith('issue-')) {\n type = 'issue'\n identifier = parseInt(wt.branch.replace('issue-', ''), 10)\n } else if (wt.branch.startsWith('pr-')) {\n type = 'pr'\n identifier = parseInt(wt.branch.replace('pr-', ''), 10)\n }\n\n return {\n id: `${type}-${identifier}`,\n path: wt.path,\n branch: wt.branch,\n type,\n identifier,\n port: await this.calculatePort({ type, identifier, originalInput: '' }),\n createdAt: new Date(),\n lastAccessed: new Date(),\n }\n }))\n }\n\n /**\n * NEW: Find existing loom for the given input\n * Checks for worktrees matching the issue/PR identifier\n */\n private async findExistingIloom(\n input: CreateLoomInput,\n githubData: Issue | PullRequest | null\n ): Promise<GitWorktree | null> {\n if (input.type === 'issue') {\n return await this.gitWorktree.findWorktreeForIssue(input.identifier as number)\n } else if (input.type === 'pr' && githubData && 'branch' in githubData) {\n return await this.gitWorktree.findWorktreeForPR(\n input.identifier as number,\n githubData.branch\n )\n }\n return null\n }\n\n /**\n * NEW: Reuse an existing loom\n * Includes environment setup and database branching for existing worktrees\n * Ports: handle_existing_worktree() from bash script lines 168-215\n */\n private async reuseIloom(\n worktree: GitWorktree,\n input: CreateLoomInput,\n githubData: Issue | PullRequest | null\n ): Promise<Loom> {\n const worktreePath = worktree.path\n const branchName = worktree.branch\n\n // 1. Load main .env variables into process.env\n this.loadMainEnvFile()\n\n // 2. Detect capabilities (quick, no installation)\n const { capabilities, binEntries } = await this.capabilityDetector.detectCapabilities(worktreePath)\n\n // 3. Defensively copy .env and settings.local.json if missing\n await this.copyEnvironmentFiles(worktreePath)\n await this.copyIloomSettings(worktreePath)\n\n // 4. Setup PORT for web projects (ensure it's set even if .env existed)\n // Load base port from settings\n const settingsData = await this.settings.loadSettings()\n const basePort = settingsData.capabilities?.web?.basePort ?? 3000\n\n let port = basePort\n if (capabilities.includes('web')) {\n port = await this.setupPortForWeb(worktreePath, input, basePort)\n }\n\n // 5. Skip database branch creation for existing worktrees\n // The database branch should have been created when the worktree was first created\n // Matches bash script behavior: handle_existing_worktree() skips all setup\n logger.info('Database branch assumed to be already configured for existing worktree')\n const databaseBranch: string | undefined = undefined\n\n // 6. Move issue to In Progress (for reused worktrees too)\n if (input.type === 'issue') {\n try {\n logger.info('Moving issue to In Progress...')\n await this.github.moveIssueToInProgress(input.identifier as number)\n } catch (error) {\n logger.warn(\n `Failed to move issue to In Progress: ${error instanceof Error ? error.message : 'Unknown error'}`,\n error\n )\n }\n }\n\n // 7. Launch components (same as new worktree)\n const enableClaude = input.options?.enableClaude !== false\n const enableCode = input.options?.enableCode !== false\n const enableDevServer = input.options?.enableDevServer !== false\n const enableTerminal = input.options?.enableTerminal ?? false\n const oneShot = input.options?.oneShot ?? 'default'\n const setArguments = input.options?.setArguments\n const executablePath = input.options?.executablePath\n\n if (enableClaude || enableCode || enableDevServer || enableTerminal) {\n logger.info('Launching workspace components...')\n const { LoomLauncher } = await import('./LoomLauncher.js')\n const { ClaudeContextManager } = await import('./ClaudeContextManager.js')\n\n // Create ClaudeContextManager with shared SettingsManager to ensure CLI overrides work\n const claudeContext = new ClaudeContextManager(undefined, undefined, this.settings)\n const launcher = new LoomLauncher(claudeContext)\n\n await launcher.launchLoom({\n enableClaude,\n enableCode,\n enableDevServer,\n enableTerminal,\n worktreePath,\n branchName,\n port,\n capabilities,\n workflowType: input.type === 'branch' ? 'regular' : input.type,\n identifier: input.identifier,\n ...(githubData?.title && { title: githubData.title }),\n oneShot,\n ...(setArguments && { setArguments }),\n ...(executablePath && { executablePath }),\n })\n }\n\n // 8. Return loom metadata\n const loom: Loom = {\n id: this.generateLoomId(input),\n path: worktreePath,\n branch: branchName,\n type: input.type,\n identifier: input.identifier,\n port,\n createdAt: new Date(), // We don't have actual creation date, use now\n lastAccessed: new Date(),\n ...(databaseBranch !== undefined && { databaseBranch }),\n ...(capabilities.length > 0 && { capabilities }),\n ...(Object.keys(binEntries).length > 0 && { binEntries }),\n ...(githubData !== null && {\n githubData: {\n title: githubData.title,\n body: githubData.body,\n url: githubData.url,\n state: githubData.state,\n },\n }),\n }\n\n logger.success(`Reused existing loom: ${loom.id} at ${loom.path}`)\n return loom\n }\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport { parse, modify, applyEdits } from 'jsonc-parser'\nimport { logger } from '../utils/logger.js'\nimport {\n\thexToRgb,\n\trgbToHex,\n\tlightenColor,\n\tcalculateForegroundColor,\n} from '../utils/color.js'\n\n/**\n * VSCode settings structure\n */\ninterface VSCodeSettings {\n\t'workbench.colorCustomizations'?: {\n\t\t// Title Bar\n\t\t'titleBar.activeBackground'?: string\n\t\t'titleBar.inactiveBackground'?: string\n\t\t'titleBar.activeForeground'?: string\n\t\t'titleBar.inactiveForeground'?: string\n\t\t// Status Bar\n\t\t'statusBar.background'?: string\n\t\t'statusBar.foreground'?: string\n\t\t'statusBarItem.hoverBackground'?: string\n\t\t'statusBarItem.remoteBackground'?: string\n\t\t'statusBarItem.remoteForeground'?: string\n\t\t// UI Accents\n\t\t'sash.hoverBorder'?: string\n\t\t'commandCenter.border'?: string\n\t\t[key: string]: string | undefined\n\t}\n\t[key: string]: unknown\n}\n\n/**\n * Manages VSCode settings.json manipulation for workspace color synchronization\n */\nexport class VSCodeIntegration {\n\t/**\n\t * Set VSCode title bar color for a workspace\n\t *\n\t * @param workspacePath - Path to workspace directory\n\t * @param hexColor - Hex color string (e.g., \"#dcebf8\")\n\t */\n\tasync setTitleBarColor(workspacePath: string, hexColor: string): Promise<void> {\n\t\tconst vscodeDir = path.join(workspacePath, '.vscode')\n\t\tconst settingsPath = path.join(vscodeDir, 'settings.json')\n\n\t\ttry {\n\t\t\t// Ensure .vscode directory exists\n\t\t\tawait fs.ensureDir(vscodeDir)\n\n\t\t\t// Read existing settings (or create empty object)\n\t\t\tconst settings = await this.readSettings(settingsPath)\n\n\t\t\t// Merge color settings\n\t\t\tconst updatedSettings = this.mergeColorSettings(settings, hexColor)\n\n\t\t\t// Write settings atomically\n\t\t\tawait this.writeSettings(settingsPath, updatedSettings)\n\n\t\t\tlogger.debug(`Set VSCode title bar color to ${hexColor} for ${workspacePath}`)\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to set VSCode title bar color: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Read VSCode settings from file\n\t * Supports JSONC (JSON with Comments)\n\t *\n\t * @param settingsPath - Path to settings.json file\n\t * @returns Parsed settings object\n\t */\n\tprivate async readSettings(settingsPath: string): Promise<VSCodeSettings> {\n\t\ttry {\n\t\t\t// Check if file exists\n\t\t\tif (!(await fs.pathExists(settingsPath))) {\n\t\t\t\treturn {}\n\t\t\t}\n\n\t\t\t// Read file content\n\t\t\tconst content = await fs.readFile(settingsPath, 'utf8')\n\n\t\t\t// Parse JSONC (handles comments)\n\t\t\tconst errors: import('jsonc-parser').ParseError[] = []\n\t\t\tconst settings = parse(content, errors, { allowTrailingComma: true })\n\n\t\t\t// Check for parse errors\n\t\t\tif (errors.length > 0) {\n\t\t\t\tconst firstError = errors[0]\n\t\t\t\tthrow new Error(`Invalid JSON: ${firstError ? firstError.error : 'Unknown parse error'}`)\n\t\t\t}\n\n\t\t\treturn settings ?? {}\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse settings.json: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Write VSCode settings to file atomically\n\t * Preserves comments if present (using JSONC parser)\n\t *\n\t * @param settingsPath - Path to settings.json file\n\t * @param settings - Settings object to write\n\t */\n\tprivate async writeSettings(\n\t\tsettingsPath: string,\n\t\tsettings: VSCodeSettings\n\t): Promise<void> {\n\t\ttry {\n\t\t\tlet content: string\n\n\t\t\t// Check if file exists with comments\n\t\t\tif (await fs.pathExists(settingsPath)) {\n\t\t\t\tconst existingContent = await fs.readFile(settingsPath, 'utf8')\n\n\t\t\t\t// Try to preserve comments by using jsonc-parser's modify function\n\t\t\t\tif (existingContent.includes('//') || existingContent.includes('/*')) {\n\t\t\t\t\t// File has comments - use JSONC modify to preserve them\n\t\t\t\t\tcontent = await this.modifyWithCommentsPreserved(existingContent, settings)\n\t\t\t\t} else {\n\t\t\t\t\t// No comments - use standard JSON.stringify\n\t\t\t\t\tcontent = JSON.stringify(settings, null, 2) + '\\n'\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// New file - use standard JSON.stringify\n\t\t\t\tcontent = JSON.stringify(settings, null, 2) + '\\n'\n\t\t\t}\n\n\t\t\t// Write atomically using temp file + rename\n\t\t\tconst tempPath = `${settingsPath}.tmp`\n\t\t\tawait fs.writeFile(tempPath, content, 'utf8')\n\t\t\tawait fs.rename(tempPath, settingsPath)\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to write settings.json: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Modify JSONC content while preserving comments\n\t *\n\t * @param existingContent - Original JSONC content\n\t * @param newSettings - New settings to apply\n\t * @returns Modified JSONC content with comments preserved\n\t */\n\tprivate async modifyWithCommentsPreserved(\n\t\texistingContent: string,\n\t\tnewSettings: VSCodeSettings\n\t): Promise<string> {\n\t\tlet modifiedContent = existingContent\n\n\t\t// Apply each setting modification\n\t\tfor (const [key, value] of Object.entries(newSettings)) {\n\t\t\tconst edits = modify(modifiedContent, [key], value, {})\n\t\t\tmodifiedContent = applyEdits(modifiedContent, edits)\n\t\t}\n\n\t\treturn modifiedContent\n\t}\n\n\t/**\n\t * Merge color settings into existing settings object\n\t *\n\t * @param existing - Existing settings object\n\t * @param hexColor - Hex color to apply (subtle palette color)\n\t * @returns Updated settings object with color merged\n\t */\n\tprivate mergeColorSettings(existing: VSCodeSettings, hexColor: string): VSCodeSettings {\n\t\t// Clone existing settings\n\t\tconst updated: VSCodeSettings = { ...existing }\n\n\t\t// Initialize workbench.colorCustomizations if needed\n\t\tupdated['workbench.colorCustomizations'] ??= {}\n\n\t\tconst colors = updated['workbench.colorCustomizations']\n\n\t\t// Convert hex to RGB for manipulation\n\t\tconst baseRgb = hexToRgb(hexColor)\n\n\t\t// Calculate foreground color based on background luminance\n\t\tconst foreground = calculateForegroundColor(baseRgb)\n\t\tconst foregroundTransparent = foreground.replace('#', '#') + '99' // Add 60% opacity\n\n\t\t// Create lighter variant for hover states\n\t\tconst lighterRgb = lightenColor(baseRgb, 0.05) // 5% lighter\n\t\tconst lighterHex = rgbToHex(lighterRgb.r, lighterRgb.g, lighterRgb.b)\n\n\t\t// Title Bar - subtle top indicator\n\t\tcolors['titleBar.activeBackground'] = hexColor\n\t\tcolors['titleBar.inactiveBackground'] = hexColor + '99' // Semi-transparent when unfocused\n\t\tcolors['titleBar.activeForeground'] = foreground\n\t\tcolors['titleBar.inactiveForeground'] = foregroundTransparent\n\n\t\t// Status Bar - constant visibility at bottom\n\t\tcolors['statusBar.background'] = hexColor\n\t\tcolors['statusBar.foreground'] = foreground\n\t\tcolors['statusBarItem.hoverBackground'] = lighterHex\n\t\tcolors['statusBarItem.remoteBackground'] = hexColor // When connected to remote\n\t\tcolors['statusBarItem.remoteForeground'] = foreground\n\n\t\t// UI Accents - subtle hints\n\t\tcolors['sash.hoverBorder'] = hexColor // Resize borders\n\t\tcolors['commandCenter.border'] = foregroundTransparent // Search box border\n\n\t\treturn updated\n\t}\n}\n","import { logger } from '../utils/logger.js'\nimport { GitHubService } from '../lib/GitHubService.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { ClaudeContextManager } from '../lib/ClaudeContextManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { IssueEnhancementService } from '../lib/IssueEnhancementService.js'\nimport { branchExists, findMainWorktreePathWithSettings } from '../utils/git.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport type { StartOptions } from '../types/index.js'\n\nexport interface StartCommandInput {\n\tidentifier: string\n\toptions: StartOptions\n}\n\nexport interface ParsedInput {\n\ttype: 'issue' | 'pr' | 'branch' | 'description'\n\tnumber?: number\n\tbranchName?: string\n\toriginalInput: string\n}\n\nexport class StartCommand {\n\tprivate gitHubService: GitHubService\n\tprivate loomManager: LoomManager | null = null\n\tprivate agentManager: AgentManager\n\tprivate settingsManager: SettingsManager\n\tprivate enhancementService: IssueEnhancementService\n\tprivate providedLoomManager: LoomManager | undefined\n\n\tconstructor(\n\t\tgitHubService?: GitHubService,\n\t\tloomManager?: LoomManager,\n\t\tagentManager?: AgentManager,\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.gitHubService = gitHubService ?? new GitHubService()\n\t\tthis.agentManager = agentManager ?? new AgentManager()\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t\tthis.enhancementService = new IssueEnhancementService(\n\t\t\tthis.gitHubService,\n\t\t\tthis.agentManager,\n\t\t\tthis.settingsManager\n\t\t)\n\t\t// Store provided LoomManager for testing, but don't initialize yet\n\t\tthis.providedLoomManager = loomManager\n\n\t\t// Load environment variables first\n\t\tconst envResult = loadEnvIntoProcess()\n\t\tif (envResult.error) {\n\t\t\tlogger.debug(`Environment loading warning: ${envResult.error.message}`)\n\t\t}\n\t\tif (envResult.parsed) {\n\t\t\tlogger.debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n\t\t}\n\t}\n\n\t/**\n\t * Initialize LoomManager with the main worktree path\n\t * Uses lazy initialization to ensure we have the correct path\n\t */\n\tprivate async initializeLoomManager(): Promise<LoomManager> {\n\t\tif (this.loomManager) {\n\t\t\treturn this.loomManager\n\t\t}\n\n\t\tif (this.providedLoomManager) {\n\t\t\tthis.loomManager = this.providedLoomManager\n\t\t\treturn this.loomManager\n\t\t}\n\n\t\t// Find main worktree path\n\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings()\n\n\t\t// Load settings to get database configuration\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\t// Create DatabaseManager with NeonProvider and EnvironmentManager\n\t\tconst environmentManager = new EnvironmentManager()\n\t\tconst neonProvider = createNeonProviderFromSettings(settings)\n\t\tconst databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n\t\tconst databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n\n\t\tthis.loomManager = new LoomManager(\n\t\t\tnew GitWorktreeManager(mainWorktreePath),\n\t\t\tthis.gitHubService,\n\t\t\tenvironmentManager, // Reuse same instance\n\t\t\tnew ClaudeContextManager(),\n\t\t\tnew ProjectCapabilityDetector(),\n\t\t\tnew CLIIsolationManager(),\n\t\t\tthis.settingsManager, // Use same instance with CLI overrides\n\t\t\tdatabaseManager // Add database manager\n\t\t)\n\n\t\treturn this.loomManager\n\t}\n\n\t/**\n\t * Main entry point for the start command\n\t */\n\tpublic async execute(input: StartCommandInput): Promise<void> {\n\t\ttry {\n\t\t\t// Step 0: Load settings and get configured repo for GitHub operations\n\t\t\tconst initialSettings = await this.settingsManager.loadSettings()\n\t\t\tlet repo: string | undefined\n\n\t\t\t// Only get repo if we have multiple remotes (prehook already validated config)\n\t\t\tconst multipleRemotes = await hasMultipleRemotes()\n\t\t\tif (multipleRemotes) {\n\t\t\t\trepo = await getConfiguredRepoFromSettings(initialSettings)\n\t\t\t\tlogger.info(`Using GitHub repository: ${repo}`)\n\t\t\t}\n\n\t\t\t// Step 0.5: Initialize LoomManager with main worktree path\n\t\t\tconst loomManager = await this.initializeLoomManager()\n\n\t\t\t// Step 1: Parse and validate input (pass repo to methods)\n\t\t\tconst parsed = await this.parseInput(input.identifier, repo)\n\n\t\t\t// Step 2: Validate based on type\n\t\t\tawait this.validateInput(parsed, repo)\n\n\t\t\t// Step 2.5: Handle description input - create GitHub issue\n\t\t\tif (parsed.type === 'description') {\n\t\t\t\tconst issueNumber = await this.enhanceAndCreateIssue(parsed.originalInput)\n\t\t\t\t// Update parsed to be an issue type with the new number\n\t\t\t\tparsed.type = 'issue'\n\t\t\t\tparsed.number = issueNumber\n\t\t\t}\n\n\t\t\t// Step 2.7: Confirm bypassPermissions mode if applicable\n\t\t\tif (input.options.oneShot === 'bypassPermissions') {\n\t\t\t\tconst { promptConfirmation } = await import('../utils/prompt.js')\n\t\t\t\tconst confirmed = await promptConfirmation(\n\t\t\t\t\t'⚠️ WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. ' +\n\t\t\t\t\t'This can be dangerous. Do you want to proceed?'\n\t\t\t\t)\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tlogger.info('Operation cancelled by user')\n\t\t\t\t\tprocess.exit(0)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Step 2.8: Load workflow-specific settings with CLI overrides\n\t\t\tconst cliOverrides = extractSettingsOverrides()\n\t\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\t\tconst workflowType = parsed.type === 'branch' ? 'regular' : parsed.type\n\t\t\tconst workflowConfig = settings.workflows?.[workflowType]\n\n\t\t\t// Step 2.9: Extract raw --set arguments and executable path for forwarding to spin\n\t\t\tconst { extractRawSetArguments, getExecutablePath } = await import('../utils/cli-overrides.js')\n\t\t\tconst setArguments = extractRawSetArguments()\n\t\t\tconst executablePath = getExecutablePath()\n\n\t\t\t// Step 3: Log success and create loom\n\t\t\tlogger.info(`✅ Validated input: ${this.formatParsedInput(parsed)}`)\n\n\t\t\t// Step 4: Create loom using LoomManager\n\t\t\tconst identifier =\n\t\t\t\tparsed.type === 'branch'\n\t\t\t\t\t? parsed.branchName ?? ''\n\t\t\t\t\t: parsed.number ?? 0\n\n\t\t\t// Apply configuration precedence: CLI flags > workflow config > defaults (true)\n\t\t\tconst enableClaude = input.options.claude ?? workflowConfig?.startAiAgent ?? true\n\t\t\tconst enableCode = input.options.code ?? workflowConfig?.startIde ?? true\n\t\t\tconst enableDevServer = input.options.devServer ?? workflowConfig?.startDevServer ?? true\n\t\t\tconst enableTerminal = input.options.terminal ?? workflowConfig?.startTerminal ?? false\n\n\t\t\tlogger.debug('Final workflow config values:', {\n\t\t\t\tenableClaude,\n\t\t\t\tenableCode,\n\t\t\t\tenableDevServer,\n\t\t\t\tenableTerminal,\n\t\t\t})\n\n\t\t\tconst loom = await loomManager.createIloom({\n\t\t\t\ttype: parsed.type,\n\t\t\t\tidentifier,\n\t\t\t\toriginalInput: parsed.originalInput,\n\t\t\t\toptions: {\n\t\t\t\t\tenableClaude,\n\t\t\t\t\tenableCode,\n\t\t\t\t\tenableDevServer,\n\t\t\t\t\tenableTerminal,\n\t\t\t\t\t...(input.options.oneShot && { oneShot: input.options.oneShot }),\n\t\t\t\t\t...(setArguments.length > 0 && { setArguments }),\n\t\t\t\t\t...(executablePath && { executablePath }),\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tlogger.success(`✅ Created loom: ${loom.id} at ${loom.path}`)\n\t\t\tlogger.info(` Branch: ${loom.branch}`)\n\t\t\t// Only show port for web projects\n\t\t\tif (loom.capabilities?.includes('web')) {\n\t\t\t\tlogger.info(` Port: ${loom.port}`)\n\t\t\t}\n\t\t\tif (loom.githubData?.title) {\n\t\t\t\tlogger.info(` Title: ${loom.githubData.title}`)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tlogger.error(`❌ ${error.message}`)\n\t\t\t} else {\n\t\t\t\tlogger.error('❌ An unknown error occurred')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Parse input to determine type and extract relevant data\n\t */\n\tprivate async parseInput(identifier: string, repo?: string): Promise<ParsedInput> {\n\t\t// Handle empty input\n\t\tconst trimmedIdentifier = identifier.trim()\n\t\tif (!trimmedIdentifier) {\n\t\t\tthrow new Error('Missing required argument: identifier')\n\t\t}\n\n\t\t// Check for description: >25 chars AND >2 spaces\n\t\tconst spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length\n\t\tif (trimmedIdentifier.length > 25 && spaceCount > 2) {\n\t\t\treturn {\n\t\t\t\ttype: 'description',\n\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t}\n\t\t}\n\n\t\t// Check for PR-specific formats: pr/123, PR-123, PR/123\n\t\tconst prPattern = /^(?:pr|PR)[/-](\\d+)$/\n\t\tconst prMatch = trimmedIdentifier.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: parseInt(prMatch[1], 10),\n\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t}\n\t\t}\n\n\t\t// Check for numeric pattern (could be issue or PR)\n\t\tconst numericPattern = /^#?(\\d+)$/\n\t\tconst numericMatch = trimmedIdentifier.match(numericPattern)\n\t\tif (numericMatch?.[1]) {\n\t\t\tconst number = parseInt(numericMatch[1], 10)\n\n\t\t\t// Use GitHubService to detect if it's a PR or issue\n\t\t\tconst detection = await this.gitHubService.detectInputType(\n\t\t\t\ttrimmedIdentifier,\n\t\t\t\trepo\n\t\t\t)\n\n\t\t\tif (detection.type === 'pr') {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'pr',\n\t\t\t\t\tnumber: detection.number ?? number,\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t} else if (detection.type === 'issue') {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tnumber: detection.number ?? number,\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Could not find issue or PR #${number}`)\n\t\t\t}\n\t\t}\n\n\t\t// Treat as branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: trimmedIdentifier,\n\t\t\toriginalInput: trimmedIdentifier,\n\t\t}\n\t}\n\n\t/**\n\t * Validate the parsed input based on its type\n\t */\n\tprivate async validateInput(parsed: ParsedInput, repo?: string): Promise<void> {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\t\t\t\t// Fetch and validate PR state\n\t\t\t\tconst pr = await this.gitHubService.fetchPR(parsed.number, repo)\n\t\t\t\tawait this.gitHubService.validatePRState(pr)\n\t\t\t\tlogger.debug(`Validated PR #${parsed.number}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\t\t\t\t// Fetch and validate issue state\n\t\t\t\tconst issue = await this.gitHubService.fetchIssue(parsed.number, repo)\n\t\t\t\tawait this.gitHubService.validateIssueState(issue)\n\t\t\t\tlogger.debug(`Validated issue #${parsed.number}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\t\t\t\t// Validate branch name characters (from bash script line 586)\n\t\t\t\tif (!this.isValidBranchName(parsed.branchName)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes'\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\t// Check if branch already exists\n\t\t\t\tconst exists = await branchExists(parsed.branchName)\n\t\t\t\tif (exists) {\n\t\t\t\t\tthrow new Error(`Branch '${parsed.branchName}' already exists`)\n\t\t\t\t}\n\t\t\t\tlogger.debug(`Validated branch name: ${parsed.branchName}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'description': {\n\t\t\t\t// Description inputs are valid - they will be converted to issues\n\t\t\t\tlogger.debug('Detected description input', {\n\t\t\t\t\tlength: parsed.originalInput.length\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Validate branch name format\n\t */\n\tprivate isValidBranchName(branch: string): boolean {\n\t\t// Pattern from bash script line 586\n\t\treturn /^[a-zA-Z0-9/_-]+$/.test(branch)\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedInput): string {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr':\n\t\t\t\treturn `PR #${parsed.number}`\n\t\t\tcase 'issue':\n\t\t\t\treturn `Issue #${parsed.number}`\n\t\t\tcase 'branch':\n\t\t\t\treturn `Branch '${parsed.branchName}'`\n\t\t\tcase 'description':\n\t\t\t\treturn `Description: ${parsed.originalInput.slice(0, 50)}...`\n\t\t\tdefault:\n\t\t\t\treturn 'Unknown input'\n\t\t}\n\t}\n\n\t/**\n\t * Enhance description using Claude AI and create GitHub issue\n\t * Returns the new issue number\n\t */\n\tprivate async enhanceAndCreateIssue(description: string): Promise<number> {\n\t\t// Use IssueEnhancementService for the workflow\n\t\tconst enhancedDescription = await this.enhancementService.enhanceDescription(description)\n\t\tconst result = await this.enhancementService.createEnhancedIssue(description, enhancedDescription)\n\t\tawait this.enhancementService.waitForReviewAndOpen(result.number, true)\n\n\t\treturn result.number\n\t}\n\n}\n"],"mappings":"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","names":["path","fs","path","ClaudeContextManager","fs"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/test-webserver.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\n\nexport interface TestWebserverOptions {\n\tkill?: boolean\n}\n\nexport interface TestWebserverCommandInput {\n\tissueNumber: number\n\toptions: TestWebserverOptions\n}\n\n/**\n * Command to test if a web server is running on a workspace port\n * and optionally kill it if detected.\n *\n * This uses the ProcessManager to detect processes on ports and\n * safely terminate web servers when requested.\n */\nexport class TestWebserverCommand {\n\tprivate readonly processManager: ProcessManager\n\n\tconstructor(processManager?: ProcessManager) {\n\t\tthis.processManager = processManager ?? new ProcessManager()\n\t}\n\n\t/**\n\t * Main entry point for the test-webserver command\n\t */\n\tpublic async execute(input: TestWebserverCommandInput): Promise<void> {\n\t\tconst { issueNumber, options } = input\n\n\t\t// Validate issue number\n\t\tif (!Number.isInteger(issueNumber) || issueNumber <= 0) {\n\t\t\tthrow new Error('Issue number must be a positive integer')\n\t\t}\n\n\t\t// Calculate port from issue number\n\t\tconst port = this.processManager.calculatePort(issueNumber)\n\t\tlogger.info(`Checking port ${port} (issue #${issueNumber})...`)\n\n\t\t// Detect what's running on the port\n\t\tconst processInfo = await this.processManager.detectDevServer(port)\n\n\t\tif (!processInfo) {\n\t\t\tlogger.info(`No process found on port ${port}`)\n\t\t\treturn\n\t\t}\n\n\t\t// Report what we found\n\t\tlogger.info(`Found process on port ${port}:`)\n\t\tlogger.info(` PID: ${processInfo.pid}`)\n\t\tlogger.info(` Name: ${processInfo.name}`)\n\t\tlogger.info(` Command: ${processInfo.command}`)\n\n\t\tif (processInfo.isDevServer) {\n\t\t\tlogger.success(`Detected as web server`)\n\t\t} else {\n\t\t\tlogger.warn(`Not detected as web server`)\n\t\t\tlogger.info(`This appears to be a non-web-server process. Skipping for safety.`)\n\t\t}\n\n\t\t// Kill process if requested (and it's a web server)\n\t\tif (options.kill) {\n\t\t\tif (!processInfo.isDevServer) {\n\t\t\t\tlogger.error(`Cannot kill non-web-server process (PID ${processInfo.pid}) for safety reasons`)\n\t\t\t\tlogger.info(`Process must match web server patterns to be killed automatically`)\n\t\t\t\tthrow new Error('Cannot kill non-web-server process')\n\t\t\t}\n\n\t\t\tlogger.info(`Terminating web server (PID ${processInfo.pid})...`)\n\t\t\tconst terminated = await this.processManager.terminateProcess(processInfo.pid)\n\n\t\t\tif (terminated) {\n\t\t\t\tlogger.success(`Web server terminated successfully`)\n\n\t\t\t\t// Verify port is now free\n\t\t\t\tconst isFree = await this.processManager.verifyPortFree(port)\n\t\t\t\tif (isFree) {\n\t\t\t\t\tlogger.success(`Port ${port} is now free`)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.warn(`Port ${port} may still be in use (TIME_WAIT state)`)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;AAmBO,IAAM,uBAAN,MAA2B;AAAA,EAGjC,YAAY,gBAAiC;AAC5C,SAAK,iBAAiB,kBAAkB,IAAI,eAAe;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,QAAQ,OAAiD;AACrE,UAAM,EAAE,aAAa,QAAQ,IAAI;AAGjC,QAAI,CAAC,OAAO,UAAU,WAAW,KAAK,eAAe,GAAG;AACvD,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC1D;AAGA,UAAM,OAAO,KAAK,eAAe,cAAc,WAAW;AAC1D,WAAO,KAAK,iBAAiB,IAAI,YAAY,WAAW,MAAM;AAG9D,UAAM,cAAc,MAAM,KAAK,eAAe,gBAAgB,IAAI;AAElE,QAAI,CAAC,aAAa;AACjB,aAAO,KAAK,4BAA4B,IAAI,EAAE;AAC9C;AAAA,IACD;AAGA,WAAO,KAAK,yBAAyB,IAAI,GAAG;AAC5C,WAAO,KAAK,WAAW,YAAY,GAAG,EAAE;AACxC,WAAO,KAAK,YAAY,YAAY,IAAI,EAAE;AAC1C,WAAO,KAAK,eAAe,YAAY,OAAO,EAAE;AAEhD,QAAI,YAAY,aAAa;AAC5B,aAAO,QAAQ,wBAAwB;AAAA,IACxC,OAAO;AACN,aAAO,KAAK,4BAA4B;AACxC,aAAO,KAAK,mEAAmE;AAAA,IAChF;AAGA,QAAI,QAAQ,MAAM;AACjB,UAAI,CAAC,YAAY,aAAa;AAC7B,eAAO,MAAM,2CAA2C,YAAY,GAAG,sBAAsB;AAC7F,eAAO,KAAK,mEAAmE;AAC/E,cAAM,IAAI,MAAM,oCAAoC;AAAA,MACrD;AAEA,aAAO,KAAK,+BAA+B,YAAY,GAAG,MAAM;AAChE,YAAM,aAAa,MAAM,KAAK,eAAe,iBAAiB,YAAY,GAAG;AAE7E,UAAI,YAAY;AACf,eAAO,QAAQ,oCAAoC;AAGnD,cAAM,SAAS,MAAM,KAAK,eAAe,eAAe,IAAI;AAC5D,YAAI,QAAQ;AACX,iBAAO,QAAQ,QAAQ,IAAI,cAAc;AAAA,QAC1C,OAAO;AACN,iBAAO,KAAK,QAAQ,IAAI,wCAAwC;AAAA,QACjE;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|