vde-layout 0.0.2 → 0.0.3
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/index.js +16 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -114,7 +114,7 @@ const ConfigSchema = z.object({ presets: z.record(PresetSchema) });
|
|
|
114
114
|
* @returns Parsed object
|
|
115
115
|
* @throws {ValidationError} When YAML parsing fails
|
|
116
116
|
*/
|
|
117
|
-
|
|
117
|
+
const parseYAML = (yamlText) => {
|
|
118
118
|
if (!yamlText || typeof yamlText !== "string") throw createValidationError("YAML text not provided", ErrorCodes.CONFIG_PARSE_ERROR, { received: typeof yamlText });
|
|
119
119
|
try {
|
|
120
120
|
return YAML.parse(yamlText);
|
|
@@ -124,25 +124,25 @@ function parseYAML(yamlText) {
|
|
|
124
124
|
yamlSnippet: yamlText.substring(0, 200)
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
|
-
}
|
|
127
|
+
};
|
|
128
128
|
/**
|
|
129
129
|
* Validate basic configuration structure
|
|
130
130
|
* @param parsed - Parsed YAML object
|
|
131
131
|
* @throws {ValidationError} When structure is invalid
|
|
132
132
|
*/
|
|
133
|
-
|
|
133
|
+
const validateConfigStructure = (parsed) => {
|
|
134
134
|
if (parsed === null || parsed === void 0 || typeof parsed !== "object") throw createValidationError("YAML is empty or invalid format", ErrorCodes.CONFIG_PARSE_ERROR, { parsed });
|
|
135
135
|
const parsedObj = parsed;
|
|
136
136
|
if (!("presets" in parsedObj) || parsedObj.presets === void 0 || parsedObj.presets === null) throw createValidationError("presets field is required", ErrorCodes.INVALID_PRESET, { availableFields: Object.keys(parsedObj) });
|
|
137
137
|
const presetsObj = parsedObj.presets;
|
|
138
138
|
if (typeof presetsObj !== "object" || presetsObj === null || Object.keys(presetsObj).length === 0) throw createValidationError("At least one preset is required", ErrorCodes.INVALID_PRESET, { presets: presetsObj });
|
|
139
|
-
}
|
|
139
|
+
};
|
|
140
140
|
/**
|
|
141
141
|
* Format Zod validation errors into user-friendly messages
|
|
142
142
|
* @param error - Zod validation error
|
|
143
143
|
* @returns Formatted error issues
|
|
144
144
|
*/
|
|
145
|
-
|
|
145
|
+
const formatZodErrors = (error) => {
|
|
146
146
|
return error.issues.map((issue) => {
|
|
147
147
|
const path$1 = issue.path.join(".");
|
|
148
148
|
let message = issue.message;
|
|
@@ -170,14 +170,14 @@ function formatZodErrors(error) {
|
|
|
170
170
|
code: issue.code
|
|
171
171
|
};
|
|
172
172
|
});
|
|
173
|
-
}
|
|
173
|
+
};
|
|
174
174
|
/**
|
|
175
175
|
* Validates YAML text and converts it to a type-safe Config object
|
|
176
176
|
* @param yamlText - YAML text to validate
|
|
177
177
|
* @returns Validated Config object
|
|
178
178
|
* @throws {ValidationError} When YAML is invalid
|
|
179
179
|
*/
|
|
180
|
-
|
|
180
|
+
const validateYAML = (yamlText) => {
|
|
181
181
|
const parsed = parseYAML(yamlText);
|
|
182
182
|
validateConfigStructure(parsed);
|
|
183
183
|
try {
|
|
@@ -194,7 +194,7 @@ function validateYAML(yamlText) {
|
|
|
194
194
|
if (isVDELayoutError(error) && error.name === "ValidationError") throw error;
|
|
195
195
|
throw createValidationError("Unexpected validation error occurred", ErrorCodes.CONFIG_PARSE_ERROR, { error: error instanceof Error ? error.message : String(error) });
|
|
196
196
|
}
|
|
197
|
-
}
|
|
197
|
+
};
|
|
198
198
|
|
|
199
199
|
//#endregion
|
|
200
200
|
//#region src/config/loader.ts
|
|
@@ -765,7 +765,7 @@ const createAccumulator = () => {
|
|
|
765
765
|
}
|
|
766
766
|
};
|
|
767
767
|
};
|
|
768
|
-
|
|
768
|
+
const runDiagnostics = (input) => {
|
|
769
769
|
const accumulator = createAccumulator();
|
|
770
770
|
const knownIssues = input.knownIssues ?? [];
|
|
771
771
|
let parsedPreset;
|
|
@@ -810,7 +810,7 @@ function runDiagnostics(input) {
|
|
|
810
810
|
nextSteps: Array.from(accumulator.nextSteps),
|
|
811
811
|
backlog: sortBacklog(accumulator.backlog)
|
|
812
812
|
};
|
|
813
|
-
}
|
|
813
|
+
};
|
|
814
814
|
const checkFocusDuplications = (preset, accumulator) => {
|
|
815
815
|
const layout = preset.layout;
|
|
816
816
|
if (layout === void 0 || layout === null) return;
|
|
@@ -1169,8 +1169,10 @@ const collectSplitSteps = (node, steps) => {
|
|
|
1169
1169
|
const appendSplitSteps = (node, steps) => {
|
|
1170
1170
|
const directionFlag = node.orientation === "horizontal" ? "-h" : "-v";
|
|
1171
1171
|
for (let index = 1; index < node.panes.length; index += 1) {
|
|
1172
|
-
const
|
|
1173
|
-
const
|
|
1172
|
+
const remainingIncludingTarget = node.ratio.slice(index - 1).reduce((sum, value) => sum + value, 0);
|
|
1173
|
+
const remainingAfterTarget = node.ratio.slice(index).reduce((sum, value) => sum + value, 0);
|
|
1174
|
+
const desiredPercentage = remainingIncludingTarget === 0 ? 0 : remainingAfterTarget / remainingIncludingTarget * 100;
|
|
1175
|
+
const percentage = Math.max(1, Math.round(desiredPercentage));
|
|
1174
1176
|
const targetPaneId = node.panes[index - 1]?.id ?? node.id;
|
|
1175
1177
|
const createdPaneId = node.panes[index]?.id;
|
|
1176
1178
|
steps.push({
|
|
@@ -1440,7 +1442,7 @@ const createCli = (options = {}) => {
|
|
|
1440
1442
|
* Main entry point
|
|
1441
1443
|
* Launches the CLI application
|
|
1442
1444
|
*/
|
|
1443
|
-
async
|
|
1445
|
+
const main = async () => {
|
|
1444
1446
|
const cli = createCli();
|
|
1445
1447
|
try {
|
|
1446
1448
|
await cli.run(process.argv.slice(2));
|
|
@@ -1451,7 +1453,7 @@ async function main() {
|
|
|
1451
1453
|
} else console.error("An unexpected error occurred:", String(error));
|
|
1452
1454
|
process.exit(1);
|
|
1453
1455
|
}
|
|
1454
|
-
}
|
|
1456
|
+
};
|
|
1455
1457
|
main();
|
|
1456
1458
|
|
|
1457
1459
|
//#endregion
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["formatters: Record<string, (error: VDELayoutError) => string>","SplitPaneSchema: z.ZodType<unknown>","PaneSchema: z.ZodType<unknown>","path","candidates: string[]","mergedConfig: Config","yaml","paths: string[]","existing: string[]","loaderOptions: ConfigLoaderOptions","cachedConfig: Config | null","parseCommand","toCommandString","newWindowCommand: string[]","severityRank: Record<DiagnosticsSeverity, number>","findings: DiagnosticsFinding[]","path","parsedPreset: unknown","parsed: unknown","panes: PlanNode[]","focusPaneIds: string[]","terminalPaneIds: string[]","steps: CommandStep[]","current: PlanNode","KNOWN_ISSUES: ReadonlyArray<string>","functionalCore: FunctionalCoreBridge","defaultCompilePreset","defaultCreateLayoutPlan","defaultEmitPlan","logger: Logger","document: Record<string, unknown>","toYAML","options","compileResult: CompilePresetSuccess","planResult: CreateLayoutPlanSuccess","emission: PlanEmission"],"sources":["../src/utils/errors.ts","../src/models/schema.ts","../src/config/validator.ts","../src/config/loader.ts","../src/layout/preset.ts","../src/utils/logger.ts","../src/executor/real-executor.ts","../src/executor/dry-run-executor.ts","../src/core/errors.ts","../src/executor/plan-runner.ts","../src/core/diagnostics.ts","../src/core/compile.ts","../src/core/planner.ts","../src/core/emitter.ts","../src/cli.ts","../src/index.ts"],"sourcesContent":["export type VDELayoutError = Error & {\n readonly code: string\n readonly details: Readonly<Record<string, unknown>>\n}\n\nexport const ErrorCodes = {\n CONFIG_NOT_FOUND: \"CONFIG_NOT_FOUND\",\n CONFIG_PARSE_ERROR: \"CONFIG_PARSE_ERROR\",\n CONFIG_PERMISSION_ERROR: \"CONFIG_PERMISSION_ERROR\",\n INVALID_PRESET: \"INVALID_PRESET\",\n PRESET_NOT_FOUND: \"PRESET_NOT_FOUND\",\n INVALID_LAYOUT: \"INVALID_LAYOUT\",\n INVALID_PANE: \"INVALID_PANE\",\n TMUX_NOT_RUNNING: \"TMUX_NOT_RUNNING\",\n TMUX_COMMAND_FAILED: \"TMUX_COMMAND_FAILED\",\n NOT_IN_TMUX_SESSION: \"NOT_IN_TMUX_SESSION\",\n NOT_IN_TMUX: \"NOT_IN_TMUX\",\n TMUX_NOT_FOUND: \"TMUX_NOT_FOUND\",\n TMUX_NOT_INSTALLED: \"TMUX_NOT_INSTALLED\",\n UNSUPPORTED_TMUX_VERSION: \"UNSUPPORTED_TMUX_VERSION\",\n} as const\n\nconst createBaseError = (\n name: string,\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n const error = new Error(message) as VDELayoutError\n error.name = name\n ;(error as { code: string }).code = code\n ;(error as { details: Readonly<Record<string, unknown>> }).details = details\n return error\n}\n\nexport const createConfigError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"ConfigError\", message, code, details)\n}\n\nexport const createValidationError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"ValidationError\", message, code, details)\n}\n\nexport const createTmuxError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"TmuxError\", message, code, details)\n}\n\nexport const createEnvironmentError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"EnvironmentError\", message, code, details)\n}\n\nexport const isVDELayoutError = (error: unknown): error is VDELayoutError => {\n if (typeof error !== \"object\" || error === null) {\n return false\n }\n\n if (!(\"code\" in error)) {\n return false\n }\n\n const { code } = error as { code?: unknown }\n if (typeof code !== \"string\") {\n return false\n }\n\n if (!(\"details\" in error)) {\n return false\n }\n\n return true\n}\n\nconst formatters: Record<string, (error: VDELayoutError) => string> = {\n [ErrorCodes.CONFIG_NOT_FOUND]: (error) => {\n const searchPaths = error.details.searchPaths\n if (!Array.isArray(searchPaths)) {\n return \"\"\n }\n\n const lines = [\"\", \"Searched in the following locations:\"]\n searchPaths.forEach((location) => lines.push(` - ${location}`))\n lines.push(\"\", \"To create a configuration file, run:\")\n lines.push(\" mkdir -p ~/.config/vde\")\n lines.push(' echo \"presets: {}\" > ~/.config/vde/layout.yml')\n return lines.join(\"\\n\")\n },\n [ErrorCodes.NOT_IN_TMUX_SESSION]: () => {\n return \"\\nThis command must be run inside a tmux session.\\nStart tmux first with: tmux\\n\"\n },\n [ErrorCodes.TMUX_NOT_INSTALLED]: () => {\n return (\n \"\\ntmux is required but not installed.\\n\" +\n \"Install tmux using your package manager:\\n\" +\n \" - macOS: brew install tmux\\n\" +\n \" - Ubuntu/Debian: sudo apt-get install tmux\\n\" +\n \" - Fedora: sudo dnf install tmux\\n\"\n )\n },\n [ErrorCodes.UNSUPPORTED_TMUX_VERSION]: (error) => {\n const requiredVersion = error.details.requiredVersion\n if (typeof requiredVersion !== \"string\") {\n return \"\"\n }\n return `\\nRequired tmux version: ${requiredVersion} or higher\\n`\n },\n}\n\nexport const formatError = (error: Error): string => {\n if (!isVDELayoutError(error)) {\n return `${error.name}: ${error.message}`\n }\n\n let message = `Error: ${error.message}`\n\n const formatter = formatters[error.code]\n if (formatter) {\n message += `\\n${formatter(error)}`\n }\n\n const commandDetail = error.details.command\n if (commandDetail !== undefined) {\n message += `\\nCommand: ${JSON.stringify(commandDetail)}`\n }\n\n const stderrDetail = error.details.stderr\n if (stderrDetail !== undefined) {\n message += `\\nstderr: ${String(stderrDetail)}`\n }\n\n const presetDetail = error.details.preset\n if (presetDetail !== undefined) {\n message += `\\npreset: ${String(presetDetail)}`\n }\n\n const nestedErrors = error.details.errors\n if (Array.isArray(nestedErrors) && nestedErrors.length > 0) {\n message += \"\\nValidation errors:\\n\"\n nestedErrors.forEach((item) => {\n message += ` - ${String(item)}\\n`\n })\n }\n\n return message\n}\n","import { z } from \"zod\"\n\n// Terminal pane schema\nconst TerminalPaneSchema = z\n .object({\n name: z.string().min(1),\n command: z.string().optional(),\n cwd: z.string().optional(),\n env: z.record(z.string()).optional(),\n delay: z.number().int().positive().optional(),\n title: z.string().optional(),\n focus: z.boolean().optional(),\n })\n .strict()\n\n// Split container schema (recursive)\nconst SplitPaneSchema: z.ZodType<unknown> = z.lazy(() =>\n z\n .object({\n type: z.enum([\"horizontal\", \"vertical\"]),\n ratio: z.array(z.number().positive()).min(1),\n panes: z.array(PaneSchema).min(1),\n })\n .strict()\n .refine((data) => data.ratio.length === data.panes.length, {\n message: \"Number of elements in ratio array does not match number of elements in panes array\",\n }),\n)\n\n// Recursive Pane schema definition\nexport const PaneSchema: z.ZodType<unknown> = z.lazy(() => z.union([SplitPaneSchema, TerminalPaneSchema]))\n\n// Layout schema definition\nexport const LayoutSchema = z\n .object({\n type: z.enum([\"horizontal\", \"vertical\"]),\n ratio: z.array(z.number().positive()).min(1),\n panes: z.array(PaneSchema).min(1),\n })\n .refine((data) => data.ratio.length === data.panes.length, {\n message: \"Number of elements in ratio array does not match number of elements in panes array\",\n })\n\n// Preset schema definition\nexport const PresetSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n layout: LayoutSchema.optional(),\n command: z.string().optional(),\n})\n\n// Config schema definition\nexport const ConfigSchema = z.object({\n presets: z.record(PresetSchema),\n})\n\n// Validation result type\ntype ValidationResult<T> = {\n success: boolean\n data?: T\n error?: string\n}\n\n// Helper function to format Zod errors consistently\nfunction formatValidationError(error: z.ZodError): string {\n const messages = error.errors.map((e) => {\n const path = e.path.join(\".\")\n const message = e.message\n\n // Customize error message for panes array element count check\n if (path === \"layout.panes\" && message.includes(\"at least 2 element\")) {\n return `${path}: panes array must have at least 2 elements`\n }\n\n return `${path}: ${message}`\n })\n\n return messages.join(\"\\n\")\n}\n\n// Config validation\nexport function validateConfig(data: unknown): ValidationResult<z.infer<typeof ConfigSchema>> {\n try {\n const parsed = ConfigSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n\n// Preset validation\nexport function validatePreset(data: unknown): ValidationResult<z.infer<typeof PresetSchema>> {\n try {\n const parsed = PresetSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n\n// Pane validation\nexport function validatePane(data: unknown): ValidationResult<z.infer<typeof PaneSchema>> {\n try {\n const parsed = PaneSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n","import * as YAML from \"yaml\"\nimport { z } from \"zod\"\nimport { ConfigSchema } from \"../models/schema.ts\"\nimport type { Config } from \"../models/types.ts\"\nimport { createValidationError, ErrorCodes, isVDELayoutError } from \"../utils/errors.ts\"\n\n/**\n * Parse YAML text into an object\n * @param yamlText - YAML text to parse\n * @returns Parsed object\n * @throws {ValidationError} When YAML parsing fails\n */\nfunction parseYAML(yamlText: string): unknown {\n // Input validation\n if (!yamlText || typeof yamlText !== \"string\") {\n throw createValidationError(\"YAML text not provided\", ErrorCodes.CONFIG_PARSE_ERROR, {\n received: typeof yamlText,\n })\n }\n\n try {\n return YAML.parse(yamlText)\n } catch (error) {\n throw createValidationError(\"Failed to parse YAML\", ErrorCodes.CONFIG_PARSE_ERROR, {\n parseError: error instanceof Error ? error.message : String(error),\n yamlSnippet: yamlText.substring(0, 200),\n })\n }\n}\n\n/**\n * Validate basic configuration structure\n * @param parsed - Parsed YAML object\n * @throws {ValidationError} When structure is invalid\n */\nfunction validateConfigStructure(parsed: unknown): void {\n // Check for empty YAML\n if (parsed === null || parsed === undefined || typeof parsed !== \"object\") {\n throw createValidationError(\"YAML is empty or invalid format\", ErrorCodes.CONFIG_PARSE_ERROR, {\n parsed: parsed,\n })\n }\n\n // Check for presets field existence\n const parsedObj = parsed as Record<string, unknown>\n if (!(\"presets\" in parsedObj) || parsedObj.presets === undefined || parsedObj.presets === null) {\n throw createValidationError(\"presets field is required\", ErrorCodes.INVALID_PRESET, {\n availableFields: Object.keys(parsedObj),\n })\n }\n\n // Check for empty presets\n const presetsObj = parsedObj.presets\n if (typeof presetsObj !== \"object\" || presetsObj === null || Object.keys(presetsObj).length === 0) {\n throw createValidationError(\"At least one preset is required\", ErrorCodes.INVALID_PRESET, {\n presets: presetsObj,\n })\n }\n}\n\n/**\n * Format Zod validation errors into user-friendly messages\n * @param error - Zod validation error\n * @returns Formatted error issues\n */\nfunction formatZodErrors(error: z.ZodError): Array<{ path: string; message: string; code: string }> {\n return error.issues.map((issue) => {\n const path = issue.path.join(\".\")\n let message = issue.message\n\n // Custom error messages\n if (issue.code === \"invalid_type\") {\n if (issue.path.includes(\"command\") && issue.expected === \"string\") {\n message = \"command field must be a string\"\n } else if (issue.path.includes(\"workingDirectory\") && issue.expected === \"string\") {\n message = \"workingDirectory field must be a string\"\n } else if (issue.received === \"number\" && issue.expected === \"string\") {\n message = `${path} must be a string`\n } else if (issue.received === \"array\" && issue.expected === \"string\") {\n message = `${path} must be a string`\n }\n } else if (issue.code === \"invalid_union\") {\n // Detailed error messages for union types\n const unionIssue = issue as z.ZodIssue & { unionErrors?: z.ZodError[] }\n if (unionIssue.unionErrors !== undefined) {\n // When command is missing in terminal pane\n const terminalError = unionIssue.unionErrors.find(\n (e) => e.issues?.some((i) => i.path.includes(\"command\") && i.code === \"invalid_type\") === true,\n )\n if (terminalError !== undefined) {\n message = \"command field is required\"\n } else {\n // When panes is missing in split pane\n const splitError = unionIssue.unionErrors.find(\n (e) => e.issues?.some((i) => i.path.includes(\"panes\") && i.code === \"invalid_type\") === true,\n )\n if (splitError !== undefined) {\n message = \"panes field is required\"\n } else {\n message = 'Pane type must be \"terminal\" or \"split\"'\n }\n }\n } else {\n message = 'Pane type must be \"terminal\" or \"split\"'\n }\n } else if (issue.code === \"invalid_literal\") {\n if (issue.path.includes(\"direction\")) {\n message = 'direction must be \"horizontal\" or \"vertical\"'\n }\n } else if (issue.message.includes(\"required\")) {\n // Use the message as is\n message = issue.message\n } else if (issue.code === \"custom\" && issue.message.includes(\"ratio array\")) {\n message = issue.message\n } else if (issue.code === \"too_small\" && issue.message.includes(\"Array must contain at least\")) {\n // Minimum array elements error\n if (path.includes(\"panes\")) {\n message = \"panes array must contain at least 2 elements\"\n } else if (path.includes(\"ratio\")) {\n message = \"ratio array must contain at least 2 elements\"\n } else {\n message = issue.message\n }\n }\n\n return {\n path,\n message,\n code: issue.code,\n }\n })\n}\n\n/**\n * Validates YAML text and converts it to a type-safe Config object\n * @param yamlText - YAML text to validate\n * @returns Validated Config object\n * @throws {ValidationError} When YAML is invalid\n */\nexport function validateYAML(yamlText: string): Config {\n // Parse YAML\n const parsed = parseYAML(yamlText)\n\n // Validate basic structure\n validateConfigStructure(parsed)\n\n // Ratio sum validation removed - unnecessary due to automatic normalization\n\n // Validation with Zod schema\n try {\n const validated = ConfigSchema.parse(parsed)\n return validated\n } catch (error) {\n if (error instanceof z.ZodError) {\n const issues = formatZodErrors(error)\n\n // Use the first error message as the primary message\n const primaryMessage = issues.length > 0 && issues[0] ? issues[0].message : \"Configuration validation failed\"\n\n throw createValidationError(primaryMessage, ErrorCodes.CONFIG_PARSE_ERROR, {\n issues,\n rawErrors: error.issues,\n })\n }\n\n if (isVDELayoutError(error) && error.name === \"ValidationError\") {\n throw error\n }\n\n // Other errors\n throw createValidationError(\"Unexpected validation error occurred\", ErrorCodes.CONFIG_PARSE_ERROR, {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n}\n","import fs from \"fs-extra\"\nimport path from \"path\"\nimport os from \"os\"\nimport * as yaml from \"yaml\"\nimport type { Config } from \"../models/types.ts\"\nimport { createConfigError, ErrorCodes } from \"../utils/errors.ts\"\nimport { validateYAML } from \"./validator.ts\"\n\nexport type ConfigLoaderOptions = {\n readonly configPaths?: string[]\n}\n\nexport type ConfigLoader = {\n readonly loadYAML: () => Promise<string>\n readonly loadConfig: () => Promise<Config>\n readonly findConfigFile: () => Promise<string | null>\n readonly getSearchPaths: () => string[]\n}\n\nexport const createConfigLoader = (options: ConfigLoaderOptions = {}): ConfigLoader => {\n const explicitConfigPaths = options.configPaths\n\n const computeCachedSearchPaths = (): string[] => {\n if (explicitConfigPaths && explicitConfigPaths.length > 0) {\n return [...explicitConfigPaths]\n }\n\n const candidates: string[] = []\n const projectCandidate = findProjectConfigCandidate()\n if (projectCandidate !== null) {\n candidates.push(projectCandidate)\n }\n\n candidates.push(...buildDefaultSearchPaths())\n\n return [...new Set(candidates)]\n }\n\n const loadConfig = async (): Promise<Config> => {\n if (explicitConfigPaths && explicitConfigPaths.length > 0) {\n const filePath = await findFirstExisting(explicitConfigPaths)\n if (filePath === null) {\n throw createConfigError(\"Configuration file not found\", ErrorCodes.CONFIG_NOT_FOUND, {\n searchPaths: explicitConfigPaths,\n })\n }\n\n const content = await safeReadFile(filePath)\n return validateYAML(content)\n }\n\n const searchPaths = computeCachedSearchPaths()\n const existingPaths = await filterExistingPaths(searchPaths)\n\n if (existingPaths.length === 0) {\n throw createConfigError(\"Configuration file not found\", ErrorCodes.CONFIG_NOT_FOUND, {\n searchPaths,\n })\n }\n\n const projectPath = findProjectConfigCandidate()\n const globalPaths = existingPaths.filter((filePath) => filePath !== projectPath)\n\n let mergedConfig: Config = { presets: {} }\n\n for (const globalPath of globalPaths) {\n const content = await safeReadFile(globalPath)\n const config = validateYAML(content)\n mergedConfig = mergeConfigs(mergedConfig, config)\n }\n\n if (projectPath !== null && (await fs.pathExists(projectPath))) {\n const content = await safeReadFile(projectPath)\n const config = validateYAML(content)\n mergedConfig = mergeConfigs(mergedConfig, config)\n }\n\n return mergedConfig\n }\n\n return {\n loadYAML: async (): Promise<string> => {\n const config = await loadConfig()\n return yaml.stringify(config)\n },\n loadConfig,\n findConfigFile: async (): Promise<string | null> => {\n const searchPaths =\n explicitConfigPaths && explicitConfigPaths.length > 0 ? [...explicitConfigPaths] : computeCachedSearchPaths()\n\n for (const searchPath of searchPaths) {\n if (await fs.pathExists(searchPath)) {\n return searchPath\n }\n }\n return null\n },\n getSearchPaths: (): string[] => computeCachedSearchPaths(),\n }\n}\n\nconst buildDefaultSearchPaths = (): string[] => {\n const paths: string[] = []\n\n const vdeConfigPath = process.env.VDE_CONFIG_PATH\n if (vdeConfigPath !== undefined) {\n paths.push(path.join(vdeConfigPath, \"layout.yml\"))\n }\n\n const homeDir = process.env.HOME ?? os.homedir()\n const xdgConfigHome = process.env.XDG_CONFIG_HOME ?? path.join(homeDir, \".config\")\n paths.push(path.join(xdgConfigHome, \"vde\", \"layout.yml\"))\n\n return [...new Set(paths)]\n}\n\nconst findProjectConfigCandidate = (): string | null => {\n let currentDir = process.cwd()\n const { root } = path.parse(currentDir)\n\n while (true) {\n const candidate = path.join(currentDir, \".vde\", \"layout.yml\")\n if (fs.existsSync(candidate)) {\n return candidate\n }\n\n if (currentDir === root) {\n break\n }\n\n const parent = path.dirname(currentDir)\n if (parent === currentDir) {\n break\n }\n\n currentDir = parent\n }\n\n return null\n}\n\nconst findFirstExisting = async (paths: ReadonlyArray<string>): Promise<string | null> => {\n for (const candidate of paths) {\n if (await fs.pathExists(candidate)) {\n return candidate\n }\n }\n return null\n}\n\nconst filterExistingPaths = async (paths: ReadonlyArray<string>): Promise<string[]> => {\n const existing: string[] = []\n for (const candidate of paths) {\n if (await fs.pathExists(candidate)) {\n existing.push(candidate)\n }\n }\n return existing\n}\n\nconst safeReadFile = async (filePath: string): Promise<string> => {\n try {\n return await fs.readFile(filePath, \"utf8\")\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw createConfigError(`Failed to read configuration file`, ErrorCodes.CONFIG_PERMISSION_ERROR, {\n filePath,\n error: errorMessage,\n })\n }\n}\n\nconst mergeConfigs = (base: Config, override: Config): Config => {\n return {\n presets: {\n ...base.presets,\n ...override.presets,\n },\n }\n}\n","import { createConfigLoader, type ConfigLoaderOptions } from \"../config/loader.ts\"\nimport { createConfigError, ErrorCodes } from \"../utils/errors.ts\"\nimport type { Config, Preset, PresetInfo } from \"../models/types.ts\"\nimport type { PresetManager } from \"../types/preset-manager.ts\"\n\ntype PresetState = {\n setConfigPath: (filePath: string) => void\n loadConfig: () => Promise<void>\n getPreset: (name: string) => Preset\n listPresets: () => PresetInfo[]\n getDefaultPreset: () => Preset\n}\n\nconst createState = (options: ConfigLoaderOptions = {}): PresetState => {\n let loaderOptions: ConfigLoaderOptions = options\n let cachedConfig: Config | null = null\n\n const setConfigPath = (filePath: string): void => {\n loaderOptions = { configPaths: [filePath] }\n cachedConfig = null\n }\n\n const loadConfig = async (): Promise<void> => {\n const loader = createConfigLoader(loaderOptions)\n cachedConfig = await loader.loadConfig()\n }\n\n const ensureConfig = (): Config => {\n if (cachedConfig === null) {\n throw createConfigError(\"Configuration not loaded\", ErrorCodes.CONFIG_NOT_FOUND)\n }\n return cachedConfig\n }\n\n const getPreset = (name: string): Preset => {\n const config = ensureConfig()\n const preset = config.presets[name]\n if (preset === undefined) {\n throw createConfigError(`Preset \"${name}\" not found`, ErrorCodes.PRESET_NOT_FOUND, {\n availablePresets: Object.keys(config.presets),\n })\n }\n return preset\n }\n\n const listPresets = (): PresetInfo[] => {\n if (cachedConfig === null) {\n return []\n }\n\n return Object.entries(cachedConfig.presets).map(([key, preset]) => ({\n key,\n name: preset.name,\n description: preset.description,\n }))\n }\n\n const getDefaultPreset = (): Preset => {\n const config = ensureConfig()\n\n if (config.presets.default !== undefined) {\n return config.presets.default\n }\n\n const firstKey = Object.keys(config.presets)[0]\n if (typeof firstKey !== \"string\" || firstKey.length === 0) {\n throw createConfigError(\"No presets defined\", ErrorCodes.PRESET_NOT_FOUND)\n }\n\n return config.presets[firstKey]!\n }\n\n return {\n setConfigPath,\n loadConfig,\n getPreset,\n listPresets,\n getDefaultPreset,\n }\n}\n\nexport const createPresetManager = (options: ConfigLoaderOptions = {}): PresetManager => {\n const state = createState(options)\n return {\n setConfigPath: state.setConfigPath,\n loadConfig: state.loadConfig,\n getPreset: state.getPreset,\n listPresets: state.listPresets,\n getDefaultPreset: state.getDefaultPreset,\n }\n}\n","import chalk from \"chalk\"\n\nexport enum LogLevel {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n}\n\ntype LoggerOptions = {\n readonly level?: LogLevel\n readonly prefix?: string\n}\n\nexport type Logger = {\n readonly level: LogLevel\n readonly prefix: string\n error: (message: string, error?: Error) => void\n warn: (message: string) => void\n info: (message: string) => void\n debug: (message: string) => void\n success: (message: string) => void\n createChild: (suffix: string) => Logger\n}\n\nconst resolveDefaultLogLevel = (): LogLevel => {\n if (process.env.VDE_DEBUG === \"true\") {\n return LogLevel.DEBUG\n }\n if (process.env.VDE_VERBOSE === \"true\") {\n return LogLevel.INFO\n }\n return LogLevel.WARN\n}\n\nconst formatMessage = (prefix: string, message: string): string => {\n return prefix ? `${prefix} ${message}` : message\n}\n\nexport const createLogger = (options: LoggerOptions = {}): Logger => {\n const level = options.level ?? resolveDefaultLogLevel()\n const prefix = options.prefix ?? \"\"\n\n const build = (nextPrefix: string, nextLevel: LogLevel): Logger => {\n const resolvedPrefix = nextPrefix\n\n return {\n level: nextLevel,\n prefix: resolvedPrefix,\n error(message: string, error?: Error): void {\n if (nextLevel >= LogLevel.ERROR) {\n console.error(chalk.red(formatMessage(resolvedPrefix, `Error: ${message}`)))\n if (error && process.env.VDE_DEBUG === \"true\") {\n console.error(chalk.gray(error.stack))\n }\n }\n },\n warn(message: string): void {\n if (nextLevel >= LogLevel.WARN) {\n console.warn(chalk.yellow(formatMessage(resolvedPrefix, message)))\n }\n },\n info(message: string): void {\n if (nextLevel >= LogLevel.INFO) {\n console.log(formatMessage(resolvedPrefix, message))\n }\n },\n debug(message: string): void {\n if (nextLevel >= LogLevel.DEBUG) {\n console.log(chalk.gray(formatMessage(resolvedPrefix, `[DEBUG] ${message}`)))\n }\n },\n success(message: string): void {\n console.log(chalk.green(formatMessage(resolvedPrefix, message)))\n },\n createChild(suffix: string): Logger {\n const childPrefix = resolvedPrefix ? `${resolvedPrefix} ${suffix}` : suffix\n return build(childPrefix, nextLevel)\n },\n }\n }\n\n return build(prefix, level)\n}\n","import { execa } from \"execa\"\nimport { createTmuxError, ErrorCodes } from \"../utils/errors.ts\"\nimport type { CommandExecutor } from \"../types/command-executor.ts\"\nimport { createLogger, LogLevel } from \"../utils/logger.ts\"\n\ntype RealExecutorOptions = {\n readonly verbose?: boolean\n}\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createRealExecutor = (options: RealExecutorOptions = {}): CommandExecutor => {\n const verbose = options.verbose ?? false\n const logger = createLogger({\n level: verbose ? LogLevel.INFO : LogLevel.WARN,\n prefix: \"[tmux]\",\n })\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n const commandString = toCommandString(args)\n\n logger.info(`Executing: ${commandString}`)\n\n try {\n const result = await execa(\"tmux\", args)\n return result.stdout\n } catch (error) {\n const execaError = error as { exitCode?: number; stderr?: string; message: string }\n\n throw createTmuxError(\"Failed to execute tmux command\", ErrorCodes.TMUX_COMMAND_FAILED, {\n command: commandString,\n exitCode: execaError.exitCode,\n stderr: execaError.stderr,\n })\n }\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return false\n },\n logCommand(command: string): void {\n logger.info(`Executing: ${command}`)\n },\n }\n}\n","import type { CommandExecutor } from \"../types/command-executor.ts\"\nimport { createLogger, LogLevel } from \"../utils/logger.ts\"\n\ntype DryRunExecutorOptions = {\n readonly verbose?: boolean\n}\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createDryRunExecutor = (options: DryRunExecutorOptions = {}): CommandExecutor => {\n const verbose = options.verbose ?? false\n const logger = createLogger({\n level: verbose ? LogLevel.INFO : LogLevel.WARN,\n prefix: \"[tmux] [DRY RUN]\",\n })\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n const commandString = toCommandString(args)\n logger.info(`Would execute: ${commandString}`)\n return \"\"\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return true\n },\n logCommand(command: string): void {\n logger.info(`Would execute: ${command}`)\n },\n }\n}\n","type FunctionalCoreErrorKind = \"compile\" | \"plan\" | \"emit\" | \"execution\"\n\nexport type FunctionalCoreError = {\n readonly kind: FunctionalCoreErrorKind\n readonly code: string\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n}\n\nexport const createFunctionalError = (\n kind: FunctionalCoreErrorKind,\n error: {\n readonly code: string\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): FunctionalCoreError => ({\n kind,\n code: error.code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n})\n\nexport const isFunctionalCoreError = (value: unknown): value is FunctionalCoreError => {\n if (typeof value !== \"object\" || value === null) {\n return false\n }\n const candidate = value as Partial<FunctionalCoreError>\n return (\n (candidate.kind === \"compile\" ||\n candidate.kind === \"plan\" ||\n candidate.kind === \"emit\" ||\n candidate.kind === \"execution\") &&\n typeof candidate.code === \"string\" &&\n typeof candidate.message === \"string\"\n )\n}\n","import type { CommandExecutor } from \"../types/command-executor.ts\"\nimport type { PlanEmission, CommandStep, EmittedTerminal } from \"../core/emitter.ts\"\nimport { ErrorCodes } from \"../utils/errors.ts\"\nimport { createFunctionalError } from \"../core/errors.ts\"\n\nconst DOUBLE_QUOTE = '\"'\nconst ESCAPED_DOUBLE_QUOTE = '\\\\\"'\n\ntype ExecutePlanInput = {\n readonly emission: PlanEmission\n readonly executor: CommandExecutor\n readonly windowName?: string\n}\n\ntype ExecutePlanSuccess = {\n readonly executedSteps: number\n}\n\nexport const executePlan = async ({\n emission,\n executor,\n windowName,\n}: ExecutePlanInput): Promise<ExecutePlanSuccess> => {\n const initialVirtualPaneId = emission.summary.initialPaneId\n if (typeof initialVirtualPaneId !== \"string\" || initialVirtualPaneId.length === 0) {\n raiseExecutionError(\"INVALID_PLAN\", {\n message: \"Plan emission is missing initial pane metadata\",\n path: \"plan.initialPaneId\",\n })\n }\n\n const paneMap = new Map<string, string>()\n\n const newWindowCommand: string[] = [\"new-window\", \"-P\", \"-F\", \"#{pane_id}\"]\n if (typeof windowName === \"string\" && windowName.trim().length > 0) {\n newWindowCommand.push(\"-n\", windowName.trim())\n }\n\n const initialPaneId = normalizePaneId(\n await executeCommand(executor, newWindowCommand, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to create tmux window\",\n path: initialVirtualPaneId,\n }),\n )\n\n registerPane(paneMap, initialVirtualPaneId, initialPaneId)\n\n let executedSteps = 0\n\n for (const step of emission.steps) {\n if (step.kind === \"split\") {\n await executeSplitStep({ step, executor, paneMap })\n } else if (step.kind === \"focus\") {\n await executeFocusStep({ step, executor, paneMap })\n }\n executedSteps += 1\n }\n\n await executeTerminalCommands({ terminals: emission.terminals, executor, paneMap })\n\n const finalRealFocus = resolvePaneId(paneMap, emission.summary.focusPaneId)\n if (typeof finalRealFocus === \"string\" && finalRealFocus.length > 0) {\n await executeCommand(executor, [\"select-pane\", \"-t\", finalRealFocus], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to restore focus\",\n path: emission.summary.focusPaneId,\n })\n }\n\n return { executedSteps }\n}\n\nconst executeSplitStep = async ({\n step,\n executor,\n paneMap,\n}: {\n readonly step: CommandStep\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n const targetVirtualId = ensureNonEmpty(step.targetPaneId, () =>\n raiseExecutionError(\"MISSING_TARGET\", {\n message: \"Split step missing target pane metadata\",\n path: step.id,\n }),\n )\n\n const targetRealId = ensureNonEmpty(resolvePaneId(paneMap, targetVirtualId), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: `Unknown target pane: ${targetVirtualId}`,\n path: step.id,\n }),\n )\n\n const panesBefore = await listPaneIds(executor, step)\n const splitCommand = replaceTarget(step.command, targetRealId)\n await executeCommand(executor, splitCommand, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute split step ${step.id}`,\n path: step.id,\n details: { command: splitCommand },\n })\n\n const panesAfter = await listPaneIds(executor, step)\n const newPaneId = ensureNonEmpty(findNewPaneId(panesBefore, panesAfter), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: \"Unable to determine newly created pane\",\n path: step.id,\n }),\n )\n\n const createdVirtualId = step.createdPaneId\n if (typeof createdVirtualId === \"string\" && createdVirtualId.length > 0) {\n registerPane(paneMap, createdVirtualId, newPaneId)\n }\n}\n\nconst executeFocusStep = async ({\n step,\n executor,\n paneMap,\n}: {\n readonly step: CommandStep\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n const targetVirtualId = ensureNonEmpty(step.targetPaneId, () =>\n raiseExecutionError(\"MISSING_TARGET\", {\n message: \"Focus step missing target pane metadata\",\n path: step.id,\n }),\n )\n\n const targetRealId = ensureNonEmpty(resolvePaneId(paneMap, targetVirtualId), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: `Unknown focus pane: ${targetVirtualId}`,\n path: step.id,\n }),\n )\n\n const command = replaceTarget(step.command, targetRealId)\n await executeCommand(executor, command, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute focus step ${step.id}`,\n path: step.id,\n details: { command },\n })\n}\n\nconst executeTerminalCommands = async ({\n terminals,\n executor,\n paneMap,\n}: {\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n for (const terminal of terminals) {\n const realPaneId = ensureNonEmpty(resolvePaneId(paneMap, terminal.virtualPaneId), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: `Unknown terminal pane: ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n }),\n )\n\n if (typeof terminal.cwd === \"string\" && terminal.cwd.length > 0) {\n const escapedCwd = terminal.cwd.split(DOUBLE_QUOTE).join(ESCAPED_DOUBLE_QUOTE)\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, `cd \"${escapedCwd}\"`, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to change directory for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { cwd: terminal.cwd },\n })\n }\n\n if (terminal.env !== undefined) {\n for (const [key, value] of Object.entries(terminal.env)) {\n const escaped = String(value).split(DOUBLE_QUOTE).join(ESCAPED_DOUBLE_QUOTE)\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, `export ${key}=\"${escaped}\"`, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to set environment variable ${key}`,\n path: terminal.virtualPaneId,\n })\n }\n }\n\n if (typeof terminal.command === \"string\" && terminal.command.length > 0) {\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, terminal.command, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute command for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { command: terminal.command },\n })\n }\n }\n}\n\nconst executeCommand = async (\n executor: CommandExecutor,\n command: string[],\n context: {\n readonly code: string\n readonly message: string\n readonly path: string\n readonly details?: Record<string, unknown>\n },\n): Promise<string> => {\n try {\n return await executor.execute([...command])\n } catch (error) {\n if (error instanceof Error && \"code\" in error && \"message\" in error) {\n const candidate = error as { code?: string; message?: string; details?: Record<string, unknown> }\n throw createFunctionalError(\"execution\", {\n code: typeof candidate.code === \"string\" ? candidate.code : context.code,\n message: candidate.message ?? context.message,\n path: context.path,\n details: candidate.details ?? context.details,\n })\n }\n\n throw createFunctionalError(\"execution\", {\n code: context.code,\n message: context.message,\n path: context.path,\n details: context.details,\n })\n }\n}\n\nconst listPaneIds = async (executor: CommandExecutor, step: CommandStep): Promise<string[]> => {\n const output = await executeCommand(executor, [\"list-panes\", \"-F\", \"#{pane_id}\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to list tmux panes\",\n path: step.id,\n })\n\n return output\n .split(\"\\n\")\n .map((pane) => pane.trim())\n .filter((pane) => pane.length > 0)\n}\n\nconst findNewPaneId = (before: string[], after: string[]): string | undefined => {\n const beforeSet = new Set(before)\n return after.find((id) => !beforeSet.has(id))\n}\n\nconst replaceTarget = (command: ReadonlyArray<string>, realTarget: string): string[] => {\n const next = [...command]\n const targetIndex = next.findIndex((value, index) => value === \"-t\" && index + 1 < next.length)\n if (targetIndex >= 0) {\n next[targetIndex + 1] = realTarget\n return next\n }\n\n if (next.length > 0) {\n next[next.length - 1] = realTarget\n }\n return next\n}\n\nconst normalizePaneId = (raw: string): string => {\n const trimmed = raw.trim()\n return trimmed.length === 0 ? \"%0\" : trimmed\n}\n\nconst registerPane = (paneMap: Map<string, string>, virtualId: string, realId: string): void => {\n paneMap.set(virtualId, realId)\n}\n\nconst resolvePaneId = (paneMap: Map<string, string>, virtualId: string): string | undefined => {\n const direct = paneMap.get(virtualId)\n if (typeof direct === \"string\" && direct.length > 0) {\n return direct\n }\n\n let ancestor = virtualId\n while (ancestor.includes(\".\")) {\n ancestor = ancestor.slice(0, ancestor.lastIndexOf(\".\"))\n const candidate = paneMap.get(ancestor)\n if (typeof candidate === \"string\" && candidate.length > 0) {\n paneMap.set(virtualId, candidate)\n return candidate\n }\n }\n\n for (const [key, value] of paneMap.entries()) {\n if (key.startsWith(`${virtualId}.`)) {\n if (typeof value === \"string\" && value.length > 0) {\n paneMap.set(virtualId, value)\n return value\n }\n }\n }\n\n return undefined\n}\n\nconst ensureNonEmpty = <T extends string>(value: T | undefined, buildError: () => never): T => {\n if (value === undefined || value.length === 0) {\n return buildError()\n }\n return value\n}\n\nconst raiseExecutionError = (\n code: string,\n error: {\n readonly message: string\n readonly path: string\n readonly details?: Record<string, unknown>\n },\n): never => {\n throw createFunctionalError(\"execution\", {\n code,\n message: error.message,\n path: error.path,\n details: error.details,\n })\n}\n","import { parse } from \"yaml\"\n\nexport type DiagnosticsSeverity = \"high\" | \"medium\" | \"low\"\n\ntype DiagnosticsFinding = {\n readonly path: string\n readonly severity: DiagnosticsSeverity\n readonly description: string\n}\n\ntype DiagnosticsBacklogItem = {\n readonly id: string\n readonly severity: DiagnosticsSeverity\n readonly summary: string\n readonly actions: ReadonlyArray<string>\n}\n\nexport type DiagnosticsReport = {\n readonly findings: ReadonlyArray<DiagnosticsFinding>\n readonly nextSteps: ReadonlyArray<string>\n readonly backlog: ReadonlyArray<DiagnosticsBacklogItem>\n}\n\ntype DiagnosticsInput = {\n readonly presetDocument: string\n readonly knownIssues?: ReadonlyArray<string>\n}\n\nconst severityRank: Record<DiagnosticsSeverity, number> = {\n high: 3,\n medium: 2,\n low: 1,\n}\n\ntype FindingAccumulator = {\n add: (args: { path: string; severity: DiagnosticsSeverity; description: string; nextStep?: string }) => void\n readonly findings: DiagnosticsFinding[]\n readonly nextSteps: Set<string>\n readonly backlog: Map<string, DiagnosticsBacklogItem>\n}\n\nconst createAccumulator = (): FindingAccumulator => {\n const findings: DiagnosticsFinding[] = []\n const nextSteps = new Set<string>()\n const backlog = new Map<string, DiagnosticsBacklogItem>()\n\n return {\n findings,\n nextSteps,\n backlog,\n add: ({ path, severity, description, nextStep }): void => {\n findings.push({ path, severity, description })\n if (typeof nextStep === \"string\" && nextStep.length > 0) {\n nextSteps.add(nextStep)\n }\n\n const existing = backlog.get(path)\n const existingActions = new Set(existing?.actions ?? [])\n existingActions.add(description)\n if (typeof nextStep === \"string\" && nextStep.length > 0) {\n existingActions.add(nextStep)\n }\n\n const mergedSeverity = existing !== undefined ? maxSeverity(existing.severity, severity) : severity\n\n const summary =\n existing !== undefined && severityRank[existing.severity] >= severityRank[severity]\n ? existing.summary\n : description\n\n backlog.set(path, {\n id: path,\n severity: mergedSeverity,\n summary,\n actions: Array.from(existingActions),\n })\n },\n }\n}\n\nexport function runDiagnostics(input: DiagnosticsInput): DiagnosticsReport {\n const accumulator = createAccumulator()\n const knownIssues = input.knownIssues ?? []\n let parsedPreset: unknown\n\n try {\n parsedPreset = parse(input.presetDocument)\n } catch (error) {\n accumulator.add({\n path: \"presetDocument\",\n severity: \"high\",\n description: `プリセットYAMLの解析に失敗しました: ${(error as Error).message}`,\n nextStep: \"プリセットYAMLを構文チェックし、Functional Coreリライト前に整合性を確保する\",\n })\n return {\n findings: sortBySeverity(accumulator.findings),\n nextSteps: Array.from(accumulator.nextSteps),\n backlog: sortBacklog(accumulator.backlog),\n }\n }\n\n if (parsedPreset === null || typeof parsedPreset !== \"object\") {\n accumulator.add({\n path: \"preset\",\n severity: \"high\",\n description: \"プリセット定義がオブジェクト形式ではありません\",\n nextStep: \"プリセットYAMLをオブジェクト構造に整形し整合性を確保する\",\n })\n } else {\n const presetObject = parsedPreset as Record<string, unknown>\n checkFocusDuplications(presetObject, accumulator)\n collectLowPrioritySignals(presetObject, accumulator)\n }\n\n knownIssues.forEach((issue, index) => {\n const trimmed = issue.trim()\n if (trimmed.length === 0) {\n return\n }\n\n accumulator.add({\n path: `codebase.knownIssues[${index}]`,\n severity: \"medium\",\n description: trimmed,\n nextStep: `tmux依存や副作用をFunctional Core境界で切り離す: ${trimmed}`,\n })\n })\n\n return {\n findings: sortBySeverity(accumulator.findings),\n nextSteps: Array.from(accumulator.nextSteps),\n backlog: sortBacklog(accumulator.backlog),\n }\n}\n\nconst checkFocusDuplications = (preset: Record<string, unknown>, accumulator: FindingAccumulator): void => {\n const layout = preset.layout as unknown\n if (layout === undefined || layout === null) {\n return\n }\n\n const focusCount = countFocusFlags(layout)\n if (focusCount > 1) {\n accumulator.add({\n path: \"preset.layout\",\n severity: \"high\",\n description: \"複数のペインでfocus: trueが指定されています\",\n nextStep: \"focusは単一ペインに限定しPlan生成時に一貫するようFunctional Coreで制御する\",\n })\n }\n}\n\nconst collectLowPrioritySignals = (preset: Record<string, unknown>, accumulator: FindingAccumulator): void => {\n const layout = preset.layout as Record<string, unknown> | undefined | null\n if (layout === undefined || layout === null) {\n accumulator.add({\n path: \"preset.layout\",\n severity: \"low\",\n description: \"layout定義が存在しません(単一ペイン運用が前提)\",\n nextStep: \"単一ペイン前提でもPlan出力に影響しないことをFunctional Coreで確認する\",\n })\n return\n }\n\n if (!Array.isArray(layout.panes)) {\n accumulator.add({\n path: \"preset.layout.panes\",\n severity: \"low\",\n description: \"panes配列が存在しないか配列ではありません\",\n nextStep: \"レイアウト定義の構造を正規化し、Plan生成の入力契約を明示する\",\n })\n }\n}\n\nconst countFocusFlags = (node: unknown): number => {\n if (Array.isArray(node)) {\n return node.reduce((sum, child) => sum + countFocusFlags(child), 0)\n }\n\n if (node === null || typeof node !== \"object\") {\n return 0\n }\n\n const record = node as Record<string, unknown>\n const selfFocus = record.focus === true ? 1 : 0\n const childFocus = Array.isArray(record.panes)\n ? record.panes.reduce((sum, child) => sum + countFocusFlags(child), 0)\n : 0\n\n return selfFocus + childFocus\n}\n\nconst sortBySeverity = (findings: DiagnosticsFinding[]): DiagnosticsFinding[] => {\n return [...findings].sort((a, b) => severityRank[b.severity] - severityRank[a.severity])\n}\n\nconst sortBacklog = (backlog: Map<string, DiagnosticsBacklogItem>): DiagnosticsBacklogItem[] => {\n return [...backlog.values()].sort((a, b) => severityRank[b.severity] - severityRank[a.severity])\n}\n\nconst maxSeverity = (left: DiagnosticsSeverity, right: DiagnosticsSeverity): DiagnosticsSeverity => {\n return severityRank[left] >= severityRank[right] ? left : right\n}\n","import { parse } from \"yaml\"\nimport { createFunctionalError, type FunctionalCoreError } from \"./errors.ts\"\n\nexport type CompilePresetInput = {\n readonly document: string\n readonly source: string\n}\n\nexport type FunctionalTerminalPane = {\n readonly kind: \"terminal\"\n readonly name: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly focus?: boolean\n readonly options?: Readonly<Record<string, unknown>>\n}\n\nexport type FunctionalSplitPane = {\n readonly kind: \"split\"\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly ratio: ReadonlyArray<number>\n readonly panes: ReadonlyArray<FunctionalLayoutNode>\n}\n\nexport type FunctionalLayoutNode = FunctionalTerminalPane | FunctionalSplitPane\n\ntype FunctionalPresetMetadata = {\n readonly source: string\n}\n\nexport type FunctionalPreset = {\n readonly name: string\n readonly version: string\n readonly command?: string\n readonly layout?: FunctionalLayoutNode\n readonly metadata: FunctionalPresetMetadata\n}\n\nexport type CompilePresetSuccess = {\n readonly preset: FunctionalPreset\n}\n\nexport const compilePreset = ({ document, source }: CompilePresetInput): CompilePresetSuccess => {\n let parsed: unknown\n try {\n parsed = parse(document)\n } catch (error) {\n throw compileError(\"PRESET_PARSE_ERROR\", {\n source,\n message: `YAMLの解析に失敗しました: ${(error as Error).message}`,\n details: {\n reason: error instanceof Error ? error.message : String(error),\n },\n })\n }\n\n if (!isRecord(parsed)) {\n throw compileError(\"PRESET_INVALID_DOCUMENT\", {\n source,\n message: \"プリセット定義がオブジェクトではありません\",\n path: \"preset\",\n })\n }\n\n const name = typeof parsed.name === \"string\" && parsed.name.trim().length > 0 ? parsed.name : \"Unnamed preset\"\n\n const layout = parseLayoutNode(parsed.layout, {\n source,\n path: \"preset.layout\",\n })\n\n return {\n preset: {\n name,\n version: \"legacy\",\n command: typeof parsed.command === \"string\" ? parsed.command : undefined,\n layout: layout ?? undefined,\n metadata: { source },\n },\n }\n}\n\nconst parseLayoutNode = (\n node: unknown,\n context: { readonly source: string; readonly path: string },\n): FunctionalLayoutNode | null => {\n if (node === undefined || node === null) {\n return null\n }\n\n if (!isRecord(node)) {\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"レイアウトノードの形式が不正です\",\n path: context.path,\n details: { node },\n })\n }\n\n if (typeof node.type === \"string\" && Array.isArray(node.panes)) {\n return parseSplitPane(node, context)\n }\n\n if (typeof node.name === \"string\") {\n return parseTerminalPane(node)\n }\n\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"レイアウトノードの形式が不正です\",\n path: context.path,\n details: { node },\n })\n}\n\nconst parseSplitPane = (\n node: Record<string, unknown>,\n context: { readonly source: string; readonly path: string },\n): FunctionalSplitPane => {\n const orientation = node.type\n if (orientation !== \"horizontal\" && orientation !== \"vertical\") {\n throw compileError(\"LAYOUT_INVALID_ORIENTATION\", {\n source: context.source,\n message: \"layout.type は horizontal か vertical である必要があります\",\n path: `${context.path}.type`,\n details: { type: orientation },\n })\n }\n\n if (!Array.isArray(node.panes) || node.panes.length === 0) {\n throw compileError(\"LAYOUT_PANES_MISSING\", {\n source: context.source,\n message: \"panes 配列が存在しません\",\n path: `${context.path}.panes`,\n })\n }\n\n if (!Array.isArray(node.ratio) || node.ratio.length === 0) {\n throw compileError(\"LAYOUT_RATIO_MISSING\", {\n source: context.source,\n message: \"ratio 配列が存在しません\",\n path: `${context.path}.ratio`,\n })\n }\n\n if (node.ratio.length !== node.panes.length) {\n throw compileError(\"LAYOUT_RATIO_MISMATCH\", {\n source: context.source,\n message: \"ratio 配列と panes 配列の長さが一致しません\",\n path: context.path,\n details: {\n ratioLength: node.ratio.length,\n panesLength: node.panes.length,\n },\n })\n }\n\n const ratio = node.ratio.map((value, index) => {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw compileError(\"RATIO_INVALID_VALUE\", {\n source: context.source,\n message: \"ratio の値が正の数値ではありません\",\n path: `${context.path}.ratio[${index}]`,\n details: { value },\n })\n }\n return value\n })\n\n const panes = node.panes.map((child, index) =>\n parseLayoutNode(child, {\n source: context.source,\n path: `${context.path}.panes[${index}]`,\n }),\n )\n\n return {\n kind: \"split\",\n orientation,\n ratio,\n panes: panes.filter((pane): pane is FunctionalLayoutNode => pane !== null),\n }\n}\n\nconst parseTerminalPane = (node: Record<string, unknown>): FunctionalTerminalPane => {\n const name = typeof node.name === \"string\" ? node.name : \"\"\n const command = typeof node.command === \"string\" ? node.command : undefined\n const cwd = typeof node.cwd === \"string\" ? node.cwd : undefined\n const focus = node.focus === true ? true : undefined\n const env = normalizeEnv(node.env)\n\n const knownKeys = new Set([\"name\", \"command\", \"cwd\", \"env\", \"focus\", \"options\", \"title\", \"delay\"])\n const options = collectOptions(node, knownKeys)\n\n return {\n kind: \"terminal\",\n name,\n command,\n cwd,\n env,\n focus,\n options,\n }\n}\n\nconst normalizeEnv = (env: unknown): Readonly<Record<string, string>> | undefined => {\n if (!isRecord(env)) {\n return undefined\n }\n\n const entries = Object.entries(env).reduce<Record<string, string>>((accumulator, [key, value]) => {\n if (typeof value === \"string\") {\n accumulator[key] = value\n }\n return accumulator\n }, {})\n\n return Object.keys(entries).length > 0 ? entries : undefined\n}\n\nconst collectOptions = (\n node: Record<string, unknown>,\n excludedKeys: ReadonlySet<string>,\n): Readonly<Record<string, unknown>> | undefined => {\n const optionsEntries = Object.entries(node).filter(([key]) => !excludedKeys.has(key))\n if (optionsEntries.length === 0) {\n return undefined\n }\n\n return optionsEntries.reduce<Record<string, unknown>>((accumulator, [key, value]) => {\n accumulator[key] = value\n return accumulator\n }, {})\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === \"object\" && value !== null\n}\n\nconst compileError = (\n code: string,\n error: {\n readonly source?: string\n readonly message: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): FunctionalCoreError => {\n return createFunctionalError(\"compile\", {\n code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n })\n}\n","import type { FunctionalLayoutNode, FunctionalPreset, FunctionalSplitPane, FunctionalTerminalPane } from \"./compile.ts\"\nimport { createFunctionalError, type FunctionalCoreError } from \"./errors.ts\"\n\ntype CreateLayoutPlanInput = {\n readonly preset: FunctionalPreset\n}\n\ntype PlanTerminal = {\n readonly kind: \"terminal\"\n readonly id: string\n readonly name: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly focus: boolean\n readonly options?: Readonly<Record<string, unknown>>\n}\n\ntype PlanSplit = {\n readonly kind: \"split\"\n readonly id: string\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly ratio: ReadonlyArray<number>\n readonly panes: ReadonlyArray<PlanNode>\n}\n\nexport type PlanNode = PlanTerminal | PlanSplit\n\nexport type LayoutPlan = {\n readonly root: PlanNode\n readonly focusPaneId: string\n}\n\nexport type CreateLayoutPlanSuccess = {\n readonly plan: LayoutPlan\n}\n\nexport const createLayoutPlan = ({ preset }: CreateLayoutPlanInput): CreateLayoutPlanSuccess => {\n if (!preset.layout) {\n const terminal = createTerminalNode({\n id: \"root\",\n terminal: {\n kind: \"terminal\",\n name: preset.name,\n command: preset.command,\n },\n focusOverride: true,\n })\n\n return {\n plan: {\n root: terminal,\n focusPaneId: terminal.id,\n },\n }\n }\n\n const { node, focusPaneIds, terminalPaneIds } = buildLayoutNode(preset.layout, {\n parentId: \"root\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n })\n\n if (focusPaneIds.length > 1) {\n throw planError(\"FOCUS_CONFLICT\", {\n message: \"複数のペインでfocusが指定されています\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n details: { focusPaneIds },\n })\n }\n\n if (terminalPaneIds.length === 0) {\n throw planError(\"NO_TERMINAL_PANES\", {\n message: \"ターミナルペインが存在しません\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n })\n }\n\n const focusPaneId = focusPaneIds[0] ?? terminalPaneIds[0]!\n const root = ensureFocus(node, focusPaneId)\n\n return {\n plan: {\n root,\n focusPaneId,\n },\n }\n}\n\ntype BuildResult = {\n readonly node: PlanNode\n readonly focusPaneIds: ReadonlyArray<string>\n readonly terminalPaneIds: ReadonlyArray<string>\n}\n\nconst buildLayoutNode = (\n node: FunctionalLayoutNode,\n context: { readonly parentId: string; readonly path: string; readonly source: string },\n): BuildResult => {\n if (node.kind === \"split\") {\n return buildSplitNode(node, context)\n }\n\n return {\n node: createTerminalNode({ id: context.parentId, terminal: node }),\n focusPaneIds: node.focus === true ? [context.parentId] : [],\n terminalPaneIds: [context.parentId],\n }\n}\n\nconst buildSplitNode = (\n node: FunctionalSplitPane,\n context: { readonly parentId: string; readonly path: string; readonly source: string },\n): BuildResult => {\n const ratio = normalizeRatio(node.ratio, context)\n\n const panes: PlanNode[] = []\n const focusPaneIds: string[] = []\n const terminalPaneIds: string[] = []\n\n for (let index = 0; index < node.panes.length; index += 1) {\n const childId = `${context.parentId}.${index}`\n const childContext = {\n parentId: childId,\n path: `${context.path}.panes[${index}]`,\n source: context.source,\n }\n\n const childResult = buildLayoutNode(node.panes[index]!, childContext)\n panes.push(childResult.node)\n focusPaneIds.push(...childResult.focusPaneIds)\n terminalPaneIds.push(...childResult.terminalPaneIds)\n }\n\n return {\n node: {\n kind: \"split\",\n id: context.parentId,\n orientation: node.orientation,\n ratio,\n panes,\n },\n focusPaneIds,\n terminalPaneIds,\n }\n}\n\nconst createTerminalNode = ({\n id,\n terminal,\n focusOverride,\n}: {\n readonly id: string\n readonly terminal: FunctionalTerminalPane\n readonly focusOverride?: boolean\n}): PlanTerminal => {\n return {\n kind: \"terminal\",\n id,\n name: terminal.name,\n command: terminal.command,\n cwd: terminal.cwd,\n env: terminal.env,\n options: terminal.options,\n focus: focusOverride === true ? true : terminal.focus === true,\n }\n}\n\nconst ensureFocus = (node: PlanNode, focusPaneId: string): PlanNode => {\n if (node.kind === \"terminal\") {\n return {\n ...node,\n focus: node.id === focusPaneId,\n }\n }\n\n return {\n ...node,\n panes: node.panes.map((pane) => ensureFocus(pane, focusPaneId)),\n }\n}\n\nconst normalizeRatio = (\n ratio: ReadonlyArray<number>,\n context: { readonly path: string; readonly source: string },\n): number[] => {\n const total = ratio.reduce((sum, value, index) => {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n throw planError(\"RATIO_INVALID_VALUE\", {\n message: \"ratio の値が非負の数値ではありません\",\n path: `${context.path}.ratio[${index}]`,\n source: context.source,\n details: { value },\n })\n }\n return sum + value\n }, 0)\n\n if (total === 0) {\n return ratio.map(() => 1 / ratio.length)\n }\n\n return ratio.map((value) => value / total)\n}\n\nconst planError = (\n code: string,\n error: {\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): FunctionalCoreError => {\n return createFunctionalError(\"plan\", {\n code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n })\n}\n","import { createHash } from \"crypto\"\nimport type { LayoutPlan, PlanNode } from \"./planner.ts\"\n\ntype EmitPlanInput = {\n readonly plan: LayoutPlan\n}\n\ntype CommandStepKind = \"split\" | \"focus\"\n\nexport type CommandStep = {\n readonly id: string\n readonly kind: CommandStepKind\n readonly command: ReadonlyArray<string>\n readonly summary: string\n readonly targetPaneId?: string\n readonly createdPaneId?: string\n}\n\nexport type EmittedTerminal = {\n readonly virtualPaneId: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly focus: boolean\n readonly name: string\n}\n\ntype PlanEmissionSummary = {\n readonly stepsCount: number\n readonly focusPaneId: string\n readonly initialPaneId: string\n}\n\nexport type PlanEmission = {\n readonly steps: ReadonlyArray<CommandStep>\n readonly summary: PlanEmissionSummary\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly hash: string\n}\n\ntype SplitNode = Extract<PlanNode, { kind: \"split\" }>\n\nexport const emitPlan = ({ plan }: EmitPlanInput): PlanEmission => {\n const steps: CommandStep[] = []\n collectSplitSteps(plan.root, steps)\n\n steps.push({\n id: `${plan.focusPaneId}:focus`,\n kind: \"focus\",\n command: [\"select-pane\", \"-t\", plan.focusPaneId],\n summary: `select pane ${plan.focusPaneId}`,\n targetPaneId: plan.focusPaneId,\n })\n\n const hash = createPlanHash(plan, steps)\n const initialPaneId = determineInitialPaneId(plan.root)\n const terminals = collectTerminals(plan.root)\n\n return {\n steps,\n summary: {\n stepsCount: steps.length,\n focusPaneId: plan.focusPaneId,\n initialPaneId,\n },\n terminals,\n hash,\n }\n}\n\nconst collectSplitSteps = (node: PlanNode, steps: CommandStep[]): void => {\n if (node.kind === \"terminal\") {\n return\n }\n\n appendSplitSteps(node, steps)\n node.panes.forEach((pane) => collectSplitSteps(pane, steps))\n}\n\nconst appendSplitSteps = (node: SplitNode, steps: CommandStep[]): void => {\n const directionFlag = node.orientation === \"horizontal\" ? \"-h\" : \"-v\"\n\n for (let index = 1; index < node.panes.length; index += 1) {\n const previousRatioSum = node.ratio.slice(0, index).reduce((sum, value) => sum + value, 0)\n const percentage = Math.max(1, Math.round((1 - previousRatioSum) * 100))\n const targetPaneId = node.panes[index - 1]?.id ?? node.id\n const createdPaneId = node.panes[index]?.id\n\n steps.push({\n id: `${node.id}:split:${index}`,\n kind: \"split\",\n command: [\"split-window\", directionFlag, \"-t\", targetPaneId, \"-p\", String(Math.min(percentage, 99))],\n summary: `split ${targetPaneId} (${directionFlag})`,\n targetPaneId,\n createdPaneId,\n })\n }\n}\n\nconst collectTerminals = (node: PlanNode): EmittedTerminal[] => {\n if (node.kind === \"terminal\") {\n return [\n {\n virtualPaneId: node.id,\n command: node.command,\n cwd: node.cwd,\n env: node.env,\n focus: node.focus,\n name: node.name,\n },\n ]\n }\n\n return node.panes.flatMap((pane) => collectTerminals(pane))\n}\n\nconst determineInitialPaneId = (node: PlanNode): string => {\n if (node.kind === \"terminal\") {\n return node.id\n }\n\n let current: PlanNode = node\n while (current.kind === \"split\") {\n current = current.panes[0]!\n }\n return current.id\n}\n\nconst createPlanHash = (plan: LayoutPlan, steps: ReadonlyArray<CommandStep>): string => {\n const digest = createHash(\"sha256\")\n const normalized = {\n focusPaneId: plan.focusPaneId,\n root: plan.root,\n steps,\n }\n digest.update(JSON.stringify(normalized))\n return digest.digest(\"hex\")\n}\n","import { Command } from \"commander\"\nimport chalk from \"chalk\"\nimport { stringify as toYAML } from \"yaml\"\nimport { createRequire } from \"module\"\nimport { createPresetManager } from \"./layout/preset.ts\"\nimport type { Preset, PresetInfo } from \"./models/types\"\nimport type { CommandExecutor } from \"./types/command-executor.ts\"\nimport type { PresetManager } from \"./types/preset-manager.ts\"\nimport { createRealExecutor, createDryRunExecutor } from \"./executor/index.ts\"\nimport { executePlan } from \"./executor/plan-runner.ts\"\nimport { createLogger, LogLevel, type Logger } from \"./utils/logger.ts\"\nimport {\n runDiagnostics,\n compilePreset as defaultCompilePreset,\n createLayoutPlan as defaultCreateLayoutPlan,\n emitPlan as defaultEmitPlan,\n} from \"./core/index.ts\"\nimport type {\n DiagnosticsReport,\n DiagnosticsSeverity,\n CompilePresetInput,\n PlanEmission,\n FunctionalCoreError,\n CompilePresetSuccess,\n CreateLayoutPlanSuccess,\n} from \"./core/index.ts\"\nimport { isFunctionalCoreError } from \"./core/index.ts\"\n\nconst KNOWN_ISSUES: ReadonlyArray<string> = [\n \"LayoutEngineがtmux依存とI/Oを同一クラスで扱っている\",\n \"dry-run実行と本番適用でPlan構造が共有されていない\",\n \"Loggerが境界層とFunctional Coreの責務を混在させている\",\n]\n\nconst formatSeverityTag = (severity: DiagnosticsSeverity): string => {\n switch (severity) {\n case \"high\":\n return chalk.red(\"[HIGH]\")\n case \"medium\":\n return chalk.yellow(\"[MEDIUM]\")\n case \"low\":\n default:\n return chalk.blue(\"[LOW]\")\n }\n}\n\nexport type FunctionalCoreBridge = {\n readonly compilePreset: (input: CompilePresetInput) => ReturnType<typeof defaultCompilePreset>\n readonly createLayoutPlan: (\n input: Parameters<typeof defaultCreateLayoutPlan>[0],\n ) => ReturnType<typeof defaultCreateLayoutPlan>\n readonly emitPlan: (input: Parameters<typeof defaultEmitPlan>[0]) => ReturnType<typeof defaultEmitPlan>\n}\n\nexport type CLIOptions = {\n readonly presetManager?: PresetManager\n readonly createCommandExecutor?: (options: { verbose: boolean; dryRun: boolean }) => CommandExecutor\n readonly functionalCore?: FunctionalCoreBridge\n}\n\nexport type CLI = {\n run(args?: string[]): Promise<void>\n}\n\nexport const createCli = (options: CLIOptions = {}): CLI => {\n const presetManager = options.presetManager ?? createPresetManager()\n const createCommandExecutor =\n options.createCommandExecutor ??\n ((opts: { verbose: boolean; dryRun: boolean }): CommandExecutor => {\n if (opts.dryRun) {\n return createDryRunExecutor({ verbose: opts.verbose })\n }\n return createRealExecutor({ verbose: opts.verbose })\n })\n\n const functionalCore: FunctionalCoreBridge =\n options.functionalCore ??\n ({\n compilePreset: defaultCompilePreset,\n createLayoutPlan: defaultCreateLayoutPlan,\n emitPlan: defaultEmitPlan,\n } as const)\n\n const program = new Command()\n const require = createRequire(import.meta.url)\n const { version } = require(\"../package.json\") as { version: string }\n let logger: Logger = createLogger()\n\n const renderDiagnosticsReport = (report: DiagnosticsReport): void => {\n console.log(chalk.bold(\"\\nFunctional Core Diagnostics\\n\"))\n\n if (report.backlog.length > 0) {\n console.log(chalk.bold(\"改善バックログ\"))\n report.backlog.forEach((item, index) => {\n const prefix = `${index + 1}. ${formatSeverityTag(item.severity)}`\n console.log(`${prefix} ${item.summary}`)\n item.actions.forEach((action) => {\n console.log(` - ${action}`)\n })\n })\n console.log(\"\")\n }\n\n if (report.findings.length > 0) {\n console.log(chalk.bold(\"診断結果\"))\n report.findings.forEach((finding) => {\n console.log(`${formatSeverityTag(finding.severity)} ${finding.path} :: ${finding.description}`)\n })\n console.log(\"\")\n }\n\n if (report.nextSteps.length > 0) {\n console.log(chalk.bold(\"次のアクション\"))\n report.nextSteps.forEach((step) => {\n console.log(` - ${step}`)\n })\n console.log(\"\")\n }\n }\n\n const renderDryRun = (emission: PlanEmission): void => {\n console.log(chalk.bold(\"\\nPlanned tmux steps (dry-run)\"))\n emission.steps.forEach((step, index) => {\n const commandString = step.command.join(\" \")\n console.log(` ${index + 1}. ${step.summary}: tmux ${commandString}`)\n })\n }\n\n const buildPresetDocument = (preset: Preset, presetName?: string): string => {\n const document: Record<string, unknown> = {\n name: preset.name ?? presetName ?? \"vde-layout\",\n command: preset.command,\n layout: preset.layout,\n }\n\n if (typeof preset.command !== \"string\" || preset.command.length === 0) {\n delete document.command\n }\n\n if (preset.layout === undefined || preset.layout === null) {\n delete document.layout\n }\n\n return toYAML(document)\n }\n\n const buildPresetSource = (presetName?: string): string => {\n return typeof presetName === \"string\" && presetName.length > 0 ? `preset://${presetName}` : \"preset://default\"\n }\n\n const handleFunctionalError = (error: FunctionalCoreError): never => {\n const header = [`[${error.kind}]`, `[${error.code}]`]\n if (typeof error.path === \"string\" && error.path.length > 0) {\n header.push(`[${error.path}]`)\n }\n\n const lines = [`${header.join(\" \")} ${error.message}`.trim()]\n\n if (typeof error.source === \"string\" && error.source.length > 0) {\n lines.push(`source: ${error.source}`)\n }\n\n const commandDetail = error.details?.command\n if (Array.isArray(commandDetail)) {\n const tmuxCommand = commandDetail.filter((segment): segment is string => typeof segment === \"string\")\n if (tmuxCommand.length > 0) {\n lines.push(`command: tmux ${tmuxCommand.join(\" \")}`)\n }\n } else if (typeof commandDetail === \"string\" && commandDetail.length > 0) {\n lines.push(`command: ${commandDetail}`)\n }\n\n const stderrDetail = error.details?.stderr\n if (typeof stderrDetail === \"string\" && stderrDetail.length > 0) {\n lines.push(`stderr: ${stderrDetail}`)\n } else if (stderrDetail !== undefined) {\n lines.push(`stderr: ${String(stderrDetail)}`)\n }\n\n logger.error(lines.join(\"\\n\"))\n process.exit(1)\n }\n\n const handleError = (error: unknown): never => {\n if (error instanceof Error) {\n logger.error(error.message, error)\n } else {\n logger.error(\"An unexpected error occurred\")\n }\n\n process.exit(1)\n }\n\n const handlePipelineFailure = (error: unknown): never => {\n if (isFunctionalCoreError(error)) {\n return handleFunctionalError(error)\n }\n return handleError(error)\n }\n\n const listPresets = async (): Promise<never> => {\n try {\n await presetManager.loadConfig()\n const presets = presetManager.listPresets()\n\n if (presets.length === 0) {\n logger.warn(\"No presets defined\")\n process.exit(0)\n }\n\n console.log(chalk.bold(\"Available presets:\\n\"))\n\n const maxKeyLength = Math.max(...presets.map((p) => p.key.length))\n\n presets.forEach((preset: PresetInfo) => {\n const paddedKey = preset.key.padEnd(maxKeyLength + 2)\n const description = preset.description ?? \"\"\n console.log(` ${chalk.cyan(paddedKey)} ${description}`)\n })\n\n process.exit(0)\n } catch (error) {\n return handleError(error)\n }\n }\n\n const diagnosePreset = async (presetName: string | undefined): Promise<never> => {\n try {\n await presetManager.loadConfig()\n const preset =\n typeof presetName === \"string\" && presetName.length > 0\n ? presetManager.getPreset(presetName)\n : presetManager.getDefaultPreset()\n\n const presetDocument = toYAML(preset ?? {})\n const report = runDiagnostics({\n presetDocument,\n knownIssues: KNOWN_ISSUES,\n })\n\n renderDiagnosticsReport(report)\n process.exit(0)\n } catch (error) {\n return handleError(error)\n }\n }\n\n const executePreset = async (\n presetName: string | undefined,\n options: { verbose: boolean; dryRun: boolean },\n ): Promise<never> => {\n try {\n await presetManager.loadConfig()\n\n const preset =\n typeof presetName === \"string\" && presetName.length > 0\n ? presetManager.getPreset(presetName)\n : presetManager.getDefaultPreset()\n\n const tmuxEnv = process.env.TMUX\n const insideTmux = typeof tmuxEnv === \"string\" && tmuxEnv.length > 0\n if (!insideTmux && options.dryRun !== true) {\n throw new Error(\"Must be run inside a tmux session\")\n }\n\n const executor = createCommandExecutor({\n verbose: options.verbose,\n dryRun: options.dryRun,\n })\n\n if (options.dryRun === true) {\n console.log(\"[DRY RUN] No actual commands will be executed\")\n }\n\n let compileResult: CompilePresetSuccess\n let planResult: CreateLayoutPlanSuccess\n let emission: PlanEmission\n\n try {\n compileResult = functionalCore.compilePreset({\n document: buildPresetDocument(preset, presetName),\n source: buildPresetSource(presetName),\n })\n planResult = functionalCore.createLayoutPlan({ preset: compileResult.preset })\n emission = functionalCore.emitPlan({ plan: planResult.plan })\n } catch (error) {\n return handlePipelineFailure(error)\n }\n\n if (options.dryRun === true) {\n renderDryRun(emission)\n } else {\n try {\n const executionResult = await executePlan({\n emission,\n executor,\n windowName: preset.name ?? presetName ?? \"vde-layout\",\n })\n logger.info(`Executed ${executionResult.executedSteps} tmux steps`)\n } catch (error) {\n return handlePipelineFailure(error)\n }\n }\n\n logger.success(`✓ Applied preset \"${preset.name}\"`)\n process.exit(0)\n } catch (error) {\n return handleError(error)\n }\n }\n\n const setupProgram = (): void => {\n program\n .name(\"vde-layout\")\n .description(\"VDE (Vibrant Development Environment) Layout Manager - tmux pane layout management tool\")\n .version(version, \"-V, --version\", \"Show version\")\n .helpOption(\"-h, --help\", \"Show help\")\n\n program.option(\"-v, --verbose\", \"Show detailed logs\", false)\n program.option(\"--dry-run\", \"Display commands without executing\", false)\n program.option(\"--config <path>\", \"Path to configuration file\")\n\n program\n .command(\"list\")\n .description(\"List available presets\")\n .action(async () => {\n await listPresets()\n })\n\n program\n .command(\"diagnose\")\n .description(\"Functional Coreリライトに向けた診断レポートを表示する\")\n .argument(\"[preset]\", 'Preset name (defaults to \"default\" preset when omitted)')\n .action(async (presetName?: string) => {\n await diagnosePreset(presetName)\n })\n\n program\n .argument(\"[preset]\", 'Preset name (defaults to \"default\" preset when omitted)')\n .action(async (presetName?: string) => {\n const opts = program.opts<{ verbose?: boolean; dryRun?: boolean }>()\n await executePreset(presetName, {\n verbose: opts.verbose === true,\n dryRun: opts.dryRun === true,\n })\n })\n }\n\n setupProgram()\n\n const run = async (args: string[] = process.argv.slice(2)): Promise<void> => {\n const requestedVersion = args.includes(\"--version\") || args.includes(\"-V\")\n const requestedHelp = args.includes(\"--help\") || args.includes(\"-h\")\n try {\n await program.parseAsync(args, { from: \"user\" })\n const opts = program.opts<{ verbose?: boolean; config?: string }>()\n\n if (requestedVersion || requestedHelp) {\n return\n }\n\n if (opts.verbose === true) {\n logger = createLogger({ level: LogLevel.INFO })\n } else {\n logger = createLogger()\n }\n\n if (\n typeof opts.config === \"string\" &&\n opts.config.length > 0 &&\n typeof presetManager.setConfigPath === \"function\"\n ) {\n presetManager.setConfigPath(opts.config)\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Process exited\")) {\n throw error\n }\n handleError(error)\n }\n }\n\n return { run }\n}\n","#!/usr/bin/env node\nimport { createCli } from \"./cli.ts\"\n\n/**\n * Main entry point\n * Launches the CLI application\n */\nasync function main(): Promise<void> {\n const cli = createCli()\n try {\n // Pass arguments excluding the first two elements (node, script path) from process.argv\n await cli.run(process.argv.slice(2))\n } catch (error) {\n // Format and display error message appropriately\n if (error instanceof Error) {\n console.error(\"Error:\", error.message)\n\n // Also display stack trace in debug mode\n if (process.env.VDE_DEBUG === \"true\") {\n console.error(error.stack)\n }\n } else {\n console.error(\"An unexpected error occurred:\", String(error))\n }\n\n process.exit(1)\n }\n}\n\n// Execute immediately\nvoid main()\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["formatters: Record<string, (error: VDELayoutError) => string>","SplitPaneSchema: z.ZodType<unknown>","PaneSchema: z.ZodType<unknown>","path","candidates: string[]","mergedConfig: Config","yaml","paths: string[]","existing: string[]","loaderOptions: ConfigLoaderOptions","cachedConfig: Config | null","parseCommand","toCommandString","newWindowCommand: string[]","severityRank: Record<DiagnosticsSeverity, number>","findings: DiagnosticsFinding[]","path","parsedPreset: unknown","parsed: unknown","panes: PlanNode[]","focusPaneIds: string[]","terminalPaneIds: string[]","steps: CommandStep[]","current: PlanNode","KNOWN_ISSUES: ReadonlyArray<string>","functionalCore: FunctionalCoreBridge","defaultCompilePreset","defaultCreateLayoutPlan","defaultEmitPlan","logger: Logger","document: Record<string, unknown>","toYAML","options","compileResult: CompilePresetSuccess","planResult: CreateLayoutPlanSuccess","emission: PlanEmission"],"sources":["../src/utils/errors.ts","../src/models/schema.ts","../src/config/validator.ts","../src/config/loader.ts","../src/layout/preset.ts","../src/utils/logger.ts","../src/executor/real-executor.ts","../src/executor/dry-run-executor.ts","../src/core/errors.ts","../src/executor/plan-runner.ts","../src/core/diagnostics.ts","../src/core/compile.ts","../src/core/planner.ts","../src/core/emitter.ts","../src/cli.ts","../src/index.ts"],"sourcesContent":["export type VDELayoutError = Error & {\n readonly code: string\n readonly details: Readonly<Record<string, unknown>>\n}\n\nexport const ErrorCodes = {\n CONFIG_NOT_FOUND: \"CONFIG_NOT_FOUND\",\n CONFIG_PARSE_ERROR: \"CONFIG_PARSE_ERROR\",\n CONFIG_PERMISSION_ERROR: \"CONFIG_PERMISSION_ERROR\",\n INVALID_PRESET: \"INVALID_PRESET\",\n PRESET_NOT_FOUND: \"PRESET_NOT_FOUND\",\n INVALID_LAYOUT: \"INVALID_LAYOUT\",\n INVALID_PANE: \"INVALID_PANE\",\n TMUX_NOT_RUNNING: \"TMUX_NOT_RUNNING\",\n TMUX_COMMAND_FAILED: \"TMUX_COMMAND_FAILED\",\n NOT_IN_TMUX_SESSION: \"NOT_IN_TMUX_SESSION\",\n NOT_IN_TMUX: \"NOT_IN_TMUX\",\n TMUX_NOT_FOUND: \"TMUX_NOT_FOUND\",\n TMUX_NOT_INSTALLED: \"TMUX_NOT_INSTALLED\",\n UNSUPPORTED_TMUX_VERSION: \"UNSUPPORTED_TMUX_VERSION\",\n} as const\n\nconst createBaseError = (\n name: string,\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n const error = new Error(message) as VDELayoutError\n error.name = name\n ;(error as { code: string }).code = code\n ;(error as { details: Readonly<Record<string, unknown>> }).details = details\n return error\n}\n\nexport const createConfigError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"ConfigError\", message, code, details)\n}\n\nexport const createValidationError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"ValidationError\", message, code, details)\n}\n\nexport const createTmuxError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"TmuxError\", message, code, details)\n}\n\nexport const createEnvironmentError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"EnvironmentError\", message, code, details)\n}\n\nexport const isVDELayoutError = (error: unknown): error is VDELayoutError => {\n if (typeof error !== \"object\" || error === null) {\n return false\n }\n\n if (!(\"code\" in error)) {\n return false\n }\n\n const { code } = error as { code?: unknown }\n if (typeof code !== \"string\") {\n return false\n }\n\n if (!(\"details\" in error)) {\n return false\n }\n\n return true\n}\n\nconst formatters: Record<string, (error: VDELayoutError) => string> = {\n [ErrorCodes.CONFIG_NOT_FOUND]: (error) => {\n const searchPaths = error.details.searchPaths\n if (!Array.isArray(searchPaths)) {\n return \"\"\n }\n\n const lines = [\"\", \"Searched in the following locations:\"]\n searchPaths.forEach((location) => lines.push(` - ${location}`))\n lines.push(\"\", \"To create a configuration file, run:\")\n lines.push(\" mkdir -p ~/.config/vde\")\n lines.push(' echo \"presets: {}\" > ~/.config/vde/layout.yml')\n return lines.join(\"\\n\")\n },\n [ErrorCodes.NOT_IN_TMUX_SESSION]: () => {\n return \"\\nThis command must be run inside a tmux session.\\nStart tmux first with: tmux\\n\"\n },\n [ErrorCodes.TMUX_NOT_INSTALLED]: () => {\n return (\n \"\\ntmux is required but not installed.\\n\" +\n \"Install tmux using your package manager:\\n\" +\n \" - macOS: brew install tmux\\n\" +\n \" - Ubuntu/Debian: sudo apt-get install tmux\\n\" +\n \" - Fedora: sudo dnf install tmux\\n\"\n )\n },\n [ErrorCodes.UNSUPPORTED_TMUX_VERSION]: (error) => {\n const requiredVersion = error.details.requiredVersion\n if (typeof requiredVersion !== \"string\") {\n return \"\"\n }\n return `\\nRequired tmux version: ${requiredVersion} or higher\\n`\n },\n}\n\nexport const formatError = (error: Error): string => {\n if (!isVDELayoutError(error)) {\n return `${error.name}: ${error.message}`\n }\n\n let message = `Error: ${error.message}`\n\n const formatter = formatters[error.code]\n if (formatter) {\n message += `\\n${formatter(error)}`\n }\n\n const commandDetail = error.details.command\n if (commandDetail !== undefined) {\n message += `\\nCommand: ${JSON.stringify(commandDetail)}`\n }\n\n const stderrDetail = error.details.stderr\n if (stderrDetail !== undefined) {\n message += `\\nstderr: ${String(stderrDetail)}`\n }\n\n const presetDetail = error.details.preset\n if (presetDetail !== undefined) {\n message += `\\npreset: ${String(presetDetail)}`\n }\n\n const nestedErrors = error.details.errors\n if (Array.isArray(nestedErrors) && nestedErrors.length > 0) {\n message += \"\\nValidation errors:\\n\"\n nestedErrors.forEach((item) => {\n message += ` - ${String(item)}\\n`\n })\n }\n\n return message\n}\n","import { z } from \"zod\"\n\n// Terminal pane schema\nconst TerminalPaneSchema = z\n .object({\n name: z.string().min(1),\n command: z.string().optional(),\n cwd: z.string().optional(),\n env: z.record(z.string()).optional(),\n delay: z.number().int().positive().optional(),\n title: z.string().optional(),\n focus: z.boolean().optional(),\n })\n .strict()\n\n// Split container schema (recursive)\nconst SplitPaneSchema: z.ZodType<unknown> = z.lazy(() =>\n z\n .object({\n type: z.enum([\"horizontal\", \"vertical\"]),\n ratio: z.array(z.number().positive()).min(1),\n panes: z.array(PaneSchema).min(1),\n })\n .strict()\n .refine((data) => data.ratio.length === data.panes.length, {\n message: \"Number of elements in ratio array does not match number of elements in panes array\",\n }),\n)\n\n// Recursive Pane schema definition\nexport const PaneSchema: z.ZodType<unknown> = z.lazy(() => z.union([SplitPaneSchema, TerminalPaneSchema]))\n\n// Layout schema definition\nexport const LayoutSchema = z\n .object({\n type: z.enum([\"horizontal\", \"vertical\"]),\n ratio: z.array(z.number().positive()).min(1),\n panes: z.array(PaneSchema).min(1),\n })\n .refine((data) => data.ratio.length === data.panes.length, {\n message: \"Number of elements in ratio array does not match number of elements in panes array\",\n })\n\n// Preset schema definition\nexport const PresetSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n layout: LayoutSchema.optional(),\n command: z.string().optional(),\n})\n\n// Config schema definition\nexport const ConfigSchema = z.object({\n presets: z.record(PresetSchema),\n})\n\n// Validation result type\ntype ValidationResult<T> = {\n success: boolean\n data?: T\n error?: string\n}\n\n// Helper function to format Zod errors consistently\nconst formatValidationError = (error: z.ZodError): string => {\n const messages = error.errors.map((e) => {\n const path = e.path.join(\".\")\n const message = e.message\n\n // Customize error message for panes array element count check\n if (path === \"layout.panes\" && message.includes(\"at least 2 element\")) {\n return `${path}: panes array must have at least 2 elements`\n }\n\n return `${path}: ${message}`\n })\n\n return messages.join(\"\\n\")\n}\n\n// Config validation\nexport const validateConfig = (data: unknown): ValidationResult<z.infer<typeof ConfigSchema>> => {\n try {\n const parsed = ConfigSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n\n// Preset validation\nexport const validatePreset = (data: unknown): ValidationResult<z.infer<typeof PresetSchema>> => {\n try {\n const parsed = PresetSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n\n// Pane validation\nexport const validatePane = (data: unknown): ValidationResult<z.infer<typeof PaneSchema>> => {\n try {\n const parsed = PaneSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n","import * as YAML from \"yaml\"\nimport { z } from \"zod\"\nimport { ConfigSchema } from \"../models/schema.ts\"\nimport type { Config } from \"../models/types.ts\"\nimport { createValidationError, ErrorCodes, isVDELayoutError } from \"../utils/errors.ts\"\n\n/**\n * Parse YAML text into an object\n * @param yamlText - YAML text to parse\n * @returns Parsed object\n * @throws {ValidationError} When YAML parsing fails\n */\nconst parseYAML = (yamlText: string): unknown => {\n // Input validation\n if (!yamlText || typeof yamlText !== \"string\") {\n throw createValidationError(\"YAML text not provided\", ErrorCodes.CONFIG_PARSE_ERROR, {\n received: typeof yamlText,\n })\n }\n\n try {\n return YAML.parse(yamlText)\n } catch (error) {\n throw createValidationError(\"Failed to parse YAML\", ErrorCodes.CONFIG_PARSE_ERROR, {\n parseError: error instanceof Error ? error.message : String(error),\n yamlSnippet: yamlText.substring(0, 200),\n })\n }\n}\n\n/**\n * Validate basic configuration structure\n * @param parsed - Parsed YAML object\n * @throws {ValidationError} When structure is invalid\n */\nconst validateConfigStructure = (parsed: unknown): void => {\n // Check for empty YAML\n if (parsed === null || parsed === undefined || typeof parsed !== \"object\") {\n throw createValidationError(\"YAML is empty or invalid format\", ErrorCodes.CONFIG_PARSE_ERROR, {\n parsed: parsed,\n })\n }\n\n // Check for presets field existence\n const parsedObj = parsed as Record<string, unknown>\n if (!(\"presets\" in parsedObj) || parsedObj.presets === undefined || parsedObj.presets === null) {\n throw createValidationError(\"presets field is required\", ErrorCodes.INVALID_PRESET, {\n availableFields: Object.keys(parsedObj),\n })\n }\n\n // Check for empty presets\n const presetsObj = parsedObj.presets\n if (typeof presetsObj !== \"object\" || presetsObj === null || Object.keys(presetsObj).length === 0) {\n throw createValidationError(\"At least one preset is required\", ErrorCodes.INVALID_PRESET, {\n presets: presetsObj,\n })\n }\n}\n\n/**\n * Format Zod validation errors into user-friendly messages\n * @param error - Zod validation error\n * @returns Formatted error issues\n */\nconst formatZodErrors = (error: z.ZodError): Array<{ path: string; message: string; code: string }> => {\n return error.issues.map((issue) => {\n const path = issue.path.join(\".\")\n let message = issue.message\n\n // Custom error messages\n if (issue.code === \"invalid_type\") {\n if (issue.path.includes(\"command\") && issue.expected === \"string\") {\n message = \"command field must be a string\"\n } else if (issue.path.includes(\"workingDirectory\") && issue.expected === \"string\") {\n message = \"workingDirectory field must be a string\"\n } else if (issue.received === \"number\" && issue.expected === \"string\") {\n message = `${path} must be a string`\n } else if (issue.received === \"array\" && issue.expected === \"string\") {\n message = `${path} must be a string`\n }\n } else if (issue.code === \"invalid_union\") {\n // Detailed error messages for union types\n const unionIssue = issue as z.ZodIssue & { unionErrors?: z.ZodError[] }\n if (unionIssue.unionErrors !== undefined) {\n // When command is missing in terminal pane\n const terminalError = unionIssue.unionErrors.find(\n (e) => e.issues?.some((i) => i.path.includes(\"command\") && i.code === \"invalid_type\") === true,\n )\n if (terminalError !== undefined) {\n message = \"command field is required\"\n } else {\n // When panes is missing in split pane\n const splitError = unionIssue.unionErrors.find(\n (e) => e.issues?.some((i) => i.path.includes(\"panes\") && i.code === \"invalid_type\") === true,\n )\n if (splitError !== undefined) {\n message = \"panes field is required\"\n } else {\n message = 'Pane type must be \"terminal\" or \"split\"'\n }\n }\n } else {\n message = 'Pane type must be \"terminal\" or \"split\"'\n }\n } else if (issue.code === \"invalid_literal\") {\n if (issue.path.includes(\"direction\")) {\n message = 'direction must be \"horizontal\" or \"vertical\"'\n }\n } else if (issue.message.includes(\"required\")) {\n // Use the message as is\n message = issue.message\n } else if (issue.code === \"custom\" && issue.message.includes(\"ratio array\")) {\n message = issue.message\n } else if (issue.code === \"too_small\" && issue.message.includes(\"Array must contain at least\")) {\n // Minimum array elements error\n if (path.includes(\"panes\")) {\n message = \"panes array must contain at least 2 elements\"\n } else if (path.includes(\"ratio\")) {\n message = \"ratio array must contain at least 2 elements\"\n } else {\n message = issue.message\n }\n }\n\n return {\n path,\n message,\n code: issue.code,\n }\n })\n}\n\n/**\n * Validates YAML text and converts it to a type-safe Config object\n * @param yamlText - YAML text to validate\n * @returns Validated Config object\n * @throws {ValidationError} When YAML is invalid\n */\nexport const validateYAML = (yamlText: string): Config => {\n // Parse YAML\n const parsed = parseYAML(yamlText)\n\n // Validate basic structure\n validateConfigStructure(parsed)\n\n // Ratio sum validation removed - unnecessary due to automatic normalization\n\n // Validation with Zod schema\n try {\n const validated = ConfigSchema.parse(parsed)\n return validated\n } catch (error) {\n if (error instanceof z.ZodError) {\n const issues = formatZodErrors(error)\n\n // Use the first error message as the primary message\n const primaryMessage = issues.length > 0 && issues[0] ? issues[0].message : \"Configuration validation failed\"\n\n throw createValidationError(primaryMessage, ErrorCodes.CONFIG_PARSE_ERROR, {\n issues,\n rawErrors: error.issues,\n })\n }\n\n if (isVDELayoutError(error) && error.name === \"ValidationError\") {\n throw error\n }\n\n // Other errors\n throw createValidationError(\"Unexpected validation error occurred\", ErrorCodes.CONFIG_PARSE_ERROR, {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n}\n","import fs from \"fs-extra\"\nimport path from \"path\"\nimport os from \"os\"\nimport * as yaml from \"yaml\"\nimport type { Config } from \"../models/types.ts\"\nimport { createConfigError, ErrorCodes } from \"../utils/errors.ts\"\nimport { validateYAML } from \"./validator.ts\"\n\nexport type ConfigLoaderOptions = {\n readonly configPaths?: string[]\n}\n\nexport type ConfigLoader = {\n readonly loadYAML: () => Promise<string>\n readonly loadConfig: () => Promise<Config>\n readonly findConfigFile: () => Promise<string | null>\n readonly getSearchPaths: () => string[]\n}\n\nexport const createConfigLoader = (options: ConfigLoaderOptions = {}): ConfigLoader => {\n const explicitConfigPaths = options.configPaths\n\n const computeCachedSearchPaths = (): string[] => {\n if (explicitConfigPaths && explicitConfigPaths.length > 0) {\n return [...explicitConfigPaths]\n }\n\n const candidates: string[] = []\n const projectCandidate = findProjectConfigCandidate()\n if (projectCandidate !== null) {\n candidates.push(projectCandidate)\n }\n\n candidates.push(...buildDefaultSearchPaths())\n\n return [...new Set(candidates)]\n }\n\n const loadConfig = async (): Promise<Config> => {\n if (explicitConfigPaths && explicitConfigPaths.length > 0) {\n const filePath = await findFirstExisting(explicitConfigPaths)\n if (filePath === null) {\n throw createConfigError(\"Configuration file not found\", ErrorCodes.CONFIG_NOT_FOUND, {\n searchPaths: explicitConfigPaths,\n })\n }\n\n const content = await safeReadFile(filePath)\n return validateYAML(content)\n }\n\n const searchPaths = computeCachedSearchPaths()\n const existingPaths = await filterExistingPaths(searchPaths)\n\n if (existingPaths.length === 0) {\n throw createConfigError(\"Configuration file not found\", ErrorCodes.CONFIG_NOT_FOUND, {\n searchPaths,\n })\n }\n\n const projectPath = findProjectConfigCandidate()\n const globalPaths = existingPaths.filter((filePath) => filePath !== projectPath)\n\n let mergedConfig: Config = { presets: {} }\n\n for (const globalPath of globalPaths) {\n const content = await safeReadFile(globalPath)\n const config = validateYAML(content)\n mergedConfig = mergeConfigs(mergedConfig, config)\n }\n\n if (projectPath !== null && (await fs.pathExists(projectPath))) {\n const content = await safeReadFile(projectPath)\n const config = validateYAML(content)\n mergedConfig = mergeConfigs(mergedConfig, config)\n }\n\n return mergedConfig\n }\n\n return {\n loadYAML: async (): Promise<string> => {\n const config = await loadConfig()\n return yaml.stringify(config)\n },\n loadConfig,\n findConfigFile: async (): Promise<string | null> => {\n const searchPaths =\n explicitConfigPaths && explicitConfigPaths.length > 0 ? [...explicitConfigPaths] : computeCachedSearchPaths()\n\n for (const searchPath of searchPaths) {\n if (await fs.pathExists(searchPath)) {\n return searchPath\n }\n }\n return null\n },\n getSearchPaths: (): string[] => computeCachedSearchPaths(),\n }\n}\n\nconst buildDefaultSearchPaths = (): string[] => {\n const paths: string[] = []\n\n const vdeConfigPath = process.env.VDE_CONFIG_PATH\n if (vdeConfigPath !== undefined) {\n paths.push(path.join(vdeConfigPath, \"layout.yml\"))\n }\n\n const homeDir = process.env.HOME ?? os.homedir()\n const xdgConfigHome = process.env.XDG_CONFIG_HOME ?? path.join(homeDir, \".config\")\n paths.push(path.join(xdgConfigHome, \"vde\", \"layout.yml\"))\n\n return [...new Set(paths)]\n}\n\nconst findProjectConfigCandidate = (): string | null => {\n let currentDir = process.cwd()\n const { root } = path.parse(currentDir)\n\n while (true) {\n const candidate = path.join(currentDir, \".vde\", \"layout.yml\")\n if (fs.existsSync(candidate)) {\n return candidate\n }\n\n if (currentDir === root) {\n break\n }\n\n const parent = path.dirname(currentDir)\n if (parent === currentDir) {\n break\n }\n\n currentDir = parent\n }\n\n return null\n}\n\nconst findFirstExisting = async (paths: ReadonlyArray<string>): Promise<string | null> => {\n for (const candidate of paths) {\n if (await fs.pathExists(candidate)) {\n return candidate\n }\n }\n return null\n}\n\nconst filterExistingPaths = async (paths: ReadonlyArray<string>): Promise<string[]> => {\n const existing: string[] = []\n for (const candidate of paths) {\n if (await fs.pathExists(candidate)) {\n existing.push(candidate)\n }\n }\n return existing\n}\n\nconst safeReadFile = async (filePath: string): Promise<string> => {\n try {\n return await fs.readFile(filePath, \"utf8\")\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw createConfigError(`Failed to read configuration file`, ErrorCodes.CONFIG_PERMISSION_ERROR, {\n filePath,\n error: errorMessage,\n })\n }\n}\n\nconst mergeConfigs = (base: Config, override: Config): Config => {\n return {\n presets: {\n ...base.presets,\n ...override.presets,\n },\n }\n}\n","import { createConfigLoader, type ConfigLoaderOptions } from \"../config/loader.ts\"\nimport { createConfigError, ErrorCodes } from \"../utils/errors.ts\"\nimport type { Config, Preset, PresetInfo } from \"../models/types.ts\"\nimport type { PresetManager } from \"../types/preset-manager.ts\"\n\ntype PresetState = {\n setConfigPath: (filePath: string) => void\n loadConfig: () => Promise<void>\n getPreset: (name: string) => Preset\n listPresets: () => PresetInfo[]\n getDefaultPreset: () => Preset\n}\n\nconst createState = (options: ConfigLoaderOptions = {}): PresetState => {\n let loaderOptions: ConfigLoaderOptions = options\n let cachedConfig: Config | null = null\n\n const setConfigPath = (filePath: string): void => {\n loaderOptions = { configPaths: [filePath] }\n cachedConfig = null\n }\n\n const loadConfig = async (): Promise<void> => {\n const loader = createConfigLoader(loaderOptions)\n cachedConfig = await loader.loadConfig()\n }\n\n const ensureConfig = (): Config => {\n if (cachedConfig === null) {\n throw createConfigError(\"Configuration not loaded\", ErrorCodes.CONFIG_NOT_FOUND)\n }\n return cachedConfig\n }\n\n const getPreset = (name: string): Preset => {\n const config = ensureConfig()\n const preset = config.presets[name]\n if (preset === undefined) {\n throw createConfigError(`Preset \"${name}\" not found`, ErrorCodes.PRESET_NOT_FOUND, {\n availablePresets: Object.keys(config.presets),\n })\n }\n return preset\n }\n\n const listPresets = (): PresetInfo[] => {\n if (cachedConfig === null) {\n return []\n }\n\n return Object.entries(cachedConfig.presets).map(([key, preset]) => ({\n key,\n name: preset.name,\n description: preset.description,\n }))\n }\n\n const getDefaultPreset = (): Preset => {\n const config = ensureConfig()\n\n if (config.presets.default !== undefined) {\n return config.presets.default\n }\n\n const firstKey = Object.keys(config.presets)[0]\n if (typeof firstKey !== \"string\" || firstKey.length === 0) {\n throw createConfigError(\"No presets defined\", ErrorCodes.PRESET_NOT_FOUND)\n }\n\n return config.presets[firstKey]!\n }\n\n return {\n setConfigPath,\n loadConfig,\n getPreset,\n listPresets,\n getDefaultPreset,\n }\n}\n\nexport const createPresetManager = (options: ConfigLoaderOptions = {}): PresetManager => {\n const state = createState(options)\n return {\n setConfigPath: state.setConfigPath,\n loadConfig: state.loadConfig,\n getPreset: state.getPreset,\n listPresets: state.listPresets,\n getDefaultPreset: state.getDefaultPreset,\n }\n}\n","import chalk from \"chalk\"\n\nexport enum LogLevel {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n}\n\ntype LoggerOptions = {\n readonly level?: LogLevel\n readonly prefix?: string\n}\n\nexport type Logger = {\n readonly level: LogLevel\n readonly prefix: string\n error: (message: string, error?: Error) => void\n warn: (message: string) => void\n info: (message: string) => void\n debug: (message: string) => void\n success: (message: string) => void\n createChild: (suffix: string) => Logger\n}\n\nconst resolveDefaultLogLevel = (): LogLevel => {\n if (process.env.VDE_DEBUG === \"true\") {\n return LogLevel.DEBUG\n }\n if (process.env.VDE_VERBOSE === \"true\") {\n return LogLevel.INFO\n }\n return LogLevel.WARN\n}\n\nconst formatMessage = (prefix: string, message: string): string => {\n return prefix ? `${prefix} ${message}` : message\n}\n\nexport const createLogger = (options: LoggerOptions = {}): Logger => {\n const level = options.level ?? resolveDefaultLogLevel()\n const prefix = options.prefix ?? \"\"\n\n const build = (nextPrefix: string, nextLevel: LogLevel): Logger => {\n const resolvedPrefix = nextPrefix\n\n return {\n level: nextLevel,\n prefix: resolvedPrefix,\n error(message: string, error?: Error): void {\n if (nextLevel >= LogLevel.ERROR) {\n console.error(chalk.red(formatMessage(resolvedPrefix, `Error: ${message}`)))\n if (error && process.env.VDE_DEBUG === \"true\") {\n console.error(chalk.gray(error.stack))\n }\n }\n },\n warn(message: string): void {\n if (nextLevel >= LogLevel.WARN) {\n console.warn(chalk.yellow(formatMessage(resolvedPrefix, message)))\n }\n },\n info(message: string): void {\n if (nextLevel >= LogLevel.INFO) {\n console.log(formatMessage(resolvedPrefix, message))\n }\n },\n debug(message: string): void {\n if (nextLevel >= LogLevel.DEBUG) {\n console.log(chalk.gray(formatMessage(resolvedPrefix, `[DEBUG] ${message}`)))\n }\n },\n success(message: string): void {\n console.log(chalk.green(formatMessage(resolvedPrefix, message)))\n },\n createChild(suffix: string): Logger {\n const childPrefix = resolvedPrefix ? `${resolvedPrefix} ${suffix}` : suffix\n return build(childPrefix, nextLevel)\n },\n }\n }\n\n return build(prefix, level)\n}\n","import { execa } from \"execa\"\nimport { createTmuxError, ErrorCodes } from \"../utils/errors.ts\"\nimport type { CommandExecutor } from \"../types/command-executor.ts\"\nimport { createLogger, LogLevel } from \"../utils/logger.ts\"\n\ntype RealExecutorOptions = {\n readonly verbose?: boolean\n}\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createRealExecutor = (options: RealExecutorOptions = {}): CommandExecutor => {\n const verbose = options.verbose ?? false\n const logger = createLogger({\n level: verbose ? LogLevel.INFO : LogLevel.WARN,\n prefix: \"[tmux]\",\n })\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n const commandString = toCommandString(args)\n\n logger.info(`Executing: ${commandString}`)\n\n try {\n const result = await execa(\"tmux\", args)\n return result.stdout\n } catch (error) {\n const execaError = error as { exitCode?: number; stderr?: string; message: string }\n\n throw createTmuxError(\"Failed to execute tmux command\", ErrorCodes.TMUX_COMMAND_FAILED, {\n command: commandString,\n exitCode: execaError.exitCode,\n stderr: execaError.stderr,\n })\n }\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return false\n },\n logCommand(command: string): void {\n logger.info(`Executing: ${command}`)\n },\n }\n}\n","import type { CommandExecutor } from \"../types/command-executor.ts\"\nimport { createLogger, LogLevel } from \"../utils/logger.ts\"\n\ntype DryRunExecutorOptions = {\n readonly verbose?: boolean\n}\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createDryRunExecutor = (options: DryRunExecutorOptions = {}): CommandExecutor => {\n const verbose = options.verbose ?? false\n const logger = createLogger({\n level: verbose ? LogLevel.INFO : LogLevel.WARN,\n prefix: \"[tmux] [DRY RUN]\",\n })\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n const commandString = toCommandString(args)\n logger.info(`Would execute: ${commandString}`)\n return \"\"\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return true\n },\n logCommand(command: string): void {\n logger.info(`Would execute: ${command}`)\n },\n }\n}\n","type FunctionalCoreErrorKind = \"compile\" | \"plan\" | \"emit\" | \"execution\"\n\nexport type FunctionalCoreError = {\n readonly kind: FunctionalCoreErrorKind\n readonly code: string\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n}\n\nexport const createFunctionalError = (\n kind: FunctionalCoreErrorKind,\n error: {\n readonly code: string\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): FunctionalCoreError => ({\n kind,\n code: error.code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n})\n\nexport const isFunctionalCoreError = (value: unknown): value is FunctionalCoreError => {\n if (typeof value !== \"object\" || value === null) {\n return false\n }\n const candidate = value as Partial<FunctionalCoreError>\n return (\n (candidate.kind === \"compile\" ||\n candidate.kind === \"plan\" ||\n candidate.kind === \"emit\" ||\n candidate.kind === \"execution\") &&\n typeof candidate.code === \"string\" &&\n typeof candidate.message === \"string\"\n )\n}\n","import type { CommandExecutor } from \"../types/command-executor.ts\"\nimport type { PlanEmission, CommandStep, EmittedTerminal } from \"../core/emitter.ts\"\nimport { ErrorCodes } from \"../utils/errors.ts\"\nimport { createFunctionalError } from \"../core/errors.ts\"\n\nconst DOUBLE_QUOTE = '\"'\nconst ESCAPED_DOUBLE_QUOTE = '\\\\\"'\n\ntype ExecutePlanInput = {\n readonly emission: PlanEmission\n readonly executor: CommandExecutor\n readonly windowName?: string\n}\n\ntype ExecutePlanSuccess = {\n readonly executedSteps: number\n}\n\nexport const executePlan = async ({\n emission,\n executor,\n windowName,\n}: ExecutePlanInput): Promise<ExecutePlanSuccess> => {\n const initialVirtualPaneId = emission.summary.initialPaneId\n if (typeof initialVirtualPaneId !== \"string\" || initialVirtualPaneId.length === 0) {\n raiseExecutionError(\"INVALID_PLAN\", {\n message: \"Plan emission is missing initial pane metadata\",\n path: \"plan.initialPaneId\",\n })\n }\n\n const paneMap = new Map<string, string>()\n\n const newWindowCommand: string[] = [\"new-window\", \"-P\", \"-F\", \"#{pane_id}\"]\n if (typeof windowName === \"string\" && windowName.trim().length > 0) {\n newWindowCommand.push(\"-n\", windowName.trim())\n }\n\n const initialPaneId = normalizePaneId(\n await executeCommand(executor, newWindowCommand, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to create tmux window\",\n path: initialVirtualPaneId,\n }),\n )\n\n registerPane(paneMap, initialVirtualPaneId, initialPaneId)\n\n let executedSteps = 0\n\n for (const step of emission.steps) {\n if (step.kind === \"split\") {\n await executeSplitStep({ step, executor, paneMap })\n } else if (step.kind === \"focus\") {\n await executeFocusStep({ step, executor, paneMap })\n }\n executedSteps += 1\n }\n\n await executeTerminalCommands({ terminals: emission.terminals, executor, paneMap })\n\n const finalRealFocus = resolvePaneId(paneMap, emission.summary.focusPaneId)\n if (typeof finalRealFocus === \"string\" && finalRealFocus.length > 0) {\n await executeCommand(executor, [\"select-pane\", \"-t\", finalRealFocus], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to restore focus\",\n path: emission.summary.focusPaneId,\n })\n }\n\n return { executedSteps }\n}\n\nconst executeSplitStep = async ({\n step,\n executor,\n paneMap,\n}: {\n readonly step: CommandStep\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n const targetVirtualId = ensureNonEmpty(step.targetPaneId, () =>\n raiseExecutionError(\"MISSING_TARGET\", {\n message: \"Split step missing target pane metadata\",\n path: step.id,\n }),\n )\n\n const targetRealId = ensureNonEmpty(resolvePaneId(paneMap, targetVirtualId), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: `Unknown target pane: ${targetVirtualId}`,\n path: step.id,\n }),\n )\n\n const panesBefore = await listPaneIds(executor, step)\n const splitCommand = replaceTarget(step.command, targetRealId)\n await executeCommand(executor, splitCommand, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute split step ${step.id}`,\n path: step.id,\n details: { command: splitCommand },\n })\n\n const panesAfter = await listPaneIds(executor, step)\n const newPaneId = ensureNonEmpty(findNewPaneId(panesBefore, panesAfter), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: \"Unable to determine newly created pane\",\n path: step.id,\n }),\n )\n\n const createdVirtualId = step.createdPaneId\n if (typeof createdVirtualId === \"string\" && createdVirtualId.length > 0) {\n registerPane(paneMap, createdVirtualId, newPaneId)\n }\n}\n\nconst executeFocusStep = async ({\n step,\n executor,\n paneMap,\n}: {\n readonly step: CommandStep\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n const targetVirtualId = ensureNonEmpty(step.targetPaneId, () =>\n raiseExecutionError(\"MISSING_TARGET\", {\n message: \"Focus step missing target pane metadata\",\n path: step.id,\n }),\n )\n\n const targetRealId = ensureNonEmpty(resolvePaneId(paneMap, targetVirtualId), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: `Unknown focus pane: ${targetVirtualId}`,\n path: step.id,\n }),\n )\n\n const command = replaceTarget(step.command, targetRealId)\n await executeCommand(executor, command, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute focus step ${step.id}`,\n path: step.id,\n details: { command },\n })\n}\n\nconst executeTerminalCommands = async ({\n terminals,\n executor,\n paneMap,\n}: {\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n for (const terminal of terminals) {\n const realPaneId = ensureNonEmpty(resolvePaneId(paneMap, terminal.virtualPaneId), () =>\n raiseExecutionError(\"UNKNOWN_PANE\", {\n message: `Unknown terminal pane: ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n }),\n )\n\n if (typeof terminal.cwd === \"string\" && terminal.cwd.length > 0) {\n const escapedCwd = terminal.cwd.split(DOUBLE_QUOTE).join(ESCAPED_DOUBLE_QUOTE)\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, `cd \"${escapedCwd}\"`, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to change directory for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { cwd: terminal.cwd },\n })\n }\n\n if (terminal.env !== undefined) {\n for (const [key, value] of Object.entries(terminal.env)) {\n const escaped = String(value).split(DOUBLE_QUOTE).join(ESCAPED_DOUBLE_QUOTE)\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, `export ${key}=\"${escaped}\"`, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to set environment variable ${key}`,\n path: terminal.virtualPaneId,\n })\n }\n }\n\n if (typeof terminal.command === \"string\" && terminal.command.length > 0) {\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, terminal.command, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute command for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { command: terminal.command },\n })\n }\n }\n}\n\nconst executeCommand = async (\n executor: CommandExecutor,\n command: string[],\n context: {\n readonly code: string\n readonly message: string\n readonly path: string\n readonly details?: Record<string, unknown>\n },\n): Promise<string> => {\n try {\n return await executor.execute([...command])\n } catch (error) {\n if (error instanceof Error && \"code\" in error && \"message\" in error) {\n const candidate = error as { code?: string; message?: string; details?: Record<string, unknown> }\n throw createFunctionalError(\"execution\", {\n code: typeof candidate.code === \"string\" ? candidate.code : context.code,\n message: candidate.message ?? context.message,\n path: context.path,\n details: candidate.details ?? context.details,\n })\n }\n\n throw createFunctionalError(\"execution\", {\n code: context.code,\n message: context.message,\n path: context.path,\n details: context.details,\n })\n }\n}\n\nconst listPaneIds = async (executor: CommandExecutor, step: CommandStep): Promise<string[]> => {\n const output = await executeCommand(executor, [\"list-panes\", \"-F\", \"#{pane_id}\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to list tmux panes\",\n path: step.id,\n })\n\n return output\n .split(\"\\n\")\n .map((pane) => pane.trim())\n .filter((pane) => pane.length > 0)\n}\n\nconst findNewPaneId = (before: string[], after: string[]): string | undefined => {\n const beforeSet = new Set(before)\n return after.find((id) => !beforeSet.has(id))\n}\n\nconst replaceTarget = (command: ReadonlyArray<string>, realTarget: string): string[] => {\n const next = [...command]\n const targetIndex = next.findIndex((value, index) => value === \"-t\" && index + 1 < next.length)\n if (targetIndex >= 0) {\n next[targetIndex + 1] = realTarget\n return next\n }\n\n if (next.length > 0) {\n next[next.length - 1] = realTarget\n }\n return next\n}\n\nconst normalizePaneId = (raw: string): string => {\n const trimmed = raw.trim()\n return trimmed.length === 0 ? \"%0\" : trimmed\n}\n\nconst registerPane = (paneMap: Map<string, string>, virtualId: string, realId: string): void => {\n paneMap.set(virtualId, realId)\n}\n\nconst resolvePaneId = (paneMap: Map<string, string>, virtualId: string): string | undefined => {\n const direct = paneMap.get(virtualId)\n if (typeof direct === \"string\" && direct.length > 0) {\n return direct\n }\n\n let ancestor = virtualId\n while (ancestor.includes(\".\")) {\n ancestor = ancestor.slice(0, ancestor.lastIndexOf(\".\"))\n const candidate = paneMap.get(ancestor)\n if (typeof candidate === \"string\" && candidate.length > 0) {\n paneMap.set(virtualId, candidate)\n return candidate\n }\n }\n\n for (const [key, value] of paneMap.entries()) {\n if (key.startsWith(`${virtualId}.`)) {\n if (typeof value === \"string\" && value.length > 0) {\n paneMap.set(virtualId, value)\n return value\n }\n }\n }\n\n return undefined\n}\n\nconst ensureNonEmpty = <T extends string>(value: T | undefined, buildError: () => never): T => {\n if (value === undefined || value.length === 0) {\n return buildError()\n }\n return value\n}\n\nconst raiseExecutionError = (\n code: string,\n error: {\n readonly message: string\n readonly path: string\n readonly details?: Record<string, unknown>\n },\n): never => {\n throw createFunctionalError(\"execution\", {\n code,\n message: error.message,\n path: error.path,\n details: error.details,\n })\n}\n","import { parse } from \"yaml\"\n\nexport type DiagnosticsSeverity = \"high\" | \"medium\" | \"low\"\n\ntype DiagnosticsFinding = {\n readonly path: string\n readonly severity: DiagnosticsSeverity\n readonly description: string\n}\n\ntype DiagnosticsBacklogItem = {\n readonly id: string\n readonly severity: DiagnosticsSeverity\n readonly summary: string\n readonly actions: ReadonlyArray<string>\n}\n\nexport type DiagnosticsReport = {\n readonly findings: ReadonlyArray<DiagnosticsFinding>\n readonly nextSteps: ReadonlyArray<string>\n readonly backlog: ReadonlyArray<DiagnosticsBacklogItem>\n}\n\ntype DiagnosticsInput = {\n readonly presetDocument: string\n readonly knownIssues?: ReadonlyArray<string>\n}\n\nconst severityRank: Record<DiagnosticsSeverity, number> = {\n high: 3,\n medium: 2,\n low: 1,\n}\n\ntype FindingAccumulator = {\n add: (args: { path: string; severity: DiagnosticsSeverity; description: string; nextStep?: string }) => void\n readonly findings: DiagnosticsFinding[]\n readonly nextSteps: Set<string>\n readonly backlog: Map<string, DiagnosticsBacklogItem>\n}\n\nconst createAccumulator = (): FindingAccumulator => {\n const findings: DiagnosticsFinding[] = []\n const nextSteps = new Set<string>()\n const backlog = new Map<string, DiagnosticsBacklogItem>()\n\n return {\n findings,\n nextSteps,\n backlog,\n add: ({ path, severity, description, nextStep }): void => {\n findings.push({ path, severity, description })\n if (typeof nextStep === \"string\" && nextStep.length > 0) {\n nextSteps.add(nextStep)\n }\n\n const existing = backlog.get(path)\n const existingActions = new Set(existing?.actions ?? [])\n existingActions.add(description)\n if (typeof nextStep === \"string\" && nextStep.length > 0) {\n existingActions.add(nextStep)\n }\n\n const mergedSeverity = existing !== undefined ? maxSeverity(existing.severity, severity) : severity\n\n const summary =\n existing !== undefined && severityRank[existing.severity] >= severityRank[severity]\n ? existing.summary\n : description\n\n backlog.set(path, {\n id: path,\n severity: mergedSeverity,\n summary,\n actions: Array.from(existingActions),\n })\n },\n }\n}\n\nexport const runDiagnostics = (input: DiagnosticsInput): DiagnosticsReport => {\n const accumulator = createAccumulator()\n const knownIssues = input.knownIssues ?? []\n let parsedPreset: unknown\n\n try {\n parsedPreset = parse(input.presetDocument)\n } catch (error) {\n accumulator.add({\n path: \"presetDocument\",\n severity: \"high\",\n description: `プリセットYAMLの解析に失敗しました: ${(error as Error).message}`,\n nextStep: \"プリセットYAMLを構文チェックし、Functional Coreリライト前に整合性を確保する\",\n })\n return {\n findings: sortBySeverity(accumulator.findings),\n nextSteps: Array.from(accumulator.nextSteps),\n backlog: sortBacklog(accumulator.backlog),\n }\n }\n\n if (parsedPreset === null || typeof parsedPreset !== \"object\") {\n accumulator.add({\n path: \"preset\",\n severity: \"high\",\n description: \"プリセット定義がオブジェクト形式ではありません\",\n nextStep: \"プリセットYAMLをオブジェクト構造に整形し整合性を確保する\",\n })\n } else {\n const presetObject = parsedPreset as Record<string, unknown>\n checkFocusDuplications(presetObject, accumulator)\n collectLowPrioritySignals(presetObject, accumulator)\n }\n\n knownIssues.forEach((issue, index) => {\n const trimmed = issue.trim()\n if (trimmed.length === 0) {\n return\n }\n\n accumulator.add({\n path: `codebase.knownIssues[${index}]`,\n severity: \"medium\",\n description: trimmed,\n nextStep: `tmux依存や副作用をFunctional Core境界で切り離す: ${trimmed}`,\n })\n })\n\n return {\n findings: sortBySeverity(accumulator.findings),\n nextSteps: Array.from(accumulator.nextSteps),\n backlog: sortBacklog(accumulator.backlog),\n }\n}\n\nconst checkFocusDuplications = (preset: Record<string, unknown>, accumulator: FindingAccumulator): void => {\n const layout = preset.layout as unknown\n if (layout === undefined || layout === null) {\n return\n }\n\n const focusCount = countFocusFlags(layout)\n if (focusCount > 1) {\n accumulator.add({\n path: \"preset.layout\",\n severity: \"high\",\n description: \"複数のペインでfocus: trueが指定されています\",\n nextStep: \"focusは単一ペインに限定しPlan生成時に一貫するようFunctional Coreで制御する\",\n })\n }\n}\n\nconst collectLowPrioritySignals = (preset: Record<string, unknown>, accumulator: FindingAccumulator): void => {\n const layout = preset.layout as Record<string, unknown> | undefined | null\n if (layout === undefined || layout === null) {\n accumulator.add({\n path: \"preset.layout\",\n severity: \"low\",\n description: \"layout定義が存在しません(単一ペイン運用が前提)\",\n nextStep: \"単一ペイン前提でもPlan出力に影響しないことをFunctional Coreで確認する\",\n })\n return\n }\n\n if (!Array.isArray(layout.panes)) {\n accumulator.add({\n path: \"preset.layout.panes\",\n severity: \"low\",\n description: \"panes配列が存在しないか配列ではありません\",\n nextStep: \"レイアウト定義の構造を正規化し、Plan生成の入力契約を明示する\",\n })\n }\n}\n\nconst countFocusFlags = (node: unknown): number => {\n if (Array.isArray(node)) {\n return node.reduce((sum, child) => sum + countFocusFlags(child), 0)\n }\n\n if (node === null || typeof node !== \"object\") {\n return 0\n }\n\n const record = node as Record<string, unknown>\n const selfFocus = record.focus === true ? 1 : 0\n const childFocus = Array.isArray(record.panes)\n ? record.panes.reduce((sum, child) => sum + countFocusFlags(child), 0)\n : 0\n\n return selfFocus + childFocus\n}\n\nconst sortBySeverity = (findings: DiagnosticsFinding[]): DiagnosticsFinding[] => {\n return [...findings].sort((a, b) => severityRank[b.severity] - severityRank[a.severity])\n}\n\nconst sortBacklog = (backlog: Map<string, DiagnosticsBacklogItem>): DiagnosticsBacklogItem[] => {\n return [...backlog.values()].sort((a, b) => severityRank[b.severity] - severityRank[a.severity])\n}\n\nconst maxSeverity = (left: DiagnosticsSeverity, right: DiagnosticsSeverity): DiagnosticsSeverity => {\n return severityRank[left] >= severityRank[right] ? left : right\n}\n","import { parse } from \"yaml\"\nimport { createFunctionalError, type FunctionalCoreError } from \"./errors.ts\"\n\nexport type CompilePresetInput = {\n readonly document: string\n readonly source: string\n}\n\nexport type FunctionalTerminalPane = {\n readonly kind: \"terminal\"\n readonly name: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly focus?: boolean\n readonly options?: Readonly<Record<string, unknown>>\n}\n\nexport type FunctionalSplitPane = {\n readonly kind: \"split\"\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly ratio: ReadonlyArray<number>\n readonly panes: ReadonlyArray<FunctionalLayoutNode>\n}\n\nexport type FunctionalLayoutNode = FunctionalTerminalPane | FunctionalSplitPane\n\ntype FunctionalPresetMetadata = {\n readonly source: string\n}\n\nexport type FunctionalPreset = {\n readonly name: string\n readonly version: string\n readonly command?: string\n readonly layout?: FunctionalLayoutNode\n readonly metadata: FunctionalPresetMetadata\n}\n\nexport type CompilePresetSuccess = {\n readonly preset: FunctionalPreset\n}\n\nexport const compilePreset = ({ document, source }: CompilePresetInput): CompilePresetSuccess => {\n let parsed: unknown\n try {\n parsed = parse(document)\n } catch (error) {\n throw compileError(\"PRESET_PARSE_ERROR\", {\n source,\n message: `YAMLの解析に失敗しました: ${(error as Error).message}`,\n details: {\n reason: error instanceof Error ? error.message : String(error),\n },\n })\n }\n\n if (!isRecord(parsed)) {\n throw compileError(\"PRESET_INVALID_DOCUMENT\", {\n source,\n message: \"プリセット定義がオブジェクトではありません\",\n path: \"preset\",\n })\n }\n\n const name = typeof parsed.name === \"string\" && parsed.name.trim().length > 0 ? parsed.name : \"Unnamed preset\"\n\n const layout = parseLayoutNode(parsed.layout, {\n source,\n path: \"preset.layout\",\n })\n\n return {\n preset: {\n name,\n version: \"legacy\",\n command: typeof parsed.command === \"string\" ? parsed.command : undefined,\n layout: layout ?? undefined,\n metadata: { source },\n },\n }\n}\n\nconst parseLayoutNode = (\n node: unknown,\n context: { readonly source: string; readonly path: string },\n): FunctionalLayoutNode | null => {\n if (node === undefined || node === null) {\n return null\n }\n\n if (!isRecord(node)) {\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"レイアウトノードの形式が不正です\",\n path: context.path,\n details: { node },\n })\n }\n\n if (typeof node.type === \"string\" && Array.isArray(node.panes)) {\n return parseSplitPane(node, context)\n }\n\n if (typeof node.name === \"string\") {\n return parseTerminalPane(node)\n }\n\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"レイアウトノードの形式が不正です\",\n path: context.path,\n details: { node },\n })\n}\n\nconst parseSplitPane = (\n node: Record<string, unknown>,\n context: { readonly source: string; readonly path: string },\n): FunctionalSplitPane => {\n const orientation = node.type\n if (orientation !== \"horizontal\" && orientation !== \"vertical\") {\n throw compileError(\"LAYOUT_INVALID_ORIENTATION\", {\n source: context.source,\n message: \"layout.type は horizontal か vertical である必要があります\",\n path: `${context.path}.type`,\n details: { type: orientation },\n })\n }\n\n if (!Array.isArray(node.panes) || node.panes.length === 0) {\n throw compileError(\"LAYOUT_PANES_MISSING\", {\n source: context.source,\n message: \"panes 配列が存在しません\",\n path: `${context.path}.panes`,\n })\n }\n\n if (!Array.isArray(node.ratio) || node.ratio.length === 0) {\n throw compileError(\"LAYOUT_RATIO_MISSING\", {\n source: context.source,\n message: \"ratio 配列が存在しません\",\n path: `${context.path}.ratio`,\n })\n }\n\n if (node.ratio.length !== node.panes.length) {\n throw compileError(\"LAYOUT_RATIO_MISMATCH\", {\n source: context.source,\n message: \"ratio 配列と panes 配列の長さが一致しません\",\n path: context.path,\n details: {\n ratioLength: node.ratio.length,\n panesLength: node.panes.length,\n },\n })\n }\n\n const ratio = node.ratio.map((value, index) => {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw compileError(\"RATIO_INVALID_VALUE\", {\n source: context.source,\n message: \"ratio の値が正の数値ではありません\",\n path: `${context.path}.ratio[${index}]`,\n details: { value },\n })\n }\n return value\n })\n\n const panes = node.panes.map((child, index) =>\n parseLayoutNode(child, {\n source: context.source,\n path: `${context.path}.panes[${index}]`,\n }),\n )\n\n return {\n kind: \"split\",\n orientation,\n ratio,\n panes: panes.filter((pane): pane is FunctionalLayoutNode => pane !== null),\n }\n}\n\nconst parseTerminalPane = (node: Record<string, unknown>): FunctionalTerminalPane => {\n const name = typeof node.name === \"string\" ? node.name : \"\"\n const command = typeof node.command === \"string\" ? node.command : undefined\n const cwd = typeof node.cwd === \"string\" ? node.cwd : undefined\n const focus = node.focus === true ? true : undefined\n const env = normalizeEnv(node.env)\n\n const knownKeys = new Set([\"name\", \"command\", \"cwd\", \"env\", \"focus\", \"options\", \"title\", \"delay\"])\n const options = collectOptions(node, knownKeys)\n\n return {\n kind: \"terminal\",\n name,\n command,\n cwd,\n env,\n focus,\n options,\n }\n}\n\nconst normalizeEnv = (env: unknown): Readonly<Record<string, string>> | undefined => {\n if (!isRecord(env)) {\n return undefined\n }\n\n const entries = Object.entries(env).reduce<Record<string, string>>((accumulator, [key, value]) => {\n if (typeof value === \"string\") {\n accumulator[key] = value\n }\n return accumulator\n }, {})\n\n return Object.keys(entries).length > 0 ? entries : undefined\n}\n\nconst collectOptions = (\n node: Record<string, unknown>,\n excludedKeys: ReadonlySet<string>,\n): Readonly<Record<string, unknown>> | undefined => {\n const optionsEntries = Object.entries(node).filter(([key]) => !excludedKeys.has(key))\n if (optionsEntries.length === 0) {\n return undefined\n }\n\n return optionsEntries.reduce<Record<string, unknown>>((accumulator, [key, value]) => {\n accumulator[key] = value\n return accumulator\n }, {})\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === \"object\" && value !== null\n}\n\nconst compileError = (\n code: string,\n error: {\n readonly source?: string\n readonly message: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): FunctionalCoreError => {\n return createFunctionalError(\"compile\", {\n code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n })\n}\n","import type { FunctionalLayoutNode, FunctionalPreset, FunctionalSplitPane, FunctionalTerminalPane } from \"./compile.ts\"\nimport { createFunctionalError, type FunctionalCoreError } from \"./errors.ts\"\n\ntype CreateLayoutPlanInput = {\n readonly preset: FunctionalPreset\n}\n\ntype PlanTerminal = {\n readonly kind: \"terminal\"\n readonly id: string\n readonly name: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly focus: boolean\n readonly options?: Readonly<Record<string, unknown>>\n}\n\ntype PlanSplit = {\n readonly kind: \"split\"\n readonly id: string\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly ratio: ReadonlyArray<number>\n readonly panes: ReadonlyArray<PlanNode>\n}\n\nexport type PlanNode = PlanTerminal | PlanSplit\n\nexport type LayoutPlan = {\n readonly root: PlanNode\n readonly focusPaneId: string\n}\n\nexport type CreateLayoutPlanSuccess = {\n readonly plan: LayoutPlan\n}\n\nexport const createLayoutPlan = ({ preset }: CreateLayoutPlanInput): CreateLayoutPlanSuccess => {\n if (!preset.layout) {\n const terminal = createTerminalNode({\n id: \"root\",\n terminal: {\n kind: \"terminal\",\n name: preset.name,\n command: preset.command,\n },\n focusOverride: true,\n })\n\n return {\n plan: {\n root: terminal,\n focusPaneId: terminal.id,\n },\n }\n }\n\n const { node, focusPaneIds, terminalPaneIds } = buildLayoutNode(preset.layout, {\n parentId: \"root\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n })\n\n if (focusPaneIds.length > 1) {\n throw planError(\"FOCUS_CONFLICT\", {\n message: \"複数のペインでfocusが指定されています\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n details: { focusPaneIds },\n })\n }\n\n if (terminalPaneIds.length === 0) {\n throw planError(\"NO_TERMINAL_PANES\", {\n message: \"ターミナルペインが存在しません\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n })\n }\n\n const focusPaneId = focusPaneIds[0] ?? terminalPaneIds[0]!\n const root = ensureFocus(node, focusPaneId)\n\n return {\n plan: {\n root,\n focusPaneId,\n },\n }\n}\n\ntype BuildResult = {\n readonly node: PlanNode\n readonly focusPaneIds: ReadonlyArray<string>\n readonly terminalPaneIds: ReadonlyArray<string>\n}\n\nconst buildLayoutNode = (\n node: FunctionalLayoutNode,\n context: { readonly parentId: string; readonly path: string; readonly source: string },\n): BuildResult => {\n if (node.kind === \"split\") {\n return buildSplitNode(node, context)\n }\n\n return {\n node: createTerminalNode({ id: context.parentId, terminal: node }),\n focusPaneIds: node.focus === true ? [context.parentId] : [],\n terminalPaneIds: [context.parentId],\n }\n}\n\nconst buildSplitNode = (\n node: FunctionalSplitPane,\n context: { readonly parentId: string; readonly path: string; readonly source: string },\n): BuildResult => {\n const ratio = normalizeRatio(node.ratio, context)\n\n const panes: PlanNode[] = []\n const focusPaneIds: string[] = []\n const terminalPaneIds: string[] = []\n\n for (let index = 0; index < node.panes.length; index += 1) {\n const childId = `${context.parentId}.${index}`\n const childContext = {\n parentId: childId,\n path: `${context.path}.panes[${index}]`,\n source: context.source,\n }\n\n const childResult = buildLayoutNode(node.panes[index]!, childContext)\n panes.push(childResult.node)\n focusPaneIds.push(...childResult.focusPaneIds)\n terminalPaneIds.push(...childResult.terminalPaneIds)\n }\n\n return {\n node: {\n kind: \"split\",\n id: context.parentId,\n orientation: node.orientation,\n ratio,\n panes,\n },\n focusPaneIds,\n terminalPaneIds,\n }\n}\n\nconst createTerminalNode = ({\n id,\n terminal,\n focusOverride,\n}: {\n readonly id: string\n readonly terminal: FunctionalTerminalPane\n readonly focusOverride?: boolean\n}): PlanTerminal => {\n return {\n kind: \"terminal\",\n id,\n name: terminal.name,\n command: terminal.command,\n cwd: terminal.cwd,\n env: terminal.env,\n options: terminal.options,\n focus: focusOverride === true ? true : terminal.focus === true,\n }\n}\n\nconst ensureFocus = (node: PlanNode, focusPaneId: string): PlanNode => {\n if (node.kind === \"terminal\") {\n return {\n ...node,\n focus: node.id === focusPaneId,\n }\n }\n\n return {\n ...node,\n panes: node.panes.map((pane) => ensureFocus(pane, focusPaneId)),\n }\n}\n\nconst normalizeRatio = (\n ratio: ReadonlyArray<number>,\n context: { readonly path: string; readonly source: string },\n): number[] => {\n const total = ratio.reduce((sum, value, index) => {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n throw planError(\"RATIO_INVALID_VALUE\", {\n message: \"ratio の値が非負の数値ではありません\",\n path: `${context.path}.ratio[${index}]`,\n source: context.source,\n details: { value },\n })\n }\n return sum + value\n }, 0)\n\n if (total === 0) {\n return ratio.map(() => 1 / ratio.length)\n }\n\n return ratio.map((value) => value / total)\n}\n\nconst planError = (\n code: string,\n error: {\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): FunctionalCoreError => {\n return createFunctionalError(\"plan\", {\n code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n })\n}\n","import { createHash } from \"crypto\"\nimport type { LayoutPlan, PlanNode } from \"./planner.ts\"\n\ntype EmitPlanInput = {\n readonly plan: LayoutPlan\n}\n\ntype CommandStepKind = \"split\" | \"focus\"\n\nexport type CommandStep = {\n readonly id: string\n readonly kind: CommandStepKind\n readonly command: ReadonlyArray<string>\n readonly summary: string\n readonly targetPaneId?: string\n readonly createdPaneId?: string\n}\n\nexport type EmittedTerminal = {\n readonly virtualPaneId: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly focus: boolean\n readonly name: string\n}\n\ntype PlanEmissionSummary = {\n readonly stepsCount: number\n readonly focusPaneId: string\n readonly initialPaneId: string\n}\n\nexport type PlanEmission = {\n readonly steps: ReadonlyArray<CommandStep>\n readonly summary: PlanEmissionSummary\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly hash: string\n}\n\ntype SplitNode = Extract<PlanNode, { kind: \"split\" }>\n\nexport const emitPlan = ({ plan }: EmitPlanInput): PlanEmission => {\n const steps: CommandStep[] = []\n collectSplitSteps(plan.root, steps)\n\n steps.push({\n id: `${plan.focusPaneId}:focus`,\n kind: \"focus\",\n command: [\"select-pane\", \"-t\", plan.focusPaneId],\n summary: `select pane ${plan.focusPaneId}`,\n targetPaneId: plan.focusPaneId,\n })\n\n const hash = createPlanHash(plan, steps)\n const initialPaneId = determineInitialPaneId(plan.root)\n const terminals = collectTerminals(plan.root)\n\n return {\n steps,\n summary: {\n stepsCount: steps.length,\n focusPaneId: plan.focusPaneId,\n initialPaneId,\n },\n terminals,\n hash,\n }\n}\n\nconst collectSplitSteps = (node: PlanNode, steps: CommandStep[]): void => {\n if (node.kind === \"terminal\") {\n return\n }\n\n appendSplitSteps(node, steps)\n node.panes.forEach((pane) => collectSplitSteps(pane, steps))\n}\n\nconst appendSplitSteps = (node: SplitNode, steps: CommandStep[]): void => {\n const directionFlag = node.orientation === \"horizontal\" ? \"-h\" : \"-v\"\n\n for (let index = 1; index < node.panes.length; index += 1) {\n const remainingIncludingTarget = node.ratio.slice(index - 1).reduce((sum, value) => sum + value, 0)\n const remainingAfterTarget = node.ratio.slice(index).reduce((sum, value) => sum + value, 0)\n\n const desiredPercentage =\n remainingIncludingTarget === 0 ? 0 : (remainingAfterTarget / remainingIncludingTarget) * 100\n const percentage = Math.max(1, Math.round(desiredPercentage))\n const targetPaneId = node.panes[index - 1]?.id ?? node.id\n const createdPaneId = node.panes[index]?.id\n\n steps.push({\n id: `${node.id}:split:${index}`,\n kind: \"split\",\n command: [\"split-window\", directionFlag, \"-t\", targetPaneId, \"-p\", String(Math.min(percentage, 99))],\n summary: `split ${targetPaneId} (${directionFlag})`,\n targetPaneId,\n createdPaneId,\n })\n }\n}\n\nconst collectTerminals = (node: PlanNode): EmittedTerminal[] => {\n if (node.kind === \"terminal\") {\n return [\n {\n virtualPaneId: node.id,\n command: node.command,\n cwd: node.cwd,\n env: node.env,\n focus: node.focus,\n name: node.name,\n },\n ]\n }\n\n return node.panes.flatMap((pane) => collectTerminals(pane))\n}\n\nconst determineInitialPaneId = (node: PlanNode): string => {\n if (node.kind === \"terminal\") {\n return node.id\n }\n\n let current: PlanNode = node\n while (current.kind === \"split\") {\n current = current.panes[0]!\n }\n return current.id\n}\n\nconst createPlanHash = (plan: LayoutPlan, steps: ReadonlyArray<CommandStep>): string => {\n const digest = createHash(\"sha256\")\n const normalized = {\n focusPaneId: plan.focusPaneId,\n root: plan.root,\n steps,\n }\n digest.update(JSON.stringify(normalized))\n return digest.digest(\"hex\")\n}\n","import { Command } from \"commander\"\nimport chalk from \"chalk\"\nimport { stringify as toYAML } from \"yaml\"\nimport { createRequire } from \"module\"\nimport { createPresetManager } from \"./layout/preset.ts\"\nimport type { Preset, PresetInfo } from \"./models/types\"\nimport type { CommandExecutor } from \"./types/command-executor.ts\"\nimport type { PresetManager } from \"./types/preset-manager.ts\"\nimport { createRealExecutor, createDryRunExecutor } from \"./executor/index.ts\"\nimport { executePlan } from \"./executor/plan-runner.ts\"\nimport { createLogger, LogLevel, type Logger } from \"./utils/logger.ts\"\nimport {\n runDiagnostics,\n compilePreset as defaultCompilePreset,\n createLayoutPlan as defaultCreateLayoutPlan,\n emitPlan as defaultEmitPlan,\n} from \"./core/index.ts\"\nimport type {\n DiagnosticsReport,\n DiagnosticsSeverity,\n CompilePresetInput,\n PlanEmission,\n FunctionalCoreError,\n CompilePresetSuccess,\n CreateLayoutPlanSuccess,\n} from \"./core/index.ts\"\nimport { isFunctionalCoreError } from \"./core/index.ts\"\n\nconst KNOWN_ISSUES: ReadonlyArray<string> = [\n \"LayoutEngineがtmux依存とI/Oを同一クラスで扱っている\",\n \"dry-run実行と本番適用でPlan構造が共有されていない\",\n \"Loggerが境界層とFunctional Coreの責務を混在させている\",\n]\n\nconst formatSeverityTag = (severity: DiagnosticsSeverity): string => {\n switch (severity) {\n case \"high\":\n return chalk.red(\"[HIGH]\")\n case \"medium\":\n return chalk.yellow(\"[MEDIUM]\")\n case \"low\":\n default:\n return chalk.blue(\"[LOW]\")\n }\n}\n\nexport type FunctionalCoreBridge = {\n readonly compilePreset: (input: CompilePresetInput) => ReturnType<typeof defaultCompilePreset>\n readonly createLayoutPlan: (\n input: Parameters<typeof defaultCreateLayoutPlan>[0],\n ) => ReturnType<typeof defaultCreateLayoutPlan>\n readonly emitPlan: (input: Parameters<typeof defaultEmitPlan>[0]) => ReturnType<typeof defaultEmitPlan>\n}\n\nexport type CLIOptions = {\n readonly presetManager?: PresetManager\n readonly createCommandExecutor?: (options: { verbose: boolean; dryRun: boolean }) => CommandExecutor\n readonly functionalCore?: FunctionalCoreBridge\n}\n\nexport type CLI = {\n run(args?: string[]): Promise<void>\n}\n\nexport const createCli = (options: CLIOptions = {}): CLI => {\n const presetManager = options.presetManager ?? createPresetManager()\n const createCommandExecutor =\n options.createCommandExecutor ??\n ((opts: { verbose: boolean; dryRun: boolean }): CommandExecutor => {\n if (opts.dryRun) {\n return createDryRunExecutor({ verbose: opts.verbose })\n }\n return createRealExecutor({ verbose: opts.verbose })\n })\n\n const functionalCore: FunctionalCoreBridge =\n options.functionalCore ??\n ({\n compilePreset: defaultCompilePreset,\n createLayoutPlan: defaultCreateLayoutPlan,\n emitPlan: defaultEmitPlan,\n } as const)\n\n const program = new Command()\n const require = createRequire(import.meta.url)\n const { version } = require(\"../package.json\") as { version: string }\n let logger: Logger = createLogger()\n\n const renderDiagnosticsReport = (report: DiagnosticsReport): void => {\n console.log(chalk.bold(\"\\nFunctional Core Diagnostics\\n\"))\n\n if (report.backlog.length > 0) {\n console.log(chalk.bold(\"改善バックログ\"))\n report.backlog.forEach((item, index) => {\n const prefix = `${index + 1}. ${formatSeverityTag(item.severity)}`\n console.log(`${prefix} ${item.summary}`)\n item.actions.forEach((action) => {\n console.log(` - ${action}`)\n })\n })\n console.log(\"\")\n }\n\n if (report.findings.length > 0) {\n console.log(chalk.bold(\"診断結果\"))\n report.findings.forEach((finding) => {\n console.log(`${formatSeverityTag(finding.severity)} ${finding.path} :: ${finding.description}`)\n })\n console.log(\"\")\n }\n\n if (report.nextSteps.length > 0) {\n console.log(chalk.bold(\"次のアクション\"))\n report.nextSteps.forEach((step) => {\n console.log(` - ${step}`)\n })\n console.log(\"\")\n }\n }\n\n const renderDryRun = (emission: PlanEmission): void => {\n console.log(chalk.bold(\"\\nPlanned tmux steps (dry-run)\"))\n emission.steps.forEach((step, index) => {\n const commandString = step.command.join(\" \")\n console.log(` ${index + 1}. ${step.summary}: tmux ${commandString}`)\n })\n }\n\n const buildPresetDocument = (preset: Preset, presetName?: string): string => {\n const document: Record<string, unknown> = {\n name: preset.name ?? presetName ?? \"vde-layout\",\n command: preset.command,\n layout: preset.layout,\n }\n\n if (typeof preset.command !== \"string\" || preset.command.length === 0) {\n delete document.command\n }\n\n if (preset.layout === undefined || preset.layout === null) {\n delete document.layout\n }\n\n return toYAML(document)\n }\n\n const buildPresetSource = (presetName?: string): string => {\n return typeof presetName === \"string\" && presetName.length > 0 ? `preset://${presetName}` : \"preset://default\"\n }\n\n const handleFunctionalError = (error: FunctionalCoreError): never => {\n const header = [`[${error.kind}]`, `[${error.code}]`]\n if (typeof error.path === \"string\" && error.path.length > 0) {\n header.push(`[${error.path}]`)\n }\n\n const lines = [`${header.join(\" \")} ${error.message}`.trim()]\n\n if (typeof error.source === \"string\" && error.source.length > 0) {\n lines.push(`source: ${error.source}`)\n }\n\n const commandDetail = error.details?.command\n if (Array.isArray(commandDetail)) {\n const tmuxCommand = commandDetail.filter((segment): segment is string => typeof segment === \"string\")\n if (tmuxCommand.length > 0) {\n lines.push(`command: tmux ${tmuxCommand.join(\" \")}`)\n }\n } else if (typeof commandDetail === \"string\" && commandDetail.length > 0) {\n lines.push(`command: ${commandDetail}`)\n }\n\n const stderrDetail = error.details?.stderr\n if (typeof stderrDetail === \"string\" && stderrDetail.length > 0) {\n lines.push(`stderr: ${stderrDetail}`)\n } else if (stderrDetail !== undefined) {\n lines.push(`stderr: ${String(stderrDetail)}`)\n }\n\n logger.error(lines.join(\"\\n\"))\n process.exit(1)\n }\n\n const handleError = (error: unknown): never => {\n if (error instanceof Error) {\n logger.error(error.message, error)\n } else {\n logger.error(\"An unexpected error occurred\")\n }\n\n process.exit(1)\n }\n\n const handlePipelineFailure = (error: unknown): never => {\n if (isFunctionalCoreError(error)) {\n return handleFunctionalError(error)\n }\n return handleError(error)\n }\n\n const listPresets = async (): Promise<never> => {\n try {\n await presetManager.loadConfig()\n const presets = presetManager.listPresets()\n\n if (presets.length === 0) {\n logger.warn(\"No presets defined\")\n process.exit(0)\n }\n\n console.log(chalk.bold(\"Available presets:\\n\"))\n\n const maxKeyLength = Math.max(...presets.map((p) => p.key.length))\n\n presets.forEach((preset: PresetInfo) => {\n const paddedKey = preset.key.padEnd(maxKeyLength + 2)\n const description = preset.description ?? \"\"\n console.log(` ${chalk.cyan(paddedKey)} ${description}`)\n })\n\n process.exit(0)\n } catch (error) {\n return handleError(error)\n }\n }\n\n const diagnosePreset = async (presetName: string | undefined): Promise<never> => {\n try {\n await presetManager.loadConfig()\n const preset =\n typeof presetName === \"string\" && presetName.length > 0\n ? presetManager.getPreset(presetName)\n : presetManager.getDefaultPreset()\n\n const presetDocument = toYAML(preset ?? {})\n const report = runDiagnostics({\n presetDocument,\n knownIssues: KNOWN_ISSUES,\n })\n\n renderDiagnosticsReport(report)\n process.exit(0)\n } catch (error) {\n return handleError(error)\n }\n }\n\n const executePreset = async (\n presetName: string | undefined,\n options: { verbose: boolean; dryRun: boolean },\n ): Promise<never> => {\n try {\n await presetManager.loadConfig()\n\n const preset =\n typeof presetName === \"string\" && presetName.length > 0\n ? presetManager.getPreset(presetName)\n : presetManager.getDefaultPreset()\n\n const tmuxEnv = process.env.TMUX\n const insideTmux = typeof tmuxEnv === \"string\" && tmuxEnv.length > 0\n if (!insideTmux && options.dryRun !== true) {\n throw new Error(\"Must be run inside a tmux session\")\n }\n\n const executor = createCommandExecutor({\n verbose: options.verbose,\n dryRun: options.dryRun,\n })\n\n if (options.dryRun === true) {\n console.log(\"[DRY RUN] No actual commands will be executed\")\n }\n\n let compileResult: CompilePresetSuccess\n let planResult: CreateLayoutPlanSuccess\n let emission: PlanEmission\n\n try {\n compileResult = functionalCore.compilePreset({\n document: buildPresetDocument(preset, presetName),\n source: buildPresetSource(presetName),\n })\n planResult = functionalCore.createLayoutPlan({ preset: compileResult.preset })\n emission = functionalCore.emitPlan({ plan: planResult.plan })\n } catch (error) {\n return handlePipelineFailure(error)\n }\n\n if (options.dryRun === true) {\n renderDryRun(emission)\n } else {\n try {\n const executionResult = await executePlan({\n emission,\n executor,\n windowName: preset.name ?? presetName ?? \"vde-layout\",\n })\n logger.info(`Executed ${executionResult.executedSteps} tmux steps`)\n } catch (error) {\n return handlePipelineFailure(error)\n }\n }\n\n logger.success(`✓ Applied preset \"${preset.name}\"`)\n process.exit(0)\n } catch (error) {\n return handleError(error)\n }\n }\n\n const setupProgram = (): void => {\n program\n .name(\"vde-layout\")\n .description(\"VDE (Vibrant Development Environment) Layout Manager - tmux pane layout management tool\")\n .version(version, \"-V, --version\", \"Show version\")\n .helpOption(\"-h, --help\", \"Show help\")\n\n program.option(\"-v, --verbose\", \"Show detailed logs\", false)\n program.option(\"--dry-run\", \"Display commands without executing\", false)\n program.option(\"--config <path>\", \"Path to configuration file\")\n\n program\n .command(\"list\")\n .description(\"List available presets\")\n .action(async () => {\n await listPresets()\n })\n\n program\n .command(\"diagnose\")\n .description(\"Functional Coreリライトに向けた診断レポートを表示する\")\n .argument(\"[preset]\", 'Preset name (defaults to \"default\" preset when omitted)')\n .action(async (presetName?: string) => {\n await diagnosePreset(presetName)\n })\n\n program\n .argument(\"[preset]\", 'Preset name (defaults to \"default\" preset when omitted)')\n .action(async (presetName?: string) => {\n const opts = program.opts<{ verbose?: boolean; dryRun?: boolean }>()\n await executePreset(presetName, {\n verbose: opts.verbose === true,\n dryRun: opts.dryRun === true,\n })\n })\n }\n\n setupProgram()\n\n const run = async (args: string[] = process.argv.slice(2)): Promise<void> => {\n const requestedVersion = args.includes(\"--version\") || args.includes(\"-V\")\n const requestedHelp = args.includes(\"--help\") || args.includes(\"-h\")\n try {\n await program.parseAsync(args, { from: \"user\" })\n const opts = program.opts<{ verbose?: boolean; config?: string }>()\n\n if (requestedVersion || requestedHelp) {\n return\n }\n\n if (opts.verbose === true) {\n logger = createLogger({ level: LogLevel.INFO })\n } else {\n logger = createLogger()\n }\n\n if (\n typeof opts.config === \"string\" &&\n opts.config.length > 0 &&\n typeof presetManager.setConfigPath === \"function\"\n ) {\n presetManager.setConfigPath(opts.config)\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Process exited\")) {\n throw error\n }\n handleError(error)\n }\n }\n\n return { run }\n}\n","#!/usr/bin/env node\nimport { createCli } from \"./cli.ts\"\n\n/**\n * Main entry point\n * Launches the CLI application\n */\nconst main = async (): Promise<void> => {\n const cli = createCli()\n try {\n // Pass arguments excluding the first two elements (node, script path) from process.argv\n await cli.run(process.argv.slice(2))\n } catch (error) {\n // Format and display error message appropriately\n if (error instanceof Error) {\n console.error(\"Error:\", error.message)\n\n // Also display stack trace in debug mode\n if (process.env.VDE_DEBUG === \"true\") {\n console.error(error.stack)\n }\n } else {\n console.error(\"An unexpected error occurred:\", String(error))\n }\n\n process.exit(1)\n }\n}\n\n// Execute immediately\nvoid main()\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vde-layout",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Terminal multiplexer layout management tool for VDE (Vibe Coding Development Environment)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsdown",
|
|
21
21
|
"clean": "rm -rf dist",
|
|
22
|
-
"compile": "tsdown",
|
|
23
22
|
"dev": "tsdown --watch",
|
|
24
23
|
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
25
24
|
"test": "bun run build && vitest run",
|