@prover-coder-ai/docker-git 1.0.8 → 1.0.10

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/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sources":["../../lib/dist/core/clone.js","../../lib/dist/core/strings.js","../../lib/dist/core/repo.js","../../lib/dist/core/domain.js","../../lib/dist/core/parse-errors.js","../../lib/dist/shell/command-runner.js","../../lib/dist/shell/errors.js","../../lib/dist/shell/clone.js","../../lib/dist/shell/paths.js","../../lib/dist/shell/config.js","../../lib/dist/shell/docker.js","../../lib/dist/usecases/env-file.js","../../lib/dist/usecases/path-helpers.js","../../lib/dist/usecases/runtime.js","../../lib/dist/usecases/menu-helpers.js","../../lib/dist/usecases/state-repo/git-commands.js","../../lib/dist/usecases/state-repo/github-auth.js","../../lib/dist/usecases/docker-git-config-search.js","../../lib/dist/usecases/state-repo.js","../../lib/dist/usecases/errors.js","../../lib/dist/usecases/projects-core.js","../../lib/dist/usecases/projects-down.js","../../lib/dist/usecases/projects-list.js","../../lib/dist/usecases/projects-ssh.js","../../lib/dist/usecases/actions/docker-up.js","../src/app/program.ts","../src/app/main.ts"],"sourcesContent":["const emptyRequest = { _tag: \"None\" };\nconst toCloneRequest = (args) => ({\n _tag: \"Clone\",\n args\n});\n// CHANGE: resolve a clone request from argv + npm lifecycle metadata\n// WHY: support pnpm run clone <url> without requiring \"--\"\n// QUOTE(ТЗ): \"pnpm run clone <url>\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall a,e: resolve(a,e) -> deterministic\n// PURITY: CORE\n// EFFECT: Effect<CloneRequest, never, never>\n// INVARIANT: clone requested only when argv[0] == \"clone\" or npmLifecycleEvent == \"clone\"\n// COMPLEXITY: O(n)\nexport const resolveCloneRequest = (argv, npmLifecycleEvent) => {\n if (npmLifecycleEvent === \"clone\") {\n if (argv.length > 0) {\n const [first, ...rest] = argv;\n return first === \"clone\" ? toCloneRequest(rest) : toCloneRequest(argv);\n }\n return toCloneRequest([]);\n }\n if (argv.length > 0 && argv[0] === \"clone\") {\n return toCloneRequest(argv.slice(1));\n }\n return emptyRequest;\n};\n","export const trimLeftChar = (value, char) => {\n let start = 0;\n while (start < value.length && value[start] === char) {\n start += 1;\n }\n return value.slice(start);\n};\nexport const trimRightChar = (value, char) => {\n let end = value.length;\n while (end > 0 && value[end - 1] === char) {\n end -= 1;\n }\n return value.slice(0, end);\n};\n","import { trimLeftChar, trimRightChar } from \"./strings.js\";\nconst slugify = (value) => {\n const normalized = value\n .trim()\n .toLowerCase()\n .replaceAll(/[^a-z0-9_-]+/g, \"-\")\n .replaceAll(/-+/g, \"-\");\n const withoutLeading = trimLeftChar(normalized, \"-\");\n const cleaned = trimRightChar(withoutLeading, \"-\");\n return cleaned.length > 0 ? cleaned : \"app\";\n};\n// CHANGE: derive a stable repo slug from a repo URL\n// WHY: generate deterministic container/service names per repository\n// QUOTE(ТЗ): \"по факту он должен создавтаь постоянно новый контейнер для нового репозитория\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall url: slug(url) = s -> deterministic(s)\n// PURITY: CORE\n// EFFECT: Effect<string, never, never>\n// INVARIANT: slug is lowercase and non-empty\n// COMPLEXITY: O(n) where n = |url|\nexport const deriveRepoSlug = (repoUrl) => {\n const trimmed = trimRightChar(repoUrl.trim(), \"/\");\n if (trimmed.length === 0) {\n return \"app\";\n }\n const lastSlash = trimmed.lastIndexOf(\"/\");\n const lastColon = trimmed.lastIndexOf(\":\");\n const pivot = Math.max(lastSlash, lastColon);\n const segment = pivot >= 0 ? trimmed.slice(pivot + 1) : trimmed;\n const withoutGit = segment.endsWith(\".git\") ? segment.slice(0, -4) : segment;\n return slugify(withoutGit);\n};\nconst stripGitSuffix = (segment) => segment.endsWith(\".git\") ? segment.slice(0, -4) : segment;\nconst normalizePathParts = (pathPart) => {\n const cleaned = trimLeftChar(pathPart, \"/\");\n if (cleaned.length === 0) {\n return [];\n }\n const rawParts = cleaned.split(\"/\").filter(Boolean);\n return rawParts.map((part, index) => index === rawParts.length - 1 ? stripGitSuffix(part) : part);\n};\nconst extractFromScheme = (trimmed) => {\n const schemeIndex = trimmed.indexOf(\"://\");\n if (schemeIndex === -1) {\n return null;\n }\n const afterScheme = trimmed.slice(schemeIndex + 3);\n const firstSlash = afterScheme.indexOf(\"/\");\n if (firstSlash === -1) {\n return [];\n }\n return normalizePathParts(afterScheme.slice(firstSlash + 1));\n};\nconst extractFromColon = (trimmed) => {\n const colonIndex = trimmed.indexOf(\":\");\n if (colonIndex === -1) {\n return null;\n }\n return normalizePathParts(trimmed.slice(colonIndex + 1));\n};\nconst extractFromSlash = (trimmed) => {\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex === -1) {\n return null;\n }\n return normalizePathParts(trimmed.slice(slashIndex + 1));\n};\nconst extractRepoPathParts = (repoUrl) => {\n const trimmed = trimRightChar(repoUrl.trim(), \"/\");\n if (trimmed.length === 0) {\n return [];\n }\n const fromScheme = extractFromScheme(trimmed);\n if (fromScheme !== null) {\n return fromScheme;\n }\n const fromColon = extractFromColon(trimmed);\n if (fromColon !== null) {\n return fromColon;\n }\n const fromSlash = extractFromSlash(trimmed);\n if (fromSlash !== null) {\n return fromSlash;\n }\n return [stripGitSuffix(trimmed)];\n};\nconst normalizeRepoSegment = (segment, fallback) => {\n const normalized = slugify(segment);\n return normalized.length > 0 ? normalized : fallback;\n};\n// CHANGE: derive stable owner/repo path parts from a repo URL\n// WHY: avoid collisions when orgs have identical repo names\n// QUOTE(ТЗ): \"пути учитывают организацию в которой это лежит\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall url: parts(url) -> deterministic(parts)\n// PURITY: CORE\n// EFFECT: Effect<RepoPathParts, never, never>\n// INVARIANT: path parts are slugified and non-empty\n// COMPLEXITY: O(n) where n = |url|\nexport const deriveRepoPathParts = (repoUrl) => {\n const repoSlug = deriveRepoSlug(repoUrl);\n const rawParts = extractRepoPathParts(repoUrl);\n if (rawParts.length === 0) {\n return { ownerParts: [], repo: repoSlug, pathParts: [repoSlug] };\n }\n const rawRepo = rawParts.at(-1) ?? repoSlug;\n const repo = normalizeRepoSegment(rawRepo, repoSlug);\n const ownerParts = rawParts\n .slice(0, -1)\n .map((part) => normalizeRepoSegment(part, \"org\"))\n .filter((part) => part.length > 0);\n const pathParts = ownerParts.length > 0 ? [...ownerParts, repo] : [repo];\n return { ownerParts, repo, pathParts };\n};\nconst stripQueryHash = (value) => {\n const queryIndex = value.indexOf(\"?\");\n const hashIndex = value.indexOf(\"#\");\n const indices = [queryIndex, hashIndex].filter((index) => index >= 0);\n if (indices.length === 0) {\n return value;\n }\n const cutIndex = Math.min(...indices);\n return value.slice(0, cutIndex);\n};\nconst splitGithubPath = (input) => {\n const trimmed = input.trim();\n const httpsPrefix = \"https://github.com/\";\n const sshPrefix = \"ssh://git@github.com/\";\n const gitPrefix = \"git@github.com:\";\n let rest = null;\n if (trimmed.startsWith(httpsPrefix)) {\n rest = trimmed.slice(httpsPrefix.length);\n }\n else if (trimmed.startsWith(sshPrefix)) {\n rest = trimmed.slice(sshPrefix.length);\n }\n else if (trimmed.startsWith(gitPrefix)) {\n rest = trimmed.slice(gitPrefix.length);\n }\n if (rest === null) {\n return null;\n }\n const cleaned = trimRightChar(stripQueryHash(rest), \"/\");\n if (cleaned.length === 0) {\n return [];\n }\n return cleaned.split(\"/\").filter((part) => part.length > 0);\n};\n// CHANGE: parse GitHub owner/repo from common URL formats\n// WHY: enable auto-fork logic without relying on slugified paths\n// QUOTE(ТЗ): \"Сразу на issues и он бы делал форк репы если это надо\"\n// REF: user-request-2026-02-05-issues-fork\n// SOURCE: n/a\n// FORMAT THEOREM: ∀u: github(u) → repo(u) = {owner, repo}\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: returns null for non-GitHub inputs\n// COMPLEXITY: O(n) where n = |input|\nexport const parseGithubRepoUrl = (input) => {\n const parts = splitGithubPath(input);\n if (!parts || parts.length < 2) {\n return null;\n }\n const owner = parts[0]?.trim();\n const repoRaw = parts[1]?.trim();\n if (!owner || !repoRaw) {\n return null;\n }\n const repo = stripGitSuffix(repoRaw);\n return { owner, repo };\n};\nconst readGithubPart = (value) => {\n const trimmed = value?.trim() ?? \"\";\n return trimmed.length > 0 ? trimmed : null;\n};\nconst parseGithubRefParts = (input) => {\n const parts = splitGithubPath(input);\n if (!parts || parts.length < 4) {\n return null;\n }\n const owner = readGithubPart(parts[0]);\n const repoRaw = readGithubPart(parts[1]);\n const markerRaw = readGithubPart(parts[2]);\n const ref = readGithubPart(parts[3]);\n if (!owner || !repoRaw || !markerRaw || !ref) {\n return null;\n }\n return { owner, repoRaw, marker: markerRaw.toLowerCase(), ref };\n};\nconst parseGithubPrUrl = (input) => {\n const parsed = parseGithubRefParts(input);\n if (!parsed || parsed.marker !== \"pull\") {\n return null;\n }\n const repo = stripGitSuffix(parsed.repoRaw);\n const workspaceSuffix = `pr-${slugify(parsed.ref)}`;\n return {\n repoUrl: `https://github.com/${parsed.owner}/${repo}.git`,\n repoRef: `refs/pull/${parsed.ref}/head`,\n workspaceSuffix\n };\n};\n// CHANGE: normalize GitHub tree/blob URLs into repo + ref\n// WHY: allow docker-git clone to accept branch URLs like /tree/<branch>\n// QUOTE(ТЗ): \"вызови --force на https://github.com/agiens/crm/tree/vova-fork\"\n// REF: user-request-2026-02-10-github-tree-url\n// SOURCE: n/a\n// FORMAT THEOREM: ∀u: tree(u) → repo(u)=git(u) ∧ ref(u)=branch(u)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: ignores additional path segments after the ref\n// COMPLEXITY: O(n) where n = |url|\nconst parseGithubTreeUrl = (input) => {\n const parsed = parseGithubRefParts(input);\n if (!parsed || (parsed.marker !== \"tree\" && parsed.marker !== \"blob\")) {\n return null;\n }\n const repo = stripGitSuffix(parsed.repoRaw);\n return { repoUrl: `https://github.com/${parsed.owner}/${repo}.git`, repoRef: parsed.ref };\n};\n// CHANGE: normalize GitHub issue URLs into repo URLs\n// WHY: allow docker-git clone to accept issue links directly\n// QUOTE(ТЗ): \"Сразу на issues\"\n// REF: user-request-2026-02-05-issues\n// SOURCE: n/a\n// FORMAT THEOREM: ∀u: issue(u) → repo(u)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: issue URL yields repoUrl + deterministic issue branch\n// COMPLEXITY: O(n) where n = |url|\nconst parseGithubIssueUrl = (input) => {\n const parsed = parseGithubRefParts(input);\n if (!parsed || parsed.marker !== \"issues\") {\n return null;\n }\n const repo = stripGitSuffix(parsed.repoRaw);\n const workspaceSuffix = `issue-${slugify(parsed.ref)}`;\n return {\n repoUrl: `https://github.com/${parsed.owner}/${repo}.git`,\n repoRef: workspaceSuffix,\n workspaceSuffix\n };\n};\n// CHANGE: normalize repo input and PR/issue URLs into repo + ref\n// WHY: allow cloning GitHub PR links and issue links directly\n// QUOTE(ТЗ): \"клонировть по cсылке на PR\" | \"Сразу на issues\"\n// REF: user-request-2026-01-28-pr | user-request-2026-02-05-issues\n// SOURCE: n/a\n// FORMAT THEOREM: forall url: resolve(url) -> deterministic(url, ref)\n// PURITY: CORE\n// EFFECT: Effect<ResolvedRepoInput, never, never>\n// INVARIANT: PR URL yields repoUrl + refs/pull/<id>/head\n// COMPLEXITY: O(n) where n = |url|\nexport const resolveRepoInput = (repoUrl) => parseGithubPrUrl(repoUrl)\n ?? parseGithubTreeUrl(repoUrl)\n ?? parseGithubIssueUrl(repoUrl)\n ?? { repoUrl: repoUrl.trim() };\n","export { parseMenuSelection } from \"./menu.js\";\nexport { deriveRepoPathParts, deriveRepoSlug, resolveRepoInput } from \"./repo.js\";\nexport const defaultTemplateConfig = {\n containerName: \"dev-ssh\",\n serviceName: \"dev\",\n sshUser: \"dev\",\n sshPort: 2222,\n repoRef: \"main\",\n targetDir: \"/home/dev/app\",\n volumeName: \"dev_home\",\n authorizedKeysPath: \"./.docker-git/authorized_keys\",\n envGlobalPath: \"./.docker-git/.orch/env/global.env\",\n envProjectPath: \"./.orch/env/project.env\",\n codexAuthPath: \"./.docker-git/.orch/auth/codex\",\n codexSharedAuthPath: \"./.docker-git/.orch/auth/codex\",\n codexHome: \"/home/dev/.codex\",\n enableMcpPlaywright: false,\n pnpmVersion: \"10.27.0\"\n};\n","import { Match } from \"effect\";\n// CHANGE: normalize parse errors into deterministic messages\n// WHY: reuse parse error formatting across CLI and server flows\n// QUOTE(ТЗ): \"ошибки должны быть описывающими\"\n// REF: user-request-2026-02-02-cli-split\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: format(e) = s -> deterministic(s)\n// PURITY: CORE\n// EFFECT: Effect<string, never, never>\n// INVARIANT: each ParseError maps to exactly one message\n// COMPLEXITY: O(1)\nexport const formatParseError = (error) => Match.value(error).pipe(Match.when({ _tag: \"UnknownCommand\" }, ({ command }) => `Unknown command: ${command}`), Match.when({ _tag: \"UnknownOption\" }, ({ option }) => `Unknown option: ${option}`), Match.when({ _tag: \"MissingOptionValue\" }, ({ option }) => `Missing value for option: ${option}`), Match.when({ _tag: \"MissingRequiredOption\" }, ({ option }) => `Missing required option: ${option}`), Match.when({ _tag: \"InvalidOption\" }, ({ option, reason }) => `Invalid option ${option}: ${reason}`), Match.when({ _tag: \"UnexpectedArgument\" }, ({ value }) => `Unexpected argument: ${value}`), Match.exhaustive);\n","import * as Command from \"@effect/platform/Command\";\nimport * as CommandExecutor from \"@effect/platform/CommandExecutor\";\nimport { Effect, pipe } from \"effect\";\nimport * as Chunk from \"effect/Chunk\";\nimport * as Stream from \"effect/Stream\";\nconst buildCommand = (spec, stdout, stderr, stdin = \"pipe\") => pipe(Command.make(spec.command, ...spec.args), Command.workingDirectory(spec.cwd), spec.env ? Command.env(spec.env) : (value) => value, Command.stdin(stdin), Command.stdout(stdout), Command.stderr(stderr));\nconst ensureExitCode = (exitCode, okExitCodes, onFailure) => okExitCodes.includes(exitCode)\n ? Effect.succeed(exitCode)\n : Effect.fail(onFailure(exitCode));\nexport const runCommandWithExitCodes = (spec, okExitCodes, onFailure) => Effect.gen(function* (_) {\n const exitCode = yield* _(Command.exitCode(buildCommand(spec, \"inherit\", \"inherit\", \"inherit\")));\n const numericExitCode = Number(exitCode);\n yield* _(ensureExitCode(numericExitCode, okExitCodes, onFailure));\n});\n// CHANGE: run a command and return the exit code\n// WHY: enable status checks without throwing on non-zero exits\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall cmd: exitCode(cmd) = n\n// PURITY: SHELL\n// EFFECT: Effect<number, PlatformError, CommandExecutor>\n// INVARIANT: stdout/stderr are suppressed for status checks\n// COMPLEXITY: O(command)\nexport const runCommandExitCode = (spec) => Effect.map(Command.exitCode(buildCommand(spec, \"pipe\", \"pipe\", \"inherit\")), Number);\nconst collectUint8Array = (chunks) => Chunk.reduce(chunks, new Uint8Array(), (acc, curr) => {\n const next = new Uint8Array(acc.length + curr.length);\n next.set(acc);\n next.set(curr, acc.length);\n return next;\n});\n// CHANGE: run a command and capture stdout\n// WHY: allow auth flows to retrieve tokens from CLI tools\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall cmd: capture(cmd) -> stdout(cmd)\n// PURITY: SHELL\n// EFFECT: Effect<string, E | PlatformError, CommandExecutor>\n// INVARIANT: stderr is captured but ignored for output\n// COMPLEXITY: O(command)\nexport const runCommandCapture = (spec, okExitCodes, onFailure) => Effect.scoped(Effect.gen(function* (_) {\n const executor = yield* _(CommandExecutor.CommandExecutor);\n const process = yield* _(executor.start(buildCommand(spec, \"pipe\", \"pipe\", \"pipe\")));\n const bytes = yield* _(pipe(process.stdout, Stream.runCollect, Effect.map((chunks) => collectUint8Array(chunks))));\n const exitCode = yield* _(process.exitCode);\n yield* _(ensureExitCode(Number(exitCode), okExitCodes, onFailure));\n return new TextDecoder(\"utf-8\").decode(bytes);\n}));\n","import { Data } from \"effect\";\nexport class FileExistsError extends Data.TaggedError(\"FileExistsError\") {\n}\nexport class ConfigNotFoundError extends Data.TaggedError(\"ConfigNotFoundError\") {\n}\nexport class ConfigDecodeError extends Data.TaggedError(\"ConfigDecodeError\") {\n}\nexport class InputCancelledError extends Data.TaggedError(\"InputCancelledError\") {\n}\nexport class InputReadError extends Data.TaggedError(\"InputReadError\") {\n}\nexport class DockerCommandError extends Data.TaggedError(\"DockerCommandError\") {\n}\nexport class DockerAccessError extends Data.TaggedError(\"DockerAccessError\") {\n}\nexport class CloneFailedError extends Data.TaggedError(\"CloneFailedError\") {\n}\nexport class PortProbeError extends Data.TaggedError(\"PortProbeError\") {\n}\nexport class CommandFailedError extends Data.TaggedError(\"CommandFailedError\") {\n}\nexport class AuthError extends Data.TaggedError(\"AuthError\") {\n}\n","import { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\nimport { resolveCloneRequest } from \"../core/clone.js\";\nimport { runCommandWithExitCodes } from \"./command-runner.js\";\nimport { CommandFailedError } from \"./errors.js\";\nconst successExitCode = Number(ExitCode(0));\n// CHANGE: read clone request from process argv and npm lifecycle metadata\n// WHY: allow pnpm run clone <url> to work without \"--\"\n// QUOTE(ТЗ): \"pnpm run clone <url>\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall env: read(env) -> deterministic(request)\n// PURITY: SHELL\n// EFFECT: Effect<CloneRequest, never, never>\n// INVARIANT: only argv/env are read\n// COMPLEXITY: O(n)\nexport const readCloneRequest = Effect.sync(() => resolveCloneRequest(process.argv.slice(2), process.env[\"npm_lifecycle_event\"]));\n// CHANGE: run docker-git clone by building and invoking its CLI\n// WHY: reuse docker-git without mutating its codebase\n// QUOTE(ТЗ): \"docker git мы никак не изменяем\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall args: build && run(args) -> docker_git_invoked(args)\n// PURITY: SHELL\n// EFFECT: Effect<void, CommandFailedError | PlatformError, CommandExecutor | Path>\n// INVARIANT: build runs before clone command\n// COMPLEXITY: O(build + clone)\nexport const runDockerGitClone = (args) => Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const workspaceRoot = process.cwd();\n const appRoot = path.join(workspaceRoot, \"packages\", \"app\");\n const dockerGitCli = path.join(appRoot, \"dist\", \"src\", \"docker-git\", \"main.js\");\n const buildLabel = `pnpm -C ${appRoot} build:docker-git`;\n const cloneLabel = `node ${dockerGitCli} clone`;\n yield* _(runCommandWithExitCodes({ cwd: workspaceRoot, command: \"pnpm\", args: [\"-C\", appRoot, \"build:docker-git\"] }, [successExitCode], (exitCode) => new CommandFailedError({ command: buildLabel, exitCode })));\n yield* _(runCommandWithExitCodes({ cwd: workspaceRoot, command: \"node\", args: [dockerGitCli, \"clone\", ...args] }, [successExitCode], (exitCode) => new CommandFailedError({ command: cloneLabel, exitCode })));\n});\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\nexport const resolveBaseDir = (baseDir) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const resolved = path.resolve(baseDir);\n return { fs, path, resolved };\n});\n","import * as ParseResult from \"@effect/schema/ParseResult\";\nimport * as Schema from \"@effect/schema/Schema\";\nimport * as TreeFormatter from \"@effect/schema/TreeFormatter\";\nimport { Effect, Either } from \"effect\";\nimport { defaultTemplateConfig } from \"../core/domain.js\";\nimport { ConfigDecodeError, ConfigNotFoundError } from \"./errors.js\";\nimport { resolveBaseDir } from \"./paths.js\";\nconst TemplateConfigSchema = Schema.Struct({\n containerName: Schema.String,\n serviceName: Schema.String,\n sshUser: Schema.String,\n sshPort: Schema.Number.pipe(Schema.int()),\n repoUrl: Schema.String,\n repoRef: Schema.String,\n targetDir: Schema.String,\n volumeName: Schema.String,\n authorizedKeysPath: Schema.String,\n envGlobalPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.envGlobalPath\n }),\n envProjectPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.envProjectPath\n }),\n codexAuthPath: Schema.String,\n codexSharedAuthPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.codexSharedAuthPath\n }),\n codexHome: Schema.String,\n enableMcpPlaywright: Schema.optionalWith(Schema.Boolean, {\n default: () => defaultTemplateConfig.enableMcpPlaywright\n }),\n pnpmVersion: Schema.String\n});\nconst ProjectConfigSchema = Schema.Struct({\n schemaVersion: Schema.Literal(1),\n template: TemplateConfigSchema\n});\nconst ProjectConfigJsonSchema = Schema.parseJson(ProjectConfigSchema);\nconst decodeProjectConfig = (path, input) => Either.match(ParseResult.decodeUnknownEither(ProjectConfigJsonSchema)(input), {\n onLeft: (issue) => Effect.fail(new ConfigDecodeError({\n path,\n message: TreeFormatter.formatIssueSync(issue)\n })),\n onRight: (value) => Effect.succeed(value)\n});\n// CHANGE: read and decode docker-git.json from disk\n// WHY: keep unknown inputs at the boundary and validate with schema\n// QUOTE(ТЗ): \"интерфейс в котором можно авторизировать все что мы хотим иметь\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: decode(read(p)) = cfg -> cfg.schemaVersion = 1\n// PURITY: SHELL\n// EFFECT: Effect<ProjectConfig, ConfigNotFoundError | ConfigDecodeError | PlatformError, FileSystem | Path>\n// INVARIANT: unknown input never leaks past this boundary\n// COMPLEXITY: O(n) where n = |file|\nexport const readProjectConfig = (baseDir) => Effect.gen(function* (_) {\n const { fs, path, resolved } = yield* _(resolveBaseDir(baseDir));\n const configPath = path.join(resolved, \"docker-git.json\");\n const exists = yield* _(fs.exists(configPath));\n if (!exists) {\n return yield* _(Effect.fail(new ConfigNotFoundError({ path: configPath })));\n }\n const contents = yield* _(fs.readFileString(configPath));\n return yield* _(decodeProjectConfig(configPath, contents));\n});\n","import * as Command from \"@effect/platform/Command\";\nimport * as CommandExecutor from \"@effect/platform/CommandExecutor\";\nimport { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport { Effect, pipe } from \"effect\";\nimport * as Chunk from \"effect/Chunk\";\nimport * as Stream from \"effect/Stream\";\nimport { runCommandCapture, runCommandWithExitCodes } from \"./command-runner.js\";\nimport { CommandFailedError, DockerAccessError, DockerCommandError } from \"./errors.js\";\nconst composeSpec = (cwd, args) => ({\n cwd,\n command: \"docker\",\n args: [\"compose\", \"--ansi\", \"never\", \"--progress\", \"plain\", ...args]\n});\nconst parseInspectNetworkEntry = (line) => {\n const idx = line.indexOf(\"=\");\n if (idx <= 0) {\n return [];\n }\n const network = line.slice(0, idx).trim();\n const ip = line.slice(idx + 1).trim();\n if (network.length === 0 || ip.length === 0) {\n return [];\n }\n const entry = [network, ip];\n return [entry];\n};\nconst collectUint8Array = (chunks) => Chunk.reduce(chunks, new Uint8Array(), (acc, curr) => {\n const next = new Uint8Array(acc.length + curr.length);\n next.set(acc);\n next.set(curr, acc.length);\n return next;\n});\nconst permissionDeniedPattern = /permission denied/i;\n// CHANGE: classify docker daemon access failure into deterministic typed reasons\n// WHY: allow callers to render actionable recovery guidance for socket permission issues\n// QUOTE(ТЗ): \"docker-git handles Docker socket permission problems predictably\"\n// REF: issue-11\n// SOURCE: n/a\n// FORMAT THEOREM: ∀m: classify(m) ∈ {\"PermissionDenied\",\"DaemonUnavailable\"}\n// PURITY: CORE\n// EFFECT: Effect<DockerAccessIssue, never, never>\n// INVARIANT: classification is stable for equal input\n// COMPLEXITY: O(|m|)\nexport const classifyDockerAccessIssue = (message) => permissionDeniedPattern.test(message) ? \"PermissionDenied\" : \"DaemonUnavailable\";\n// CHANGE: verify docker daemon access before compose/auth flows\n// WHY: fail fast on socket permission errors instead of cascading into opaque command failures\n// QUOTE(ТЗ): \"permission denied to /var/run/docker.sock\"\n// REF: issue-11\n// SOURCE: n/a\n// FORMAT THEOREM: ∀cwd: access(cwd)=ok ∨ DockerAccessError\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerAccessError | PlatformError, CommandExecutor>\n// INVARIANT: non-zero docker info exit always maps to DockerAccessError\n// COMPLEXITY: O(command)\nexport const ensureDockerDaemonAccess = (cwd) => Effect.scoped(Effect.gen(function* (_) {\n const executor = yield* _(CommandExecutor.CommandExecutor);\n const process = yield* _(executor.start(pipe(Command.make(\"docker\", \"info\"), Command.workingDirectory(cwd), Command.stdin(\"pipe\"), Command.stdout(\"pipe\"), Command.stderr(\"pipe\"))));\n const stderrBytes = yield* _(pipe(process.stderr, Stream.runCollect, Effect.map((chunks) => collectUint8Array(chunks))));\n const exitCode = Number(yield* _(process.exitCode));\n if (exitCode === 0) {\n return;\n }\n const stderr = new TextDecoder(\"utf-8\").decode(stderrBytes).trim();\n const details = stderr.length > 0 ? stderr : `docker info failed with exit code ${exitCode}`;\n return yield* _(Effect.fail(new DockerAccessError({\n issue: classifyDockerAccessIssue(details),\n details\n })));\n}));\nconst runCompose = (cwd, args, okExitCodes) => runCommandWithExitCodes(composeSpec(cwd, args), okExitCodes, (exitCode) => new DockerCommandError({ exitCode }));\nconst runComposeCapture = (cwd, args, okExitCodes) => runCommandCapture(composeSpec(cwd, args), okExitCodes, (exitCode) => new DockerCommandError({ exitCode }));\n// CHANGE: run docker compose up -d --build in the target directory\n// WHY: provide a controlled shell effect for image creation\n// QUOTE(ТЗ): \"создавать докер образы\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) = 0 -> image_built(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeUp = (cwd) => runCompose(cwd, [\"up\", \"-d\", \"--build\"], [Number(ExitCode(0))]);\nexport const dockerComposeUpRecreateArgs = [\n \"up\",\n \"-d\",\n \"--build\",\n \"--force-recreate\"\n];\n// CHANGE: recreate running containers and refresh images when needed\n// WHY: apply env/template updates while preserving workspace volumes\n// QUOTE(ТЗ): \"сбросит только окружение\"\n// REF: user-request-2026-02-11-force-env\n// SOURCE: n/a\n// FORMAT THEOREM: ∀dir: up_force_recreate(dir) → recreated(containers(dir)) ∧ preserved(volumes(dir)) ∧ updated(images(dir))\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: may rebuild images but does not remove volumes\n// COMPLEXITY: O(command)\nexport const runDockerComposeUpRecreate = (cwd) => runCompose(cwd, dockerComposeUpRecreateArgs, [Number(ExitCode(0))]);\n// CHANGE: run docker compose down in the target directory\n// WHY: allow stopping managed containers from the CLI/menu\n// QUOTE(ТЗ): \"Могу удалить / Отключить\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) = 0 -> containers_stopped(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeDown = (cwd) => runCompose(cwd, [\"down\"], [Number(ExitCode(0))]);\n// CHANGE: run docker compose down -v in the target directory\n// WHY: allow a truly fresh environment by wiping the named volumes (e.g. /home/dev)\n// QUOTE(ТЗ): \"контейнер полностью должен же очищаться при --force\"\n// REF: user-request-2026-02-07-force-wipe-volumes\n// SOURCE: n/a\n// FORMAT THEOREM: ∀dir: down_v(dir) → removed(volumes(dir))\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: removes only resources within the compose project (containers, networks, volumes)\n// COMPLEXITY: O(command)\nexport const runDockerComposeDownVolumes = (cwd) => runCompose(cwd, [\"down\", \"-v\"], [Number(ExitCode(0))]);\n// CHANGE: recreate docker compose environment in the target directory\n// WHY: allow a clean rebuild of the container from the UI\n// QUOTE(ТЗ): \"дропнул контейнер и заново его создал\"\n// REF: user-request-2026-01-13\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: down(dir) && up(dir) -> recreated(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: down completes before up starts\n// COMPLEXITY: O(command)\nexport const runDockerComposeRecreate = (cwd) => pipe(runDockerComposeDown(cwd), Effect.zipRight(runDockerComposeUp(cwd)));\n// CHANGE: run docker compose ps in the target directory\n// WHY: expose runtime status in the interactive menu\n// QUOTE(ТЗ): \"вижу всю инфу по ним\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) = 0 -> status_listed(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposePs = (cwd) => runCompose(cwd, [\"ps\"], [Number(ExitCode(0))]);\n// CHANGE: capture docker compose ps output in a parseable format\n// WHY: allow structured, readable status output for CLI\n// QUOTE(ТЗ): \"информация отображалиась удобно\"\n// REF: user-request-2026-01-28\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: ps_fmt(dir) -> tabbed_string\n// PURITY: SHELL\n// EFFECT: Effect<string, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: output is tab-delimited columns from docker compose ps\n// COMPLEXITY: O(command)\nexport const runDockerComposePsFormatted = (cwd) => runComposeCapture(cwd, [\"ps\", \"--format\", \"{{.Name}}\\t{{.Status}}\\t{{.Ports}}\\t{{.Image}}\"], [Number(ExitCode(0))]);\n// CHANGE: run docker compose logs in the target directory\n// WHY: allow quick inspection of container output without leaving the menu\n// QUOTE(ТЗ): \"вижу всю инфу по ним\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) in {0,130} -> logs_shown(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeLogs = (cwd) => runCompose(cwd, [\"logs\", \"--tail\", \"200\"], [Number(ExitCode(0)), 130]);\n// CHANGE: stream docker compose logs until interrupted\n// WHY: allow synchronous clone flow to surface container output\n// QUOTE(ТЗ): \"должно работать синхронно отображая весь процесс\"\n// REF: user-request-2026-01-28\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: logs_follow(dir) -> stdout(stream)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeLogsFollow = (cwd) => runCompose(cwd, [\"logs\", \"--follow\", \"--tail\", \"0\"], [Number(ExitCode(0)), 130]);\n// CHANGE: run docker exec and return its exit code\n// WHY: allow polling for clone completion markers inside the container\n// QUOTE(ТЗ): \"весь процесс от и до\"\n// REF: user-request-2026-01-28\n// SOURCE: n/a\n// FORMAT THEOREM: forall cmd: exitCode(docker exec cmd) = n -> deterministic(n)\n// PURITY: SHELL\n// EFFECT: Effect<number, PlatformError, CommandExecutor>\n// INVARIANT: stdout/stderr are suppressed for polling commands\n// COMPLEXITY: O(command)\nexport const runDockerExecExitCode = (cwd, containerName, args) => Effect.gen(function* (_) {\n const command = pipe(Command.make(\"docker\", \"exec\", containerName, ...args), Command.workingDirectory(cwd), Command.stdout(\"pipe\"), Command.stderr(\"pipe\"));\n const exitCode = yield* _(Command.exitCode(command));\n return Number(exitCode);\n});\n// CHANGE: inspect container IP address\n// WHY: enable per-container DNS mapping on the host\n// QUOTE(ТЗ): \"У каждого контейнера свой IP т.е свой домен\"\n// REF: user-request-2026-01-30-dns\n// SOURCE: n/a\n// FORMAT THEOREM: forall c: inspect(c) -> ip(c)\n// PURITY: SHELL\n// EFFECT: Effect<string, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: returns empty string when not available\n// COMPLEXITY: O(command)\nexport const runDockerInspectContainerIp = (cwd, containerName) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\n \"inspect\",\n \"-f\",\n // Prefer the built-in `bridge` network IP when present so the printed IP\n // works from \"external\" containers that default to `bridge`.\n // Example output:\n // bridge=172.17.0.4\n // <project>_dg-<repo>-net=192.168.64.3\n String.raw `{{range $k,$v := .NetworkSettings.Networks}}{{printf \"%s=%s\\n\" $k $v.IPAddress}}{{end}}`,\n containerName\n ]\n}, [Number(ExitCode(0))], (exitCode) => new DockerCommandError({ exitCode })), Effect.map((output) => {\n const lines = output\n .trim()\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const entries = lines.flatMap((line) => parseInspectNetworkEntry(line));\n if (entries.length === 0) {\n return \"\";\n }\n const map = new Map(entries);\n return map.get(\"bridge\") ?? entries[0][1];\n}));\n// CHANGE: inspect the container IP address on the default `bridge` network\n// WHY: allow callers to decide whether `docker network connect bridge` is needed\n// QUOTE(ТЗ): \"подключиться с внешнего контейнера\"\n// REF: user-request-2026-02-10-bridge-ip\n// SOURCE: n/a\n// FORMAT THEOREM: ∀c: bridge(c) → ip_bridge(c) ≠ \"\"\n// PURITY: SHELL\n// EFFECT: Effect<string, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: returns \"\" when the container is not connected to `bridge`\n// COMPLEXITY: O(command)\nexport const runDockerInspectContainerBridgeIp = (cwd, containerName) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\n \"inspect\",\n \"-f\",\n \"{{with (index .NetworkSettings.Networks \\\"bridge\\\")}}{{.IPAddress}}{{end}}\",\n containerName\n ]\n}, [Number(ExitCode(0))], (exitCode) => new DockerCommandError({ exitCode })), Effect.map((output) => output.trim()));\n// CHANGE: connect an existing container to the default `bridge` network\n// WHY: allow \"external\" containers (which default to `bridge`) to reach services by container IP\n// QUOTE(ТЗ): \"Всё что запущено в докере должно быть публично наружу\"\n// REF: user-request-2026-02-10-public-ports\n// SOURCE: n/a\n// FORMAT THEOREM: ∀c: up(c) → reachable(bridge_ip(c), ports(c))\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: does not fail the overall flow when already connected (handled by caller)\n// COMPLEXITY: O(command)\nexport const runDockerNetworkConnectBridge = (cwd, containerName) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\"network\", \"connect\", \"bridge\", containerName]\n}, [Number(ExitCode(0))], (exitCode) => new DockerCommandError({ exitCode })), Effect.asVoid);\n// CHANGE: list names of running Docker containers\n// WHY: support TUI filtering (e.g. stop only running docker-git containers)\n// QUOTE(ТЗ): \"Если я выбираю остановку контейнера значит он мне должен показывать контейнеры которые запущены\"\n// REF: user-request-2026-02-07-stop-only-running\n// SOURCE: n/a\n// FORMAT THEOREM: forall c: c in ps -> running(c)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<string>, CommandFailedError | PlatformError, CommandExecutor>\n// INVARIANT: result contains only non-empty container names\n// COMPLEXITY: O(command)\nexport const runDockerPsNames = (cwd) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\"ps\", \"--format\", \"{{.Names}}\"]\n}, [Number(ExitCode(0))], (exitCode) => new CommandFailedError({ command: \"docker ps\", exitCode })), Effect.map((output) => output\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)));\n","import { Effect } from \"effect\";\nconst splitLines = (input) => input.replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\\n\").split(\"\\n\");\nconst joinLines = (lines) => lines.join(\"\\n\");\nconst normalizeEnvText = (input) => {\n const normalized = joinLines(splitLines(input));\n return normalized.endsWith(\"\\n\") ? normalized : `${normalized}\\n`;\n};\nconst isAlpha = (char) => {\n const code = char.codePointAt(0) ?? 0;\n return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);\n};\nconst isDigit = (char) => {\n const code = char.codePointAt(0) ?? 0;\n return code >= 48 && code <= 57;\n};\nconst isValidFirstChar = (char) => isAlpha(char) || char === \"_\";\nconst isValidEnvChar = (char) => isAlpha(char) || isDigit(char) || char === \"_\";\nconst hasOnlyValidChars = (value) => {\n for (const char of value) {\n if (!isValidEnvChar(char)) {\n return false;\n }\n }\n return true;\n};\nconst isEnvKey = (value) => {\n if (value.length === 0) {\n return false;\n }\n const first = value[0] ?? \"\";\n if (!isValidFirstChar(first)) {\n return false;\n }\n return hasOnlyValidChars(value.slice(1));\n};\nconst parseEnvLine = (line) => {\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed.startsWith(\"#\")) {\n return null;\n }\n const raw = trimmed.startsWith(\"export \") ? trimmed.slice(\"export \".length).trimStart() : trimmed;\n const eqIndex = raw.indexOf(\"=\");\n if (eqIndex <= 0) {\n return null;\n }\n const key = raw.slice(0, eqIndex).trim();\n if (!isEnvKey(key)) {\n return null;\n }\n const value = raw.slice(eqIndex + 1).trim();\n return { key, value };\n};\n// CHANGE: parse env file contents into key/value entries\n// WHY: allow updating shared auth env deterministically\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall t: parse(t) -> entries(t)\n// PURITY: CORE\n// INVARIANT: only valid KEY=VALUE lines are emitted\n// COMPLEXITY: O(n) where n = |lines|\nexport const parseEnvEntries = (input) => {\n const entries = [];\n for (const line of splitLines(input)) {\n const parsed = parseEnvLine(line);\n if (parsed) {\n entries.push(parsed);\n }\n }\n return entries;\n};\n// CHANGE: upsert a key in env contents\n// WHY: update tokens without manual edits\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall k,v: upsert(k,v) -> env(k)=v\n// PURITY: CORE\n// INVARIANT: env ends with newline\n// COMPLEXITY: O(n) where n = |lines|\nexport const upsertEnvKey = (input, key, value) => {\n const sanitized = normalizeEnvText(input);\n const lines = splitLines(sanitized);\n const trimmedKey = key.trim();\n const cleaned = trimmedKey.length === 0 ? lines : lines.filter((line) => {\n const parsed = parseEnvLine(line);\n return parsed ? parsed.key !== trimmedKey : true;\n });\n if (trimmedKey.length === 0 || value.trim().length === 0) {\n return normalizeEnvText(joinLines(cleaned));\n }\n return normalizeEnvText(joinLines([...cleaned, `${trimmedKey}=${value}`]));\n};\n// CHANGE: remove a key from env contents\n// WHY: allow token revocation\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall k: remove(k) -> !env(k)\n// PURITY: CORE\n// INVARIANT: env ends with newline\n// COMPLEXITY: O(n) where n = |lines|\nexport const removeEnvKey = (input, key) => upsertEnvKey(input, key, \"\");\nexport const defaultEnvContents = \"# docker-git env\\n# KEY=value\\n\";\n// CHANGE: ensure env file exists\n// WHY: persist auth tokens in a stable file\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: ensure(p) -> exists(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path>\n// INVARIANT: parent directories are created\n// COMPLEXITY: O(1)\nexport const ensureEnvFile = (fs, path, envPath) => Effect.gen(function* (_) {\n const exists = yield* _(fs.exists(envPath));\n if (exists) {\n return;\n }\n yield* _(fs.makeDirectory(path.dirname(envPath), { recursive: true }));\n yield* _(fs.writeFileString(envPath, defaultEnvContents));\n});\n// CHANGE: read env file contents\n// WHY: list and update stored tokens\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: read(p) -> contents(p)\n// PURITY: SHELL\n// EFFECT: Effect<string, PlatformError, FileSystem>\n// INVARIANT: returns default contents for missing/invalid file\n// COMPLEXITY: O(n) where n = |file|\nexport const readEnvText = (fs, envPath) => Effect.gen(function* (_) {\n const exists = yield* _(fs.exists(envPath));\n if (!exists) {\n return defaultEnvContents;\n }\n const info = yield* _(fs.stat(envPath));\n if (info.type !== \"File\") {\n return defaultEnvContents;\n }\n return yield* _(fs.readFileString(envPath));\n});\n","import { Effect } from \"effect\";\nexport const resolveAuthorizedKeysPath = (path, baseDir, authorizedKeysPath) => path.isAbsolute(authorizedKeysPath)\n ? authorizedKeysPath\n : path.resolve(baseDir, authorizedKeysPath);\nconst resolveHomeDir = () => {\n const raw = process.env[\"HOME\"] ?? process.env[\"USERPROFILE\"];\n const home = raw?.trim() ?? \"\";\n return home.length > 0 ? home : null;\n};\nconst expandHome = (value, home) => {\n if (home === null) {\n return value;\n }\n if (value === \"~\") {\n return home;\n }\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return `${home}${value.slice(1)}`;\n }\n return value;\n};\nconst trimTrailingSlash = (value) => {\n let end = value.length;\n while (end > 0) {\n const char = value[end - 1];\n if (char !== \"/\" && char !== \"\\\\\") {\n break;\n }\n end -= 1;\n }\n return value.slice(0, end);\n};\nexport const defaultProjectsRoot = (cwd) => {\n const home = resolveHomeDir();\n const explicit = process.env[\"DOCKER_GIT_PROJECTS_ROOT\"]?.trim();\n if (explicit && explicit.length > 0) {\n return expandHome(explicit, home);\n }\n if (home !== null) {\n return `${trimTrailingSlash(home)}/.docker-git`;\n }\n return `${cwd}/.docker-git`;\n};\nconst normalizeRelativePath = (value) => value\n .replaceAll(\"\\\\\", \"/\")\n .replace(/^\\.\\//, \"\")\n .trim();\nexport const resolvePathFromCwd = (path, cwd, targetPath) => path.isAbsolute(targetPath)\n ? targetPath\n : (() => {\n const projectsRoot = path.resolve(defaultProjectsRoot(cwd));\n const normalized = normalizeRelativePath(targetPath);\n if (normalized === \".docker-git\") {\n return projectsRoot;\n }\n const prefix = \".docker-git/\";\n if (normalized.startsWith(prefix)) {\n return path.join(projectsRoot, normalized.slice(prefix.length));\n }\n return path.resolve(cwd, targetPath);\n })();\nexport const findExistingUpwards = (fs, path, startDir, fileName, maxDepth) => Effect.gen(function* (_) {\n let current = startDir;\n for (let depth = 0; depth <= maxDepth; depth += 1) {\n const candidate = path.join(current, fileName);\n const exists = yield* _(fs.exists(candidate));\n if (exists) {\n return candidate;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n return null;\n});\nexport const resolveEnvPath = (key) => {\n const value = process.env[key]?.trim();\n return value && value.length > 0 ? value : null;\n};\nexport const findExistingPath = (fs, candidate) => candidate === null\n ? Effect.succeed(null)\n : Effect.flatMap(fs.exists(candidate), (exists) => (exists ? Effect.succeed(candidate) : Effect.succeed(null)));\nexport const findFirstExisting = (fs, candidates) => Effect.gen(function* (_) {\n for (const candidate of candidates) {\n const existing = yield* _(findExistingPath(fs, candidate));\n if (existing !== null) {\n return existing;\n }\n }\n return null;\n});\nexport const findKeyByPriority = (fs, path, cwd, spec) => Effect.gen(function* (_) {\n const envPath = resolveEnvPath(spec.envVar);\n const envExisting = yield* _(findExistingPath(fs, envPath));\n if (envExisting !== null) {\n return envExisting;\n }\n const devKey = yield* _(findExistingUpwards(fs, path, cwd, spec.devKeyName, 6));\n if (devKey !== null) {\n return devKey;\n }\n if (spec.fallbackName !== undefined) {\n const fallback = yield* _(findExistingUpwards(fs, path, cwd, spec.fallbackName, 6));\n if (fallback !== null) {\n return fallback;\n }\n }\n const home = resolveEnvPath(\"HOME\");\n if (home === null) {\n return null;\n }\n return yield* _(findFirstExisting(fs, spec.homeCandidates.map((candidate) => path.join(home, \".ssh\", candidate))));\n});\nconst authorizedKeysSpec = {\n envVar: \"DOCKER_GIT_AUTHORIZED_KEYS\",\n devKeyName: \"dev_ssh_key.pub\",\n fallbackName: \"authorized_keys\",\n homeCandidates: [\"id_ed25519.pub\", \"id_rsa.pub\"]\n};\nconst sshPrivateKeySpec = {\n envVar: \"DOCKER_GIT_SSH_KEY\",\n devKeyName: \"dev_ssh_key\",\n homeCandidates: [\"id_ed25519\", \"id_rsa\"]\n};\nconst makeKeyFinder = (spec) => (fs, path, cwd) => findKeyByPriority(fs, path, cwd, spec);\nexport const findAuthorizedKeysSource = makeKeyFinder(authorizedKeysSpec);\nexport const findSshPrivateKey = makeKeyFinder(sshPrivateKeySpec);\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\n// CHANGE: provide a shared FileSystem/Path context for usecases\n// WHY: avoid duplicated setup across shell workflows\n// QUOTE(ТЗ): \"минимальный корректный diff\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall run: ctx(run) -> fs,path,cwd\n// PURITY: SHELL\n// EFFECT: Effect<A, PlatformError, FileSystem | Path>\n// INVARIANT: cwd is captured once per call\n// COMPLEXITY: O(1)\nexport const withFsPathContext = (run) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n return yield* _(run({ fs, path, cwd: process.cwd() }));\n});\n","export { defaultProjectsRoot, findSshPrivateKey, resolveAuthorizedKeysPath } from \"./path-helpers.js\";\nexport const isRepoUrlInput = (input) => {\n const trimmed = input.trim().toLowerCase();\n return trimmed.startsWith(\"http://\") ||\n trimmed.startsWith(\"https://\") ||\n trimmed.startsWith(\"ssh://\") ||\n trimmed.startsWith(\"git@\");\n};\nexport const formatConnectionInfo = (cwd, config, authorizedKeysPath, authorizedKeysExists, sshCommand) => `Project directory: ${cwd}\n` +\n `Container: ${config.template.containerName}\n` +\n `Service: ${config.template.serviceName}\n` +\n `SSH command: ${sshCommand}\n` +\n `Repo: ${config.template.repoUrl} (${config.template.repoRef})\n` +\n `Workspace: ${config.template.targetDir}\n` +\n `Authorized keys: ${authorizedKeysPath}${authorizedKeysExists ? \"\" : \" (missing)\"}\n` +\n `Env global: ${config.template.envGlobalPath}\n` +\n `Env project: ${config.template.envProjectPath}\n` +\n `Codex auth: ${config.template.codexAuthPath} -> ${config.template.codexHome}`;\n","import { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport { Effect } from \"effect\";\nimport { runCommandCapture, runCommandExitCode, runCommandWithExitCodes } from \"../../shell/command-runner.js\";\nimport { CommandFailedError } from \"../../shell/errors.js\";\nexport const successExitCode = Number(ExitCode(0));\nexport const gitBaseEnv = {\n // Avoid blocking on interactive credential prompts in CI / TUI contexts.\n GIT_TERMINAL_PROMPT: \"0\"\n};\nexport const git = (cwd, args, env = gitBaseEnv) => runCommandWithExitCodes({ cwd, command: \"git\", args, env }, [successExitCode], (exitCode) => new CommandFailedError({ command: `git ${args[0] ?? \"\"}`, exitCode }));\nexport const gitExitCode = (cwd, args, env = gitBaseEnv) => runCommandExitCode({ cwd, command: \"git\", args, env });\nexport const gitCapture = (cwd, args, env = gitBaseEnv) => runCommandCapture({ cwd, command: \"git\", args, env }, [successExitCode], (exitCode) => new CommandFailedError({ command: `git ${args[0] ?? \"\"}`, exitCode }));\nexport const isGitRepo = (root) => Effect.map(gitExitCode(root, [\"rev-parse\", \"--is-inside-work-tree\"]), (exit) => exit === successExitCode);\nexport const hasOriginRemote = (root) => Effect.map(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"]), (exit) => exit === successExitCode);\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport { Effect } from \"effect\";\nimport { parseEnvEntries } from \"../env-file.js\";\nimport { gitBaseEnv } from \"./git-commands.js\";\nconst githubTokenKey = \"GITHUB_TOKEN\";\nconst githubHttpsRemoteRe = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/;\nconst githubSshRemoteRe = /^git@github\\.com:([^/]+)\\/(.+?)(?:\\.git)?$/;\nconst githubSshUrlRemoteRe = /^ssh:\\/\\/git@github\\.com\\/([^/]+)\\/(.+?)(?:\\.git)?$/;\nconst tryParseGithubRemoteParts = (originUrl) => {\n const trimmed = originUrl.trim();\n const match = githubHttpsRemoteRe.exec(trimmed) ??\n githubSshRemoteRe.exec(trimmed) ??\n githubSshUrlRemoteRe.exec(trimmed);\n if (match === null) {\n return null;\n }\n const owner = match[1] ?? \"\";\n const repo = match[2] ?? \"\";\n return owner.length > 0 && repo.length > 0 ? { owner, repo } : null;\n};\nexport const tryBuildGithubCompareUrl = (originUrl, baseBranch, headBranch) => {\n const parts = tryParseGithubRemoteParts(originUrl);\n if (parts === null) {\n return null;\n }\n return `https://github.com/${parts.owner}/${parts.repo}/compare/${encodeURIComponent(baseBranch)}...${encodeURIComponent(headBranch)}?expand=1`;\n};\nexport const isGithubHttpsRemote = (url) => /^https:\\/\\/github\\.com\\//.test(url.trim());\nconst resolveTokenFromProcessEnv = () => {\n const github = process.env[\"GITHUB_TOKEN\"];\n if (github !== undefined) {\n const trimmed = github.trim();\n if (trimmed.length > 0) {\n return trimmed;\n }\n }\n const gh = process.env[\"GH_TOKEN\"];\n if (gh !== undefined) {\n const trimmed = gh.trim();\n if (trimmed.length > 0) {\n return trimmed;\n }\n }\n return null;\n};\nconst findTokenInEnvEntries = (entries) => {\n const directEntry = entries.find((e) => e.key === githubTokenKey);\n if (directEntry !== undefined) {\n const direct = directEntry.value.trim();\n if (direct.length > 0) {\n return direct;\n }\n }\n const labeledEntry = entries.find((e) => e.key.startsWith(\"GITHUB_TOKEN__\"));\n if (labeledEntry !== undefined) {\n const labeled = labeledEntry.value.trim();\n if (labeled.length > 0) {\n return labeled;\n }\n }\n return null;\n};\nexport const resolveGithubToken = (fs, path, root) => Effect.gen(function* (_) {\n const fromEnv = resolveTokenFromProcessEnv();\n if (fromEnv !== null) {\n return fromEnv;\n }\n const envPath = path.join(root, \".orch\", \"env\", \"global.env\");\n const exists = yield* _(fs.exists(envPath));\n if (!exists) {\n return null;\n }\n const text = yield* _(fs.readFileString(envPath));\n return findTokenInEnvEntries(parseEnvEntries(text));\n});\nexport const withGithubAskpassEnv = (token, use) => Effect.scoped(Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const askpassPath = yield* _(fs.makeTempFileScoped({ prefix: \"docker-git-askpass-\" }));\n const contents = [\n \"#!/bin/sh\",\n \"case \\\"$1\\\" in\",\n \" *Username*) echo \\\"x-access-token\\\" ;;\",\n \" *Password*) echo \\\"${DOCKER_GIT_GITHUB_TOKEN}\\\" ;;\",\n \" *) echo \\\"${DOCKER_GIT_GITHUB_TOKEN}\\\" ;;\",\n \"esac\",\n \"\"\n ].join(\"\\n\");\n yield* _(fs.writeFileString(askpassPath, contents));\n yield* _(fs.chmod(askpassPath, 0o700));\n const env = {\n ...gitBaseEnv,\n DOCKER_GIT_GITHUB_TOKEN: token,\n GIT_ASKPASS: askpassPath,\n GIT_ASKPASS_REQUIRE: \"force\"\n };\n return yield* _(use(env));\n}));\n","import { Effect } from \"effect\";\nconst isDockerGitConfig = (entry) => entry.endsWith(\"docker-git.json\");\nconst shouldSkipDir = (entry) => entry === \".git\" || entry === \".orch\";\nconst processDockerGitEntry = (fs, path, dir, entry, state) => Effect.gen(function* (_) {\n if (shouldSkipDir(entry)) {\n return;\n }\n const resolved = path.join(dir, entry);\n const info = yield* _(fs.stat(resolved));\n if (info.type === \"Directory\") {\n state.stack.push(resolved);\n return;\n }\n if (info.type === \"File\" && isDockerGitConfig(entry)) {\n state.results.push(resolved);\n }\n}).pipe(Effect.asVoid);\nexport const findDockerGitConfigPaths = (fs, path, rootDir) => Effect.gen(function* (_) {\n const exists = yield* _(fs.exists(rootDir));\n if (!exists) {\n return [];\n }\n // Avoid traversing git metadata (projectsRoot can itself be a git repo).\n const results = [];\n const stack = [rootDir];\n const state = { stack, results };\n while (stack.length > 0) {\n const dir = stack.pop();\n if (dir === undefined) {\n break;\n }\n const entries = yield* _(fs.readDirectory(dir));\n for (const entry of entries) {\n yield* _(processDockerGitEntry(fs, path, dir, entry, state));\n }\n }\n return results;\n});\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\nimport { runCommandExitCode } from \"../shell/command-runner.js\";\nimport { CommandFailedError } from \"../shell/errors.js\";\nimport { defaultProjectsRoot } from \"./menu-helpers.js\";\nimport { autoSyncEnvKey, autoSyncStrictEnvKey, isAutoSyncEnabled, isTruthyEnv } from \"./state-repo/env.js\";\nimport { git, gitBaseEnv, gitCapture, gitExitCode, hasOriginRemote, isGitRepo, successExitCode } from \"./state-repo/git-commands.js\";\nimport { isGithubHttpsRemote, resolveGithubToken, withGithubAskpassEnv } from \"./state-repo/github-auth.js\";\nimport { ensureStateGitignore } from \"./state-repo/gitignore.js\";\nimport { runStateSyncOps, runStateSyncWithToken } from \"./state-repo/sync-ops.js\";\nconst resolveStateRoot = (path, cwd) => path.resolve(defaultProjectsRoot(cwd));\nexport const statePath = Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const cwd = process.cwd();\n const root = resolveStateRoot(path, cwd);\n yield* _(Effect.log(root));\n}).pipe(Effect.asVoid);\nexport const stateSync = (message) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const repoExit = yield* _(gitExitCode(root, [\"rev-parse\", \"--is-inside-work-tree\"], gitBaseEnv));\n if (repoExit !== successExitCode) {\n yield* _(Effect.logWarning(`State dir is not a git repository: ${root}`));\n yield* _(Effect.logWarning(`Run: docker-git state init --repo-url <url>`));\n return yield* _(Effect.fail(new CommandFailedError({ command: \"git rev-parse --is-inside-work-tree\", exitCode: repoExit })));\n }\n const originUrlExit = yield* _(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv));\n if (originUrlExit !== successExitCode) {\n yield* _(Effect.logWarning(`State dir has no origin remote: ${root}`));\n yield* _(Effect.logWarning(`Run: docker-git state init --repo-url <url>`));\n return yield* _(Effect.fail(new CommandFailedError({ command: \"git remote get-url origin\", exitCode: originUrlExit })));\n }\n const originUrl = yield* _(gitCapture(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv).pipe(Effect.map((value) => value.trim())));\n const token = yield* _(resolveGithubToken(fs, path, root));\n const syncEffect = token && token.length > 0 && isGithubHttpsRemote(originUrl)\n ? runStateSyncWithToken(token, root, originUrl, message)\n : runStateSyncOps(root, originUrl, message, gitBaseEnv);\n yield* _(syncEffect);\n}).pipe(Effect.asVoid);\nexport const autoSyncState = (message) => Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const repoOk = yield* _(isGitRepo(root));\n if (!repoOk) {\n return;\n }\n const originOk = yield* _(hasOriginRemote(root));\n const enabled = isAutoSyncEnabled(process.env[autoSyncEnvKey], originOk);\n if (!enabled) {\n return;\n }\n const strictValue = process.env[autoSyncStrictEnvKey];\n const strict = strictValue !== undefined && strictValue.trim().length > 0 ? isTruthyEnv(strictValue) : false;\n const effect = stateSync(message);\n if (strict) {\n yield* _(effect);\n return;\n }\n yield* _(effect.pipe(Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`State auto-sync failed: ${error._tag === \"CommandFailedError\"\n ? `${error.command} (exit ${error.exitCode})`\n : String(error)}`),\n onSuccess: () => Effect.void\n })));\n}).pipe(Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`State auto-sync failed: ${String(error)}`),\n onSuccess: () => Effect.void\n}), Effect.asVoid);\nconst cloneStateRepo = (root, input) => Effect.gen(function* (_) {\n const cloneWithBranch = [\"clone\", \"--branch\", input.repoRef, input.repoUrl, root];\n const cloneBranchExit = yield* _(runCommandExitCode({ cwd: root, command: \"git\", args: cloneWithBranch, env: gitBaseEnv }));\n if (cloneBranchExit === successExitCode) {\n return;\n }\n // Empty remotes (no branch yet) and remotes without the requested branch can fail here.\n // Fall back to cloning the default branch so we can still set up the repo and create the branch locally.\n yield* _(Effect.logWarning(`git clone --branch ${input.repoRef} failed (exit ${cloneBranchExit}); retrying without --branch`));\n const cloneDefault = [\"clone\", input.repoUrl, root];\n const cloneDefaultExit = yield* _(runCommandExitCode({ cwd: root, command: \"git\", args: cloneDefault, env: gitBaseEnv }));\n if (cloneDefaultExit !== successExitCode) {\n return yield* _(Effect.fail(new CommandFailedError({ command: \"git clone\", exitCode: cloneDefaultExit })));\n }\n}).pipe(Effect.asVoid);\nconst initRepoIfNeeded = (fs, path, root, input) => Effect.gen(function* (_) {\n yield* _(fs.makeDirectory(root, { recursive: true }));\n const gitDir = path.join(root, \".git\");\n const hasGit = yield* _(fs.exists(gitDir));\n if (hasGit) {\n return;\n }\n const entries = yield* _(fs.readDirectory(root));\n if (entries.length === 0) {\n yield* _(cloneStateRepo(root, input));\n yield* _(Effect.log(`State dir cloned: ${root}`));\n return;\n }\n yield* _(git(root, [\"init\"], gitBaseEnv));\n}).pipe(Effect.asVoid);\nconst ensureOriginRemote = (root, repoUrl) => Effect.gen(function* (_) {\n const setUrlExit = yield* _(gitExitCode(root, [\"remote\", \"set-url\", \"origin\", repoUrl], gitBaseEnv));\n if (setUrlExit === successExitCode) {\n return;\n }\n yield* _(git(root, [\"remote\", \"add\", \"origin\", repoUrl], gitBaseEnv));\n});\nconst checkoutBranchBestEffort = (root, repoRef) => Effect.gen(function* (_) {\n const checkoutExit = yield* _(gitExitCode(root, [\"checkout\", \"-B\", repoRef], gitBaseEnv));\n if (checkoutExit === successExitCode) {\n return;\n }\n yield* _(Effect.logWarning(`git checkout -B ${repoRef} failed (exit ${checkoutExit})`));\n});\nexport const stateInit = (input) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n yield* _(initRepoIfNeeded(fs, path, root, input));\n yield* _(ensureOriginRemote(root, input.repoUrl));\n yield* _(checkoutBranchBestEffort(root, input.repoRef));\n yield* _(ensureStateGitignore(fs, path, root));\n yield* _(Effect.log(`State dir ready: ${root}`));\n yield* _(Effect.log(`Remote: ${input.repoUrl}`));\n}).pipe(Effect.asVoid);\nexport const stateStatus = Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const output = yield* _(gitCapture(root, [\"status\", \"-sb\", \"--porcelain=v1\"], gitBaseEnv));\n yield* _(Effect.log(output.trim().length > 0 ? output.trimEnd() : \"(clean)\"));\n}).pipe(Effect.asVoid);\nexport const statePull = Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const originUrlExit = yield* _(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv));\n if (originUrlExit !== successExitCode) {\n yield* _(git(root, [\"pull\", \"--rebase\"], gitBaseEnv));\n return;\n }\n const originUrl = yield* _(gitCapture(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv).pipe(Effect.map((value) => value.trim())));\n const token = yield* _(resolveGithubToken(fs, path, root));\n const effect = token && token.length > 0 && isGithubHttpsRemote(originUrl)\n ? withGithubAskpassEnv(token, (env) => git(root, [\"pull\", \"--rebase\"], env))\n : git(root, [\"pull\", \"--rebase\"], gitBaseEnv);\n yield* _(effect);\n}).pipe(Effect.asVoid);\nexport const statePush = Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const originUrlExit = yield* _(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv));\n if (originUrlExit !== successExitCode) {\n yield* _(git(root, [\"push\", \"-u\", \"origin\", \"HEAD\"], gitBaseEnv));\n return;\n }\n const originUrl = yield* _(gitCapture(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv).pipe(Effect.map((value) => value.trim())));\n const token = yield* _(resolveGithubToken(fs, path, root));\n const effect = token && token.length > 0 && isGithubHttpsRemote(originUrl)\n ? withGithubAskpassEnv(token, (env) => git(root, [\"push\", \"-u\", \"origin\", \"HEAD\"], env))\n : git(root, [\"push\", \"-u\", \"origin\", \"HEAD\"], gitBaseEnv);\n yield* _(effect);\n}).pipe(Effect.asVoid);\nexport const stateCommit = (message) => Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n yield* _(git(root, [\"add\", \"-A\"], gitBaseEnv));\n const diffExit = yield* _(gitExitCode(root, [\"diff\", \"--cached\", \"--quiet\"], gitBaseEnv));\n if (diffExit === successExitCode) {\n yield* _(Effect.log(\"Nothing to commit.\"));\n return;\n }\n yield* _(git(root, [\"commit\", \"-m\", message], gitBaseEnv));\n}).pipe(Effect.asVoid);\n","import {} from \"../core/domain.js\";\nimport { formatParseError } from \"../core/parse-errors.js\";\nconst isParseError = (error) => error._tag === \"UnknownCommand\" ||\n error._tag === \"UnknownOption\" ||\n error._tag === \"MissingOptionValue\" ||\n error._tag === \"MissingRequiredOption\" ||\n error._tag === \"InvalidOption\" ||\n error._tag === \"UnexpectedArgument\";\nconst renderDockerAccessHeadline = (issue) => issue === \"PermissionDenied\"\n ? \"Cannot access Docker daemon socket: permission denied.\"\n : \"Cannot connect to Docker daemon.\";\nconst renderPrimaryError = (error) => {\n if (error._tag === \"FileExistsError\") {\n return `File already exists: ${error.path} (use --force to overwrite)`;\n }\n if (error._tag === \"DockerCommandError\") {\n return [\n `docker compose failed with exit code ${error.exitCode}`,\n \"Hint: ensure Docker daemon is running and current user can access /var/run/docker.sock (for example via the docker group).\"\n ].join(\"\\n\");\n }\n if (error._tag === \"DockerAccessError\") {\n return [\n renderDockerAccessHeadline(error.issue),\n \"Hint: ensure Docker daemon is running and current user can access the docker socket.\",\n \"Hint: if you use rootless Docker, set DOCKER_HOST to your user socket (for example unix:///run/user/$UID/docker.sock).\",\n `Details: ${error.details}`\n ].join(\"\\n\");\n }\n if (error._tag === \"CloneFailedError\") {\n return `Clone failed for ${error.repoUrl} (${error.repoRef}) into ${error.targetDir}`;\n }\n if (error._tag === \"PortProbeError\") {\n return `SSH port check failed for ${error.port}: ${error.message}`;\n }\n if (error._tag === \"CommandFailedError\") {\n return `${error.command} failed with exit code ${error.exitCode}`;\n }\n if (error._tag === \"AuthError\") {\n return error.message;\n }\n return null;\n};\nconst renderConfigError = (error) => {\n if (error._tag === \"ConfigNotFoundError\") {\n return `docker-git.json not found: ${error.path} (run docker-git create in that directory)`;\n }\n if (error._tag === \"ConfigDecodeError\") {\n return `Invalid docker-git.json at ${error.path}: ${error.message}`;\n }\n return null;\n};\nconst renderInputError = (error) => {\n if (error._tag === \"InputCancelledError\") {\n return \"Input cancelled.\";\n }\n if (error._tag === \"InputReadError\") {\n return `Input error: ${error.message}`;\n }\n return null;\n};\nconst renderNonParseError = (error) => renderPrimaryError(error) ?? renderConfigError(error) ?? renderInputError(error) ?? error.message;\n// CHANGE: render typed application errors into user-facing text\n// WHY: provide deterministic messaging for CLI and menu flows\n// QUOTE(ТЗ): \"вижу всю инфу по ним\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: render(e) = s -> deterministic(s)\n// PURITY: CORE\n// EFFECT: Effect<string, never, never>\n// INVARIANT: each AppError maps to exactly one message\n// COMPLEXITY: O(1)\nexport const renderError = (error) => {\n if (isParseError(error)) {\n return formatParseError(error);\n }\n return renderNonParseError(error);\n};\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect, pipe } from \"effect\";\nimport { deriveRepoPathParts } from \"../core/domain.js\";\nimport { readProjectConfig } from \"../shell/config.js\";\nimport { resolveBaseDir } from \"../shell/paths.js\";\nimport { findDockerGitConfigPaths } from \"./docker-git-config-search.js\";\nimport { renderError } from \"./errors.js\";\nimport { defaultProjectsRoot, formatConnectionInfo } from \"./menu-helpers.js\";\nimport { findSshPrivateKey, resolveAuthorizedKeysPath, resolvePathFromCwd } from \"./path-helpers.js\";\nimport { withFsPathContext } from \"./runtime.js\";\nconst sshOptions = \"-tt -Y -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\";\nexport const buildSshCommand = (config, sshKey) => sshKey === null\n ? `ssh ${sshOptions} -p ${config.sshPort} ${config.sshUser}@localhost`\n : `ssh -i ${sshKey} ${sshOptions} -p ${config.sshPort} ${config.sshUser}@localhost`;\nconst loadProjectBase = (configPath) => Effect.gen(function* (_) {\n const { fs, path, resolved } = yield* _(resolveBaseDir(configPath));\n const projectDir = path.dirname(resolved);\n const config = yield* _(readProjectConfig(projectDir));\n return { fs, path, projectDir, config };\n});\nconst findProjectConfigPaths = (projectsRoot) => withFsPathContext(({ fs, path }) => findDockerGitConfigPaths(fs, path, path.resolve(projectsRoot)));\nexport const loadProjectSummary = (configPath, sshKey) => Effect.gen(function* (_) {\n const { config, fs, path, projectDir } = yield* _(loadProjectBase(configPath));\n const resolvedAuthorizedKeys = resolveAuthorizedKeysPath(path, projectDir, config.template.authorizedKeysPath);\n const authExists = yield* _(fs.exists(resolvedAuthorizedKeys));\n const sshCommand = buildSshCommand(config.template, sshKey);\n return {\n projectDir,\n config,\n sshCommand,\n authorizedKeysPath: resolvedAuthorizedKeys,\n authorizedKeysExists: authExists\n };\n});\nexport const loadProjectStatus = (configPath) => Effect.gen(function* (_) {\n const { config, projectDir } = yield* _(loadProjectBase(configPath));\n return { projectDir, config };\n});\nexport const renderProjectSummary = (summary) => formatConnectionInfo(summary.projectDir, summary.config, summary.authorizedKeysPath, summary.authorizedKeysExists, summary.sshCommand);\nconst formatDisplayName = (repoUrl) => {\n const parts = deriveRepoPathParts(repoUrl);\n if (parts.pathParts.length > 0) {\n return parts.pathParts.join(\"/\");\n }\n return repoUrl;\n};\nexport const loadProjectItem = (configPath, sshKey) => Effect.gen(function* (_) {\n const { config, fs, path, projectDir } = yield* _(loadProjectBase(configPath));\n const template = config.template;\n const resolvedAuthorizedKeys = resolveAuthorizedKeysPath(path, projectDir, template.authorizedKeysPath);\n const authExists = yield* _(fs.exists(resolvedAuthorizedKeys));\n const sshCommand = buildSshCommand(template, sshKey);\n const displayName = formatDisplayName(template.repoUrl);\n return {\n projectDir,\n displayName,\n repoUrl: template.repoUrl,\n repoRef: template.repoRef,\n containerName: template.containerName,\n serviceName: template.serviceName,\n sshUser: template.sshUser,\n sshPort: template.sshPort,\n targetDir: template.targetDir,\n sshCommand,\n sshKeyPath: sshKey,\n authorizedKeysPath: resolvedAuthorizedKeys,\n authorizedKeysExists: authExists,\n envGlobalPath: resolvePathFromCwd(path, projectDir, template.envGlobalPath),\n envProjectPath: resolvePathFromCwd(path, projectDir, template.envProjectPath),\n codexAuthPath: resolvePathFromCwd(path, projectDir, template.codexAuthPath),\n codexHome: template.codexHome\n };\n});\nexport const renderProjectStatusHeader = (status) => `Project: ${status.projectDir}`;\nexport const skipWithWarning = (configPath) => (error) => pipe(Effect.logWarning(`Skipping ${configPath}: ${renderError(error)}`), Effect.as(null));\nexport const forEachProjectStatus = (configPaths, run) => Effect.gen(function* (_) {\n for (const configPath of configPaths) {\n const status = yield* _(loadProjectStatus(configPath).pipe(Effect.matchEffect({\n onFailure: skipWithWarning(configPath),\n onSuccess: (value) => Effect.succeed(value)\n })));\n if (status === null) {\n continue;\n }\n yield* _(run(status));\n }\n}).pipe(Effect.asVoid);\nconst normalizeCell = (value) => value?.trim() ?? \"-\";\nconst parseComposeLine = (line) => {\n const [name, status, ports, image] = line.split(\"\\t\");\n return {\n name: normalizeCell(name),\n status: normalizeCell(status),\n ports: normalizeCell(ports),\n image: normalizeCell(image)\n };\n};\nexport const parseComposePsOutput = (raw) => {\n const lines = raw\n .split(/\\r?\\n/)\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n return lines.map((line) => parseComposeLine(line));\n};\nconst padRight = (value, width) => value.length >= width ? value : `${value}${\" \".repeat(width - value.length)}`;\nexport const formatComposeRows = (entries) => {\n if (entries.length === 0) {\n return \" status: not running\";\n }\n const nameWidth = Math.min(24, Math.max(...entries.map((row) => row.name.length), \"name\".length));\n const statusWidth = Math.min(28, Math.max(...entries.map((row) => row.status.length), \"status\".length));\n const portsWidth = Math.min(28, Math.max(...entries.map((row) => row.ports.length), \"ports\".length));\n const header = ` ${padRight(\"name\", nameWidth)} ${padRight(\"status\", statusWidth)} ${padRight(\"ports\", portsWidth)} image`;\n const lines = entries.map((row) => ` ${padRight(row.name, nameWidth)} ${padRight(row.status, statusWidth)} ${padRight(row.ports, portsWidth)} ${row.image}`);\n return [header, ...lines].join(\"\\n\");\n};\nexport const loadProjectIndex = () => Effect.gen(function* (_) {\n const projectsRoot = defaultProjectsRoot(process.cwd());\n const configPaths = yield* _(findProjectConfigPaths(projectsRoot));\n if (configPaths.length === 0) {\n yield* _(Effect.log(`No docker-git projects found in ${projectsRoot}`));\n return null;\n }\n return { projectsRoot, configPaths };\n});\nexport const withProjectIndexAndSsh = (run) => pipe(loadProjectIndex(), Effect.flatMap((index) => index === null\n ? Effect.succeed(null)\n : Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const sshKey = yield* _(findSshPrivateKey(fs, path, process.cwd()));\n return yield* _(run(index, sshKey));\n })));\n","import { Effect, pipe } from \"effect\";\nimport { runDockerComposeDown } from \"../shell/docker.js\";\nimport { renderError } from \"./errors.js\";\nimport { forEachProjectStatus, loadProjectIndex, renderProjectStatusHeader } from \"./projects-core.js\";\n// CHANGE: provide a \"stop all\" helper for docker-git managed projects\n// WHY: allow quickly stopping all running docker-git containers from the CLI/TUI\n// QUOTE(ТЗ): \"Выведи сюда возможность убивать все контейнеры\"\n// REF: user-request-2026-02-06-stop-all\n// SOURCE: n/a\n// FORMAT THEOREM: ∀p ∈ Projects: downAll(p) → stopped(p) ∨ warned(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path | CommandExecutor>\n// INVARIANT: continues stopping other projects when one docker compose down fails with DockerCommandError\n// COMPLEXITY: O(n) where n = |projects|\nexport const downAllDockerGitProjects = pipe(loadProjectIndex(), Effect.flatMap((index) => index === null\n ? Effect.void\n : forEachProjectStatus(index.configPaths, (status) => pipe(Effect.log(renderProjectStatusHeader(status)), Effect.zipRight(runDockerComposeDown(status.projectDir).pipe(Effect.catchTag(\"DockerCommandError\", (error) => Effect.logWarning(`docker compose down failed for ${status.projectDir}: ${renderError(error)}`))))))), Effect.asVoid);\n","import { Effect, pipe } from \"effect\";\nimport { runDockerPsNames } from \"../shell/docker.js\";\nimport { loadProjectItem, loadProjectSummary, renderProjectSummary, skipWithWarning, withProjectIndexAndSsh } from \"./projects-core.js\";\n// CHANGE: list docker-git projects with SSH connection info\n// WHY: provide a deterministic inventory of created environments\n// QUOTE(ТЗ): \"мне нужны мои... доступы к ним по SSH\"\n// REF: user-request-2026-01-27-list\n// SOURCE: n/a\n// FORMAT THEOREM: forall root: list(root) -> summaries(root)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path>\n// INVARIANT: output is deterministic for a stable filesystem\n// COMPLEXITY: O(n) where n = |projects|\nexport const listProjects = pipe(withProjectIndexAndSsh((index, sshKey) => Effect.gen(function* (_) {\n const available = [];\n for (const configPath of index.configPaths) {\n const summary = yield* _(loadProjectSummary(configPath, sshKey).pipe(Effect.matchEffect({\n onFailure: skipWithWarning(configPath),\n onSuccess: (value) => Effect.succeed(value)\n })));\n if (summary !== null) {\n available.push(summary);\n }\n }\n if (available.length === 0) {\n yield* _(Effect.log(`No readable docker-git projects found in ${index.projectsRoot}`));\n return;\n }\n yield* _(Effect.log(`Found ${available.length} docker-git project(s) in ${index.projectsRoot}`));\n for (const summary of available) {\n yield* _(Effect.log(renderProjectSummary(summary)));\n }\n})), Effect.asVoid);\n// CHANGE: collect docker-git connection info lines without logging\n// WHY: allow TUI to render connection info inline\n// QUOTE(ТЗ): \"А кнопка \\\"Show connection info\\\" ничего не отображает\"\n// REF: user-request-2026-02-01-tui-info\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in projects: summary(p) -> line(p)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<string>, PlatformError, FileSystem | Path>\n// INVARIANT: output order matches configPaths order\n// COMPLEXITY: O(n) where n = |projects|\nconst emptySummaries = () => [];\nconst emptyItems = () => [];\nconst collectProjectValues = (configPaths, sshKey, load, toValue) => Effect.gen(function* (_) {\n const available = [];\n for (const configPath of configPaths) {\n const value = yield* _(load(configPath, sshKey).pipe(Effect.matchEffect({\n onFailure: () => Effect.succeed(null),\n onSuccess: (item) => Effect.succeed(toValue(item))\n })));\n if (value !== null) {\n available.push(value);\n }\n }\n return available;\n});\nconst listProjectValues = (load, toValue, empty) => pipe(withProjectIndexAndSsh((index, sshKey) => collectProjectValues(index.configPaths, sshKey, load, toValue)), Effect.map((values) => values ?? empty()));\nexport const listProjectSummaries = listProjectValues(loadProjectSummary, renderProjectSummary, emptySummaries);\n// CHANGE: load docker-git projects for TUI selection\n// WHY: provide structured project data without noisy logs\n// QUOTE(ТЗ): \"А ты можешь сделать удобный выбор проектов?\"\n// REF: user-request-2026-02-02-select-project\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in projects: item(p) -> selectable(p)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<ProjectItem>, PlatformError, FileSystem | Path>\n// INVARIANT: output order matches configPaths order\n// COMPLEXITY: O(n) where n = |projects|\nexport const listProjectItems = listProjectValues(loadProjectItem, (value) => value, emptyItems);\n// CHANGE: list only running docker-git projects (for \"Stop container\" UI)\n// WHY: stopping already-stopped projects is confusing and noisy\n// QUOTE(ТЗ): \"Смысл мне пытаться остановить тот контейнер который уже остановлен?\"\n// REF: user-request-2026-02-07-stop-only-running\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in result: running(container(p))\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<ProjectItem>, PlatformError | CommandFailedError, FileSystem | Path | CommandExecutor>\n// INVARIANT: result order follows listProjectItems order\n// COMPLEXITY: O(n + command)\nexport const listRunningProjectItems = pipe(Effect.all([listProjectItems, runDockerPsNames(process.cwd())]), Effect.map(([items, runningNames]) => items.filter((item) => runningNames.includes(item.containerName))));\n","import { Duration, Effect, pipe, Schedule } from \"effect\";\nimport { runCommandExitCode, runCommandWithExitCodes } from \"../shell/command-runner.js\";\nimport { runDockerComposePsFormatted } from \"../shell/docker.js\";\nimport { CommandFailedError } from \"../shell/errors.js\";\nimport { renderError } from \"./errors.js\";\nimport { buildSshCommand, forEachProjectStatus, formatComposeRows, parseComposePsOutput, renderProjectStatusHeader, withProjectIndexAndSsh } from \"./projects-core.js\";\nimport { runDockerComposeUpWithPortCheck } from \"./projects-up.js\";\nconst buildSshArgs = (item) => {\n const args = [];\n if (item.sshKeyPath !== null) {\n args.push(\"-i\", item.sshKeyPath);\n }\n args.push(\"-tt\", \"-Y\", \"-o\", \"LogLevel=ERROR\", \"-o\", \"StrictHostKeyChecking=no\", \"-o\", \"UserKnownHostsFile=/dev/null\", \"-p\", String(item.sshPort), `${item.sshUser}@localhost`);\n return args;\n};\nconst buildSshProbeArgs = (item) => {\n const args = [];\n if (item.sshKeyPath !== null) {\n args.push(\"-i\", item.sshKeyPath);\n }\n args.push(\"-T\", \"-o\", \"BatchMode=yes\", \"-o\", \"ConnectTimeout=2\", \"-o\", \"ConnectionAttempts=1\", \"-o\", \"LogLevel=ERROR\", \"-o\", \"StrictHostKeyChecking=no\", \"-o\", \"UserKnownHostsFile=/dev/null\", \"-p\", String(item.sshPort), `${item.sshUser}@localhost`, \"true\");\n return args;\n};\nconst waitForSshReady = (item) => {\n const probe = Effect.gen(function* (_) {\n const exitCode = yield* _(runCommandExitCode({\n cwd: process.cwd(),\n command: \"ssh\",\n args: buildSshProbeArgs(item)\n }));\n if (exitCode !== 0) {\n return yield* _(Effect.fail(new CommandFailedError({ command: \"ssh wait\", exitCode })));\n }\n });\n return pipe(Effect.log(`Waiting for SSH on localhost:${item.sshPort} ...`), Effect.zipRight(Effect.retry(probe, pipe(Schedule.spaced(Duration.seconds(2)), Schedule.intersect(Schedule.recurs(30))))), Effect.tap(() => Effect.log(\"SSH is ready.\")));\n};\n// CHANGE: connect to a project via SSH using its resolved settings\n// WHY: allow TUI to open a shell immediately after selection\n// QUOTE(ТЗ): \"выбор проекта сразу подключает по SSH\"\n// REF: user-request-2026-02-02-select-ssh\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: connect(p) -> ssh(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, CommandFailedError | PlatformError, CommandExecutor>\n// INVARIANT: command is ssh with deterministic args\n// COMPLEXITY: O(1)\nexport const connectProjectSsh = (item) => runCommandWithExitCodes({\n cwd: process.cwd(),\n command: \"ssh\",\n args: buildSshArgs(item)\n}, [0, 130], (exitCode) => new CommandFailedError({ command: \"ssh\", exitCode }));\n// CHANGE: ensure docker compose is up before SSH connection\n// WHY: selected project should auto-start when not running\n// QUOTE(ТЗ): \"Если не поднят то пусть поднимает\"\n// REF: user-request-2026-02-02-select-up\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: up(p) -> ssh(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, CommandFailedError | DockerCommandError | PlatformError, CommandExecutor | FileSystem | Path>\n// INVARIANT: docker compose up runs before ssh\n// COMPLEXITY: O(1)\nexport const connectProjectSshWithUp = (item) => pipe(Effect.log(`Starting docker compose for ${item.displayName} ...`), Effect.zipRight(runDockerComposeUpWithPortCheck(item.projectDir)), Effect.map((template) => ({ ...item, sshPort: template.sshPort })), Effect.tap((updated) => waitForSshReady(updated)), Effect.flatMap((updated) => connectProjectSsh(updated)));\n// CHANGE: show docker compose status for all known docker-git projects\n// WHY: allow checking active containers without switching directories\n// QUOTE(ТЗ): \"как посмотреть какие активны?\"\n// REF: user-request-2026-01-27-status\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in projects: status(p) -> output(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path | CommandExecutor>\n// INVARIANT: each project emits a header before docker compose output\n// COMPLEXITY: O(n) where n = |projects|\nexport const listProjectStatus = Effect.asVoid(withProjectIndexAndSsh((index, sshKey) => forEachProjectStatus(index.configPaths, (status) => pipe(Effect.log(renderProjectStatusHeader(status)), Effect.zipRight(Effect.log(`SSH access: ${buildSshCommand(status.config.template, sshKey)}`)), Effect.zipRight(runDockerComposePsFormatted(status.projectDir).pipe(Effect.map((raw) => parseComposePsOutput(raw)), Effect.map((rows) => formatComposeRows(rows)), Effect.flatMap((text) => Effect.log(text)), Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`docker compose ps failed for ${status.projectDir}: ${renderError(error)}`),\n onSuccess: () => Effect.void\n})))))));\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Duration, Effect, Fiber, Schedule } from \"effect\";\nimport { runDockerComposeDownVolumes, runDockerComposeLogsFollow, runDockerComposeUp, runDockerComposeUpRecreate, runDockerExecExitCode, runDockerInspectContainerBridgeIp, runDockerNetworkConnectBridge } from \"../../shell/docker.js\";\nimport { CloneFailedError } from \"../../shell/errors.js\";\nimport { findSshPrivateKey, resolveAuthorizedKeysPath } from \"../path-helpers.js\";\nimport { buildSshCommand } from \"../projects.js\";\nconst maxPortAttempts = 25;\nconst clonePollInterval = Duration.seconds(1);\nconst cloneDonePath = \"/run/docker-git/clone.done\";\nconst cloneFailPath = \"/run/docker-git/clone.failed\";\nconst logSshAccess = (baseDir, config) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const resolvedAuthorizedKeys = resolveAuthorizedKeysPath(path, baseDir, config.authorizedKeysPath);\n const authExists = yield* _(fs.exists(resolvedAuthorizedKeys));\n const sshKey = yield* _(findSshPrivateKey(fs, path, process.cwd()));\n const sshCommand = buildSshCommand(config, sshKey);\n yield* _(Effect.log(`SSH access: ${sshCommand}`));\n if (!authExists) {\n yield* _(Effect.logWarning(`Authorized keys file missing: ${resolvedAuthorizedKeys} (SSH may fail without a matching key).`));\n }\n});\nconst checkCloneState = (cwd, containerName) => Effect.gen(function* (_) {\n const failed = yield* _(runDockerExecExitCode(cwd, containerName, [\"test\", \"-f\", cloneFailPath]));\n if (failed === 0) {\n return \"failed\";\n }\n const done = yield* _(runDockerExecExitCode(cwd, containerName, [\"test\", \"-f\", cloneDonePath]));\n return done === 0 ? \"done\" : \"pending\";\n});\nconst waitForCloneCompletion = (cwd, config) => Effect.gen(function* (_) {\n const logsFiber = yield* _(runDockerComposeLogsFollow(cwd).pipe(Effect.tapError((error) => Effect.logWarning(`docker compose logs --follow failed: ${error instanceof Error ? error.message : String(error)}`)), Effect.fork));\n const result = yield* _(checkCloneState(cwd, config.containerName).pipe(Effect.repeat(Schedule.addDelay(Schedule.recurUntil((state) => state !== \"pending\"), () => clonePollInterval))));\n yield* _(Fiber.interrupt(logsFiber));\n if (result === \"failed\") {\n return yield* _(Effect.fail(new CloneFailedError({\n repoUrl: config.repoUrl,\n repoRef: config.repoRef,\n targetDir: config.targetDir\n })));\n }\n});\nconst runDockerComposeUpByMode = (resolvedOutDir, force, forceEnv) => Effect.gen(function* (_) {\n if (force) {\n yield* _(Effect.log(\"Force enabled: wiping docker compose volumes (docker compose down -v)...\"));\n yield* _(runDockerComposeDownVolumes(resolvedOutDir));\n yield* _(Effect.log(\"Running: docker compose up -d --build\"));\n yield* _(runDockerComposeUp(resolvedOutDir));\n return;\n }\n if (forceEnv) {\n yield* _(Effect.log(\"Force env enabled: resetting env defaults and recreating containers (volumes preserved)...\"));\n yield* _(runDockerComposeUpRecreate(resolvedOutDir));\n return;\n }\n yield* _(Effect.log(\"Running: docker compose up -d --build\"));\n yield* _(runDockerComposeUp(resolvedOutDir));\n});\nconst ensureContainerBridgeAccess = (resolvedOutDir, containerName) => runDockerInspectContainerBridgeIp(resolvedOutDir, containerName).pipe(Effect.flatMap((bridgeIp) => bridgeIp.length > 0\n ? Effect.void\n : runDockerNetworkConnectBridge(resolvedOutDir, containerName)), Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`Failed to connect ${containerName} to bridge network: ${error instanceof Error ? error.message : String(error)}`),\n onSuccess: () => Effect.void\n}));\nconst ensureBridgeAccess = (resolvedOutDir, projectConfig) => Effect.gen(function* (_) {\n // Make container ports reachable from other (non-compose) containers by IP.\n yield* _(ensureContainerBridgeAccess(resolvedOutDir, projectConfig.containerName));\n if (projectConfig.enableMcpPlaywright) {\n yield* _(ensureContainerBridgeAccess(resolvedOutDir, `${projectConfig.containerName}-browser`));\n }\n});\nexport const runDockerUpIfNeeded = (resolvedOutDir, projectConfig, options) => Effect.gen(function* (_) {\n if (!options.runUp) {\n return;\n }\n yield* _(runDockerComposeUpByMode(resolvedOutDir, options.force, options.forceEnv));\n yield* _(ensureBridgeAccess(resolvedOutDir, projectConfig));\n if (options.waitForClone) {\n yield* _(Effect.log(\"Streaming container logs until clone completes...\"));\n yield* _(waitForCloneCompletion(resolvedOutDir, projectConfig));\n }\n yield* _(Effect.log(\"Docker environment is up\"));\n yield* _(logSshAccess(resolvedOutDir, projectConfig));\n});\nexport const maxSshPortAttempts = maxPortAttempts;\n","import { listProjects, readCloneRequest, runDockerGitClone } from \"@effect-template/lib\"\nimport { Console, Effect, Match, pipe } from \"effect\"\n\n/**\n * Compose the CLI program as a single effect.\n *\n * @returns Effect that either runs docker-git clone or prints usage.\n *\n * @pure false - uses Console output and spawns commands when cloning\n * @effect Console, CommandExecutor, Path\n * @invariant forall args in Argv: clone(args) -> docker_git_invoked(args)\n * @precondition true\n * @postcondition clone(args) -> docker_git_invoked(args); otherwise usage printed\n * @complexity O(build + clone)\n * @throws Never - all errors are typed in the Effect error channel\n */\n// CHANGE: replace greeting demo with deterministic usage text\n// WHY: greeting was scaffolding noise and should not ship in docker-git tooling\n// QUOTE(ТЗ): \"Можешь удалить использование greting ...? Это старый мусор который остался\"\n// REF: user-request-2026-02-06-remove-greeting\n// SOURCE: n/a\n// FORMAT THEOREM: usageText is constant -> deterministic(help)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: usageText does not depend on argv/env\n// COMPLEXITY: O(1)\nconst usageText = [\n \"Usage:\",\n \" pnpm docker-git\",\n \" pnpm clone <repo-url> [ref]\",\n \" pnpm list\",\n \"\",\n \"Notes:\",\n \" - docker-git is the interactive TUI.\",\n \" - clone builds + runs docker-git clone for you.\"\n].join(\"\\n\")\n\n// PURITY: SHELL\n// EFFECT: Effect<void, never, Console>\nconst runHelp = Console.log(usageText)\n\n// CHANGE: route between clone runner and help based on CLI context\n// WHY: allow pnpm run clone <url> while keeping a single entrypoint\n// QUOTE(ТЗ): \"pnpm run clone <url>\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall argv: clone(argv) -> docker_git_invoked(argv)\n// PURITY: SHELL\n// EFFECT: Effect<void, Error, Console | CommandExecutor | Path>\n// INVARIANT: help is printed when clone is not requested\n// COMPLEXITY: O(build + clone)\nconst runDockerGit = pipe(\n readCloneRequest,\n Effect.flatMap((request) =>\n Match.value(request).pipe(\n Match.when({ _tag: \"Clone\" }, ({ args }) => runDockerGitClone(args)),\n Match.when({ _tag: \"None\" }, () => runHelp),\n Match.exhaustive\n )\n )\n)\n\nconst readListFlag = Effect.sync(() => {\n const command = process.argv.slice(2)[0] ?? \"\"\n return command === \"list\" || command === \"ls\"\n})\n\nexport const program = Effect.gen(function*(_) {\n const isList = yield* _(readListFlag)\n if (isList) {\n yield* _(listProjects)\n return\n }\n yield* _(runDockerGit)\n})\n","import { NodeContext, NodeRuntime } from \"@effect/platform-node\"\nimport { Effect, pipe } from \"effect\"\n\nimport { program } from \"./program.js\"\n\n// CHANGE: run the program through the Node platform runtime with its layer\n// WHY: ensure effects execute under the platform runtime with proper teardown/logging behavior\n// QUOTE(TZ): \"\\u0414\\u0430 \\u0434\\u0430\\u0432\\u0430\\u0439 \\u0442\\u0430\\u043a \\u044d\\u0442\\u043e \\u0431\\u043e\\u043b\\u0435\\u0435 \\u043f\\u0440\\u0430\\u0432\\u0438\\u043b\\u044c\\u043d\\u0430\\u044f \\u0440\\u0435\\u0430\\u043b\\u0438\\u0437\\u0430\\u0446\\u0438\\u044f\"\n// REF: user-2025-12-19-platform-node\n// SOURCE: https://effect.website/docs/platform/runtime/ \"runMain helps you execute a main effect with built-in error handling, logging, and signal management.\"\n// FORMAT THEOREM: forall args in Argv: decode(args) = v -> runMain(program)\n// PURITY: SHELL\n// EFFECT: Effect<string, S.ParseError, Console>\n// INVARIANT: program executed with NodeContext.layer\n// COMPLEXITY: O(1)/O(1)\nconst main = pipe(program, Effect.provide(NodeContext.layer))\n\nNodeRuntime.runMain(main)\n"],"names":["process","successExitCode"],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sources":["../../lib/dist/core/clone.js","../../lib/dist/core/strings.js","../../lib/dist/core/repo.js","../../lib/dist/core/domain.js","../../lib/dist/core/parse-errors.js","../../lib/dist/shell/command-runner.js","../../lib/dist/shell/errors.js","../../lib/dist/shell/clone.js","../../lib/dist/shell/paths.js","../../lib/dist/shell/config.js","../../lib/dist/shell/docker.js","../../lib/dist/usecases/env-file.js","../../lib/dist/usecases/path-helpers.js","../../lib/dist/usecases/runtime.js","../../lib/dist/usecases/menu-helpers.js","../../lib/dist/usecases/state-repo/git-commands.js","../../lib/dist/usecases/state-repo/github-auth.js","../../lib/dist/usecases/docker-git-config-search.js","../../lib/dist/usecases/state-repo.js","../../lib/dist/usecases/errors.js","../../lib/dist/usecases/projects-core.js","../../lib/dist/usecases/projects-down.js","../../lib/dist/usecases/projects-list.js","../../lib/dist/usecases/projects-ssh.js","../../lib/dist/usecases/actions/docker-up.js","../../lib/dist/usecases/scrap-chunks.js","../../lib/dist/usecases/scrap-session-manifest.js","../src/app/program.ts","../src/app/main.ts"],"sourcesContent":["const emptyRequest = { _tag: \"None\" };\nconst toCloneRequest = (args) => ({\n _tag: \"Clone\",\n args\n});\n// CHANGE: resolve a clone request from argv + npm lifecycle metadata\n// WHY: support pnpm run clone <url> without requiring \"--\"\n// QUOTE(ТЗ): \"pnpm run clone <url>\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall a,e: resolve(a,e) -> deterministic\n// PURITY: CORE\n// EFFECT: Effect<CloneRequest, never, never>\n// INVARIANT: clone requested only when argv[0] == \"clone\" or npmLifecycleEvent == \"clone\"\n// COMPLEXITY: O(n)\nexport const resolveCloneRequest = (argv, npmLifecycleEvent) => {\n if (npmLifecycleEvent === \"clone\") {\n if (argv.length > 0) {\n const [first, ...rest] = argv;\n return first === \"clone\" ? toCloneRequest(rest) : toCloneRequest(argv);\n }\n return toCloneRequest([]);\n }\n if (argv.length > 0 && argv[0] === \"clone\") {\n return toCloneRequest(argv.slice(1));\n }\n return emptyRequest;\n};\n","export const trimLeftChar = (value, char) => {\n let start = 0;\n while (start < value.length && value[start] === char) {\n start += 1;\n }\n return value.slice(start);\n};\nexport const trimRightChar = (value, char) => {\n let end = value.length;\n while (end > 0 && value[end - 1] === char) {\n end -= 1;\n }\n return value.slice(0, end);\n};\n","import { trimLeftChar, trimRightChar } from \"./strings.js\";\nconst slugify = (value) => {\n const normalized = value\n .trim()\n .toLowerCase()\n .replaceAll(/[^a-z0-9_-]+/g, \"-\")\n .replaceAll(/-+/g, \"-\");\n const withoutLeading = trimLeftChar(normalized, \"-\");\n const cleaned = trimRightChar(withoutLeading, \"-\");\n return cleaned.length > 0 ? cleaned : \"app\";\n};\n// CHANGE: derive a stable repo slug from a repo URL\n// WHY: generate deterministic container/service names per repository\n// QUOTE(ТЗ): \"по факту он должен создавтаь постоянно новый контейнер для нового репозитория\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall url: slug(url) = s -> deterministic(s)\n// PURITY: CORE\n// EFFECT: Effect<string, never, never>\n// INVARIANT: slug is lowercase and non-empty\n// COMPLEXITY: O(n) where n = |url|\nexport const deriveRepoSlug = (repoUrl) => {\n const trimmed = trimRightChar(repoUrl.trim(), \"/\");\n if (trimmed.length === 0) {\n return \"app\";\n }\n const lastSlash = trimmed.lastIndexOf(\"/\");\n const lastColon = trimmed.lastIndexOf(\":\");\n const pivot = Math.max(lastSlash, lastColon);\n const segment = pivot >= 0 ? trimmed.slice(pivot + 1) : trimmed;\n const withoutGit = segment.endsWith(\".git\") ? segment.slice(0, -4) : segment;\n return slugify(withoutGit);\n};\nconst stripGitSuffix = (segment) => segment.endsWith(\".git\") ? segment.slice(0, -4) : segment;\nconst normalizePathParts = (pathPart) => {\n const cleaned = trimLeftChar(pathPart, \"/\");\n if (cleaned.length === 0) {\n return [];\n }\n const rawParts = cleaned.split(\"/\").filter(Boolean);\n return rawParts.map((part, index) => index === rawParts.length - 1 ? stripGitSuffix(part) : part);\n};\nconst extractFromScheme = (trimmed) => {\n const schemeIndex = trimmed.indexOf(\"://\");\n if (schemeIndex === -1) {\n return null;\n }\n const afterScheme = trimmed.slice(schemeIndex + 3);\n const firstSlash = afterScheme.indexOf(\"/\");\n if (firstSlash === -1) {\n return [];\n }\n return normalizePathParts(afterScheme.slice(firstSlash + 1));\n};\nconst extractFromColon = (trimmed) => {\n const colonIndex = trimmed.indexOf(\":\");\n if (colonIndex === -1) {\n return null;\n }\n return normalizePathParts(trimmed.slice(colonIndex + 1));\n};\nconst extractFromSlash = (trimmed) => {\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex === -1) {\n return null;\n }\n return normalizePathParts(trimmed.slice(slashIndex + 1));\n};\nconst extractRepoPathParts = (repoUrl) => {\n const trimmed = trimRightChar(repoUrl.trim(), \"/\");\n if (trimmed.length === 0) {\n return [];\n }\n const fromScheme = extractFromScheme(trimmed);\n if (fromScheme !== null) {\n return fromScheme;\n }\n const fromColon = extractFromColon(trimmed);\n if (fromColon !== null) {\n return fromColon;\n }\n const fromSlash = extractFromSlash(trimmed);\n if (fromSlash !== null) {\n return fromSlash;\n }\n return [stripGitSuffix(trimmed)];\n};\nconst normalizeRepoSegment = (segment, fallback) => {\n const normalized = slugify(segment);\n return normalized.length > 0 ? normalized : fallback;\n};\n// CHANGE: derive stable owner/repo path parts from a repo URL\n// WHY: avoid collisions when orgs have identical repo names\n// QUOTE(ТЗ): \"пути учитывают организацию в которой это лежит\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall url: parts(url) -> deterministic(parts)\n// PURITY: CORE\n// EFFECT: Effect<RepoPathParts, never, never>\n// INVARIANT: path parts are slugified and non-empty\n// COMPLEXITY: O(n) where n = |url|\nexport const deriveRepoPathParts = (repoUrl) => {\n const repoSlug = deriveRepoSlug(repoUrl);\n const rawParts = extractRepoPathParts(repoUrl);\n if (rawParts.length === 0) {\n return { ownerParts: [], repo: repoSlug, pathParts: [repoSlug] };\n }\n const rawRepo = rawParts.at(-1) ?? repoSlug;\n const repo = normalizeRepoSegment(rawRepo, repoSlug);\n const ownerParts = rawParts\n .slice(0, -1)\n .map((part) => normalizeRepoSegment(part, \"org\"))\n .filter((part) => part.length > 0);\n const pathParts = ownerParts.length > 0 ? [...ownerParts, repo] : [repo];\n return { ownerParts, repo, pathParts };\n};\nconst stripQueryHash = (value) => {\n const queryIndex = value.indexOf(\"?\");\n const hashIndex = value.indexOf(\"#\");\n const indices = [queryIndex, hashIndex].filter((index) => index >= 0);\n if (indices.length === 0) {\n return value;\n }\n const cutIndex = Math.min(...indices);\n return value.slice(0, cutIndex);\n};\nconst splitGithubPath = (input) => {\n const trimmed = input.trim();\n const httpsPrefix = \"https://github.com/\";\n const sshPrefix = \"ssh://git@github.com/\";\n const gitPrefix = \"git@github.com:\";\n let rest = null;\n if (trimmed.startsWith(httpsPrefix)) {\n rest = trimmed.slice(httpsPrefix.length);\n }\n else if (trimmed.startsWith(sshPrefix)) {\n rest = trimmed.slice(sshPrefix.length);\n }\n else if (trimmed.startsWith(gitPrefix)) {\n rest = trimmed.slice(gitPrefix.length);\n }\n if (rest === null) {\n return null;\n }\n const cleaned = trimRightChar(stripQueryHash(rest), \"/\");\n if (cleaned.length === 0) {\n return [];\n }\n return cleaned.split(\"/\").filter((part) => part.length > 0);\n};\n// CHANGE: parse GitHub owner/repo from common URL formats\n// WHY: enable auto-fork logic without relying on slugified paths\n// QUOTE(ТЗ): \"Сразу на issues и он бы делал форк репы если это надо\"\n// REF: user-request-2026-02-05-issues-fork\n// SOURCE: n/a\n// FORMAT THEOREM: ∀u: github(u) → repo(u) = {owner, repo}\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: returns null for non-GitHub inputs\n// COMPLEXITY: O(n) where n = |input|\nexport const parseGithubRepoUrl = (input) => {\n const parts = splitGithubPath(input);\n if (!parts || parts.length < 2) {\n return null;\n }\n const owner = parts[0]?.trim();\n const repoRaw = parts[1]?.trim();\n if (!owner || !repoRaw) {\n return null;\n }\n const repo = stripGitSuffix(repoRaw);\n return { owner, repo };\n};\nconst readGithubPart = (value) => {\n const trimmed = value?.trim() ?? \"\";\n return trimmed.length > 0 ? trimmed : null;\n};\nconst parseGithubRefParts = (input) => {\n const parts = splitGithubPath(input);\n if (!parts || parts.length < 4) {\n return null;\n }\n const owner = readGithubPart(parts[0]);\n const repoRaw = readGithubPart(parts[1]);\n const markerRaw = readGithubPart(parts[2]);\n const ref = readGithubPart(parts[3]);\n if (!owner || !repoRaw || !markerRaw || !ref) {\n return null;\n }\n return { owner, repoRaw, marker: markerRaw.toLowerCase(), ref };\n};\nconst parseGithubPrUrl = (input) => {\n const parsed = parseGithubRefParts(input);\n if (!parsed || parsed.marker !== \"pull\") {\n return null;\n }\n const repo = stripGitSuffix(parsed.repoRaw);\n const workspaceSuffix = `pr-${slugify(parsed.ref)}`;\n return {\n repoUrl: `https://github.com/${parsed.owner}/${repo}.git`,\n repoRef: `refs/pull/${parsed.ref}/head`,\n workspaceSuffix\n };\n};\n// CHANGE: normalize GitHub tree/blob URLs into repo + ref\n// WHY: allow docker-git clone to accept branch URLs like /tree/<branch>\n// QUOTE(ТЗ): \"вызови --force на https://github.com/agiens/crm/tree/vova-fork\"\n// REF: user-request-2026-02-10-github-tree-url\n// SOURCE: n/a\n// FORMAT THEOREM: ∀u: tree(u) → repo(u)=git(u) ∧ ref(u)=branch(u)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: ignores additional path segments after the ref\n// COMPLEXITY: O(n) where n = |url|\nconst parseGithubTreeUrl = (input) => {\n const parsed = parseGithubRefParts(input);\n if (!parsed || (parsed.marker !== \"tree\" && parsed.marker !== \"blob\")) {\n return null;\n }\n const repo = stripGitSuffix(parsed.repoRaw);\n return { repoUrl: `https://github.com/${parsed.owner}/${repo}.git`, repoRef: parsed.ref };\n};\n// CHANGE: normalize GitHub issue URLs into repo URLs\n// WHY: allow docker-git clone to accept issue links directly\n// QUOTE(ТЗ): \"Сразу на issues\"\n// REF: user-request-2026-02-05-issues\n// SOURCE: n/a\n// FORMAT THEOREM: ∀u: issue(u) → repo(u)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: issue URL yields repoUrl + deterministic issue branch\n// COMPLEXITY: O(n) where n = |url|\nconst parseGithubIssueUrl = (input) => {\n const parsed = parseGithubRefParts(input);\n if (!parsed || parsed.marker !== \"issues\") {\n return null;\n }\n const repo = stripGitSuffix(parsed.repoRaw);\n const workspaceSuffix = `issue-${slugify(parsed.ref)}`;\n return {\n repoUrl: `https://github.com/${parsed.owner}/${repo}.git`,\n repoRef: workspaceSuffix,\n workspaceSuffix\n };\n};\n// CHANGE: normalize repo input and PR/issue URLs into repo + ref\n// WHY: allow cloning GitHub PR links and issue links directly\n// QUOTE(ТЗ): \"клонировть по cсылке на PR\" | \"Сразу на issues\"\n// REF: user-request-2026-01-28-pr | user-request-2026-02-05-issues\n// SOURCE: n/a\n// FORMAT THEOREM: forall url: resolve(url) -> deterministic(url, ref)\n// PURITY: CORE\n// EFFECT: Effect<ResolvedRepoInput, never, never>\n// INVARIANT: PR URL yields repoUrl + refs/pull/<id>/head\n// COMPLEXITY: O(n) where n = |url|\nexport const resolveRepoInput = (repoUrl) => parseGithubPrUrl(repoUrl)\n ?? parseGithubTreeUrl(repoUrl)\n ?? parseGithubIssueUrl(repoUrl)\n ?? { repoUrl: repoUrl.trim() };\n","export { parseMenuSelection } from \"./menu.js\";\nexport { deriveRepoPathParts, deriveRepoSlug, resolveRepoInput } from \"./repo.js\";\nexport const defaultTemplateConfig = {\n containerName: \"dev-ssh\",\n serviceName: \"dev\",\n sshUser: \"dev\",\n sshPort: 2222,\n repoRef: \"main\",\n targetDir: \"/home/dev/app\",\n volumeName: \"dev_home\",\n dockerGitPath: \"./.docker-git\",\n authorizedKeysPath: \"./.docker-git/authorized_keys\",\n envGlobalPath: \"./.docker-git/.orch/env/global.env\",\n envProjectPath: \"./.orch/env/project.env\",\n codexAuthPath: \"./.docker-git/.orch/auth/codex\",\n codexSharedAuthPath: \"./.docker-git/.orch/auth/codex\",\n codexHome: \"/home/dev/.codex\",\n enableMcpPlaywright: false,\n pnpmVersion: \"10.27.0\"\n};\n","import { Match } from \"effect\";\n// CHANGE: normalize parse errors into deterministic messages\n// WHY: reuse parse error formatting across CLI and server flows\n// QUOTE(ТЗ): \"ошибки должны быть описывающими\"\n// REF: user-request-2026-02-02-cli-split\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: format(e) = s -> deterministic(s)\n// PURITY: CORE\n// EFFECT: Effect<string, never, never>\n// INVARIANT: each ParseError maps to exactly one message\n// COMPLEXITY: O(1)\nexport const formatParseError = (error) => Match.value(error).pipe(Match.when({ _tag: \"UnknownCommand\" }, ({ command }) => `Unknown command: ${command}`), Match.when({ _tag: \"UnknownOption\" }, ({ option }) => `Unknown option: ${option}`), Match.when({ _tag: \"MissingOptionValue\" }, ({ option }) => `Missing value for option: ${option}`), Match.when({ _tag: \"MissingRequiredOption\" }, ({ option }) => `Missing required option: ${option}`), Match.when({ _tag: \"InvalidOption\" }, ({ option, reason }) => `Invalid option ${option}: ${reason}`), Match.when({ _tag: \"UnexpectedArgument\" }, ({ value }) => `Unexpected argument: ${value}`), Match.exhaustive);\n","import * as Command from \"@effect/platform/Command\";\nimport * as CommandExecutor from \"@effect/platform/CommandExecutor\";\nimport { Effect, pipe } from \"effect\";\nimport * as Chunk from \"effect/Chunk\";\nimport * as Stream from \"effect/Stream\";\nconst buildCommand = (spec, stdout, stderr, stdin = \"pipe\") => pipe(Command.make(spec.command, ...spec.args), Command.workingDirectory(spec.cwd), spec.env ? Command.env(spec.env) : (value) => value, Command.stdin(stdin), Command.stdout(stdout), Command.stderr(stderr));\nconst ensureExitCode = (exitCode, okExitCodes, onFailure) => okExitCodes.includes(exitCode)\n ? Effect.succeed(exitCode)\n : Effect.fail(onFailure(exitCode));\nexport const runCommandWithExitCodes = (spec, okExitCodes, onFailure) => Effect.gen(function* (_) {\n const exitCode = yield* _(Command.exitCode(buildCommand(spec, \"inherit\", \"inherit\", \"inherit\")));\n const numericExitCode = Number(exitCode);\n yield* _(ensureExitCode(numericExitCode, okExitCodes, onFailure));\n});\n// CHANGE: run a command and return the exit code\n// WHY: enable status checks without throwing on non-zero exits\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall cmd: exitCode(cmd) = n\n// PURITY: SHELL\n// EFFECT: Effect<number, PlatformError, CommandExecutor>\n// INVARIANT: stdout/stderr are suppressed for status checks\n// COMPLEXITY: O(command)\nexport const runCommandExitCode = (spec) => Effect.map(Command.exitCode(buildCommand(spec, \"pipe\", \"pipe\", \"inherit\")), Number);\nconst collectUint8Array = (chunks) => Chunk.reduce(chunks, new Uint8Array(), (acc, curr) => {\n const next = new Uint8Array(acc.length + curr.length);\n next.set(acc);\n next.set(curr, acc.length);\n return next;\n});\n// CHANGE: run a command and capture stdout\n// WHY: allow auth flows to retrieve tokens from CLI tools\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall cmd: capture(cmd) -> stdout(cmd)\n// PURITY: SHELL\n// EFFECT: Effect<string, E | PlatformError, CommandExecutor>\n// INVARIANT: stderr is captured but ignored for output\n// COMPLEXITY: O(command)\nexport const runCommandCapture = (spec, okExitCodes, onFailure) => Effect.scoped(Effect.gen(function* (_) {\n const executor = yield* _(CommandExecutor.CommandExecutor);\n const process = yield* _(executor.start(buildCommand(spec, \"pipe\", \"pipe\", \"pipe\")));\n const bytes = yield* _(pipe(process.stdout, Stream.runCollect, Effect.map((chunks) => collectUint8Array(chunks))));\n const exitCode = yield* _(process.exitCode);\n yield* _(ensureExitCode(Number(exitCode), okExitCodes, onFailure));\n return new TextDecoder(\"utf-8\").decode(bytes);\n}));\n","import { Data } from \"effect\";\nexport class FileExistsError extends Data.TaggedError(\"FileExistsError\") {\n}\nexport class ConfigNotFoundError extends Data.TaggedError(\"ConfigNotFoundError\") {\n}\nexport class ConfigDecodeError extends Data.TaggedError(\"ConfigDecodeError\") {\n}\nexport class InputCancelledError extends Data.TaggedError(\"InputCancelledError\") {\n}\nexport class InputReadError extends Data.TaggedError(\"InputReadError\") {\n}\nexport class DockerCommandError extends Data.TaggedError(\"DockerCommandError\") {\n}\nexport class DockerAccessError extends Data.TaggedError(\"DockerAccessError\") {\n}\nexport class CloneFailedError extends Data.TaggedError(\"CloneFailedError\") {\n}\nexport class PortProbeError extends Data.TaggedError(\"PortProbeError\") {\n}\nexport class CommandFailedError extends Data.TaggedError(\"CommandFailedError\") {\n}\nexport class AuthError extends Data.TaggedError(\"AuthError\") {\n}\nexport class ScrapArchiveNotFoundError extends Data.TaggedError(\"ScrapArchiveNotFoundError\") {\n}\nexport class ScrapArchiveInvalidError extends Data.TaggedError(\"ScrapArchiveInvalidError\") {\n}\nexport class ScrapTargetDirUnsupportedError extends Data.TaggedError(\"ScrapTargetDirUnsupportedError\") {\n}\nexport class ScrapWipeRefusedError extends Data.TaggedError(\"ScrapWipeRefusedError\") {\n}\n","import { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\nimport { resolveCloneRequest } from \"../core/clone.js\";\nimport { runCommandWithExitCodes } from \"./command-runner.js\";\nimport { CommandFailedError } from \"./errors.js\";\nconst successExitCode = Number(ExitCode(0));\n// CHANGE: read clone request from process argv and npm lifecycle metadata\n// WHY: allow pnpm run clone <url> to work without \"--\"\n// QUOTE(ТЗ): \"pnpm run clone <url>\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall env: read(env) -> deterministic(request)\n// PURITY: SHELL\n// EFFECT: Effect<CloneRequest, never, never>\n// INVARIANT: only argv/env are read\n// COMPLEXITY: O(n)\nexport const readCloneRequest = Effect.sync(() => resolveCloneRequest(process.argv.slice(2), process.env[\"npm_lifecycle_event\"]));\n// CHANGE: run docker-git clone by building and invoking its CLI\n// WHY: reuse docker-git without mutating its codebase\n// QUOTE(ТЗ): \"docker git мы никак не изменяем\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall args: build && run(args) -> docker_git_invoked(args)\n// PURITY: SHELL\n// EFFECT: Effect<void, CommandFailedError | PlatformError, CommandExecutor | Path>\n// INVARIANT: build runs before clone command\n// COMPLEXITY: O(build + clone)\nexport const runDockerGitClone = (args) => Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const workspaceRoot = process.cwd();\n const appRoot = path.join(workspaceRoot, \"packages\", \"app\");\n const dockerGitCli = path.join(appRoot, \"dist\", \"src\", \"docker-git\", \"main.js\");\n const buildLabel = `pnpm -C ${appRoot} build:docker-git`;\n const cloneLabel = `node ${dockerGitCli} clone`;\n yield* _(runCommandWithExitCodes({ cwd: workspaceRoot, command: \"pnpm\", args: [\"-C\", appRoot, \"build:docker-git\"] }, [successExitCode], (exitCode) => new CommandFailedError({ command: buildLabel, exitCode })));\n yield* _(runCommandWithExitCodes({ cwd: workspaceRoot, command: \"node\", args: [dockerGitCli, \"clone\", ...args] }, [successExitCode], (exitCode) => new CommandFailedError({ command: cloneLabel, exitCode })));\n});\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\nexport const resolveBaseDir = (baseDir) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const resolved = path.resolve(baseDir);\n return { fs, path, resolved };\n});\n","import * as ParseResult from \"@effect/schema/ParseResult\";\nimport * as Schema from \"@effect/schema/Schema\";\nimport * as TreeFormatter from \"@effect/schema/TreeFormatter\";\nimport { Effect, Either } from \"effect\";\nimport { defaultTemplateConfig } from \"../core/domain.js\";\nimport { ConfigDecodeError, ConfigNotFoundError } from \"./errors.js\";\nimport { resolveBaseDir } from \"./paths.js\";\nconst TemplateConfigSchema = Schema.Struct({\n containerName: Schema.String,\n serviceName: Schema.String,\n sshUser: Schema.String,\n sshPort: Schema.Number.pipe(Schema.int()),\n repoUrl: Schema.String,\n repoRef: Schema.String,\n targetDir: Schema.String,\n volumeName: Schema.String,\n dockerGitPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.dockerGitPath\n }),\n authorizedKeysPath: Schema.String,\n envGlobalPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.envGlobalPath\n }),\n envProjectPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.envProjectPath\n }),\n codexAuthPath: Schema.String,\n codexSharedAuthPath: Schema.optionalWith(Schema.String, {\n default: () => defaultTemplateConfig.codexSharedAuthPath\n }),\n codexHome: Schema.String,\n enableMcpPlaywright: Schema.optionalWith(Schema.Boolean, {\n default: () => defaultTemplateConfig.enableMcpPlaywright\n }),\n pnpmVersion: Schema.String\n});\nconst ProjectConfigSchema = Schema.Struct({\n schemaVersion: Schema.Literal(1),\n template: TemplateConfigSchema\n});\nconst ProjectConfigJsonSchema = Schema.parseJson(ProjectConfigSchema);\nconst decodeProjectConfig = (path, input) => Either.match(ParseResult.decodeUnknownEither(ProjectConfigJsonSchema)(input), {\n onLeft: (issue) => Effect.fail(new ConfigDecodeError({\n path,\n message: TreeFormatter.formatIssueSync(issue)\n })),\n onRight: (value) => Effect.succeed(value)\n});\n// CHANGE: read and decode docker-git.json from disk\n// WHY: keep unknown inputs at the boundary and validate with schema\n// QUOTE(ТЗ): \"интерфейс в котором можно авторизировать все что мы хотим иметь\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: decode(read(p)) = cfg -> cfg.schemaVersion = 1\n// PURITY: SHELL\n// EFFECT: Effect<ProjectConfig, ConfigNotFoundError | ConfigDecodeError | PlatformError, FileSystem | Path>\n// INVARIANT: unknown input never leaks past this boundary\n// COMPLEXITY: O(n) where n = |file|\nexport const readProjectConfig = (baseDir) => Effect.gen(function* (_) {\n const { fs, path, resolved } = yield* _(resolveBaseDir(baseDir));\n const configPath = path.join(resolved, \"docker-git.json\");\n const exists = yield* _(fs.exists(configPath));\n if (!exists) {\n return yield* _(Effect.fail(new ConfigNotFoundError({ path: configPath })));\n }\n const contents = yield* _(fs.readFileString(configPath));\n return yield* _(decodeProjectConfig(configPath, contents));\n});\n","import * as Command from \"@effect/platform/Command\";\nimport * as CommandExecutor from \"@effect/platform/CommandExecutor\";\nimport { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport { Effect, pipe } from \"effect\";\nimport * as Chunk from \"effect/Chunk\";\nimport * as Stream from \"effect/Stream\";\nimport { runCommandCapture, runCommandWithExitCodes } from \"./command-runner.js\";\nimport { CommandFailedError, DockerAccessError, DockerCommandError } from \"./errors.js\";\nconst composeSpec = (cwd, args) => ({\n cwd,\n command: \"docker\",\n args: [\"compose\", \"--ansi\", \"never\", \"--progress\", \"plain\", ...args]\n});\nconst parseInspectNetworkEntry = (line) => {\n const idx = line.indexOf(\"=\");\n if (idx <= 0) {\n return [];\n }\n const network = line.slice(0, idx).trim();\n const ip = line.slice(idx + 1).trim();\n if (network.length === 0 || ip.length === 0) {\n return [];\n }\n const entry = [network, ip];\n return [entry];\n};\nconst collectUint8Array = (chunks) => Chunk.reduce(chunks, new Uint8Array(), (acc, curr) => {\n const next = new Uint8Array(acc.length + curr.length);\n next.set(acc);\n next.set(curr, acc.length);\n return next;\n});\nconst permissionDeniedPattern = /permission denied/i;\n// CHANGE: classify docker daemon access failure into deterministic typed reasons\n// WHY: allow callers to render actionable recovery guidance for socket permission issues\n// QUOTE(ТЗ): \"docker-git handles Docker socket permission problems predictably\"\n// REF: issue-11\n// SOURCE: n/a\n// FORMAT THEOREM: ∀m: classify(m) ∈ {\"PermissionDenied\",\"DaemonUnavailable\"}\n// PURITY: CORE\n// EFFECT: Effect<DockerAccessIssue, never, never>\n// INVARIANT: classification is stable for equal input\n// COMPLEXITY: O(|m|)\nexport const classifyDockerAccessIssue = (message) => permissionDeniedPattern.test(message) ? \"PermissionDenied\" : \"DaemonUnavailable\";\n// CHANGE: verify docker daemon access before compose/auth flows\n// WHY: fail fast on socket permission errors instead of cascading into opaque command failures\n// QUOTE(ТЗ): \"permission denied to /var/run/docker.sock\"\n// REF: issue-11\n// SOURCE: n/a\n// FORMAT THEOREM: ∀cwd: access(cwd)=ok ∨ DockerAccessError\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerAccessError | PlatformError, CommandExecutor>\n// INVARIANT: non-zero docker info exit always maps to DockerAccessError\n// COMPLEXITY: O(command)\nexport const ensureDockerDaemonAccess = (cwd) => Effect.scoped(Effect.gen(function* (_) {\n const executor = yield* _(CommandExecutor.CommandExecutor);\n const process = yield* _(executor.start(pipe(Command.make(\"docker\", \"info\"), Command.workingDirectory(cwd), Command.stdin(\"pipe\"), Command.stdout(\"pipe\"), Command.stderr(\"pipe\"))));\n const stderrBytes = yield* _(pipe(process.stderr, Stream.runCollect, Effect.map((chunks) => collectUint8Array(chunks))));\n const exitCode = Number(yield* _(process.exitCode));\n if (exitCode === 0) {\n return;\n }\n const stderr = new TextDecoder(\"utf-8\").decode(stderrBytes).trim();\n const details = stderr.length > 0 ? stderr : `docker info failed with exit code ${exitCode}`;\n return yield* _(Effect.fail(new DockerAccessError({\n issue: classifyDockerAccessIssue(details),\n details\n })));\n}));\nconst runCompose = (cwd, args, okExitCodes) => runCommandWithExitCodes(composeSpec(cwd, args), okExitCodes, (exitCode) => new DockerCommandError({ exitCode }));\nconst runComposeCapture = (cwd, args, okExitCodes) => runCommandCapture(composeSpec(cwd, args), okExitCodes, (exitCode) => new DockerCommandError({ exitCode }));\n// CHANGE: run docker compose up -d --build in the target directory\n// WHY: provide a controlled shell effect for image creation\n// QUOTE(ТЗ): \"создавать докер образы\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) = 0 -> image_built(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeUp = (cwd) => runCompose(cwd, [\"up\", \"-d\", \"--build\"], [Number(ExitCode(0))]);\nexport const dockerComposeUpRecreateArgs = [\n \"up\",\n \"-d\",\n \"--build\",\n \"--force-recreate\"\n];\n// CHANGE: recreate running containers and refresh images when needed\n// WHY: apply env/template updates while preserving workspace volumes\n// QUOTE(ТЗ): \"сбросит только окружение\"\n// REF: user-request-2026-02-11-force-env\n// SOURCE: n/a\n// FORMAT THEOREM: ∀dir: up_force_recreate(dir) → recreated(containers(dir)) ∧ preserved(volumes(dir)) ∧ updated(images(dir))\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: may rebuild images but does not remove volumes\n// COMPLEXITY: O(command)\nexport const runDockerComposeUpRecreate = (cwd) => runCompose(cwd, dockerComposeUpRecreateArgs, [Number(ExitCode(0))]);\n// CHANGE: run docker compose down in the target directory\n// WHY: allow stopping managed containers from the CLI/menu\n// QUOTE(ТЗ): \"Могу удалить / Отключить\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) = 0 -> containers_stopped(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeDown = (cwd) => runCompose(cwd, [\"down\"], [Number(ExitCode(0))]);\n// CHANGE: run docker compose down -v in the target directory\n// WHY: allow a truly fresh environment by wiping the named volumes (e.g. /home/dev)\n// QUOTE(ТЗ): \"контейнер полностью должен же очищаться при --force\"\n// REF: user-request-2026-02-07-force-wipe-volumes\n// SOURCE: n/a\n// FORMAT THEOREM: ∀dir: down_v(dir) → removed(volumes(dir))\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: removes only resources within the compose project (containers, networks, volumes)\n// COMPLEXITY: O(command)\nexport const runDockerComposeDownVolumes = (cwd) => runCompose(cwd, [\"down\", \"-v\"], [Number(ExitCode(0))]);\n// CHANGE: recreate docker compose environment in the target directory\n// WHY: allow a clean rebuild of the container from the UI\n// QUOTE(ТЗ): \"дропнул контейнер и заново его создал\"\n// REF: user-request-2026-01-13\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: down(dir) && up(dir) -> recreated(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: down completes before up starts\n// COMPLEXITY: O(command)\nexport const runDockerComposeRecreate = (cwd) => pipe(runDockerComposeDown(cwd), Effect.zipRight(runDockerComposeUp(cwd)));\n// CHANGE: run docker compose ps in the target directory\n// WHY: expose runtime status in the interactive menu\n// QUOTE(ТЗ): \"вижу всю инфу по ним\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) = 0 -> status_listed(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposePs = (cwd) => runCompose(cwd, [\"ps\"], [Number(ExitCode(0))]);\n// CHANGE: capture docker compose ps output in a parseable format\n// WHY: allow structured, readable status output for CLI\n// QUOTE(ТЗ): \"информация отображалиась удобно\"\n// REF: user-request-2026-01-28\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: ps_fmt(dir) -> tabbed_string\n// PURITY: SHELL\n// EFFECT: Effect<string, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: output is tab-delimited columns from docker compose ps\n// COMPLEXITY: O(command)\nexport const runDockerComposePsFormatted = (cwd) => runComposeCapture(cwd, [\"ps\", \"--format\", \"{{.Name}}\\t{{.Status}}\\t{{.Ports}}\\t{{.Image}}\"], [Number(ExitCode(0))]);\n// CHANGE: run docker compose logs in the target directory\n// WHY: allow quick inspection of container output without leaving the menu\n// QUOTE(ТЗ): \"вижу всю инфу по ним\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: exitCode(cmd(dir)) in {0,130} -> logs_shown(dir)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeLogs = (cwd) => runCompose(cwd, [\"logs\", \"--tail\", \"200\"], [Number(ExitCode(0)), 130]);\n// CHANGE: stream docker compose logs until interrupted\n// WHY: allow synchronous clone flow to surface container output\n// QUOTE(ТЗ): \"должно работать синхронно отображая весь процесс\"\n// REF: user-request-2026-01-28\n// SOURCE: n/a\n// FORMAT THEOREM: forall dir: logs_follow(dir) -> stdout(stream)\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: command output is inherited from the parent process\n// COMPLEXITY: O(command)\nexport const runDockerComposeLogsFollow = (cwd) => runCompose(cwd, [\"logs\", \"--follow\", \"--tail\", \"0\"], [Number(ExitCode(0)), 130]);\n// CHANGE: run docker exec and return its exit code\n// WHY: allow polling for clone completion markers inside the container\n// QUOTE(ТЗ): \"весь процесс от и до\"\n// REF: user-request-2026-01-28\n// SOURCE: n/a\n// FORMAT THEOREM: forall cmd: exitCode(docker exec cmd) = n -> deterministic(n)\n// PURITY: SHELL\n// EFFECT: Effect<number, PlatformError, CommandExecutor>\n// INVARIANT: stdout/stderr are suppressed for polling commands\n// COMPLEXITY: O(command)\nexport const runDockerExecExitCode = (cwd, containerName, args) => Effect.gen(function* (_) {\n const command = pipe(Command.make(\"docker\", \"exec\", containerName, ...args), Command.workingDirectory(cwd), Command.stdout(\"pipe\"), Command.stderr(\"pipe\"));\n const exitCode = yield* _(Command.exitCode(command));\n return Number(exitCode);\n});\n// CHANGE: inspect container IP address\n// WHY: enable per-container DNS mapping on the host\n// QUOTE(ТЗ): \"У каждого контейнера свой IP т.е свой домен\"\n// REF: user-request-2026-01-30-dns\n// SOURCE: n/a\n// FORMAT THEOREM: forall c: inspect(c) -> ip(c)\n// PURITY: SHELL\n// EFFECT: Effect<string, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: returns empty string when not available\n// COMPLEXITY: O(command)\nexport const runDockerInspectContainerIp = (cwd, containerName) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\n \"inspect\",\n \"-f\",\n // Prefer the built-in `bridge` network IP when present so the printed IP\n // works from \"external\" containers that default to `bridge`.\n // Example output:\n // bridge=172.17.0.4\n // <project>_dg-<repo>-net=192.168.64.3\n String.raw `{{range $k,$v := .NetworkSettings.Networks}}{{printf \"%s=%s\\n\" $k $v.IPAddress}}{{end}}`,\n containerName\n ]\n}, [Number(ExitCode(0))], (exitCode) => new DockerCommandError({ exitCode })), Effect.map((output) => {\n const lines = output\n .trim()\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const entries = lines.flatMap((line) => parseInspectNetworkEntry(line));\n if (entries.length === 0) {\n return \"\";\n }\n const map = new Map(entries);\n return map.get(\"bridge\") ?? entries[0][1];\n}));\n// CHANGE: inspect the container IP address on the default `bridge` network\n// WHY: allow callers to decide whether `docker network connect bridge` is needed\n// QUOTE(ТЗ): \"подключиться с внешнего контейнера\"\n// REF: user-request-2026-02-10-bridge-ip\n// SOURCE: n/a\n// FORMAT THEOREM: ∀c: bridge(c) → ip_bridge(c) ≠ \"\"\n// PURITY: SHELL\n// EFFECT: Effect<string, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: returns \"\" when the container is not connected to `bridge`\n// COMPLEXITY: O(command)\nexport const runDockerInspectContainerBridgeIp = (cwd, containerName) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\n \"inspect\",\n \"-f\",\n \"{{with (index .NetworkSettings.Networks \\\"bridge\\\")}}{{.IPAddress}}{{end}}\",\n containerName\n ]\n}, [Number(ExitCode(0))], (exitCode) => new DockerCommandError({ exitCode })), Effect.map((output) => output.trim()));\n// CHANGE: connect an existing container to the default `bridge` network\n// WHY: allow \"external\" containers (which default to `bridge`) to reach services by container IP\n// QUOTE(ТЗ): \"Всё что запущено в докере должно быть публично наружу\"\n// REF: user-request-2026-02-10-public-ports\n// SOURCE: n/a\n// FORMAT THEOREM: ∀c: up(c) → reachable(bridge_ip(c), ports(c))\n// PURITY: SHELL\n// EFFECT: Effect<void, DockerCommandError | PlatformError, CommandExecutor>\n// INVARIANT: does not fail the overall flow when already connected (handled by caller)\n// COMPLEXITY: O(command)\nexport const runDockerNetworkConnectBridge = (cwd, containerName) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\"network\", \"connect\", \"bridge\", containerName]\n}, [Number(ExitCode(0))], (exitCode) => new DockerCommandError({ exitCode })), Effect.asVoid);\n// CHANGE: list names of running Docker containers\n// WHY: support TUI filtering (e.g. stop only running docker-git containers)\n// QUOTE(ТЗ): \"Если я выбираю остановку контейнера значит он мне должен показывать контейнеры которые запущены\"\n// REF: user-request-2026-02-07-stop-only-running\n// SOURCE: n/a\n// FORMAT THEOREM: forall c: c in ps -> running(c)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<string>, CommandFailedError | PlatformError, CommandExecutor>\n// INVARIANT: result contains only non-empty container names\n// COMPLEXITY: O(command)\nexport const runDockerPsNames = (cwd) => pipe(runCommandCapture({\n cwd,\n command: \"docker\",\n args: [\"ps\", \"--format\", \"{{.Names}}\"]\n}, [Number(ExitCode(0))], (exitCode) => new CommandFailedError({ command: \"docker ps\", exitCode })), Effect.map((output) => output\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)));\n","import { Effect } from \"effect\";\nconst splitLines = (input) => input.replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\\n\").split(\"\\n\");\nconst joinLines = (lines) => lines.join(\"\\n\");\nconst normalizeEnvText = (input) => {\n const normalized = joinLines(splitLines(input));\n return normalized.endsWith(\"\\n\") ? normalized : `${normalized}\\n`;\n};\nconst isAlpha = (char) => {\n const code = char.codePointAt(0) ?? 0;\n return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);\n};\nconst isDigit = (char) => {\n const code = char.codePointAt(0) ?? 0;\n return code >= 48 && code <= 57;\n};\nconst isValidFirstChar = (char) => isAlpha(char) || char === \"_\";\nconst isValidEnvChar = (char) => isAlpha(char) || isDigit(char) || char === \"_\";\nconst hasOnlyValidChars = (value) => {\n for (const char of value) {\n if (!isValidEnvChar(char)) {\n return false;\n }\n }\n return true;\n};\nconst isEnvKey = (value) => {\n if (value.length === 0) {\n return false;\n }\n const first = value[0] ?? \"\";\n if (!isValidFirstChar(first)) {\n return false;\n }\n return hasOnlyValidChars(value.slice(1));\n};\nconst parseEnvLine = (line) => {\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed.startsWith(\"#\")) {\n return null;\n }\n const raw = trimmed.startsWith(\"export \") ? trimmed.slice(\"export \".length).trimStart() : trimmed;\n const eqIndex = raw.indexOf(\"=\");\n if (eqIndex <= 0) {\n return null;\n }\n const key = raw.slice(0, eqIndex).trim();\n if (!isEnvKey(key)) {\n return null;\n }\n const value = raw.slice(eqIndex + 1).trim();\n return { key, value };\n};\n// CHANGE: parse env file contents into key/value entries\n// WHY: allow updating shared auth env deterministically\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall t: parse(t) -> entries(t)\n// PURITY: CORE\n// INVARIANT: only valid KEY=VALUE lines are emitted\n// COMPLEXITY: O(n) where n = |lines|\nexport const parseEnvEntries = (input) => {\n const entries = [];\n for (const line of splitLines(input)) {\n const parsed = parseEnvLine(line);\n if (parsed) {\n entries.push(parsed);\n }\n }\n return entries;\n};\n// CHANGE: upsert a key in env contents\n// WHY: update tokens without manual edits\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall k,v: upsert(k,v) -> env(k)=v\n// PURITY: CORE\n// INVARIANT: env ends with newline\n// COMPLEXITY: O(n) where n = |lines|\nexport const upsertEnvKey = (input, key, value) => {\n const sanitized = normalizeEnvText(input);\n const lines = splitLines(sanitized);\n const trimmedKey = key.trim();\n const cleaned = trimmedKey.length === 0 ? lines : lines.filter((line) => {\n const parsed = parseEnvLine(line);\n return parsed ? parsed.key !== trimmedKey : true;\n });\n if (trimmedKey.length === 0 || value.trim().length === 0) {\n return normalizeEnvText(joinLines(cleaned));\n }\n return normalizeEnvText(joinLines([...cleaned, `${trimmedKey}=${value}`]));\n};\n// CHANGE: remove a key from env contents\n// WHY: allow token revocation\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall k: remove(k) -> !env(k)\n// PURITY: CORE\n// INVARIANT: env ends with newline\n// COMPLEXITY: O(n) where n = |lines|\nexport const removeEnvKey = (input, key) => upsertEnvKey(input, key, \"\");\nexport const defaultEnvContents = \"# docker-git env\\n# KEY=value\\n\";\n// CHANGE: ensure env file exists\n// WHY: persist auth tokens in a stable file\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: ensure(p) -> exists(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path>\n// INVARIANT: parent directories are created\n// COMPLEXITY: O(1)\nexport const ensureEnvFile = (fs, path, envPath) => Effect.gen(function* (_) {\n const exists = yield* _(fs.exists(envPath));\n if (exists) {\n return;\n }\n yield* _(fs.makeDirectory(path.dirname(envPath), { recursive: true }));\n yield* _(fs.writeFileString(envPath, defaultEnvContents));\n});\n// CHANGE: read env file contents\n// WHY: list and update stored tokens\n// QUOTE(ТЗ): \"система авторизации\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: read(p) -> contents(p)\n// PURITY: SHELL\n// EFFECT: Effect<string, PlatformError, FileSystem>\n// INVARIANT: returns default contents for missing/invalid file\n// COMPLEXITY: O(n) where n = |file|\nexport const readEnvText = (fs, envPath) => Effect.gen(function* (_) {\n const exists = yield* _(fs.exists(envPath));\n if (!exists) {\n return defaultEnvContents;\n }\n const info = yield* _(fs.stat(envPath));\n if (info.type !== \"File\") {\n return defaultEnvContents;\n }\n return yield* _(fs.readFileString(envPath));\n});\n","import { Effect } from \"effect\";\nexport const resolveAuthorizedKeysPath = (path, baseDir, authorizedKeysPath) => path.isAbsolute(authorizedKeysPath)\n ? authorizedKeysPath\n : path.resolve(baseDir, authorizedKeysPath);\nconst resolveHomeDir = () => {\n const raw = process.env[\"HOME\"] ?? process.env[\"USERPROFILE\"];\n const home = raw?.trim() ?? \"\";\n return home.length > 0 ? home : null;\n};\nconst expandHome = (value, home) => {\n if (home === null) {\n return value;\n }\n if (value === \"~\") {\n return home;\n }\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return `${home}${value.slice(1)}`;\n }\n return value;\n};\nconst trimTrailingSlash = (value) => {\n let end = value.length;\n while (end > 0) {\n const char = value[end - 1];\n if (char !== \"/\" && char !== \"\\\\\") {\n break;\n }\n end -= 1;\n }\n return value.slice(0, end);\n};\nexport const defaultProjectsRoot = (cwd) => {\n const home = resolveHomeDir();\n const explicit = process.env[\"DOCKER_GIT_PROJECTS_ROOT\"]?.trim();\n if (explicit && explicit.length > 0) {\n return expandHome(explicit, home);\n }\n if (home !== null) {\n return `${trimTrailingSlash(home)}/.docker-git`;\n }\n return `${cwd}/.docker-git`;\n};\nconst normalizeRelativePath = (value) => value\n .replaceAll(\"\\\\\", \"/\")\n .replace(/^\\.\\//, \"\")\n .trim();\nexport const resolvePathFromCwd = (path, cwd, targetPath) => path.isAbsolute(targetPath)\n ? targetPath\n : (() => {\n const projectsRoot = path.resolve(defaultProjectsRoot(cwd));\n const normalized = normalizeRelativePath(targetPath);\n if (normalized === \".docker-git\") {\n return projectsRoot;\n }\n const prefix = \".docker-git/\";\n if (normalized.startsWith(prefix)) {\n return path.join(projectsRoot, normalized.slice(prefix.length));\n }\n return path.resolve(cwd, targetPath);\n })();\nexport const findExistingUpwards = (fs, path, startDir, fileName, maxDepth) => Effect.gen(function* (_) {\n let current = startDir;\n for (let depth = 0; depth <= maxDepth; depth += 1) {\n const candidate = path.join(current, fileName);\n const exists = yield* _(fs.exists(candidate));\n if (exists) {\n return candidate;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n return null;\n});\nexport const resolveEnvPath = (key) => {\n const value = process.env[key]?.trim();\n return value && value.length > 0 ? value : null;\n};\nexport const findExistingPath = (fs, candidate) => candidate === null\n ? Effect.succeed(null)\n : Effect.flatMap(fs.exists(candidate), (exists) => (exists ? Effect.succeed(candidate) : Effect.succeed(null)));\nexport const findFirstExisting = (fs, candidates) => Effect.gen(function* (_) {\n for (const candidate of candidates) {\n const existing = yield* _(findExistingPath(fs, candidate));\n if (existing !== null) {\n return existing;\n }\n }\n return null;\n});\nexport const findKeyByPriority = (fs, path, cwd, spec) => Effect.gen(function* (_) {\n const envPath = resolveEnvPath(spec.envVar);\n const envExisting = yield* _(findExistingPath(fs, envPath));\n if (envExisting !== null) {\n return envExisting;\n }\n const devKey = yield* _(findExistingUpwards(fs, path, cwd, spec.devKeyName, 6));\n if (devKey !== null) {\n return devKey;\n }\n if (spec.fallbackName !== undefined) {\n const fallback = yield* _(findExistingUpwards(fs, path, cwd, spec.fallbackName, 6));\n if (fallback !== null) {\n return fallback;\n }\n }\n const home = resolveEnvPath(\"HOME\");\n if (home === null) {\n return null;\n }\n return yield* _(findFirstExisting(fs, spec.homeCandidates.map((candidate) => path.join(home, \".ssh\", candidate))));\n});\nconst authorizedKeysSpec = {\n envVar: \"DOCKER_GIT_AUTHORIZED_KEYS\",\n devKeyName: \"dev_ssh_key.pub\",\n fallbackName: \"authorized_keys\",\n homeCandidates: [\"id_ed25519.pub\", \"id_rsa.pub\"]\n};\nconst sshPrivateKeySpec = {\n envVar: \"DOCKER_GIT_SSH_KEY\",\n devKeyName: \"dev_ssh_key\",\n homeCandidates: [\"id_ed25519\", \"id_rsa\"]\n};\nconst makeKeyFinder = (spec) => (fs, path, cwd) => findKeyByPriority(fs, path, cwd, spec);\nexport const findAuthorizedKeysSource = makeKeyFinder(authorizedKeysSpec);\nexport const findSshPrivateKey = makeKeyFinder(sshPrivateKeySpec);\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\n// CHANGE: provide a shared FileSystem/Path context for usecases\n// WHY: avoid duplicated setup across shell workflows\n// QUOTE(ТЗ): \"минимальный корректный diff\"\n// REF: user-request-2026-01-28-auth\n// SOURCE: n/a\n// FORMAT THEOREM: forall run: ctx(run) -> fs,path,cwd\n// PURITY: SHELL\n// EFFECT: Effect<A, PlatformError, FileSystem | Path>\n// INVARIANT: cwd is captured once per call\n// COMPLEXITY: O(1)\nexport const withFsPathContext = (run) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n return yield* _(run({ fs, path, cwd: process.cwd() }));\n});\n","export { defaultProjectsRoot, findSshPrivateKey, resolveAuthorizedKeysPath } from \"./path-helpers.js\";\nexport const isRepoUrlInput = (input) => {\n const trimmed = input.trim().toLowerCase();\n return trimmed.startsWith(\"http://\") ||\n trimmed.startsWith(\"https://\") ||\n trimmed.startsWith(\"ssh://\") ||\n trimmed.startsWith(\"git@\");\n};\nexport const formatConnectionInfo = (cwd, config, authorizedKeysPath, authorizedKeysExists, sshCommand) => `Project directory: ${cwd}\n` +\n `Container: ${config.template.containerName}\n` +\n `Service: ${config.template.serviceName}\n` +\n `SSH command: ${sshCommand}\n` +\n `Repo: ${config.template.repoUrl} (${config.template.repoRef})\n` +\n `Workspace: ${config.template.targetDir}\n` +\n `Authorized keys: ${authorizedKeysPath}${authorizedKeysExists ? \"\" : \" (missing)\"}\n` +\n `Env global: ${config.template.envGlobalPath}\n` +\n `Env project: ${config.template.envProjectPath}\n` +\n `Codex auth: ${config.template.codexAuthPath} -> ${config.template.codexHome}`;\n","import { ExitCode } from \"@effect/platform/CommandExecutor\";\nimport { Effect } from \"effect\";\nimport { runCommandCapture, runCommandExitCode, runCommandWithExitCodes } from \"../../shell/command-runner.js\";\nimport { CommandFailedError } from \"../../shell/errors.js\";\nexport const successExitCode = Number(ExitCode(0));\nexport const gitBaseEnv = {\n // Avoid blocking on interactive credential prompts in CI / TUI contexts.\n GIT_TERMINAL_PROMPT: \"0\"\n};\nexport const git = (cwd, args, env = gitBaseEnv) => runCommandWithExitCodes({ cwd, command: \"git\", args, env }, [successExitCode], (exitCode) => new CommandFailedError({ command: `git ${args[0] ?? \"\"}`, exitCode }));\nexport const gitExitCode = (cwd, args, env = gitBaseEnv) => runCommandExitCode({ cwd, command: \"git\", args, env });\nexport const gitCapture = (cwd, args, env = gitBaseEnv) => runCommandCapture({ cwd, command: \"git\", args, env }, [successExitCode], (exitCode) => new CommandFailedError({ command: `git ${args[0] ?? \"\"}`, exitCode }));\nexport const isGitRepo = (root) => Effect.map(gitExitCode(root, [\"rev-parse\", \"--is-inside-work-tree\"]), (exit) => exit === successExitCode);\nexport const hasOriginRemote = (root) => Effect.map(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"]), (exit) => exit === successExitCode);\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport { Effect } from \"effect\";\nimport { parseEnvEntries } from \"../env-file.js\";\nimport { gitBaseEnv } from \"./git-commands.js\";\nconst githubTokenKey = \"GITHUB_TOKEN\";\nconst githubHttpsRemoteRe = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/;\nconst githubSshRemoteRe = /^git@github\\.com:([^/]+)\\/(.+?)(?:\\.git)?$/;\nconst githubSshUrlRemoteRe = /^ssh:\\/\\/git@github\\.com\\/([^/]+)\\/(.+?)(?:\\.git)?$/;\nconst tryParseGithubRemoteParts = (originUrl) => {\n const trimmed = originUrl.trim();\n const match = githubHttpsRemoteRe.exec(trimmed) ??\n githubSshRemoteRe.exec(trimmed) ??\n githubSshUrlRemoteRe.exec(trimmed);\n if (match === null) {\n return null;\n }\n const owner = match[1] ?? \"\";\n const repo = match[2] ?? \"\";\n return owner.length > 0 && repo.length > 0 ? { owner, repo } : null;\n};\nexport const tryBuildGithubCompareUrl = (originUrl, baseBranch, headBranch) => {\n const parts = tryParseGithubRemoteParts(originUrl);\n if (parts === null) {\n return null;\n }\n return `https://github.com/${parts.owner}/${parts.repo}/compare/${encodeURIComponent(baseBranch)}...${encodeURIComponent(headBranch)}?expand=1`;\n};\nexport const isGithubHttpsRemote = (url) => /^https:\\/\\/github\\.com\\//.test(url.trim());\nconst resolveTokenFromProcessEnv = () => {\n const github = process.env[\"GITHUB_TOKEN\"];\n if (github !== undefined) {\n const trimmed = github.trim();\n if (trimmed.length > 0) {\n return trimmed;\n }\n }\n const gh = process.env[\"GH_TOKEN\"];\n if (gh !== undefined) {\n const trimmed = gh.trim();\n if (trimmed.length > 0) {\n return trimmed;\n }\n }\n return null;\n};\nconst findTokenInEnvEntries = (entries) => {\n const directEntry = entries.find((e) => e.key === githubTokenKey);\n if (directEntry !== undefined) {\n const direct = directEntry.value.trim();\n if (direct.length > 0) {\n return direct;\n }\n }\n const labeledEntry = entries.find((e) => e.key.startsWith(\"GITHUB_TOKEN__\"));\n if (labeledEntry !== undefined) {\n const labeled = labeledEntry.value.trim();\n if (labeled.length > 0) {\n return labeled;\n }\n }\n return null;\n};\nexport const resolveGithubToken = (fs, path, root) => Effect.gen(function* (_) {\n const fromEnv = resolveTokenFromProcessEnv();\n if (fromEnv !== null) {\n return fromEnv;\n }\n const envPath = path.join(root, \".orch\", \"env\", \"global.env\");\n const exists = yield* _(fs.exists(envPath));\n if (!exists) {\n return null;\n }\n const text = yield* _(fs.readFileString(envPath));\n return findTokenInEnvEntries(parseEnvEntries(text));\n});\nexport const withGithubAskpassEnv = (token, use) => Effect.scoped(Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const askpassPath = yield* _(fs.makeTempFileScoped({ prefix: \"docker-git-askpass-\" }));\n const contents = [\n \"#!/bin/sh\",\n \"case \\\"$1\\\" in\",\n \" *Username*) echo \\\"x-access-token\\\" ;;\",\n \" *Password*) echo \\\"${DOCKER_GIT_GITHUB_TOKEN}\\\" ;;\",\n \" *) echo \\\"${DOCKER_GIT_GITHUB_TOKEN}\\\" ;;\",\n \"esac\",\n \"\"\n ].join(\"\\n\");\n yield* _(fs.writeFileString(askpassPath, contents));\n yield* _(fs.chmod(askpassPath, 0o700));\n const env = {\n ...gitBaseEnv,\n DOCKER_GIT_GITHUB_TOKEN: token,\n GIT_ASKPASS: askpassPath,\n GIT_ASKPASS_REQUIRE: \"force\"\n };\n return yield* _(use(env));\n}));\n","import { Effect } from \"effect\";\nconst isDockerGitConfig = (entry) => entry.endsWith(\"docker-git.json\");\nconst shouldSkipDir = (entry) => entry === \".git\" || entry === \".orch\";\nconst processDockerGitEntry = (fs, path, dir, entry, state) => Effect.gen(function* (_) {\n if (shouldSkipDir(entry)) {\n return;\n }\n const resolved = path.join(dir, entry);\n const info = yield* _(fs.stat(resolved));\n if (info.type === \"Directory\") {\n state.stack.push(resolved);\n return;\n }\n if (info.type === \"File\" && isDockerGitConfig(entry)) {\n state.results.push(resolved);\n }\n}).pipe(Effect.asVoid);\nexport const findDockerGitConfigPaths = (fs, path, rootDir) => Effect.gen(function* (_) {\n const exists = yield* _(fs.exists(rootDir));\n if (!exists) {\n return [];\n }\n // Avoid traversing git metadata (projectsRoot can itself be a git repo).\n const results = [];\n const stack = [rootDir];\n const state = { stack, results };\n while (stack.length > 0) {\n const dir = stack.pop();\n if (dir === undefined) {\n break;\n }\n const entries = yield* _(fs.readDirectory(dir));\n for (const entry of entries) {\n yield* _(processDockerGitEntry(fs, path, dir, entry, state));\n }\n }\n return results;\n});\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect } from \"effect\";\nimport { runCommandExitCode } from \"../shell/command-runner.js\";\nimport { CommandFailedError } from \"../shell/errors.js\";\nimport { defaultProjectsRoot } from \"./menu-helpers.js\";\nimport { autoSyncEnvKey, autoSyncStrictEnvKey, isAutoSyncEnabled, isTruthyEnv } from \"./state-repo/env.js\";\nimport { git, gitBaseEnv, gitCapture, gitExitCode, hasOriginRemote, isGitRepo, successExitCode } from \"./state-repo/git-commands.js\";\nimport { isGithubHttpsRemote, resolveGithubToken, withGithubAskpassEnv } from \"./state-repo/github-auth.js\";\nimport { ensureStateGitignore } from \"./state-repo/gitignore.js\";\nimport { runStateSyncOps, runStateSyncWithToken } from \"./state-repo/sync-ops.js\";\nconst resolveStateRoot = (path, cwd) => path.resolve(defaultProjectsRoot(cwd));\nexport const statePath = Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const cwd = process.cwd();\n const root = resolveStateRoot(path, cwd);\n yield* _(Effect.log(root));\n}).pipe(Effect.asVoid);\nexport const stateSync = (message) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const repoExit = yield* _(gitExitCode(root, [\"rev-parse\", \"--is-inside-work-tree\"], gitBaseEnv));\n if (repoExit !== successExitCode) {\n yield* _(Effect.logWarning(`State dir is not a git repository: ${root}`));\n yield* _(Effect.logWarning(`Run: docker-git state init --repo-url <url>`));\n return yield* _(Effect.fail(new CommandFailedError({ command: \"git rev-parse --is-inside-work-tree\", exitCode: repoExit })));\n }\n const originUrlExit = yield* _(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv));\n if (originUrlExit !== successExitCode) {\n yield* _(Effect.logWarning(`State dir has no origin remote: ${root}`));\n yield* _(Effect.logWarning(`Run: docker-git state init --repo-url <url>`));\n return yield* _(Effect.fail(new CommandFailedError({ command: \"git remote get-url origin\", exitCode: originUrlExit })));\n }\n const originUrl = yield* _(gitCapture(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv).pipe(Effect.map((value) => value.trim())));\n const token = yield* _(resolveGithubToken(fs, path, root));\n const syncEffect = token && token.length > 0 && isGithubHttpsRemote(originUrl)\n ? runStateSyncWithToken(token, root, originUrl, message)\n : runStateSyncOps(root, originUrl, message, gitBaseEnv);\n yield* _(syncEffect);\n}).pipe(Effect.asVoid);\nexport const autoSyncState = (message) => Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const repoOk = yield* _(isGitRepo(root));\n if (!repoOk) {\n return;\n }\n const originOk = yield* _(hasOriginRemote(root));\n const enabled = isAutoSyncEnabled(process.env[autoSyncEnvKey], originOk);\n if (!enabled) {\n return;\n }\n const strictValue = process.env[autoSyncStrictEnvKey];\n const strict = strictValue !== undefined && strictValue.trim().length > 0 ? isTruthyEnv(strictValue) : false;\n const effect = stateSync(message);\n if (strict) {\n yield* _(effect);\n return;\n }\n yield* _(effect.pipe(Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`State auto-sync failed: ${error._tag === \"CommandFailedError\"\n ? `${error.command} (exit ${error.exitCode})`\n : String(error)}`),\n onSuccess: () => Effect.void\n })));\n}).pipe(Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`State auto-sync failed: ${String(error)}`),\n onSuccess: () => Effect.void\n}), Effect.asVoid);\nconst cloneStateRepo = (root, input) => Effect.gen(function* (_) {\n const cloneWithBranch = [\"clone\", \"--branch\", input.repoRef, input.repoUrl, root];\n const cloneBranchExit = yield* _(runCommandExitCode({ cwd: root, command: \"git\", args: cloneWithBranch, env: gitBaseEnv }));\n if (cloneBranchExit === successExitCode) {\n return;\n }\n // Empty remotes (no branch yet) and remotes without the requested branch can fail here.\n // Fall back to cloning the default branch so we can still set up the repo and create the branch locally.\n yield* _(Effect.logWarning(`git clone --branch ${input.repoRef} failed (exit ${cloneBranchExit}); retrying without --branch`));\n const cloneDefault = [\"clone\", input.repoUrl, root];\n const cloneDefaultExit = yield* _(runCommandExitCode({ cwd: root, command: \"git\", args: cloneDefault, env: gitBaseEnv }));\n if (cloneDefaultExit !== successExitCode) {\n return yield* _(Effect.fail(new CommandFailedError({ command: \"git clone\", exitCode: cloneDefaultExit })));\n }\n}).pipe(Effect.asVoid);\nconst initRepoIfNeeded = (fs, path, root, input) => Effect.gen(function* (_) {\n yield* _(fs.makeDirectory(root, { recursive: true }));\n const gitDir = path.join(root, \".git\");\n const hasGit = yield* _(fs.exists(gitDir));\n if (hasGit) {\n return;\n }\n const entries = yield* _(fs.readDirectory(root));\n if (entries.length === 0) {\n yield* _(cloneStateRepo(root, input));\n yield* _(Effect.log(`State dir cloned: ${root}`));\n return;\n }\n yield* _(git(root, [\"init\"], gitBaseEnv));\n}).pipe(Effect.asVoid);\nconst ensureOriginRemote = (root, repoUrl) => Effect.gen(function* (_) {\n const setUrlExit = yield* _(gitExitCode(root, [\"remote\", \"set-url\", \"origin\", repoUrl], gitBaseEnv));\n if (setUrlExit === successExitCode) {\n return;\n }\n yield* _(git(root, [\"remote\", \"add\", \"origin\", repoUrl], gitBaseEnv));\n});\nconst checkoutBranchBestEffort = (root, repoRef) => Effect.gen(function* (_) {\n const checkoutExit = yield* _(gitExitCode(root, [\"checkout\", \"-B\", repoRef], gitBaseEnv));\n if (checkoutExit === successExitCode) {\n return;\n }\n yield* _(Effect.logWarning(`git checkout -B ${repoRef} failed (exit ${checkoutExit})`));\n});\nexport const stateInit = (input) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n yield* _(initRepoIfNeeded(fs, path, root, input));\n yield* _(ensureOriginRemote(root, input.repoUrl));\n yield* _(checkoutBranchBestEffort(root, input.repoRef));\n yield* _(ensureStateGitignore(fs, path, root));\n yield* _(Effect.log(`State dir ready: ${root}`));\n yield* _(Effect.log(`Remote: ${input.repoUrl}`));\n}).pipe(Effect.asVoid);\nexport const stateStatus = Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const output = yield* _(gitCapture(root, [\"status\", \"-sb\", \"--porcelain=v1\"], gitBaseEnv));\n yield* _(Effect.log(output.trim().length > 0 ? output.trimEnd() : \"(clean)\"));\n}).pipe(Effect.asVoid);\nexport const statePull = Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const originUrlExit = yield* _(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv));\n if (originUrlExit !== successExitCode) {\n yield* _(git(root, [\"pull\", \"--rebase\"], gitBaseEnv));\n return;\n }\n const originUrl = yield* _(gitCapture(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv).pipe(Effect.map((value) => value.trim())));\n const token = yield* _(resolveGithubToken(fs, path, root));\n const effect = token && token.length > 0 && isGithubHttpsRemote(originUrl)\n ? withGithubAskpassEnv(token, (env) => git(root, [\"pull\", \"--rebase\"], env))\n : git(root, [\"pull\", \"--rebase\"], gitBaseEnv);\n yield* _(effect);\n}).pipe(Effect.asVoid);\nexport const statePush = Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n const originUrlExit = yield* _(gitExitCode(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv));\n if (originUrlExit !== successExitCode) {\n yield* _(git(root, [\"push\", \"-u\", \"origin\", \"HEAD\"], gitBaseEnv));\n return;\n }\n const originUrl = yield* _(gitCapture(root, [\"remote\", \"get-url\", \"origin\"], gitBaseEnv).pipe(Effect.map((value) => value.trim())));\n const token = yield* _(resolveGithubToken(fs, path, root));\n const effect = token && token.length > 0 && isGithubHttpsRemote(originUrl)\n ? withGithubAskpassEnv(token, (env) => git(root, [\"push\", \"-u\", \"origin\", \"HEAD\"], env))\n : git(root, [\"push\", \"-u\", \"origin\", \"HEAD\"], gitBaseEnv);\n yield* _(effect);\n}).pipe(Effect.asVoid);\nexport const stateCommit = (message) => Effect.gen(function* (_) {\n const path = yield* _(Path.Path);\n const root = resolveStateRoot(path, process.cwd());\n yield* _(git(root, [\"add\", \"-A\"], gitBaseEnv));\n const diffExit = yield* _(gitExitCode(root, [\"diff\", \"--cached\", \"--quiet\"], gitBaseEnv));\n if (diffExit === successExitCode) {\n yield* _(Effect.log(\"Nothing to commit.\"));\n return;\n }\n yield* _(git(root, [\"commit\", \"-m\", message], gitBaseEnv));\n}).pipe(Effect.asVoid);\n","import { Match } from \"effect\";\nimport {} from \"../core/domain.js\";\nimport { formatParseError } from \"../core/parse-errors.js\";\nconst isParseError = (error) => error._tag === \"UnknownCommand\" ||\n error._tag === \"UnknownOption\" ||\n error._tag === \"MissingOptionValue\" ||\n error._tag === \"MissingRequiredOption\" ||\n error._tag === \"InvalidOption\" ||\n error._tag === \"UnexpectedArgument\";\nconst renderDockerAccessHeadline = (issue) => issue === \"PermissionDenied\"\n ? \"Cannot access Docker daemon socket: permission denied.\"\n : \"Cannot connect to Docker daemon.\";\nconst renderPrimaryError = (error) => Match.value(error).pipe(Match.when({ _tag: \"FileExistsError\" }, ({ path }) => `File already exists: ${path} (use --force to overwrite)`), Match.when({ _tag: \"DockerCommandError\" }, ({ exitCode }) => [\n `docker compose failed with exit code ${exitCode}`,\n \"Hint: ensure Docker daemon is running and current user can access /var/run/docker.sock (for example via the docker group).\"\n].join(\"\\n\")), Match.when({ _tag: \"DockerAccessError\" }, ({ details, issue }) => [\n renderDockerAccessHeadline(issue),\n \"Hint: ensure Docker daemon is running and current user can access the docker socket.\",\n \"Hint: if you use rootless Docker, set DOCKER_HOST to your user socket (for example unix:///run/user/$UID/docker.sock).\",\n `Details: ${details}`\n].join(\"\\n\")), Match.when({ _tag: \"CloneFailedError\" }, ({ repoRef, repoUrl, targetDir }) => `Clone failed for ${repoUrl} (${repoRef}) into ${targetDir}`), Match.when({ _tag: \"PortProbeError\" }, ({ message, port }) => `SSH port check failed for ${port}: ${message}`), Match.when({ _tag: \"CommandFailedError\" }, ({ command, exitCode }) => `${command} failed with exit code ${exitCode}`), Match.when({ _tag: \"ScrapArchiveNotFoundError\" }, ({ path }) => `Scrap archive not found: ${path} (run docker-git scrap export first)`), Match.when({ _tag: \"ScrapArchiveInvalidError\" }, ({ message, path }) => `Invalid scrap archive: ${path}\\nDetails: ${message}`), Match.when({ _tag: \"ScrapTargetDirUnsupportedError\" }, ({ reason, sshUser, targetDir }) => [\n `Cannot use scrap with targetDir ${targetDir}.`,\n `Reason: ${reason}`,\n `Hint: scrap currently supports workspaces under /home/${sshUser}/... only.`\n].join(\"\\n\")), Match.when({ _tag: \"ScrapWipeRefusedError\" }, ({ reason, targetDir }) => [\n `Refusing to wipe workspace for scrap import (targetDir ${targetDir}).`,\n `Reason: ${reason}`,\n \"Hint: re-run with --no-wipe, or set a narrower --target-dir when creating the project.\"\n].join(\"\\n\")), Match.when({ _tag: \"AuthError\" }, ({ message }) => message), Match.orElse(() => null));\nconst renderConfigError = (error) => {\n if (error._tag === \"ConfigNotFoundError\") {\n return `docker-git.json not found: ${error.path} (run docker-git create in that directory)`;\n }\n if (error._tag === \"ConfigDecodeError\") {\n return `Invalid docker-git.json at ${error.path}: ${error.message}`;\n }\n return null;\n};\nconst renderInputError = (error) => {\n if (error._tag === \"InputCancelledError\") {\n return \"Input cancelled.\";\n }\n if (error._tag === \"InputReadError\") {\n return `Input error: ${error.message}`;\n }\n return null;\n};\nconst renderNonParseError = (error) => renderPrimaryError(error) ?? renderConfigError(error) ?? renderInputError(error) ?? error.message;\n// CHANGE: render typed application errors into user-facing text\n// WHY: provide deterministic messaging for CLI and menu flows\n// QUOTE(ТЗ): \"вижу всю инфу по ним\"\n// REF: user-request-2026-01-07\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: render(e) = s -> deterministic(s)\n// PURITY: CORE\n// EFFECT: Effect<string, never, never>\n// INVARIANT: each AppError maps to exactly one message\n// COMPLEXITY: O(1)\nexport const renderError = (error) => {\n if (isParseError(error)) {\n return formatParseError(error);\n }\n return renderNonParseError(error);\n};\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Effect, pipe } from \"effect\";\nimport { deriveRepoPathParts } from \"../core/domain.js\";\nimport { readProjectConfig } from \"../shell/config.js\";\nimport { resolveBaseDir } from \"../shell/paths.js\";\nimport { findDockerGitConfigPaths } from \"./docker-git-config-search.js\";\nimport { renderError } from \"./errors.js\";\nimport { defaultProjectsRoot, formatConnectionInfo } from \"./menu-helpers.js\";\nimport { findSshPrivateKey, resolveAuthorizedKeysPath, resolvePathFromCwd } from \"./path-helpers.js\";\nimport { withFsPathContext } from \"./runtime.js\";\nconst sshOptions = \"-tt -Y -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\";\nexport const buildSshCommand = (config, sshKey) => sshKey === null\n ? `ssh ${sshOptions} -p ${config.sshPort} ${config.sshUser}@localhost`\n : `ssh -i ${sshKey} ${sshOptions} -p ${config.sshPort} ${config.sshUser}@localhost`;\nconst loadProjectBase = (configPath) => Effect.gen(function* (_) {\n const { fs, path, resolved } = yield* _(resolveBaseDir(configPath));\n const projectDir = path.dirname(resolved);\n const config = yield* _(readProjectConfig(projectDir));\n return { fs, path, projectDir, config };\n});\nconst findProjectConfigPaths = (projectsRoot) => withFsPathContext(({ fs, path }) => findDockerGitConfigPaths(fs, path, path.resolve(projectsRoot)));\nexport const loadProjectSummary = (configPath, sshKey) => Effect.gen(function* (_) {\n const { config, fs, path, projectDir } = yield* _(loadProjectBase(configPath));\n const resolvedAuthorizedKeys = resolveAuthorizedKeysPath(path, projectDir, config.template.authorizedKeysPath);\n const authExists = yield* _(fs.exists(resolvedAuthorizedKeys));\n const sshCommand = buildSshCommand(config.template, sshKey);\n return {\n projectDir,\n config,\n sshCommand,\n authorizedKeysPath: resolvedAuthorizedKeys,\n authorizedKeysExists: authExists\n };\n});\nexport const loadProjectStatus = (configPath) => Effect.gen(function* (_) {\n const { config, projectDir } = yield* _(loadProjectBase(configPath));\n return { projectDir, config };\n});\nexport const renderProjectSummary = (summary) => formatConnectionInfo(summary.projectDir, summary.config, summary.authorizedKeysPath, summary.authorizedKeysExists, summary.sshCommand);\nconst formatDisplayName = (repoUrl) => {\n const parts = deriveRepoPathParts(repoUrl);\n if (parts.pathParts.length > 0) {\n return parts.pathParts.join(\"/\");\n }\n return repoUrl;\n};\nexport const loadProjectItem = (configPath, sshKey) => Effect.gen(function* (_) {\n const { config, fs, path, projectDir } = yield* _(loadProjectBase(configPath));\n const template = config.template;\n const resolvedAuthorizedKeys = resolveAuthorizedKeysPath(path, projectDir, template.authorizedKeysPath);\n const authExists = yield* _(fs.exists(resolvedAuthorizedKeys));\n const sshCommand = buildSshCommand(template, sshKey);\n const displayName = formatDisplayName(template.repoUrl);\n return {\n projectDir,\n displayName,\n repoUrl: template.repoUrl,\n repoRef: template.repoRef,\n containerName: template.containerName,\n serviceName: template.serviceName,\n sshUser: template.sshUser,\n sshPort: template.sshPort,\n targetDir: template.targetDir,\n sshCommand,\n sshKeyPath: sshKey,\n authorizedKeysPath: resolvedAuthorizedKeys,\n authorizedKeysExists: authExists,\n envGlobalPath: resolvePathFromCwd(path, projectDir, template.envGlobalPath),\n envProjectPath: resolvePathFromCwd(path, projectDir, template.envProjectPath),\n codexAuthPath: resolvePathFromCwd(path, projectDir, template.codexAuthPath),\n codexHome: template.codexHome\n };\n});\nexport const renderProjectStatusHeader = (status) => `Project: ${status.projectDir}`;\nexport const skipWithWarning = (configPath) => (error) => pipe(Effect.logWarning(`Skipping ${configPath}: ${renderError(error)}`), Effect.as(null));\nexport const forEachProjectStatus = (configPaths, run) => Effect.gen(function* (_) {\n for (const configPath of configPaths) {\n const status = yield* _(loadProjectStatus(configPath).pipe(Effect.matchEffect({\n onFailure: skipWithWarning(configPath),\n onSuccess: (value) => Effect.succeed(value)\n })));\n if (status === null) {\n continue;\n }\n yield* _(run(status));\n }\n}).pipe(Effect.asVoid);\nconst normalizeCell = (value) => value?.trim() ?? \"-\";\nconst parseComposeLine = (line) => {\n const [name, status, ports, image] = line.split(\"\\t\");\n return {\n name: normalizeCell(name),\n status: normalizeCell(status),\n ports: normalizeCell(ports),\n image: normalizeCell(image)\n };\n};\nexport const parseComposePsOutput = (raw) => {\n const lines = raw\n .split(/\\r?\\n/)\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n return lines.map((line) => parseComposeLine(line));\n};\nconst padRight = (value, width) => value.length >= width ? value : `${value}${\" \".repeat(width - value.length)}`;\nexport const formatComposeRows = (entries) => {\n if (entries.length === 0) {\n return \" status: not running\";\n }\n const nameWidth = Math.min(24, Math.max(...entries.map((row) => row.name.length), \"name\".length));\n const statusWidth = Math.min(28, Math.max(...entries.map((row) => row.status.length), \"status\".length));\n const portsWidth = Math.min(28, Math.max(...entries.map((row) => row.ports.length), \"ports\".length));\n const header = ` ${padRight(\"name\", nameWidth)} ${padRight(\"status\", statusWidth)} ${padRight(\"ports\", portsWidth)} image`;\n const lines = entries.map((row) => ` ${padRight(row.name, nameWidth)} ${padRight(row.status, statusWidth)} ${padRight(row.ports, portsWidth)} ${row.image}`);\n return [header, ...lines].join(\"\\n\");\n};\nexport const loadProjectIndex = () => Effect.gen(function* (_) {\n const projectsRoot = defaultProjectsRoot(process.cwd());\n const configPaths = yield* _(findProjectConfigPaths(projectsRoot));\n if (configPaths.length === 0) {\n yield* _(Effect.log(`No docker-git projects found in ${projectsRoot}`));\n return null;\n }\n return { projectsRoot, configPaths };\n});\nexport const withProjectIndexAndSsh = (run) => pipe(loadProjectIndex(), Effect.flatMap((index) => index === null\n ? Effect.succeed(null)\n : Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const sshKey = yield* _(findSshPrivateKey(fs, path, process.cwd()));\n return yield* _(run(index, sshKey));\n })));\n","import { Effect, pipe } from \"effect\";\nimport { runDockerComposeDown } from \"../shell/docker.js\";\nimport { renderError } from \"./errors.js\";\nimport { forEachProjectStatus, loadProjectIndex, renderProjectStatusHeader } from \"./projects-core.js\";\n// CHANGE: provide a \"stop all\" helper for docker-git managed projects\n// WHY: allow quickly stopping all running docker-git containers from the CLI/TUI\n// QUOTE(ТЗ): \"Выведи сюда возможность убивать все контейнеры\"\n// REF: user-request-2026-02-06-stop-all\n// SOURCE: n/a\n// FORMAT THEOREM: ∀p ∈ Projects: downAll(p) → stopped(p) ∨ warned(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path | CommandExecutor>\n// INVARIANT: continues stopping other projects when one docker compose down fails with DockerCommandError\n// COMPLEXITY: O(n) where n = |projects|\nexport const downAllDockerGitProjects = pipe(loadProjectIndex(), Effect.flatMap((index) => index === null\n ? Effect.void\n : forEachProjectStatus(index.configPaths, (status) => pipe(Effect.log(renderProjectStatusHeader(status)), Effect.zipRight(runDockerComposeDown(status.projectDir).pipe(Effect.catchTag(\"DockerCommandError\", (error) => Effect.logWarning(`docker compose down failed for ${status.projectDir}: ${renderError(error)}`))))))), Effect.asVoid);\n","import { Effect, pipe } from \"effect\";\nimport { runDockerPsNames } from \"../shell/docker.js\";\nimport { loadProjectItem, loadProjectSummary, renderProjectSummary, skipWithWarning, withProjectIndexAndSsh } from \"./projects-core.js\";\n// CHANGE: list docker-git projects with SSH connection info\n// WHY: provide a deterministic inventory of created environments\n// QUOTE(ТЗ): \"мне нужны мои... доступы к ним по SSH\"\n// REF: user-request-2026-01-27-list\n// SOURCE: n/a\n// FORMAT THEOREM: forall root: list(root) -> summaries(root)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path>\n// INVARIANT: output is deterministic for a stable filesystem\n// COMPLEXITY: O(n) where n = |projects|\nexport const listProjects = pipe(withProjectIndexAndSsh((index, sshKey) => Effect.gen(function* (_) {\n const available = [];\n for (const configPath of index.configPaths) {\n const summary = yield* _(loadProjectSummary(configPath, sshKey).pipe(Effect.matchEffect({\n onFailure: skipWithWarning(configPath),\n onSuccess: (value) => Effect.succeed(value)\n })));\n if (summary !== null) {\n available.push(summary);\n }\n }\n if (available.length === 0) {\n yield* _(Effect.log(`No readable docker-git projects found in ${index.projectsRoot}`));\n return;\n }\n yield* _(Effect.log(`Found ${available.length} docker-git project(s) in ${index.projectsRoot}`));\n for (const summary of available) {\n yield* _(Effect.log(renderProjectSummary(summary)));\n }\n})), Effect.asVoid);\n// CHANGE: collect docker-git connection info lines without logging\n// WHY: allow TUI to render connection info inline\n// QUOTE(ТЗ): \"А кнопка \\\"Show connection info\\\" ничего не отображает\"\n// REF: user-request-2026-02-01-tui-info\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in projects: summary(p) -> line(p)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<string>, PlatformError, FileSystem | Path>\n// INVARIANT: output order matches configPaths order\n// COMPLEXITY: O(n) where n = |projects|\nconst emptySummaries = () => [];\nconst emptyItems = () => [];\nconst collectProjectValues = (configPaths, sshKey, load, toValue) => Effect.gen(function* (_) {\n const available = [];\n for (const configPath of configPaths) {\n const value = yield* _(load(configPath, sshKey).pipe(Effect.matchEffect({\n onFailure: () => Effect.succeed(null),\n onSuccess: (item) => Effect.succeed(toValue(item))\n })));\n if (value !== null) {\n available.push(value);\n }\n }\n return available;\n});\nconst listProjectValues = (load, toValue, empty) => pipe(withProjectIndexAndSsh((index, sshKey) => collectProjectValues(index.configPaths, sshKey, load, toValue)), Effect.map((values) => values ?? empty()));\nexport const listProjectSummaries = listProjectValues(loadProjectSummary, renderProjectSummary, emptySummaries);\n// CHANGE: load docker-git projects for TUI selection\n// WHY: provide structured project data without noisy logs\n// QUOTE(ТЗ): \"А ты можешь сделать удобный выбор проектов?\"\n// REF: user-request-2026-02-02-select-project\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in projects: item(p) -> selectable(p)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<ProjectItem>, PlatformError, FileSystem | Path>\n// INVARIANT: output order matches configPaths order\n// COMPLEXITY: O(n) where n = |projects|\nexport const listProjectItems = listProjectValues(loadProjectItem, (value) => value, emptyItems);\n// CHANGE: list only running docker-git projects (for \"Stop container\" UI)\n// WHY: stopping already-stopped projects is confusing and noisy\n// QUOTE(ТЗ): \"Смысл мне пытаться остановить тот контейнер который уже остановлен?\"\n// REF: user-request-2026-02-07-stop-only-running\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in result: running(container(p))\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<ProjectItem>, PlatformError | CommandFailedError, FileSystem | Path | CommandExecutor>\n// INVARIANT: result order follows listProjectItems order\n// COMPLEXITY: O(n + command)\nexport const listRunningProjectItems = pipe(Effect.all([listProjectItems, runDockerPsNames(process.cwd())]), Effect.map(([items, runningNames]) => items.filter((item) => runningNames.includes(item.containerName))));\n","import { Duration, Effect, pipe, Schedule } from \"effect\";\nimport { runCommandExitCode, runCommandWithExitCodes } from \"../shell/command-runner.js\";\nimport { runDockerComposePsFormatted } from \"../shell/docker.js\";\nimport { CommandFailedError } from \"../shell/errors.js\";\nimport { renderError } from \"./errors.js\";\nimport { buildSshCommand, forEachProjectStatus, formatComposeRows, parseComposePsOutput, renderProjectStatusHeader, withProjectIndexAndSsh } from \"./projects-core.js\";\nimport { runDockerComposeUpWithPortCheck } from \"./projects-up.js\";\nconst buildSshArgs = (item) => {\n const args = [];\n if (item.sshKeyPath !== null) {\n args.push(\"-i\", item.sshKeyPath);\n }\n args.push(\"-tt\", \"-Y\", \"-o\", \"LogLevel=ERROR\", \"-o\", \"StrictHostKeyChecking=no\", \"-o\", \"UserKnownHostsFile=/dev/null\", \"-p\", String(item.sshPort), `${item.sshUser}@localhost`);\n return args;\n};\nconst buildSshProbeArgs = (item) => {\n const args = [];\n if (item.sshKeyPath !== null) {\n args.push(\"-i\", item.sshKeyPath);\n }\n args.push(\"-T\", \"-o\", \"BatchMode=yes\", \"-o\", \"ConnectTimeout=2\", \"-o\", \"ConnectionAttempts=1\", \"-o\", \"LogLevel=ERROR\", \"-o\", \"StrictHostKeyChecking=no\", \"-o\", \"UserKnownHostsFile=/dev/null\", \"-p\", String(item.sshPort), `${item.sshUser}@localhost`, \"true\");\n return args;\n};\nconst waitForSshReady = (item) => {\n const probe = Effect.gen(function* (_) {\n const exitCode = yield* _(runCommandExitCode({\n cwd: process.cwd(),\n command: \"ssh\",\n args: buildSshProbeArgs(item)\n }));\n if (exitCode !== 0) {\n return yield* _(Effect.fail(new CommandFailedError({ command: \"ssh wait\", exitCode })));\n }\n });\n return pipe(Effect.log(`Waiting for SSH on localhost:${item.sshPort} ...`), Effect.zipRight(Effect.retry(probe, pipe(Schedule.spaced(Duration.seconds(2)), Schedule.intersect(Schedule.recurs(30))))), Effect.tap(() => Effect.log(\"SSH is ready.\")));\n};\n// CHANGE: connect to a project via SSH using its resolved settings\n// WHY: allow TUI to open a shell immediately after selection\n// QUOTE(ТЗ): \"выбор проекта сразу подключает по SSH\"\n// REF: user-request-2026-02-02-select-ssh\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: connect(p) -> ssh(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, CommandFailedError | PlatformError, CommandExecutor>\n// INVARIANT: command is ssh with deterministic args\n// COMPLEXITY: O(1)\nexport const connectProjectSsh = (item) => runCommandWithExitCodes({\n cwd: process.cwd(),\n command: \"ssh\",\n args: buildSshArgs(item)\n}, [0, 130], (exitCode) => new CommandFailedError({ command: \"ssh\", exitCode }));\n// CHANGE: ensure docker compose is up before SSH connection\n// WHY: selected project should auto-start when not running\n// QUOTE(ТЗ): \"Если не поднят то пусть поднимает\"\n// REF: user-request-2026-02-02-select-up\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: up(p) -> ssh(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, CommandFailedError | DockerCommandError | PlatformError, CommandExecutor | FileSystem | Path>\n// INVARIANT: docker compose up runs before ssh\n// COMPLEXITY: O(1)\nexport const connectProjectSshWithUp = (item) => pipe(Effect.log(`Starting docker compose for ${item.displayName} ...`), Effect.zipRight(runDockerComposeUpWithPortCheck(item.projectDir)), Effect.map((template) => ({ ...item, sshPort: template.sshPort })), Effect.tap((updated) => waitForSshReady(updated)), Effect.flatMap((updated) => connectProjectSsh(updated)));\n// CHANGE: show docker compose status for all known docker-git projects\n// WHY: allow checking active containers without switching directories\n// QUOTE(ТЗ): \"как посмотреть какие активны?\"\n// REF: user-request-2026-01-27-status\n// SOURCE: n/a\n// FORMAT THEOREM: forall p in projects: status(p) -> output(p)\n// PURITY: SHELL\n// EFFECT: Effect<void, PlatformError, FileSystem | Path | CommandExecutor>\n// INVARIANT: each project emits a header before docker compose output\n// COMPLEXITY: O(n) where n = |projects|\nexport const listProjectStatus = Effect.asVoid(withProjectIndexAndSsh((index, sshKey) => forEachProjectStatus(index.configPaths, (status) => pipe(Effect.log(renderProjectStatusHeader(status)), Effect.zipRight(Effect.log(`SSH access: ${buildSshCommand(status.config.template, sshKey)}`)), Effect.zipRight(runDockerComposePsFormatted(status.projectDir).pipe(Effect.map((raw) => parseComposePsOutput(raw)), Effect.map((rows) => formatComposeRows(rows)), Effect.flatMap((text) => Effect.log(text)), Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`docker compose ps failed for ${status.projectDir}: ${renderError(error)}`),\n onSuccess: () => Effect.void\n})))))));\n","import * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport { Duration, Effect, Fiber, Schedule } from \"effect\";\nimport { runDockerComposeDownVolumes, runDockerComposeLogsFollow, runDockerComposeUp, runDockerComposeUpRecreate, runDockerExecExitCode, runDockerInspectContainerBridgeIp, runDockerNetworkConnectBridge } from \"../../shell/docker.js\";\nimport { CloneFailedError } from \"../../shell/errors.js\";\nimport { findSshPrivateKey, resolveAuthorizedKeysPath } from \"../path-helpers.js\";\nimport { buildSshCommand } from \"../projects.js\";\nconst maxPortAttempts = 25;\nconst clonePollInterval = Duration.seconds(1);\nconst cloneDonePath = \"/run/docker-git/clone.done\";\nconst cloneFailPath = \"/run/docker-git/clone.failed\";\nconst logSshAccess = (baseDir, config) => Effect.gen(function* (_) {\n const fs = yield* _(FileSystem.FileSystem);\n const path = yield* _(Path.Path);\n const resolvedAuthorizedKeys = resolveAuthorizedKeysPath(path, baseDir, config.authorizedKeysPath);\n const authExists = yield* _(fs.exists(resolvedAuthorizedKeys));\n const sshKey = yield* _(findSshPrivateKey(fs, path, process.cwd()));\n const sshCommand = buildSshCommand(config, sshKey);\n yield* _(Effect.log(`SSH access: ${sshCommand}`));\n if (!authExists) {\n yield* _(Effect.logWarning(`Authorized keys file missing: ${resolvedAuthorizedKeys} (SSH may fail without a matching key).`));\n }\n});\nconst checkCloneState = (cwd, containerName) => Effect.gen(function* (_) {\n const failed = yield* _(runDockerExecExitCode(cwd, containerName, [\"test\", \"-f\", cloneFailPath]));\n if (failed === 0) {\n return \"failed\";\n }\n const done = yield* _(runDockerExecExitCode(cwd, containerName, [\"test\", \"-f\", cloneDonePath]));\n return done === 0 ? \"done\" : \"pending\";\n});\nconst waitForCloneCompletion = (cwd, config) => Effect.gen(function* (_) {\n const logsFiber = yield* _(runDockerComposeLogsFollow(cwd).pipe(Effect.tapError((error) => Effect.logWarning(`docker compose logs --follow failed: ${error instanceof Error ? error.message : String(error)}`)), Effect.fork));\n const result = yield* _(checkCloneState(cwd, config.containerName).pipe(Effect.repeat(Schedule.addDelay(Schedule.recurUntil((state) => state !== \"pending\"), () => clonePollInterval))));\n yield* _(Fiber.interrupt(logsFiber));\n if (result === \"failed\") {\n return yield* _(Effect.fail(new CloneFailedError({\n repoUrl: config.repoUrl,\n repoRef: config.repoRef,\n targetDir: config.targetDir\n })));\n }\n});\nconst runDockerComposeUpByMode = (resolvedOutDir, force, forceEnv) => Effect.gen(function* (_) {\n if (force) {\n yield* _(Effect.log(\"Force enabled: wiping docker compose volumes (docker compose down -v)...\"));\n yield* _(runDockerComposeDownVolumes(resolvedOutDir));\n yield* _(Effect.log(\"Running: docker compose up -d --build\"));\n yield* _(runDockerComposeUp(resolvedOutDir));\n return;\n }\n if (forceEnv) {\n yield* _(Effect.log(\"Force env enabled: resetting env defaults and recreating containers (volumes preserved)...\"));\n yield* _(runDockerComposeUpRecreate(resolvedOutDir));\n return;\n }\n yield* _(Effect.log(\"Running: docker compose up -d --build\"));\n yield* _(runDockerComposeUp(resolvedOutDir));\n});\nconst ensureContainerBridgeAccess = (resolvedOutDir, containerName) => runDockerInspectContainerBridgeIp(resolvedOutDir, containerName).pipe(Effect.flatMap((bridgeIp) => bridgeIp.length > 0\n ? Effect.void\n : runDockerNetworkConnectBridge(resolvedOutDir, containerName)), Effect.matchEffect({\n onFailure: (error) => Effect.logWarning(`Failed to connect ${containerName} to bridge network: ${error instanceof Error ? error.message : String(error)}`),\n onSuccess: () => Effect.void\n}));\nconst ensureBridgeAccess = (resolvedOutDir, projectConfig) => Effect.gen(function* (_) {\n // Make container ports reachable from other (non-compose) containers by IP.\n yield* _(ensureContainerBridgeAccess(resolvedOutDir, projectConfig.containerName));\n if (projectConfig.enableMcpPlaywright) {\n yield* _(ensureContainerBridgeAccess(resolvedOutDir, `${projectConfig.containerName}-browser`));\n }\n});\nexport const runDockerUpIfNeeded = (resolvedOutDir, projectConfig, options) => Effect.gen(function* (_) {\n if (!options.runUp) {\n return;\n }\n yield* _(runDockerComposeUpByMode(resolvedOutDir, options.force, options.forceEnv));\n yield* _(ensureBridgeAccess(resolvedOutDir, projectConfig));\n if (options.waitForClone) {\n yield* _(Effect.log(\"Streaming container logs until clone completes...\"));\n yield* _(waitForCloneCompletion(resolvedOutDir, projectConfig));\n }\n yield* _(Effect.log(\"Docker environment is up\"));\n yield* _(logSshAccess(resolvedOutDir, projectConfig));\n});\nexport const maxSshPortAttempts = maxPortAttempts;\n","import * as ParseResult from \"@effect/schema/ParseResult\";\nimport * as Schema from \"@effect/schema/Schema\";\nimport * as TreeFormatter from \"@effect/schema/TreeFormatter\";\nimport { Effect, Either } from \"effect\";\nimport { ScrapArchiveInvalidError as ScrapArchiveInvalidErrorClass } from \"../shell/errors.js\";\nexport const maxGitBlobBytes = 99 * 1000 * 1000;\nexport const chunkManifestSuffix = \".chunks.json\";\nconst ChunkManifestSchema = Schema.Struct({\n original: Schema.String,\n originalSize: Schema.Number,\n parts: Schema.Array(Schema.String),\n splitAt: Schema.Number,\n partsCount: Schema.Number,\n createdAt: Schema.String\n});\nconst ChunkManifestJsonSchema = Schema.parseJson(ChunkManifestSchema);\nexport const decodeChunkManifest = (manifestPath, input) => Either.match(ParseResult.decodeUnknownEither(ChunkManifestJsonSchema)(input), {\n onLeft: (issue) => Effect.fail(new ScrapArchiveInvalidErrorClass({\n path: manifestPath,\n message: TreeFormatter.formatIssueSync(issue)\n })),\n onRight: (value) => Effect.succeed(value)\n});\nexport const removeChunkArtifacts = (fs, path, fileAbs) => Effect.gen(function* (_) {\n const dir = path.dirname(fileAbs);\n const base = path.basename(fileAbs);\n const entries = yield* _(fs.readDirectory(dir));\n for (const entry of entries) {\n if (!entry.startsWith(`${base}.part`)) {\n continue;\n }\n yield* _(fs.remove(path.join(dir, entry), { force: true }));\n }\n yield* _(fs.remove(`${fileAbs}${chunkManifestSuffix}`, { force: true }));\n}).pipe(Effect.asVoid);\nexport const listChunkParts = (fs, path, fileAbs) => Effect.gen(function* (_) {\n const dir = path.dirname(fileAbs);\n const base = path.basename(fileAbs);\n const entries = yield* _(fs.readDirectory(dir));\n const parts = entries\n .filter((entry) => entry.startsWith(`${base}.part`))\n .toSorted((a, b) => a.localeCompare(b));\n return parts.map((entry) => path.join(dir, entry));\n});\nexport const sumFileSizes = (fs, filesAbs) => Effect.gen(function* (_) {\n let total = 0;\n for (const fileAbs of filesAbs) {\n const stat = yield* _(fs.stat(fileAbs));\n if (stat.type === \"File\") {\n total += Number(stat.size);\n }\n }\n return total;\n});\nexport const writeChunkManifest = (fs, path, fileAbs, originalSize, partsAbs) => Effect.gen(function* (_) {\n const base = path.basename(fileAbs);\n const manifest = {\n original: base,\n originalSize,\n parts: partsAbs.map((part) => path.basename(part)),\n splitAt: maxGitBlobBytes,\n partsCount: partsAbs.length,\n createdAt: new Date().toISOString()\n };\n const manifestPath = `${fileAbs}${chunkManifestSuffix}`;\n yield* _(fs.writeFileString(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`));\n return manifestPath;\n});\n","import * as ParseResult from \"@effect/schema/ParseResult\";\nimport * as Schema from \"@effect/schema/Schema\";\nimport * as TreeFormatter from \"@effect/schema/TreeFormatter\";\nimport { Effect, Either } from \"effect\";\nimport { ScrapArchiveInvalidError as ScrapArchiveInvalidErrorClass } from \"../shell/errors.js\";\nconst SessionManifestSchema = Schema.Struct({\n schemaVersion: Schema.Literal(1),\n mode: Schema.Literal(\"session\"),\n snapshotId: Schema.String,\n createdAtUtc: Schema.String,\n repo: Schema.Struct({\n originUrl: Schema.String,\n head: Schema.String,\n branch: Schema.String\n }),\n artifacts: Schema.Struct({\n worktreePatchChunks: Schema.String,\n codexChunks: Schema.String,\n codexSharedChunks: Schema.String,\n envGlobalFile: Schema.optionalWith(Schema.Union(Schema.String, Schema.Null), { default: () => null }),\n envProjectFile: Schema.optionalWith(Schema.Union(Schema.String, Schema.Null), { default: () => null })\n }),\n rebuild: Schema.optionalWith(Schema.Struct({\n commands: Schema.Array(Schema.String)\n }), { default: () => ({ commands: [] }) })\n});\nconst SessionManifestJsonSchema = Schema.parseJson(SessionManifestSchema);\nexport const decodeSessionManifest = (manifestPath, input) => Either.match(ParseResult.decodeUnknownEither(SessionManifestJsonSchema)(input), {\n onLeft: (issue) => Effect.fail(new ScrapArchiveInvalidErrorClass({\n path: manifestPath,\n message: TreeFormatter.formatIssueSync(issue)\n })),\n onRight: (value) => Effect.succeed(value)\n});\n","import { listProjects, readCloneRequest, runDockerGitClone } from \"@effect-template/lib\"\nimport { Console, Effect, Match, pipe } from \"effect\"\n\n/**\n * Compose the CLI program as a single effect.\n *\n * @returns Effect that either runs docker-git clone or prints usage.\n *\n * @pure false - uses Console output and spawns commands when cloning\n * @effect Console, CommandExecutor, Path\n * @invariant forall args in Argv: clone(args) -> docker_git_invoked(args)\n * @precondition true\n * @postcondition clone(args) -> docker_git_invoked(args); otherwise usage printed\n * @complexity O(build + clone)\n * @throws Never - all errors are typed in the Effect error channel\n */\n// CHANGE: replace greeting demo with deterministic usage text\n// WHY: greeting was scaffolding noise and should not ship in docker-git tooling\n// QUOTE(ТЗ): \"Можешь удалить использование greting ...? Это старый мусор который остался\"\n// REF: user-request-2026-02-06-remove-greeting\n// SOURCE: n/a\n// FORMAT THEOREM: usageText is constant -> deterministic(help)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: usageText does not depend on argv/env\n// COMPLEXITY: O(1)\nconst usageText = [\n \"Usage:\",\n \" pnpm docker-git\",\n \" pnpm clone <repo-url> [ref]\",\n \" pnpm list\",\n \"\",\n \"Notes:\",\n \" - docker-git is the interactive TUI.\",\n \" - clone builds + runs docker-git clone for you.\"\n].join(\"\\n\")\n\n// PURITY: SHELL\n// EFFECT: Effect<void, never, Console>\nconst runHelp = Console.log(usageText)\n\n// CHANGE: route between clone runner and help based on CLI context\n// WHY: allow pnpm run clone <url> while keeping a single entrypoint\n// QUOTE(ТЗ): \"pnpm run clone <url>\"\n// REF: user-request-2026-01-27\n// SOURCE: n/a\n// FORMAT THEOREM: forall argv: clone(argv) -> docker_git_invoked(argv)\n// PURITY: SHELL\n// EFFECT: Effect<void, Error, Console | CommandExecutor | Path>\n// INVARIANT: help is printed when clone is not requested\n// COMPLEXITY: O(build + clone)\nconst runDockerGit = pipe(\n readCloneRequest,\n Effect.flatMap((request) =>\n Match.value(request).pipe(\n Match.when({ _tag: \"Clone\" }, ({ args }) => runDockerGitClone(args)),\n Match.when({ _tag: \"None\" }, () => runHelp),\n Match.exhaustive\n )\n )\n)\n\nconst readListFlag = Effect.sync(() => {\n const command = process.argv.slice(2)[0] ?? \"\"\n return command === \"list\" || command === \"ls\"\n})\n\nexport const program = Effect.gen(function*(_) {\n const isList = yield* _(readListFlag)\n if (isList) {\n yield* _(listProjects)\n return\n }\n yield* _(runDockerGit)\n})\n","import { NodeContext, NodeRuntime } from \"@effect/platform-node\"\nimport { Effect, pipe } from \"effect\"\n\nimport { program } from \"./program.js\"\n\n// CHANGE: run the program through the Node platform runtime with its layer\n// WHY: ensure effects execute under the platform runtime with proper teardown/logging behavior\n// QUOTE(TZ): \"\\u0414\\u0430 \\u0434\\u0430\\u0432\\u0430\\u0439 \\u0442\\u0430\\u043a \\u044d\\u0442\\u043e \\u0431\\u043e\\u043b\\u0435\\u0435 \\u043f\\u0440\\u0430\\u0432\\u0438\\u043b\\u044c\\u043d\\u0430\\u044f \\u0440\\u0435\\u0430\\u043b\\u0438\\u0437\\u0430\\u0446\\u0438\\u044f\"\n// REF: user-2025-12-19-platform-node\n// SOURCE: https://effect.website/docs/platform/runtime/ \"runMain helps you execute a main effect with built-in error handling, logging, and signal management.\"\n// FORMAT THEOREM: forall args in Argv: decode(args) = v -> runMain(program)\n// PURITY: SHELL\n// EFFECT: Effect<string, S.ParseError, Console>\n// INVARIANT: program executed with NodeContext.layer\n// COMPLEXITY: O(1)/O(1)\nconst main = pipe(program, Effect.provide(NodeContext.layer))\n\nNodeRuntime.runMain(main)\n"],"names":["process","successExitCode"],"mappings":"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"}